comparison src/video/SDL_yuv_sw.c @ 1684:c4aa1a2f48f1 SDL-1.3

Software YUV texture support in progress...
author Sam Lantinga <slouken@libsdl.org>
date Sun, 18 Jun 2006 06:35:41 +0000
parents 9488fca10677
children
comparison
equal deleted inserted replaced
1683:396a35389351 1684:c4aa1a2f48f1
19 Sam Lantinga 19 Sam Lantinga
20 slouken@libsdl.org 20 slouken@libsdl.org
21 */ 21 */
22 #include "SDL_config.h" 22 #include "SDL_config.h"
23 23
24 #if 0 /* TODO */ 24 /* This is the software implementation of the YUV texture support */
25 /* This is the software implementation of the YUV video overlay support */
26 25
27 /* This code was derived from code carrying the following copyright notices: 26 /* This code was derived from code carrying the following copyright notices:
28 27
29 * Copyright (c) 1995 The Regents of the University of California. 28 * Copyright (c) 1995 The Regents of the University of California.
30 * All rights reserved. 29 * All rights reserved.
85 */ 84 */
86 85
87 #include "SDL_video.h" 86 #include "SDL_video.h"
88 #include "SDL_cpuinfo.h" 87 #include "SDL_cpuinfo.h"
89 #include "SDL_stretch_c.h" 88 #include "SDL_stretch_c.h"
90 #include "SDL_yuvfuncs.h"
91 #include "SDL_yuv_sw_c.h" 89 #include "SDL_yuv_sw_c.h"
92 90
93 /* The functions used to manipulate software video overlays */ 91
94 static struct private_yuvhwfuncs sw_yuvfuncs = { 92 struct SDL_SW_YUVTexture
95 SDL_LockYUV_SW, 93 {
96 SDL_UnlockYUV_SW, 94 SDL_Texture *texture;
97 SDL_DisplayYUV_SW, 95
98 SDL_FreeYUV_SW 96 Uint32 target_format;
99 };
100
101 /* RGB conversion lookup tables */
102 struct private_yuvhwdata
103 {
104 SDL_Surface *stretch;
105 SDL_Surface *display;
106 Uint8 *pixels; 97 Uint8 *pixels;
107 int *colortab; 98 int *colortab;
108 Uint32 *rgb_2_pix; 99 Uint32 *rgb_2_pix;
109 void (*Display1X) (int *colortab, Uint32 * rgb_2_pix, 100 void (*Display1X) (int *colortab, Uint32 * rgb_2_pix,
110 unsigned char *lum, unsigned char *cr, 101 unsigned char *lum, unsigned char *cr,
116 int rows, int cols, int mod); 107 int rows, int cols, int mod);
117 108
118 /* These are just so we don't have to allocate them separately */ 109 /* These are just so we don't have to allocate them separately */
119 Uint16 pitches[3]; 110 Uint16 pitches[3];
120 Uint8 *planes[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;
121 }; 116 };
122
123 117
124 /* The colorspace conversion functions */ 118 /* The colorspace conversion functions */
125 119
126 #if 0 /*defined(__GNUC__) && defined(__i386__) && SDL_ASSEMBLY_ROUTINES */ 120 #if 0 /*defined(__GNUC__) && defined(__i386__) && SDL_ASSEMBLY_ROUTINES */
127 extern void Color565DitherYV12MMX1X(int *colortab, Uint32 * rgb_2_pix, 121 extern void Color565DitherYV12MMX1X(int *colortab, Uint32 * rgb_2_pix,
916 if (((Sint32) a) & 1l) 910 if (((Sint32) a) & 1l)
917 return 0; 911 return 0;
918 return 1 + free_bits_at_bottom(a >> 1); 912 return 1 + free_bits_at_bottom(a >> 1);
919 } 913 }
920 914
921 915 static int
922 SDL_Overlay * 916 SDL_SW_SetupYUVDisplay(SDL_SW_YUVTexture * swdata, Uint32 target_format)
923 SDL_CreateYUV_SW(_THIS, int width, int height, Uint32 format, 917 {
924 SDL_Surface * display)
925 {
926 SDL_Overlay *overlay;
927 struct private_yuvhwdata *swdata;
928 int *Cr_r_tab;
929 int *Cr_g_tab;
930 int *Cb_g_tab;
931 int *Cb_b_tab;
932 Uint32 *r_2_pix_alloc; 918 Uint32 *r_2_pix_alloc;
933 Uint32 *g_2_pix_alloc; 919 Uint32 *g_2_pix_alloc;
934 Uint32 *b_2_pix_alloc; 920 Uint32 *b_2_pix_alloc;
935 int i; 921 int i;
936 int CR, CB; 922 int bpp;
937 Uint32 Rmask, Gmask, Bmask; 923 Uint32 Rmask, Gmask, Bmask, Amask;
938 924
939 /* Only RGB packed pixel conversion supported */ 925 if (!SDL_PixelFormatEnumToMasks
940 if ((display->format->BytesPerPixel != 2) && 926 (target_format, &bpp, &Rmask, &Gmask, &Bmask, &Amask) || bpp < 15) {
941 (display->format->BytesPerPixel != 3) && 927 SDL_SetError("Unsupported YUV destination format");
942 (display->format->BytesPerPixel != 4)) { 928 return -1;
943 SDL_SetError("Can't use YUV data on non 16/24/32 bit surfaces"); 929 }
944 return (NULL); 930
945 } 931 swdata->target_format = target_format;
946
947 /* Verify that we support the format */
948 switch (format) {
949 case SDL_YV12_OVERLAY:
950 case SDL_IYUV_OVERLAY:
951 case SDL_YUY2_OVERLAY:
952 case SDL_UYVY_OVERLAY:
953 case SDL_YVYU_OVERLAY:
954 break;
955 default:
956 SDL_SetError("Unsupported YUV format");
957 return (NULL);
958 }
959
960 /* Create the overlay structure */
961 overlay = (SDL_Overlay *) SDL_malloc(sizeof *overlay);
962 if (overlay == NULL) {
963 SDL_OutOfMemory();
964 return (NULL);
965 }
966 SDL_memset(overlay, 0, (sizeof *overlay));
967
968 /* Fill in the basic members */
969 overlay->format = format;
970 overlay->w = width;
971 overlay->h = height;
972
973 /* Set up the YUV surface function structure */
974 overlay->hwfuncs = &sw_yuvfuncs;
975
976 /* Create the pixel data and lookup tables */
977 swdata = (struct private_yuvhwdata *) SDL_malloc(sizeof *swdata);
978 overlay->hwdata = swdata;
979 if (swdata == NULL) {
980 SDL_OutOfMemory();
981 SDL_FreeYUVOverlay(overlay);
982 return (NULL);
983 }
984 swdata->stretch = NULL;
985 swdata->display = display;
986 swdata->pixels = (Uint8 *) SDL_malloc(width * height * 2);
987 swdata->colortab = (int *) SDL_malloc(4 * 256 * sizeof(int));
988 Cr_r_tab = &swdata->colortab[0 * 256];
989 Cr_g_tab = &swdata->colortab[1 * 256];
990 Cb_g_tab = &swdata->colortab[2 * 256];
991 Cb_b_tab = &swdata->colortab[3 * 256];
992 swdata->rgb_2_pix = (Uint32 *) SDL_malloc(3 * 768 * sizeof(Uint32));
993 r_2_pix_alloc = &swdata->rgb_2_pix[0 * 768]; 932 r_2_pix_alloc = &swdata->rgb_2_pix[0 * 768];
994 g_2_pix_alloc = &swdata->rgb_2_pix[1 * 768]; 933 g_2_pix_alloc = &swdata->rgb_2_pix[1 * 768];
995 b_2_pix_alloc = &swdata->rgb_2_pix[2 * 768]; 934 b_2_pix_alloc = &swdata->rgb_2_pix[2 * 768];
996 if (!swdata->pixels || !swdata->colortab || !swdata->rgb_2_pix) {
997 SDL_OutOfMemory();
998 SDL_FreeYUVOverlay(overlay);
999 return (NULL);
1000 }
1001
1002 /* Generate the tables for the display surface */
1003 for (i = 0; i < 256; i++) {
1004 /* Gamma correction (luminescence table) and chroma correction
1005 would be done here. See the Berkeley mpeg_play sources.
1006 */
1007 CB = CR = (i - 128);
1008 Cr_r_tab[i] = (int) ((0.419 / 0.299) * CR);
1009 Cr_g_tab[i] = (int) (-(0.299 / 0.419) * CR);
1010 Cb_g_tab[i] = (int) (-(0.114 / 0.331) * CB);
1011 Cb_b_tab[i] = (int) ((0.587 / 0.331) * CB);
1012 }
1013 935
1014 /* 936 /*
1015 * Set up entries 0-255 in rgb-to-pixel value tables. 937 * Set up entries 0-255 in rgb-to-pixel value tables.
1016 */ 938 */
1017 Rmask = display->format->Rmask;
1018 Gmask = display->format->Gmask;
1019 Bmask = display->format->Bmask;
1020 for (i = 0; i < 256; ++i) { 939 for (i = 0; i < 256; ++i) {
1021 r_2_pix_alloc[i + 256] = i >> (8 - number_of_bits_set(Rmask)); 940 r_2_pix_alloc[i + 256] = i >> (8 - number_of_bits_set(Rmask));
1022 r_2_pix_alloc[i + 256] <<= free_bits_at_bottom(Rmask); 941 r_2_pix_alloc[i + 256] <<= free_bits_at_bottom(Rmask);
1023 g_2_pix_alloc[i + 256] = i >> (8 - number_of_bits_set(Gmask)); 942 g_2_pix_alloc[i + 256] = i >> (8 - number_of_bits_set(Gmask));
1024 g_2_pix_alloc[i + 256] <<= free_bits_at_bottom(Gmask); 943 g_2_pix_alloc[i + 256] <<= free_bits_at_bottom(Gmask);
1031 * in the top word. This means that we can write out both 950 * in the top word. This means that we can write out both
1032 * pixels in the pixel doubling mode with one op. It is 951 * pixels in the pixel doubling mode with one op. It is
1033 * harmless in the normal case as storing a 32-bit value 952 * harmless in the normal case as storing a 32-bit value
1034 * through a short pointer will lose the top bits anyway. 953 * through a short pointer will lose the top bits anyway.
1035 */ 954 */
1036 if (display->format->BytesPerPixel == 2) { 955 if (SDL_BYTESPERPIXEL(target_format) == 2) {
1037 for (i = 0; i < 256; ++i) { 956 for (i = 0; i < 256; ++i) {
1038 r_2_pix_alloc[i + 256] |= (r_2_pix_alloc[i + 256]) << 16; 957 r_2_pix_alloc[i + 256] |= (r_2_pix_alloc[i + 256]) << 16;
1039 g_2_pix_alloc[i + 256] |= (g_2_pix_alloc[i + 256]) << 16; 958 g_2_pix_alloc[i + 256] |= (g_2_pix_alloc[i + 256]) << 16;
1040 b_2_pix_alloc[i + 256] |= (b_2_pix_alloc[i + 256]) << 16; 959 b_2_pix_alloc[i + 256] |= (b_2_pix_alloc[i + 256]) << 16;
1041 } 960 }
1053 b_2_pix_alloc[i] = b_2_pix_alloc[256]; 972 b_2_pix_alloc[i] = b_2_pix_alloc[256];
1054 b_2_pix_alloc[i + 512] = b_2_pix_alloc[511]; 973 b_2_pix_alloc[i + 512] = b_2_pix_alloc[511];
1055 } 974 }
1056 975
1057 /* You have chosen wisely... */ 976 /* You have chosen wisely... */
1058 switch (format) { 977 switch (swdata->texture->format) {
1059 case SDL_YV12_OVERLAY: 978 case SDL_PixelFormat_YV12:
1060 case SDL_IYUV_OVERLAY: 979 case SDL_PixelFormat_IYUV:
1061 if (display->format->BytesPerPixel == 2) { 980 if (SDL_BYTESPERPIXEL(target_format) == 2) {
1062 #if 0 /*defined(__GNUC__) && defined(__i386__) && SDL_ASSEMBLY_ROUTINES */ 981 #if 0 /*defined(__GNUC__) && defined(__i386__) && SDL_ASSEMBLY_ROUTINES */
1063 /* inline assembly functions */ 982 /* inline assembly functions */
1064 if (SDL_HasMMX() && (Rmask == 0xF800) && 983 if (SDL_HasMMX() && (Rmask == 0xF800) &&
1065 (Gmask == 0x07E0) && (Bmask == 0x001F) && (width & 15) == 0) { 984 (Gmask == 0x07E0) && (Bmask == 0x001F) && (width & 15) == 0) {
1066 /*printf("Using MMX 16-bit 565 dither\n");*/ 985 /*printf("Using MMX 16-bit 565 dither\n");*/
1072 #else 991 #else
1073 swdata->Display1X = Color16DitherYV12Mod1X; 992 swdata->Display1X = Color16DitherYV12Mod1X;
1074 #endif 993 #endif
1075 swdata->Display2X = Color16DitherYV12Mod2X; 994 swdata->Display2X = Color16DitherYV12Mod2X;
1076 } 995 }
1077 if (display->format->BytesPerPixel == 3) { 996 if (SDL_BYTESPERPIXEL(target_format) == 3) {
1078 swdata->Display1X = Color24DitherYV12Mod1X; 997 swdata->Display1X = Color24DitherYV12Mod1X;
1079 swdata->Display2X = Color24DitherYV12Mod2X; 998 swdata->Display2X = Color24DitherYV12Mod2X;
1080 } 999 }
1081 if (display->format->BytesPerPixel == 4) { 1000 if (SDL_BYTESPERPIXEL(target_format) == 4) {
1082 #if 0 /*defined(__GNUC__) && defined(__i386__) && SDL_ASSEMBLY_ROUTINES */ 1001 #if 0 /*defined(__GNUC__) && defined(__i386__) && SDL_ASSEMBLY_ROUTINES */
1083 /* inline assembly functions */ 1002 /* inline assembly functions */
1084 if (SDL_HasMMX() && (Rmask == 0x00FF0000) && 1003 if (SDL_HasMMX() && (Rmask == 0x00FF0000) &&
1085 (Gmask == 0x0000FF00) && 1004 (Gmask == 0x0000FF00) &&
1086 (Bmask == 0x000000FF) && (width & 15) == 0) { 1005 (Bmask == 0x000000FF) && (width & 15) == 0) {
1094 swdata->Display1X = Color32DitherYV12Mod1X; 1013 swdata->Display1X = Color32DitherYV12Mod1X;
1095 #endif 1014 #endif
1096 swdata->Display2X = Color32DitherYV12Mod2X; 1015 swdata->Display2X = Color32DitherYV12Mod2X;
1097 } 1016 }
1098 break; 1017 break;
1099 case SDL_YUY2_OVERLAY: 1018 case SDL_PixelFormat_YUY2:
1100 case SDL_UYVY_OVERLAY: 1019 case SDL_PixelFormat_UYVY:
1101 case SDL_YVYU_OVERLAY: 1020 case SDL_PixelFormat_YVYU:
1102 if (display->format->BytesPerPixel == 2) { 1021 if (SDL_BYTESPERPIXEL(target_format) == 2) {
1103 swdata->Display1X = Color16DitherYUY2Mod1X; 1022 swdata->Display1X = Color16DitherYUY2Mod1X;
1104 swdata->Display2X = Color16DitherYUY2Mod2X; 1023 swdata->Display2X = Color16DitherYUY2Mod2X;
1105 } 1024 }
1106 if (display->format->BytesPerPixel == 3) { 1025 if (SDL_BYTESPERPIXEL(target_format) == 3) {
1107 swdata->Display1X = Color24DitherYUY2Mod1X; 1026 swdata->Display1X = Color24DitherYUY2Mod1X;
1108 swdata->Display2X = Color24DitherYUY2Mod2X; 1027 swdata->Display2X = Color24DitherYUY2Mod2X;
1109 } 1028 }
1110 if (display->format->BytesPerPixel == 4) { 1029 if (SDL_BYTESPERPIXEL(target_format) == 4) {
1111 swdata->Display1X = Color32DitherYUY2Mod1X; 1030 swdata->Display1X = Color32DitherYUY2Mod1X;
1112 swdata->Display2X = Color32DitherYUY2Mod2X; 1031 swdata->Display2X = Color32DitherYUY2Mod2X;
1113 } 1032 }
1114 break; 1033 break;
1115 default: 1034 default:
1116 /* We should never get here (caught above) */ 1035 /* We should never get here (caught above) */
1117 break; 1036 break;
1118 } 1037 }
1119 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_malloc(sizeof(*swdata));
1058 if (!swdata) {
1059 SDL_OutOfMemory();
1060 return NULL;
1061 }
1062 SDL_zerop(swdata);
1063
1064 switch (texture->format) {
1065 case SDL_PixelFormat_YV12:
1066 case SDL_PixelFormat_IYUV:
1067 case SDL_PixelFormat_YUY2:
1068 case SDL_PixelFormat_UYVY:
1069 case SDL_PixelFormat_YVYU:
1070 break;
1071 default:
1072 SDL_SetError("Unsupported YUV format");
1073 return NULL;
1074 }
1075
1076 swdata->texture = texture;
1077 swdata->target_format = SDL_PixelFormat_Unknown;
1078 swdata->pixels = (Uint8 *) SDL_malloc(texture->w * texture->h * 2);
1079 swdata->colortab = (int *) SDL_malloc(4 * 256 * sizeof(int));
1080 swdata->rgb_2_pix = (Uint32 *) SDL_malloc(3 * 768 * sizeof(Uint32));
1081 if (!swdata->pixels || !swdata->colortab || !swdata->rgb_2_pix) {
1082 SDL_OutOfMemory();
1083 SDL_SW_DestroyYUVTexture(swdata);
1084 return NULL;
1085 }
1086
1087 /* Generate the tables for the display surface */
1088 Cr_r_tab = &swdata->colortab[0 * 256];
1089 Cr_g_tab = &swdata->colortab[1 * 256];
1090 Cb_g_tab = &swdata->colortab[2 * 256];
1091 Cb_b_tab = &swdata->colortab[3 * 256];
1092 for (i = 0; i < 256; i++) {
1093 /* Gamma correction (luminescence table) and chroma correction
1094 would be done here. See the Berkeley mpeg_play sources.
1095 */
1096 CB = CR = (i - 128);
1097 Cr_r_tab[i] = (int) ((0.419 / 0.299) * CR);
1098 Cr_g_tab[i] = (int) (-(0.299 / 0.419) * CR);
1099 Cb_g_tab[i] = (int) (-(0.114 / 0.331) * CB);
1100 Cb_b_tab[i] = (int) ((0.587 / 0.331) * CB);
1101 }
1102
1120 /* Find the pitch and offset values for the overlay */ 1103 /* Find the pitch and offset values for the overlay */
1121 overlay->pitches = swdata->pitches; 1104 switch (texture->format) {
1122 overlay->pixels = swdata->planes; 1105 case SDL_PixelFormat_YV12:
1123 switch (format) { 1106 case SDL_PixelFormat_IYUV:
1124 case SDL_YV12_OVERLAY: 1107 swdata->pitches[0] = texture->w;
1125 case SDL_IYUV_OVERLAY: 1108 swdata->pitches[1] = swdata->pitches[0] / 2;
1126 overlay->pitches[0] = overlay->w; 1109 swdata->pitches[2] = swdata->pitches[0] / 2;
1127 overlay->pitches[1] = overlay->pitches[0] / 2; 1110 swdata->planes[0] = swdata->pixels;
1128 overlay->pitches[2] = overlay->pitches[0] / 2; 1111 swdata->planes[1] =
1129 overlay->pixels[0] = swdata->pixels; 1112 swdata->planes[0] + swdata->pitches[0] * texture->h;
1130 overlay->pixels[1] = overlay->pixels[0] + 1113 swdata->planes[2] =
1131 overlay->pitches[0] * overlay->h; 1114 swdata->planes[1] + swdata->pitches[1] * texture->h / 2;
1132 overlay->pixels[2] = overlay->pixels[1] + 1115 break;
1133 overlay->pitches[1] * overlay->h / 2; 1116 case SDL_PixelFormat_YUY2:
1134 overlay->planes = 3; 1117 case SDL_PixelFormat_UYVY:
1135 break; 1118 case SDL_PixelFormat_YVYU:
1136 case SDL_YUY2_OVERLAY: 1119 swdata->pitches[0] = texture->w * 2;
1137 case SDL_UYVY_OVERLAY: 1120 swdata->planes[0] = swdata->pixels;
1138 case SDL_YVYU_OVERLAY:
1139 overlay->pitches[0] = overlay->w * 2;
1140 overlay->pixels[0] = swdata->pixels;
1141 overlay->planes = 1;
1142 break; 1121 break;
1143 default: 1122 default:
1144 /* We should never get here (caught above) */ 1123 /* We should never get here (caught above) */
1145 break; 1124 break;
1146 } 1125 }
1147 1126
1148 /* We're all done.. */ 1127 /* We're all done.. */
1149 return (overlay); 1128 return (swdata);
1150 } 1129 }
1151 1130
1152 int 1131 int
1153 SDL_LockYUV_SW(_THIS, SDL_Overlay * overlay) 1132 SDL_SW_QueryYUVTexturePixels(SDL_SW_YUVTexture * swdata, void **pixels,
1154 { 1133 int *pitch)
1155 return (0); 1134 {
1135 *pixels = swdata->planes[0];
1136 *pitch = swdata->pitches[0];
1137 return 0;
1138 }
1139
1140 int
1141 SDL_SW_UpdateYUVTexture(SDL_SW_YUVTexture * swdata, const SDL_Rect * rect,
1142 const void *pixels, int pitch)
1143 {
1144 SDL_Texture *texture = swdata->texture;
1145
1146 switch (texture->format) {
1147 case SDL_PixelFormat_YV12:
1148 case SDL_PixelFormat_IYUV:
1149 if (rect
1150 && (rect->x != 0 || rect->y != 0 || rect->w != texture->w
1151 || rect->h != texture->h)) {
1152 SDL_SetError
1153 ("YV12 and IYUV textures only support full surface updates");
1154 return -1;
1155 }
1156 SDL_memcpy(swdata->pixels, pixels, texture->h * texture->w * 2);
1157 break;
1158 case SDL_PixelFormat_YUY2:
1159 case SDL_PixelFormat_UYVY:
1160 case SDL_PixelFormat_YVYU:
1161 {
1162 Uint8 *src, *dst;
1163 int row;
1164 size_t length;
1165
1166 src = (Uint8 *) pixels;
1167 dst =
1168 swdata->planes[0] + rect->y * swdata->pitches[0] +
1169 rect->x * 2;
1170 length = rect->w * 2;
1171 for (row = 0; row < rect->h; ++row) {
1172 SDL_memcpy(dst, src, length);
1173 src += pitch;
1174 dst += swdata->pitches[0];
1175 }
1176 }
1177 break;
1178 }
1179 return 0;
1180 }
1181
1182 int
1183 SDL_SW_LockYUVTexture(SDL_SW_YUVTexture * swdata, const SDL_Rect * rect,
1184 int markDirty, void **pixels, int *pitch)
1185 {
1186 SDL_Texture *texture = swdata->texture;
1187
1188 switch (texture->format) {
1189 case SDL_PixelFormat_YV12:
1190 case SDL_PixelFormat_IYUV:
1191 if (rect
1192 && (rect->x != 0 || rect->y != 0 || rect->w != texture->w
1193 || rect->h != texture->h)) {
1194 SDL_SetError
1195 ("YV12 and IYUV textures only support full surface locks");
1196 return -1;
1197 }
1198 break;
1199 }
1200
1201 *pixels = swdata->planes[0] + rect->y * swdata->pitches[0] + rect->x * 2;
1202 *pitch = swdata->pitches[0];
1203 return 0;
1156 } 1204 }
1157 1205
1158 void 1206 void
1159 SDL_UnlockYUV_SW(_THIS, SDL_Overlay * overlay) 1207 SDL_SW_UnlockYUVTexture(SDL_SW_YUVTexture * swdata)
1160 { 1208 {
1161 return;
1162 } 1209 }
1163 1210
1164 int 1211 int
1165 SDL_DisplayYUV_SW(_THIS, SDL_Overlay * overlay, SDL_Rect * src, 1212 SDL_SW_CopyYUVToRGB(SDL_SW_YUVTexture * swdata, const SDL_Rect * srcrect,
1166 SDL_Rect * dst) 1213 Uint32 target_format, int w, int h, void *pixels,
1167 { 1214 int pitch)
1168 struct private_yuvhwdata *swdata; 1215 {
1216 SDL_Texture *texture = swdata->texture;
1169 int stretch; 1217 int stretch;
1170 int scale_2x; 1218 int scale_2x;
1171 SDL_Surface *display;
1172 Uint8 *lum, *Cr, *Cb; 1219 Uint8 *lum, *Cr, *Cb;
1173 Uint8 *dstp;
1174 int mod; 1220 int mod;
1175 1221
1176 swdata = overlay->hwdata; 1222 /* Make sure we're set up to display in the desired format */
1223 if (target_format != swdata->target_format) {
1224 if (SDL_SW_SetupYUVDisplay(swdata, target_format) < 0) {
1225 return -1;
1226 }
1227 }
1228
1177 stretch = 0; 1229 stretch = 0;
1178 scale_2x = 0; 1230 scale_2x = 0;
1179 if (src->x || src->y || src->w < overlay->w || src->h < overlay->h) { 1231 if (srcrect->x || srcrect->y || srcrect->w < texture->w
1232 || srcrect->h < texture->h) {
1180 /* The source rectangle has been clipped. 1233 /* The source rectangle has been clipped.
1181 Using a scratch surface is easier than adding clipped 1234 Using a scratch surface is easier than adding clipped
1182 source support to all the blitters, plus that would 1235 source support to all the blitters, plus that would
1183 slow them down in the general unclipped case. 1236 slow them down in the general unclipped case.
1184 */ 1237 */
1185 stretch = 1; 1238 stretch = 1;
1186 } else if ((src->w != dst->w) || (src->h != dst->h)) { 1239 } else if ((srcrect->w != w) || (srcrect->h != h)) {
1187 if ((dst->w == 2 * src->w) && (dst->h == 2 * src->h)) { 1240 if ((w == 2 * srcrect->w) && (h == 2 * srcrect->h)) {
1188 scale_2x = 1; 1241 scale_2x = 1;
1189 } else { 1242 } else {
1190 stretch = 1; 1243 stretch = 1;
1191 } 1244 }
1192 } 1245 }
1193 if (stretch) { 1246 if (stretch) {
1247 int bpp;
1248 Uint32 Rmask, Gmask, Bmask, Amask;
1249
1250 if (swdata->display) {
1251 swdata->display->w = w;
1252 swdata->display->h = h;
1253 swdata->display->pixels = pixels;
1254 swdata->display->pitch = pitch;
1255 } else {
1256 /* This must have succeeded in SDL_SW_SetupYUVDisplay() earlier */
1257 SDL_PixelFormatEnumToMasks(target_format, &bpp, &Rmask, &Gmask,
1258 &Bmask, &Amask);
1259 swdata->display =
1260 SDL_CreateRGBSurfaceFrom(pixels, w, h, bpp, pitch, Rmask,
1261 Gmask, Bmask, Amask);
1262 if (!swdata->display) {
1263 return (-1);
1264 }
1265 }
1194 if (!swdata->stretch) { 1266 if (!swdata->stretch) {
1195 display = swdata->display; 1267 /* This must have succeeded in SDL_SW_SetupYUVDisplay() earlier */
1196 swdata->stretch = SDL_CreateRGBSurface(0, 1268 SDL_PixelFormatEnumToMasks(target_format, &bpp, &Rmask, &Gmask,
1197 overlay->w, 1269 &Bmask, &Amask);
1198 overlay->h, 1270 swdata->stretch =
1199 display->format-> 1271 SDL_CreateRGBSurface(0, texture->w, texture->h, bpp, Rmask,
1200 BitsPerPixel, 1272 Gmask, Bmask, Amask);
1201 display->format->
1202 Rmask,
1203 display->format->
1204 Gmask,
1205 display->format->Bmask, 0);
1206 if (!swdata->stretch) { 1273 if (!swdata->stretch) {
1207 return (-1); 1274 return (-1);
1208 } 1275 }
1209 } 1276 }
1210 display = swdata->stretch; 1277 pixels = swdata->stretch->pixels;
1211 } else { 1278 pitch = swdata->stretch->pitch;
1212 display = swdata->display; 1279 }
1213 } 1280 switch (texture->format) {
1214 switch (overlay->format) { 1281 case SDL_PixelFormat_YV12:
1215 case SDL_YV12_OVERLAY: 1282 lum = swdata->planes[0];
1216 lum = overlay->pixels[0]; 1283 Cr = swdata->planes[1];
1217 Cr = overlay->pixels[1]; 1284 Cb = swdata->planes[2];
1218 Cb = overlay->pixels[2]; 1285 break;
1219 break; 1286 case SDL_PixelFormat_IYUV:
1220 case SDL_IYUV_OVERLAY: 1287 lum = swdata->planes[0];
1221 lum = overlay->pixels[0]; 1288 Cr = swdata->planes[2];
1222 Cr = overlay->pixels[2]; 1289 Cb = swdata->planes[1];
1223 Cb = overlay->pixels[1]; 1290 break;
1224 break; 1291 case SDL_PixelFormat_YUY2:
1225 case SDL_YUY2_OVERLAY: 1292 lum = swdata->planes[0];
1226 lum = overlay->pixels[0];
1227 Cr = lum + 3; 1293 Cr = lum + 3;
1228 Cb = lum + 1; 1294 Cb = lum + 1;
1229 break; 1295 break;
1230 case SDL_UYVY_OVERLAY: 1296 case SDL_PixelFormat_UYVY:
1231 lum = overlay->pixels[0] + 1; 1297 lum = swdata->planes[0] + 1;
1232 Cr = lum + 1; 1298 Cr = lum + 1;
1233 Cb = lum - 1; 1299 Cb = lum - 1;
1234 break; 1300 break;
1235 case SDL_YVYU_OVERLAY: 1301 case SDL_PixelFormat_YVYU:
1236 lum = overlay->pixels[0]; 1302 lum = swdata->planes[0];
1237 Cr = lum + 1; 1303 Cr = lum + 1;
1238 Cb = lum + 3; 1304 Cb = lum + 3;
1239 break; 1305 break;
1240 default: 1306 default:
1241 SDL_SetError("Unsupported YUV format in blit"); 1307 SDL_SetError("Unsupported YUV format in copy");
1242 return (-1); 1308 return (-1);
1243 } 1309 }
1244 if (SDL_MUSTLOCK(display)) { 1310 mod = (pitch / SDL_BYTESPERPIXEL(target_format));
1245 if (SDL_LockSurface(display) < 0) { 1311
1246 return (-1); 1312 if (scale_2x) {
1247 } 1313 mod -= (texture->w * 2);
1314 swdata->Display2X(swdata->colortab, swdata->rgb_2_pix,
1315 lum, Cr, Cb, pixels, texture->h, texture->w, mod);
1316 } else {
1317 mod -= texture->w;
1318 swdata->Display1X(swdata->colortab, swdata->rgb_2_pix,
1319 lum, Cr, Cb, pixels, texture->h, texture->w, mod);
1248 } 1320 }
1249 if (stretch) { 1321 if (stretch) {
1250 dstp = (Uint8 *) swdata->stretch->pixels; 1322 SDL_Rect rect = *srcrect;
1251 } else { 1323 SDL_SoftStretch(swdata->stretch, &rect, swdata->display, NULL);
1252 dstp = (Uint8 *) display->pixels 1324 }
1253 + dst->x * display->format->BytesPerPixel 1325 return 0;
1254 + dst->y * display->pitch;
1255 }
1256 mod = (display->pitch / display->format->BytesPerPixel);
1257
1258 if (scale_2x) {
1259 mod -= (overlay->w * 2);
1260 swdata->Display2X(swdata->colortab, swdata->rgb_2_pix,
1261 lum, Cr, Cb, dstp, overlay->h, overlay->w, mod);
1262 } else {
1263 mod -= overlay->w;
1264 swdata->Display1X(swdata->colortab, swdata->rgb_2_pix,
1265 lum, Cr, Cb, dstp, overlay->h, overlay->w, mod);
1266 }
1267 if (SDL_MUSTLOCK(display)) {
1268 SDL_UnlockSurface(display);
1269 }
1270 if (stretch) {
1271 display = swdata->display;
1272 SDL_SoftStretch(swdata->stretch, src, display, dst);
1273 }
1274 SDL_UpdateRects(display, 1, dst);
1275
1276 return (0);
1277 } 1326 }
1278 1327
1279 void 1328 void
1280 SDL_FreeYUV_SW(_THIS, SDL_Overlay * overlay) 1329 SDL_SW_DestroyYUVTexture(SDL_SW_YUVTexture * swdata)
1281 { 1330 {
1282 struct private_yuvhwdata *swdata;
1283
1284 swdata = overlay->hwdata;
1285 if (swdata) { 1331 if (swdata) {
1332 if (swdata->pixels) {
1333 SDL_free(swdata->pixels);
1334 }
1335 if (swdata->colortab) {
1336 SDL_free(swdata->colortab);
1337 }
1338 if (swdata->rgb_2_pix) {
1339 SDL_free(swdata->rgb_2_pix);
1340 }
1286 if (swdata->stretch) { 1341 if (swdata->stretch) {
1287 SDL_FreeSurface(swdata->stretch); 1342 SDL_FreeSurface(swdata->stretch);
1288 } 1343 }
1289 if (swdata->pixels) { 1344 if (swdata->display) {
1290 SDL_free(swdata->pixels); 1345 SDL_FreeSurface(swdata->display);
1291 }
1292 if (swdata->colortab) {
1293 SDL_free(swdata->colortab);
1294 }
1295 if (swdata->rgb_2_pix) {
1296 SDL_free(swdata->rgb_2_pix);
1297 } 1346 }
1298 SDL_free(swdata); 1347 SDL_free(swdata);
1299 } 1348 }
1300 } 1349 }
1301 #endif /* TODO */
1302 1350
1303 /* vi: set ts=4 sw=4 expandtab: */ 1351 /* vi: set ts=4 sw=4 expandtab: */