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@libsdl.org
21 */
22 #include "SDL_config.h"
23
24 /* Pocket PC GAPI SDL video driver implementation;
25 Implemented by Dmitry Yakimov - support@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
GAPI_Available(void)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
cmpmodes(const void * va,const void * vb)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
GAPI_AddMode(_THIS,int bpp,int w,int h)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
GAPI_DeleteDevice(SDL_VideoDevice * device)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
GAPI_CreateDevice(int devindex)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
FillStructs(_THIS,BOOL useVga)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
GAPI_CreatePalette(int ncolors,SDL_Color * colors)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
GAPI_VideoInit(_THIS,SDL_PixelFormat * vformat)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
GAPI_ListModes(_THIS,SDL_PixelFormat * format,Uint32 flags)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
GAPI_SetVideoMode(_THIS,SDL_Surface * current,int width,int height,int bpp,Uint32 flags)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 */
GAPI_AllocHWSurface(_THIS,SDL_Surface * surface)789 static int GAPI_AllocHWSurface(_THIS, SDL_Surface *surface)
790 {
791 return(-1);
792 }
GAPI_FreeHWSurface(_THIS,SDL_Surface * surface)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 */
GAPI_LockHWSurface(_THIS,SDL_Surface * surface)799 static int GAPI_LockHWSurface(_THIS, SDL_Surface *surface)
800 {
801 return(0);
802 }
803
GAPI_UnlockHWSurface(_THIS,SDL_Surface * surface)804 static void GAPI_UnlockHWSurface(_THIS, SDL_Surface *surface)
805 {
806 return;
807 }
808
updateLine8to8(_THIS,unsigned char * srcPointer,unsigned char * destPointer,int width,int height,int lines)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 */
updateLine16to16(_THIS,PIXEL * srcPointer,PIXEL * destPointer,int width,int height,int lines)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
updateLine16to4(_THIS,PIXEL * srcPointer,unsigned char * destPointer,int width,int height,int lines,int yNibble,int xNibble)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
GAPI_UpdateRectsMono(_THIS,int numrects,SDL_Rect * rects)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
GAPI_UpdateRectsColor(_THIS,int numrects,SDL_Rect * rects)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
GAPI_UpdateRects(_THIS,int numrects,SDL_Rect * rects)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 */
GAPI_VideoQuit(_THIS)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
GAPI_RealizePalette(_THIS)1166 static void GAPI_RealizePalette(_THIS)
1167 {
1168 OutputDebugString(TEXT("GAPI_RealizePalette NOT IMPLEMENTED !\r\n"));
1169 }
1170
GAPI_PaletteChanged(_THIS,HWND window)1171 static void GAPI_PaletteChanged(_THIS, HWND window)
1172 {
1173 OutputDebugString(TEXT("GAPI_PaletteChanged NOT IMPLEMENTED !\r\n"));
1174 }
1175
GAPI_WinPAINT(_THIS,HDC hdc)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
GAPI_SetColors(_THIS,int firstcolor,int ncolors,SDL_Color * colors)1228 int GAPI_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors)
1229 {
1230 GAPI_CreatePalette(ncolors, colors);
1231 return 1;
1232 }
1233