Mercurial > sdl-ios-xcode
comparison src/video/SDL_yuv_sw.c @ 2781:5651642f4a78
Added software fallback for YUV overlay code when YUV textures aren't available.
author | Sam Lantinga <slouken@libsdl.org> |
---|---|
date | Mon, 24 Nov 2008 23:25:36 +0000 |
parents | 2ff40f30af31 |
children | 6bacfecbf27e |
comparison
equal
deleted
inserted
replaced
2780:cc15254e44b6 | 2781:5651642f4a78 |
---|---|
89 #include "SDL_yuv_sw_c.h" | 89 #include "SDL_yuv_sw_c.h" |
90 | 90 |
91 | 91 |
92 struct SDL_SW_YUVTexture | 92 struct SDL_SW_YUVTexture |
93 { | 93 { |
94 SDL_Texture *texture; | 94 Uint32 format; |
95 | |
96 Uint32 target_format; | 95 Uint32 target_format; |
96 int w, h; | |
97 Uint8 *pixels; | 97 Uint8 *pixels; |
98 int *colortab; | 98 int *colortab; |
99 Uint32 *rgb_2_pix; | 99 Uint32 *rgb_2_pix; |
100 void (*Display1X) (int *colortab, Uint32 * rgb_2_pix, | 100 void (*Display1X) (int *colortab, Uint32 * rgb_2_pix, |
101 unsigned char *lum, unsigned char *cr, | 101 unsigned char *lum, unsigned char *cr, |
972 b_2_pix_alloc[i] = b_2_pix_alloc[256]; | 972 b_2_pix_alloc[i] = b_2_pix_alloc[256]; |
973 b_2_pix_alloc[i + 512] = b_2_pix_alloc[511]; | 973 b_2_pix_alloc[i + 512] = b_2_pix_alloc[511]; |
974 } | 974 } |
975 | 975 |
976 /* You have chosen wisely... */ | 976 /* You have chosen wisely... */ |
977 switch (swdata->texture->format) { | 977 switch (swdata->format) { |
978 case SDL_PIXELFORMAT_YV12: | 978 case SDL_PIXELFORMAT_YV12: |
979 case SDL_PIXELFORMAT_IYUV: | 979 case SDL_PIXELFORMAT_IYUV: |
980 if (SDL_BYTESPERPIXEL(target_format) == 2) { | 980 if (SDL_BYTESPERPIXEL(target_format) == 2) { |
981 #if (__GNUC__ > 2) && defined(__i386__) && __OPTIMIZE__ && SDL_ASSEMBLY_ROUTINES | 981 #if (__GNUC__ > 2) && defined(__i386__) && __OPTIMIZE__ && SDL_ASSEMBLY_ROUTINES |
982 /* inline assembly functions */ | 982 /* inline assembly functions */ |
983 if (SDL_HasMMX() && (Rmask == 0xF800) && | 983 if (SDL_HasMMX() && (Rmask == 0xF800) && |
984 (Gmask == 0x07E0) && (Bmask == 0x001F) | 984 (Gmask == 0x07E0) && (Bmask == 0x001F) |
985 && (swdata->texture->w & 15) == 0) { | 985 && (swdata->w & 15) == 0) { |
986 /*printf("Using MMX 16-bit 565 dither\n");*/ | 986 /*printf("Using MMX 16-bit 565 dither\n");*/ |
987 swdata->Display1X = Color565DitherYV12MMX1X; | 987 swdata->Display1X = Color565DitherYV12MMX1X; |
988 } else { | 988 } else { |
989 /*printf("Using C 16-bit dither\n");*/ | 989 /*printf("Using C 16-bit dither\n");*/ |
990 swdata->Display1X = Color16DitherYV12Mod1X; | 990 swdata->Display1X = Color16DitherYV12Mod1X; |
1001 if (SDL_BYTESPERPIXEL(target_format) == 4) { | 1001 if (SDL_BYTESPERPIXEL(target_format) == 4) { |
1002 #if (__GNUC__ > 2) && defined(__i386__) && __OPTIMIZE__ && SDL_ASSEMBLY_ROUTINES | 1002 #if (__GNUC__ > 2) && defined(__i386__) && __OPTIMIZE__ && SDL_ASSEMBLY_ROUTINES |
1003 /* inline assembly functions */ | 1003 /* inline assembly functions */ |
1004 if (SDL_HasMMX() && (Rmask == 0x00FF0000) && | 1004 if (SDL_HasMMX() && (Rmask == 0x00FF0000) && |
1005 (Gmask == 0x0000FF00) && | 1005 (Gmask == 0x0000FF00) && |
1006 (Bmask == 0x000000FF) && (swdata->texture->w & 15) == 0) { | 1006 (Bmask == 0x000000FF) && (swdata->w & 15) == 0) { |
1007 /*printf("Using MMX 32-bit dither\n");*/ | 1007 /*printf("Using MMX 32-bit dither\n");*/ |
1008 swdata->Display1X = ColorRGBDitherYV12MMX1X; | 1008 swdata->Display1X = ColorRGBDitherYV12MMX1X; |
1009 } else { | 1009 } else { |
1010 /*printf("Using C 32-bit dither\n");*/ | 1010 /*printf("Using C 32-bit dither\n");*/ |
1011 swdata->Display1X = Color32DitherYV12Mod1X; | 1011 swdata->Display1X = Color32DitherYV12Mod1X; |
1043 } | 1043 } |
1044 return 0; | 1044 return 0; |
1045 } | 1045 } |
1046 | 1046 |
1047 SDL_SW_YUVTexture * | 1047 SDL_SW_YUVTexture * |
1048 SDL_SW_CreateYUVTexture(SDL_Texture * texture) | 1048 SDL_SW_CreateYUVTexture(Uint32 format, int w, int h) |
1049 { | 1049 { |
1050 SDL_SW_YUVTexture *swdata; | 1050 SDL_SW_YUVTexture *swdata; |
1051 int *Cr_r_tab; | 1051 int *Cr_r_tab; |
1052 int *Cr_g_tab; | 1052 int *Cr_g_tab; |
1053 int *Cb_g_tab; | 1053 int *Cb_g_tab; |
1059 if (!swdata) { | 1059 if (!swdata) { |
1060 SDL_OutOfMemory(); | 1060 SDL_OutOfMemory(); |
1061 return NULL; | 1061 return NULL; |
1062 } | 1062 } |
1063 | 1063 |
1064 switch (texture->format) { | 1064 switch (format) { |
1065 case SDL_PIXELFORMAT_YV12: | 1065 case SDL_PIXELFORMAT_YV12: |
1066 case SDL_PIXELFORMAT_IYUV: | 1066 case SDL_PIXELFORMAT_IYUV: |
1067 case SDL_PIXELFORMAT_YUY2: | 1067 case SDL_PIXELFORMAT_YUY2: |
1068 case SDL_PIXELFORMAT_UYVY: | 1068 case SDL_PIXELFORMAT_UYVY: |
1069 case SDL_PIXELFORMAT_YVYU: | 1069 case SDL_PIXELFORMAT_YVYU: |
1071 default: | 1071 default: |
1072 SDL_SetError("Unsupported YUV format"); | 1072 SDL_SetError("Unsupported YUV format"); |
1073 return NULL; | 1073 return NULL; |
1074 } | 1074 } |
1075 | 1075 |
1076 swdata->texture = texture; | 1076 swdata->format = format; |
1077 swdata->target_format = SDL_PIXELFORMAT_UNKNOWN; | 1077 swdata->target_format = SDL_PIXELFORMAT_UNKNOWN; |
1078 swdata->pixels = (Uint8 *) SDL_malloc(texture->w * texture->h * 2); | 1078 swdata->w = w; |
1079 swdata->h = h; | |
1080 swdata->pixels = (Uint8 *) SDL_malloc(w * h * 2); | |
1079 swdata->colortab = (int *) SDL_malloc(4 * 256 * sizeof(int)); | 1081 swdata->colortab = (int *) SDL_malloc(4 * 256 * sizeof(int)); |
1080 swdata->rgb_2_pix = (Uint32 *) SDL_malloc(3 * 768 * sizeof(Uint32)); | 1082 swdata->rgb_2_pix = (Uint32 *) SDL_malloc(3 * 768 * sizeof(Uint32)); |
1081 if (!swdata->pixels || !swdata->colortab || !swdata->rgb_2_pix) { | 1083 if (!swdata->pixels || !swdata->colortab || !swdata->rgb_2_pix) { |
1082 SDL_OutOfMemory(); | 1084 SDL_OutOfMemory(); |
1083 SDL_SW_DestroyYUVTexture(swdata); | 1085 SDL_SW_DestroyYUVTexture(swdata); |
1099 Cb_g_tab[i] = (int) (-(0.114 / 0.331) * CB); | 1101 Cb_g_tab[i] = (int) (-(0.114 / 0.331) * CB); |
1100 Cb_b_tab[i] = (int) ((0.587 / 0.331) * CB); | 1102 Cb_b_tab[i] = (int) ((0.587 / 0.331) * CB); |
1101 } | 1103 } |
1102 | 1104 |
1103 /* Find the pitch and offset values for the overlay */ | 1105 /* Find the pitch and offset values for the overlay */ |
1104 switch (texture->format) { | 1106 switch (format) { |
1105 case SDL_PIXELFORMAT_YV12: | 1107 case SDL_PIXELFORMAT_YV12: |
1106 case SDL_PIXELFORMAT_IYUV: | 1108 case SDL_PIXELFORMAT_IYUV: |
1107 swdata->pitches[0] = texture->w; | 1109 swdata->pitches[0] = w; |
1108 swdata->pitches[1] = swdata->pitches[0] / 2; | 1110 swdata->pitches[1] = swdata->pitches[0] / 2; |
1109 swdata->pitches[2] = swdata->pitches[0] / 2; | 1111 swdata->pitches[2] = swdata->pitches[0] / 2; |
1110 swdata->planes[0] = swdata->pixels; | 1112 swdata->planes[0] = swdata->pixels; |
1111 swdata->planes[1] = | 1113 swdata->planes[1] = |
1112 swdata->planes[0] + swdata->pitches[0] * texture->h; | 1114 swdata->planes[0] + swdata->pitches[0] * h; |
1113 swdata->planes[2] = | 1115 swdata->planes[2] = |
1114 swdata->planes[1] + swdata->pitches[1] * texture->h / 2; | 1116 swdata->planes[1] + swdata->pitches[1] * h / 2; |
1115 break; | 1117 break; |
1116 case SDL_PIXELFORMAT_YUY2: | 1118 case SDL_PIXELFORMAT_YUY2: |
1117 case SDL_PIXELFORMAT_UYVY: | 1119 case SDL_PIXELFORMAT_UYVY: |
1118 case SDL_PIXELFORMAT_YVYU: | 1120 case SDL_PIXELFORMAT_YVYU: |
1119 swdata->pitches[0] = texture->w * 2; | 1121 swdata->pitches[0] = w * 2; |
1120 swdata->planes[0] = swdata->pixels; | 1122 swdata->planes[0] = swdata->pixels; |
1121 break; | 1123 break; |
1122 default: | 1124 default: |
1123 /* We should never get here (caught above) */ | 1125 /* We should never get here (caught above) */ |
1124 break; | 1126 break; |
1139 | 1141 |
1140 int | 1142 int |
1141 SDL_SW_UpdateYUVTexture(SDL_SW_YUVTexture * swdata, const SDL_Rect * rect, | 1143 SDL_SW_UpdateYUVTexture(SDL_SW_YUVTexture * swdata, const SDL_Rect * rect, |
1142 const void *pixels, int pitch) | 1144 const void *pixels, int pitch) |
1143 { | 1145 { |
1144 SDL_Texture *texture = swdata->texture; | 1146 switch (swdata->format) { |
1145 | |
1146 switch (texture->format) { | |
1147 case SDL_PIXELFORMAT_YV12: | 1147 case SDL_PIXELFORMAT_YV12: |
1148 case SDL_PIXELFORMAT_IYUV: | 1148 case SDL_PIXELFORMAT_IYUV: |
1149 if (rect | 1149 if (rect |
1150 && (rect->x != 0 || rect->y != 0 || rect->w != texture->w | 1150 && (rect->x != 0 || rect->y != 0 || rect->w != swdata->w |
1151 || rect->h != texture->h)) { | 1151 || rect->h != swdata->h)) { |
1152 SDL_SetError | 1152 SDL_SetError |
1153 ("YV12 and IYUV textures only support full surface updates"); | 1153 ("YV12 and IYUV textures only support full surface updates"); |
1154 return -1; | 1154 return -1; |
1155 } | 1155 } |
1156 SDL_memcpy(swdata->pixels, pixels, texture->h * texture->w * 2); | 1156 SDL_memcpy(swdata->pixels, pixels, swdata->h * swdata->w * 2); |
1157 break; | 1157 break; |
1158 case SDL_PIXELFORMAT_YUY2: | 1158 case SDL_PIXELFORMAT_YUY2: |
1159 case SDL_PIXELFORMAT_UYVY: | 1159 case SDL_PIXELFORMAT_UYVY: |
1160 case SDL_PIXELFORMAT_YVYU: | 1160 case SDL_PIXELFORMAT_YVYU: |
1161 { | 1161 { |
1181 | 1181 |
1182 int | 1182 int |
1183 SDL_SW_LockYUVTexture(SDL_SW_YUVTexture * swdata, const SDL_Rect * rect, | 1183 SDL_SW_LockYUVTexture(SDL_SW_YUVTexture * swdata, const SDL_Rect * rect, |
1184 int markDirty, void **pixels, int *pitch) | 1184 int markDirty, void **pixels, int *pitch) |
1185 { | 1185 { |
1186 SDL_Texture *texture = swdata->texture; | 1186 switch (swdata->format) { |
1187 | |
1188 switch (texture->format) { | |
1189 case SDL_PIXELFORMAT_YV12: | 1187 case SDL_PIXELFORMAT_YV12: |
1190 case SDL_PIXELFORMAT_IYUV: | 1188 case SDL_PIXELFORMAT_IYUV: |
1191 if (rect | 1189 if (rect |
1192 && (rect->x != 0 || rect->y != 0 || rect->w != texture->w | 1190 && (rect->x != 0 || rect->y != 0 || rect->w != swdata->w |
1193 || rect->h != texture->h)) { | 1191 || rect->h != swdata->h)) { |
1194 SDL_SetError | 1192 SDL_SetError |
1195 ("YV12 and IYUV textures only support full surface locks"); | 1193 ("YV12 and IYUV textures only support full surface locks"); |
1196 return -1; | 1194 return -1; |
1197 } | 1195 } |
1198 break; | 1196 break; |
1211 int | 1209 int |
1212 SDL_SW_CopyYUVToRGB(SDL_SW_YUVTexture * swdata, const SDL_Rect * srcrect, | 1210 SDL_SW_CopyYUVToRGB(SDL_SW_YUVTexture * swdata, const SDL_Rect * srcrect, |
1213 Uint32 target_format, int w, int h, void *pixels, | 1211 Uint32 target_format, int w, int h, void *pixels, |
1214 int pitch) | 1212 int pitch) |
1215 { | 1213 { |
1216 SDL_Texture *texture = swdata->texture; | |
1217 int stretch; | 1214 int stretch; |
1218 int scale_2x; | 1215 int scale_2x; |
1219 Uint8 *lum, *Cr, *Cb; | 1216 Uint8 *lum, *Cr, *Cb; |
1220 int mod; | 1217 int mod; |
1221 | 1218 |
1226 } | 1223 } |
1227 } | 1224 } |
1228 | 1225 |
1229 stretch = 0; | 1226 stretch = 0; |
1230 scale_2x = 0; | 1227 scale_2x = 0; |
1231 if (srcrect->x || srcrect->y || srcrect->w < texture->w | 1228 if (srcrect->x || srcrect->y || srcrect->w < swdata->w |
1232 || srcrect->h < texture->h) { | 1229 || srcrect->h < swdata->h) { |
1233 /* The source rectangle has been clipped. | 1230 /* The source rectangle has been clipped. |
1234 Using a scratch surface is easier than adding clipped | 1231 Using a scratch surface is easier than adding clipped |
1235 source support to all the blitters, plus that would | 1232 source support to all the blitters, plus that would |
1236 slow them down in the general unclipped case. | 1233 slow them down in the general unclipped case. |
1237 */ | 1234 */ |
1266 if (!swdata->stretch) { | 1263 if (!swdata->stretch) { |
1267 /* This must have succeeded in SDL_SW_SetupYUVDisplay() earlier */ | 1264 /* This must have succeeded in SDL_SW_SetupYUVDisplay() earlier */ |
1268 SDL_PixelFormatEnumToMasks(target_format, &bpp, &Rmask, &Gmask, | 1265 SDL_PixelFormatEnumToMasks(target_format, &bpp, &Rmask, &Gmask, |
1269 &Bmask, &Amask); | 1266 &Bmask, &Amask); |
1270 swdata->stretch = | 1267 swdata->stretch = |
1271 SDL_CreateRGBSurface(0, texture->w, texture->h, bpp, Rmask, | 1268 SDL_CreateRGBSurface(0, swdata->w, swdata->h, bpp, Rmask, |
1272 Gmask, Bmask, Amask); | 1269 Gmask, Bmask, Amask); |
1273 if (!swdata->stretch) { | 1270 if (!swdata->stretch) { |
1274 return (-1); | 1271 return (-1); |
1275 } | 1272 } |
1276 } | 1273 } |
1277 pixels = swdata->stretch->pixels; | 1274 pixels = swdata->stretch->pixels; |
1278 pitch = swdata->stretch->pitch; | 1275 pitch = swdata->stretch->pitch; |
1279 } | 1276 } |
1280 switch (texture->format) { | 1277 switch (swdata->format) { |
1281 case SDL_PIXELFORMAT_YV12: | 1278 case SDL_PIXELFORMAT_YV12: |
1282 lum = swdata->planes[0]; | 1279 lum = swdata->planes[0]; |
1283 Cr = swdata->planes[1]; | 1280 Cr = swdata->planes[1]; |
1284 Cb = swdata->planes[2]; | 1281 Cb = swdata->planes[2]; |
1285 break; | 1282 break; |
1308 return (-1); | 1305 return (-1); |
1309 } | 1306 } |
1310 mod = (pitch / SDL_BYTESPERPIXEL(target_format)); | 1307 mod = (pitch / SDL_BYTESPERPIXEL(target_format)); |
1311 | 1308 |
1312 if (scale_2x) { | 1309 if (scale_2x) { |
1313 mod -= (texture->w * 2); | 1310 mod -= (swdata->w * 2); |
1314 swdata->Display2X(swdata->colortab, swdata->rgb_2_pix, | 1311 swdata->Display2X(swdata->colortab, swdata->rgb_2_pix, |
1315 lum, Cr, Cb, pixels, texture->h, texture->w, mod); | 1312 lum, Cr, Cb, pixels, swdata->h, swdata->w, mod); |
1316 } else { | 1313 } else { |
1317 mod -= texture->w; | 1314 mod -= swdata->w; |
1318 swdata->Display1X(swdata->colortab, swdata->rgb_2_pix, | 1315 swdata->Display1X(swdata->colortab, swdata->rgb_2_pix, |
1319 lum, Cr, Cb, pixels, texture->h, texture->w, mod); | 1316 lum, Cr, Cb, pixels, swdata->h, swdata->w, mod); |
1320 } | 1317 } |
1321 if (stretch) { | 1318 if (stretch) { |
1322 SDL_Rect rect = *srcrect; | 1319 SDL_Rect rect = *srcrect; |
1323 SDL_SoftStretch(swdata->stretch, &rect, swdata->display, NULL); | 1320 SDL_SoftStretch(swdata->stretch, &rect, swdata->display, NULL); |
1324 } | 1321 } |