/
SDL_ph_image.c
498 lines (422 loc) · 12.7 KB
1
2
/*
SDL - Simple DirectMedia Layer
3
Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002 Sam Lantinga
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with this library; if not, write to the Free
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Sam Lantinga
20
slouken@libsdl.org
21
22
23
24
25
26
27
28
29
30
31
*/
#ifdef SAVE_RCSID
static char rcsid =
"@(#) $Id$";
#endif
#include <stdlib.h>
#include <Ph.h>
#include <photon/Pg.h>
32
#include "SDL.h"
33
34
#include "SDL_error.h"
#include "SDL_endian.h"
35
36
#include "SDL_video.h"
#include "SDL_pixels_c.h"
37
#include "SDL_ph_image_c.h"
38
#include "SDL_ph_modes_c.h"
39
40
41
int ph_SetupImage(_THIS, SDL_Surface *screen)
{
42
PgColor_t* palette=NULL;
43
44
45
46
int type=0;
int bpp;
bpp=screen->format->BitsPerPixel;
47
48
/* Determine image type */
49
switch(bpp)
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
{
case 8:{
type = Pg_IMAGE_PALETTE_BYTE;
}
break;
case 15:{
type = Pg_IMAGE_DIRECT_555;
}
break;
case 16:{
type = Pg_IMAGE_DIRECT_565;
}
break;
case 24:{
type = Pg_IMAGE_DIRECT_888;
}
break;
case 32:{
type = Pg_IMAGE_DIRECT_8888;
}
break;
default:{
72
SDL_SetError("ph_SetupImage(): unsupported bpp=%d !\n", bpp);
73
74
75
76
return -1;
}
break;
}
77
78
/* palette emulation code */
79
if ((bpp==8) && (desktoppal==SDLPH_PAL_EMULATE))
80
81
82
{
/* creating image palette */
palette=malloc(_Pg_MAX_PALETTE*sizeof(PgColor_t));
83
84
85
86
87
if (palette==NULL)
{
SDL_SetError("ph_SetupImage(): can't allocate memory for palette !\n");
return -1;
}
88
89
90
91
92
PgGetPalette(palette);
/* using shared memory for speed (set last param to 1) */
if ((SDL_Image = PhCreateImage(NULL, screen->w, screen->h, type, palette, _Pg_MAX_PALETTE, 1)) == NULL)
{
93
94
SDL_SetError("ph_SetupImage(): PhCreateImage() failed for bpp=8 !\n");
free(palette);
95
96
97
98
return -1;
}
}
else
99
{
100
101
102
/* using shared memory for speed (set last param to 1) */
if ((SDL_Image = PhCreateImage(NULL, screen->w, screen->h, type, NULL, 0, 1)) == NULL)
{
103
SDL_SetError("ph_SetupImage(): PhCreateImage() failed for bpp=%d !\n", bpp);
104
105
return -1;
}
106
}
107
108
screen->pixels = SDL_Image->image;
109
screen->pitch = SDL_Image->bpl;
110
111
this->UpdateRects = ph_NormalUpdate;
112
113
return 0;
114
115
}
116
int ph_SetupOCImage(_THIS, SDL_Surface *screen)
117
{
118
int type = 0;
119
int bpp;
120
121
OCImage.flags = screen->flags;
122
123
bpp=screen->format->BitsPerPixel;
124
125
/* Determine image type */
126
switch(bpp)
127
128
129
130
131
132
133
{
case 8: {
type = Pg_IMAGE_PALETTE_BYTE;
}
break;
case 15:{
type = Pg_IMAGE_DIRECT_555;
134
135
}
break;
136
137
138
139
140
141
142
143
144
145
146
147
148
case 16:{
type = Pg_IMAGE_DIRECT_565;
}
break;
case 24:{
type = Pg_IMAGE_DIRECT_888;
}
break;
case 32:{
type = Pg_IMAGE_DIRECT_8888;
}
break;
default:{
149
SDL_SetError("ph_SetupOCImage(): unsupported bpp=%d !\n", bpp);
150
151
152
153
return -1;
}
break;
}
154
155
156
/* Currently only offscreen contexts with the same bit depth as the
* display can be created. */
157
158
159
160
OCImage.offscreen_context = PdCreateOffscreenContext(0, screen->w, screen->h, Pg_OSC_MEM_PAGE_ALIGN);
if (OCImage.offscreen_context == NULL)
{
161
SDL_SetError("ph_SetupOCImage(): PdCreateOffscreenContext() function failed !\n");
162
163
164
return -1;
}
165
screen->pitch = OCImage.offscreen_context->pitch;
166
167
OCImage.dc_ptr = (unsigned char *) PdGetOffscreenContextPtr(OCImage.offscreen_context);
168
169
if (OCImage.dc_ptr == NULL)
170
{
171
172
SDL_SetError("ph_SetupOCImage(): PdGetOffscreenContextPtr function failed !\n");
PhDCRelease(OCImage.offscreen_context);
173
174
175
return -1;
}
176
OCImage.FrameData0 = OCImage.dc_ptr;
177
178
179
180
181
OCImage.CurrentFrameData = OCImage.FrameData0;
OCImage.current = 0;
PhDCSetCurrent(OCImage.offscreen_context);
182
screen->pixels = OCImage.CurrentFrameData;
183
184
185
186
this->UpdateRects = ph_OCUpdate;
return 0;
187
188
}
189
190
191
192
193
194
int ph_SetupOpenGLImage(_THIS, SDL_Surface* screen)
{
this->UpdateRects = ph_OpenGLUpdate;
return 0;
}
195
196
197
198
199
int ph_SetupFullScreenImage(_THIS, SDL_Surface* screen)
{
OCImage.flags = screen->flags;
200
201
/* Begin direct mode */
if (!ph_EnterFullScreen(this, screen))
202
203
204
205
{
return -1;
}
206
207
/* store palette for fullscreen */
if ((screen->format->BitsPerPixel==8) && (desktopbpp!=8))
208
{
209
210
211
PgGetPalette(savedpal);
PgGetPalette(syspalph);
}
212
213
214
215
216
217
218
219
220
221
222
223
OCImage.offscreen_context = PdCreateOffscreenContext(0, 0, 0, Pg_OSC_MAIN_DISPLAY);
if (OCImage.offscreen_context == NULL)
{
SDL_SetError("ph_SetupFullScreenImage(): PdCreateOffscreenContext() function failed !\n");
return -1;
}
if ((screen->flags & SDL_DOUBLEBUF) == SDL_DOUBLEBUF)
{
OCImage.offscreen_backcontext = PdDupOffscreenContext(OCImage.offscreen_context, Pg_OSC_CRTC_SAFE);
if (OCImage.offscreen_backcontext == NULL)
224
{
225
226
SDL_SetError("ph_SetupFullScreenImage(): PdCreateOffscreenContext(back) function failed !\n");
return -1;
227
228
229
}
}
230
231
OCImage.FrameData0 = (unsigned char *)PdGetOffscreenContextPtr(OCImage.offscreen_context);
if (OCImage.FrameData0 == NULL)
232
{
233
234
SDL_SetError("ph_SetupFullScreenImage(): PdGetOffscreenContextPtr() function failed !\n");
ph_DestroyImage(this, screen);
235
236
237
return -1;
}
238
239
240
241
242
243
244
245
246
247
if ((screen->flags & SDL_DOUBLEBUF) == SDL_DOUBLEBUF)
{
OCImage.FrameData1 = (unsigned char *)PdGetOffscreenContextPtr(OCImage.offscreen_backcontext);
if (OCImage.FrameData1 == NULL)
{
SDL_SetError("ph_SetupFullScreenImage(back): PdGetOffscreenContextPtr() function failed !\n");
ph_DestroyImage(this, screen);
return -1;
}
}
248
249
250
/* wait for the hardware */
PgWaitHWIdle();
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
if ((screen->flags & SDL_DOUBLEBUF) == SDL_DOUBLEBUF)
{
OCImage.current = 1;
PhDCSetCurrent(OCImage.offscreen_backcontext);
screen->pitch = OCImage.offscreen_backcontext->pitch;
screen->pixels = OCImage.FrameData1;
PgSwapDisplay(OCImage.offscreen_context, 0);
}
else
{
OCImage.current = 0;
PhDCSetCurrent(OCImage.offscreen_context);
screen->pitch = OCImage.offscreen_context->pitch;
screen->pixels = OCImage.FrameData0;
}
267
268
this->UpdateRects = ph_OCDCUpdate;
269
270
271
272
return 0;
}
273
274
void ph_DestroyImage(_THIS, SDL_Surface *screen)
{
275
276
277
278
279
280
281
282
283
284
285
286
if (currently_fullscreen)
{
/* if we right now in 8bpp fullscreen we must release palette */
if ((screen->format->BitsPerPixel==8) && (desktopbpp!=8))
{
PgSetPalette(syspalph, 0, -1, 0, 0, 0);
PgSetPalette(savedpal, 0, 0, _Pg_MAX_PALETTE, Pg_PALSET_GLOBAL | Pg_PALSET_FORCE_EXPOSE, 0);
PgFlush();
}
ph_LeaveFullScreen(this);
}
287
288
289
290
291
if (OCImage.offscreen_context != NULL)
{
PhDCRelease(OCImage.offscreen_context);
OCImage.offscreen_context = NULL;
OCImage.FrameData0 = NULL;
292
293
294
295
296
}
if (OCImage.offscreen_backcontext != NULL)
{
PhDCRelease(OCImage.offscreen_backcontext);
OCImage.offscreen_backcontext = NULL;
297
298
OCImage.FrameData1 = NULL;
}
299
OCImage.CurrentFrameData = NULL;
300
301
302
if (SDL_Image)
{
303
304
305
306
307
/* if palette allocated, free it */
if (SDL_Image->palette)
{
free(SDL_Image->palette);
}
308
309
310
PgShmemDestroy(SDL_Image->image);
free(SDL_Image);
}
311
312
313
314
/* Must be zeroed everytime */
SDL_Image = NULL;
315
316
317
318
if (screen)
{
screen->pixels = NULL;
}
319
320
}
321
int ph_SetupUpdateFunction(_THIS, SDL_Surface *screen, Uint32 flags)
322
323
324
{
ph_DestroyImage(this, screen);
325
326
327
328
329
if ((flags & SDL_FULLSCREEN)==SDL_FULLSCREEN)
{
return ph_SetupFullScreenImage(this, screen);
}
if ((flags & SDL_HWSURFACE)==SDL_HWSURFACE)
330
{
331
return ph_SetupOCImage(this, screen);
332
}
333
if ((flags & SDL_OPENGL)==SDL_OPENGL)
334
{
335
return ph_SetupOpenGLImage(this, screen);
336
}
337
338
return ph_SetupImage(this, screen);
339
}
340
341
342
int ph_AllocHWSurface(_THIS, SDL_Surface *surface)
{
343
return(-1);
344
345
346
347
}
void ph_FreeHWSurface(_THIS, SDL_Surface *surface)
{
348
return;
349
350
}
351
int ph_FlipHWSurface(_THIS, SDL_Surface *screen)
352
{
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
PhArea_t area;
area.pos.x=0;
area.pos.y=0;
area.size.w=screen->w;
area.size.h=screen->h;
if ((screen->flags & SDL_FULLSCREEN) == SDL_FULLSCREEN)
{
if (OCImage.current==0)
{
PgSwapDisplay(OCImage.offscreen_context, 0);
OCImage.current=1;
screen->pitch = OCImage.offscreen_backcontext->pitch;
screen->pixels = OCImage.FrameData1;
// memcpy(OCImage.FrameData1, OCImage.FrameData0, OCImage.offscreen_context->shared_size);
PgContextBlitArea(OCImage.offscreen_context, &area, OCImage.offscreen_backcontext, &area);
PhDCSetCurrent(OCImage.offscreen_backcontext);
PgFlush();
}
else
{
PgSwapDisplay(OCImage.offscreen_backcontext, 0);
OCImage.current=0;
screen->pitch = OCImage.offscreen_context->pitch;
screen->pixels = OCImage.FrameData0;
// memcpy(OCImage.FrameData0, OCImage.FrameData1, OCImage.offscreen_context->shared_size);
PgContextBlitArea(OCImage.offscreen_backcontext, &area, OCImage.offscreen_context, &area);
PhDCSetCurrent(OCImage.offscreen_context);
PgFlush();
}
}
return 0;
386
387
388
389
}
int ph_LockHWSurface(_THIS, SDL_Surface *surface)
{
390
return(0);
391
392
393
394
}
void ph_UnlockHWSurface(_THIS, SDL_Surface *surface)
{
395
return;
396
397
}
398
399
400
401
402
403
404
void ph_OpenGLUpdate(_THIS, int numrects, SDL_Rect* rects)
{
this->GL_SwapBuffers(this);
return;
}
405
406
void ph_NormalUpdate(_THIS, int numrects, SDL_Rect *rects)
{
407
408
409
410
411
PhPoint_t ph_pos;
PhRect_t ph_rect;
int i;
for (i=0; i<numrects; ++i)
412
413
414
415
{
if (rects[i].w==0) /* Clipped? */
{
continue;
416
417
}
418
419
420
421
422
if (rects[i].h==0) /* Clipped? */
{
continue;
}
423
424
425
426
427
428
429
430
431
ph_pos.x = rects[i].x;
ph_pos.y = rects[i].y;
ph_rect.ul.x = rects[i].x;
ph_rect.ul.y = rects[i].y;
ph_rect.lr.x = rects[i].x + rects[i].w;
ph_rect.lr.y = rects[i].y + rects[i].h;
if (PgDrawPhImageRectmx(&ph_pos, SDL_Image, &ph_rect, 0) < 0)
{
432
SDL_SetError("ph_NormalUpdate(): PgDrawPhImageRectmx failed !\n");
433
434
}
}
435
436
if (PgFlush() < 0)
437
{
438
SDL_SetError("ph_NormalUpdate(): PgFlush failed.\n");
439
440
}
}
441
442
443
void ph_OCUpdate(_THIS, int numrects, SDL_Rect *rects)
{
444
445
int i;
446
PhPoint_t zero = {0};
447
448
PhArea_t src_rect;
PhArea_t dest_rect;
449
450
PgSetRegion(PtWidgetRid(window));
451
PgSetClipping(0, NULL);
452
453
454
455
456
457
458
PgWaitHWIdle();
for (i=0; i<numrects; ++i)
{
if (rects[i].w == 0) /* Clipped? */
{
continue;
459
460
}
461
462
463
464
465
if (rects[i].h == 0) /* Clipped? */
{
continue;
}
466
467
468
469
src_rect.pos.x=rects[i].x;
src_rect.pos.y=rects[i].y;
dest_rect.pos.x=rects[i].x;
dest_rect.pos.y=rects[i].y;
470
471
472
473
474
src_rect.size.w=rects[i].w;
src_rect.size.h=rects[i].h;
dest_rect.size.w=rects[i].w;
dest_rect.size.h=rects[i].h;
475
476
477
478
zero.x = 0;
zero.y = 0;
PgSetTranslation(&zero, 0);
479
PgSetRegion(PtWidgetRid(window));
480
481
PgSetClipping(0, NULL);
PgContextBlitArea(OCImage.offscreen_context, &src_rect, NULL, &dest_rect);
482
}
483
484
if (PgFlush() < 0)
485
{
486
SDL_SetError("ph_OCUpdate(): PgFlush failed.\n");
487
}
488
489
490
491
492
493
494
}
void ph_OCDCUpdate(_THIS, int numrects, SDL_Rect *rects)
{
PgWaitHWIdle();
if (PgFlush() < 0)
495
{
496
SDL_SetError("ph_OCDCUpdate(): PgFlush failed.\n");
497
}
498
}