Mercurial > sdl-ios-xcode
annotate src/video/macdsp/SDL_dspvideo.c @ 1032:c1c2efca4548
Date: Mon, 24 Jan 2005 21:37:56 +0800
From: Chris Taylor
Subject: Patch to put back dynamic OpenGL loading for MPW
I sent a patch a while ago that removes dynamic OpenGL loading for
Macintosh Programmer's Workshop. Dynamic loading DOES actually work
when an SDL program is built with MPW, it just has to be set up for it.
(Whoops!!) This is the ideal way to get OpenGL extensions to work,
which D2X uses quite a few of.
This patch puts dynamic loading back in SDL for Mac OS 9. It applies to
current CVS. I noticed that two members need to be set when
DrawSprocket is used.
author | Sam Lantinga <slouken@libsdl.org> |
---|---|
date | Tue, 25 Jan 2005 16:57:11 +0000 |
parents | b8d311d90021 |
children | 609c060fd2a2 |
rev | line source |
---|---|
0 | 1 /* |
2 SDL - Simple DirectMedia Layer | |
769
b8d311d90021
Updated copyright information for 2004 (Happy New Year!)
Sam Lantinga <slouken@libsdl.org>
parents:
297
diff
changeset
|
3 Copyright (C) 1997-2004 Sam Lantinga |
0 | 4 |
5 This library is free software; you can redistribute it and/or | |
6 modify it under the terms of the GNU Library General Public | |
7 License as published by the Free Software Foundation; either | |
8 version 2 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 Library General Public License for more details. | |
14 | |
15 You should have received a copy of the GNU Library General Public | |
16 License along with this library; if not, write to the Free | |
17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
18 | |
19 Sam Lantinga | |
252
e8157fcb3114
Updated the source with the correct e-mail address
Sam Lantinga <slouken@libsdl.org>
parents:
0
diff
changeset
|
20 slouken@libsdl.org |
0 | 21 */ |
22 | |
23 /* | |
24 Written by Darrell Walisser <dwaliss1@purdue.edu> | |
25 | |
26 Implementation notes ---------------------------------------------------------------------- | |
27 | |
28 A bit on GWorlds in VRAM from technote 1182: | |
29 | |
30 There are two important things to note about GWorld's allocated in | |
31 VRAM. First, the base address retrieved through GetPixBaseAddr or | |
32 read directly from the PixMap structure can become invalid anytime | |
33 memory is allocated in VRAM. This can occur either by explicit | |
34 allocations, such as calls to NewGWorld, or by implicit ones, such as | |
35 those associated with the internal texture allocation of OpenGL. The | |
36 stored pixel images themselves will still be valid but may have been | |
37 moved in VRAM, thus rendering any stored base addresses invalid. | |
38 You should never store an image's base address for longer than is | |
39 necessary and especially never across calls to NewGWorld or | |
40 texture-creation routines. | |
41 | |
42 Secondly, an offscreen pixel image allocated in VRAM can be | |
43 purged at system task time by the display driver. This means any | |
44 time your application yields time such by calling WaitNextEvent or | |
45 SystemTask you can lose your VRAM GWorld contents. While this | |
46 happens infrequently, usually associated with display resolution or | |
47 pixel depth changes you must code for this eventuality. This purge | |
48 can occur whether or not the GWorld is locked or not. A return value | |
49 of false from LockPixels, a NULL return value from GetPixBaseAddr | |
50 or NULL in the baseAddr field of the PixMap mean that the pixel | |
51 image has been purged. To reallocate it you can either call | |
52 UpdateGWorld or Dispose your current GWorld through | |
53 DisposeGWorld and reallocate it via NewGWorld. Either way you must | |
54 then rebuild the pixel image. | |
55 | |
56 ------------------------------------------------------------------------------------ | |
57 | |
58 Currently, I don't account for (1). In my testing, NewGWorld never invalidated | |
59 other existing GWorlds in VRAM. However, I do have protection for (2). | |
60 Namely, I am using GetOSEvent() instead of WaitNextEvent() so that there are no | |
61 context switches (the app hogs the CPU). Eventually a book-keeping system should | |
62 be coded to take care of (1) and (2). | |
63 | |
64 ------------------------------------------------------------------------------------ | |
65 | |
66 System requirements (* denotes optional): | |
67 | |
68 1. DrawSprocket 1.7.3 | |
69 2. *MacOS 9 or later for hardware accelerated blit / fill | |
70 3. *May also require certain graphics hardware for (2). I trust that all Apple OEM | |
71 hardware will work. Third party accelerators may work if they have QuickDraw | |
72 acceleration in the drivers and the drivers have been updated for OS 9. The current | |
73 Voodoo 3 drivers (1.0b12) do not work. | |
74 | |
75 Coding suggestions: | |
76 | |
77 1. Use SDL_UpdateRects ! | |
78 | |
79 If no QuickDraw acceleration is present, double-buffered surfaces will use a back buffer | |
80 in System memory. I recommend you use SDL_UpdateRects with double-buffered surfaces | |
81 for best performance on these cards, since the overhead is nearly zero for VRAM back buffer. | |
82 | |
83 2. Load most-resident surfaces first. | |
84 | |
85 If you fill up VRAM or AGP memory, there is no contingency for purging to make room for the next one. | |
86 Therefore, you should load the surfaces you plan to use the most frequently first. | |
87 Sooner or later, I will code LRU replacement to help this. | |
88 | |
89 TODO: | |
90 Some kind of posterized mode for resolutions < 640x480. | |
91 Window support / fullscreen toggle. | |
92 Figure out how much VRAM is available. Put in video->info->video_mem. | |
93 Track VRAM usage. | |
94 | |
95 BUGS: | |
96 I can't create a hardware surface the same size as the screen?! How to fix? | |
97 | |
98 | |
99 | |
100 COMPILE OPTIONS: | |
101 | |
102 DSP_TRY_CC_AND_AA - Define if you want to try HWA color-key and alpha blitters | |
103 HW color-key blitting gives substantial improvements, | |
104 but hw alpha is neck-and-neck with SDL's soft bitter. | |
105 | |
106 DSP_NO_SYNC_VBL - Define for HWA double-buffered surfaces: don't sync | |
107 pseudo-flip to monitor redraw. | |
108 | |
109 DSP_NO_SYNC_OPENGL - Define for OpenGL surfaces: don't sync buffer swap. Synching buffer | |
110 swap may result in reduced performance, but can eliminate some | |
111 tearing artifacts. | |
112 CHANGELOG: | |
113 09/17/00 Lots of little tweaks. Build modelist in reverse order so largest contexts | |
114 list first. Compared various methods with ROM methods and fixed rez switch | |
115 crashing bug in GL Tron. (Woohoo!) | |
116 */ | |
117 | |
118 #define DSP_TRY_CC_AND_AA | |
119 | |
120 /* #define DSP_NO_SYNC_VBL */ | |
121 | |
122 #define DSP_NO_SYNC_OPENGL | |
123 | |
124 | |
125 #ifdef SAVE_RCSID | |
126 static char rcsid = | |
127 "@(#) $Id$"; | |
128 #endif | |
129 | |
130 #include <stdio.h> | |
131 #include <stdlib.h> | |
132 | |
133 #if TARGET_API_MAC_CARBON | |
134 #include <Carbon.h> | |
135 #else | |
136 #include <LowMem.h> | |
137 #include <Gestalt.h> | |
138 #include <Devices.h> | |
139 #include <DiskInit.h> | |
140 #include <QDOffscreen.h> | |
141 #endif | |
142 | |
143 #include "SDL_video.h" | |
144 #include "SDL_blit.h" | |
145 #include "SDL_error.h" | |
146 #include "SDL_syswm.h" | |
147 #include "SDL_sysvideo.h" | |
148 #include "SDL_dspvideo.h" | |
149 #include "SDL_macgl_c.h" | |
150 #include "SDL_macwm_c.h" | |
151 #include "SDL_macmouse_c.h" | |
152 #include "SDL_macevents_c.h" | |
153 | |
154 /* Initialization/Query functions */ | |
155 static int DSp_VideoInit(_THIS, SDL_PixelFormat *vformat); | |
156 static SDL_Rect **DSp_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags); | |
157 static SDL_Surface *DSp_SetVideoMode(_THIS, SDL_Surface *current, int width, int height, int bpp, Uint32 flags); | |
158 static int DSp_SetColors(_THIS, int firstcolor, int ncolors, | |
159 SDL_Color *colors); | |
160 static int DSp_CreatePalette(_THIS); | |
161 static int DSp_DestroyPalette(_THIS); | |
162 static void DSp_VideoQuit(_THIS); | |
163 | |
164 static int DSp_GetMainDevice (_THIS, GDHandle *device); | |
165 static void DSp_IsHWAvailable (_THIS, SDL_PixelFormat *vformat); | |
166 static void DSp_DSpUpdate(_THIS, int numrects, SDL_Rect *sdl_rects); | |
167 static void DSp_DirectUpdate(_THIS, int numrects, SDL_Rect *sdl_rects); | |
168 | |
169 /* Hardware surface functions */ | |
170 static int DSp_SetHWAlpha(_THIS, SDL_Surface *surface, UInt8 alpha); | |
171 static int DSp_SetHWColorKey(_THIS, SDL_Surface *surface, Uint32 key); | |
172 static int DSp_NewHWSurface(_THIS, CGrafPtr *port, int depth, int width, int height); | |
173 static int DSp_AllocHWSurface(_THIS, SDL_Surface *surface); | |
174 static int DSp_LockHWSurface(_THIS, SDL_Surface *surface); | |
175 static void DSp_UnlockHWSurface(_THIS, SDL_Surface *surface); | |
176 static void DSp_FreeHWSurface(_THIS, SDL_Surface *surface); | |
177 static int DSp_FlipHWSurface(_THIS, SDL_Surface *surface); | |
178 static int DSp_CheckHWBlit(_THIS, SDL_Surface *src, SDL_Surface *dest); | |
179 static int DSp_HWAccelBlit(SDL_Surface *src, SDL_Rect *srcrect, | |
180 SDL_Surface *dst, SDL_Rect *dstrect); | |
181 static int DSp_FillHWRect(_THIS, SDL_Surface *dst, SDL_Rect *rect, Uint32 color); | |
182 | |
183 #ifdef HAVE_OPENGL | |
184 static void DSp_GL_SwapBuffers (_THIS); | |
185 #endif | |
186 | |
187 #if ! TARGET_API_MAC_CARBON | |
188 | |
189 #define GetPortPixRowBytes(x) ( (*(x->portPixMap))->rowBytes ) | |
190 #define GetGDevPixMap(x) ((**(x)).gdPMap) | |
191 #define GetPortPixMap(x) ((*(x)).portPixMap) | |
192 | |
193 #define GetPixDepth(y) ((**(y)).pixelSize) | |
194 //#define GetPixRowBytes(y) ((**(y)).rowBytes) | |
195 //#define GetPixBaseAddr(y) ((**(y)).baseAddr) | |
196 #define GetPixCTab(y) ((**(y)).pmTable) | |
197 #define GetPortBitMapForCopyBits(x) (&(((GrafPtr)(x))->portBits)) | |
198 | |
199 #else | |
200 #define GetPortPixRowBytes(x) (GetPixRowBytes(GetPortPixMap(x)) ) | |
201 #define GetGDevPixMap(x) ((**(x)).gdPMap) | |
202 | |
203 #endif | |
204 | |
205 typedef struct private_hwdata { | |
206 | |
207 GWorldPtr offscreen; // offscreen gworld in VRAM or AGP | |
208 | |
209 #ifdef DSP_TRY_CC_AND_AA | |
210 GWorldPtr mask; // transparent mask | |
211 RGBColor alpha; // alpha color | |
212 RGBColor trans; // transparent color | |
213 #endif | |
214 | |
215 } private_hwdata; | |
216 | |
217 typedef private_hwdata private_swdata ; /* have same fields */ | |
218 | |
219 /* Macintosh toolbox driver bootstrap functions */ | |
220 | |
221 static int DSp_Available(void) | |
222 { | |
223 /* Check for DrawSprocket */ | |
224 /* This check is only meaningful if you weak-link DrawSprocketLib */ | |
225 return ((Ptr)DSpStartup != (Ptr)kUnresolvedCFragSymbolAddress); | |
226 } | |
227 | |
228 static void DSp_DeleteDevice(SDL_VideoDevice *device) | |
229 { | |
230 /* -dw- taking no chances with null pointers */ | |
231 if (device) { | |
232 | |
233 if (device->hidden) { | |
234 | |
235 if (device->hidden->dspinfo) | |
236 free(device->hidden->dspinfo); | |
237 | |
238 free(device->hidden); | |
239 } | |
240 free(device); | |
241 } | |
242 } | |
243 | |
244 static SDL_VideoDevice *DSp_CreateDevice(int devindex) | |
245 { | |
246 SDL_VideoDevice *device; | |
247 | |
248 /* Initialize all variables that we clean on shutdown */ | |
249 device = (SDL_VideoDevice *)malloc(sizeof(SDL_VideoDevice)); | |
250 if ( device ) { | |
251 memset(device, 0, sizeof (*device)); | |
252 device->hidden = (struct SDL_PrivateVideoData *) | |
253 malloc((sizeof *device->hidden)); | |
254 if (device->hidden) | |
255 memset(device->hidden, 0, sizeof ( *(device->hidden) ) ); | |
256 } | |
257 if ( (device == NULL) || (device->hidden == NULL) ) { | |
258 SDL_OutOfMemory(); | |
259 | |
260 if ( device ) { | |
261 | |
262 if (device->hidden) | |
263 free (device->hidden); | |
264 | |
265 free(device); | |
266 } | |
267 | |
268 return(NULL); | |
269 } | |
270 | |
271 /* Allocate DrawSprocket information */ | |
272 device->hidden->dspinfo = (struct DSpInfo *)malloc( | |
273 (sizeof *device->hidden->dspinfo)); | |
274 if ( device->hidden->dspinfo == NULL ) { | |
275 SDL_OutOfMemory(); | |
276 free(device->hidden); | |
277 free(device); | |
278 return(0); | |
279 } | |
280 memset(device->hidden->dspinfo, 0, (sizeof *device->hidden->dspinfo)); | |
281 | |
282 /* Set the function pointers */ | |
283 device->VideoInit = DSp_VideoInit; | |
284 device->ListModes = DSp_ListModes; | |
285 device->SetVideoMode = DSp_SetVideoMode; | |
286 device->SetColors = DSp_SetColors; | |
287 device->UpdateRects = NULL; | |
288 device->VideoQuit = DSp_VideoQuit; | |
289 device->AllocHWSurface = DSp_AllocHWSurface; | |
290 device->CheckHWBlit = NULL; | |
291 device->FillHWRect = NULL; | |
292 device->SetHWColorKey = NULL; | |
293 device->SetHWAlpha = NULL; | |
294 device->LockHWSurface = DSp_LockHWSurface; | |
295 device->UnlockHWSurface = DSp_UnlockHWSurface; | |
296 device->FlipHWSurface = DSp_FlipHWSurface; | |
297 device->FreeHWSurface = DSp_FreeHWSurface; | |
298 #ifdef HAVE_OPENGL | |
299 device->GL_MakeCurrent = Mac_GL_MakeCurrent; | |
300 device->GL_SwapBuffers = DSp_GL_SwapBuffers; | |
1032
c1c2efca4548
Date: Mon, 24 Jan 2005 21:37:56 +0800
Sam Lantinga <slouken@libsdl.org>
parents:
769
diff
changeset
|
301 device->GL_LoadLibrary = Mac_GL_LoadLibrary; |
c1c2efca4548
Date: Mon, 24 Jan 2005 21:37:56 +0800
Sam Lantinga <slouken@libsdl.org>
parents:
769
diff
changeset
|
302 device->GL_GetProcAddress = Mac_GL_GetProcAddress; |
0 | 303 #endif |
304 device->SetCaption = NULL; | |
305 device->SetIcon = NULL; | |
306 device->IconifyWindow = NULL; | |
307 device->GrabInput = NULL; | |
308 device->GetWMInfo = NULL; | |
309 device->FreeWMCursor = Mac_FreeWMCursor; | |
310 device->CreateWMCursor = Mac_CreateWMCursor; | |
311 device->ShowWMCursor = Mac_ShowWMCursor; | |
312 device->WarpWMCursor = Mac_WarpWMCursor; | |
313 device->InitOSKeymap = Mac_InitOSKeymap; | |
314 device->PumpEvents = Mac_PumpEvents; | |
315 | |
316 device->GrabInput = NULL; | |
317 device->CheckMouseMode = NULL; | |
318 | |
319 device->free = DSp_DeleteDevice; | |
320 | |
321 return device; | |
322 } | |
323 | |
324 VideoBootStrap DSp_bootstrap = { | |
325 "DSp", "MacOS DrawSprocket", | |
326 DSp_Available, DSp_CreateDevice | |
327 }; | |
328 | |
329 /* Use DSp/Display Manager to build mode list for given screen */ | |
330 static SDL_Rect** DSp_BuildModeList (const GDHandle gDevice) | |
331 { | |
332 DSpContextAttributes attributes; | |
333 DSpContextReference context; | |
334 DisplayIDType displayID; | |
335 SDL_Rect temp_list [16]; | |
336 SDL_Rect **mode_list; | |
337 int width, height, i, j; | |
338 | |
339 #if TARGET_API_MAC_OSX | |
340 | |
341 displayID = 0; | |
342 | |
343 #else | |
344 /* Ask Display Manager for integer id of screen device */ | |
345 if ( DMGetDisplayIDByGDevice (gDevice, &displayID, SDL_TRUE) != noErr ) { | |
346 return NULL; | |
347 } | |
348 #endif | |
349 /* Get the first possible DSp context on this device */ | |
350 if ( DSpGetFirstContext (displayID, &context) != noErr ) { | |
351 return NULL; | |
352 } | |
353 | |
354 if ( DSpContext_GetAttributes (context, &attributes) != noErr ) | |
355 return NULL; | |
356 | |
357 for ( i = 0; i < SDL_TABLESIZE(temp_list); i++ ) { | |
358 width = attributes.displayWidth; | |
359 height = attributes.displayHeight; | |
360 | |
361 temp_list [i].x = 0 | attributes.displayBestDepth; | |
362 temp_list [i].y = 0; | |
363 temp_list [i].w = width; | |
364 temp_list [i].h = height; | |
365 | |
366 /* DSp will report many different contexts with the same width and height. */ | |
367 /* They will differ in bit depth and refresh rate. */ | |
368 /* We will ignore them until we reach one with a different width/height */ | |
369 /* When there are no more contexts to look at, we will quit building the list*/ | |
370 while ( width == attributes.displayWidth && height == attributes.displayHeight ) { | |
371 | |
372 OSStatus err = DSpGetNextContext (context, &context); | |
373 if (err != noErr) | |
374 if (err == kDSpContextNotFoundErr) | |
375 goto done; | |
376 else | |
377 return NULL; | |
378 | |
379 if ( DSpContext_GetAttributes (context, &attributes) != noErr ) | |
380 return NULL; | |
381 | |
382 temp_list [i].x |= attributes.displayBestDepth; | |
383 } | |
384 } | |
385 done: | |
386 i++; /* i was not incremented before kicking out of the loop */ | |
387 | |
388 mode_list = (SDL_Rect**) malloc (sizeof (SDL_Rect*) * (i+1)); | |
389 if (mode_list) { | |
390 | |
391 /* -dw- new stuff: build in reverse order so largest sizes list first */ | |
392 for (j = i-1; j >= 0; j--) { | |
393 mode_list [j] = (SDL_Rect*) malloc (sizeof (SDL_Rect)); | |
394 if (mode_list [j]) | |
395 memcpy (mode_list [j], &(temp_list [j]), sizeof (SDL_Rect)); | |
396 else { | |
397 SDL_OutOfMemory (); | |
398 return NULL; | |
399 } | |
400 } | |
401 mode_list [i] = NULL; /* append null to the end */ | |
402 } | |
403 else { | |
404 SDL_OutOfMemory (); | |
405 return NULL; | |
406 } | |
407 | |
408 return mode_list; | |
409 } | |
410 | |
411 static void DSp_IsHWAvailable (_THIS, SDL_PixelFormat *vformat) | |
412 { | |
413 /* | |
414 VRAM GWorlds are only available on OS 9 or later. | |
415 Even with OS 9, some display drivers won't support it, | |
416 so we create a test GWorld and check for errors. | |
417 */ | |
418 | |
419 long versionSystem; | |
420 | |
421 dsp_vram_available = SDL_FALSE; | |
422 dsp_agp_available = SDL_FALSE; | |
423 | |
424 Gestalt ('sysv', &versionSystem); | |
425 if (0x00000860 < (versionSystem & 0x0000FFFF)) { | |
426 | |
427 GWorldPtr offscreen; | |
428 OSStatus err; | |
429 Rect bounds; | |
430 | |
431 SetRect (&bounds, 0, 0, 320, 240); | |
432 | |
433 err = NewGWorld (&offscreen, vformat->BitsPerPixel, &bounds, NULL, SDL_Display, useDistantHdwrMem | noNewDevice); | |
434 if (err == noErr) { | |
435 dsp_vram_available = SDL_TRUE; | |
436 DisposeGWorld (offscreen); | |
437 } | |
438 | |
439 err = NewGWorld (&offscreen, vformat->BitsPerPixel, &bounds, NULL, SDL_Display, useLocalHdwrMem | noNewDevice); | |
440 if (err == noErr) { | |
441 DisposeGWorld (offscreen); | |
442 dsp_agp_available = SDL_TRUE; | |
443 } | |
444 } | |
445 } | |
446 | |
447 static int DSp_GetMainDevice (_THIS, GDHandle *device) | |
448 { | |
449 | |
450 #if TARGET_API_MAC_OSX | |
451 /* DSpUserSelectContext not available on OS X */ | |
452 *device = GetMainDevice(); | |
453 return 0; | |
454 #else | |
455 | |
456 DSpContextAttributes attrib; | |
457 DSpContextReference context; | |
458 DisplayIDType display_id; | |
459 GDHandle main_device; | |
460 GDHandle device_list; | |
461 | |
462 device_list = GetDeviceList (); | |
463 main_device = GetMainDevice (); | |
464 | |
465 /* Quick check to avoid slower method when only one display exists */ | |
466 if ( (**device_list).gdNextGD == NULL ) { | |
467 *device = main_device; | |
468 return 0; | |
469 } | |
470 | |
471 memset (&attrib, 0, sizeof (DSpContextAttributes)); | |
472 | |
473 /* These attributes are hopefully supported on all devices...*/ | |
474 attrib.displayWidth = 640; | |
475 attrib.displayHeight = 480; | |
476 attrib.displayBestDepth = 8; | |
477 attrib.backBufferBestDepth = 8; | |
478 attrib.displayDepthMask = kDSpDepthMask_All; | |
479 attrib.backBufferDepthMask = kDSpDepthMask_All; | |
480 attrib.colorNeeds = kDSpColorNeeds_Require; | |
481 attrib.pageCount = 1; | |
482 | |
483 if (noErr != DMGetDisplayIDByGDevice (main_device, &display_id, SDL_FALSE)) { | |
484 SDL_SetError ("Display Manager couldn't associate GDevice with a Display ID"); | |
485 return (-1); | |
486 } | |
487 | |
488 /* Put up dialog on main display to select which display to use */ | |
489 if (noErr != DSpUserSelectContext (&attrib, display_id, NULL, &context)) { | |
490 SDL_SetError ("DrawSprocket couldn't create a context"); | |
491 return (-1); | |
492 } | |
493 | |
494 if (noErr != DSpContext_GetDisplayID (context, &display_id)) { | |
495 SDL_SetError ("DrawSprocket couldn't get display ID"); | |
496 return (-1); | |
497 } | |
498 | |
499 if (noErr != DMGetGDeviceByDisplayID (display_id, &main_device, SDL_FALSE)) { | |
500 SDL_SetError ("Display Manager couldn't associate Display ID with GDevice"); | |
501 return (-1); | |
502 } | |
503 | |
504 *device = main_device; | |
505 return (0); | |
506 #endif | |
507 } | |
508 | |
509 static int DSp_VideoInit(_THIS, SDL_PixelFormat *vformat) | |
510 { | |
511 | |
512 NumVersion dsp_version = DSpGetVersion (); | |
513 | |
514 if ( (dsp_version.majorRev == 1 && dsp_version.minorAndBugRev < 0x73) || | |
515 (dsp_version.majorRev < 1) ) { | |
516 | |
517 /* StandardAlert (kAlertStopAlert, "\pError!", | |
518 "\pI need DrawSprocket 1.7.3 or later!\n" | |
519 "You can find a newer version at http://www.apple.com/swupdates.", | |
520 NULL, NULL); | |
521 */ | |
522 SDL_SetError ("DrawSprocket version is too old. Need 1.7.3 or later."); | |
523 return (-1); | |
524 } | |
525 | |
526 if ( DSpStartup () != noErr ) { | |
527 SDL_SetError ("DrawSprocket couldn't startup"); | |
528 return(-1); | |
529 } | |
530 | |
531 /* Start DSpintosh events */ | |
532 Mac_InitEvents(this); | |
533 | |
534 /* Get a handle to the main monitor, or choose one on multiple monitor setups */ | |
535 if ( DSp_GetMainDevice(this, &SDL_Display) < 0) | |
536 return (-1); | |
537 | |
538 /* Determine pixel format */ | |
539 vformat->BitsPerPixel = GetPixDepth ( (**SDL_Display).gdPMap ); | |
540 dsp_old_depth = vformat->BitsPerPixel; | |
541 | |
542 switch (vformat->BitsPerPixel) { | |
543 case 16: | |
544 vformat->Rmask = 0x00007c00; | |
545 vformat->Gmask = 0x000003e0; | |
546 vformat->Bmask = 0x0000001f; | |
547 break; | |
548 default: | |
549 break; | |
550 } | |
551 | |
552 if ( DSp_CreatePalette (this) < 0 ) { | |
553 | |
554 SDL_SetError ("Could not create palette"); | |
555 return (-1); | |
556 } | |
557 | |
558 /* Get a list of available fullscreen modes */ | |
559 SDL_modelist = DSp_BuildModeList (SDL_Display); | |
560 if (SDL_modelist == NULL) { | |
561 SDL_SetError ("DrawSprocket could not build a mode list"); | |
562 return (-1); | |
563 } | |
564 | |
565 /* Check for VRAM and AGP GWorlds for HW Blitting */ | |
566 DSp_IsHWAvailable (this, vformat); | |
567 | |
568 this->info.wm_available = 0; | |
569 | |
570 if (dsp_vram_available || dsp_agp_available) { | |
571 | |
572 this->info.hw_available = SDL_TRUE; | |
573 | |
574 this->CheckHWBlit = DSp_CheckHWBlit; | |
575 this->info.blit_hw = SDL_TRUE; | |
576 | |
577 this->FillHWRect = DSp_FillHWRect; | |
578 this->info.blit_fill = SDL_TRUE; | |
579 | |
580 #ifdef DSP_TRY_CC_AND_AA | |
581 this->SetHWColorKey = DSp_SetHWColorKey; | |
582 this->info.blit_hw_CC = SDL_TRUE; | |
583 | |
584 this->SetHWAlpha = DSp_SetHWAlpha; | |
585 this->info.blit_hw_A = SDL_TRUE; | |
586 #endif | |
587 | |
588 } | |
589 | |
590 return(0); | |
591 } | |
592 | |
593 static SDL_Rect **DSp_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags) | |
594 { | |
595 static SDL_Rect *dsp_modes[16]; | |
596 int i = 0, j = 0; | |
597 | |
598 if ( format->BitsPerPixel == 0 ) | |
599 return ( (SDL_Rect**) NULL ); | |
600 | |
601 while (SDL_modelist[i] != NULL) { | |
602 | |
603 if (SDL_modelist[i]->x & format->BitsPerPixel) { | |
604 dsp_modes[j] = SDL_modelist[i]; | |
605 j++; | |
606 } | |
607 i++; | |
608 } | |
609 | |
610 dsp_modes[j] = NULL; | |
611 | |
612 return dsp_modes; | |
613 } | |
614 | |
615 /* Various screen update functions available */ | |
616 static void DSp_DirectUpdate(_THIS, int numrects, SDL_Rect *rects); | |
617 | |
618 static volatile unsigned int retrace_count = 0; /* -dw- need volatile because it updates asychronously */ | |
619 | |
620 #if ! TARGET_API_MAC_OSX | |
621 Boolean DSp_VBLProc ( DSpContextReference context, void *ref_con ) | |
622 { | |
623 retrace_count++; | |
624 | |
625 return 1; /* Darrell, is this right? */ | |
626 } | |
627 #endif | |
628 | |
629 static void DSp_SetHWError (OSStatus err, int is_agp) | |
630 { | |
631 char message[1024]; | |
632 const char *fmt, *mem; | |
633 | |
634 if ( is_agp ) { | |
635 mem = "AGP Memory"; | |
636 } else { | |
637 mem = "VRAM"; | |
638 } | |
639 switch(err) { | |
640 case memFullErr: | |
641 fmt = "Hardware surface possible but not enough %s available"; | |
642 break; | |
643 case cDepthErr: | |
644 fmt = "Hardware surface possible but invalid color depth"; | |
645 break; | |
646 default: | |
647 fmt = "Hardware surface could not be allocated in %s - unknown error"; | |
648 break; | |
649 } | |
650 sprintf(message, fmt, mem); | |
651 SDL_SetError(message); | |
652 } | |
653 | |
654 /* put up a dialog to verify display change */ | |
655 static int DSp_ConfirmSwitch () { | |
656 | |
657 /* resource id's for dialog */ | |
658 const int rDialog = 1002; | |
659 const int bCancel = 1; | |
660 const int bOK = 2; | |
661 | |
662 DialogPtr dialog; | |
663 OSStatus err; | |
664 SInt32 response; | |
665 DialogItemIndex item = 0; | |
666 GrafPtr savePort; | |
667 | |
668 GetPort (&savePort); | |
669 | |
670 dialog = GetNewDialog (rDialog, NULL, (WindowPtr) -1); | |
671 if (dialog == NULL) | |
672 return (0); | |
673 | |
674 SetPort (dialog); | |
675 | |
676 SetDialogDefaultItem (dialog, bCancel); | |
677 SetDialogCancelItem (dialog, bCancel); | |
678 | |
679 SetEventMask (everyEvent); | |
680 FlushEvents (everyEvent, 0); | |
681 | |
682 /* On MacOS 8.5 or later, we can make the dialog go away after 15 seconds */ | |
683 /* This is good since it's possible user can't even see the dialog! */ | |
684 /* Requires linking to DialogsLib */ | |
685 err = Gestalt(gestaltSystemVersion,&response); | |
686 if (err == noErr && response >= 0x00000850) { | |
687 SetDialogTimeout(dialog, bCancel, 15); | |
688 } | |
689 | |
690 do { | |
691 | |
692 ModalDialog ( NULL, &item ); | |
693 | |
694 } while ( item != bCancel && item != bOK && err != noErr); | |
695 | |
696 DisposeWindow (dialog); | |
697 SetPort (savePort); | |
698 | |
699 SetEventMask(everyEvent - autoKeyMask); | |
700 FlushEvents(everyEvent, 0); | |
701 | |
702 return (item - 1); | |
703 } | |
704 | |
705 static void DSp_UnsetVideoMode(_THIS, SDL_Surface *current) | |
706 { | |
707 | |
708 | |
709 if ( current->flags & SDL_OPENGL ) { | |
710 Mac_GL_Quit (this); | |
711 } | |
712 | |
713 if (dsp_context != NULL) { | |
714 | |
715 GWorldPtr front; | |
716 DSpContext_GetFrontBuffer (dsp_context, &front); | |
717 | |
718 if (front != dsp_back_buffer) | |
719 DisposeGWorld (dsp_back_buffer); | |
720 | |
721 if (current->hwdata) | |
722 free (current->hwdata); | |
723 | |
724 DSpContext_SetState (dsp_context, kDSpContextState_Inactive ); | |
725 DSpContext_Release (dsp_context); | |
726 | |
727 dsp_context = NULL; | |
728 } | |
729 | |
730 if (SDL_Window != NULL) { | |
731 DisposeWindow (SDL_Window); | |
732 SDL_Window = NULL; | |
733 } | |
734 | |
735 current->pixels = NULL; | |
736 current->flags = 0; | |
737 } | |
738 | |
739 static SDL_Surface *DSp_SetVideoMode(_THIS, | |
740 SDL_Surface *current, int width, int height, int bpp, Uint32 flags) | |
741 { | |
742 | |
743 DisplayIDType display_id; | |
744 DSpContextAttributes attrib; | |
745 Fixed freq; | |
746 OSStatus err; | |
747 UInt32 rmask = 0, gmask = 0, bmask = 0; | |
748 | |
749 int page_count; | |
750 int double_buf; | |
751 int hw_surface; | |
752 int use_dsp_back_buffer; | |
753 | |
754 DSp_UnsetVideoMode (this, current); | |
755 | |
756 if (bpp != dsp_old_depth) | |
757 DSp_DestroyPalette (this); | |
758 | |
759 double_buf = (flags & SDL_DOUBLEBUF) != 0; | |
760 hw_surface = (flags & SDL_HWSURFACE) != 0; | |
761 use_dsp_back_buffer = !dsp_vram_available || !hw_surface ; | |
762 | |
763 current->flags |= SDL_FULLSCREEN; | |
764 | |
765 rebuild: | |
766 | |
767 if ( double_buf && use_dsp_back_buffer ) { | |
768 page_count = 2; | |
769 } else { | |
770 page_count = 1; | |
771 } | |
772 | |
773 memset (&attrib, 0, sizeof (DSpContextAttributes)); | |
774 attrib.displayWidth = width; | |
775 attrib.displayHeight = height; | |
776 attrib.displayBestDepth = bpp; | |
777 attrib.backBufferBestDepth = bpp; | |
778 attrib.displayDepthMask = kDSpDepthMask_All; | |
779 attrib.backBufferDepthMask = kDSpDepthMask_All; | |
780 attrib.colorNeeds = kDSpColorNeeds_Require; | |
781 attrib.colorTable = 0; | |
782 attrib.pageCount = page_count; | |
783 #if TARGET_API_MAC_OSX | |
784 | |
785 if ( DSpFindBestContext (&attrib, &dsp_context) != noErr ) { | |
786 SDL_SetError ("DrawSprocket couldn't find a context"); | |
787 return NULL; | |
788 } | |
789 | |
790 #else | |
791 if ( noErr != DMGetDisplayIDByGDevice (SDL_Display, &display_id, SDL_FALSE) ) { | |
792 SDL_SetError ("Display Manager couldn't associate GDevice with display_id"); | |
793 return NULL; | |
794 } | |
1032
c1c2efca4548
Date: Mon, 24 Jan 2005 21:37:56 +0800
Sam Lantinga <slouken@libsdl.org>
parents:
769
diff
changeset
|
795 if ( DSpFindBestContextOnDisplayID(&attrib, &dsp_context, display_id) != noErr ) { |
0 | 796 SDL_SetError ("DrawSprocket couldn't find a suitable context on given display"); |
797 return NULL; | |
798 } | |
799 | |
800 #endif | |
801 if ( DSpContext_Reserve (dsp_context, &attrib) != noErr ) { | |
802 SDL_SetError ("DrawSprocket couldn't get the needed resources to build the display"); | |
803 return NULL; | |
804 } | |
805 | |
806 if ( (err = DSpContext_SetState (dsp_context, kDSpContextState_Active)) != noErr ) { | |
807 | |
808 if (err == kDSpConfirmSwitchWarning) { | |
809 | |
810 if ( ! DSp_ConfirmSwitch () ) { | |
811 | |
812 DSpContext_Release (dsp_context); | |
813 dsp_context = NULL; | |
814 SDL_SetError ("User cancelled display switch"); | |
815 return NULL; | |
816 } | |
817 else | |
818 /* Have to reactivate context. Why? */ | |
819 DSpContext_SetState (dsp_context, kDSpContextState_Active); | |
820 | |
821 } | |
822 else { | |
823 SDL_SetError ("DrawSprocket couldn't activate the context"); | |
824 return NULL; | |
825 } | |
826 } | |
827 | |
828 | |
829 if (bpp != dsp_old_depth) { | |
830 | |
831 DSp_CreatePalette (this); | |
832 | |
833 /* update format if display depth changed */ | |
834 if (bpp == 16) { | |
835 | |
836 rmask = 0x00007c00; | |
837 gmask = 0x000003e0; | |
838 bmask = 0x0000001f; | |
839 } | |
840 if ( ! SDL_ReallocFormat (current, bpp, rmask, gmask, bmask, 0 ) ) { | |
841 | |
842 SDL_SetError ("Could not reallocate video format."); | |
843 return(NULL); | |
844 } | |
845 } | |
846 | |
847 if (!double_buf) { | |
848 | |
849 /* single-buffer context */ | |
850 DSpContext_GetFrontBuffer (dsp_context, &dsp_back_buffer); | |
851 | |
852 current->hwdata = (private_hwdata*) malloc (sizeof (private_hwdata)); | |
853 if (current ->hwdata == NULL) { | |
854 SDL_OutOfMemory (); | |
855 return NULL; | |
856 } | |
857 current->hwdata->offscreen = dsp_back_buffer; | |
858 current->flags |= SDL_HWSURFACE; | |
859 this->UpdateRects = DSp_DirectUpdate; | |
860 } | |
861 else if ( use_dsp_back_buffer ) { | |
862 | |
863 DSpContext_GetBackBuffer (dsp_context, kDSpBufferKind_Normal, &dsp_back_buffer); | |
864 | |
865 current->flags |= SDL_DOUBLEBUF | SDL_SWSURFACE; /* only front buffer is in VRAM */ | |
866 this->UpdateRects = DSp_DSpUpdate; | |
867 } | |
868 else if ( DSp_NewHWSurface(this, &dsp_back_buffer, bpp, width-1, height-1) == 0 ) { | |
869 | |
870 current->hwdata = (private_hwdata*) malloc (sizeof (private_hwdata)); | |
871 if (current ->hwdata == NULL) { | |
872 SDL_OutOfMemory (); | |
873 return NULL; | |
874 } | |
875 | |
876 memset (current->hwdata, 0, sizeof (private_hwdata)); | |
877 current->hwdata->offscreen = dsp_back_buffer; | |
878 current->flags |= SDL_DOUBLEBUF | SDL_HWSURFACE; | |
879 this->UpdateRects = DSp_DirectUpdate; /* hardware doesn't do update rects, must be page-flipped */ | |
880 } | |
881 else { | |
882 | |
883 DSpContext_Release (dsp_context); | |
884 use_dsp_back_buffer = SDL_TRUE; | |
885 goto rebuild; | |
886 } | |
887 | |
888 current->pitch = GetPortPixRowBytes(dsp_back_buffer) & 0x3FFF; | |
889 current->pixels = GetPixBaseAddr(GetPortPixMap(dsp_back_buffer)); | |
890 | |
891 current->w = width; | |
892 current->h = height; | |
893 | |
894 #if ! TARGET_API_MAC_OSX | |
895 | |
896 if (use_dsp_back_buffer) { | |
897 | |
898 DSpContext_GetMonitorFrequency (dsp_context, &freq); | |
899 DSpContext_SetMaxFrameRate (dsp_context, freq >> 16); | |
900 } | |
901 | |
902 | |
903 if ( (current->flags & SDL_HWSURFACE) || (current->flags & SDL_OPENGL) ) | |
904 DSpContext_SetVBLProc (dsp_context, DSp_VBLProc, NULL); | |
905 #endif | |
906 | |
907 if (bpp == 8) | |
908 current->flags |= SDL_HWPALETTE; | |
909 | |
910 if (flags & SDL_OPENGL) { | |
911 | |
912 Rect rect; | |
913 RGBColor rgb = { 0.0, 0.0, 0.0 }; | |
914 GrafPtr save_port; | |
915 | |
916 SetRect (&rect, 0, 0, width, height); | |
917 SDL_Window = NewCWindow(nil, &( (**SDL_Display).gdRect), "\p", SDL_TRUE, plainDBox, (WindowPtr)-1, SDL_FALSE, 0); | |
918 | |
919 if (SDL_Window == NULL) { | |
920 | |
921 SDL_SetError ("DSp_SetVideoMode : OpenGL window could not be created."); | |
922 return NULL; | |
923 } | |
924 | |
925 /* Set window color to black to avoid white flash*/ | |
926 GetPort (&save_port); | |
927 SetPort (SDL_Window); | |
928 RGBForeColor (&rgb); | |
929 PaintRect (&rect); | |
930 SetPort (save_port); | |
931 | |
932 SetPortWindowPort (SDL_Window); | |
933 SelectWindow (SDL_Window); | |
934 | |
935 if ( Mac_GL_Init (this) < 0 ) { | |
936 | |
937 SDL_SetError ("DSp_SetVideoMode : could not create OpenGL context."); | |
938 return NULL; | |
939 } | |
940 | |
941 current->flags |= SDL_OPENGL; | |
942 } | |
943 | |
944 return current; | |
945 } | |
946 | |
947 #ifdef DSP_TRY_CC_AND_AA | |
948 | |
949 static int DSp_MakeHWMask (_THIS, SDL_Surface *surface) | |
950 { | |
951 GDHandle save_device; | |
952 CGrafPtr save_port; | |
953 GWorldPtr temp; | |
954 RGBColor black = { 0, 0, 0 }; | |
955 RGBColor white = { 0xFFFF, 0xFFFF, 0xFFFF }; | |
956 Rect rect; | |
957 | |
958 Uint32 depth = GetPixDepth ( GetGDevPixMap (SDL_Display) ); | |
959 | |
960 SetRect (&rect, 0, 0, surface->w, surface->h); | |
961 | |
962 if ( noErr != NewGWorld (&(surface->hwdata->mask), depth, &rect, 0, SDL_Display, 0 ) < 0 ) { | |
963 | |
964 SDL_OutOfMemory (); | |
965 return (-1); | |
966 } | |
967 | |
968 if ( noErr != NewGWorld (&temp, depth, &rect, 0 , SDL_Display, 0 ) ) { | |
969 | |
970 SDL_OutOfMemory (); | |
971 return (-1); | |
972 } | |
973 | |
974 | |
975 GetGWorld (&save_port, &save_device); | |
976 SetGWorld (surface->hwdata->mask, SDL_Display); | |
977 | |
978 RGBForeColor (&white); | |
979 PaintRect (&rect); | |
980 | |
981 RGBBackColor (&(surface->hwdata->trans)); | |
982 | |
983 CopyBits ( GetPortBitMapForCopyBits(surface->hwdata->offscreen), | |
984 GetPortBitMapForCopyBits(surface->hwdata->mask), | |
985 &rect, &rect, transparent, NULL ); | |
986 | |
987 SetGWorld (surface->hwdata->mask, SDL_Display); | |
988 SetGWorld (save_port, save_device); | |
989 return (0); | |
990 } | |
991 | |
992 static int DSp_SetHWAlpha(_THIS, SDL_Surface *surface, UInt8 alpha) | |
993 { | |
994 surface->hwdata->alpha.red = (alpha / 255.0) * 65535; | |
995 surface->hwdata->alpha.blue = (alpha / 255.0) * 65535; | |
996 surface->hwdata->alpha.green = (alpha / 255.0) * 65535; | |
997 | |
998 surface->flags |= SDL_SRCALPHA; | |
999 | |
1000 if (surface->flags & SDL_SRCCOLORKEY) { | |
1001 return(DSp_MakeHWMask (this, surface)); | |
1002 } | |
1003 return(0); | |
1004 } | |
1005 | |
1006 static int DSp_SetHWColorKey(_THIS, SDL_Surface *surface, Uint32 key) | |
1007 { | |
1008 CGrafPtr save_port; | |
1009 GDHandle save_device; | |
1010 | |
1011 GetGWorld (&save_port, &save_device); | |
1012 SetGWorld (surface->hwdata->offscreen, NULL); | |
1013 | |
1014 Index2Color (key, &(surface->hwdata->trans)); | |
1015 surface->flags |= SDL_SRCCOLORKEY; | |
1016 | |
1017 SetGWorld (save_port, save_device); | |
1018 | |
1019 if ( surface->flags & SDL_SRCALPHA ) { | |
1020 return(DSp_MakeHWMask (this, surface)); | |
1021 } | |
1022 return(0); | |
1023 } | |
1024 | |
1025 #endif /* DSP_TRY_CC_AND_AA */ | |
1026 | |
1027 static int DSp_NewHWSurface(_THIS, CGrafPtr *port, int depth, int width, int height) { | |
1028 | |
1029 OSStatus err; | |
1030 Rect bounds; | |
1031 | |
1032 SetRect (&bounds, 0, 0, width, height); | |
1033 | |
1034 if (dsp_vram_available) { | |
1035 /* try VRAM */ | |
1036 err = NewGWorld (port, depth, &bounds, 0 , SDL_Display, useDistantHdwrMem | noNewDevice ); | |
1037 if (err != noErr) | |
1038 DSp_SetHWError (err, SDL_FALSE); | |
1039 else | |
1040 return (0); | |
1041 } | |
1042 | |
1043 if (dsp_agp_available) { | |
1044 /* try AGP */ | |
1045 err = NewGWorld (port, depth, &bounds, 0 , SDL_Display, useLocalHdwrMem | noNewDevice ); | |
1046 | |
1047 if (err != noErr) | |
1048 DSp_SetHWError (err, SDL_TRUE); | |
1049 else | |
1050 return (0); | |
1051 } | |
1052 | |
1053 return (-1); | |
1054 } | |
1055 | |
1056 static int DSp_AllocHWSurface(_THIS, SDL_Surface *surface) | |
1057 { | |
1058 GWorldPtr temp; | |
1059 | |
1060 if ( DSp_NewHWSurface (this, &temp, surface->format->BitsPerPixel, surface->w, surface->h) < 0 ) | |
1061 return (-1); | |
1062 | |
1063 surface->hwdata = (private_hwdata*) malloc (sizeof (private_hwdata)); | |
1064 if (surface->hwdata == NULL) { | |
1065 SDL_OutOfMemory (); | |
1066 return -1; | |
1067 } | |
1068 | |
1069 memset (surface->hwdata, 0, sizeof(private_hwdata)); | |
1070 surface->hwdata->offscreen = temp; | |
1071 surface->pitch = GetPixRowBytes (GetPortPixMap (temp)) & 0x3FFF; | |
1072 surface->pixels = GetPixBaseAddr (GetPortPixMap (temp)); | |
1073 surface->flags |= SDL_HWSURFACE; | |
1074 #ifdef DSP_TRY_CC_AND_AA | |
1075 surface->flags |= SDL_HWACCEL; | |
1076 #endif | |
1077 return 0; | |
1078 } | |
1079 | |
1080 static void DSp_FreeHWSurface(_THIS, SDL_Surface *surface) | |
1081 { | |
1082 if (surface->hwdata->offscreen != NULL) | |
1083 DisposeGWorld (surface->hwdata->offscreen); | |
1084 free (surface->hwdata); | |
1085 | |
1086 surface->pixels = NULL; | |
1087 } | |
1088 | |
1089 static int DSp_CheckHWBlit(_THIS, SDL_Surface *src, SDL_Surface *dest) | |
1090 { | |
1091 int accelerated; | |
1092 | |
1093 /* Set initial acceleration on */ | |
1094 src->flags |= SDL_HWACCEL; | |
1095 | |
1096 /* Set the surface attributes */ | |
1097 if ( (src->flags & SDL_SRCALPHA) == SDL_SRCALPHA ) { | |
1098 if ( ! this->info.blit_hw_A ) { | |
1099 src->flags &= ~SDL_HWACCEL; | |
1100 } | |
1101 } | |
1102 if ( (src->flags & SDL_SRCCOLORKEY) == SDL_SRCCOLORKEY ) { | |
1103 if ( ! this->info.blit_hw_CC ) { | |
1104 src->flags &= ~SDL_HWACCEL; | |
1105 } | |
1106 } | |
1107 | |
1108 /* Check to see if final surface blit is accelerated */ | |
1109 accelerated = !!(src->flags & SDL_HWACCEL); | |
1110 if ( accelerated ) { | |
1111 src->map->hw_blit = DSp_HWAccelBlit; | |
1112 } | |
1113 return(accelerated); | |
1114 } | |
1115 | |
1116 static int DSp_HWAccelBlit(SDL_Surface *src, SDL_Rect *srcrect, | |
1117 SDL_Surface *dst, SDL_Rect *dstrect) | |
1118 { | |
1119 CGrafPtr save_port; | |
1120 GDHandle save_device; | |
1121 Rect src_rect, dst_rect; | |
1122 RGBColor black = { 0, 0, 0 }; | |
1123 RGBColor white = { 0xFFFF, 0xFFFF, 0xFFFF }; | |
1124 | |
1125 #ifdef DSP_TRY_CC_AND_AA | |
1126 UInt32 mode; | |
1127 #endif | |
1128 | |
1129 SetRect (&src_rect, srcrect->x, srcrect->y, srcrect->x + srcrect->w, srcrect->y + srcrect->h); | |
1130 SetRect (&dst_rect, dstrect->x, dstrect->y, dstrect->x + dstrect->w, dstrect->y + dstrect->h); | |
1131 | |
1132 GetGWorld (&save_port, &save_device); | |
1133 SetGWorld (dst->hwdata->offscreen, NULL); | |
1134 | |
1135 RGBForeColor (&black); | |
1136 RGBBackColor (&white); | |
1137 | |
1138 #ifdef DSP_TRY_CC_AND_AA | |
1139 | |
1140 if ( (src->flags & SDL_SRCCOLORKEY) && | |
1141 (src->flags & SDL_SRCALPHA) ) { | |
1142 | |
1143 OpColor (&(src->hwdata->alpha)); | |
1144 | |
1145 CopyDeepMask ( GetPortBitMapForCopyBits(src->hwdata->offscreen), | |
1146 GetPortBitMapForCopyBits(src->hwdata->mask), | |
1147 GetPortBitMapForCopyBits(dst->hwdata->offscreen), | |
1148 &src_rect, &src_rect, &dst_rect, | |
1149 blend, | |
1150 NULL ); | |
1151 } | |
1152 else { | |
1153 | |
1154 if ( src->flags & SDL_SRCCOLORKEY) { | |
1155 RGBBackColor (&(src->hwdata->trans) ); | |
1156 mode = transparent; | |
1157 } | |
1158 else if (src->flags & SDL_SRCALPHA) { | |
1159 | |
1160 OpColor (&(src->hwdata->alpha)); | |
1161 mode = blend; | |
1162 } | |
1163 else { | |
1164 | |
1165 mode = srcCopy; | |
1166 } | |
1167 | |
1168 CopyBits ( GetPortBitMapForCopyBits(src->hwdata->offscreen), | |
1169 GetPortBitMapForCopyBits(dst->hwdata->offscreen), | |
1170 &src_rect, &dst_rect, mode, NULL ); | |
1171 } | |
1172 #else | |
1173 | |
1174 CopyBits ( &(((GrafPtr)(src->hwdata->offscreen))->portBits), | |
1175 &(((GrafPtr)(dst->hwdata->offscreen))->portBits), | |
1176 &src_rect, &dst_rect, srcCopy, NULL ); | |
1177 | |
1178 #endif /* DSP_TRY_CC_AND_AA */ | |
1179 | |
1180 SetGWorld (save_port, save_device); | |
1181 | |
1182 return(0); | |
1183 } | |
1184 | |
1185 static int DSp_FillHWRect(_THIS, SDL_Surface *dst, SDL_Rect *rect, Uint32 color) | |
1186 { | |
1187 CGrafPtr save_port; | |
1188 GDHandle save_device; | |
1189 Rect fill_rect; | |
1190 RGBColor rgb; | |
1191 | |
1192 SetRect (&fill_rect, rect->x, rect->y, rect->x + rect->w, rect->y + rect->h); | |
1193 | |
1194 GetGWorld (&save_port, &save_device); | |
1195 SetGWorld (dst->hwdata->offscreen, NULL); | |
1196 | |
1197 Index2Color (color, &rgb); | |
1198 | |
1199 RGBForeColor (&rgb); | |
1200 PaintRect (&fill_rect); | |
1201 | |
1202 SetGWorld (save_port, save_device); | |
1203 | |
1204 return(0); | |
1205 } | |
1206 | |
1207 static int DSp_FlipHWSurface(_THIS, SDL_Surface *surface) | |
1208 { | |
1209 if ( (surface->flags & SDL_HWSURFACE) ) { | |
1210 CGrafPtr dsp_front_buffer, save_port; | |
1211 Rect rect; | |
1212 | |
1213 unsigned int old_count; | |
1214 | |
1215 /* pseudo page flipping for VRAM back buffer*/ | |
1216 DSpContext_GetFrontBuffer (dsp_context, &dsp_front_buffer); | |
1217 SetRect (&rect, 0, 0, surface->w-1, surface->h-1); | |
1218 | |
1219 GetPort ((GrafPtr *)&save_port); | |
1220 SetPort ((GrafPtr)dsp_front_buffer); | |
1221 | |
1222 /* wait for retrace */ | |
1223 /* I have tried doing the swap in interrupt routine (VBL Proc) to do */ | |
1224 /* it asynchronously, but apparently CopyBits isn't interrupt safe */ | |
1225 | |
1226 #if ! TARGET_API_MAC_OSX | |
1227 #ifndef DSP_NO_SYNC_VBL | |
1228 old_count = retrace_count; | |
1229 while (old_count == retrace_count) | |
1230 ; | |
1231 #endif | |
1232 #endif | |
1233 | |
1234 CopyBits ( GetPortBitMapForCopyBits(dsp_back_buffer), | |
1235 GetPortBitMapForCopyBits(dsp_front_buffer), | |
1236 &rect, &rect, srcCopy, NULL ); | |
1237 | |
1238 SetPort ((GrafPtr)save_port); | |
1239 | |
1240 } else { | |
1241 /* not really page flipping at all: DSp just blits the dirty rectangles from DSp_UpdateRects */ | |
1242 Boolean busy_flag; | |
1243 DSpContext_SwapBuffers (dsp_context, NULL, &busy_flag); /* this waits for VBL */ | |
1244 DSpContext_GetBackBuffer (dsp_context, kDSpBufferKind_Normal, &dsp_back_buffer); | |
1245 surface->pixels = GetPixBaseAddr( GetPortPixMap(dsp_back_buffer) ); | |
1246 } | |
1247 return(0); | |
1248 } | |
1249 | |
1250 static int DSp_LockHWSurface(_THIS, SDL_Surface *surface) | |
1251 { | |
1252 if ( LockPixels (GetGWorldPixMap (surface->hwdata->offscreen)) ) | |
1253 return 0; | |
1254 else | |
1255 return -1; | |
1256 } | |
1257 | |
1258 static void DSp_UnlockHWSurface(_THIS, SDL_Surface *surface) | |
1259 { | |
1260 UnlockPixels (GetGWorldPixMap (surface->hwdata->offscreen)); | |
1261 } | |
1262 | |
1263 static void DSp_DirectUpdate(_THIS, int numrects, SDL_Rect *sdl_rects) | |
1264 { | |
1265 return; | |
1266 } | |
1267 | |
1268 static void DSp_DSpUpdate(_THIS, int numrects, SDL_Rect *sdl_rects) | |
1269 { | |
1270 #if ! TARGET_API_MAC_OSX /* Unsupported DSp in here */ | |
1271 int i; | |
1272 Rect rect; | |
1273 | |
1274 for (i = 0; i < numrects; i++) { | |
1275 | |
1276 rect.top = sdl_rects[i].y; | |
1277 rect.left = sdl_rects[i].x; | |
1278 rect.bottom = sdl_rects[i].h + sdl_rects[i].y; | |
1279 rect.right = sdl_rects[i].w + sdl_rects[i].x; | |
1280 | |
1281 DSpContext_InvalBackBufferRect (dsp_context, &rect); | |
1282 } | |
1283 #endif | |
1284 } | |
1285 | |
1286 static int DSp_CreatePalette(_THIS) { | |
1287 | |
1288 | |
1289 /* Create our palette */ | |
1290 SDL_CTab = (CTabHandle)NewHandle(sizeof(ColorSpec)*256 + 8); | |
1291 if ( SDL_CTab == nil ) { | |
1292 SDL_OutOfMemory(); | |
1293 return(-1); | |
1294 } | |
1295 (**SDL_CTab).ctSeed = GetCTSeed(); | |
1296 (**SDL_CTab).ctFlags = 0; | |
1297 (**SDL_CTab).ctSize = 255; | |
1298 CTabChanged(SDL_CTab); | |
1299 SDL_CPal = NewPalette(256, SDL_CTab, pmExplicit+pmTolerant, 0); | |
1300 | |
1301 return 0; | |
1302 } | |
1303 | |
1304 static int DSp_DestroyPalette(_THIS) { | |
1305 | |
1306 /* Free palette and restore original one */ | |
1307 if ( SDL_CTab != nil ) { | |
1308 DisposeHandle((Handle)SDL_CTab); | |
1309 SDL_CTab = nil; | |
1310 } | |
1311 if ( SDL_CPal != nil ) { | |
1312 DisposePalette(SDL_CPal); | |
1313 SDL_CPal = nil; | |
1314 } | |
1315 RestoreDeviceClut(SDL_Display); | |
1316 | |
1317 return (0); | |
1318 } | |
1319 | |
1320 static int DSp_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors) | |
1321 { | |
1322 CTabHandle cTab; | |
1323 | |
1324 int i; | |
1325 | |
1326 cTab = SDL_CTab; | |
1327 | |
1328 /* Verify the range of colors */ | |
1329 if ( (firstcolor+ncolors) > ((**cTab).ctSize+1) ) { | |
1330 return(0); | |
1331 } | |
1332 | |
1333 /* Set the screen palette and update the display */ | |
1334 for(i = 0; i < ncolors; i++) { | |
1335 int j = firstcolor + i; | |
1336 (**cTab).ctTable[j].value = j; | |
1337 (**cTab).ctTable[j].rgb.red = colors[i].r << 8 | colors[i].r; | |
1338 (**cTab).ctTable[j].rgb.green = colors[i].g << 8 | colors[i].g; | |
1339 (**cTab).ctTable[j].rgb.blue = colors[i].b << 8 | colors[i].b; | |
1340 } | |
1341 | |
1342 SetGDevice(SDL_Display); | |
1343 SetEntries(0, (**cTab).ctSize, (ColorSpec *)&(**cTab).ctTable); | |
1344 | |
1345 return(1); | |
1346 } | |
1347 | |
1348 void DSp_VideoQuit(_THIS) | |
1349 { | |
1350 int i; | |
1351 | |
1352 /* Free current video mode */ | |
1353 DSp_UnsetVideoMode(this, this->screen); | |
1354 | |
1355 /* Free Palette and restore original */ | |
1356 DSp_DestroyPalette (this); | |
1357 | |
1358 /* Free list of video modes */ | |
1359 if ( SDL_modelist != NULL ) { | |
1360 for ( i=0; SDL_modelist[i]; i++ ) { | |
1361 free(SDL_modelist[i]); | |
1362 } | |
1363 free(SDL_modelist); | |
1364 SDL_modelist = NULL; | |
1365 } | |
1366 | |
1367 /* Unload DrawSprocket */ | |
1368 DSpShutdown (); | |
1369 } | |
1370 | |
1371 #ifdef HAVE_OPENGL | |
1372 | |
1373 /* swap buffers with v-sync */ | |
1374 static void DSp_GL_SwapBuffers (_THIS) { | |
1375 | |
1376 #ifndef DSP_NO_SYNC_OPENGL | |
1377 | |
1378 unsigned int old_count; | |
1379 | |
1380 old_count = retrace_count; | |
1381 while (old_count == retrace_count) | |
1382 ; | |
1383 #endif | |
1384 | |
1385 aglSwapBuffers (glContext); | |
1386 } | |
1387 | |
1388 #endif |