Mercurial > sdl-ios-xcode
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: */ |