1 /* 2 SDL - Simple DirectMedia Layer 3 Copyright (C) 1997-2006 Sam Lantinga 4 5 This library is free software; you can redistribute it and/or 6 modify it under the terms of the GNU Lesser General Public 7 License as published by the Free Software Foundation; either 8 version 2.1 of the License, or (at your option) any later version. 9 10 This library is distributed in the hope that it will be useful, 11 but WITHOUT ANY WARRANTY; without even the implied warranty of 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 Lesser General Public License for more details. 14 15 You should have received a copy of the GNU Lesser General Public 16 License along with this library; if not, write to the Free Software 17 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 18 19 Sam Lantinga 20 slouken (at) libsdl.org 21 */ 22 #include "SDL_config.h" 23 24 /* Pocket PC GAPI SDL video driver implementation; 25 Implemented by Dmitry Yakimov - support (at) activekitten.com 26 Inspired by http://arisme.free.fr/ports/SDL.php 27 */ 28 29 // TODO: copy surface on window when lost focus 30 // TODO: test buttons rotation 31 // TODO: test on be300 and HPC ( check WinDib fullscreen keys catching ) 32 // TODO: test on smartphones 33 // TODO: windib on SH3 PPC2000 landscape test 34 // TODO: optimize 8bpp landscape mode 35 36 // there is some problems in runnings apps from a device landscape mode 37 // due to WinCE bugs. Some works and some - does not. 38 // TODO: finish Axim Dell X30 and user landscape mode, device landscape mode 39 // TODO: finish Axim Dell X30 user portrait, device landscape stylus conversion 40 // TODO: fix running GAPI apps from landscape mode - 41 // wince goes to portrait mode, but does not update video memory 42 43 44 #include "SDL.h" 45 #include "SDL_error.h" 46 #include "SDL_video.h" 47 #include "SDL_mouse.h" 48 #include "../SDL_sysvideo.h" 49 #include "../SDL_pixels_c.h" 50 #include "../../events/SDL_events_c.h" 51 #include "../wincommon/SDL_syswm_c.h" 52 #include "../wincommon/SDL_sysmouse_c.h" 53 #include "../windib/SDL_dibevents_c.h" 54 55 #include "SDL_gapivideo.h" 56 57 #define GAPIVID_DRIVER_NAME "gapi" 58 59 #if defined(DEBUG) || defined (_DEBUG) || defined(NDEBUG) 60 #define REPORT_VIDEO_INFO 1 61 #else 62 #define REPORT_VIDEO_INFO 0 63 #endif 64 65 // for testing with GapiEmu 66 #define USE_GAPI_EMU 0 67 #define EMULATE_AXIM_X30 0 68 #define WITHOUT_GAPI 0 69 70 #if USE_GAPI_EMU && !REPORT_VIDEO_INFO 71 #pragma message("Warning: Using GapiEmu in release build. I assume you'd like to set USE_GAPI_EMU to zero.") 72 #endif 73 74 // defined and used in SDL_sysevents.c 75 extern HINSTANCE aygshell; 76 extern void SDL_UnregisterApp(); 77 extern int DIB_AddMode(_THIS, int bpp, int w, int h); 78 79 /* Initialization/Query functions */ 80 static int GAPI_VideoInit(_THIS, SDL_PixelFormat *vformat); 81 static SDL_Rect **GAPI_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags); 82 static SDL_Surface *GAPI_SetVideoMode(_THIS, SDL_Surface *current, int width, int height, int bpp, Uint32 flags); 83 static int GAPI_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors); 84 static void GAPI_VideoQuit(_THIS); 85 86 /* Hardware surface functions */ 87 static int GAPI_AllocHWSurface(_THIS, SDL_Surface *surface); 88 static int GAPI_LockHWSurface(_THIS, SDL_Surface *surface); 89 static void GAPI_UnlockHWSurface(_THIS, SDL_Surface *surface); 90 static void GAPI_FreeHWSurface(_THIS, SDL_Surface *surface); 91 92 /* Windows message handling functions, will not be processed */ 93 static void GAPI_RealizePalette(_THIS); 94 static void GAPI_PaletteChanged(_THIS, HWND window); 95 static void GAPI_WinPAINT(_THIS, HDC hdc); 96 97 /* etc. */ 98 static void GAPI_UpdateRects(_THIS, int numrects, SDL_Rect *rects); 99 100 static HMODULE g_hGapiLib = 0; 101 #define LINK(type,name,import) \ 102 if( g_hGapiLib ) \ 103 name = (PFN##type)GetProcAddress( g_hGapiLib, _T(import) ); 104 105 static char g_bRawBufferAvailable = 0; 106 107 /* GAPI driver bootstrap functions */ 108 109 /* hi res definitions */ 110 typedef struct _RawFrameBufferInfo 111 { 112 WORD wFormat; 113 WORD wBPP; 114 VOID *pFramePointer; 115 int cxStride; 116 int cyStride; 117 int cxPixels; 118 int cyPixels; 119 } RawFrameBufferInfo; 120 121 static struct _RawFrameBufferInfo g_RawFrameBufferInfo = {0}; 122 123 #define GETRAWFRAMEBUFFER 0x00020001 124 125 #define FORMAT_565 1 126 #define FORMAT_555 2 127 #define FORMAT_OTHER 3 128 129 /* Dell Axim x30 hangs when we use GAPI from landscape, 130 so lets avoid using GxOpenDisplay there via GETGXINFO trick 131 It seems that GAPI subsystem use the same ExtEscape code. 132 */ 133 #define GETGXINFO 0x00020000 134 135 typedef struct GXDeviceInfo 136 { 137 long Version; //00 (should filled with 100 before calling ExtEscape) 138 void * pvFrameBuffer; //04 139 unsigned long cbStride; //08 140 unsigned long cxWidth; //0c 141 unsigned long cyHeight; //10 142 unsigned long cBPP; //14 143 unsigned long ffFormat; //18 144 char Unused[0x84-7*4]; 145 } GXDeviceInfo; 146 147 static int GAPI_Available(void) 148 { 149 // try to use VGA display, even on emulator 150 HDC hdc = GetDC(NULL); 151 int result = ExtEscape(hdc, GETRAWFRAMEBUFFER, 0, NULL, sizeof(RawFrameBufferInfo), (char *)&g_RawFrameBufferInfo); 152 ReleaseDC(NULL, hdc); 153 g_bRawBufferAvailable = result > 0; 154 155 #if WITHOUT_GAPI 156 return g_bRawBufferAvailable; 157 #endif 158 159 #if USE_GAPI_EMU 160 g_hGapiLib = LoadLibrary(_T("GAPI_Emu.dll")); 161 if( !g_hGapiLib ) 162 { 163 SDL_SetError("Gapi Emu not found!"); 164 } 165 return g_hGapiLib != 0; 166 #endif 167 168 // try to find gx.dll 169 g_hGapiLib = LoadLibrary(_T("\\Windows\\gx.dll")); 170 if( !g_hGapiLib ) 171 { 172 g_hGapiLib = LoadLibrary(_T("gx.dll")); 173 if( !g_hGapiLib ) return g_bRawBufferAvailable; 174 } 175 176 return(1); 177 } 178 179 static int cmpmodes(const void *va, const void *vb) 180 { 181 SDL_Rect *a = *(SDL_Rect **)va; 182 SDL_Rect *b = *(SDL_Rect **)vb; 183 if ( a->w == b->w ) 184 return b->h - a->h; 185 else 186 return b->w - a->w; 187 } 188 189 static int GAPI_AddMode(_THIS, int bpp, int w, int h) 190 { 191 SDL_Rect *mode; 192 int i, index; 193 int next_mode; 194 195 /* Check to see if we already have this mode */ 196 if ( bpp < 8 ) { /* Not supported */ 197 return(0); 198 } 199 index = ((bpp+7)/8)-1; 200 for ( i=0; i<gapi->SDL_nummodes[index]; ++i ) { 201 mode = gapi->SDL_modelist[index][i]; 202 if ( (mode->w == w) && (mode->h == h) ) { 203 return(0); 204 } 205 } 206 207 /* Set up the new video mode rectangle */ 208 mode = (SDL_Rect *)SDL_malloc(sizeof *mode); 209 if ( mode == NULL ) { 210 SDL_OutOfMemory(); 211 return(-1); 212 } 213 mode->x = 0; 214 mode->y = 0; 215 mode->w = w; 216 mode->h = h; 217 218 /* Allocate the new list of modes, and fill in the new mode */ 219 next_mode = gapi->SDL_nummodes[index]; 220 gapi->SDL_modelist[index] = (SDL_Rect **) 221 SDL_realloc(gapi->SDL_modelist[index], (1+next_mode+1)*sizeof(SDL_Rect *)); 222 if ( gapi->SDL_modelist[index] == NULL ) { 223 SDL_OutOfMemory(); 224 gapi->SDL_nummodes[index] = 0; 225 SDL_free(mode); 226 return(-1); 227 } 228 gapi->SDL_modelist[index][next_mode] = mode; 229 gapi->SDL_modelist[index][next_mode+1] = NULL; 230 gapi->SDL_nummodes[index]++; 231 232 return(0); 233 } 234 235 static void GAPI_DeleteDevice(SDL_VideoDevice *device) 236 { 237 if( g_hGapiLib ) 238 { 239 FreeLibrary(g_hGapiLib); 240 g_hGapiLib = 0; 241 } 242 SDL_free(device->hidden); 243 SDL_free(device); 244 } 245 246 static SDL_VideoDevice *GAPI_CreateDevice(int devindex) 247 { 248 SDL_VideoDevice *device; 249 250 if( !g_hGapiLib && !g_bRawBufferAvailable) 251 { 252 if( !GAPI_Available() ) 253 { 254 SDL_SetError("GAPI dll is not found and VGA mode is not available!"); 255 return 0; 256 } 257 } 258 259 /* Initialize all variables that we clean on shutdown */ 260 device = (SDL_VideoDevice *)SDL_malloc(sizeof(SDL_VideoDevice)); 261 if ( device ) { 262 SDL_memset(device, 0, (sizeof *device)); 263 device->hidden = (struct SDL_PrivateVideoData *) 264 SDL_malloc((sizeof *device->hidden)); 265 } 266 if ( (device == NULL) || (device->hidden == NULL) ) { 267 SDL_OutOfMemory(); 268 if ( device ) { 269 SDL_free(device); 270 } 271 return(0); 272 } 273 SDL_memset(device->hidden, 0, (sizeof *device->hidden)); 274 275 /* Set the function pointers */ 276 device->VideoInit = GAPI_VideoInit; 277 device->ListModes = GAPI_ListModes; 278 device->SetVideoMode = GAPI_SetVideoMode; 279 device->UpdateMouse = WIN_UpdateMouse; 280 device->CreateYUVOverlay = NULL; 281 device->SetColors = GAPI_SetColors; 282 device->UpdateRects = GAPI_UpdateRects; 283 device->VideoQuit = GAPI_VideoQuit; 284 device->AllocHWSurface = GAPI_AllocHWSurface; 285 device->CheckHWBlit = NULL; 286 device->FillHWRect = NULL; 287 device->SetHWColorKey = NULL; 288 device->SetHWAlpha = NULL; 289 device->LockHWSurface = GAPI_LockHWSurface; 290 device->UnlockHWSurface = GAPI_UnlockHWSurface; 291 device->FlipHWSurface = NULL; 292 device->FreeHWSurface = GAPI_FreeHWSurface; 293 device->SetCaption = WIN_SetWMCaption; 294 device->SetIcon = WIN_SetWMIcon; 295 device->IconifyWindow = WIN_IconifyWindow; 296 device->GrabInput = WIN_GrabInput; 297 device->GetWMInfo = WIN_GetWMInfo; 298 device->FreeWMCursor = WIN_FreeWMCursor; 299 device->CreateWMCursor = WIN_CreateWMCursor; 300 device->ShowWMCursor = WIN_ShowWMCursor; 301 device->WarpWMCursor = WIN_WarpWMCursor; 302 device->CheckMouseMode = WIN_CheckMouseMode; 303 device->InitOSKeymap = DIB_InitOSKeymap; 304 device->PumpEvents = DIB_PumpEvents; 305 306 /* Set up the windows message handling functions */ 307 WIN_RealizePalette = GAPI_RealizePalette; 308 WIN_PaletteChanged = GAPI_PaletteChanged; 309 WIN_WinPAINT = GAPI_WinPAINT; 310 HandleMessage = DIB_HandleMessage; 311 312 device->free = GAPI_DeleteDevice; 313 314 /* Load gapi library */ 315 #define gx device->hidden->gxFunc 316 317 LINK( GXOpenDisplay, gx.GXOpenDisplay, "?GXOpenDisplay@@YAHPAUHWND__@@K@Z" ) 318 LINK( GXCloseDisplay, gx.GXCloseDisplay, "?GXCloseDisplay@@YAHXZ" ) 319 LINK( GXBeginDraw, gx.GXBeginDraw, "?GXBeginDraw@@YAPAXXZ" ) 320 LINK( GXEndDraw, gx.GXEndDraw, "?GXEndDraw@@YAHXZ" ) 321 LINK( GXOpenInput, gx.GXOpenInput, "?GXOpenInput@@YAHXZ" ) 322 LINK( GXCloseInput, gx.GXCloseInput, "?GXCloseInput@@YAHXZ" ) 323 LINK( GXGetDisplayProperties, gx.GXGetDisplayProperties,"?GXGetDisplayProperties@@YA?AUGXDisplayProperties@@XZ" ) 324 LINK( GXGetDefaultKeys, gx.GXGetDefaultKeys, "?GXGetDefaultKeys@@YA?AUGXKeyList@@H@Z" ) 325 LINK( GXSuspend, gx.GXSuspend, "?GXSuspend@@YAHXZ" ) 326 LINK( GXResume, gx.GXResume, "?GXResume@@YAHXZ" ) 327 LINK( GXSetViewport, gx.GXSetViewport, "?GXSetViewport@@YAHKKKK@Z" ) 328 LINK( GXIsDisplayDRAMBuffer, gx.GXIsDisplayDRAMBuffer, "?GXIsDisplayDRAMBuffer@@YAHXZ" ) 329 330 /* wrong gapi.dll */ 331 if( !gx.GXOpenDisplay ) 332 { 333 if( g_hGapiLib ) 334 { 335 FreeLibrary(g_hGapiLib); 336 g_hGapiLib = 0; 337 } 338 } 339 340 if( !gx.GXOpenDisplay && !g_bRawBufferAvailable) 341 { 342 SDL_SetError("Error: damaged or unknown gapi.dll!\n"); 343 GAPI_DeleteDevice(device); 344 return 0; 345 } 346 347 return device; 348 } 349 350 VideoBootStrap GAPI_bootstrap = { 351 GAPIVID_DRIVER_NAME, "WinCE GAPI video driver", 352 GAPI_Available, GAPI_CreateDevice 353 }; 354 355 static void FillStructs(_THIS, BOOL useVga) 356 { 357 #ifdef _ARM_ 358 WCHAR oemstr[100]; 359 #endif 360 /* fill a device properties */ 361 362 if( !useVga ) 363 { 364 this->hidden->gxProperties = this->hidden->gxFunc.GXGetDisplayProperties(); 365 this->hidden->needUpdate = 1; 366 this->hidden->hiresFix = 0; 367 this->hidden->useVga = 0; 368 this->hidden->useGXOpenDisplay = 1; 369 370 #ifdef _ARM_ 371 /* check some devices and extract addition info */ 372 SystemParametersInfo( SPI_GETOEMINFO, sizeof( oemstr ), oemstr, 0 ); 373 374 // buggy iPaq38xx 375 if ((oemstr[12] == 'H') && (oemstr[13] == '3') && (oemstr[14] == '8') && (this->hidden->gxProperties.cbxPitch > 0)) 376 { 377 this->hidden->videoMem = (PIXEL*)0xac0755a0; 378 this->hidden->gxProperties.cbxPitch = -640; 379 this->hidden->gxProperties.cbyPitch = 2; 380 this->hidden->needUpdate = 0; 381 } 382 #if (EMULATE_AXIM_X30 == 0) 383 // buggy Dell Axim X30 384 if( _tcsncmp(oemstr, L"Dell Axim X30", 13) == 0 ) 385 #endif 386 { 387 GXDeviceInfo gxInfo = {0}; 388 HDC hdc = GetDC(NULL); 389 int result; 390 391 gxInfo.Version = 100; 392 result = ExtEscape(hdc, GETGXINFO, 0, NULL, sizeof(gxInfo), (char *)&gxInfo); 393 if( result > 0 ) 394 { 395 this->hidden->useGXOpenDisplay = 0; 396 this->hidden->videoMem = gxInfo.pvFrameBuffer; 397 this->hidden->needUpdate = 0; 398 this->hidden->gxProperties.cbxPitch = 2; 399 this->hidden->gxProperties.cbyPitch = 480; 400 this->hidden->gxProperties.cxWidth = gxInfo.cxWidth; 401 this->hidden->gxProperties.cyHeight = gxInfo.cyHeight; 402 this->hidden->gxProperties.ffFormat = gxInfo.ffFormat; 403 } 404 } 405 #endif 406 } else 407 { 408 this->hidden->needUpdate = 0; 409 this->hidden->hiresFix = 0; 410 this->hidden->gxProperties.cBPP = g_RawFrameBufferInfo.wBPP; 411 this->hidden->gxProperties.cbxPitch = g_RawFrameBufferInfo.cxStride; 412 this->hidden->gxProperties.cbyPitch = g_RawFrameBufferInfo.cyStride; 413 this->hidden->gxProperties.cxWidth = g_RawFrameBufferInfo.cxPixels; 414 this->hidden->gxProperties.cyHeight = g_RawFrameBufferInfo.cyPixels; 415 this->hidden->videoMem = g_RawFrameBufferInfo.pFramePointer; 416 this->hidden->useVga = 1; 417 418 switch( g_RawFrameBufferInfo.wFormat ) 419 { 420 case FORMAT_565: 421 this->hidden->gxProperties.ffFormat = kfDirect565; 422 break; 423 case FORMAT_555: 424 this->hidden->gxProperties.ffFormat = kfDirect555; 425 break; 426 default: 427 /* unknown pixel format, try define by BPP! */ 428 switch( g_RawFrameBufferInfo.wBPP ) 429 { 430 case 4: 431 case 8: 432 this->hidden->gxProperties.ffFormat = kfDirect; 433 case 16: 434 this->hidden->gxProperties.ffFormat = kfDirect565; 435 default: 436 this->hidden->gxProperties.ffFormat = kfDirect; 437 break; 438 } 439 } 440 } 441 442 if( this->hidden->gxProperties.cBPP != 16 ) 443 { 444 this->hidden->gapiOrientation = SDL_ORIENTATION_UP; 445 } else 446 if( (this->hidden->gxProperties.cbxPitch > 0) && (this->hidden->gxProperties.cbyPitch > 0 )) 447 { 448 this->hidden->gapiOrientation = SDL_ORIENTATION_UP; 449 } else 450 if( (this->hidden->gxProperties.cbxPitch > 0) && (this->hidden->gxProperties.cbyPitch < 0 )) 451 { 452 this->hidden->gapiOrientation = SDL_ORIENTATION_RIGHT; // ipaq 3660 453 } else 454 if( (this->hidden->gxProperties.cbxPitch < 0) && (this->hidden->gxProperties.cbyPitch > 0 )) 455 { 456 this->hidden->gapiOrientation = SDL_ORIENTATION_LEFT; // ipaq 3800 457 } 458 } 459 460 static void GAPI_CreatePalette(int ncolors, SDL_Color *colors) 461 { 462 // Setup a custom color palette 463 BYTE buffer[ sizeof(LOGPALETTE) + 255 * sizeof(PALETTEENTRY) ]; 464 int i; 465 LOGPALETTE* pLogical = (LOGPALETTE*)buffer; 466 PALETTEENTRY* entries = pLogical->palPalEntry; 467 HPALETTE hPalette; 468 HDC hdc; 469 470 for (i = 0; i < ncolors; ++i) 471 { 472 // Find intensity by replicating the bit patterns over a byte 473 entries[i].peRed = colors[i].r; 474 entries[i].peGreen = colors[i].g; 475 entries[i].peBlue = colors[i].b; 476 entries[i].peFlags = 0; 477 } 478 479 // Create the GDI palette object 480 pLogical->palVersion = 0x0300; 481 pLogical->palNumEntries = ncolors; 482 483 hPalette = CreatePalette( pLogical ); 484 ASSERT(hPalette); 485 486 487 // Realize the palette 488 hdc = GetDC(0); 489 490 SelectPalette( hdc, hPalette, FALSE ); 491 RealizePalette( hdc ); 492 493 ReleaseDC( 0, hdc ); 494 DeleteObject( hPalette ); 495 } 496 497 int GAPI_VideoInit(_THIS, SDL_PixelFormat *vformat) 498 { 499 int i,bpp; 500 501 /* Create the window */ 502 if ( DIB_CreateWindow(this) < 0 ) { 503 return(-1); 504 } 505 506 if( g_hGapiLib ) 507 { 508 FillStructs(this, 0); 509 510 // SDL does not supports 2/4bpp mode, so use 16 bpp 511 bpp = gapi->gxProperties.cBPP < 8 ? 16 : gapi->gxProperties.cBPP; 512 513 /* set up normal and landscape mode */ 514 GAPI_AddMode(this, bpp, gapi->gxProperties.cyHeight, gapi->gxProperties.cxWidth); 515 GAPI_AddMode(this, bpp, gapi->gxProperties.cxWidth, gapi->gxProperties.cyHeight); 516 } 517 518 /* add hi-res mode */ 519 if( g_bRawBufferAvailable && 520 !((gapi->gxProperties.cxWidth == (unsigned)g_RawFrameBufferInfo.cxPixels) && (gapi->gxProperties.cyHeight == (unsigned)g_RawFrameBufferInfo.cyPixels))) 521 { 522 FillStructs(this, 1); 523 524 // SDL does not supports 2/4bpp mode, so use 16 bpp 525 bpp = gapi->gxProperties.cBPP < 8 ? 16 : gapi->gxProperties.cBPP; 526 527 /* set up normal and landscape mode */ 528 GAPI_AddMode(this, bpp, gapi->gxProperties.cyHeight, gapi->gxProperties.cxWidth); 529 GAPI_AddMode(this, bpp, gapi->gxProperties.cxWidth, gapi->gxProperties.cyHeight); 530 } 531 532 /* Determine the current screen size */ 533 this->info.current_w = gapi->gxProperties.cxWidth; 534 this->info.current_h = gapi->gxProperties.cyHeight; 535 536 /* Sort the mode lists */ 537 for ( i=0; i<NUM_MODELISTS; ++i ) { 538 if ( gapi->SDL_nummodes[i] > 0 ) { 539 SDL_qsort(gapi->SDL_modelist[i], gapi->SDL_nummodes[i], sizeof *gapi->SDL_modelist[i], cmpmodes); 540 } 541 } 542 543 vformat->BitsPerPixel = this->hidden->gxProperties.cBPP < 8 ? 16 : (unsigned char)this->hidden->gxProperties.cBPP; 544 545 // Get color mask 546 if (this->hidden->gxProperties.ffFormat & kfDirect565) { 547 vformat->BitsPerPixel = 16; 548 vformat->Rmask = 0x0000f800; 549 vformat->Gmask = 0x000007e0; 550 vformat->Bmask = 0x0000001f; 551 this->hidden->videoMode = GAPI_DIRECT_565; 552 } 553 else 554 if (this->hidden->gxProperties.ffFormat & kfDirect555) { 555 vformat->BitsPerPixel = 16; 556 vformat->Rmask = 0x00007c00; 557 vformat->Gmask = 0x000003e0; 558 vformat->Bmask = 0x0000001f; 559 this->hidden->videoMode = GAPI_DIRECT_555; 560 } 561 else 562 if ((this->hidden->gxProperties.ffFormat & kfDirect) && (this->hidden->gxProperties.cBPP < 8)) { 563 // We'll perform the conversion 564 vformat->BitsPerPixel = 16; 565 vformat->Rmask = 0x0000f800; // 16 bit 565 566 vformat->Gmask = 0x000007e0; 567 vformat->Bmask = 0x0000001f; 568 if (this->hidden->gxProperties.ffFormat & kfDirectInverted) 569 this->hidden->invert = (1 << this->hidden->gxProperties.cBPP) - 1; 570 this->hidden->colorscale = this->hidden->gxProperties.cBPP < 8 ? 8 - this->hidden->gxProperties.cBPP : 0; 571 this->hidden->videoMode = GAPI_MONO; 572 } 573 else 574 if (this->hidden->gxProperties.ffFormat & kfPalette) { 575 this->hidden->videoMode = GAPI_PALETTE; 576 } 577 578 /* We're done! */ 579 return(0); 580 } 581 582 SDL_Rect **GAPI_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags) 583 { 584 return(this->hidden->SDL_modelist[((format->BitsPerPixel+7)/8)-1]); 585 // return (SDL_Rect **) -1; 586 } 587 588 SDL_Surface *GAPI_SetVideoMode(_THIS, SDL_Surface *current, 589 int width, int height, int bpp, Uint32 flags) 590 { 591 SDL_Surface *video; 592 Uint32 Rmask, Gmask, Bmask; 593 DWORD style; 594 SDL_Rect allScreen; 595 596 if( bpp < 4 ) 597 { 598 SDL_SetError("1 bpp and 2 bpp modes is not implemented yet!"); 599 return 0; 600 } 601 602 /* Recalculate bitmasks if necessary */ 603 if (bpp == current->format->BitsPerPixel) { 604 video = current; 605 } 606 else { 607 switch(bpp) { 608 case 8: 609 Rmask = 0; 610 Gmask = 0; 611 Bmask = 0; 612 break; 613 case 15: 614 case 16: 615 /* Default is 565 unless the display is specifically 555 */ 616 if (this->hidden->gxProperties.ffFormat & kfDirect555) { 617 Rmask = 0x00007c00; 618 Gmask = 0x000003e0; 619 Bmask = 0x0000001f; 620 } 621 else { 622 Rmask = 0x0000f800; 623 Gmask = 0x000007e0; 624 Bmask = 0x0000001f; 625 } 626 break; 627 case 24: 628 case 32: 629 Rmask = 0x00ff0000; 630 Gmask = 0x0000ff00; 631 Bmask = 0x000000ff; 632 break; 633 default: 634 SDL_SetError("Unsupported Bits Per Pixel format requested"); 635 return NULL; 636 } 637 video = SDL_CreateRGBSurface(SDL_SWSURFACE, 638 0, 0, bpp, Rmask, Gmask, Bmask, 0); 639 if ( video == NULL ) { 640 SDL_OutOfMemory(); 641 return(NULL); 642 } 643 } 644 645 gapi->userOrientation = SDL_ORIENTATION_UP; 646 video->flags = SDL_FULLSCREEN; /* Clear flags, GAPI supports fullscreen only */ 647 648 /* GAPI or VGA? */ 649 if( g_hGapiLib ) 650 { 651 FillStructs(this, 0); 652 if( (((unsigned)width != gapi->gxProperties.cxWidth) || ((unsigned)height != gapi->gxProperties.cyHeight)) 653 && (((unsigned)width != gapi->gxProperties.cyHeight) || ((unsigned)height != gapi->gxProperties.cxWidth))) 654 FillStructs(this, 1); // gapi is found but we use VGA resolution 655 } else 656 FillStructs(this, 1); 657 658 if ( !this->hidden->needUpdate && !this->hidden->videoMem) { 659 SDL_SetError("Couldn't get address of video memory, may be unsupported device or bug"); 660 return(NULL); 661 } 662 663 /* detect user landscape mode */ 664 if( (width > height) && (GetSystemMetrics(SM_CXSCREEN) < GetSystemMetrics(SM_CYSCREEN))) 665 gapi->userOrientation = SDL_ORIENTATION_RIGHT; 666 667 /* shall we apply hires fix? for example when we do not use hires resource */ 668 gapi->hiresFix = 0; 669 if( gapi->userOrientation == SDL_ORIENTATION_RIGHT ) 670 { 671 if( (width > GetSystemMetrics(SM_CYSCREEN)) || (height > GetSystemMetrics(SM_CXSCREEN))) 672 gapi->hiresFix = 1; 673 } else 674 if( (width > GetSystemMetrics(SM_CXSCREEN)) || (height > GetSystemMetrics(SM_CYSCREEN))) 675 if( !((width == GetSystemMetrics(SM_CYSCREEN)) && (height == GetSystemMetrics(SM_CXSCREEN)))) // user portrait, device landscape 676 gapi->hiresFix = 1; 677 678 switch( gapi->userOrientation ) 679 { 680 case SDL_ORIENTATION_UP: 681 gapi->startOffset = 0; 682 gapi->dstLineStep = gapi->gxProperties.cbyPitch; 683 gapi->dstPixelStep = gapi->gxProperties.cbxPitch; 684 break; 685 case SDL_ORIENTATION_RIGHT: 686 switch( gapi->gapiOrientation ) 687 { 688 case SDL_ORIENTATION_UP: 689 case SDL_ORIENTATION_RIGHT: 690 case SDL_ORIENTATION_LEFT: 691 if( (this->hidden->videoMode == GAPI_MONO) ) 692 gapi->startOffset = -gapi->gxProperties.cbxPitch + 1; // monochrome mode 693 else 694 gapi->startOffset = gapi->gxProperties.cbyPitch * (gapi->gxProperties.cyHeight - 1); 695 696 gapi->dstLineStep = gapi->gxProperties.cbxPitch; 697 gapi->dstPixelStep = -gapi->gxProperties.cbyPitch; 698 break; 699 } 700 } 701 702 video->w = this->hidden->w = width; 703 video->h = this->hidden->h = height; 704 video->pitch = SDL_CalculatePitch(video); 705 706 /* Small fix for WinCE/Win32 - when activating window 707 SDL_VideoSurface is equal to zero, so activating code 708 is not called properly for fullscreen windows because 709 macros WINDIB_FULLSCREEN uses SDL_VideoSurface 710 */ 711 SDL_VideoSurface = video; 712 713 /* GAPI is always fullscreen, title bar is useless */ 714 style = 0; 715 716 if (!SDL_windowid) 717 SetWindowLong(SDL_Window, GWL_STYLE, style); 718 719 /* Allocate bitmap */ 720 if(gapiBuffer) 721 { 722 SDL_free(gapiBuffer); 723 gapiBuffer = NULL; 724 } 725 gapiBuffer = SDL_malloc(video->h * video->pitch); 726 video->pixels = gapiBuffer; 727 728 if ( ! this->hidden->buffer ) { 729 SDL_SetError("Couldn't allocate buffer for requested mode"); 730 return(NULL); 731 } 732 733 SDL_memset(gapiBuffer, 255, video->h * video->pitch); 734 MoveWindow(SDL_Window, 0, 0, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN), FALSE); 735 ShowWindow(SDL_Window, SW_SHOW); 736 SetForegroundWindow(SDL_Window); 737 738 /* JC 14 Mar 2006 739 Flush the message loop or this can cause big problems later 740 Especially if the user decides to use dialog boxes or assert()! 741 */ 742 WIN_FlushMessageQueue(); 743 744 /* Open GAPI display */ 745 if( !gapi->useVga && this->hidden->useGXOpenDisplay ) 746 if( !gapi->gxFunc.GXOpenDisplay(SDL_Window, GX_FULLSCREEN) ) 747 { 748 SDL_SetError("Couldn't initialize GAPI"); 749 return(NULL); 750 } 751 752 #if REPORT_VIDEO_INFO 753 printf("Video properties:\n"); 754 printf("display bpp: %d\n", gapi->gxProperties.cBPP); 755 printf("display width: %d\n", gapi->gxProperties.cxWidth); 756 printf("display height: %d\n", gapi->gxProperties.cyHeight); 757 printf("x pitch: %d\n", gapi->gxProperties.cbxPitch); 758 printf("y pitch: %d\n", gapi->gxProperties.cbyPitch); 759 printf("gapi flags: 0x%x\n", gapi->gxProperties.ffFormat); 760 761 if( !gapi->useVga && this->hidden->useGXOpenDisplay && gapi->needUpdate) 762 { 763 gapi->videoMem = gapi->gxFunc.GXBeginDraw(); 764 gapi->gxFunc.GXEndDraw(); 765 } 766 767 printf("video memory: 0x%x\n", gapi->videoMem); 768 printf("need update: %d\n", gapi->needUpdate); 769 printf("hi-res fix: %d\n", gapi->hiresFix); 770 printf("VGA is available on the device: %d\n", g_bRawBufferAvailable); 771 printf("use raw framebuffer: %d\n", gapi->useVga); 772 printf("video surface bpp: %d\n", video->format->BitsPerPixel); 773 printf("video surface width: %d\n", video->w); 774 printf("video surface height: %d\n", video->h); 775 #endif 776 777 778 /* Blank screen */ 779 allScreen.x = allScreen.y = 0; 780 allScreen.w = video->w - 1; 781 allScreen.h = video->h - 1; 782 GAPI_UpdateRects(this, 1, &allScreen); 783 784 /* We're done */ 785 return(video); 786 } 787 788 /* We don't actually allow hardware surfaces other than the main one */ 789 static int GAPI_AllocHWSurface(_THIS, SDL_Surface *surface) 790 { 791 return(-1); 792 } 793 static void GAPI_FreeHWSurface(_THIS, SDL_Surface *surface) 794 { 795 return; 796 } 797 798 /* We need to wait for vertical retrace on page flipped displays */ 799 static int GAPI_LockHWSurface(_THIS, SDL_Surface *surface) 800 { 801 return(0); 802 } 803 804 static void GAPI_UnlockHWSurface(_THIS, SDL_Surface *surface) 805 { 806 return; 807 } 808 809 static int updateLine8to8(_THIS, unsigned char *srcPointer, unsigned char *destPointer, int width, int height, int lines) 810 { 811 if( gapi->dstPixelStep == 1) /* optimized blitting on most devices */ 812 { 813 SDL_memcpy(destPointer, srcPointer, width); 814 return 1; 815 } else 816 { 817 // TODO: read 4 pixels, write DWORD 818 int step = gapi->dstPixelStep; 819 while(width--) 820 { 821 *destPointer = *srcPointer++; 822 destPointer += step; 823 } 824 } 825 return 1; 826 } 827 828 /* Video memory is very slow so lets optimize as much as possible */ 829 static int updateLine16to16(_THIS, PIXEL *srcPointer, PIXEL *destPointer, int width, int height, int lines) 830 { 831 PIXEL *line1, *line2; 832 int step = gapi->dstPixelStep / 2; 833 834 if( step == 1 ) /* optimized blitting on most devices */ 835 { 836 SDL_memcpy(destPointer, srcPointer, width * sizeof(PIXEL)); 837 return 1; 838 } 839 else 840 { 841 if( (gapi->gapiOrientation != SDL_ORIENTATION_UP) && 842 (gapi->userOrientation == SDL_ORIENTATION_UP )) // iPaq 3660/3800 and user orientation up 843 { 844 // to prevent data misalignment copy only one line 845 if( ((((unsigned)destPointer & 3) != 0) && (gapi->gapiOrientation == SDL_ORIENTATION_LEFT)) 846 || ((((unsigned)destPointer & 3) == 0) && (gapi->gapiOrientation != SDL_ORIENTATION_LEFT)) 847 || (lines == 1) ) 848 { 849 while(width--) 850 { 851 *destPointer = *srcPointer++; 852 destPointer += step; 853 } 854 return 1; 855 } 856 857 /* read two lines at the same time, write DWORD */ 858 line1 = srcPointer; 859 line2 = srcPointer + SDL_VideoSurface->pitch / 2; 860 861 if( gapi->gapiOrientation == SDL_ORIENTATION_LEFT ) 862 while(width--) // iPaq 3800 863 { 864 *(DWORD*)destPointer =(*line2++ << 16) | *line1++; 865 destPointer += step; 866 } 867 else 868 { 869 destPointer += gapi->gxProperties.cbyPitch / 2; 870 871 while(width--) // iPaq 3660 872 { 873 *(DWORD*)destPointer =(*line1++ << 16) | *line2++; 874 destPointer += step; 875 } 876 } 877 return 2; 878 } else 879 { 880 // iPaq 3800 and user orientation landscape 881 if( gapi->gapiOrientation == SDL_ORIENTATION_LEFT ) 882 { 883 int w1; 884 885 // to prevent data misalignment copy only one pixel 886 if( (((unsigned)destPointer & 3) == 0) && (width > 0)) 887 { 888 *destPointer-- = *srcPointer++; 889 width--; 890 } 891 892 destPointer--; 893 894 w1 = width / 2; 895 896 while(w1--) 897 { 898 DWORD p = *(DWORD*)srcPointer; 899 *((DWORD*)destPointer) = (p << 16) | (p >> 16); 900 destPointer -= 2; 901 srcPointer += 2; 902 } 903 904 if( width & 1 ) // copy the last pixel 905 { 906 destPointer++; 907 *destPointer = *srcPointer; 908 } 909 910 return 1; 911 } 912 913 // modern iPaqs and user orientation landscape 914 // read two pixels, write DWORD 915 916 line1 = srcPointer; 917 line2 = srcPointer + SDL_VideoSurface->pitch / 2; 918 919 if( (((unsigned)destPointer & 3) != 0) || (lines == 1) ) 920 { 921 while(width--) 922 { 923 *destPointer = *srcPointer++; 924 destPointer += step; 925 } 926 return 1; 927 } 928 929 while(width--) 930 { 931 *(DWORD*)destPointer =(*line2++ << 16) | *line1++; 932 destPointer -= gapi->gxProperties.cbyPitch / 2; 933 } 934 return 2; 935 } 936 } 937 } 938 939 // Color component masks for 565 940 #define REDMASK (31<<11) 941 #define GREENMASK (63<<5) 942 #define BLUEMASK (31) 943 944 945 static int updateLine16to4(_THIS, PIXEL *srcPointer, unsigned char *destPointer, int width, int height, int lines, int yNibble, int xNibble) 946 { 947 PIXEL *line1, *line2; 948 int step = gapi->dstPixelStep; 949 950 if( gapi->userOrientation == SDL_ORIENTATION_UP ) 951 { 952 if( yNibble ) // copy bottom half of a line 953 { 954 while(width--) 955 { 956 PIXEL c1 = *srcPointer++; 957 c1 = ((c1 & REDMASK) >> 11) + ((c1 & GREENMASK) >> 5) + (c1 & BLUEMASK); 958 *destPointer = (*destPointer & 0x0F) | ((~(c1 >> 3) << 4)); 959 destPointer += step; 960 } 961 return 1; 962 } 963 964 // either 1 pixel picture or tail, anyway this is the last line 965 if( lines == 1 ) 966 { 967 while(width--) 968 { 969 PIXEL c1 = *srcPointer++; 970 c1 = ((c1 & REDMASK) >> 11) + ((c1 & GREENMASK) >> 5) + (c1 & BLUEMASK); 971 *destPointer = (*destPointer & 0xF0) | ((~(c1 >> 3) & 0xF)); 972 destPointer += step; 973 } 974 return 1; 975 } 976 977 line1 = srcPointer; 978 line2 = srcPointer + SDL_VideoSurface->pitch / 2; 979 980 while(width--) 981 { 982 PIXEL c1 = *line1++; 983 PIXEL c2 = *line2++; 984 c1 = ((c1 & REDMASK) >> 11) + ((c1 & GREENMASK) >> 5) + (c1 & BLUEMASK); 985 c2 = ((c2 & REDMASK) >> 11) + ((c2 & GREENMASK) >> 5) + (c2 & BLUEMASK); 986 *destPointer = ~((c1 >> 3) + ((c2 >> 3) << 4)); 987 destPointer += step; 988 } 989 return 2; 990 } else 991 { 992 int w1; 993 w1 = width / 2; 994 995 if( xNibble ) 996 { 997 // copy one pixel 998 PIXEL c1 = *srcPointer++; 999 c1 = ((c1 & REDMASK) >> 11) + ((c1 & GREENMASK) >> 5) + (c1 & BLUEMASK); 1000 *destPointer = (*destPointer & 0xF0) | ((~(c1 >> 3) & 0xF)); 1001 destPointer++; 1002 } 1003 1004 while(w1--) 1005 { 1006 PIXEL c1 = *srcPointer; 1007 PIXEL c2 = *(srcPointer + 1); 1008 c1 = ((c1 & REDMASK) >> 11) + ((c1 & GREENMASK) >> 5) + (c1 & BLUEMASK); 1009 c2 = ((c2 & REDMASK) >> 11) + ((c2 & GREENMASK) >> 5) + (c2 & BLUEMASK); 1010 *destPointer++ = ~((c2 >> 3) + ((c1 >> 3) << 4)); 1011 srcPointer += 2; 1012 } 1013 1014 // copy tail 1015 if( (width & 1) && !xNibble ) 1016 { 1017 PIXEL c1 = *srcPointer; 1018 c1 = ((c1 & REDMASK) >> 11) + ((c1 & GREENMASK) >> 5) + (c1 & BLUEMASK); 1019 *destPointer = (*destPointer & 0x0F) | ((~(c1 >> 3) << 4)); 1020 } 1021 1022 return 1; 1023 } 1024 } 1025 1026 static void GAPI_UpdateRectsMono(_THIS, int numrects, SDL_Rect *rects) 1027 { 1028 int i, height; 1029 int linesProcessed; 1030 int xNibble, yNibble; 1031 1032 for (i=0; i<numrects; i++) 1033 { 1034 unsigned char *destPointer; 1035 unsigned char *srcPointer; 1036 1037 if( gapi->userOrientation == SDL_ORIENTATION_UP ) 1038 destPointer = (unsigned char*) gapi->videoMem + gapi->startOffset - rects[i].y * gapi->gxProperties.cBPP / 8 + rects[i].x * gapi->dstPixelStep; 1039 else 1040 destPointer = (unsigned char*) gapi->videoMem + gapi->startOffset + rects[i].x * gapi->gxProperties.cBPP / 8 + rects[i].y * gapi->dstLineStep; 1041 1042 srcPointer = ((unsigned char*) SDL_VideoSurface->pixels) + rects[i].y * SDL_VideoSurface->pitch + rects[i].x * 2; 1043 yNibble = rects[i].y & 1; // TODO: only for 4 bpp 1044 xNibble = rects[i].x & 1; 1045 height = rects[i].h; 1046 while (height > 0) 1047 { 1048 switch(gapi->gxProperties.cBPP) 1049 { 1050 case 2: // TODO 1051 case 4: 1052 linesProcessed = updateLine16to4(this, (PIXEL*) srcPointer, destPointer, rects[i].w, rects[i].h, height, yNibble, xNibble); 1053 yNibble = 0; 1054 } 1055 height -= linesProcessed; 1056 if( gapi->userOrientation == SDL_ORIENTATION_UP ) 1057 destPointer--; // always fill 1 byte 1058 else destPointer += gapi->dstLineStep; 1059 srcPointer += SDL_VideoSurface->pitch * linesProcessed; // pitch in bytes 1060 } 1061 } 1062 } 1063 1064 static void GAPI_UpdateRectsColor(_THIS, int numrects, SDL_Rect *rects) 1065 { 1066 int i, height; 1067 int bytesPerPixel = (gapi->gxProperties.cBPP + 1) / 8; 1068 int linesProcessed; 1069 for (i=0; i<numrects; i++) { 1070 unsigned char *destPointer = (unsigned char*) gapi->videoMem + gapi->startOffset + rects[i].y * gapi->dstLineStep + rects[i].x * gapi->dstPixelStep; 1071 unsigned char *srcPointer = ((unsigned char*) SDL_VideoSurface->pixels) + rects[i].y * SDL_VideoSurface->pitch + rects[i].x * bytesPerPixel; 1072 height = rects[i].h; 1073 1074 // fprintf(stderr, "Starting rect %dx%d, dst=0x%x, w = %d, h = %d\n", rects[i].w, rects[i].h,destPointer,rects[i].w,rects[i].h); 1075 // fflush(stderr); 1076 linesProcessed = height; 1077 1078 while (height > 0) { 1079 switch(bytesPerPixel) 1080 { 1081 case 1: 1082 linesProcessed = updateLine8to8(this, srcPointer, (unsigned char *) destPointer, rects[i].w, rects[i].h, height); 1083 break; 1084 case 2: 1085 #pragma warning(disable: 4133) 1086 linesProcessed = updateLine16to16(this, (PIXEL*) srcPointer, destPointer, rects[i].w, rects[i].h, height); 1087 break; 1088 } 1089 height -= linesProcessed; 1090 destPointer += gapi->dstLineStep * linesProcessed; 1091 srcPointer += SDL_VideoSurface->pitch * linesProcessed; // pitch in bytes 1092 } 1093 // fprintf(stderr, "End of rect\n"); 1094 // fflush(stderr); 1095 } 1096 } 1097 1098 1099 static void GAPI_UpdateRects(_THIS, int numrects, SDL_Rect *rects) 1100 { 1101 // we do not want to corrupt video memory 1102 if( gapi->suspended ) return; 1103 1104 if( gapi->needUpdate ) 1105 gapi->videoMem = gapi->gxFunc.GXBeginDraw(); 1106 1107 if( gapi->gxProperties.cBPP < 8 ) 1108 GAPI_UpdateRectsMono(this, numrects, rects); 1109 else 1110 GAPI_UpdateRectsColor(this, numrects, rects); 1111 1112 if( gapi->needUpdate ) 1113 gapi->gxFunc.GXEndDraw(); 1114 } 1115 1116 /* Note: If we are terminated, this could be called in the middle of 1117 another SDL video routine -- notably UpdateRects. 1118 */ 1119 void GAPI_VideoQuit(_THIS) 1120 { 1121 int i, j; 1122 /* Destroy the window and everything associated with it */ 1123 if ( SDL_Window ) 1124 { 1125 if ((g_hGapiLib != 0) && this && this->hidden && this->hidden->gxFunc.GXCloseDisplay && !this->hidden->useVga) 1126 this->hidden->gxFunc.GXCloseDisplay(); 1127 1128 if (this->screen->pixels != NULL) 1129 { 1130 SDL_free(this->screen->pixels); 1131 this->screen->pixels = NULL; 1132 } 1133 if ( screen_icn ) { 1134 DestroyIcon(screen_icn); 1135 screen_icn = NULL; 1136 } 1137 1138 DIB_DestroyWindow(this); 1139 SDL_UnregisterApp(); 1140 1141 SDL_Window = NULL; 1142 #if defined(_WIN32_WCE) 1143 1144 // Unload wince aygshell library to prevent leak 1145 if( aygshell ) 1146 { 1147 FreeLibrary(aygshell); 1148 aygshell = NULL; 1149 } 1150 #endif 1151 1152 /* Free video mode lists */ 1153 for ( i=0; i<NUM_MODELISTS; ++i ) { 1154 if ( gapi->SDL_modelist[i] != NULL ) { 1155 for ( j=0; gapi->SDL_modelist[i][j]; ++j ) 1156 SDL_free(gapi->SDL_modelist[i][j]); 1157 SDL_free(gapi->SDL_modelist[i]); 1158 gapi->SDL_modelist[i] = NULL; 1159 } 1160 } 1161 1162 } 1163 1164 } 1165 1166 static void GAPI_RealizePalette(_THIS) 1167 { 1168 OutputDebugString(TEXT("GAPI_RealizePalette NOT IMPLEMENTED !\r\n")); 1169 } 1170 1171 static void GAPI_PaletteChanged(_THIS, HWND window) 1172 { 1173 OutputDebugString(TEXT("GAPI_PaletteChanged NOT IMPLEMENTED !\r\n")); 1174 } 1175 1176 static void GAPI_WinPAINT(_THIS, HDC hdc) 1177 { 1178 // draw current offscreen buffer on hdc 1179 1180 int bpp = 16; // we always use either 8 or 16 bpp internally 1181 HGDIOBJ prevObject; 1182 unsigned short *bitmapData; 1183 HBITMAP hb; 1184 HDC srcDC; 1185 1186 // Create a DIB 1187 BYTE buffer[sizeof(BITMAPINFOHEADER) + 3 * sizeof(RGBQUAD)] = {0}; 1188 BITMAPINFO* pBMI = (BITMAPINFO*)buffer; 1189 BITMAPINFOHEADER* pHeader = &pBMI->bmiHeader; 1190 DWORD* pColors = (DWORD*)&pBMI->bmiColors; 1191 1192 // CreateDIBSection does not support 332 pixel format on wce 1193 if( gapi->gxProperties.cBPP == 8 ) return; 1194 1195 // DIB Header 1196 pHeader->biSize = sizeof(BITMAPINFOHEADER); 1197 pHeader->biWidth = this->hidden->w; 1198 pHeader->biHeight = -this->hidden->h; 1199 pHeader->biPlanes = 1; 1200 pHeader->biBitCount = bpp; 1201 pHeader->biCompression = BI_RGB; 1202 pHeader->biSizeImage = (this->hidden->w * this->hidden->h * bpp) / 8; 1203 1204 // Color masks 1205 if( bpp == 16 ) 1206 { 1207 pColors[0] = REDMASK; 1208 pColors[1] = GREENMASK; 1209 pColors[2] = BLUEMASK; 1210 pHeader->biCompression = BI_BITFIELDS; 1211 } 1212 // Create the DIB 1213 hb = CreateDIBSection( 0, pBMI, DIB_RGB_COLORS, (void**)&bitmapData, 0, 0 ); 1214 1215 // copy data 1216 // FIXME: prevent misalignment, but I've never seen non aligned width of screen 1217 memcpy(bitmapData, this->hidden->buffer, pHeader->biSizeImage); 1218 srcDC = CreateCompatibleDC(hdc); 1219 prevObject = SelectObject(srcDC, hb); 1220 1221 BitBlt(hdc, 0, 0, this->hidden->w, this->hidden->h, srcDC, 0, 0, SRCCOPY); 1222 1223 SelectObject(srcDC, prevObject); 1224 DeleteObject(hb); 1225 DeleteDC(srcDC); 1226 } 1227 1228 int GAPI_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors) 1229 { 1230 GAPI_CreatePalette(ncolors, colors); 1231 return 1; 1232 } 1233