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