src/video/SDL_yuv_sw.c
author Sam Lantinga <slouken@libsdl.org>
Tue, 15 Dec 2009 08:11:06 +0000
changeset 3565 f43c8f688f77
parent 3257 94fb40a4a9a7
child 3697 f7b03b6838cb
permissions -rw-r--r--
Fixed bug #906

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