/
SDL_ph_image.c
472 lines (394 loc) · 11.6 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
38
#include "SDL_ph_image_c.h"
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
/* Mask values for SDL_ReallocFormat() */
struct ColourMasks
{
Uint32 red;
Uint32 green;
Uint32 blue;
Uint32 alpha;
Uint32 bpp;
};
static const struct ColourMasks *ph_GetColourMasks( int format )
{
/* The alpha mask doesn't appear to be needed */
static const struct ColourMasks phColorMasks[5] = {
/* 8 bit */ {0, 0, 0, 0, 8},
/* 15 bit ARGB */ {0x7C00, 0x03E0, 0x001F, 0x8000, 16},
/* 16 bit RGB */ {0xF800, 0x07E0, 0x001F, 0x0000, 16},
/* 24 bit RGB */ {0xFF0000, 0x00FF00, 0x0000FF, 0x000000, 24},
/* 32 bit ARGB */ {0x00FF0000, 0x0000FF00, 0x000000FF, 0xFF000000, 32},
};
switch( format )
{
case Pg_IMAGE_PALETTE_BYTE:
return &phColorMasks[0];
break;
case Pg_IMAGE_DIRECT_1555:
case Pg_IMAGE_DIRECT_555:
return &phColorMasks[1];
break;
case Pg_IMAGE_DIRECT_565:
return &phColorMasks[2];
break;
case Pg_IMAGE_DIRECT_888:
return &phColorMasks[3];
break;
case Pg_IMAGE_DIRECT_8888:
return &phColorMasks[4];
break;
}
return NULL;
}
81
82
83
int ph_SetupImage(_THIS, SDL_Surface *screen)
{
84
PgColor_t* palette=NULL;
85
const struct ColourMasks* mask;
86
87
88
89
int type=0;
int bpp;
bpp=screen->format->BitsPerPixel;
90
91
/* Determine image type */
92
switch(bpp)
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
{
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:{
115
fprintf(stderr,"ph_SetupImage(): unsupported bpp=%d !\n", bpp);
116
117
118
119
return -1;
}
break;
}
120
121
/* palette emulation code */
122
if ((bpp==8) && (desktoppal==SDLPH_PAL_EMULATE))
123
124
125
126
127
128
129
130
{
/* creating image palette */
palette=malloc(_Pg_MAX_PALETTE*sizeof(PgColor_t));
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)
{
131
fprintf(stderr,"ph_SetupImage(): PhCreateImage failed for bpp=8 !\n");
132
133
134
135
return -1;
}
}
else
136
{
137
138
139
/* using shared memory for speed (set last param to 1) */
if ((SDL_Image = PhCreateImage(NULL, screen->w, screen->h, type, NULL, 0, 1)) == NULL)
{
140
fprintf(stderr,"ph_SetupImage: PhCreateImage failed !\n");
141
142
return -1;
}
143
}
144
145
screen->pixels = SDL_Image->image;
146
screen->pitch = SDL_Image->bpl; /* Recalculated pitch, created by PhCreateImage */
147
148
149
150
151
152
153
mask = ph_GetColourMasks(type);
if (mask != NULL)
{
SDL_ReallocFormat(screen, mask->bpp, mask->red, mask->green, mask->blue, 0);
}
154
this->UpdateRects = ph_NormalUpdate;
155
156
return 0;
157
158
}
159
int ph_SetupOCImage(_THIS, SDL_Surface *screen)
160
{
161
const struct ColourMasks *mask;
162
int type = 0;
163
int bpp;
164
165
166
screen->flags &= ~SDL_DOUBLEBUF;
OCImage.flags = screen->flags;
167
168
bpp=screen->format->BitsPerPixel;
169
170
/* Determine image type */
171
switch(bpp)
172
173
174
175
176
177
178
{
case 8: {
type = Pg_IMAGE_PALETTE_BYTE;
}
break;
case 15:{
type = Pg_IMAGE_DIRECT_555;
179
180
}
break;
181
182
183
184
185
186
187
188
189
190
191
192
193
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:{
194
fprintf(stderr,"ph_SetupOCImage(): unsupported bpp=%d !\n", bpp);
195
196
197
198
return -1;
}
break;
}
199
200
201
/* Currently only offscreen contexts with the same bit depth as the
* display can be created. */
202
203
204
205
206
207
208
209
OCImage.offscreen_context = PdCreateOffscreenContext(0, screen->w, screen->h, Pg_OSC_MEM_PAGE_ALIGN);
if (OCImage.offscreen_context == NULL)
{
fprintf(stderr, "ph_SetupOCImage(): PdCreateOffscreenContext failed !\n");
return -1;
}
210
211
212
213
214
/* If the bit depth of the context is different than was requested,
* these values need to be updated accordingly. SDL will
* allocate a shadow surface if it needs to. */
mask = ph_GetColourMasks(OCImage.offscreen_context->format);
if (mask != NULL)
215
{
216
217
218
219
220
221
SDL_ReallocFormat(screen, mask->bpp, mask->red, mask->green, mask->blue, 0);
if (mask->bpp > 8)
{
screen->flags &= ~SDL_HWPALETTE;
}
222
223
}
224
225
screen->pitch = OCImage.offscreen_context->pitch; /* Recalculated pitch */
226
227
228
229
230
231
232
233
OCImage.dc_ptr.ptr8 = (unsigned char *) PdGetOffscreenContextPtr(OCImage.offscreen_context);
if (OCImage.dc_ptr.ptr8 == NULL)
{
fprintf(stderr, "ph_SetupOCImage(): PdGetOffscreenContextPtr failed !\n");
return -1;
}
234
OCImage.FrameData0 = OCImage.dc_ptr.ptr8;
235
236
237
238
239
OCImage.CurrentFrameData = OCImage.FrameData0;
OCImage.current = 0;
PhDCSetCurrent(OCImage.offscreen_context);
240
screen->pixels = OCImage.CurrentFrameData;
241
242
243
244
this->UpdateRects = ph_OCUpdate;
return 0;
245
246
}
247
248
249
250
251
252
int ph_SetupOpenGLImage(_THIS, SDL_Surface* screen)
{
this->UpdateRects = ph_OpenGLUpdate;
return 0;
}
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
int ph_SetupFullScreenImage(_THIS, SDL_Surface* screen)
{
const struct ColourMasks *mask;
screen->flags &= ~SDL_DOUBLEBUF;
OCImage.flags = screen->flags;
OCImage.offscreen_context = PdCreateOffscreenContext(0, 0, 0, Pg_OSC_MAIN_DISPLAY);
if (OCImage.offscreen_context == NULL)
{
fprintf(stderr, "ph_SetupFullScreenImage(): PdCreateOffscreenContext failed !\n");
return -1;
}
/* If the bit depth of the context is different than was requested,
* these values need to be updated accordingly. SDL will
* allocate a shadow surface if it needs to. */
mask = ph_GetColourMasks(OCImage.offscreen_context->format);
if (mask != NULL)
{
SDL_ReallocFormat(screen, mask->bpp, mask->red, mask->green, mask->blue, 0);
if (mask->bpp > 8)
{
screen->flags &= ~SDL_HWPALETTE;
}
}
screen->pitch = OCImage.offscreen_context->pitch; /* Recalculated pitch */
OCImage.dc_ptr.ptr8 = (unsigned char *)PdGetOffscreenContextPtr(OCImage.offscreen_context);
if (OCImage.dc_ptr.ptr8 == NULL)
{
fprintf(stderr, "ph_SetupOCImage(): PdGetOffscreenContextPtr failed !\n");
return -1;
}
/* wait for hw */
PgWaitHWIdle();
OCImage.FrameData0 = OCImage.dc_ptr.ptr8;
OCImage.CurrentFrameData = OCImage.FrameData0;
OCImage.current = 0;
PhDCSetCurrent(OCImage.offscreen_context);
screen->pixels = OCImage.CurrentFrameData;
this->UpdateRects = ph_OCUpdate;
return 0;
}
308
309
void ph_DestroyImage(_THIS, SDL_Surface *screen)
{
310
311
312
313
314
315
316
if (OCImage.offscreen_context != NULL)
{
PhDCRelease(OCImage.offscreen_context);
OCImage.offscreen_context = NULL;
OCImage.FrameData0 = NULL;
OCImage.FrameData1 = NULL;
}
317
318
319
if (SDL_Image)
{
320
321
322
323
324
/* if palette allocated, free it */
if (SDL_Image->palette)
{
free(SDL_Image->palette);
}
325
326
327
PgShmemDestroy(SDL_Image->image);
free(SDL_Image);
}
328
329
330
331
/* Must be zeroed everytime */
SDL_Image = NULL;
332
333
334
335
if (screen)
{
screen->pixels = NULL;
}
336
337
}
338
int ph_SetupUpdateFunction(_THIS, SDL_Surface *screen, Uint32 flags)
339
340
341
{
ph_DestroyImage(this, screen);
342
343
344
345
346
if ((flags & SDL_FULLSCREEN)==SDL_FULLSCREEN)
{
return ph_SetupFullScreenImage(this, screen);
}
if ((flags & SDL_HWSURFACE)==SDL_HWSURFACE)
347
{
348
return ph_SetupOCImage(this, screen);
349
}
350
if ((flags & SDL_OPENGL)==SDL_OPENGL)
351
{
352
return ph_SetupOpenGLImage(this, screen);
353
}
354
355
return ph_SetupImage(this, screen);
356
357
358
}
int ph_AllocHWSurface(_THIS, SDL_Surface *surface)
{
359
return(-1);
360
361
362
363
}
void ph_FreeHWSurface(_THIS, SDL_Surface *surface)
{
364
return;
365
366
367
368
}
int ph_FlipHWSurface(_THIS, SDL_Surface *surface)
{
369
return(0);
370
371
372
373
}
int ph_LockHWSurface(_THIS, SDL_Surface *surface)
{
374
return(0);
375
376
377
378
}
void ph_UnlockHWSurface(_THIS, SDL_Surface *surface)
{
379
return;
380
381
}
382
383
384
385
386
387
388
void ph_OpenGLUpdate(_THIS, int numrects, SDL_Rect* rects)
{
this->GL_SwapBuffers(this);
return;
}
389
390
void ph_NormalUpdate(_THIS, int numrects, SDL_Rect *rects)
{
391
392
393
394
395
PhPoint_t ph_pos;
PhRect_t ph_rect;
int i;
for (i=0; i<numrects; ++i)
396
397
398
399
{
if (rects[i].w==0) /* Clipped? */
{
continue;
400
401
}
402
403
404
405
406
407
408
409
410
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)
{
411
fprintf(stderr,"ph_NormalUpdate(): PgDrawPhImageRectmx failed !\n");
412
413
}
}
414
415
if (PgFlush() < 0)
416
{
417
fprintf(stderr,"ph_NormalUpdate(): PgFlush failed.\n");
418
419
}
}
420
421
422
void ph_OCUpdate(_THIS, int numrects, SDL_Rect *rects)
{
423
424
int i;
425
PhPoint_t zero = {0};
426
427
PhArea_t src_rect;
PhArea_t dest_rect;
428
429
PgSetRegion(PtWidgetRid(window));
430
PgSetClipping(0, NULL);
431
432
433
434
435
436
437
PgWaitHWIdle();
for (i=0; i<numrects; ++i)
{
if (rects[i].w == 0) /* Clipped? */
{
continue;
438
439
}
440
441
442
443
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;
444
445
446
447
448
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;
449
450
451
452
zero.x = 0;
zero.y = 0;
PgSetTranslation(&zero, 0);
453
PgSetRegion(PtWidgetRid(window));
454
455
PgSetClipping(0, NULL);
PgContextBlitArea(OCImage.offscreen_context, &src_rect, NULL, &dest_rect);
456
}
457
458
if (PgFlush() < 0)
459
{
460
fprintf(stderr,"ph_OCUpdate(): PgFlush failed.\n");
461
462
}
463
464
465
466
467
468
469
470
471
/* later used to toggling double buffer */
if (OCImage.current == 0)
{
OCImage.CurrentFrameData = OCImage.FrameData0;
}
else
{
OCImage.CurrentFrameData = OCImage.FrameData1;
}
472
}