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)