src/render/SDL_yuv_sw.c
author Sam Lantinga <slouken@libsdl.org>
Wed, 05 Jun 2013 22:33:10 -0700
changeset 7286 04087a99e3f4
parent 7191 75360622e65f
child 7332 b53acf6ab70b
permissions -rw-r--r--
Added testautomation to the Visual Studio 2008 project.
slouken@0
     1
/*
slouken@5535
     2
  Simple DirectMedia Layer
slouken@6885
     3
  Copyright (C) 1997-2013 Sam Lantinga <slouken@libsdl.org>
slouken@0
     4
slouken@5535
     5
  This software is provided 'as-is', without any express or implied
slouken@5535
     6
  warranty.  In no event will the authors be held liable for any damages
slouken@5535
     7
  arising from the use of this software.
slouken@0
     8
slouken@5535
     9
  Permission is granted to anyone to use this software for any purpose,
slouken@5535
    10
  including commercial applications, and to alter it and redistribute it
slouken@5535
    11
  freely, subject to the following restrictions:
slouken@0
    12
slouken@5535
    13
  1. The origin of this software must not be misrepresented; you must not
slouken@5535
    14
     claim that you wrote the original software. If you use this software
slouken@5535
    15
     in a product, an acknowledgment in the product documentation would be
slouken@5535
    16
     appreciated but is not required.
slouken@5535
    17
  2. Altered source versions must be plainly marked as such, and must not be
slouken@5535
    18
     misrepresented as being the original software.
slouken@5535
    19
  3. This notice may not be removed or altered from any source distribution.
slouken@0
    20
*/
slouken@1402
    21
#include "SDL_config.h"
slouken@0
    22
slouken@1895
    23
/* This is the software implementation of the YUV texture support */
slouken@0
    24
slouken@0
    25
/* This code was derived from code carrying the following copyright notices:
slouken@0
    26
slouken@0
    27
 * Copyright (c) 1995 The Regents of the University of California.
slouken@0
    28
 * All rights reserved.
slouken@7191
    29
 *
slouken@0
    30
 * Permission to use, copy, modify, and distribute this software and its
slouken@0
    31
 * documentation for any purpose, without fee, and without written agreement is
slouken@0
    32
 * hereby granted, provided that the above copyright notice and the following
slouken@0
    33
 * two paragraphs appear in all copies of this software.
slouken@7191
    34
 *
slouken@0
    35
 * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
slouken@0
    36
 * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
slouken@0
    37
 * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
slouken@0
    38
 * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
slouken@7191
    39
 *
slouken@0
    40
 * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
slouken@0
    41
 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
slouken@0
    42
 * AND FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
slouken@0
    43
 * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO
slouken@0
    44
 * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
slouken@0
    45
slouken@0
    46
 * Copyright (c) 1995 Erik Corry
slouken@0
    47
 * All rights reserved.
slouken@7191
    48
 *
slouken@0
    49
 * Permission to use, copy, modify, and distribute this software and its
slouken@0
    50
 * documentation for any purpose, without fee, and without written agreement is
slouken@0
    51
 * hereby granted, provided that the above copyright notice and the following
slouken@0
    52
 * two paragraphs appear in all copies of this software.
slouken@7191
    53
 *
slouken@0
    54
 * IN NO EVENT SHALL ERIK CORRY BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT,
slouken@0
    55
 * SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OF
slouken@0
    56
 * THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF ERIK CORRY HAS BEEN ADVISED
slouken@0
    57
 * OF THE POSSIBILITY OF SUCH DAMAGE.
slouken@7191
    58
 *
slouken@0
    59
 * ERIK CORRY SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT
slouken@0
    60
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
slouken@0
    61
 * PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS"
slouken@0
    62
 * BASIS, AND ERIK CORRY HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT,
slouken@0
    63
 * UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
slouken@0
    64
slouken@0
    65
 * Portions of this software Copyright (c) 1995 Brown University.
slouken@0
    66
 * All rights reserved.
slouken@7191
    67
 *
slouken@0
    68
 * Permission to use, copy, modify, and distribute this software and its
slouken@0
    69
 * documentation for any purpose, without fee, and without written agreement
slouken@0
    70
 * is hereby granted, provided that the above copyright notice and the
slouken@0
    71
 * following two paragraphs appear in all copies of this software.
slouken@7191
    72
 *
slouken@0
    73
 * IN NO EVENT SHALL BROWN UNIVERSITY BE LIABLE TO ANY PARTY FOR
slouken@0
    74
 * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
slouken@0
    75
 * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF BROWN
slouken@0
    76
 * UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
slouken@7191
    77
 *
slouken@0
    78
 * BROWN UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT
slouken@0
    79
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
slouken@0
    80
 * PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS"
slouken@0
    81
 * BASIS, AND BROWN UNIVERSITY HAS NO OBLIGATION TO PROVIDE MAINTENANCE,
slouken@0
    82
 * SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
slouken@0
    83
 */
slouken@0
    84
slouken@0
    85
#include "SDL_video.h"
slouken@739
    86
#include "SDL_cpuinfo.h"
slouken@0
    87
#include "SDL_yuv_sw_c.h"
slouken@0
    88
slouken@1895
    89
slouken@0
    90
/* The colorspace conversion functions */
slouken@0
    91
icculus@2197
    92
#if (__GNUC__ > 2) && defined(__i386__) && __OPTIMIZE__ && SDL_ASSEMBLY_ROUTINES
slouken@1895
    93
extern void Color565DitherYV12MMX1X(int *colortab, Uint32 * rgb_2_pix,
slouken@0
    94
                                    unsigned char *lum, unsigned char *cr,
slouken@0
    95
                                    unsigned char *cb, unsigned char *out,
slouken@1895
    96
                                    int rows, int cols, int mod);
slouken@1895
    97
extern void ColorRGBDitherYV12MMX1X(int *colortab, Uint32 * rgb_2_pix,
slouken@1895
    98
                                    unsigned char *lum, unsigned char *cr,
slouken@1895
    99
                                    unsigned char *cb, unsigned char *out,
slouken@1895
   100
                                    int rows, int cols, int mod);
slouken@1895
   101
#endif
slouken@1895
   102
slouken@1895
   103
static void
slouken@1895
   104
Color16DitherYV12Mod1X(int *colortab, Uint32 * rgb_2_pix,
slouken@1895
   105
                       unsigned char *lum, unsigned char *cr,
slouken@1895
   106
                       unsigned char *cb, unsigned char *out,
slouken@1895
   107
                       int rows, int cols, int mod)
slouken@0
   108
{
slouken@1895
   109
    unsigned short *row1;
slouken@1895
   110
    unsigned short *row2;
slouken@1895
   111
    unsigned char *lum2;
slouken@0
   112
    int x, y;
slouken@0
   113
    int cr_r;
slouken@0
   114
    int crb_g;
slouken@0
   115
    int cb_b;
slouken@0
   116
    int cols_2 = cols / 2;
slouken@0
   117
slouken@1895
   118
    row1 = (unsigned short *) out;
slouken@0
   119
    row2 = row1 + cols + mod;
slouken@0
   120
    lum2 = lum + cols;
slouken@0
   121
slouken@0
   122
    mod += cols + mod;
slouken@0
   123
slouken@0
   124
    y = rows / 2;
slouken@1895
   125
    while (y--) {
slouken@0
   126
        x = cols_2;
slouken@1895
   127
        while (x--) {
slouken@0
   128
            register int L;
slouken@0
   129
slouken@1895
   130
            cr_r = 0 * 768 + 256 + colortab[*cr + 0 * 256];
slouken@1895
   131
            crb_g = 1 * 768 + 256 + colortab[*cr + 1 * 256]
slouken@1895
   132
                + colortab[*cb + 2 * 256];
slouken@1895
   133
            cb_b = 2 * 768 + 256 + colortab[*cb + 3 * 256];
slouken@1895
   134
            ++cr;
slouken@1895
   135
            ++cb;
slouken@0
   136
slouken@0
   137
            L = *lum++;
slouken@1895
   138
            *row1++ = (unsigned short) (rgb_2_pix[L + cr_r] |
slouken@1895
   139
                                        rgb_2_pix[L + crb_g] |
slouken@1895
   140
                                        rgb_2_pix[L + cb_b]);
slouken@0
   141
slouken@0
   142
            L = *lum++;
slouken@1895
   143
            *row1++ = (unsigned short) (rgb_2_pix[L + cr_r] |
slouken@1895
   144
                                        rgb_2_pix[L + crb_g] |
slouken@1895
   145
                                        rgb_2_pix[L + cb_b]);
slouken@0
   146
slouken@0
   147
slouken@0
   148
            /* Now, do second row.  */
slouken@0
   149
slouken@0
   150
            L = *lum2++;
slouken@1895
   151
            *row2++ = (unsigned short) (rgb_2_pix[L + cr_r] |
slouken@1895
   152
                                        rgb_2_pix[L + crb_g] |
slouken@1895
   153
                                        rgb_2_pix[L + cb_b]);
slouken@0
   154
slouken@0
   155
            L = *lum2++;
slouken@1895
   156
            *row2++ = (unsigned short) (rgb_2_pix[L + cr_r] |
slouken@1895
   157
                                        rgb_2_pix[L + crb_g] |
slouken@1895
   158
                                        rgb_2_pix[L + cb_b]);
slouken@0
   159
        }
slouken@0
   160
slouken@0
   161
        /*
slouken@0
   162
         * These values are at the start of the next line, (due
slouken@0
   163
         * to the ++'s above),but they need to be at the start
slouken@0
   164
         * of the line after that.
slouken@0
   165
         */
slouken@1895
   166
        lum += cols;
slouken@0
   167
        lum2 += cols;
slouken@0
   168
        row1 += mod;
slouken@0
   169
        row2 += mod;
slouken@0
   170
    }
slouken@0
   171
}
slouken@0
   172
slouken@1895
   173
static void
slouken@1895
   174
