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 | #include <Ph.h> |
25 | #include <photon/Pg.h> |
26 | |
27 | #include "SDL_endian.h" |
28 | #include "SDL_video.h" |
29 | #include "../SDL_pixels_c.h" |
30 | #include "SDL_ph_video.h" |
31 | #include "SDL_ph_image_c.h" |
32 | #include "SDL_ph_modes_c.h" |
33 | #include "SDL_ph_gl.h" |
34 | |
35 | int ph_SetupImage(_THIS, SDL_Surface *screen) |
36 | { |
37 | PgColor_t* palette=NULL; |
38 | int type=0; |
39 | int bpp; |
40 | |
41 | bpp=screen->format->BitsPerPixel; |
42 | |
43 | /* Determine image type */ |
44 | switch(bpp) |
45 | { |
46 | case 8:{ |
47 | type = Pg_IMAGE_PALETTE_BYTE; |
48 | } |
49 | break; |
50 | case 15:{ |
51 | type = Pg_IMAGE_DIRECT_555; |
52 | } |
53 | break; |
54 | case 16:{ |
55 | type = Pg_IMAGE_DIRECT_565; |
56 | } |
57 | break; |
58 | case 24:{ |
59 | type = Pg_IMAGE_DIRECT_888; |
60 | } |
61 | break; |
62 | case 32:{ |
63 | type = Pg_IMAGE_DIRECT_8888; |
64 | } |
65 | break; |
66 | default:{ |
67 | SDL_SetError("ph_SetupImage(): unsupported bpp=%d !\n", bpp); |
68 | return -1; |
69 | } |
70 | break; |
71 | } |
72 | |
73 | /* palette emulation code */ |
74 | if ((bpp==8) && (desktoppal==SDLPH_PAL_EMULATE)) |
75 | { |
76 | /* creating image palette */ |
77 | palette=SDL_malloc(_Pg_MAX_PALETTE*sizeof(PgColor_t)); |
78 | if (palette==NULL) |
79 | { |
80 | SDL_SetError("ph_SetupImage(): can't allocate memory for palette !\n"); |
81 | return -1; |
82 | } |
83 | PgGetPalette(palette); |
84 | |
85 | /* using shared memory for speed (set last param to 1) */ |
86 | if ((SDL_Image = PhCreateImage(NULL, screen->w, screen->h, type, palette, _Pg_MAX_PALETTE, 1)) == NULL) |
87 | { |
88 | SDL_SetError("ph_SetupImage(): PhCreateImage() failed for bpp=8 !\n"); |
89 | SDL_free(palette); |
90 | return -1; |
91 | } |
92 | } |
93 | else |
94 | { |
95 | /* using shared memory for speed (set last param to 1) */ |
96 | if ((SDL_Image = PhCreateImage(NULL, screen->w, screen->h, type, NULL, 0, 1)) == NULL) |
97 | { |
98 | SDL_SetError("ph_SetupImage(): PhCreateImage() failed for bpp=%d !\n", bpp); |
99 | return -1; |
100 | } |
101 | } |
102 | |
103 | screen->pixels = SDL_Image->image; |
104 | screen->pitch = SDL_Image->bpl; |
105 | |
106 | this->UpdateRects = ph_NormalUpdate; |
107 | |
108 | return 0; |
109 | } |
110 | |
111 | int ph_SetupOCImage(_THIS, SDL_Surface *screen) |
112 | { |
113 | int type = 0; |
114 | int bpp; |
115 | |
116 | OCImage.flags = screen->flags; |
117 | |
118 | bpp=screen->format->BitsPerPixel; |
119 | |
120 | /* Determine image type */ |
121 | switch(bpp) |
122 | { |
123 | case 8: { |
124 | type = Pg_IMAGE_PALETTE_BYTE; |
125 | } |
126 | break; |
127 | case 15:{ |
128 | type = Pg_IMAGE_DIRECT_555; |
129 | } |
130 | break; |
131 | case 16:{ |
132 | type = Pg_IMAGE_DIRECT_565; |
133 | } |
134 | break; |
135 | case 24:{ |
136 | type = Pg_IMAGE_DIRECT_888; |
137 | } |
138 | break; |
139 | case 32:{ |
140 | type = Pg_IMAGE_DIRECT_8888; |
141 | } |
142 | break; |
143 | default:{ |
144 | SDL_SetError("ph_SetupOCImage(): unsupported bpp=%d !\n", bpp); |
145 | return -1; |
146 | } |
147 | break; |
148 | } |
149 | |
150 | /* Currently offscreen contexts with the same bit depth as display bpp only can be created */ |
151 | OCImage.offscreen_context = PdCreateOffscreenContext(0, screen->w, screen->h, Pg_OSC_MEM_PAGE_ALIGN); |
152 | |
153 | if (OCImage.offscreen_context == NULL) |
154 | { |
155 | SDL_SetError("ph_SetupOCImage(): PdCreateOffscreenContext() function failed !\n"); |
156 | return -1; |
157 | } |
158 | |
159 | screen->pitch = OCImage.offscreen_context->pitch; |
160 | |
161 | OCImage.dc_ptr = (unsigned char *)PdGetOffscreenContextPtr(OCImage.offscreen_context); |
162 | |
163 | if (OCImage.dc_ptr == NULL) |
164 | { |
165 | SDL_SetError("ph_SetupOCImage(): PdGetOffscreenContextPtr function failed !\n"); |
166 | PhDCRelease(OCImage.offscreen_context); |
167 | return -1; |
168 | } |
169 | |
170 | OCImage.FrameData0 = OCImage.dc_ptr; |
171 | OCImage.CurrentFrameData = OCImage.FrameData0; |
172 | OCImage.current = 0; |
173 | |
174 | PhDCSetCurrent(OCImage.offscreen_context); |
175 | |
176 | screen->pixels = OCImage.CurrentFrameData; |
177 | |
178 | this->UpdateRects = ph_OCUpdate; |
179 | |
180 | return 0; |
181 | } |
182 | |
183 | int ph_SetupFullScreenImage(_THIS, SDL_Surface* screen) |
184 | { |
185 | OCImage.flags = screen->flags; |
186 | |
187 | /* Begin direct and fullscreen mode */ |
188 | if (!ph_EnterFullScreen(this, screen, PH_ENTER_DIRECTMODE)) |
189 | { |
190 | return -1; |
191 | } |
192 | |
193 | /* store palette for fullscreen */ |
194 | if ((screen->format->BitsPerPixel==8) && (desktopbpp!=8)) |
195 | { |
196 | PgGetPalette(savedpal); |
197 | PgGetPalette(syspalph); |
198 | } |
199 | |
200 | OCImage.offscreen_context = PdCreateOffscreenContext(0, 0, 0, Pg_OSC_MAIN_DISPLAY | Pg_OSC_MEM_PAGE_ALIGN | Pg_OSC_CRTC_SAFE); |
201 | if (OCImage.offscreen_context == NULL) |
202 | { |
203 | SDL_SetError("ph_SetupFullScreenImage(): PdCreateOffscreenContext() function failed !\n"); |
204 | return -1; |
205 | } |
206 | |
207 | if ((screen->flags & SDL_DOUBLEBUF) == SDL_DOUBLEBUF) |
208 | { |
209 | OCImage.offscreen_backcontext = PdDupOffscreenContext(OCImage.offscreen_context, Pg_OSC_MEM_PAGE_ALIGN | Pg_OSC_CRTC_SAFE); |
210 | if (OCImage.offscreen_backcontext == NULL) |
211 | { |
212 | SDL_SetError("ph_SetupFullScreenImage(): PdCreateOffscreenContext(back) function failed !\n"); |
213 | return -1; |
214 | } |
215 | } |
216 | |
217 | OCImage.FrameData0 = (unsigned char *)PdGetOffscreenContextPtr(OCImage.offscreen_context); |
218 | if (OCImage.FrameData0 == NULL) |
219 | { |
220 | SDL_SetError("ph_SetupFullScreenImage(): PdGetOffscreenContextPtr() function failed !\n"); |
221 | ph_DestroyImage(this, screen); |
222 | return -1; |
223 | } |
224 | |
225 | if ((screen->flags & SDL_DOUBLEBUF) == SDL_DOUBLEBUF) |
226 | { |
227 | OCImage.FrameData1 = (unsigned char *)PdGetOffscreenContextPtr(OCImage.offscreen_backcontext); |
228 | if (OCImage.FrameData1 == NULL) |
229 | { |
230 | SDL_SetError("ph_SetupFullScreenImage(back): PdGetOffscreenContextPtr() function failed !\n"); |
231 | ph_DestroyImage(this, screen); |
232 | return -1; |
233 | } |
234 | } |
235 | |
236 | /* wait for the hardware */ |
237 | PgFlush(); |
238 | PgWaitHWIdle(); |
239 | |
240 | if ((screen->flags & SDL_DOUBLEBUF) == SDL_DOUBLEBUF) |
241 | { |
242 | OCImage.current = 0; |
243 | PhDCSetCurrent(OCImage.offscreen_context); |
244 | screen->pitch = OCImage.offscreen_context->pitch; |
245 | screen->pixels = OCImage.FrameData0; |
246 | |
247 | /* emulate 640x400 videomode */ |
248 | if (videomode_emulatemode==1) |
249 | { |
250 | int i; |
251 | |
252 | for (i=0; i<40; i++) |
253 | { |
254 | SDL_memset(screen->pixels+screen->pitch*i, 0x00, screen->pitch); |
255 | } |
256 | for (i=440; i<480; i++) |
257 | { |
258 | SDL_memset(screen->pixels+screen->pitch*i, 0x00, screen->pitch); |
259 | } |
260 | screen->pixels+=screen->pitch*40; |
261 | } |
262 | PgSwapDisplay(OCImage.offscreen_backcontext, 0); |
263 | } |
264 | else |
265 | { |
266 | OCImage.current = 0; |
267 | PhDCSetCurrent(OCImage.offscreen_context); |
268 | screen->pitch = OCImage.offscreen_context->pitch; |
269 | screen->pixels = OCImage.FrameData0; |
270 | |
271 | /* emulate 640x400 videomode */ |
272 | if (videomode_emulatemode==1) |
273 | { |
274 | int i; |
275 | |
276 | for (i=0; i<40; i++) |
277 | { |
278 | SDL_memset(screen->pixels+screen->pitch*i, 0x00, screen->pitch); |
279 | } |
280 | for (i=440; i<480; i++) |
281 | { |
282 | SDL_memset(screen->pixels+screen->pitch*i, 0x00, screen->pitch); |
283 | } |
284 | screen->pixels+=screen->pitch*40; |
285 | } |
286 | } |
287 | |
288 | this->UpdateRects = ph_OCDCUpdate; |
289 | |
290 | /* wait for the hardware */ |
291 | PgFlush(); |
292 | PgWaitHWIdle(); |
293 | |
294 | return 0; |
295 | } |
296 | |
297 | #if SDL_VIDEO_OPENGL |
298 | |
299 | int ph_SetupOpenGLImage(_THIS, SDL_Surface* screen) |
300 | { |
301 | this->UpdateRects = ph_OpenGLUpdate; |
302 | screen->pixels=NULL; |
303 | screen->pitch=NULL; |
304 | |
305 | #if (_NTO_VERSION >= 630) |
306 | if ((screen->flags & SDL_FULLSCREEN) == SDL_FULLSCREEN) |
307 | { |
308 | if (!ph_EnterFullScreen(this, screen, PH_IGNORE_DIRECTMODE)) |
309 | { |
310 | screen->flags &= ~SDL_FULLSCREEN; |
311 | return -1; |
312 | } |
313 | } |
314 | #endif /* 6.3.0 */ |
315 | |
316 | if (ph_SetupOpenGLContext(this, screen->w, screen->h, screen->format->BitsPerPixel, screen->flags)!=0) |
317 | { |
318 | screen->flags &= ~SDL_OPENGL; |
319 | return -1; |
320 | } |
321 | |
322 | return 0; |
323 | } |
324 | |
325 | #endif /* SDL_VIDEO_OPENGL */ |
326 | |
327 | void ph_DestroyImage(_THIS, SDL_Surface* screen) |
328 | { |
329 | |
330 | #if SDL_VIDEO_OPENGL |
331 | if ((screen->flags & SDL_OPENGL)==SDL_OPENGL) |
332 | { |
333 | if (oglctx) |
334 | { |
335 | #if (_NTO_VERSION < 630) |
336 | PhDCSetCurrent(NULL); |
337 | PhDCRelease(oglctx); |
338 | #else |
339 | qnxgl_context_destroy(oglctx); |
340 | qnxgl_buffers_destroy(oglbuffers); |
341 | qnxgl_finish(); |
342 | #endif /* 6.3.0 */ |
343 | oglctx=NULL; |
344 | oglbuffers=NULL; |
345 | oglflags=0; |
346 | oglbpp=0; |
347 | } |
348 | |
349 | #if (_NTO_VERSION >= 630) |
350 | if (currently_fullscreen) |
351 | { |
352 | ph_LeaveFullScreen(this); |
353 | } |
354 | #endif /* 6.3.0 */ |
355 | |
356 | return; |
357 | } |
358 | #endif /* SDL_VIDEO_OPENGL */ |
359 | |
360 | if (currently_fullscreen) |
361 | { |
362 | /* if we right now in 8bpp fullscreen we must release palette */ |
363 | if ((screen->format->BitsPerPixel==8) && (desktopbpp!=8)) |
364 | { |
365 | PgSetPalette(syspalph, 0, -1, 0, 0, 0); |
366 | PgSetPalette(savedpal, 0, 0, _Pg_MAX_PALETTE, Pg_PALSET_GLOBAL | Pg_PALSET_FORCE_EXPOSE, 0); |
367 | PgFlush(); |
368 | } |
369 | ph_LeaveFullScreen(this); |
370 | } |
371 | |
372 | if (OCImage.offscreen_context != NULL) |
373 | { |
374 | PhDCRelease(OCImage.offscreen_context); |
375 | OCImage.offscreen_context = NULL; |
376 | OCImage.FrameData0 = NULL; |
377 | } |
378 | if (OCImage.offscreen_backcontext != NULL) |
379 | { |
380 | PhDCRelease(OCImage.offscreen_backcontext); |
381 | OCImage.offscreen_backcontext = NULL; |
382 | OCImage.FrameData1 = NULL; |
383 | } |
384 | OCImage.CurrentFrameData = NULL; |
385 | |
386 | if (SDL_Image) |
387 | { |
388 | /* if palette allocated, free it */ |
389 | if (SDL_Image->palette) |
390 | { |
391 | SDL_free(SDL_Image->palette); |
392 | } |
393 | PgShmemDestroy(SDL_Image->image); |
394 | SDL_free(SDL_Image); |
395 | } |
396 | |
397 | /* Must be zeroed everytime */ |
398 | SDL_Image = NULL; |
399 | |
400 | if (screen) |
401 | { |
402 | screen->pixels = NULL; |
403 | } |
404 | } |
405 | |
406 | int ph_UpdateHWInfo(_THIS) |
407 | { |
408 | PgVideoModeInfo_t vmode; |
409 | PgHWCaps_t hwcaps; |
410 | |
411 | /* Update video ram amount */ |
412 | if (PgGetGraphicsHWCaps(&hwcaps) < 0) |
413 | { |
414 | SDL_SetError("ph_UpdateHWInfo(): GetGraphicsHWCaps() function failed !\n"); |
415 | return -1; |
416 | } |
417 | this->info.video_mem=hwcaps.currently_available_video_ram/1024; |
418 | |
419 | /* obtain current mode capabilities */ |
420 | if (PgGetVideoModeInfo(hwcaps.current_video_mode, &vmode) < 0) |
421 | { |
422 | SDL_SetError("ph_UpdateHWInfo(): GetVideoModeInfo() function failed !\n"); |
423 | return -1; |
424 | } |
425 | |
426 | if ((vmode.mode_capabilities1 & PgVM_MODE_CAP1_OFFSCREEN) == PgVM_MODE_CAP1_OFFSCREEN) |
427 | { |
428 | /* this is a special test for drivers which tries to lie about offscreen capability */ |
429 | if (hwcaps.currently_available_video_ram!=0) |
430 | { |
431 | this->info.hw_available = 1; |
432 | } |
433 | else |
434 | { |
435 | this->info.hw_available = 0; |
436 | } |
437 | } |
438 | else |
439 | { |
440 | this->info.hw_available = 0; |
441 | } |
442 | |
443 | if ((vmode.mode_capabilities2 & PgVM_MODE_CAP2_RECTANGLE) == PgVM_MODE_CAP2_RECTANGLE) |
444 | { |
445 | this->info.blit_fill = 1; |
446 | } |
447 | else |
448 | { |
449 | this->info.blit_fill = 0; |
450 | } |
451 | |
452 | if ((vmode.mode_capabilities2 & PgVM_MODE_CAP2_BITBLT) == PgVM_MODE_CAP2_BITBLT) |
453 | { |
454 | this->info.blit_hw = 1; |
455 | } |
456 | else |
457 | { |
458 | this->info.blit_hw = 0; |
459 | } |
460 | |
461 | if ((vmode.mode_capabilities2 & PgVM_MODE_CAP2_ALPHA_BLEND) == PgVM_MODE_CAP2_ALPHA_BLEND) |
462 | { |
463 | this->info.blit_hw_A = 1; |
464 | } |
465 | else |
466 | { |
467 | this->info.blit_hw_A = 0; |
468 | } |
469 | |
470 | if ((vmode.mode_capabilities2 & PgVM_MODE_CAP2_CHROMA) == PgVM_MODE_CAP2_CHROMA) |
471 | { |
472 | this->info.blit_hw_CC = 1; |
473 | } |
474 | else |
475 | { |
476 | this->info.blit_hw_CC = 0; |
477 | } |
478 | |
479 | return 0; |
480 | } |
481 | |
482 | int ph_SetupUpdateFunction(_THIS, SDL_Surface* screen, Uint32 flags) |
483 | { |
484 | int setupresult=-1; |
485 | |
486 | ph_DestroyImage(this, screen); |
487 | |
488 | #if SDL_VIDEO_OPENGL |
489 | if ((flags & SDL_OPENGL)==SDL_OPENGL) |
490 | { |
491 | setupresult=ph_SetupOpenGLImage(this, screen); |
492 | } |
493 | else |
494 | { |
495 | #endif |
496 | if ((flags & SDL_FULLSCREEN)==SDL_FULLSCREEN) |
497 | { |
498 | setupresult=ph_SetupFullScreenImage(this, screen); |
499 | } |
500 | else |
501 | { |
502 | if ((flags & SDL_HWSURFACE)==SDL_HWSURFACE) |
503 | { |
504 | setupresult=ph_SetupOCImage(this, screen); |
505 | } |
506 | else |
507 | { |
508 | setupresult=ph_SetupImage(this, screen); |
509 | } |
510 | } |
511 | #if SDL_VIDEO_OPENGL |
512 | } |
513 | #endif |
514 | if (setupresult!=-1) |
515 | { |
516 | ph_UpdateHWInfo(this); |
517 | } |
518 | |
519 | return setupresult; |
520 | } |
521 | |
522 | int ph_AllocHWSurface(_THIS, SDL_Surface* surface) |
523 | { |
524 | PgHWCaps_t hwcaps; |
525 | |
526 | if (surface->hwdata!=NULL) |
527 | { |
528 | SDL_SetError("ph_AllocHWSurface(): hwdata already exists!\n"); |
529 | return -1; |
530 | } |
531 | surface->hwdata=SDL_malloc(sizeof(struct private_hwdata)); |
532 | SDL_memset(surface->hwdata, 0x00, sizeof(struct private_hwdata)); |
533 | surface->hwdata->offscreenctx=PdCreateOffscreenContext(0, surface->w, surface->h, Pg_OSC_MEM_PAGE_ALIGN); |
534 | if (surface->hwdata->offscreenctx == NULL) |
535 | { |
536 | SDL_SetError("ph_AllocHWSurface(): PdCreateOffscreenContext() function failed !\n"); |
537 | return -1; |
538 | } |
539 | surface->pixels=PdGetOffscreenContextPtr(surface->hwdata->offscreenctx); |
540 | if (surface->pixels==NULL) |
541 | { |
542 | PhDCRelease(surface->hwdata->offscreenctx); |
543 | SDL_SetError("ph_AllocHWSurface(): PdGetOffscreenContextPtr() function failed !\n"); |
544 | return -1; |
545 | } |
546 | surface->pitch=surface->hwdata->offscreenctx->pitch; |
547 | surface->flags|=SDL_HWSURFACE; |
548 | surface->flags|=SDL_PREALLOC; |
549 | |
550 | #if 0 /* FIXME */ |
551 | /* create simple offscreen lock */ |
552 | surface->hwdata->crlockparam.flags=0; |
553 | if (PdCreateOffscreenLock(surface->hwdata->offscreenctx, &surface->hwdata->crlockparam)!=EOK) |
554 | { |
555 | PhDCRelease(surface->hwdata->offscreenctx); |
556 | SDL_SetError("ph_AllocHWSurface(): Can't create offscreen lock !\n"); |
557 | return -1; |
558 | } |
559 | #endif /* 0 */ |
560 | |
561 | /* Update video ram amount */ |
562 | if (PgGetGraphicsHWCaps(&hwcaps) < 0) |
563 | { |
564 | PdDestroyOffscreenLock(surface->hwdata->offscreenctx); |
565 | PhDCRelease(surface->hwdata->offscreenctx); |
566 | SDL_SetError("ph_AllocHWSurface(): GetGraphicsHWCaps() function failed !\n"); |
567 | return -1; |
568 | } |
569 | this->info.video_mem=hwcaps.currently_available_video_ram/1024; |
570 | |
571 | return 0; |
572 | } |
573 | |
574 | void ph_FreeHWSurface(_THIS, SDL_Surface* surface) |
575 | { |
576 | PgHWCaps_t hwcaps; |
577 | |
578 | if (surface->hwdata==NULL) |
579 | { |
580 | SDL_SetError("ph_FreeHWSurface(): no hwdata!\n"); |
581 | return; |
582 | } |
583 | if (surface->hwdata->offscreenctx == NULL) |
584 | { |
585 | SDL_SetError("ph_FreeHWSurface(): no offscreen context to delete!\n"); |
586 | return; |
587 | } |
588 | |
589 | #if 0 /* FIXME */ |
590 | /* unlock the offscreen context if it has been locked before destroy it */ |
591 | if (PdIsOffscreenLocked(surface->hwdata->offscreenctx)==Pg_OSC_LOCKED) |
592 | { |
593 | PdUnlockOffscreen(surface->hwdata->offscreenctx); |
594 | } |
595 | |
596 | PdDestroyOffscreenLock(surface->hwdata->offscreenctx); |
597 | #endif /* 0 */ |
598 | |
599 | PhDCRelease(surface->hwdata->offscreenctx); |
600 | |
601 | SDL_free(surface->hwdata); |
602 | surface->hwdata=NULL; |
603 | |
604 | /* Update video ram amount */ |
605 | if (PgGetGraphicsHWCaps(&hwcaps) < 0) |
606 | { |
607 | SDL_SetError("ph_FreeHWSurface(): GetGraphicsHWCaps() function failed !\n"); |
608 | return; |
609 | } |
610 | this->info.video_mem=hwcaps.currently_available_video_ram/1024; |
611 | |
612 | return; |
613 | } |
614 | |
615 | int ph_CheckHWBlit(_THIS, SDL_Surface *src, SDL_Surface *dst) |
616 | { |
617 | if ((src->hwdata==NULL) && (src != this->screen)) |
618 | { |
619 | SDL_SetError("ph_CheckHWBlit(): Source surface haven't hardware specific data.\n"); |
620 | src->flags&=~SDL_HWACCEL; |
621 | return -1; |
622 | } |
623 | if ((src->flags & SDL_HWSURFACE) != SDL_HWSURFACE) |
624 | { |
625 | SDL_SetError("ph_CheckHWBlit(): Source surface isn't a hardware surface.\n"); |
626 | src->flags&=~SDL_HWACCEL; |
627 | return -1; |
628 | } |
629 | |
630 | if ((src->flags & SDL_SRCCOLORKEY) == SDL_SRCCOLORKEY) |
631 | { |
632 | if (this->info.blit_hw_CC!=1) |
633 | { |
634 | src->flags&=~SDL_HWACCEL; |
635 | src->map->hw_blit=NULL; |
636 | return -1; |
637 | } |
638 | } |
639 | |
640 | if ((src->flags & SDL_SRCALPHA) == SDL_SRCALPHA) |
641 | { |
642 | if (this->info.blit_hw_A!=1) |
643 | { |
644 | src->flags&=~SDL_HWACCEL; |
645 | src->map->hw_blit=NULL; |
646 | return -1; |
647 | } |
648 | } |
649 | |
650 | src->flags|=SDL_HWACCEL; |
651 | src->map->hw_blit = ph_HWAccelBlit; |
652 | |
653 | return 1; |
654 | } |
655 | |
656 | PgColor_t ph_ExpandColor(_THIS, SDL_Surface* surface, Uint32 color) |
657 | { |
658 | Uint32 truecolor; |
659 | |
660 | /* Photon API accepts true colors only during hw filling operations */ |
661 | switch(surface->format->BitsPerPixel) |
662 | { |
663 | case 8: |
664 | { |
665 | if ((surface->format->palette) && (color<=surface->format->palette->ncolors)) |
666 | { |
667 | truecolor=PgRGB(surface->format->palette->colors[color].r, |
668 | surface->format->palette->colors[color].g, |
669 | surface->format->palette->colors[color].b); |
670 | } |
671 | else |
672 | { |
673 | SDL_SetError("ph_ExpandColor(): Color out of range for the 8bpp mode !\n"); |
674 | return 0xFFFFFFFFUL; |
675 | } |
676 | } |
677 | break; |
678 | case 15: |
679 | { |
680 | truecolor = ((color & 0x00007C00UL) << 9) | /* R */ |
681 | ((color & 0x000003E0UL) << 6) | /* G */ |
682 | ((color & 0x0000001FUL) << 3) | /* B */ |
683 | ((color & 0x00007000UL) << 4) | /* R compensation */ |
684 | ((color & 0x00000380UL) << 1) | /* G compensation */ |
685 | ((color & 0x0000001CUL) >> 2); /* B compensation */ |
686 | } |
687 | break; |
688 | case 16: |
689 | { |
690 | truecolor = ((color & 0x0000F800UL) << 8) | /* R */ |
691 | ((color & 0x000007E0UL) << 5) | /* G */ |
692 | ((color & 0x0000001FUL) << 3) | /* B */ |
693 | ((color & 0x0000E000UL) << 3) | /* R compensation */ |
694 | ((color & 0x00000600UL) >> 1) | /* G compensation */ |
695 | ((color & 0x0000001CUL) >> 2); /* B compensation */ |
696 | |
697 | } |
698 | break; |
699 | case 24: |
700 | { |
701 | truecolor=color & 0x00FFFFFFUL; |
702 | } |
703 | break; |
704 | case 32: |
705 | { |
706 | truecolor=color; |
707 | } |
708 | break; |
709 | default: |
710 | { |
711 | SDL_SetError("ph_ExpandColor(): Unsupported depth for the hardware operations !\n"); |
712 | return 0xFFFFFFFFUL; |
713 | } |
714 | } |
715 | |
716 | return truecolor; |
717 | } |
718 | |
719 | int ph_FillHWRect(_THIS, SDL_Surface* surface, SDL_Rect* rect, Uint32 color) |
720 | { |
721 | PgColor_t oldcolor; |
722 | Uint32 truecolor; |
723 | int ydisp=0; |
724 | |
725 | if (this->info.blit_fill!=1) |
726 | { |
727 | return -1; |
728 | } |
729 | |
730 | truecolor=ph_ExpandColor(this, surface, color); |
731 | if (truecolor==0xFFFFFFFFUL) |
732 | { |
733 | return -1; |
734 | } |
735 | |
736 | oldcolor=PgSetFillColor(truecolor); |
737 | |
738 | /* 640x400 videomode emulation */ |
739 | if (videomode_emulatemode==1) |
740 | { |
741 | ydisp+=40; |
742 | } |
743 | |
744 | PgDrawIRect(rect->x, rect->y+ydisp, rect->w+rect->x-1, rect->h+rect->y+ydisp-1, Pg_DRAW_FILL); |
745 | PgSetFillColor(oldcolor); |
746 | PgFlush(); |
747 | PgWaitHWIdle(); |
748 | |
749 | return 0; |
750 | } |
751 | |
752 | int ph_FlipHWSurface(_THIS, SDL_Surface* screen) |
753 | { |
754 | PhArea_t farea; |
755 | |
756 | if ((screen->flags & SDL_FULLSCREEN) == SDL_FULLSCREEN) |
757 | { |
758 | /* flush all drawing ops before blitting */ |
759 | PgFlush(); |
760 | PgWaitHWIdle(); |
761 | |
762 | farea.pos.x=0; |
763 | farea.pos.y=0; |
764 | farea.size.w=screen->w; |
765 | farea.size.h=screen->h; |
766 | |
767 | /* emulate 640x400 videomode */ |
768 | if (videomode_emulatemode==1) |
769 | { |
770 | farea.pos.y+=40; |
771 | } |
772 | |
773 | PgContextBlitArea(OCImage.offscreen_context, &farea, OCImage.offscreen_backcontext, &farea); |
774 | |
775 | /* flush the blitting */ |
776 | PgFlush(); |
777 | PgWaitHWIdle(); |
778 | } |
779 | return 0; |
780 | } |
781 | |
782 | int ph_LockHWSurface(_THIS, SDL_Surface* surface) |
783 | { |
784 | |
785 | #if 0 /* FIXME */ |
786 | int lockresult; |
787 | |
788 | if (surface->hwdata == NULL) |
789 | { |
790 | return; |
791 | } |
792 | |
793 | surface->hwdata->lockparam.flags=0; |
794 | surface->hwdata->lockparam.time_out=NULL; |
795 | lockresult=PdLockOffscreen(surface->hwdata->offscreenctx, &surface->hwdata->lockparam); |
796 | |
797 | switch (lockresult) |
798 | { |
799 | case EOK: |
800 | break; |
801 | case Pg_OSC_LOCK_DEADLOCK: |
802 | SDL_SetError("ph_LockHWSurface(): Deadlock detected !\n"); |
803 | return -1; |
804 | case Pg_OSC_LOCK_INVALID: |
805 | SDL_SetError("ph_LockHWSurface(): Lock invalid !\n"); |
806 | return -1; |
807 | default: |
808 | SDL_SetError("ph_LockHWSurface(): Can't lock the surface !\n"); |
809 | return -1; |
810 | } |
811 | #endif /* 0 */ |
812 | |
813 | return 0; |
814 | } |
815 | |
816 | void ph_UnlockHWSurface(_THIS, SDL_Surface* surface) |
817 | { |
818 | |
819 | #if 0 /* FIXME */ |
820 | int unlockresult; |
821 | |
822 | if ((surface == NULL) || (surface->hwdata == NULL)) |
823 | { |
824 | return; |
825 | } |
826 | |
827 | if (PdIsOffscreenLocked(surface->hwdata->offscreenctx)==Pg_OSC_LOCKED) |
828 | { |
829 | unlockresult=PdUnlockOffscreen(surface->hwdata->offscreenctx); |
830 | } |
831 | #endif /* 0 */ |
832 | |
833 | return; |
834 | } |
835 | |
836 | int ph_HWAccelBlit(SDL_Surface* src, SDL_Rect* srcrect, SDL_Surface* dst, SDL_Rect* dstrect) |
837 | { |
838 | SDL_VideoDevice* this=current_video; |
839 | PhArea_t srcarea; |
840 | PhArea_t dstarea; |
841 | int ydisp=0; |
842 | |
843 | /* 640x400 videomode emulation */ |
844 | if (videomode_emulatemode==1) |
845 | { |
846 | ydisp+=40; |
847 | } |
848 | |
849 | srcarea.pos.x=srcrect->x; |
850 | srcarea.pos.y=srcrect->y; |
851 | srcarea.size.w=srcrect->w; |
852 | srcarea.size.h=srcrect->h; |
853 | |
854 | dstarea.pos.x=dstrect->x; |
855 | dstarea.pos.y=dstrect->y; |
856 | dstarea.size.w=dstrect->w; |
857 | dstarea.size.h=dstrect->h; |
858 | |
859 | if (((src == this->screen) || (src->hwdata!=NULL)) && ((dst == this->screen) || (dst->hwdata!=NULL))) |
860 | { |
861 | if ((src->flags & SDL_SRCCOLORKEY) == SDL_SRCCOLORKEY) |
862 | { |
863 | ph_SetHWColorKey(this, src, src->format->colorkey); |
864 | PgChromaOn(); |
865 | } |
866 | |
867 | if ((src->flags & SDL_SRCALPHA) == SDL_SRCALPHA) |
868 | { |
869 | ph_SetHWAlpha(this, src, src->format->alpha); |
870 | PgAlphaOn(); |
871 | } |
872 | |
873 | if (dst == this->screen) |
874 | { |
875 | if (src == this->screen) |
876 | { |
877 | /* blitting from main screen to main screen */ |
878 | dstarea.pos.y+=ydisp; |
879 | srcarea.pos.y+=ydisp; |
880 | PgContextBlitArea(OCImage.offscreen_context, &srcarea, OCImage.offscreen_context, &dstarea); |
881 | } |
882 | else |
883 | { |
884 | /* blitting from offscreen to main screen */ |
885 | dstarea.pos.y+=ydisp; |
886 | PgContextBlitArea(src->hwdata->offscreenctx, &srcarea, OCImage.offscreen_context, &dstarea); |
887 | } |
888 | } |
889 | else |
890 | { |
891 | if (src == this->screen) |
892 | { |
893 | /* blitting from main screen to offscreen */ |
894 | srcarea.pos.y+=ydisp; |
895 | PgContextBlitArea(OCImage.offscreen_context, &srcarea, dst->hwdata->offscreenctx, &dstarea); |
896 | } |
897 | else |
898 | { |
899 | /* blitting offscreen to offscreen */ |
900 | PgContextBlitArea(src->hwdata->offscreenctx, &srcarea, dst->hwdata->offscreenctx, &dstarea); |
901 | } |
902 | } |
903 | |
904 | if ((src->flags & SDL_SRCALPHA) == SDL_SRCALPHA) |
905 | { |
906 | PgAlphaOff(); |
907 | } |
908 | |
909 | if ((src->flags & SDL_SRCCOLORKEY) == SDL_SRCCOLORKEY) |
910 | { |
911 | PgChromaOff(); |
912 | } |
913 | } |
914 | else |
915 | { |
916 | SDL_SetError("ph_HWAccelBlit(): Source or target surface is not a hardware surface !\n"); |
917 | return -1; |
918 | } |
919 | |
920 | PgFlush(); |
921 | PgWaitHWIdle(); |
922 | |
923 | return 0; |
924 | } |
925 | |
926 | int ph_SetHWColorKey(_THIS, SDL_Surface *surface, Uint32 key) |
927 | { |
928 | if (this->info.blit_hw_CC!=1) |
929 | { |
930 | return -1; |
931 | } |
932 | |
933 | if (surface->hwdata!=NULL) |
934 | { |
935 | surface->hwdata->colorkey=ph_ExpandColor(this, surface, key); |
936 | if (surface->hwdata->colorkey==0xFFFFFFFFUL) |
937 | { |
938 | return -1; |
939 | } |
940 | } |
941 | PgSetChroma(surface->hwdata->colorkey, Pg_CHROMA_SRC_MATCH | Pg_CHROMA_NODRAW); |
942 | |
943 | return 0; |
944 | } |
945 | |
946 | int ph_SetHWAlpha(_THIS, SDL_Surface* surface, Uint8 alpha) |
947 | { |
948 | if (this->info.blit_hw_A!=1) |
949 | { |
950 | return -1; |
951 | } |
952 | |
953 | PgSetAlphaBlend(NULL, alpha); |
954 | |
955 | return 0; |
956 | } |
957 | |
958 | #if SDL_VIDEO_OPENGL |
959 | void ph_OpenGLUpdate(_THIS, int numrects, SDL_Rect* rects) |
960 | { |
961 | this->GL_SwapBuffers(this); |
962 | |
963 | return; |
964 | } |
965 | #endif /* SDL_VIDEO_OPENGL */ |
966 | |
967 | void ph_NormalUpdate(_THIS, int numrects, SDL_Rect *rects) |
968 | { |
969 | PhPoint_t ph_pos; |
970 | PhRect_t ph_rect; |
971 | int i; |
972 | |
973 | for (i=0; i<numrects; ++i) |
974 | { |
975 | if (rects[i].w==0) /* Clipped? dunno why but this occurs sometime. */ |
976 | { |
977 | continue; |
978 | } |
979 | |
980 | if (rects[i].h==0) /* Clipped? dunno why but this occurs sometime. */ |
981 | { |
982 | continue; |
983 | } |
984 | |
985 | ph_pos.x = rects[i].x; |
986 | ph_pos.y = rects[i].y; |
987 | ph_rect.ul.x = rects[i].x; |
988 | ph_rect.ul.y = rects[i].y; |
989 | ph_rect.lr.x = rects[i].x + rects[i].w; |
990 | ph_rect.lr.y = rects[i].y + rects[i].h; |
991 | |
992 | if (PgDrawPhImageRectmx(&ph_pos, SDL_Image, &ph_rect, 0) < 0) |
993 | { |
994 | SDL_SetError("ph_NormalUpdate(): PgDrawPhImageRectmx failed!\n"); |
995 | return; |
996 | } |
997 | } |
998 | |
999 | if (PgFlush() < 0) |
1000 | { |
1001 | SDL_SetError("ph_NormalUpdate(): PgFlush() function failed!\n"); |
1002 | } |
1003 | } |
1004 | |
1005 | void ph_OCUpdate(_THIS, int numrects, SDL_Rect *rects) |
1006 | { |
1007 | int i; |
1008 | |
1009 | PhPoint_t zero = {0, 0}; |
1010 | PhArea_t src_rect; |
1011 | PhArea_t dest_rect; |
1012 | |
1013 | PgSetTranslation(&zero, 0); |
1014 | PgSetRegion(PtWidgetRid(window)); |
1015 | PgSetClipping(0, NULL); |
1016 | |
1017 | PgFlush(); |
1018 | PgWaitHWIdle(); |
1019 | |
1020 | for (i=0; i<numrects; ++i) |
1021 | { |
1022 | if (rects[i].w == 0) /* Clipped? */ |
1023 | { |
1024 | continue; |
1025 | } |
1026 | |
1027 | if (rects[i].h == 0) /* Clipped? */ |
1028 | { |
1029 | continue; |
1030 | } |
1031 | |
1032 | src_rect.pos.x=rects[i].x; |
1033 | src_rect.pos.y=rects[i].y; |
1034 | dest_rect.pos.x=rects[i].x; |
1035 | dest_rect.pos.y=rects[i].y; |
1036 | |
1037 | src_rect.size.w=rects[i].w; |
1038 | src_rect.size.h=rects[i].h; |
1039 | dest_rect.size.w=rects[i].w; |
1040 | dest_rect.size.h=rects[i].h; |
1041 | |
1042 | PgContextBlitArea(OCImage.offscreen_context, &src_rect, NULL, &dest_rect); |
1043 | } |
1044 | |
1045 | if (PgFlush() < 0) |
1046 | { |
1047 | SDL_SetError("ph_OCUpdate(): PgFlush failed.\n"); |
1048 | } |
1049 | } |
1050 | |
1051 | void ph_OCDCUpdate(_THIS, int numrects, SDL_Rect *rects) |
1052 | { |
1053 | PgWaitHWIdle(); |
1054 | |
1055 | if (PgFlush() < 0) |
1056 | { |
1057 | SDL_SetError("ph_OCDCUpdate(): PgFlush failed.\n"); |
1058 | } |
1059 | } |