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 }