Color24DitherYV12Mod1X(int *colortab, Uint32 * rgb_2_pix,
slouken@1895
   175
                       unsigned char *lum, unsigned char *cr,
slouken@1895
   176
                       unsigned char *cb, unsigned char *out,
slouken@1895
   177
                       int rows, int cols, int mod)
slouken@0
   178
{
slouken@0
   179
    unsigned int value;
slouken@1895
   180
    unsigned char *row1;
slouken@1895
   181
    unsigned char *row2;
slouken@1895
   182
    unsigned char *lum2;
slouken@0
   183
    int x, y;
slouken@0
   184
    int cr_r;
slouken@0
   185
    int crb_g;
slouken@0
   186
    int cb_b;
slouken@0
   187
    int cols_2 = cols / 2;
slouken@0
   188
slouken@0
   189
    row1 = out;
slouken@1895
   190
    row2 = row1 + cols * 3 + mod * 3;
slouken@0
   191
    lum2 = lum + cols;
slouken@0
   192
slouken@0
   193
    mod += cols + mod;
slouken@0
   194
    mod *= 3;
slouken@0
   195
slouken@0
   196
    y = rows / 2;
slouken@1895
   197
    while (y--) {
slouken@0
   198
        x = cols_2;
slouken@1895
   199
        while (x--) {
slouken@0
   200
            register int L;
slouken@0
   201
slouken@1895
   202
            cr_r = 0 * 768 + 256 + colortab[*cr + 0 * 256];
slouken@1895
   203
            crb_g = 1 * 768 + 256 + colortab[*cr + 1 * 256]
slouken@1895
   204
                + colortab[*cb + 2 * 256];
slouken@1895
   205
            cb_b = 2 * 768 + 256 + colortab[*cb + 3 * 256];
slouken@1895
   206
            ++cr;
slouken@1895
   207
            ++cb;
slouken@0
   208
slouken@0
   209
            L = *lum++;
slouken@1895
   210
            value = (rgb_2_pix[L + cr_r] |
slouken@1895
   211
                     rgb_2_pix[L + crb_g] | rgb_2_pix[L + cb_b]);
slouken@1895
   212
            *row1++ = (value) & 0xFF;
slouken@1895
   213
            *row1++ = (value >> 8) & 0xFF;
slouken@0
   214
            *row1++ = (value >> 16) & 0xFF;
slouken@0
   215
slouken@0
   216
            L = *lum++;
slouken@1895
   217
            value = (rgb_2_pix[L + cr_r] |
slouken@1895
   218
                     rgb_2_pix[L + crb_g] | rgb_2_pix[L + cb_b]);
slouken@1895
   219
            *row1++ = (value) & 0xFF;
slouken@1895
   220
            *row1++ = (value >> 8) & 0xFF;
slouken@0
   221
            *row1++ = (value >> 16) & 0xFF;
slouken@0
   222
slouken@0
   223
slouken@0
   224
            /* Now, do second row.  */
slouken@0
   225
slouken@0
   226
            L = *lum2++;
slouken@1895
   227
            value = (rgb_2_pix[L + cr_r] |
slouken@1895
   228
                     rgb_2_pix[L + crb_g] | rgb_2_pix[L + cb_b]);
slouken@1895
   229
            *row2++ = (value) & 0xFF;
slouken@1895
   230
            *row2++ = (value >> 8) & 0xFF;
slouken@0
   231
            *row2++ = (value >> 16) & 0xFF;
slouken@0
   232
slouken@0
   233
            L = *lum2++;
slouken@1895
   234
            value = (rgb_2_pix[L + cr_r] |
slouken@1895
   235
                     rgb_2_pix[L + crb_g] | rgb_2_pix[L + cb_b]);
slouken@1895
   236
            *row2++ = (value) & 0xFF;
slouken@1895
   237
            *row2++ = (value >> 8) & 0xFF;
slouken@0
   238
            *row2++ = (value >> 16) & 0xFF;
slouken@0
   239
        }
slouken@0
   240
slouken@0
   241
        /*
slouken@0
   242
         * These values are at the start of the next line, (due
slouken@0
   243
         * to the ++'s above),but they need to be at the start
slouken@0
   244
         * of the line after that.
slouken@0
   245
         */
slouken@1895
   246
        lum += cols;
slouken@0
   247
        lum2 += cols;
slouken@0
   248
        row1 += mod;
slouken@0
   249
        row2 += mod;
slouken@0
   250
    }
slouken@0
   251
}
slouken@0
   252
slouken@1895
   253
static void
slouken@1895
   254
Color32DitherYV12Mod1X(int *colortab, Uint32 * rgb_2_pix,
slouken@1895
   255
                       unsigned char *lum, unsigned char *cr,
slouken@1895
   256
                       unsigned char *cb, unsigned char *out,
slouken@1895
   257
                       int rows, int cols, int mod)
slouken@0
   258
{
slouken@1895
   259
    unsigned int *row1;
slouken@1895
   260
    unsigned int *row2;
slouken@1895
   261
    unsigned char *lum2;
slouken@0
   262
    int x, y;
slouken@0
   263
    int cr_r;
slouken@0
   264
    int crb_g;
slouken@0
   265
    int cb_b;
slouken@0
   266
    int cols_2 = cols / 2;
slouken@0
   267
slouken@1895
   268
    row1 = (unsigned int *) out;
slouken@0
   269
    row2 = row1 + cols + mod;
slouken@0
   270
    lum2 = lum + cols;
slouken@0
   271
slouken@0
   272
    mod += cols + mod;
slouken@0
   273
slouken@0
   274
    y = rows / 2;
slouken@1895
   275
    while (y--) {
slouken@0
   276
        x = cols_2;
slouken@1895
   277
        while (x--) {
slouken@0
   278
            register int L;
slouken@0
   279
slouken@1895
   280
            cr_r = 0 * 768 + 256 + colortab[*cr + 0 * 256];
slouken@1895
   281
            crb_g = 1 * 768 + 256 + colortab[*cr + 1 * 256]
slouken@1895
   282
                + colortab[*cb + 2 * 256];
slouken@1895
   283
            cb_b = 2 * 768 + 256 + colortab[*cb + 3 * 256];
slouken@1895
   284
            ++cr;
slouken@1895
   285
            ++cb;
slouken@0
   286
slouken@0
   287
            L = *lum++;
slouken@1895
   288
            *row1++ = (rgb_2_pix[L + cr_r] |
slouken@1895
   289
                       rgb_2_pix[L + crb_g] | rgb_2_pix[L + cb_b]);
slouken@0
   290
slouken@0
   291
            L = *lum++;
slouken@1895
   292
            *row1++ = (rgb_2_pix[L + cr_r] |
slouken@1895
   293
                       rgb_2_pix[L + crb_g] | rgb_2_pix[L + cb_b]);
slouken@0
   294
slouken@0
   295
slouken@0
   296
            /* Now, do second row.  */
slouken@0
   297
slouken@0
   298
            L = *lum2++;
slouken@1895
   299
            *row2++ = (rgb_2_pix[L + cr_r] |
slouken@1895
   300
                       rgb_2_pix[L + crb_g] | rgb_2_pix[L + cb_b]);
slouken@0
   301
slouken@0
   302
            L = *lum2++;
slouken@1895
   303
            *row2++ = (rgb_2_pix[L + cr_r] |
slouken@1895
   304
                       rgb_2_pix[L + crb_g] | rgb_2_pix[L + cb_b]);
slouken@0
   305
        }
slouken@0
   306
slouken@0
   307
        /*
slouken@0
   308
         * These values are at the start of the next line, (due
slouken@0
   309
         * to the ++'s above),but they need to be at the start
slouken@0
   310
         * of the line after that.
slouken@0
   311
         */
slouken@1895
   312
        lum += cols;
slouken@0
   313
        lum2 += cols;
slouken@0
   314
        row1 += mod;
slouken@0
   315
        row2 += mod;
slouken@0
   316
    }
slouken@0
   317
}
slouken@0
   318
slouken@0
   319
/*
slouken@0
   320
 * In this function I make use of a nasty trick. The tables have the lower
slouken@0
   321
 * 16 bits replicated in the upper 16. This means I can write ints and get
slouken@0
   322
 * the horisontal doubling for free (almost).
slouken@0
   323
 */
slouken@1895
   324
static void
slouken@1895
   325
Color16DitherYV12Mod2X(int *colortab, Uint32 * rgb_2_pix,
slouken@1895
   326
                       unsigned char *lum, unsigned char *cr,
slouken@1895
   327
                       unsigned char *cb, unsigned char *out,
slouken@1895
   328
                       int rows, int cols, int mod)
