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; |
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 "../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 |
86 | extern HINSTANCE aygshell; |
87 | extern void SDL_UnregisterApp(); |
88 | extern int DIB_AddMode(_THIS, int bpp, int w, int h); |
89 | |
90 | /* Initialization/Query functions */ |
91 | static int GAPI_VideoInit(_THIS, SDL_PixelFormat *vformat); |
92 | static SDL_Rect **GAPI_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags); |
93 | static SDL_Surface *GAPI_SetVideoMode(_THIS, SDL_Surface *current, int width, int height, int bpp, Uint32 flags); |
94 | static int GAPI_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors); |
95 | static void GAPI_VideoQuit(_THIS); |
96 | |
97 | /* Hardware surface functions */ |
98 | static int GAPI_AllocHWSurface(_THIS, SDL_Surface *surface); |
99 | static int GAPI_LockHWSurface(_THIS, SDL_Surface *surface); |
100 | static void GAPI_UnlockHWSurface(_THIS, SDL_Surface *surface); |
101 | static void GAPI_FreeHWSurface(_THIS, SDL_Surface *surface); |
102 | |
103 | /* Windows message handling functions, will not be processed */ |
104 | static void GAPI_Activate(_THIS, BOOL active, BOOL minimized); |
105 | static void GAPI_RealizePalette(_THIS); |
106 | static void GAPI_PaletteChanged(_THIS, HWND window); |
107 | static void GAPI_WinPAINT(_THIS, HDC hdc); |
108 | |
109 | /* etc. */ |
110 | static void GAPI_UpdateRects(_THIS, int numrects, SDL_Rect *rects); |
111 | |
112 | static HMODULE g_hGapiLib = 0; |
113 | #define LINK(type,name,import) \ |
114 | if( g_hGapiLib ) \ |
115 | name = (PFN##type)GetProcAddress( g_hGapiLib, _T(import) ); |
116 | |
117 | static char g_bRawBufferAvailable = 0; |
118 | |
119 | /* GAPI driver bootstrap functions */ |
120 | |
121 | /* hi res definitions */ |
122 | typedef 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 | |
133 | static 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 | |
147 | typedef struct GXDeviceInfo |
148 | { |
149 | long Version; //00 (should filled with 100 before calling ExtEscape) |
150 | void * pvFrameBuffer; //04 |
151 | unsigned long cbStride; //08 |
152 | unsigned long cxWidth; //0c |
153 | unsigned long cyHeight; //10 |
154 | unsigned long cBPP; //14 |
155 | unsigned long ffFormat; //18 |
156 | char Unused[0x84-7*4]; |
157 | } GXDeviceInfo; |
158 | |
159 | static 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 | |
196 | static 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 | |
206 | static 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 | |
252 | static 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 | |
264 | static 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 | |
378 | VideoBootStrap GAPI_bootstrap = { |
379 | GAPIVID_DRIVER_NAME, "WinCE GAPI video driver", |
380 | GAPI_Available, GAPI_CreateDevice |
381 | }; |
382 | |
383 | static 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 | |
488 | static 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 | |
525 | int 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 | |
612 | SDL_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 | |
618 | SDL_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 */ |
839 | static int GAPI_AllocHWSurface(_THIS, SDL_Surface *surface) |
840 | { |
841 | return(-1); |
842 | } |
843 | static void GAPI_FreeHWSurface(_THIS, SDL_Surface *surface) |
844 | { |
845 | return; |
846 | } |
847 | |
848 | /* We need to wait for vertical retrace on page flipped displays */ |
849 | static int GAPI_LockHWSurface(_THIS, SDL_Surface *surface) |
850 | { |
851 | return(0); |
852 | } |
853 | |
854 | static void GAPI_UnlockHWSurface(_THIS, SDL_Surface *surface) |
855 | { |
856 | return; |
857 | } |
858 | |
859 | static 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 */ |
879 | static 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 | |
995 | static 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 | |
1076 | static 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 | |
1114 | static 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 | |
1149 | static 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 | */ |
1169 | void 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 | |
1216 | static void GAPI_Activate(_THIS, BOOL active, BOOL minimized) |
1217 | { |
1218 | //Nothing to do here (as far as I know) |
1219 | } |
1220 | |
1221 | static void GAPI_RealizePalette(_THIS) |
1222 | { |
1223 | OutputDebugString(TEXT("GAPI_RealizePalette NOT IMPLEMENTED !\r\n")); |
1224 | } |
1225 | |
1226 | static void GAPI_PaletteChanged(_THIS, HWND window) |
1227 | { |
1228 | OutputDebugString(TEXT("GAPI_PaletteChanged NOT IMPLEMENTED !\r\n")); |
1229 | } |
1230 | |
1231 | static 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 | |
1283 | int GAPI_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors) |
1284 | { |
1285 | GAPI_CreatePalette(ncolors, colors); |
1286 | return 1; |
1287 | } |