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