slouken@0
   329
{
slouken@1895
   330
    unsigned int *row1 = (unsigned int *) out;
slouken@1895
   331
    const int next_row = cols + (mod / 2);
slouken@1895
   332
    unsigned int *row2 = row1 + 2 * next_row;
slouken@1895
   333
    unsigned char *lum2;
slouken@0
   334
    int x, y;
slouken@0
   335
    int cr_r;
slouken@0
   336
    int crb_g;
slouken@0
   337
    int cb_b;
slouken@0
   338
    int cols_2 = cols / 2;
slouken@0
   339
slouken@0
   340
    lum2 = lum + cols;
slouken@0
   341
slouken@1895
   342
    mod = (next_row * 3) + (mod / 2);
slouken@0
   343
slouken@0
   344
    y = rows / 2;
slouken@1895
   345
    while (y--) {
slouken@0
   346
        x = cols_2;
slouken@1895
   347
        while (x--) {
slouken@0
   348
            register int L;
slouken@0
   349
slouken@1895
   350
            cr_r = 0 * 768 + 256 + colortab[*cr + 0 * 256];
slouken@1895
   351
            crb_g = 1 * 768 + 256 + colortab[*cr + 1 * 256]
slouken@1895
   352
                + colortab[*cb + 2 * 256];
slouken@1895
   353
            cb_b = 2 * 768 + 256 + colortab[*cb + 3 * 256];
slouken@1895
   354
            ++cr;
slouken@1895
   355
            ++cb;
slouken@0
   356
slouken@0
   357
            L = *lum++;
slouken@1895
   358
            row1[0] = row1[next_row] = (rgb_2_pix[L + cr_r] |
slouken@1895
   359
                                        rgb_2_pix[L + crb_g] |
slouken@1895
   360
                                        rgb_2_pix[L + cb_b]);
slouken@0
   361
            row1++;
slouken@0
   362
slouken@0
   363
            L = *lum++;
slouken@1895
   364
            row1[0] = row1[next_row] = (rgb_2_pix[L + cr_r] |
slouken@1895
   365
                                        rgb_2_pix[L + crb_g] |
slouken@1895
   366
                                        rgb_2_pix[L + cb_b]);
slouken@0
   367
            row1++;
slouken@0
   368
slouken@0
   369
slouken@0
   370
            /* Now, do second row. */
slouken@0
   371
slouken@0
   372
            L = *lum2++;
slouken@1895
   373
            row2[0] = row2[next_row] = (rgb_2_pix[L + cr_r] |
slouken@1895
   374
                                        rgb_2_pix[L + crb_g] |
slouken@1895
   375
                                        rgb_2_pix[L + cb_b]);
slouken@0
   376
            row2++;
slouken@0
   377
slouken@0
   378
            L = *lum2++;
slouken@1895
   379
            row2[0] = row2[next_row] = (rgb_2_pix[L + cr_r] |
slouken@1895
   380
                                        rgb_2_pix[L + crb_g] |
slouken@1895
   381
                                        rgb_2_pix[L + cb_b]);
slouken@0
   382
            row2++;
slouken@0
   383
        }
slouken@0
   384
slouken@0
   385
        /*
slouken@0
   386
         * These values are at the start of the next line, (due
slouken@0
   387
         * to the ++'s above),but they need to be at the start
slouken@0
   388
         * of the line after that.
slouken@0
   389
         */
slouken@1895
   390
        lum += cols;
slouken@0
   391
        lum2 += cols;
slouken@0
   392
        row1 += mod;
slouken@0
   393
        row2 += mod;
slouken@0
   394
    }
slouken@0
   395
}
slouken@0
   396
slouken@1895
   397
static void
slouken@1895
   398
Color24DitherYV12Mod2X(int *colortab, Uint32 * rgb_2_pix,
slouken@1895
   399
                       unsigned char *lum, unsigned char *cr,
slouken@1895
   400
                       unsigned char *cb, unsigned char *out,
slouken@1895
   401
                       int rows, int cols, int mod)
slouken@0
   402
{
slouken@0
   403
    unsigned int value;
slouken@1895
   404
    unsigned char *row1 = out;
slouken@1895
   405
    const int next_row = (cols * 2 + mod) * 3;
slouken@1895
   406
    unsigned char *row2 = row1 + 2 * next_row;
slouken@1895
   407
    unsigned char *lum2;
slouken@0
   408
    int x, y;
slouken@0
   409
    int cr_r;
slouken@0
   410
    int crb_g;
slouken@0
   411
    int cb_b;
slouken@0
   412
    int cols_2 = cols / 2;
slouken@0
   413
slouken@0
   414
    lum2 = lum + cols;
slouken@0
   415
slouken@1895
   416
    mod = next_row * 3 + mod * 3;
slouken@0
   417
slouken@0
   418
    y = rows / 2;
slouken@1895
   419
    while (y--) {
slouken@0
   420
        x = cols_2;
slouken@1895
   421
        while (x--) {
slouken@0
   422
            register int L;
slouken@0
   423
slouken@1895
   424
            cr_r = 0 * 768 + 256 + colortab[*cr + 0 * 256];
slouken@1895
   425
            crb_g = 1 * 768 + 256 + colortab[*cr + 1 * 256]
slouken@1895
   426
                + colortab[*cb + 2 * 256];
slouken@1895
   427
            cb_b = 2 * 768 + 256 + colortab[*cb + 3 * 256];
slouken@1895
   428
            ++cr;
slouken@1895
   429
            ++cb;
slouken@0
   430
slouken@0
   431
            L = *lum++;
slouken@1895
   432
            value = (rgb_2_pix[L + cr_r] |
slouken@1895
   433
                     rgb_2_pix[L + crb_g] | rgb_2_pix[L + cb_b]);
slouken@1895
   434
            row1[0 + 0] = row1[3 + 0] = row1[next_row + 0] =
slouken@1895
   435
                row1[next_row + 3 + 0] = (value) & 0xFF;
slouken@1895
   436
            row1[0 + 1] = row1[3 + 1] = row1[next_row + 1] =
slouken@1895
   437
                row1[next_row + 3 + 1] = (value >> 8) & 0xFF;
slouken@1895
   438
            row1[0 + 2] = row1[3 + 2] = row1[next_row + 2] =
slouken@1895
   439
                row1[next_row + 3 + 2] = (value >> 16) & 0xFF;
slouken@1895
   440
            row1 += 2 * 3;
slouken@0
   441
slouken@0
   442
            L = *lum++;
slouken@1895
   443
            value = (rgb_2_pix[L + cr_r] |
slouken@1895
   444
                     rgb_2_pix[L + crb_g] | rgb_2_pix[L + cb_b]);
slouken@1895
   445
            row1[0 + 0] = row1[3 + 0] = row1[next_row + 0] =
slouken@1895
   446
                row1[next_row + 3 + 0] = (value) & 0xFF;
slouken@1895
   447
            row1[0 + 1] = row1[3 + 1] = row1[next_row + 1] =
slouken@1895
   448
                row1[next_row + 3 + 1] = (value >> 8) & 0xFF;
slouken@1895
   449
            row1[0 + 2] = row1[3 + 2] = row1[next_row + 2] =
slouken@1895
   450
                row1[next_row + 3 + 2] = (value >> 16) & 0xFF;
slouken@1895
   451
            row1 += 2 * 3;
slouken@0
   452
slouken@0
   453
slouken@0
   454
            /* Now, do second row. */
slouken@0
   455
slouken@0
   456
            L = *lum2++;
slouken@1895
   457
            value = (rgb_2_pix[L + cr_r] |
slouken@1895
   458
                     rgb_2_pix[L + crb_g] | rgb_2_pix[L + cb_b]);
slouken@1895
   459
            row2[0 + 0] = row2[3 + 0] = row2[next_row + 0] =
slouken@1895
   460
                row2[next_row + 3 + 0] = (value) & 0xFF;
slouken@1895
   461
            row2[0 + 1] = row2[3 + 1] = row2[next_row + 1] =
slouken@1895
   462
                row2[next_row + 3 + 1] = (value >> 8) & 0xFF;
slouken@1895
   463
            row2[0 + 2] = row2[3 + 2] = row2[next_row + 2] =
slouken@1895
   464
                row2[next_row + 3 + 2] = (value >> 16) & 0xFF;
slouken@1895
   465
            row2 += 2 * 3;
slouken@0
   466
slouken@0
   467
            L = *lum2++;
slouken@1895
   468
            value = (rgb_2_pix[L + cr_r] |
slouken@1895
   469
                     rgb_2_pix[L + crb_g] | rgb_2_pix[L + cb_b]);
slouken@1895
   470
            row2[0 + 0] = row2[3 + 0] = row2[next_row + 0] =
slouken@1895
   471
                row2[next_row + 3 + 0] = (value) & 0xFF;
slouken@1895
   472
            row2[0 + 1] = row2[3 + 1] = row2[next_row + 1] =
slouken@1895
   473
                row2[next_row + 3 + 1] = (value >> 8) & 0xFF;
slouken@1895
   474
            row2[0 + 2] = row2[3 + 2] = row2[next_row + 2] =
slouken@1895
   475
                row2[next_row + 3 + 2] = (value >> 16) & 0xFF;
slouken@1895
   476
            row2 += 2 * 3;
slouken@0
   477
        }
slouken@0
   478
slouken@0
   479
        /*
slouken@0
   480
         * These values are at the start of the next line, (due
slouken@0
   481
         * to the ++'s above),but they need to be at the start
slouken@0
   482
         * of the line after that.
slouken@0
   483
         */
slouken@1895
   484
        lum += cols;
slouken@0
   485
        lum2 += cols;
slouken@0
   486
        row1 += mod;
slouken@0
   487
        row2 += mod;
slouken@0
   488
    }
slouken@0
   489
}
slouken@0
   490
slouken@1895
   491
static void
slouken@1895
   492
Color32DitherYV12Mod2X(int *colortab, Uint32 * rgb_2_pix,
slouken@1895
   493
                       unsigned char *lum, unsigned char *cr,
slouken@1895
   494
                       unsigned char *cb, unsigned char *out,
slouken@1895
   495
                       int rows, int cols, int mod)
