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