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