slouken@0
   496
{
slouken@1895
   497
    unsigned int *row1 = (unsigned int *) out;
slouken@1895
   498
    const int next_row = cols * 2 + mod;
slouken@1895
   499
    unsigned int *row2 = row1 + 2 * next_row;
slouken@1895
   500
    unsigned char *lum2;
slouken@0
   501
    int x, y;
slouken@0
   502
    int cr_r;
slouken@0
   503
    int crb_g;
slouken@0
   504
    int cb_b;
slouken@0
   505
    int cols_2 = cols / 2;
slouken@0
   506
slouken@0
   507
    lum2 = lum + cols;
slouken@0
   508
slouken@0
   509
    mod = (next_row * 3) + mod;
slouken@0
   510
slouken@0
   511
    y = rows / 2;
slouken@1895
   512
    while (y--) {
slouken@0
   513
        x = cols_2;
slouken@1895
   514
        while (x--) {
slouken@0
   515
            register int L;
slouken@0
   516
slouken@1895
   517
            cr_r = 0 * 768 + 256 + colortab[*cr + 0 * 256];
slouken@1895
   518
            crb_g = 1 * 768 + 256 + colortab[*cr + 1 * 256]
slouken@1895
   519
                + colortab[*cb + 2 * 256];
slouken@1895
   520
            cb_b = 2 * 768 + 256 + colortab[*cb + 3 * 256];
slouken@1895
   521
            ++cr;
slouken@1895
   522
            ++cb;
slouken@0
   523
slouken@0
   524
            L = *lum++;
slouken@1895
   525
            row1[0] = row1[1] = row1[next_row] = row1[next_row + 1] =
slouken@1895
   526
                (rgb_2_pix[L + cr_r] |
slouken@1895
   527
                 rgb_2_pix[L + crb_g] | rgb_2_pix[L + cb_b]);
slouken@0
   528
            row1 += 2;
slouken@0
   529
slouken@0
   530
            L = *lum++;
slouken@1895
   531
            row1[0] = row1[1] = row1[next_row] = row1[next_row + 1] =
slouken@1895
   532
                (rgb_2_pix[L + cr_r] |
slouken@1895
   533
                 rgb_2_pix[L + crb_g] | rgb_2_pix[L + cb_b]);
slouken@0
   534
            row1 += 2;
slouken@0
   535
slouken@0
   536
slouken@0
   537
            /* Now, do second row. */
slouken@0
   538
slouken@0
   539
            L = *lum2++;
slouken@1895
   540
            row2[0] = row2[1] = row2[next_row] = row2[next_row + 1] =
slouken@1895
   541
                (rgb_2_pix[L + cr_r] |
slouken@1895
   542
                 rgb_2_pix[L + crb_g] | rgb_2_pix[L + cb_b]);
slouken@0
   543
            row2 += 2;
slouken@0
   544
slouken@0
   545
            L = *lum2++;
slouken@1895
   546
            row2[0] = row2[1] = row2[next_row] = row2[next_row + 1] =
slouken@1895
   547
                (rgb_2_pix[L + cr_r] |
slouken@1895
   548
                 rgb_2_pix[L + crb_g] | rgb_2_pix[L + cb_b]);
slouken@0
   549
            row2 += 2;
slouken@0
   550
        }
slouken@0
   551
slouken@0
   552
        /*
slouken@0
   553
         * These values are at the start of the next line, (due
slouken@0
   554
         * to the ++'s above),but they need to be at the start
slouken@0
   555
         * of the line after that.
slouken@0
   556
         */
slouken@1895
   557
        lum += cols;
slouken@0
   558
        lum2 += cols;
slouken@0
   559
        row1 += mod;
slouken@0
   560
        row2 += mod;
slouken@0
   561
    }
slouken@0
   562
}
slouken@0
   563
slouken@1895
   564
static void
slouken@1895
   565
Color16DitherYUY2Mod1X(int *colortab, Uint32 * rgb_2_pix,
slouken@1895
   566
                       unsigned char *lum, unsigned char *cr,
slouken@1895
   567
                       unsigned char *cb, unsigned char *out,
slouken@1895
   568
                       int rows, int cols, int mod)
slouken@0
   569
{
slouken@1895
   570
    unsigned short *row;
slouken@0
   571
    int x, y;
slouken@0
   572
    int cr_r;
slouken@0
   573
    int crb_g;
slouken@0
   574
    int cb_b;
slouken@0
   575
    int cols_2 = cols / 2;
slouken@0
   576
slouken@1895
   577
    row = (unsigned short *) out;
slouken@0
   578
slouken@0
   579
    y = rows;
slouken@1895
   580
    while (y--) {
slouken@0
   581
        x = cols_2;
slouken@1895
   582
        while (x--) {
slouken@0
   583
            register int L;
slouken@0
   584
slouken@1895
   585
            cr_r = 0 * 768 + 256 + colortab[*cr + 0 * 256];
slouken@1895
   586
            crb_g = 1 * 768 + 256 + colortab[*cr + 1 * 256]
slouken@1895
   587
                + colortab[*cb + 2 * 256];
slouken@1895
   588
            cb_b = 2 * 768 + 256 + colortab[*cb + 3 * 256];
slouken@1895
   589
            cr += 4;
slouken@1895
   590
            cb += 4;
slouken@0
   591
slouken@1895
   592
            L = *lum;
slouken@1895
   593
            lum += 2;
slouken@1895
   594
            *row++ = (unsigned short) (rgb_2_pix[L + cr_r] |
slouken@1895
   595
                                       rgb_2_pix[L + crb_g] |
slouken@1895
   596
                                       rgb_2_pix[L + cb_b]);
slouken@0
   597
slouken@1895
   598
            L = *lum;
slouken@1895
   599
            lum += 2;
slouken@1895
   600
            *row++ = (unsigned short) (rgb_2_pix[L + cr_r] |
slouken@1895
   601
                                       rgb_2_pix[L + crb_g] |
slouken@1895
   602
                                       rgb_2_pix[L + cb_b]);
slouken@0
   603
slouken@0
   604
        }
slouken@0
   605
slouken@0
   606
        row += mod;
slouken@0
   607
    }
slouken@0
   608
}
slouken@0
   609
slouken@1895
   610
static void
slouken@1895
   611
Color24DitherYUY2Mod1X(int *colortab, Uint32 * rgb_2_pix,
slouken@1895
   612
                       unsigned char *lum, unsigned char *cr,
slouken@1895
   613
                       unsigned char *cb, unsigned char *out,
slouken@1895
   614
                       int rows, int cols, int mod)
slouken@0
   615
{
slouken@0
   616
    unsigned int value;
slouken@1895
   617
    unsigned char *row;
slouken@0
   618
    int x, y;
slouken@0
   619
    int cr_r;
slouken@0
   620
    int crb_g;
slouken@0
   621
    int cb_b;
slouken@0
   622
    int cols_2 = cols / 2;
slouken@0
   623
slouken@1895
   624
    row = (unsigned char *) out;
slouken@0
   625
    mod *= 3;
slouken@0
   626
    y = rows;
slouken@1895
   627
    while (y--) {
slouken@0
   628
        x = cols_2;
slouken@1895
   629
        while (x--) {
slouken@0
   630
            register int L;
slouken@0
   631
slouken@1895
   632
            cr_r = 0 * 768 + 256 + colortab[*cr + 0 * 256];
slouken@1895
   633
            crb_g = 1 * 768 + 256 + colortab[*cr + 1 * 256]
slouken@1895
   634
                + colortab[*cb + 2 * 256];
slouken@1895
   635
            cb_b = 2 * 768 + 256 + colortab[*cb + 3 * 256];
slouken@1895
   636
            cr += 4;
slouken@1895
   637
            cb += 4;
slouken@0
   638
slouken@1895
   639
            L = *lum;
slouken@1895
   640
            lum += 2;
slouken@1895
   641
            value = (rgb_2_pix[L + cr_r] |
slouken@1895
   642
                     rgb_2_pix[L + crb_g] | rgb_2_pix[L + cb_b]);
slouken@1895
   643
            *row++ = (value) & 0xFF;
slouken@1895
   644
            *row++ = (value >> 8) & 0xFF;
slouken@0
   645
            *row++ = (value >> 16) & 0xFF;
slouken@0
   646
slouken@1895
   647
            L = *lum;
slouken@1895
   648
            lum += 2;
slouken@1895
   649
            value = (rgb_2_pix[L + cr_r] |
slouken@1895
   650
                     rgb_2_pix[L + crb_g] | rgb_2_pix[L + cb_b]);
slouken@1895
   651
            *row++ = (value) & 0xFF;
slouken@1895
   652
            *row++ = (value >> 8) & 0xFF;
slouken@0
   653
            *row++ = (value >> 16) & 0xFF;
slouken@0
   654
slouken@0
   655
        }
slouken@0
   656
        row += mod;
slouken@0
   657
    }
slouken@0
   658
}
slouken@0
   659
slouken@1895
   660
static void
slouken@1895
   661
Color32DitherYUY2Mod1X(int *colortab, Uint32 * rgb_2_pix,
slouken@1895
   662
                       unsigned char *lum, unsigned char *cr,
slouken@1895
   663
                       unsigned char *cb, unsigned char *out,
slouken@1895
   664
                       int rows, int cols, int mod)
slouken@0
   665
{
slouken@1895
   666
    unsigned int *row;
slouken@0
   667
    int x, y;
slouken@0
   668
    int cr_r;
slouken@0
   669
    int crb_g;
slouken@0
   670
    int cb_b;
slouken@0
   671
    int cols_2 = cols / 2;
slouken@0
   672
slouken@1895
   673
    row = (unsigned int *) out;
slouken@0
   674
    y = rows;
slouken@1895
   675
    while (y--) {
slouken@0
   676
        x = cols_2;
slouken@1895
   677
        while (x--) {
slouken@0
   678
            register int L;
slouken@0
   679
slouken@1895
   680
            cr_r = 0 * 768 + 256 + colortab[*cr + 0 * 256];
slouken@1895
   681
            crb_g = 1 * 768 + 256 + colortab[*cr + 1 * 256]
slouken@1895
   682
                + colortab[*cb + 2 * 256];
slouken@1895
   683
            cb_b = 2 * 768 + 256 + colortab[*cb + 3 * 256];
slouken@1895
   684
            cr += 4;
slouken@1895
   685
            cb += 4;
slouken@0
   686
slouken@1895
   687
            L = *lum;
slouken@1895
   688
            lum += 2;
slouken@1895
   689
            *row++ = (rgb_2_pix[L + cr_r] |
slouken@1895
   690
                      rgb_2_pix[L + crb_g] | rgb_2_pix[L + cb_b]);
slouken@0
   691
slouken@1895
   692
            L = *lum;
slouken@1895
   693
            lum += 2;
slouken@1895
   694
            *row++ = (rgb_2_pix[L + cr_r] |
slouken@1895
   695
                      rgb_2_pix[L + crb_g] | rgb_2_pix[L + cb_b]);
slouken@0
   696
slouken@0
   697
slouken@0
   698
        }
slouken@0
   699
        row += mod;
slouken@0
   700
    }
slouken@0
   701
}
slouken@0
   702
slouken@0
   703
/*
slouken@0
   704
 * In this function I make use of a nasty trick. The tables have the lower
slouken@0
   705
 * 16 bits replicated in the upper 16. This means I can write ints and get
slouken@0
   706
 * the horisontal doubling for free (almost).
slouken@0
   707
 */
slouken@1895
   708
static void
slouken@1895
   709
