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