Mercurial > sdl-ios-xcode
comparison src/video/windib/SDL_dibvideo.c @ 3992:c75679dce60c SDL-1.2
Fixed bug #335
Use SetSystemPaletteUse() to get better access to the system palette.
We can still do better palette matching in the case where we aren't
using fullscreen mode or a hardware palette, but that can wait for
another day. :)
author | Sam Lantinga <slouken@libsdl.org> |
---|---|
date | Tue, 03 Jul 2007 09:05:51 +0000 |
parents | b0d021cf41b6 |
children | 0207ca19fd8f |
comparison
equal
deleted
inserted
replaced
3991:7a649501c089 | 3992:c75679dce60c |
---|---|
85 static int DIB_LockHWSurface(_THIS, SDL_Surface *surface); | 85 static int DIB_LockHWSurface(_THIS, SDL_Surface *surface); |
86 static void DIB_UnlockHWSurface(_THIS, SDL_Surface *surface); | 86 static void DIB_UnlockHWSurface(_THIS, SDL_Surface *surface); |
87 static void DIB_FreeHWSurface(_THIS, SDL_Surface *surface); | 87 static void DIB_FreeHWSurface(_THIS, SDL_Surface *surface); |
88 | 88 |
89 /* Windows message handling functions */ | 89 /* Windows message handling functions */ |
90 static void DIB_GrabStaticColors(HWND window); | |
91 static void DIB_ReleaseStaticColors(HWND window); | |
92 static void DIB_Activate(_THIS, BOOL active, BOOL minimized); | |
90 static void DIB_RealizePalette(_THIS); | 93 static void DIB_RealizePalette(_THIS); |
91 static void DIB_PaletteChanged(_THIS, HWND window); | 94 static void DIB_PaletteChanged(_THIS, HWND window); |
92 static void DIB_WinPAINT(_THIS, HDC hdc); | 95 static void DIB_WinPAINT(_THIS, HDC hdc); |
93 | 96 |
94 /* helper fn */ | 97 /* helper fn */ |
174 device->CheckMouseMode = WIN_CheckMouseMode; | 177 device->CheckMouseMode = WIN_CheckMouseMode; |
175 device->InitOSKeymap = DIB_InitOSKeymap; | 178 device->InitOSKeymap = DIB_InitOSKeymap; |
176 device->PumpEvents = DIB_PumpEvents; | 179 device->PumpEvents = DIB_PumpEvents; |
177 | 180 |
178 /* Set up the windows message handling functions */ | 181 /* Set up the windows message handling functions */ |
182 WIN_Activate = DIB_Activate; | |
179 WIN_RealizePalette = DIB_RealizePalette; | 183 WIN_RealizePalette = DIB_RealizePalette; |
180 WIN_PaletteChanged = DIB_PaletteChanged; | 184 WIN_PaletteChanged = DIB_PaletteChanged; |
181 WIN_WinPAINT = DIB_WinPAINT; | 185 WIN_WinPAINT = DIB_WinPAINT; |
182 HandleMessage = DIB_HandleMessage; | 186 HandleMessage = DIB_HandleMessage; |
183 | 187 |
246 SDL_nummodes[index]++; | 250 SDL_nummodes[index]++; |
247 | 251 |
248 return(0); | 252 return(0); |
249 } | 253 } |
250 | 254 |
251 static HPALETTE DIB_CreatePalette(int bpp) | 255 static void DIB_CreatePalette(_THIS, int bpp) |
252 { | 256 { |
253 /* RJR: March 28, 2000 | 257 /* RJR: March 28, 2000 |
254 moved palette creation here from "DIB_VideoInit" */ | 258 moved palette creation here from "DIB_VideoInit" */ |
255 | 259 |
256 HPALETTE handle = NULL; | 260 LOGPALETTE *palette; |
257 | 261 HDC hdc; |
258 if ( bpp <= 8 ) | 262 int ncolors; |
259 { | 263 |
260 LOGPALETTE *palette; | 264 ncolors = (1 << bpp); |
261 HDC hdc; | 265 palette = (LOGPALETTE *)SDL_malloc(sizeof(*palette)+ |
262 int ncolors; | 266 ncolors*sizeof(PALETTEENTRY)); |
263 int i; | 267 palette->palVersion = 0x300; |
264 | 268 palette->palNumEntries = ncolors; |
265 ncolors = 1; | 269 hdc = GetDC(SDL_Window); |
266 for ( i=0; i<bpp; ++i ) { | 270 GetSystemPaletteEntries(hdc, 0, ncolors, palette->palPalEntry); |
267 ncolors *= 2; | 271 ReleaseDC(SDL_Window, hdc); |
268 } | 272 screen_pal = CreatePalette(palette); |
269 palette = (LOGPALETTE *)SDL_malloc(sizeof(*palette)+ | 273 screen_logpal = palette; |
270 ncolors*sizeof(PALETTEENTRY)); | |
271 palette->palVersion = 0x300; | |
272 palette->palNumEntries = ncolors; | |
273 hdc = GetDC(SDL_Window); | |
274 GetSystemPaletteEntries(hdc, 0, ncolors, palette->palPalEntry); | |
275 ReleaseDC(SDL_Window, hdc); | |
276 handle = CreatePalette(palette); | |
277 SDL_free(palette); | |
278 } | |
279 | |
280 return handle; | |
281 } | 274 } |
282 | 275 |
283 int DIB_VideoInit(_THIS, SDL_PixelFormat *vformat) | 276 int DIB_VideoInit(_THIS, SDL_PixelFormat *vformat) |
284 { | 277 { |
285 const char *env = NULL; | 278 const char *env = NULL; |
369 | 362 |
370 /* Grab an identity palette if we are in a palettized mode */ | 363 /* Grab an identity palette if we are in a palettized mode */ |
371 if ( vformat->BitsPerPixel <= 8 ) { | 364 if ( vformat->BitsPerPixel <= 8 ) { |
372 /* RJR: March 28, 2000 | 365 /* RJR: March 28, 2000 |
373 moved palette creation to "DIB_CreatePalette" */ | 366 moved palette creation to "DIB_CreatePalette" */ |
374 screen_pal = DIB_CreatePalette(vformat->BitsPerPixel); | 367 DIB_CreatePalette(this, vformat->BitsPerPixel); |
375 } | 368 } |
376 | 369 |
377 /* Fill in some window manager capabilities */ | 370 /* Fill in some window manager capabilities */ |
378 this->info.wm_available = 1; | 371 this->info.wm_available = 1; |
379 | 372 |
643 } | 636 } |
644 #endif /* !NO_CHANGEDISPLAYSETTINGS */ | 637 #endif /* !NO_CHANGEDISPLAYSETTINGS */ |
645 | 638 |
646 /* Reset the palette and create a new one if necessary */ | 639 /* Reset the palette and create a new one if necessary */ |
647 if ( screen_pal != NULL ) { | 640 if ( screen_pal != NULL ) { |
641 if ( video->flags & SDL_HWPALETTE ) { | |
642 DIB_ReleaseStaticColors(SDL_Window); | |
643 } | |
648 /* RJR: March 28, 2000 | 644 /* RJR: March 28, 2000 |
649 delete identity palette if switching from a palettized mode */ | 645 delete identity palette if switching from a palettized mode */ |
650 DeleteObject(screen_pal); | 646 DeleteObject(screen_pal); |
651 screen_pal = NULL; | 647 screen_pal = NULL; |
652 } | 648 } |
649 if ( screen_logpal != NULL ) { | |
650 SDL_free(screen_logpal); | |
651 screen_logpal = NULL; | |
652 } | |
653 if ( bpp <= 8 ) | 653 if ( bpp <= 8 ) |
654 { | 654 { |
655 /* RJR: March 28, 2000 | 655 /* RJR: March 28, 2000 |
656 create identity palette switching to a palettized mode */ | 656 create identity palette switching to a palettized mode */ |
657 screen_pal = DIB_CreatePalette(bpp); | 657 DIB_CreatePalette(this, bpp); |
658 } | 658 } |
659 | 659 |
660 style = GetWindowLong(SDL_Window, GWL_STYLE); | 660 style = GetWindowLong(SDL_Window, GWL_STYLE); |
661 style &= ~(resizestyle|WS_MAXIMIZE); | 661 style &= ~(resizestyle|WS_MAXIMIZE); |
662 if ( (video->flags & SDL_FULLSCREEN) == SDL_FULLSCREEN ) { | 662 if ( (video->flags & SDL_FULLSCREEN) == SDL_FULLSCREEN ) { |
753 return(NULL); | 753 return(NULL); |
754 } | 754 } |
755 this->UpdateRects = DIB_NormalUpdate; | 755 this->UpdateRects = DIB_NormalUpdate; |
756 | 756 |
757 /* Set video surface flags */ | 757 /* Set video surface flags */ |
758 if ( bpp <= 8 ) { | 758 if ( (flags & (SDL_FULLSCREEN|SDL_HWPALETTE)) != 0 ) { |
759 if ( (video->flags & SDL_FULLSCREEN) == SDL_FULLSCREEN ) { | |
760 hdc = GetDC(SDL_Window); | |
761 SetSystemPaletteUse(hdc, SYSPAL_NOSTATIC); | |
762 ReleaseDC(SDL_Window, hdc); | |
763 } | |
764 /* BitBlt() maps colors for us */ | 759 /* BitBlt() maps colors for us */ |
765 video->flags |= SDL_HWPALETTE; | 760 video->flags |= SDL_HWPALETTE; |
766 } | 761 } |
767 } | 762 } |
768 #ifndef _WIN32_WCE | 763 #ifndef _WIN32_WCE |
883 } | 878 } |
884 DeleteDC(mdc); | 879 DeleteDC(mdc); |
885 ReleaseDC(SDL_Window, hdc); | 880 ReleaseDC(SDL_Window, hdc); |
886 } | 881 } |
887 | 882 |
883 static int FindPaletteIndex(LOGPALETTE *pal, BYTE r, BYTE g, BYTE b) | |
884 { | |
885 PALETTEENTRY *entry; | |
886 int i; | |
887 int nentries = pal->palNumEntries; | |
888 | |
889 for ( i = 0; i < nentries; ++i ) { | |
890 entry = &pal->palPalEntry[i]; | |
891 if ( entry->peRed == r && entry->peGreen == g && entry->peBlue == b ) { | |
892 return i; | |
893 } | |
894 } | |
895 return -1; | |
896 } | |
897 | |
898 static BOOL CheckPaletteEntry(LOGPALETTE *pal, int index, BYTE r, BYTE g, BYTE b) | |
899 { | |
900 PALETTEENTRY *entry; | |
901 BOOL moved = 0; | |
902 | |
903 entry = &pal->palPalEntry[index]; | |
904 if ( entry->peRed != r || entry->peGreen != g || entry->peBlue != b ) { | |
905 int found = FindPaletteIndex(pal, r, g, b); | |
906 if ( found >= 0 ) { | |
907 pal->palPalEntry[found] = *entry; | |
908 } | |
909 entry->peRed = r; | |
910 entry->peGreen = g; | |
911 entry->peBlue = b; | |
912 moved = 1; | |
913 } | |
914 entry->peFlags = 0; | |
915 | |
916 return moved; | |
917 } | |
888 | 918 |
889 int DIB_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors) | 919 int DIB_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors) |
890 { | 920 { |
891 #if !defined(_WIN32_WCE) || (_WIN32_WCE >= 400) | 921 #if !defined(_WIN32_WCE) || (_WIN32_WCE >= 400) |
892 HDC hdc, mdc; | 922 HDC hdc, mdc; |
893 RGBQUAD *pal; | 923 RGBQUAD *pal; |
894 #else | 924 #else |
895 HDC hdc; | 925 HDC hdc; |
896 #endif | 926 #endif |
897 int i; | 927 int i; |
928 int moved_entries = 0; | |
898 | 929 |
899 /* Update the display palette */ | 930 /* Update the display palette */ |
900 hdc = GetDC(SDL_Window); | 931 hdc = GetDC(SDL_Window); |
901 if ( screen_pal ) { | 932 if ( screen_pal ) { |
902 PALETTEENTRY *entries; | 933 PALETTEENTRY *entry; |
903 | 934 |
904 entries = SDL_stack_alloc(PALETTEENTRY, ncolors); | |
905 for ( i=0; i<ncolors; ++i ) { | 935 for ( i=0; i<ncolors; ++i ) { |
906 entries[i].peRed = colors[i].r; | 936 entry = &screen_logpal->palPalEntry[firstcolor+i]; |
907 entries[i].peGreen = colors[i].g; | 937 entry->peRed = colors[i].r; |
908 entries[i].peBlue = colors[i].b; | 938 entry->peGreen = colors[i].g; |
909 entries[i].peFlags = PC_NOCOLLAPSE; | 939 entry->peBlue = colors[i].b; |
910 } | 940 entry->peFlags = PC_NOCOLLAPSE; |
911 SetPaletteEntries(screen_pal, firstcolor, ncolors, entries); | 941 } |
942 /* Check to make sure black and white are in position */ | |
943 if ( GetSystemPaletteUse(hdc) != SYSPAL_NOSTATIC256 ) { | |
944 moved_entries += CheckPaletteEntry(screen_logpal, 0, 0x00, 0x00, 0x00); | |
945 moved_entries += CheckPaletteEntry(screen_logpal, screen_logpal->palNumEntries-1, 0xff, 0xff, 0xff); | |
946 } | |
947 /* FIXME: | |
948 If we don't have full access to the palette, what we | |
949 really want to do is find the 236 most diverse colors | |
950 in the desired palette, set those entries (10-245) and | |
951 then map everything into the new system palette. | |
952 */ | |
953 | |
954 /* Copy the entries into the system palette */ | |
955 UnrealizeObject(screen_pal); | |
956 SetPaletteEntries(screen_pal, 0, screen_logpal->palNumEntries, screen_logpal->palPalEntry); | |
912 SelectPalette(hdc, screen_pal, FALSE); | 957 SelectPalette(hdc, screen_pal, FALSE); |
913 RealizePalette(hdc); | 958 RealizePalette(hdc); |
914 SDL_stack_free(entries); | |
915 } | 959 } |
916 | 960 |
917 #if !defined(_WIN32_WCE) || (_WIN32_WCE >= 400) | 961 #if !defined(_WIN32_WCE) || (_WIN32_WCE >= 400) |
918 /* Copy palette colors into DIB palette */ | 962 /* Copy palette colors into DIB palette */ |
919 pal = SDL_stack_alloc(RGBQUAD, ncolors); | 963 pal = SDL_stack_alloc(RGBQUAD, ncolors); |
926 | 970 |
927 /* Set the DIB palette and update the display */ | 971 /* Set the DIB palette and update the display */ |
928 mdc = CreateCompatibleDC(hdc); | 972 mdc = CreateCompatibleDC(hdc); |
929 SelectObject(mdc, screen_bmp); | 973 SelectObject(mdc, screen_bmp); |
930 SetDIBColorTable(mdc, firstcolor, ncolors, pal); | 974 SetDIBColorTable(mdc, firstcolor, ncolors, pal); |
931 BitBlt(hdc, 0, 0, this->screen->w, this->screen->h, | 975 if ( moved_entries || !(this->screen->flags & SDL_HWPALETTE) ) { |
932 mdc, 0, 0, SRCCOPY); | 976 BitBlt(hdc, 0, 0, this->screen->w, this->screen->h, |
977 mdc, 0, 0, SRCCOPY); | |
978 } | |
933 DeleteDC(mdc); | 979 DeleteDC(mdc); |
934 SDL_stack_free(pal); | 980 SDL_stack_free(pal); |
935 #endif | 981 #endif |
936 ReleaseDC(SDL_Window, hdc); | 982 ReleaseDC(SDL_Window, hdc); |
937 return(1); | 983 return(1); |
1046 | 1092 |
1047 /* Destroy the window and everything associated with it */ | 1093 /* Destroy the window and everything associated with it */ |
1048 if ( SDL_Window ) { | 1094 if ( SDL_Window ) { |
1049 /* Delete the screen bitmap (also frees screen->pixels) */ | 1095 /* Delete the screen bitmap (also frees screen->pixels) */ |
1050 if ( this->screen ) { | 1096 if ( this->screen ) { |
1097 if ( this->screen->flags & SDL_HWPALETTE ) { | |
1098 DIB_ReleaseStaticColors(SDL_Window); | |
1099 } | |
1051 #ifndef NO_CHANGEDISPLAYSETTINGS | 1100 #ifndef NO_CHANGEDISPLAYSETTINGS |
1052 if ( this->screen->flags & SDL_FULLSCREEN ) { | 1101 if ( this->screen->flags & SDL_FULLSCREEN ) { |
1053 ChangeDisplaySettings(NULL, 0); | 1102 ChangeDisplaySettings(NULL, 0); |
1054 ShowWindow(SDL_Window, SW_HIDE); | 1103 ShowWindow(SDL_Window, SW_HIDE); |
1055 } | 1104 } |
1057 if ( this->screen->flags & SDL_OPENGL ) { | 1106 if ( this->screen->flags & SDL_OPENGL ) { |
1058 WIN_GL_ShutDown(this); | 1107 WIN_GL_ShutDown(this); |
1059 } | 1108 } |
1060 this->screen->pixels = NULL; | 1109 this->screen->pixels = NULL; |
1061 } | 1110 } |
1111 if ( screen_pal != NULL ) { | |
1112 DeleteObject(screen_pal); | |
1113 screen_pal = NULL; | |
1114 } | |
1115 if ( screen_logpal != NULL ) { | |
1116 SDL_free(screen_logpal); | |
1117 screen_logpal = NULL; | |
1118 } | |
1062 if ( screen_bmp ) { | 1119 if ( screen_bmp ) { |
1063 DeleteObject(screen_bmp); | 1120 DeleteObject(screen_bmp); |
1064 screen_bmp = NULL; | 1121 screen_bmp = NULL; |
1065 } | 1122 } |
1066 if ( screen_icn ) { | 1123 if ( screen_icn ) { |
1095 SDL_nummodes[i] = 0; | 1152 SDL_nummodes[i] = 0; |
1096 } | 1153 } |
1097 } | 1154 } |
1098 | 1155 |
1099 /* Exported for the windows message loop only */ | 1156 /* Exported for the windows message loop only */ |
1100 static void DIB_FocusPalette(_THIS, int foreground) | 1157 static void DIB_GrabStaticColors(HWND window) |
1158 { | |
1159 HDC hdc; | |
1160 | |
1161 hdc = GetDC(window); | |
1162 SetSystemPaletteUse(hdc, SYSPAL_NOSTATIC256); | |
1163 if ( GetSystemPaletteUse(hdc) != SYSPAL_NOSTATIC256 ) { | |
1164 SetSystemPaletteUse(hdc, SYSPAL_NOSTATIC); | |
1165 } | |
1166 ReleaseDC(window, hdc); | |
1167 } | |
1168 static void DIB_ReleaseStaticColors(HWND window) | |
1169 { | |
1170 HDC hdc; | |
1171 | |
1172 hdc = GetDC(window); | |
1173 SetSystemPaletteUse(hdc, SYSPAL_STATIC); | |
1174 ReleaseDC(window, hdc); | |
1175 } | |
1176 static void DIB_Activate(_THIS, BOOL active, BOOL minimized) | |
1177 { | |
1178 if ( screen_pal && (this->screen->flags & SDL_HWPALETTE) ) { | |
1179 if ( !active ) { | |
1180 DIB_ReleaseStaticColors(SDL_Window); | |
1181 DIB_RealizePalette(this); | |
1182 } else if ( !minimized ) { | |
1183 DIB_GrabStaticColors(SDL_Window); | |
1184 DIB_RealizePalette(this); | |
1185 } | |
1186 } | |
1187 } | |
1188 static void DIB_RealizePalette(_THIS) | |
1101 { | 1189 { |
1102 if ( screen_pal != NULL ) { | 1190 if ( screen_pal != NULL ) { |
1103 HDC hdc; | 1191 HDC hdc; |
1104 | 1192 |
1105 hdc = GetDC(SDL_Window); | 1193 hdc = GetDC(SDL_Window); |
1194 UnrealizeObject(screen_pal); | |
1106 SelectPalette(hdc, screen_pal, FALSE); | 1195 SelectPalette(hdc, screen_pal, FALSE); |
1107 if ( RealizePalette(hdc) ) | 1196 if ( RealizePalette(hdc) ) { |
1108 InvalidateRect(SDL_Window, NULL, FALSE); | 1197 InvalidateRect(SDL_Window, NULL, FALSE); |
1198 } | |
1109 ReleaseDC(SDL_Window, hdc); | 1199 ReleaseDC(SDL_Window, hdc); |
1110 } | 1200 } |
1111 } | 1201 } |
1112 static void DIB_RealizePalette(_THIS) | |
1113 { | |
1114 DIB_FocusPalette(this, 1); | |
1115 } | |
1116 static void DIB_PaletteChanged(_THIS, HWND window) | 1202 static void DIB_PaletteChanged(_THIS, HWND window) |
1117 { | 1203 { |
1118 if ( window != SDL_Window ) { | 1204 if ( window != SDL_Window ) { |
1119 DIB_FocusPalette(this, 0); | 1205 DIB_RealizePalette(this); |
1120 } | 1206 } |
1121 } | 1207 } |
1122 | 1208 |
1123 /* Exported for the windows message loop only */ | 1209 /* Exported for the windows message loop only */ |
1124 static void DIB_WinPAINT(_THIS, HDC hdc) | 1210 static void DIB_WinPAINT(_THIS, HDC hdc) |