Color16DitherYUY2Mod2X(int *colortab, Uint32 * rgb_2_pix,
slouken@1895
   710
                       unsigned char *lum, unsigned char *cr,
slouken@1895
   711
                       unsigned char *cb, unsigned char *out,
slouken@1895
   712
                       int rows, int cols, int mod)
slouken@0
   713
{
slouken@1895
   714
    unsigned int *row = (unsigned int *) out;
slouken@1895
   715
    const int next_row = cols + (mod / 2);
slouken@0
   716
    int x, y;
slouken@0
   717
    int cr_r;
slouken@0
   718
    int crb_g;
slouken@0
   719
    int cb_b;
slouken@0
   720
    int cols_2 = cols / 2;
slouken@0
   721
slouken@0
   722
    y = rows;
slouken@1895
   723
    while (y--) {
slouken@0
   724
        x = cols_2;
slouken@1895
   725
        while (x--) {
slouken@0
   726
            register int L;
slouken@0
   727
slouken@1895
   728
            cr_r = 0 * 768 + 256 + colortab[*cr + 0 * 256];
slouken@1895
   729
            crb_g = 1 * 768 + 256 + colortab[*cr + 1 * 256]
slouken@1895
   730
                + colortab[*cb + 2 * 256];
slouken@1895
   731
            cb_b = 2 * 768 + 256 + colortab[*cb + 3 * 256];
slouken@1895
   732
            cr += 4;
slouken@1895
   733
            cb += 4;
slouken@0
   734
slouken@1895
   735
            L = *lum;
slouken@1895
   736
            lum += 2;
slouken@1895
   737
            row[0] = row[next_row] = (rgb_2_pix[L + cr_r] |
slouken@1895
   738
                                      rgb_2_pix[L + crb_g] |
slouken@1895
   739
                                      rgb_2_pix[L + cb_b]);
slouken@0
   740
            row++;
slouken@0
   741
slouken@1895
   742
            L = *lum;
slouken@1895
   743
            lum += 2;
slouken@1895
   744
            row[0] = row[next_row] = (rgb_2_pix[L + cr_r] |
slouken@1895
   745
                                      rgb_2_pix[L + crb_g] |
slouken@1895
   746
                                      rgb_2_pix[L + cb_b]);
slouken@0
   747
            row++;
slouken@0
   748
slouken@0
   749
        }
slouken@0
   750
        row += next_row;
slouken@0
   751
    }
slouken@0
   752
}
slouken@0
   753
slouken@1895
   754
static void
slouken@1895
   755
Color24DitherYUY2Mod2X(int *colortab, Uint32 * rgb_2_pix,
slouken@1895
   756
                       unsigned char *lum, unsigned char *cr,
slouken@1895
   757
                       unsigned char *cb, unsigned char *out,
slouken@1895
   758
                       int rows, int cols, int mod)
slouken@0
   759
{
slouken@0
   760
    unsigned int value;
slouken@1895
   761
    unsigned char *row = out;
slouken@1895
   762
    const int next_row = (cols * 2 + mod) * 3;
slouken@0
   763
    int x, y;
slouken@0
   764
    int cr_r;
slouken@0
   765
    int crb_g;
slouken@0
   766
    int cb_b;
slouken@0
   767
    int cols_2 = cols / 2;
slouken@0
   768
    y = rows;
slouken@1895
   769
    while (y--) {
slouken@0
   770
        x = cols_2;
slouken@1895
   771
        while (x--) {
slouken@0
   772
            register int L;
slouken@0
   773
slouken@1895
   774
            cr_r = 0 * 768 + 256 + colortab[*cr + 0 * 256];
slouken@1895
   775
            crb_g = 1 * 768 + 256 + colortab[*cr + 1 * 256]
slouken@1895
   776
                + colortab[*cb + 2 * 256];
slouken@1895
   777
            cb_b = 2 * 768 + 256 + colortab[*cb + 3 * 256];
slouken@1895
   778
            cr += 4;
slouken@1895
   779
            cb += 4;
slouken@0
   780
slouken@1895
   781
            L = *lum;
slouken@1895
   782
            lum += 2;
slouken@1895
   783
            value = (rgb_2_pix[L + cr_r] |
slouken@1895
   784
                     rgb_2_pix[L + crb_g] | rgb_2_pix[L + cb_b]);
slouken@1895
   785
            row[0 + 0] = row[3 + 0] = row[next_row + 0] =
slouken@1895
   786
                row[next_row + 3 + 0] = (value) & 0xFF;
slouken@1895
   787
            row[0 + 1] = row[3 + 1] = row[next_row + 1] =
slouken@1895
   788
                row[next_row + 3 + 1] = (value >> 8) & 0xFF;
slouken@1895
   789
            row[0 + 2] = row[3 + 2] = row[next_row + 2] =
slouken@1895
   790
                row[next_row + 3 + 2] = (value >> 16) & 0xFF;
slouken@1895
   791
            row += 2 * 3;
slouken@0
   792
slouken@1895
   793
            L = *lum;
slouken@1895
   794
            lum += 2;
slouken@1895
   795
            value = (rgb_2_pix[L + cr_r] |
slouken@1895
   796
                     rgb_2_pix[L + crb_g] | rgb_2_pix[L + cb_b]);
slouken@1895
   797
            row[0 + 0] = row[3 + 0] = row[next_row + 0] =
slouken@1895
   798
                row[next_row + 3 + 0] = (value) & 0xFF;
slouken@1895
   799
            row[0 + 1] = row[3 + 1] = row[next_row + 1] =
slouken@1895
   800
                row[next_row + 3 + 1] = (value >> 8) & 0xFF;
slouken@1895
   801
            row[0 + 2] = row[3 + 2] = row[next_row + 2] =
slouken@1895
   802
                row[next_row + 3 + 2] = (value >> 16) & 0xFF;
slouken@1895
   803
            row += 2 * 3;
slouken@0
   804
slouken@0
   805
        }
slouken@0
   806
        row += next_row;
slouken@0
   807
    }
slouken@0
   808
}
slouken@0
   809
slouken@1895
   810
static void
slouken@1895
   811
Color32DitherYUY2Mod2X(int *colortab, Uint32 * rgb_2_pix,
slouken@1895
   812
                       unsigned char *lum, unsigned char *cr,
slouken@1895
   813
                       unsigned char *cb, unsigned char *out,
slouken@1895
   814
                       int rows, int cols, int mod)
slouken@0
   815
{
slouken@1895
   816
    unsigned int *row = (unsigned int *) out;
slouken@1895
   817
    const int next_row = cols * 2 + mod;
slouken@0
   818
    int x, y;
slouken@0
   819
    int cr_r;
slouken@0
   820
    int crb_g;
slouken@0
   821
    int cb_b;
slouken@0
   822
    int cols_2 = cols / 2;
slouken@1895
   823
    mod += mod;
slouken@0
   824
    y = rows;
slouken@1895
   825
    while (y--) {
slouken@0
   826
        x = cols_2;
slouken@1895
   827
        while (x--) {
slouken@0
   828
            register int L;
slouken@0
   829
slouken@1895
   830
            cr_r = 0 * 768 + 256 + colortab[*cr + 0 * 256];
slouken@1895
   831
            crb_g = 1 * 768 + 256 + colortab[*cr + 1 * 256]
slouken@1895
   832
                + colortab[*cb + 2 * 256];
slouken@1895
   833
            cb_b = 2 * 768 + 256 + colortab[*cb + 3 * 256];
slouken@1895
   834
            cr += 4;
slouken@1895
   835
            cb += 4;
slouken@0
   836
slouken@1895
   837
            L = *lum;
slouken@1895
   838
            lum += 2;
slouken@1895
   839
            row[0] = row[1] = row[next_row] = row[next_row + 1] =
slouken@1895
   840
                (rgb_2_pix[L + cr_r] |
slouken@1895
   841
                 rgb_2_pix[L + crb_g] | rgb_2_pix[L + cb_b]);
slouken@0
   842
            row += 2;
slouken@0
   843
slouken@1895
   844
            L = *lum;
slouken@1895
   845
            lum += 2;
slouken@1895
   846
            row[0] = row[1] = row[next_row] = row[next_row + 1] =
slouken@1895
   847
                (rgb_2_pix[L + cr_r] |
slouken@1895
   848
                 rgb_2_pix[L + crb_g] | rgb_2_pix[L + cb_b]);
slouken@0
   849
            row += 2;
slouken@0
   850
slouken@0
   851
slouken@0
   852
        }
slouken@0
   853
slouken@0
   854
        row += next_row;
slouken@0
   855
    }
slouken@0
   856
}
slouken@0
   857
slouken@0
   858
/*
slouken@0
   859
 * How many 1 bits are there in the Uint32.
slouken@0
   860
 * Low performance, do not call often.
slouken@0
   861
 */
slouken@1895
   862
static int
slouken@1895
   863
number_of_bits_set(Uint32 a)
slouken@0
   864
{
slouken@1895
   865
    if (!a)
slouken@1895
   866
        return 0;
slouken@1895
   867
    if (a & 1)
slouken@1895
   868
        return 1 + number_of_bits_set(a >> 1);
slouken@1895
   869
    return (number_of_bits_set(a >> 1));
slouken@0
   870
}
slouken@0
   871
slouken@0
   872
/*
slouken@0
   873
 * How many 0 bits are there at least significant end of Uint32.
slouken@0
   874
 * Low performance, do not call often.
slouken@0
   875
 */
slouken@1895
   876
static int
slouken@1895
   877
free_bits_at_bottom(Uint32 a)
slouken@0
   878
{
slouken@1895
   879
    /* assume char is 8 bits */
slouken@1895
   880
    if (!a)
slouken@1895
   881
        return sizeof(Uint32) * 8;
slouken@1895
   882
    if (((Sint32) a) & 1l)
slouken@1895
   883
        return 0;
slouken@1895
   884
    return 1 + free_bits_at_bottom(a >> 1);
slouken@0
   885
}
slouken@0
   886
slouken@1895
   887
static int
slouken@1895
   888
