Mercurial > sdl-ios-xcode
annotate src/video/macdsp/SDL_dspvideo.c @ 934:af585d6efec8
Date: Thu, 17 Jun 2004 11:38:51 -0700 (PDT)
From: Eric Wing <ewing2121@yahoo.com>
Subject: New OS X patch (was Re: [SDL] Bug with inverted mouse coordinates in
I have a new patch for OS X I would like to submit.
First, it appears no further action has been taken on
my fix from Apple on the OpenGL windowed mode mouse
inversion problem. The fix would reunify the code, and
no longer require case checking for which version of
the OS you are running. This is probably a good fix
because the behavior with the old code could change
again with future versions of the OS, so those fixes
are included in this new patch.
But in addition, when I was at Apple, I asked them
about the ability to distinguish between the modifier
keys on the left and right sides of the keyboard (e.g.
Left Shift, Right Shift, Left/Right Alt, L/R Cmd, L/R
Ctrl). They told me that starting with Panther, the OS
began supporting this feature. This has always been a
source of annoyance for me when bringing a program
that comes from Windows or Linux to OS X when the
keybindings happened to need distinguishable left-side
and right-side keys. So the rest of the patch I am
submitting contains new code to support this feature
on Panther (and presumably later versions of the OS).
So after removing the OS version checks for the mouse
inversion problem, I reused the OS version checks to
activate the Left/Right detection of modifier keys. If
you are running Panther (or above), the new code will
attempt to distinguish between sides. For the older
OS's, the code path reverts to the original code.
I've tested with Panther on a G4 Cube, G5 dual
processor, and Powerbook Rev C. The Cube and G5
keyboards demonstrated the ability to distinguish
between sides. The Powerbook seems to only have
left-side keys, but the patch was still able to handle
it by producing the same results as before the patch.
I also wanted to test a non-Apple keyboard.
Unfortunately, I don't have any PC USB keyboards.
However, I was able to borrow a Sun Microsystems USB
keyboard, so I tried that out on the G5, and I got the
correct behavior for left and right sides. I'm
expecting that if it worked with a Sun keyboard, most
other keyboards should work with no problems.
author | Sam Lantinga <slouken@libsdl.org> |
---|---|
date | Fri, 20 Aug 2004 22:35:23 +0000 |
parents | b8d311d90021 |
children | c1c2efca4548 |
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; | |
301 #endif | |
302 device->SetCaption = NULL; | |
303 device->SetIcon = NULL; | |
304 device->IconifyWindow = NULL; | |
305 device->GrabInput = NULL; | |
306 device->GetWMInfo = NULL; | |
307 device->FreeWMCursor = Mac_FreeWMCursor; | |
308 device->CreateWMCursor = Mac_CreateWMCursor; | |
309 device->ShowWMCursor = Mac_ShowWMCursor; | |
310 device->WarpWMCursor = Mac_WarpWMCursor; | |
311 device->InitOSKeymap = Mac_InitOSKeymap; | |
312 device->PumpEvents = Mac_PumpEvents; | |
313 | |
314 device->GrabInput = NULL; | |
315 device->CheckMouseMode = NULL; | |
316 | |
317 device->free = DSp_DeleteDevice; | |
318 | |
319 return device; | |
320 } | |
321 | |
322 VideoBootStrap DSp_bootstrap = { | |
323 "DSp", "MacOS DrawSprocket", | |
324 DSp_Available, DSp_CreateDevice | |
325 }; | |
326 | |
327 /* Use DSp/Display Manager to build mode list for given screen */ | |
328 static SDL_Rect** DSp_BuildModeList (const GDHandle gDevice) | |
329 { | |
330 DSpContextAttributes attributes; | |
331 DSpContextReference context; | |
332 DisplayIDType displayID; | |
333 SDL_Rect temp_list [16]; | |
334 SDL_Rect **mode_list; | |
335 int width, height, i, j; | |
336 | |
337 #if TARGET_API_MAC_OSX | |
338 | |
339 displayID = 0; | |
340 | |
341 #else | |
342 /* Ask Display Manager for integer id of screen device */ | |
343 if ( DMGetDisplayIDByGDevice (gDevice, &displayID, SDL_TRUE) != noErr ) { | |
344 return NULL; | |
345 } | |
346 #endif | |
347 /* Get the first possible DSp context on this device */ | |
348 if ( DSpGetFirstContext (displayID, &context) != noErr ) { | |
349 return NULL; | |
350 } | |
351 | |
352 if ( DSpContext_GetAttributes (context, &attributes) != noErr ) | |
353 return NULL; | |
354 | |
355 for ( i = 0; i < SDL_TABLESIZE(temp_list); i++ ) { | |
356 width = attributes.displayWidth; | |
357 height = attributes.displayHeight; | |
358 | |
359 temp_list [i].x = 0 | attributes.displayBestDepth; | |
360 temp_list [i].y = 0; | |
361 temp_list [i].w = width; | |
362 temp_list [i].h = height; | |
363 | |
364 /* DSp will report many different contexts with the same width and height. */ | |
365 /* They will differ in bit depth and refresh rate. */ | |
366 /* We will ignore them until we reach one with a different width/height */ | |
367 /* When there are no more contexts to look at, we will quit building the list*/ | |
368 while ( width == attributes.displayWidth && height == attributes.displayHeight ) { | |
369 | |
370 OSStatus err = DSpGetNextContext (context, &context); | |
371 if (err != noErr) | |
372 if (err == kDSpContextNotFoundErr) | |
373 goto done; | |
374 else | |
375 return NULL; | |
376 | |
377 if ( DSpContext_GetAttributes (context, &attributes) != noErr ) | |
378 return NULL; | |
379 | |
380 temp_list [i].x |= attributes.displayBestDepth; | |
381 } | |
382 } | |
383 done: | |
384 i++; /* i was not incremented before kicking out of the loop */ | |
385 | |
386 mode_list = (SDL_Rect**) malloc (sizeof (SDL_Rect*) * (i+1)); | |
387 if (mode_list) { | |
388 | |
389 /* -dw- new stuff: build in reverse order so largest sizes list first */ | |
390 for (j = i-1; j >= 0; j--) { | |
391 mode_list [j] = (SDL_Rect*) malloc (sizeof (SDL_Rect)); | |
392 if (mode_list [j]) | |
393 memcpy (mode_list [j], &(temp_list [j]), sizeof (SDL_Rect)); | |
394 else { | |
395 SDL_OutOfMemory (); | |
396 return NULL; | |
397 } | |
398 } | |
399 mode_list [i] = NULL; /* append null to the end */ | |
400 } | |
401 else { | |
402 SDL_OutOfMemory (); | |
403 return NULL; | |
404 } | |
405 | |
406 return mode_list; | |
407 } | |
408 | |
409 static void DSp_IsHWAvailable (_THIS, SDL_PixelFormat *vformat) | |
410 { | |
411 /* | |
412 VRAM GWorlds are only available on OS 9 or later. | |
413 Even with OS 9, some display drivers won't support it, | |
414 so we create a test GWorld and check for errors. | |
415 */ | |
416 | |
417 long versionSystem; | |
418 | |
419 dsp_vram_available = SDL_FALSE; | |
420 dsp_agp_available = SDL_FALSE; | |
421 | |
422 Gestalt ('sysv', &versionSystem); | |
423 if (0x00000860 < (versionSystem & 0x0000FFFF)) { | |
424 | |
425 GWorldPtr offscreen; | |
426 OSStatus err; | |
427 Rect bounds; | |
428 | |
429 SetRect (&bounds, 0, 0, 320, 240); | |
430 | |
431 err = NewGWorld (&offscreen, vformat->BitsPerPixel, &bounds, NULL, SDL_Display, useDistantHdwrMem | noNewDevice); | |
432 if (err == noErr) { | |
433 dsp_vram_available = SDL_TRUE; | |
434 DisposeGWorld (offscreen); | |
435 } | |
436 | |
437 err = NewGWorld (&offscreen, vformat->BitsPerPixel, &bounds, NULL, SDL_Display, useLocalHdwrMem | noNewDevice); | |
438 if (err == noErr) { | |
439 DisposeGWorld (offscreen); | |
440 dsp_agp_available = SDL_TRUE; | |
441 } | |
442 } | |
443 } | |
444 | |
445 static int DSp_GetMainDevice (_THIS, GDHandle *device) | |
446 { | |
447 | |
448 #if TARGET_API_MAC_OSX | |
449 /* DSpUserSelectContext not available on OS X */ | |
450 *device = GetMainDevice(); | |
451 return 0; | |
452 #else | |
453 | |
454 DSpContextAttributes attrib; | |
455 DSpContextReference context; | |
456 DisplayIDType display_id; | |
457 GDHandle main_device; | |
458 GDHandle device_list; | |
459 | |
460 device_list = GetDeviceList (); | |
461 main_device = GetMainDevice (); | |
462 | |
463 /* Quick check to avoid slower method when only one display exists */ | |
464 if ( (**device_list).gdNextGD == NULL ) { | |
465 *device = main_device; | |
466 return 0; | |
467 } | |
468 | |
469 memset (&attrib, 0, sizeof (DSpContextAttributes)); | |
470 | |
471 /* These attributes are hopefully supported on all devices...*/ | |
472 attrib.displayWidth = 640; | |
473 attrib.displayHeight = 480; | |
474 attrib.displayBestDepth = 8; | |
475 attrib.backBufferBestDepth = 8; | |
476 attrib.displayDepthMask = kDSpDepthMask_All; | |
477 attrib.backBufferDepthMask = kDSpDepthMask_All; | |
478 attrib.colorNeeds = kDSpColorNeeds_Require; | |
479 attrib.pageCount = 1; | |
480 | |
481 if (noErr != DMGetDisplayIDByGDevice (main_device, &display_id, SDL_FALSE)) { | |
482 SDL_SetError ("Display Manager couldn't associate GDevice with a Display ID"); | |
483 return (-1); | |
484 } | |
485 | |
486 /* Put up dialog on main display to select which display to use */ | |
487 if (noErr != DSpUserSelectContext (&attrib, display_id, NULL, &context)) { | |
488 SDL_SetError ("DrawSprocket couldn't create a context"); | |
489 return (-1); | |
490 } | |
491 | |
492 if (noErr != DSpContext_GetDisplayID (context, &display_id)) { | |
493 SDL_SetError ("DrawSprocket couldn't get display ID"); | |
494 return (-1); | |
495 } | |
496 | |
497 if (noErr != DMGetGDeviceByDisplayID (display_id, &main_device, SDL_FALSE)) { | |
498 SDL_SetError ("Display Manager couldn't associate Display ID with GDevice"); | |
499 return (-1); | |
500 } | |
501 | |
502 *device = main_device; | |
503 return (0); | |
504 #endif | |
505 } | |
506 | |
507 static int DSp_VideoInit(_THIS, SDL_PixelFormat *vformat) | |
508 { | |
509 | |
510 NumVersion dsp_version = DSpGetVersion (); | |
511 | |
512 if ( (dsp_version.majorRev == 1 && dsp_version.minorAndBugRev < 0x73) || | |
513 (dsp_version.majorRev < 1) ) { | |
514 | |
515 /* StandardAlert (kAlertStopAlert, "\pError!", | |
516 "\pI need DrawSprocket 1.7.3 or later!\n" | |
517 "You can find a newer version at http://www.apple.com/swupdates.", | |
518 NULL, NULL); | |
519 */ | |
520 SDL_SetError ("DrawSprocket version is too old. Need 1.7.3 or later."); | |
521 return (-1); | |
522 } | |
523 | |
524 if ( DSpStartup () != noErr ) { | |
525 SDL_SetError ("DrawSprocket couldn't startup"); | |
526 return(-1); | |
527 } | |
528 | |
529 /* Start DSpintosh events */ | |
530 Mac_InitEvents(this); | |
531 | |
532 /* Get a handle to the main monitor, or choose one on multiple monitor setups */ | |
533 if ( DSp_GetMainDevice(this, &SDL_Display) < 0) | |
534 return (-1); | |
535 | |
536 /* Determine pixel format */ | |
537 vformat->BitsPerPixel = GetPixDepth ( (**SDL_Display).gdPMap ); | |
538 dsp_old_depth = vformat->BitsPerPixel; | |
539 | |
540 switch (vformat->BitsPerPixel) { | |
541 case 16: | |
542 vformat->Rmask = 0x00007c00; | |
543 vformat->Gmask = 0x000003e0; | |
544 vformat->Bmask = 0x0000001f; | |
545 break; | |
546 default: | |
547 break; | |
548 } | |
549 | |
550 if ( DSp_CreatePalette (this) < 0 ) { | |
551 | |
552 SDL_SetError ("Could not create palette"); | |
553 return (-1); | |
554 } | |
555 | |
556 /* Get a list of available fullscreen modes */ | |
557 SDL_modelist = DSp_BuildModeList (SDL_Display); | |
558 if (SDL_modelist == NULL) { | |
559 SDL_SetError ("DrawSprocket could not build a mode list"); | |
560 return (-1); | |
561 } | |
562 | |
563 /* Check for VRAM and AGP GWorlds for HW Blitting */ | |
564 DSp_IsHWAvailable (this, vformat); | |
565 | |
566 this->info.wm_available = 0; | |
567 | |
568 if (dsp_vram_available || dsp_agp_available) { | |
569 | |
570 this->info.hw_available = SDL_TRUE; | |
571 | |
572 this->CheckHWBlit = DSp_CheckHWBlit; | |
573 this->info.blit_hw = SDL_TRUE; | |
574 | |
575 this->FillHWRect = DSp_FillHWRect; | |
576 this->info.blit_fill = SDL_TRUE; | |
577 | |
578 #ifdef DSP_TRY_CC_AND_AA | |
579 this->SetHWColorKey = DSp_SetHWColorKey; | |
580 this->info.blit_hw_CC = SDL_TRUE; | |
581 | |
582 this->SetHWAlpha = DSp_SetHWAlpha; | |
583 this->info.blit_hw_A = SDL_TRUE; | |
584 #endif | |
585 | |
586 } | |
587 | |
588 return(0); | |
589 } | |
590 | |
591 static SDL_Rect **DSp_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags) | |
592 { | |
593 static SDL_Rect *dsp_modes[16]; | |
594 int i = 0, j = 0; | |
595 | |
596 if ( format->BitsPerPixel == 0 ) | |
597 return ( (SDL_Rect**) NULL ); | |
598 | |
599 while (SDL_modelist[i] != NULL) { | |
600 | |
601 if (SDL_modelist[i]->x & format->BitsPerPixel) { | |
602 dsp_modes[j] = SDL_modelist[i]; | |
603 j++; | |
604 } | |
605 i++; | |
606 } | |
607 | |
608 dsp_modes[j] = NULL; | |
609 | |
610 return dsp_modes; | |
611 } | |
612 | |
613 /* Various screen update functions available */ | |
614 static void DSp_DirectUpdate(_THIS, int numrects, SDL_Rect *rects); | |
615 | |
616 static volatile unsigned int retrace_count = 0; /* -dw- need volatile because it updates asychronously */ | |
617 | |
618 #if ! TARGET_API_MAC_OSX | |
619 Boolean DSp_VBLProc ( DSpContextReference context, void *ref_con ) | |
620 { | |
621 retrace_count++; | |
622 | |
623 return 1; /* Darrell, is this right? */ | |
624 } | |
625 #endif | |
626 | |
627 static void DSp_SetHWError (OSStatus err, int is_agp) | |
628 { | |
629 char message[1024]; | |
630 const char *fmt, *mem; | |
631 | |
632 if ( is_agp ) { | |
633 mem = "AGP Memory"; | |
634 } else { | |
635 mem = "VRAM"; | |
636 } | |
637 switch(err) { | |
638 case memFullErr: | |
639 fmt = "Hardware surface possible but not enough %s available"; | |
640 break; | |
641 case cDepthErr: | |
642 fmt = "Hardware surface possible but invalid color depth"; | |
643 break; | |
644 default: | |
645 fmt = "Hardware surface could not be allocated in %s - unknown error"; | |
646 break; | |
647 } | |
648 sprintf(message, fmt, mem); | |
649 SDL_SetError(message); | |
650 } | |
651 | |
652 /* put up a dialog to verify display change */ | |
653 static int DSp_ConfirmSwitch () { | |
654 | |
655 /* resource id's for dialog */ | |
656 const int rDialog = 1002; | |
657 const int bCancel = 1; | |
658 const int bOK = 2; | |
659 | |
660 DialogPtr dialog; | |
661 OSStatus err; | |
662 SInt32 response; | |
663 DialogItemIndex item = 0; | |
664 GrafPtr savePort; | |
665 | |
666 GetPort (&savePort); | |
667 | |
668 dialog = GetNewDialog (rDialog, NULL, (WindowPtr) -1); | |
669 if (dialog == NULL) | |
670 return (0); | |
671 | |
672 SetPort (dialog); | |
673 | |
674 SetDialogDefaultItem (dialog, bCancel); | |
675 SetDialogCancelItem (dialog, bCancel); | |
676 | |
677 SetEventMask (everyEvent); | |
678 FlushEvents (everyEvent, 0); | |
679 | |
680 /* On MacOS 8.5 or later, we can make the dialog go away after 15 seconds */ | |
681 /* This is good since it's possible user can't even see the dialog! */ | |
682 /* Requires linking to DialogsLib */ | |
683 err = Gestalt(gestaltSystemVersion,&response); | |
684 if (err == noErr && response >= 0x00000850) { | |
685 SetDialogTimeout(dialog, bCancel, 15); | |
686 } | |
687 | |
688 do { | |
689 | |
690 ModalDialog ( NULL, &item ); | |
691 | |
692 } while ( item != bCancel && item != bOK && err != noErr); | |
693 | |
694 DisposeWindow (dialog); | |
695 SetPort (savePort); | |
696 | |
697 SetEventMask(everyEvent - autoKeyMask); | |
698 FlushEvents(everyEvent, 0); | |
699 | |
700 return (item - 1); | |
701 } | |
702 | |
703 static void DSp_UnsetVideoMode(_THIS, SDL_Surface *current) | |
704 { | |
705 | |
706 | |
707 if ( current->flags & SDL_OPENGL ) { | |
708 Mac_GL_Quit (this); | |
709 } | |
710 | |
711 if (dsp_context != NULL) { | |
712 | |
713 GWorldPtr front; | |
714 DSpContext_GetFrontBuffer (dsp_context, &front); | |
715 | |
716 if (front != dsp_back_buffer) | |
717 DisposeGWorld (dsp_back_buffer); | |
718 | |
719 if (current->hwdata) | |
720 free (current->hwdata); | |
721 | |
722 DSpContext_SetState (dsp_context, kDSpContextState_Inactive ); | |
723 DSpContext_Release (dsp_context); | |
724 | |
725 dsp_context = NULL; | |
726 } | |
727 | |
728 if (SDL_Window != NULL) { | |
729 DisposeWindow (SDL_Window); | |
730 SDL_Window = NULL; | |
731 } | |
732 | |
733 current->pixels = NULL; | |
734 current->flags = 0; | |
735 } | |
736 | |
737 static SDL_Surface *DSp_SetVideoMode(_THIS, | |
738 SDL_Surface *current, int width, int height, int bpp, Uint32 flags) | |
739 { | |
740 | |
741 DisplayIDType display_id; | |
742 DSpContextAttributes attrib; | |
743 Fixed freq; | |
744 OSStatus err; | |
745 UInt32 rmask = 0, gmask = 0, bmask = 0; | |
746 | |
747 int page_count; | |
748 int double_buf; | |
749 int hw_surface; | |
750 int use_dsp_back_buffer; | |
751 | |
752 DSp_UnsetVideoMode (this, current); | |
753 | |
754 if (bpp != dsp_old_depth) | |
755 DSp_DestroyPalette (this); | |
756 | |
757 double_buf = (flags & SDL_DOUBLEBUF) != 0; | |
758 hw_surface = (flags & SDL_HWSURFACE) != 0; | |
759 use_dsp_back_buffer = !dsp_vram_available || !hw_surface ; | |
760 | |
761 current->flags |= SDL_FULLSCREEN; | |
762 | |
763 rebuild: | |
764 | |
765 if ( double_buf && use_dsp_back_buffer ) { | |
766 page_count = 2; | |
767 } else { | |
768 page_count = 1; | |
769 } | |
770 | |
771 memset (&attrib, 0, sizeof (DSpContextAttributes)); | |
772 attrib.displayWidth = width; | |
773 attrib.displayHeight = height; | |
774 attrib.displayBestDepth = bpp; | |
775 attrib.backBufferBestDepth = bpp; | |
776 attrib.displayDepthMask = kDSpDepthMask_All; | |
777 attrib.backBufferDepthMask = kDSpDepthMask_All; | |
778 attrib.colorNeeds = kDSpColorNeeds_Require; | |
779 attrib.colorTable = 0; | |
780 attrib.pageCount = page_count; | |
781 #if TARGET_API_MAC_OSX | |
782 | |
783 if ( DSpFindBestContext (&attrib, &dsp_context) != noErr ) { | |
784 SDL_SetError ("DrawSprocket couldn't find a context"); | |
785 return NULL; | |
786 } | |
787 | |
788 #else | |
789 if ( noErr != DMGetDisplayIDByGDevice (SDL_Display, &display_id, SDL_FALSE) ) { | |
790 SDL_SetError ("Display Manager couldn't associate GDevice with display_id"); | |
791 return NULL; | |
792 } | |
793 if ( DSpFindBestContextOnDisplayID (&attrib, &dsp_context, display_id) != noErr ) { | |
794 SDL_SetError ("DrawSprocket couldn't find a suitable context on given display"); | |
795 return NULL; | |
796 } | |
797 | |
798 #endif | |
799 if ( DSpContext_Reserve (dsp_context, &attrib) != noErr ) { | |
800 SDL_SetError ("DrawSprocket couldn't get the needed resources to build the display"); | |
801 return NULL; | |
802 } | |
803 | |
804 if ( (err = DSpContext_SetState (dsp_context, kDSpContextState_Active)) != noErr ) { | |
805 | |
806 if (err == kDSpConfirmSwitchWarning) { | |
807 | |
808 if ( ! DSp_ConfirmSwitch () ) { | |
809 | |
810 DSpContext_Release (dsp_context); | |
811 dsp_context = NULL; | |
812 SDL_SetError ("User cancelled display switch"); | |
813 return NULL; | |
814 } | |
815 else | |
816 /* Have to reactivate context. Why? */ | |
817 DSpContext_SetState (dsp_context, kDSpContextState_Active); | |
818 | |
819 } | |
820 else { | |
821 SDL_SetError ("DrawSprocket couldn't activate the context"); | |
822 return NULL; | |
823 } | |
824 } | |
825 | |
826 | |
827 if (bpp != dsp_old_depth) { | |
828 | |
829 DSp_CreatePalette (this); | |
830 | |
831 /* update format if display depth changed */ | |
832 if (bpp == 16) { | |
833 | |
834 rmask = 0x00007c00; | |
835 gmask = 0x000003e0; | |
836 bmask = 0x0000001f; | |
837 } | |
838 if ( ! SDL_ReallocFormat (current, bpp, rmask, gmask, bmask, 0 ) ) { | |
839 | |
840 SDL_SetError ("Could not reallocate video format."); | |
841 return(NULL); | |
842 } | |
843 } | |
844 | |
845 if (!double_buf) { | |
846 | |
847 /* single-buffer context */ | |
848 DSpContext_GetFrontBuffer (dsp_context, &dsp_back_buffer); | |
849 | |
850 current->hwdata = (private_hwdata*) malloc (sizeof (private_hwdata)); | |
851 if (current ->hwdata == NULL) { | |
852 SDL_OutOfMemory (); | |
853 return NULL; | |
854 } | |
855 current->hwdata->offscreen = dsp_back_buffer; | |
856 current->flags |= SDL_HWSURFACE; | |
857 this->UpdateRects = DSp_DirectUpdate; | |
858 } | |
859 else if ( use_dsp_back_buffer ) { | |
860 | |
861 DSpContext_GetBackBuffer (dsp_context, kDSpBufferKind_Normal, &dsp_back_buffer); | |
862 | |
863 current->flags |= SDL_DOUBLEBUF | SDL_SWSURFACE; /* only front buffer is in VRAM */ | |
864 this->UpdateRects = DSp_DSpUpdate; | |
865 } | |
866 else if ( DSp_NewHWSurface(this, &dsp_back_buffer, bpp, width-1, height-1) == 0 ) { | |
867 | |
868 current->hwdata = (private_hwdata*) malloc (sizeof (private_hwdata)); | |
869 if (current ->hwdata == NULL) { | |
870 SDL_OutOfMemory (); | |
871 return NULL; | |
872 } | |
873 | |
874 memset (current->hwdata, 0, sizeof (private_hwdata)); | |
875 current->hwdata->offscreen = dsp_back_buffer; | |
876 current->flags |= SDL_DOUBLEBUF | SDL_HWSURFACE; | |
877 this->UpdateRects = DSp_DirectUpdate; /* hardware doesn't do update rects, must be page-flipped */ | |
878 } | |
879 else { | |
880 | |
881 DSpContext_Release (dsp_context); | |
882 use_dsp_back_buffer = SDL_TRUE; | |
883 goto rebuild; | |
884 } | |
885 | |
886 current->pitch = GetPortPixRowBytes(dsp_back_buffer) & 0x3FFF; | |
887 current->pixels = GetPixBaseAddr(GetPortPixMap(dsp_back_buffer)); | |
888 | |
889 current->w = width; | |
890 current->h = height; | |
891 | |
892 #if ! TARGET_API_MAC_OSX | |
893 | |
894 if (use_dsp_back_buffer) { | |
895 | |
896 DSpContext_GetMonitorFrequency (dsp_context, &freq); | |
897 DSpContext_SetMaxFrameRate (dsp_context, freq >> 16); | |
898 } | |
899 | |
900 | |
901 if ( (current->flags & SDL_HWSURFACE) || (current->flags & SDL_OPENGL) ) | |
902 DSpContext_SetVBLProc (dsp_context, DSp_VBLProc, NULL); | |
903 #endif | |
904 | |
905 if (bpp == 8) | |
906 current->flags |= SDL_HWPALETTE; | |
907 | |
908 if (flags & SDL_OPENGL) { | |
909 | |
910 Rect rect; | |
911 RGBColor rgb = { 0.0, 0.0, 0.0 }; | |
912 GrafPtr save_port; | |
913 | |
914 SetRect (&rect, 0, 0, width, height); | |
915 SDL_Window = NewCWindow(nil, &( (**SDL_Display).gdRect), "\p", SDL_TRUE, plainDBox, (WindowPtr)-1, SDL_FALSE, 0); | |
916 | |
917 if (SDL_Window == NULL) { | |
918 | |
919 SDL_SetError ("DSp_SetVideoMode : OpenGL window could not be created."); | |
920 return NULL; | |
921 } | |
922 | |
923 /* Set window color to black to avoid white flash*/ | |
924 GetPort (&save_port); | |
925 SetPort (SDL_Window); | |
926 RGBForeColor (&rgb); | |
927 PaintRect (&rect); | |
928 SetPort (save_port); | |
929 | |
930 SetPortWindowPort (SDL_Window); | |
931 SelectWindow (SDL_Window); | |
932 | |
933 if ( Mac_GL_Init (this) < 0 ) { | |
934 | |
935 SDL_SetError ("DSp_SetVideoMode : could not create OpenGL context."); | |
936 return NULL; | |
937 } | |
938 | |
939 current->flags |= SDL_OPENGL; | |
940 } | |
941 | |
942 return current; | |
943 } | |
944 | |
945 #ifdef DSP_TRY_CC_AND_AA | |
946 | |
947 static int DSp_MakeHWMask (_THIS, SDL_Surface *surface) | |
948 { | |
949 GDHandle save_device; | |
950 CGrafPtr save_port; | |
951 GWorldPtr temp; | |
952 RGBColor black = { 0, 0, 0 }; | |
953 RGBColor white = { 0xFFFF, 0xFFFF, 0xFFFF }; | |
954 Rect rect; | |
955 | |
956 Uint32 depth = GetPixDepth ( GetGDevPixMap (SDL_Display) ); | |
957 | |
958 SetRect (&rect, 0, 0, surface->w, surface->h); | |
959 | |
960 if ( noErr != NewGWorld (&(surface->hwdata->mask), depth, &rect, 0, SDL_Display, 0 ) < 0 ) { | |
961 | |
962 SDL_OutOfMemory (); | |
963 return (-1); | |
964 } | |
965 | |
966 if ( noErr != NewGWorld (&temp, depth, &rect, 0 , SDL_Display, 0 ) ) { | |
967 | |
968 SDL_OutOfMemory (); | |
969 return (-1); | |
970 } | |
971 | |
972 | |
973 GetGWorld (&save_port, &save_device); | |
974 SetGWorld (surface->hwdata->mask, SDL_Display); | |
975 | |
976 RGBForeColor (&white); | |
977 PaintRect (&rect); | |
978 | |
979 RGBBackColor (&(surface->hwdata->trans)); | |
980 | |
981 CopyBits ( GetPortBitMapForCopyBits(surface->hwdata->offscreen), | |
982 GetPortBitMapForCopyBits(surface->hwdata->mask), | |
983 &rect, &rect, transparent, NULL ); | |
984 | |
985 SetGWorld (surface->hwdata->mask, SDL_Display); | |
986 SetGWorld (save_port, save_device); | |
987 return (0); | |
988 } | |
989 | |
990 static int DSp_SetHWAlpha(_THIS, SDL_Surface *surface, UInt8 alpha) | |
991 { | |
992 surface->hwdata->alpha.red = (alpha / 255.0) * 65535; | |
993 surface->hwdata->alpha.blue = (alpha / 255.0) * 65535; | |
994 surface->hwdata->alpha.green = (alpha / 255.0) * 65535; | |
995 | |
996 surface->flags |= SDL_SRCALPHA; | |
997 | |
998 if (surface->flags & SDL_SRCCOLORKEY) { | |
999 return(DSp_MakeHWMask (this, surface)); | |
1000 } | |
1001 return(0); | |
1002 } | |
1003 | |
1004 static int DSp_SetHWColorKey(_THIS, SDL_Surface *surface, Uint32 key) | |
1005 { | |
1006 CGrafPtr save_port; | |
1007 GDHandle save_device; | |
1008 | |
1009 GetGWorld (&save_port, &save_device); | |
1010 SetGWorld (surface->hwdata->offscreen, NULL); | |
1011 | |
1012 Index2Color (key, &(surface->hwdata->trans)); | |
1013 surface->flags |= SDL_SRCCOLORKEY; | |
1014 | |
1015 SetGWorld (save_port, save_device); | |
1016 | |
1017 if ( surface->flags & SDL_SRCALPHA ) { | |
1018 return(DSp_MakeHWMask (this, surface)); | |
1019 } | |
1020 return(0); | |
1021 } | |
1022 | |
1023 #endif /* DSP_TRY_CC_AND_AA */ | |
1024 | |
1025 static int DSp_NewHWSurface(_THIS, CGrafPtr *port, int depth, int width, int height) { | |
1026 | |
1027 OSStatus err; | |
1028 Rect bounds; | |
1029 | |
1030 SetRect (&bounds, 0, 0, width, height); | |
1031 | |
1032 if (dsp_vram_available) { | |
1033 /* try VRAM */ | |
1034 err = NewGWorld (port, depth, &bounds, 0 , SDL_Display, useDistantHdwrMem | noNewDevice ); | |
1035 if (err != noErr) | |
1036 DSp_SetHWError (err, SDL_FALSE); | |
1037 else | |
1038 return (0); | |
1039 } | |
1040 | |
1041 if (dsp_agp_available) { | |
1042 /* try AGP */ | |
1043 err = NewGWorld (port, depth, &bounds, 0 , SDL_Display, useLocalHdwrMem | noNewDevice ); | |
1044 | |
1045 if (err != noErr) | |
1046 DSp_SetHWError (err, SDL_TRUE); | |
1047 else | |
1048 return (0); | |
1049 } | |
1050 | |
1051 return (-1); | |
1052 } | |
1053 | |
1054 static int DSp_AllocHWSurface(_THIS, SDL_Surface *surface) | |
1055 { | |
1056 GWorldPtr temp; | |
1057 | |
1058 if ( DSp_NewHWSurface (this, &temp, surface->format->BitsPerPixel, surface->w, surface->h) < 0 ) | |
1059 return (-1); | |
1060 | |
1061 surface->hwdata = (private_hwdata*) malloc (sizeof (private_hwdata)); | |
1062 if (surface->hwdata == NULL) { | |
1063 SDL_OutOfMemory (); | |
1064 return -1; | |
1065 } | |
1066 | |
1067 memset (surface->hwdata, 0, sizeof(private_hwdata)); | |
1068 surface->hwdata->offscreen = temp; | |
1069 surface->pitch = GetPixRowBytes (GetPortPixMap (temp)) & 0x3FFF; | |
1070 surface->pixels = GetPixBaseAddr (GetPortPixMap (temp)); | |
1071 surface->flags |= SDL_HWSURFACE; | |
1072 #ifdef DSP_TRY_CC_AND_AA | |
1073 surface->flags |= SDL_HWACCEL; | |
1074 #endif | |
1075 return 0; | |
1076 } | |
1077 | |
1078 static void DSp_FreeHWSurface(_THIS, SDL_Surface *surface) | |
1079 { | |
1080 if (surface->hwdata->offscreen != NULL) | |
1081 DisposeGWorld (surface->hwdata->offscreen); | |
1082 free (surface->hwdata); | |
1083 | |
1084 surface->pixels = NULL; | |
1085 } | |
1086 | |
1087 static int DSp_CheckHWBlit(_THIS, SDL_Surface *src, SDL_Surface *dest) | |
1088 { | |
1089 int accelerated; | |
1090 | |
1091 /* Set initial acceleration on */ | |
1092 src->flags |= SDL_HWACCEL; | |
1093 | |
1094 /* Set the surface attributes */ | |
1095 if ( (src->flags & SDL_SRCALPHA) == SDL_SRCALPHA ) { | |
1096 if ( ! this->info.blit_hw_A ) { | |
1097 src->flags &= ~SDL_HWACCEL; | |
1098 } | |
1099 } | |
1100 if ( (src->flags & SDL_SRCCOLORKEY) == SDL_SRCCOLORKEY ) { | |
1101 if ( ! this->info.blit_hw_CC ) { | |
1102 src->flags &= ~SDL_HWACCEL; | |
1103 } | |
1104 } | |
1105 | |
1106 /* Check to see if final surface blit is accelerated */ | |
1107 accelerated = !!(src->flags & SDL_HWACCEL); | |
1108 if ( accelerated ) { | |
1109 src->map->hw_blit = DSp_HWAccelBlit; | |
1110 } | |
1111 return(accelerated); | |
1112 } | |
1113 | |
1114 static int DSp_HWAccelBlit(SDL_Surface *src, SDL_Rect *srcrect, | |
1115 SDL_Surface *dst, SDL_Rect *dstrect) | |
1116 { | |
1117 CGrafPtr save_port; | |
1118 GDHandle save_device; | |
1119 Rect src_rect, dst_rect; | |
1120 RGBColor black = { 0, 0, 0 }; | |
1121 RGBColor white = { 0xFFFF, 0xFFFF, 0xFFFF }; | |
1122 | |
1123 #ifdef DSP_TRY_CC_AND_AA | |
1124 UInt32 mode; | |
1125 #endif | |
1126 | |
1127 SetRect (&src_rect, srcrect->x, srcrect->y, srcrect->x + srcrect->w, srcrect->y + srcrect->h); | |
1128 SetRect (&dst_rect, dstrect->x, dstrect->y, dstrect->x + dstrect->w, dstrect->y + dstrect->h); | |
1129 | |
1130 GetGWorld (&save_port, &save_device); | |
1131 SetGWorld (dst->hwdata->offscreen, NULL); | |
1132 | |
1133 RGBForeColor (&black); | |
1134 RGBBackColor (&white); | |
1135 | |
1136 #ifdef DSP_TRY_CC_AND_AA | |
1137 | |
1138 if ( (src->flags & SDL_SRCCOLORKEY) && | |
1139 (src->flags & SDL_SRCALPHA) ) { | |
1140 | |
1141 OpColor (&(src->hwdata->alpha)); | |
1142 | |
1143 CopyDeepMask ( GetPortBitMapForCopyBits(src->hwdata->offscreen), | |
1144 GetPortBitMapForCopyBits(src->hwdata->mask), | |
1145 GetPortBitMapForCopyBits(dst->hwdata->offscreen), | |
1146 &src_rect, &src_rect, &dst_rect, | |
1147 blend, | |
1148 NULL ); | |
1149 } | |
1150 else { | |
1151 | |
1152 if ( src->flags & SDL_SRCCOLORKEY) { | |
1153 RGBBackColor (&(src->hwdata->trans) ); | |
1154 mode = transparent; | |
1155 } | |
1156 else if (src->flags & SDL_SRCALPHA) { | |
1157 | |
1158 OpColor (&(src->hwdata->alpha)); | |
1159 mode = blend; | |
1160 } | |
1161 else { | |
1162 | |
1163 mode = srcCopy; | |
1164 } | |
1165 | |
1166 CopyBits ( GetPortBitMapForCopyBits(src->hwdata->offscreen), | |
1167 GetPortBitMapForCopyBits(dst->hwdata->offscreen), | |
1168 &src_rect, &dst_rect, mode, NULL ); | |
1169 } | |
1170 #else | |
1171 | |
1172 CopyBits ( &(((GrafPtr)(src->hwdata->offscreen))->portBits), | |
1173 &(((GrafPtr)(dst->hwdata->offscreen))->portBits), | |
1174 &src_rect, &dst_rect, srcCopy, NULL ); | |
1175 | |
1176 #endif /* DSP_TRY_CC_AND_AA */ | |
1177 | |
1178 SetGWorld (save_port, save_device); | |
1179 | |
1180 return(0); | |
1181 } | |
1182 | |
1183 static int DSp_FillHWRect(_THIS, SDL_Surface *dst, SDL_Rect *rect, Uint32 color) | |
1184 { | |
1185 CGrafPtr save_port; | |
1186 GDHandle save_device; | |
1187 Rect fill_rect; | |
1188 RGBColor rgb; | |
1189 | |
1190 SetRect (&fill_rect, rect->x, rect->y, rect->x + rect->w, rect->y + rect->h); | |
1191 | |
1192 GetGWorld (&save_port, &save_device); | |
1193 SetGWorld (dst->hwdata->offscreen, NULL); | |
1194 | |
1195 Index2Color (color, &rgb); | |
1196 | |
1197 RGBForeColor (&rgb); | |
1198 PaintRect (&fill_rect); | |
1199 | |
1200 SetGWorld (save_port, save_device); | |
1201 | |
1202 return(0); | |
1203 } | |
1204 | |
1205 static int DSp_FlipHWSurface(_THIS, SDL_Surface *surface) | |
1206 { | |
1207 if ( (surface->flags & SDL_HWSURFACE) ) { | |
1208 CGrafPtr dsp_front_buffer, save_port; | |
1209 Rect rect; | |
1210 | |
1211 unsigned int old_count; | |
1212 | |
1213 /* pseudo page flipping for VRAM back buffer*/ | |
1214 DSpContext_GetFrontBuffer (dsp_context, &dsp_front_buffer); | |
1215 SetRect (&rect, 0, 0, surface->w-1, surface->h-1); | |
1216 | |
1217 GetPort ((GrafPtr *)&save_port); | |
1218 SetPort ((GrafPtr)dsp_front_buffer); | |
1219 | |
1220 /* wait for retrace */ | |
1221 /* I have tried doing the swap in interrupt routine (VBL Proc) to do */ | |
1222 /* it asynchronously, but apparently CopyBits isn't interrupt safe */ | |
1223 | |
1224 #if ! TARGET_API_MAC_OSX | |
1225 #ifndef DSP_NO_SYNC_VBL | |
1226 old_count = retrace_count; | |
1227 while (old_count == retrace_count) | |
1228 ; | |
1229 #endif | |
1230 #endif | |
1231 | |
1232 CopyBits ( GetPortBitMapForCopyBits(dsp_back_buffer), | |
1233 GetPortBitMapForCopyBits(dsp_front_buffer), | |
1234 &rect, &rect, srcCopy, NULL ); | |
1235 | |
1236 SetPort ((GrafPtr)save_port); | |
1237 | |
1238 } else { | |
1239 /* not really page flipping at all: DSp just blits the dirty rectangles from DSp_UpdateRects */ | |
1240 Boolean busy_flag; | |
1241 DSpContext_SwapBuffers (dsp_context, NULL, &busy_flag); /* this waits for VBL */ | |
1242 DSpContext_GetBackBuffer (dsp_context, kDSpBufferKind_Normal, &dsp_back_buffer); | |
1243 surface->pixels = GetPixBaseAddr( GetPortPixMap(dsp_back_buffer) ); | |
1244 } | |
1245 return(0); | |
1246 } | |
1247 | |
1248 static int DSp_LockHWSurface(_THIS, SDL_Surface *surface) | |
1249 { | |
1250 if ( LockPixels (GetGWorldPixMap (surface->hwdata->offscreen)) ) | |
1251 return 0; | |
1252 else | |
1253 return -1; | |
1254 } | |
1255 | |
1256 static void DSp_UnlockHWSurface(_THIS, SDL_Surface *surface) | |
1257 { | |
1258 UnlockPixels (GetGWorldPixMap (surface->hwdata->offscreen)); | |
1259 } | |
1260 | |
1261 static void DSp_DirectUpdate(_THIS, int numrects, SDL_Rect *sdl_rects) | |
1262 { | |
1263 return; | |
1264 } | |
1265 | |
1266 static void DSp_DSpUpdate(_THIS, int numrects, SDL_Rect *sdl_rects) | |
1267 { | |
1268 #if ! TARGET_API_MAC_OSX /* Unsupported DSp in here */ | |
1269 int i; | |
1270 Rect rect; | |
1271 | |
1272 for (i = 0; i < numrects; i++) { | |
1273 | |
1274 rect.top = sdl_rects[i].y; | |
1275 rect.left = sdl_rects[i].x; | |
1276 rect.bottom = sdl_rects[i].h + sdl_rects[i].y; | |
1277 rect.right = sdl_rects[i].w + sdl_rects[i].x; | |
1278 | |
1279 DSpContext_InvalBackBufferRect (dsp_context, &rect); | |
1280 } | |
1281 #endif | |
1282 } | |
1283 | |
1284 static int DSp_CreatePalette(_THIS) { | |
1285 | |
1286 | |
1287 /* Create our palette */ | |
1288 SDL_CTab = (CTabHandle)NewHandle(sizeof(ColorSpec)*256 + 8); | |
1289 if ( SDL_CTab == nil ) { | |
1290 SDL_OutOfMemory(); | |
1291 return(-1); | |
1292 } | |
1293 (**SDL_CTab).ctSeed = GetCTSeed(); | |
1294 (**SDL_CTab).ctFlags = 0; | |
1295 (**SDL_CTab).ctSize = 255; | |
1296 CTabChanged(SDL_CTab); | |
1297 SDL_CPal = NewPalette(256, SDL_CTab, pmExplicit+pmTolerant, 0); | |
1298 | |
1299 return 0; | |
1300 } | |
1301 | |
1302 static int DSp_DestroyPalette(_THIS) { | |
1303 | |
1304 /* Free palette and restore original one */ | |
1305 if ( SDL_CTab != nil ) { | |
1306 DisposeHandle((Handle)SDL_CTab); | |
1307 SDL_CTab = nil; | |
1308 } | |
1309 if ( SDL_CPal != nil ) { | |
1310 DisposePalette(SDL_CPal); | |
1311 SDL_CPal = nil; | |
1312 } | |
1313 RestoreDeviceClut(SDL_Display); | |
1314 | |
1315 return (0); | |
1316 } | |
1317 | |
1318 static int DSp_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors) | |
1319 { | |
1320 CTabHandle cTab; | |
1321 | |
1322 int i; | |
1323 | |
1324 cTab = SDL_CTab; | |
1325 | |
1326 /* Verify the range of colors */ | |
1327 if ( (firstcolor+ncolors) > ((**cTab).ctSize+1) ) { | |
1328 return(0); | |
1329 } | |
1330 | |
1331 /* Set the screen palette and update the display */ | |
1332 for(i = 0; i < ncolors; i++) { | |
1333 int j = firstcolor + i; | |
1334 (**cTab).ctTable[j].value = j; | |
1335 (**cTab).ctTable[j].rgb.red = colors[i].r << 8 | colors[i].r; | |
1336 (**cTab).ctTable[j].rgb.green = colors[i].g << 8 | colors[i].g; | |
1337 (**cTab).ctTable[j].rgb.blue = colors[i].b << 8 | colors[i].b; | |
1338 } | |
1339 | |
1340 SetGDevice(SDL_Display); | |
1341 SetEntries(0, (**cTab).ctSize, (ColorSpec *)&(**cTab).ctTable); | |
1342 | |
1343 return(1); | |
1344 } | |
1345 | |
1346 void DSp_VideoQuit(_THIS) | |
1347 { | |
1348 int i; | |
1349 | |
1350 /* Free current video mode */ | |
1351 DSp_UnsetVideoMode(this, this->screen); | |
1352 | |
1353 /* Free Palette and restore original */ | |
1354 DSp_DestroyPalette (this); | |
1355 | |
1356 /* Free list of video modes */ | |
1357 if ( SDL_modelist != NULL ) { | |
1358 for ( i=0; SDL_modelist[i]; i++ ) { | |
1359 free(SDL_modelist[i]); | |
1360 } | |
1361 free(SDL_modelist); | |
1362 SDL_modelist = NULL; | |
1363 } | |
1364 | |
1365 /* Unload DrawSprocket */ | |
1366 DSpShutdown (); | |
1367 } | |
1368 | |
1369 #ifdef HAVE_OPENGL | |
1370 | |
1371 /* swap buffers with v-sync */ | |
1372 static void DSp_GL_SwapBuffers (_THIS) { | |
1373 | |
1374 #ifndef DSP_NO_SYNC_OPENGL | |
1375 | |
1376 unsigned int old_count; | |
1377 | |
1378 old_count = retrace_count; | |
1379 while (old_count == retrace_count) | |
1380 ; | |
1381 #endif | |
1382 | |
1383 aglSwapBuffers (glContext); | |
1384 } | |
1385 | |
1386 #endif |