SDL_SW_SetupYUVDisplay(SDL_SW_YUVTexture * swdata, Uint32 target_format)
slouken@1895
   889
{
slouken@1895
   890
    Uint32 *r_2_pix_alloc;
slouken@1895
   891
    Uint32 *g_2_pix_alloc;
slouken@1895
   892
    Uint32 *b_2_pix_alloc;
slouken@1895
   893
    int i;
slouken@1895
   894
    int bpp;
slouken@1895
   895
    Uint32 Rmask, Gmask, Bmask, Amask;
slouken@0
   896
slouken@1895
   897
    if (!SDL_PixelFormatEnumToMasks
slouken@1895
   898
        (target_format, &bpp, &Rmask, &Gmask, &Bmask, &Amask) || bpp < 15) {
icculus@7037
   899
        return SDL_SetError("Unsupported YUV destination format");
slouken@1895
   900
    }
slouken@0
   901
slouken@1895
   902
    swdata->target_format = target_format;
slouken@1895
   903
    r_2_pix_alloc = &swdata->rgb_2_pix[0 * 768];
slouken@1895
   904
    g_2_pix_alloc = &swdata->rgb_2_pix[1 * 768];
slouken@1895
   905
    b_2_pix_alloc = &swdata->rgb_2_pix[2 * 768];
slouken@0
   906
slouken@7191
   907
    /*
slouken@1895
   908
     * Set up entries 0-255 in rgb-to-pixel value tables.
slouken@1895
   909
     */
slouken@1895
   910
    for (i = 0; i < 256; ++i) {
slouken@1895
   911
        r_2_pix_alloc[i + 256] = i >> (8 - number_of_bits_set(Rmask));
slouken@1895
   912
        r_2_pix_alloc[i + 256] <<= free_bits_at_bottom(Rmask);
slouken@2795
   913
        r_2_pix_alloc[i + 256] |= Amask;
slouken@1895
   914
        g_2_pix_alloc[i + 256] = i >> (8 - number_of_bits_set(Gmask));
slouken@1895
   915
        g_2_pix_alloc[i + 256] <<= free_bits_at_bottom(Gmask);
slouken@2795
   916
        g_2_pix_alloc[i + 256] |= Amask;
slouken@1895
   917
        b_2_pix_alloc[i + 256] = i >> (8 - number_of_bits_set(Bmask));
slouken@1895
   918
        b_2_pix_alloc[i + 256] <<= free_bits_at_bottom(Bmask);
slouken@2795
   919
        b_2_pix_alloc[i + 256] |= Amask;
slouken@1895
   920
    }
slouken@0
   921
slouken@1895
   922
    /*
slouken@1895
   923
     * If we have 16-bit output depth, then we double the value
slouken@1895
   924
     * in the top word. This means that we can write out both
slouken@7191
   925
     * pixels in the pixel doubling mode with one op. It is
slouken@1895
   926
     * harmless in the normal case as storing a 32-bit value
slouken@1895
   927
     * through a short pointer will lose the top bits anyway.
slouken@1895
   928
     */
slouken@1895
   929
    if (SDL_BYTESPERPIXEL(target_format) == 2) {
slouken@1895
   930
        for (i = 0; i < 256; ++i) {
slouken@1895
   931
            r_2_pix_alloc[i + 256] |= (r_2_pix_alloc[i + 256]) << 16;
slouken@1895
   932
            g_2_pix_alloc[i + 256] |= (g_2_pix_alloc[i + 256]) << 16;
slouken@1895
   933
            b_2_pix_alloc[i + 256] |= (b_2_pix_alloc[i + 256]) << 16;
slouken@1895
   934
        }
slouken@1895
   935
    }
slouken@0
   936
slouken@1895
   937
    /*
slouken@1895
   938
     * Spread out the values we have to the rest of the array so that
slouken@1895
   939
     * we do not need to check for overflow.
slouken@1895
   940
     */
slouken@1895
   941
    for (i = 0; i < 256; ++i) {
slouken@1895
   942
        r_2_pix_alloc[i] = r_2_pix_alloc[256];
slouken@1895
   943
        r_2_pix_alloc[i + 512] = r_2_pix_alloc[511];
slouken@1895
   944
        g_2_pix_alloc[i] = g_2_pix_alloc[256];
slouken@1895
   945
        g_2_pix_alloc[i + 512] = g_2_pix_alloc[511];
slouken@1895
   946
        b_2_pix_alloc[i] = b_2_pix_alloc[256];
slouken@1895
   947
        b_2_pix_alloc[i + 512] = b_2_pix_alloc[511];
slouken@1895
   948
    }
slouken@0
   949
slouken@1895
   950
    /* You have chosen wisely... */
slouken@2781
   951
    switch (swdata->format) {
slouken@1965
   952
    case SDL_PIXELFORMAT_YV12:
slouken@1965
   953
    case SDL_PIXELFORMAT_IYUV:
slouken@1895
   954
        if (SDL_BYTESPERPIXEL(target_format) == 2) {
icculus@2197
   955
#if (__GNUC__ > 2) && defined(__i386__) && __OPTIMIZE__ && SDL_ASSEMBLY_ROUTINES
slouken@1895
   956
            /* inline assembly functions */
slouken@1895
   957
            if (SDL_HasMMX() && (Rmask == 0xF800) &&
slouken@2172
   958
                (Gmask == 0x07E0) && (Bmask == 0x001F)
slouken@2781
   959
                && (swdata->w & 15) == 0) {
slouken@1895
   960
/*printf("Using MMX 16-bit 565 dither\n");*/
slouken@1895
   961
                swdata->Display1X = Color565DitherYV12MMX1X;
slouken@1895
   962
            } else {
slouken@1895
   963
/*printf("Using C 16-bit dither\n");*/
slouken@1895
   964
                swdata->Display1X = Color16DitherYV12Mod1X;
slouken@1895
   965
            }
slouken@1895
   966
#else
slouken@1895
   967
            swdata->Display1X = Color16DitherYV12Mod1X;
slouken@1895
   968
#endif
slouken@1895
   969
            swdata->Display2X = Color16DitherYV12Mod2X;
slouken@1895
   970
        }
slouken@1895
   971
        if (SDL_BYTESPERPIXEL(target_format) == 3) {
slouken@1895
   972
            swdata->Display1X = Color24DitherYV12Mod1X;
slouken@1895
   973
            swdata->Display2X = Color24DitherYV12Mod2X;
slouken@1895
   974
        }
slouken@1895
   975
        if (SDL_BYTESPERPIXEL(target_format) == 4) {
icculus@2197
   976
#if (__GNUC__ > 2) && defined(__i386__) && __OPTIMIZE__ && SDL_ASSEMBLY_ROUTINES
slouken@1895
   977
            /* inline assembly functions */
slouken@1895
   978
            if (SDL_HasMMX() && (Rmask == 0x00FF0000) &&
slouken@1895
   979
                (Gmask == 0x0000FF00) &&
slouken@2781
   980
                (Bmask == 0x000000FF) && (swdata->w & 15) == 0) {
slouken@1895
   981
/*printf("Using MMX 32-bit dither\n");*/
slouken@1895
   982
                swdata->Display1X = ColorRGBDitherYV12MMX1X;
slouken@1895
   983
            } else {
slouken@1895
   984
/*printf("Using C 32-bit dither\n");*/
slouken@1895
   985
                swdata->Display1X = Color32DitherYV12Mod1X;
slouken@1895
   986
            }
slouken@1895
   987
#else
slouken@1895
   988
            swdata->Display1X = Color32DitherYV12Mod1X;
slouken@1895
   989
#endif
slouken@1895
   990
            swdata->Display2X = Color32DitherYV12Mod2X;
slouken@1895
   991
        }
slouken@1895
   992
        break;
slouken@1965
   993
    case SDL_PIXELFORMAT_YUY2:
slouken@1965
   994
    case SDL_PIXELFORMAT_UYVY:
slouken@1965
   995
    case SDL_PIXELFORMAT_YVYU:
slouken@1895
   996
        if (SDL_BYTESPERPIXEL(target_format) == 2) {
slouken@1895
   997
            swdata->Display1X = Color16DitherYUY2Mod1X;
slouken@1895
   998
            swdata->Display2X = Color16DitherYUY2Mod2X;
slouken@1895
   999
        }
slouken@1895
  1000
        if (SDL_BYTESPERPIXEL(target_format) == 3) {
slouken@1895
  1001
            swdata->Display1X = Color24DitherYUY2Mod1X;
slouken@1895
  1002
            swdata->Display2X = Color24DitherYUY2Mod2X;
slouken@1895
  1003
        }
slouken@1895
  1004
        if (SDL_BYTESPERPIXEL(target_format) == 4) {
slouken@1895
  1005
            swdata->Display1X = Color32DitherYUY2Mod1X;
slouken@1895
  1006
            swdata->Display2X = Color32DitherYUY2Mod2X;
slouken@1895
  1007
        }
slouken@1895
  1008
        break;
slouken@1895
  1009
    default:
slouken@1895
  1010
        /* We should never get here (caught above) */
slouken@1895
  1011
        break;
slouken@1895
  1012
    }
slouken@0
  1013
slouken@1895
  1014
    if (swdata->display) {
slouken@1895
  1015
        SDL_FreeSurface(swdata->display);
slouken@1895
  1016
        swdata->display = NULL;
slouken@1895
  1017
    }
slouken@1895
  1018
    return 0;
slouken@0
  1019
}
slouken@0
  1020
slouken@1895
  1021
SDL_SW_YUVTexture *
slouken@2781
  1022
SDL_SW_CreateYUVTexture(Uint32 format, int w, int h)
slouken@0
  1023
{
slouken@1895
  1024
    SDL_SW_YUVTexture *swdata;
slouken@1895
  1025
    int *Cr_r_tab;
slouken@1895
  1026
    int *Cr_g_tab;
slouken@1895
  1027
    int *Cb_g_tab;
slouken@1895
  1028
    int *Cb_b_tab;
slouken@1895
  1029
    int i;
slouken@1895
  1030
    int CR, CB;
slouken@1895
  1031
slouken@1920
  1032
    swdata = (SDL_SW_YUVTexture *) SDL_calloc(1, sizeof(*swdata));
slouken@1895
  1033
    if (!swdata) {
slouken@1895
  1034
        SDL_OutOfMemory();
slouken@1895
  1035
        return NULL;
slouken@1895
  1036
    }
slouken@1895
  1037
slouken@2781
  1038
    switch (format) {
slouken@1965
  1039
    case SDL_PIXELFORMAT_YV12:
slouken@1965
  1040
    case SDL_PIXELFORMAT_IYUV:
slouken@1965
  1041
    case SDL_PIXELFORMAT_YUY2:
slouken@1965
  1042
    case SDL_PIXELFORMAT_UYVY:
slouken@1965
  1043
    case SDL_PIXELFORMAT_YVYU:
slouken@1895
  1044
        break;
slouken@1895
  1045
    default:
slouken@6490
  1046
        SDL_SW_DestroyYUVTexture(swdata);
slouken@1895
  1047
        SDL_SetError("Unsupported YUV format");
slouken@1895
  1048
        return NULL;
slouken@1895
  1049
    }
slouken@1895
  1050
slouken@2781
  1051
    swdata->format = format;
slouken@1965
  1052
    swdata->target_format = SDL_PIXELFORMAT_UNKNOWN;
slouken@2786
  1053
    swdata->w = w;
slouken@2786
  1054
    swdata->h = h;
slouken@2781
  1055
    swdata->pixels = (Uint8 *) SDL_malloc(w * h * 2);
slouken@1895
  1056
    swdata->colortab = (int *) SDL_malloc(4 * 256 * sizeof(int));
slouken@1895
  1057
    swdata->rgb_2_pix = (Uint32 *) SDL_malloc(3 * 768 * sizeof(Uint32));
slouken@1895
  1058
    if (!swdata->pixels || !swdata->colortab || !swdata->rgb_2_pix) {
icculus@7037
  1059
        SDL_SW_DestroyYUVTexture(swdata);
slouken@1895
  1060
        SDL_OutOfMemory();
slouken@1895
  1061
        return NULL;
slouken@1895
  1062
    }
slouken@1895
  1063
slouken@1895
  1064
    /* Generate the tables for the display surface */
slouken@1895
  1065
    Cr_r_tab = &swdata->colortab[0 * 256];
slouken@1895
  1066
    Cr_g_tab = &swdata->colortab[1 * 256];
slouken@1895
  1067
    Cb_g_tab = &swdata->colortab[2 * 256];
slouken@1895
  1068
    Cb_b_tab = &swdata->colortab[3 * 256];
slouken@1895
  1069
    for (i = 0; i < 256; i++) {
slouken@1895
  1070
        /* Gamma correction (luminescence table) and chroma correction
slouken@1895
  1071
           would be done here.  See the Berkeley mpeg_play sources.
slouken@1895
  1072
         */
slouken@1895
  1073
        CB = CR = (i - 128);
slouken@1895
  1074
        Cr_r_tab[i] = (int) ((0.419 / 0.299) * CR);
slouken@1895
  1075
        Cr_g_tab[i] = (int) (-(0.299 / 0.419) * CR);
slouken@1895
  1076
        Cb_g_tab[i] = (int) (-(0.114 / 0.331) * CB);
slouken@1895
  1077
        Cb_b_tab[i] = (int) ((0.587 / 0.331) * CB);
slouken@1895
  1078
    }
slouken@1895
  1079
slouken@1895
  1080
    /* Find the pitch and offset values for the overlay */
slouken@2781
  1081
    switch (format) {
slouken@1965
  1082
    case SDL_PIXELFORMAT_YV12:
slouken@1965
  1083
    case SDL_PIXELFORMAT_IYUV:
slouken@2781
  1084
        swdata->pitches[0] = w;
slouken@1895
  1085
        swdata->pitches[1] = swdata->pitches[0] / 2;
slouken@1895
  1086
        swdata->pitches[2] = swdata->pitches[0] / 2;
slouken@1895
  1087
        swdata->planes[0] = swdata->pixels;
slouken@2786
  1088
        swdata->planes[1] = swdata->planes[0] + swdata->pitches[0] * h;
slouken@2786
  1089
        swdata->planes[2] = swdata->planes[1] + swdata->pitches[1] * h / 2;
slouken@1895
  1090
        break;
slouken@1965
  1091
    case SDL_PIXELFORMAT_YUY2:
slouken@1965
  1092
    case SDL_PIXELFORMAT_UYVY:
slouken@1965
  1093
    case SDL_PIXELFORMAT_YVYU:
slouken@2781
  1094
        swdata->pitches[0] = w * 2;
slouken@1895
  1095
        swdata->planes[0] = swdata->pixels;
slouken@1895
  1096
        break;
slouken@1895
  1097
    default:
slouken@1895
  1098
        /* We should never get here (caught above) */
slouken@1895
  1099
        break;
slouken@1895
  1100
    }
slouken@1895
  1101
slouken@1895
  1102
    /* We're all done.. */
slouken@1895
  1103
    return (swdata);
slouken@0
  1104
}
slouken@0
  1105
slouken@1895
  1106
int
slouken@1895
  1107
SDL_SW_QueryYUVTexturePixels(SDL_SW_YUVTexture * swdata, void **pixels,
slouken@1895
  1108
                             int *pitch)
slouken@0
  1109
{
slouken@1895
  1110
    *pixels = swdata->planes[0];
slouken@1895
  1111
    *pitch = swdata->pitches[0];
slouken@1895
  1112
    return 0;
slouken@0
  1113
}
slouken@0
  1114
slouken@1895
  1115
int
slouken@1895
  1116
SDL_SW_UpdateYUVTexture(SDL_SW_YUVTexture * swdata, const SDL_Rect * rect,
slouken@1895
  1117
                        const void *pixels, int pitch)
slouken@0
  1118
{
slouken@2781
  1119
    switch (swdata->format) {
slouken@1965
  1120
    case SDL_PIXELFORMAT_YV12:
slouken@1965
  1121
    case SDL_PIXELFORMAT_IYUV:
slouken@6136
  1122
        if (rect->x == 0 && rect->y == 0 &&
slouken@6136
  1123
            rect->w == swdata->w && rect->h == swdata->h) {
slouken@6136
  1124
                SDL_memcpy(swdata->pixels, pixels,
slouken@6136
  1125
                           (swdata->h * swdata->w) + (swdata->h * swdata->w) / 2);
slouken@6136
  1126
        } else {
slouken@6136
  1127
            Uint8 *src, *dst;
slouken@6136
  1128
            int row;
slouken@6136
  1129
            size_t length;
slouken@6136
  1130
slouken@6136
  1131
            /* Copy the Y plane */
slouken@6136
  1132
            src = (Uint8 *) pixels;
slouken@6136
  1133
            dst = swdata->pixels + rect->y * swdata->w + rect->x;
slouken@6136
  1134
            length = rect->w;
slouken@6136
  1135
            for (row = 0; row < rect->h; ++row) {
slouken@6136
  1136
                SDL_memcpy(dst, src, length);
slouken@6136
  1137
                src += pitch;
slouken@6136
  1138
                dst += swdata->w;
slouken@6136
  1139
            }
slouken@6136
  1140
slouken@6136
  1141
            /* Copy the next plane */
slouken@6136
  1142
            src = (Uint8 *) pixels + rect->h * pitch;
slouken@6136
  1143
            dst = swdata->pixels + swdata->h * swdata->w;
slouken@6136
  1144
            dst += rect->y/2 * swdata->w/2 + rect->x/2;
slouken@6136
  1145
            length = rect->w / 2;
slouken@6136
  1146
            for (row = 0; row < rect->h/2; ++row) {
slouken@6136
  1147
                SDL_memcpy(dst, src, length);
slouken@6136
  1148
                src += pitch/2;
slouken@6136
  1149
                dst += swdata->w/2;
slouken@6136
  1150
            }
slouken@6136
  1151
slouken@6136
  1152
            /* Copy the next plane */
slouken@6136
  1153
            src = (Uint8 *) pixels + rect->h * pitch + (rect->h * pitch) / 4;
slouken@6136
  1154
            dst = swdata->pixels + swdata->h * swdata->w +
slouken@6136
  1155
                  (swdata->h * swdata->w) / 4;
slouken@6136
  1156
            dst += rect->y/2 * swdata->w/2 + rect->x/2;
slouken@6136
  1157
            length = rect->w / 2;
slouken@6136
  1158
            for (row = 0; row < rect->h/2; ++row) {
slouken@6136
  1159
                SDL_memcpy(dst, src, length);
slouken@6136
  1160
                src += pitch/2;
slouken@6136
  1161
                dst += swdata->w/2;
slouken@6136
  1162
            }
slouken@1895
  1163
        }
slouken@1895
  1164
        break;
slouken@1965
  1165
    case SDL_PIXELFORMAT_YUY2:
slouken@1965
  1166
    case SDL_PIXELFORMAT_UYVY:
slouken@1965
  1167
    case SDL_PIXELFORMAT_YVYU:
slouken@1895
  1168
        {
slouken@1895
  1169
            Uint8 *src, *dst;
slouken@1895
  1170
            int row;
slouken@1895
  1171
            size_t length;
slouken@0
  1172
slouken@1895
  1173
            src = (Uint8 *) pixels;
slouken@1895
  1174
            dst =
slouken@1895
  1175
                swdata->planes[0] + rect->y * swdata->pitches[0] +
slouken@1895
  1176
                rect->x * 2;
slouken@1895
  1177
            length = rect->w * 2;
slouken@1895
  1178
            for (row = 0; row < rect->h; ++row) {
slouken@1895
  1179
                SDL_memcpy(dst, src, length);
slouken@1895
  1180
                src += pitch;
slouken@1895
  1181
                dst += swdata->pitches[0];
slouken@1895
  1182
            }
slouken@1895
  1183
        }
slouken@1895
  1184
        break;
slouken@1895
  1185
    }
slouken@1895
  1186
    return 0;
slouken@0
  1187
}
slouken@0
  1188
slouken@1895
  1189
int
slouken@1895
  1190
SDL_SW_LockYUVTexture(SDL_SW_YUVTexture * swdata, const SDL_Rect * rect,
slouken@5156
  1191
                      void **pixels, int *pitch)
slouken@0
  1192
{
slouken@2781
  1193
    switch (swdata->format) {
slouken@1965
  1194
    case SDL_PIXELFORMAT_YV12:
slouken@1965
  1195
    case SDL_PIXELFORMAT_IYUV:
slouken@1895
  1196
        if (rect
slouken@2781
  1197
            && (rect->x != 0 || rect->y != 0 || rect->w != swdata->w
slouken@2781
  1198
                || rect->h != swdata->h)) {
icculus@7037
  1199
            return SDL_SetError
slouken@1895
  1200
                ("YV12 and IYUV textures only support full surface locks");
slouken@1895
  1201
        }
slouken@1895
  1202
        break;
slouken@1895
  1203
    }
slouken@1895
  1204
slouken@1895
  1205
    *pixels = swdata->planes[0] + rect->y * swdata->pitches[0] + rect->x * 2;
slouken@1895
  1206
    *pitch = swdata->pitches[0];
slouken@1895
  1207
    return 0;
slouken@0
  1208
}
slouken@1895
  1209
slouken@1895
  1210
void
slouken@1895
  1211
SDL_SW_UnlockYUVTexture(SDL_SW_YUVTexture * swdata)
slouken@1895
  1212
{
slouken@1895
  1213
}
slouken@1895
  1214
slouken@1895
  1215
int
slouken@1895
  1216
SDL_SW_CopyYUVToRGB(SDL_SW_YUVTexture * swdata, const SDL_Rect * srcrect,
slouken@1895
  1217
                    Uint32 target_format, int w, int h, void *pixels,
slouken@1895
  1218
                    int pitch)
slouken@1895
  1219
{
slouken@1895
  1220
    int stretch;
slouken@1895
  1221
    int scale_2x;
slouken@1895
  1222
    Uint8 *lum, *Cr, *Cb;
slouken@1895
  1223
    int mod;
slouken@1895
  1224
slouken@1895
  1225
    /* Make sure we're set up to display in the desired format */
slouken@1895
  1226
    if (target_format != swdata->target_format) {
slouken@1895
  1227
        if (SDL_SW_SetupYUVDisplay(swdata, target_format) < 0) {
slouken@1895
  1228
            return -1;
slouken@1895
  1229
        }
slouken@1895
  1230
    }
slouken@1895
  1231
slouken@1895
  1232
    stretch = 0;
slouken@1895
  1233
    scale_2x = 0;
slouken@2781
  1234
    if (srcrect->x || srcrect->y || srcrect->w < swdata->w
slouken@2781
  1235
        || srcrect->h < swdata->h) {
slouken@1895
  1236
        /* The source rectangle has been clipped.
slouken@1895
  1237
           Using a scratch surface is easier than adding clipped
slouken@1895
  1238
           source support to all the blitters, plus that would
slouken@1895
  1239
           slow them down in the general unclipped case.
slouken@1895
  1240
         */
slouken@1895
  1241
        stretch = 1;
slouken@1895
  1242
    } else if ((srcrect->w != w) || (srcrect->h != h)) {
slouken@1895
  1243
        if ((w == 2 * srcrect->w) && (h == 2 * srcrect->h)) {
slouken@1895
  1244
            scale_2x = 1;
slouken@1895
  1245
        } else {
slouken@1895
  1246
            stretch = 1;
slouken@1895
  1247
        }
slouken@1895
  1248
    }
slouken@1895
  1249
    if (stretch) {
slouken@1895
  1250
        int bpp;
slouken@1895
  1251
        Uint32 Rmask, Gmask, Bmask, Amask;
slouken@1895
  1252
slouken@1895
  1253
        if (swdata->display) {
slouken@1895
  1254
            swdata->display->w = w;
slouken@1895
  1255
            swdata->display->h = h;
slouken@1895
  1256
            swdata->display->pixels = pixels;
slouken@1895
  1257
            swdata->display->pitch = pitch;
slouken@1895
  1258
        } else {
slouken@1895
  1259
            /* This must have succeeded in SDL_SW_SetupYUVDisplay() earlier */
slouken@1895
  1260
            SDL_PixelFormatEnumToMasks(target_format, &bpp, &Rmask, &Gmask,
slouken@1895
  1261
                                       &Bmask, &Amask);
slouken@1895
  1262
            swdata->display =
slouken@1895
  1263
                SDL_CreateRGBSurfaceFrom(pixels, w, h, bpp, pitch, Rmask,
slouken@1895
  1264
                                         Gmask, Bmask, Amask);
slouken@1895
  1265
            if (!swdata->display) {
slouken@1895
  1266
                return (-1);
slouken@1895
  1267
            }
slouken@1895
  1268
        }
slouken@1895
  1269
        if (!swdata->stretch) {
slouken@1895
  1270
            /* This must have succeeded in SDL_SW_SetupYUVDisplay() earlier */
slouken@1895
  1271
            SDL_PixelFormatEnumToMasks(target_format, &bpp, &Rmask, &Gmask,
slouken@1895
  1272
                                       &Bmask, &Amask);
slouken@1895
  1273
            swdata->stretch =
slouken@2781
  1274
                SDL_CreateRGBSurface(0, swdata->w, swdata->h, bpp, Rmask,
slouken@1895
  1275
                                     Gmask, Bmask, Amask);
slouken@1895
  1276
            if (!swdata->stretch) {
slouken@1895
  1277
                return (-1);
slouken@1895
  1278
            }
slouken@1895
  1279
        }
slouken@1895
  1280
        pixels = swdata->stretch->pixels;
slouken@1895
  1281
        pitch = swdata->stretch->pitch;
slouken@1895
  1282
    }
slouken@2781
  1283
    switch (swdata->format) {
slouken@1965
  1284
    case SDL_PIXELFORMAT_YV12:
slouken@1895
  1285
        lum = swdata->planes[0];
slouken@1895
  1286
        Cr = swdata->planes[1];
slouken@1895
  1287
        Cb = swdata->planes[2];
slouken@1895
  1288
        break;
slouken@1965
  1289
    case SDL_PIXELFORMAT_IYUV:
slouken@1895
  1290
        lum = swdata->planes[0];
slouken@1895
  1291
        Cr = swdata->planes[2];
slouken@1895
  1292
        Cb = swdata->planes[1];
slouken@1895
  1293
        break;
slouken@1965
  1294
    case SDL_PIXELFORMAT_YUY2:
slouken@1895
  1295
        lum = swdata->planes[0];
slouken@1895
  1296
        Cr = lum + 3;
slouken@1895
  1297
        Cb = lum + 1;
slouken@1895
  1298
        break;
slouken@1965
  1299
    case SDL_PIXELFORMAT_UYVY:
slouken@1895
  1300
        lum = swdata->planes[0] + 1;
slouken@1895
  1301
        Cr = lum + 1;
slouken@1895
  1302
        Cb = lum - 1;
slouken@1895
  1303
        break;
slouken@1965
  1304
    case SDL_PIXELFORMAT_YVYU:
slouken@1895
  1305
        lum = swdata->planes[0];
slouken@1895
  1306
        Cr = lum + 1;
slouken@1895
  1307
        Cb = lum + 3;
slouken@1895
  1308
        break;
slouken@1895
  1309
    default:
icculus@7037
  1310
        return SDL_SetError("Unsupported YUV format in copy");
slouken@1895
  1311
    }
slouken@1895
  1312
    mod = (pitch / SDL_BYTESPERPIXEL(target_format));
slouken@1895
  1313
slouken@1895
  1314
    if (scale_2x) {
slouken@2781
  1315
        mod -= (swdata->w * 2);
slouken@1895
  1316
        swdata->Display2X(swdata->colortab, swdata->rgb_2_pix,
slouken@2781
  1317
                          lum, Cr, Cb, pixels, swdata->h, swdata->w, mod);
slouken@1895
  1318
    } else {
slouken@2781
  1319
        mod -= swdata->w;
slouken@1895
  1320
        swdata->Display1X(swdata->colortab, swdata->rgb_2_pix,
slouken@2781
  1321
                          lum, Cr, Cb, pixels, swdata->h, swdata->w, mod);
slouken@1895
  1322
    }
slouken@1895
  1323
    if (stretch) {
slouken@1895
  1324
        SDL_Rect rect = *srcrect;
slouken@1895
  1325
        SDL_SoftStretch(swdata->stretch, &rect, swdata->display, NULL);
slouken@1895
  1326
    }
slouken@1895
  1327
    return 0;
slouken@1895
  1328
}
slouken@1895
  1329
slouken@1895
  1330
void
slouken@1895
  1331
SDL_SW_DestroyYUVTexture(SDL_SW_YUVTexture * swdata)
slouken@1895
  1332
{
slouken@1895
  1333
    if (swdata) {
slouken@1895
  1334
        if (swdata->pixels) {
slouken@1895
  1335
            SDL_free(swdata->pixels);
slouken@1895
  1336
        }
slouken@1895
  1337
        if (swdata->colortab) {
slouken@1895
  1338
            SDL_free(swdata->colortab);
slouken@1895
  1339
        }
slouken@1895
  1340
        if (swdata->rgb_2_pix) {
slouken@1895
  1341
            SDL_free(swdata->rgb_2_pix);
slouken@1895
  1342
        }
slouken@1895
  1343
        if (swdata->stretch) {
slouken@1895
  1344
            SDL_FreeSurface(swdata->stretch);
slouken@1895
  1345
        }
slouken@1895
  1346
        if (swdata->display) {
slouken@1895
  1347
            SDL_FreeSurface(swdata->display);
slouken@1895
  1348
        }
slouken@1895
  1349
        SDL_free(swdata);
slouken@1895
  1350
    }
slouken@1895
  1351
}
slouken@1895
  1352
slouken@1895
  1353
/* vi: set ts=4 sw=4 expandtab: */