Mercurial > sdl-ios-xcode
annotate src/video/macdsp/SDL_dspvideo.c @ 1135:cf6133247d34
Mac Classic and CodeWarrior patches.
--ryan.
From: =?ISO-8859-1?Q?Anders_F_Bj=F6rklund?= <afb@algonet.se>
Subject: Re: [SDL] Updated Mac patch
Date: Tue, 6 Sep 2005 15:21:27 +0200
To: A list for developers using the SDL library <sdl@libsdl.org>
Earlier, I wrote:
> Updated the previous Mac patch to disable Carbon by default.
> Also "fixed" the SDL.spec again, so that it builds on Darwin.
>
> http://www.algonet.se/~afb/SDL-1.2.9-mac.patch
> Also applied fine to SDL12 CVS, when I tried it.
>
> Haven't completed any new packaging or projects for Xcode/PB,
> but it seems to build and install fine here (in development).
Tested the new patch to build with old CodeWarrior and MPW,
and it seems it needed some hacks with those old headers...
Just in case you want to support the archeological versions -
here is a small add-on to the above patch, to fix those...
http://www.algonet.se/~afb/SDL-1.2.9-classic.patch
I couldn't get the old CW5 projects to build without a few
modifications - such as deleting the stray old header in:
"CWprojects/Support/Carbon/Include/ConditionalMacros.h" ?
But I updated both projects to CW6 too and built for Carbon,
and it ran all of the Mac test projects without any problems.
The MPW file seems to have compiled, with a small order change.
As long as you're still shipping the CWProjects and MPWmake
with the download, they should probably be updated/fixed ?
(another "solution" would of course be to just delete them)
I'll post my new projects along with the new Xcode projects
later on, along with XML exports of the various .mcp files.
(CW5 builds for Classic / "PPC", and CW6 builds for Carbon)
It'll be packaged as a part of the next SpriteWorld X release...
http://spriteworldx.sourceforge.net/ [Classic/Carbon/Win/X11]
--anders
author | Ryan C. Gordon <icculus@icculus.org> |
---|---|
date | Thu, 08 Sep 2005 06:34:28 +0000 |
parents | 609c060fd2a2 |
children | c9b51268668f |
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 | |
1133
609c060fd2a2
The MacOSX Carbon/Cocoa/X11 all in one library patch. Relevant emails:
Ryan C. Gordon <icculus@icculus.org>
parents:
1032
diff
changeset
|
69 2. *MacOS 9 or later (but *not* Mac OS X) for hardware accelerated blit / fill |
0 | 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 | |
1133
609c060fd2a2
The MacOSX Carbon/Cocoa/X11 all in one library patch. Relevant emails:
Ryan C. Gordon <icculus@icculus.org>
parents:
1032
diff
changeset
|
133 #if defined(__APPLE__) && defined(__MACH__) |
609c060fd2a2
The MacOSX Carbon/Cocoa/X11 all in one library patch. Relevant emails:
Ryan C. Gordon <icculus@icculus.org>
parents:
1032
diff
changeset
|
134 #include <Carbon/Carbon.h> |
609c060fd2a2
The MacOSX Carbon/Cocoa/X11 all in one library patch. Relevant emails:
Ryan C. Gordon <icculus@icculus.org>
parents:
1032
diff
changeset
|
135 #include <DrawSprocket/DrawSprocket.h> |
609c060fd2a2
The MacOSX Carbon/Cocoa/X11 all in one library patch. Relevant emails:
Ryan C. Gordon <icculus@icculus.org>
parents:
1032
diff
changeset
|
136 #elif TARGET_API_MAC_CARBON && (UNIVERSAL_INTERFACES_VERSION > 0x0335) |
0 | 137 #include <Carbon.h> |
1133
609c060fd2a2
The MacOSX Carbon/Cocoa/X11 all in one library patch. Relevant emails:
Ryan C. Gordon <icculus@icculus.org>
parents:
1032
diff
changeset
|
138 #include <DrawSprocket.h> |
0 | 139 #else |
140 #include <LowMem.h> | |
141 #include <Gestalt.h> | |
142 #include <Devices.h> | |
143 #include <DiskInit.h> | |
144 #include <QDOffscreen.h> | |
1133
609c060fd2a2
The MacOSX Carbon/Cocoa/X11 all in one library patch. Relevant emails:
Ryan C. Gordon <icculus@icculus.org>
parents:
1032
diff
changeset
|
145 #include <DrawSprocket.h> |
0 | 146 #endif |
147 | |
148 #include "SDL_video.h" | |
149 #include "SDL_blit.h" | |
150 #include "SDL_error.h" | |
151 #include "SDL_syswm.h" | |
152 #include "SDL_sysvideo.h" | |
1133
609c060fd2a2
The MacOSX Carbon/Cocoa/X11 all in one library patch. Relevant emails:
Ryan C. Gordon <icculus@icculus.org>
parents:
1032
diff
changeset
|
153 #include "SDL_pixels_c.h" |
0 | 154 #include "SDL_dspvideo.h" |
155 #include "SDL_macgl_c.h" | |
156 #include "SDL_macwm_c.h" | |
157 #include "SDL_macmouse_c.h" | |
158 #include "SDL_macevents_c.h" | |
159 | |
160 /* Initialization/Query functions */ | |
161 static int DSp_VideoInit(_THIS, SDL_PixelFormat *vformat); | |
162 static SDL_Rect **DSp_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags); | |
163 static SDL_Surface *DSp_SetVideoMode(_THIS, SDL_Surface *current, int width, int height, int bpp, Uint32 flags); | |
164 static int DSp_SetColors(_THIS, int firstcolor, int ncolors, | |
165 SDL_Color *colors); | |
166 static int DSp_CreatePalette(_THIS); | |
167 static int DSp_DestroyPalette(_THIS); | |
168 static void DSp_VideoQuit(_THIS); | |
169 | |
170 static int DSp_GetMainDevice (_THIS, GDHandle *device); | |
171 static void DSp_IsHWAvailable (_THIS, SDL_PixelFormat *vformat); | |
172 static void DSp_DSpUpdate(_THIS, int numrects, SDL_Rect *sdl_rects); | |
173 static void DSp_DirectUpdate(_THIS, int numrects, SDL_Rect *sdl_rects); | |
174 | |
175 /* Hardware surface functions */ | |
176 static int DSp_SetHWAlpha(_THIS, SDL_Surface *surface, UInt8 alpha); | |
177 static int DSp_SetHWColorKey(_THIS, SDL_Surface *surface, Uint32 key); | |
178 static int DSp_NewHWSurface(_THIS, CGrafPtr *port, int depth, int width, int height); | |
179 static int DSp_AllocHWSurface(_THIS, SDL_Surface *surface); | |
180 static int DSp_LockHWSurface(_THIS, SDL_Surface *surface); | |
181 static void DSp_UnlockHWSurface(_THIS, SDL_Surface *surface); | |
182 static void DSp_FreeHWSurface(_THIS, SDL_Surface *surface); | |
183 static int DSp_FlipHWSurface(_THIS, SDL_Surface *surface); | |
184 static int DSp_CheckHWBlit(_THIS, SDL_Surface *src, SDL_Surface *dest); | |
185 static int DSp_HWAccelBlit(SDL_Surface *src, SDL_Rect *srcrect, | |
186 SDL_Surface *dst, SDL_Rect *dstrect); | |
187 static int DSp_FillHWRect(_THIS, SDL_Surface *dst, SDL_Rect *rect, Uint32 color); | |
188 | |
189 #ifdef HAVE_OPENGL | |
190 static void DSp_GL_SwapBuffers (_THIS); | |
191 #endif | |
192 | |
193 #if ! TARGET_API_MAC_CARBON | |
194 | |
195 #define GetPortPixRowBytes(x) ( (*(x->portPixMap))->rowBytes ) | |
196 #define GetGDevPixMap(x) ((**(x)).gdPMap) | |
197 #define GetPortPixMap(x) ((*(x)).portPixMap) | |
198 | |
199 #define GetPixDepth(y) ((**(y)).pixelSize) | |
200 //#define GetPixRowBytes(y) ((**(y)).rowBytes) | |
201 //#define GetPixBaseAddr(y) ((**(y)).baseAddr) | |
202 #define GetPixCTab(y) ((**(y)).pmTable) | |
203 #define GetPortBitMapForCopyBits(x) (&(((GrafPtr)(x))->portBits)) | |
204 | |
205 #else | |
206 #define GetPortPixRowBytes(x) (GetPixRowBytes(GetPortPixMap(x)) ) | |
207 #define GetGDevPixMap(x) ((**(x)).gdPMap) | |
208 | |
209 #endif | |
210 | |
211 typedef struct private_hwdata { | |
212 | |
213 GWorldPtr offscreen; // offscreen gworld in VRAM or AGP | |
214 | |
215 #ifdef DSP_TRY_CC_AND_AA | |
216 GWorldPtr mask; // transparent mask | |
217 RGBColor alpha; // alpha color | |
218 RGBColor trans; // transparent color | |
219 #endif | |
220 | |
221 } private_hwdata; | |
222 | |
223 typedef private_hwdata private_swdata ; /* have same fields */ | |
224 | |
225 /* Macintosh toolbox driver bootstrap functions */ | |
226 | |
227 static int DSp_Available(void) | |
228 { | |
229 /* Check for DrawSprocket */ | |
1133
609c060fd2a2
The MacOSX Carbon/Cocoa/X11 all in one library patch. Relevant emails:
Ryan C. Gordon <icculus@icculus.org>
parents:
1032
diff
changeset
|
230 #if ! TARGET_API_MAC_OSX |
0 | 231 /* This check is only meaningful if you weak-link DrawSprocketLib */ |
232 return ((Ptr)DSpStartup != (Ptr)kUnresolvedCFragSymbolAddress); | |
1133
609c060fd2a2
The MacOSX Carbon/Cocoa/X11 all in one library patch. Relevant emails:
Ryan C. Gordon <icculus@icculus.org>
parents:
1032
diff
changeset
|
233 #else |
609c060fd2a2
The MacOSX Carbon/Cocoa/X11 all in one library patch. Relevant emails:
Ryan C. Gordon <icculus@icculus.org>
parents:
1032
diff
changeset
|
234 return 1; // DrawSprocket.framework doesn't have it all, but it's there |
609c060fd2a2
The MacOSX Carbon/Cocoa/X11 all in one library patch. Relevant emails:
Ryan C. Gordon <icculus@icculus.org>
parents:
1032
diff
changeset
|
235 #endif |
0 | 236 } |
237 | |
238 static void DSp_DeleteDevice(SDL_VideoDevice *device) | |
239 { | |
240 /* -dw- taking no chances with null pointers */ | |
241 if (device) { | |
242 | |
243 if (device->hidden) { | |
244 | |
245 if (device->hidden->dspinfo) | |
246 free(device->hidden->dspinfo); | |
247 | |
248 free(device->hidden); | |
249 } | |
250 free(device); | |
251 } | |
252 } | |
253 | |
254 static SDL_VideoDevice *DSp_CreateDevice(int devindex) | |
255 { | |
256 SDL_VideoDevice *device; | |
257 | |
258 /* Initialize all variables that we clean on shutdown */ | |
259 device = (SDL_VideoDevice *)malloc(sizeof(SDL_VideoDevice)); | |
260 if ( device ) { | |
261 memset(device, 0, sizeof (*device)); | |
262 device->hidden = (struct SDL_PrivateVideoData *) | |
263 malloc((sizeof *device->hidden)); | |
264 if (device->hidden) | |
265 memset(device->hidden, 0, sizeof ( *(device->hidden) ) ); | |
266 } | |
267 if ( (device == NULL) || (device->hidden == NULL) ) { | |
268 SDL_OutOfMemory(); | |
269 | |
270 if ( device ) { | |
271 | |
272 if (device->hidden) | |
273 free (device->hidden); | |
274 | |
275 free(device); | |
276 } | |
277 | |
278 return(NULL); | |
279 } | |
280 | |
281 /* Allocate DrawSprocket information */ | |
282 device->hidden->dspinfo = (struct DSpInfo *)malloc( | |
283 (sizeof *device->hidden->dspinfo)); | |
284 if ( device->hidden->dspinfo == NULL ) { | |
285 SDL_OutOfMemory(); | |
286 free(device->hidden); | |
287 free(device); | |
288 return(0); | |
289 } | |
290 memset(device->hidden->dspinfo, 0, (sizeof *device->hidden->dspinfo)); | |
291 | |
292 /* Set the function pointers */ | |
293 device->VideoInit = DSp_VideoInit; | |
294 device->ListModes = DSp_ListModes; | |
295 device->SetVideoMode = DSp_SetVideoMode; | |
296 device->SetColors = DSp_SetColors; | |
297 device->UpdateRects = NULL; | |
298 device->VideoQuit = DSp_VideoQuit; | |
299 device->AllocHWSurface = DSp_AllocHWSurface; | |
300 device->CheckHWBlit = NULL; | |
301 device->FillHWRect = NULL; | |
302 device->SetHWColorKey = NULL; | |
303 device->SetHWAlpha = NULL; | |
304 device->LockHWSurface = DSp_LockHWSurface; | |
305 device->UnlockHWSurface = DSp_UnlockHWSurface; | |
306 device->FlipHWSurface = DSp_FlipHWSurface; | |
307 device->FreeHWSurface = DSp_FreeHWSurface; | |
308 #ifdef HAVE_OPENGL | |
309 device->GL_MakeCurrent = Mac_GL_MakeCurrent; | |
310 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
|
311 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
|
312 device->GL_GetProcAddress = Mac_GL_GetProcAddress; |
0 | 313 #endif |
314 device->SetCaption = NULL; | |
315 device->SetIcon = NULL; | |
316 device->IconifyWindow = NULL; | |
317 device->GrabInput = NULL; | |
318 device->GetWMInfo = NULL; | |
319 device->FreeWMCursor = Mac_FreeWMCursor; | |
320 device->CreateWMCursor = Mac_CreateWMCursor; | |
321 device->ShowWMCursor = Mac_ShowWMCursor; | |
322 device->WarpWMCursor = Mac_WarpWMCursor; | |
323 device->InitOSKeymap = Mac_InitOSKeymap; | |
324 device->PumpEvents = Mac_PumpEvents; | |
325 | |
326 device->GrabInput = NULL; | |
327 device->CheckMouseMode = NULL; | |
328 | |
329 device->free = DSp_DeleteDevice; | |
330 | |
331 return device; | |
332 } | |
333 | |
334 VideoBootStrap DSp_bootstrap = { | |
335 "DSp", "MacOS DrawSprocket", | |
336 DSp_Available, DSp_CreateDevice | |
337 }; | |
338 | |
339 /* Use DSp/Display Manager to build mode list for given screen */ | |
340 static SDL_Rect** DSp_BuildModeList (const GDHandle gDevice) | |
341 { | |
342 DSpContextAttributes attributes; | |
343 DSpContextReference context; | |
344 DisplayIDType displayID; | |
345 SDL_Rect temp_list [16]; | |
346 SDL_Rect **mode_list; | |
347 int width, height, i, j; | |
348 | |
349 #if TARGET_API_MAC_OSX | |
350 | |
351 displayID = 0; | |
352 | |
353 #else | |
354 /* Ask Display Manager for integer id of screen device */ | |
355 if ( DMGetDisplayIDByGDevice (gDevice, &displayID, SDL_TRUE) != noErr ) { | |
356 return NULL; | |
357 } | |
358 #endif | |
359 /* Get the first possible DSp context on this device */ | |
360 if ( DSpGetFirstContext (displayID, &context) != noErr ) { | |
361 return NULL; | |
362 } | |
363 | |
364 if ( DSpContext_GetAttributes (context, &attributes) != noErr ) | |
365 return NULL; | |
366 | |
367 for ( i = 0; i < SDL_TABLESIZE(temp_list); i++ ) { | |
368 width = attributes.displayWidth; | |
369 height = attributes.displayHeight; | |
370 | |
371 temp_list [i].x = 0 | attributes.displayBestDepth; | |
372 temp_list [i].y = 0; | |
373 temp_list [i].w = width; | |
374 temp_list [i].h = height; | |
375 | |
376 /* DSp will report many different contexts with the same width and height. */ | |
377 /* They will differ in bit depth and refresh rate. */ | |
378 /* We will ignore them until we reach one with a different width/height */ | |
379 /* When there are no more contexts to look at, we will quit building the list*/ | |
380 while ( width == attributes.displayWidth && height == attributes.displayHeight ) { | |
381 | |
382 OSStatus err = DSpGetNextContext (context, &context); | |
383 if (err != noErr) | |
384 if (err == kDSpContextNotFoundErr) | |
385 goto done; | |
386 else | |
387 return NULL; | |
388 | |
389 if ( DSpContext_GetAttributes (context, &attributes) != noErr ) | |
390 return NULL; | |
391 | |
392 temp_list [i].x |= attributes.displayBestDepth; | |
393 } | |
394 } | |
395 done: | |
396 i++; /* i was not incremented before kicking out of the loop */ | |
397 | |
398 mode_list = (SDL_Rect**) malloc (sizeof (SDL_Rect*) * (i+1)); | |
399 if (mode_list) { | |
400 | |
401 /* -dw- new stuff: build in reverse order so largest sizes list first */ | |
402 for (j = i-1; j >= 0; j--) { | |
403 mode_list [j] = (SDL_Rect*) malloc (sizeof (SDL_Rect)); | |
404 if (mode_list [j]) | |
405 memcpy (mode_list [j], &(temp_list [j]), sizeof (SDL_Rect)); | |
406 else { | |
407 SDL_OutOfMemory (); | |
408 return NULL; | |
409 } | |
410 } | |
411 mode_list [i] = NULL; /* append null to the end */ | |
412 } | |
413 else { | |
414 SDL_OutOfMemory (); | |
415 return NULL; | |
416 } | |
417 | |
418 return mode_list; | |
419 } | |
420 | |
421 static void DSp_IsHWAvailable (_THIS, SDL_PixelFormat *vformat) | |
422 { | |
423 /* | |
424 VRAM GWorlds are only available on OS 9 or later. | |
425 Even with OS 9, some display drivers won't support it, | |
426 so we create a test GWorld and check for errors. | |
427 */ | |
428 | |
429 long versionSystem; | |
430 | |
431 dsp_vram_available = SDL_FALSE; | |
432 dsp_agp_available = SDL_FALSE; | |
433 | |
434 Gestalt ('sysv', &versionSystem); | |
435 if (0x00000860 < (versionSystem & 0x0000FFFF)) { | |
436 | |
437 GWorldPtr offscreen; | |
438 OSStatus err; | |
439 Rect bounds; | |
440 | |
441 SetRect (&bounds, 0, 0, 320, 240); | |
442 | |
1133
609c060fd2a2
The MacOSX Carbon/Cocoa/X11 all in one library patch. Relevant emails:
Ryan C. Gordon <icculus@icculus.org>
parents:
1032
diff
changeset
|
443 #if useDistantHdwrMem && useLocalHdwrMem |
0 | 444 err = NewGWorld (&offscreen, vformat->BitsPerPixel, &bounds, NULL, SDL_Display, useDistantHdwrMem | noNewDevice); |
445 if (err == noErr) { | |
446 dsp_vram_available = SDL_TRUE; | |
447 DisposeGWorld (offscreen); | |
448 } | |
449 | |
450 err = NewGWorld (&offscreen, vformat->BitsPerPixel, &bounds, NULL, SDL_Display, useLocalHdwrMem | noNewDevice); | |
451 if (err == noErr) { | |
452 DisposeGWorld (offscreen); | |
453 dsp_agp_available = SDL_TRUE; | |
454 } | |
1133
609c060fd2a2
The MacOSX Carbon/Cocoa/X11 all in one library patch. Relevant emails:
Ryan C. Gordon <icculus@icculus.org>
parents:
1032
diff
changeset
|
455 #endif |
0 | 456 } |
457 } | |
458 | |
459 static int DSp_GetMainDevice (_THIS, GDHandle *device) | |
460 { | |
461 | |
462 #if TARGET_API_MAC_OSX | |
463 /* DSpUserSelectContext not available on OS X */ | |
464 *device = GetMainDevice(); | |
465 return 0; | |
466 #else | |
467 | |
468 DSpContextAttributes attrib; | |
469 DSpContextReference context; | |
470 DisplayIDType display_id; | |
471 GDHandle main_device; | |
472 GDHandle device_list; | |
473 | |
474 device_list = GetDeviceList (); | |
475 main_device = GetMainDevice (); | |
476 | |
477 /* Quick check to avoid slower method when only one display exists */ | |
478 if ( (**device_list).gdNextGD == NULL ) { | |
479 *device = main_device; | |
480 return 0; | |
481 } | |
482 | |
483 memset (&attrib, 0, sizeof (DSpContextAttributes)); | |
484 | |
485 /* These attributes are hopefully supported on all devices...*/ | |
486 attrib.displayWidth = 640; | |
487 attrib.displayHeight = 480; | |
488 attrib.displayBestDepth = 8; | |
489 attrib.backBufferBestDepth = 8; | |
490 attrib.displayDepthMask = kDSpDepthMask_All; | |
491 attrib.backBufferDepthMask = kDSpDepthMask_All; | |
492 attrib.colorNeeds = kDSpColorNeeds_Require; | |
493 attrib.pageCount = 1; | |
494 | |
495 if (noErr != DMGetDisplayIDByGDevice (main_device, &display_id, SDL_FALSE)) { | |
496 SDL_SetError ("Display Manager couldn't associate GDevice with a Display ID"); | |
497 return (-1); | |
498 } | |
499 | |
500 /* Put up dialog on main display to select which display to use */ | |
501 if (noErr != DSpUserSelectContext (&attrib, display_id, NULL, &context)) { | |
502 SDL_SetError ("DrawSprocket couldn't create a context"); | |
503 return (-1); | |
504 } | |
505 | |
506 if (noErr != DSpContext_GetDisplayID (context, &display_id)) { | |
507 SDL_SetError ("DrawSprocket couldn't get display ID"); | |
508 return (-1); | |
509 } | |
510 | |
511 if (noErr != DMGetGDeviceByDisplayID (display_id, &main_device, SDL_FALSE)) { | |
512 SDL_SetError ("Display Manager couldn't associate Display ID with GDevice"); | |
513 return (-1); | |
514 } | |
515 | |
516 *device = main_device; | |
517 return (0); | |
518 #endif | |
519 } | |
520 | |
521 static int DSp_VideoInit(_THIS, SDL_PixelFormat *vformat) | |
522 { | |
1135
cf6133247d34
Mac Classic and CodeWarrior patches.
Ryan C. Gordon <icculus@icculus.org>
parents:
1133
diff
changeset
|
523 NumVersion dsp_version = { 0x01, 0x00, 0x00, 0x00 }; |
0 | 524 |
1135
cf6133247d34
Mac Classic and CodeWarrior patches.
Ryan C. Gordon <icculus@icculus.org>
parents:
1133
diff
changeset
|
525 #if UNIVERSAL_INTERFACES_VERSION > 0x0320 |
1133
609c060fd2a2
The MacOSX Carbon/Cocoa/X11 all in one library patch. Relevant emails:
Ryan C. Gordon <icculus@icculus.org>
parents:
1032
diff
changeset
|
526 dsp_version = DSpGetVersion (); |
1135
cf6133247d34
Mac Classic and CodeWarrior patches.
Ryan C. Gordon <icculus@icculus.org>
parents:
1133
diff
changeset
|
527 #endif |
0 | 528 |
529 if ( (dsp_version.majorRev == 1 && dsp_version.minorAndBugRev < 0x73) || | |
530 (dsp_version.majorRev < 1) ) { | |
531 | |
532 /* StandardAlert (kAlertStopAlert, "\pError!", | |
533 "\pI need DrawSprocket 1.7.3 or later!\n" | |
534 "You can find a newer version at http://www.apple.com/swupdates.", | |
535 NULL, NULL); | |
536 */ | |
537 SDL_SetError ("DrawSprocket version is too old. Need 1.7.3 or later."); | |
538 return (-1); | |
539 } | |
540 | |
541 if ( DSpStartup () != noErr ) { | |
542 SDL_SetError ("DrawSprocket couldn't startup"); | |
543 return(-1); | |
544 } | |
545 | |
546 /* Start DSpintosh events */ | |
547 Mac_InitEvents(this); | |
548 | |
549 /* Get a handle to the main monitor, or choose one on multiple monitor setups */ | |
550 if ( DSp_GetMainDevice(this, &SDL_Display) < 0) | |
551 return (-1); | |
552 | |
553 /* Determine pixel format */ | |
554 vformat->BitsPerPixel = GetPixDepth ( (**SDL_Display).gdPMap ); | |
555 dsp_old_depth = vformat->BitsPerPixel; | |
556 | |
557 switch (vformat->BitsPerPixel) { | |
558 case 16: | |
559 vformat->Rmask = 0x00007c00; | |
560 vformat->Gmask = 0x000003e0; | |
561 vformat->Bmask = 0x0000001f; | |
562 break; | |
563 default: | |
564 break; | |
565 } | |
566 | |
567 if ( DSp_CreatePalette (this) < 0 ) { | |
568 | |
569 SDL_SetError ("Could not create palette"); | |
570 return (-1); | |
571 } | |
572 | |
573 /* Get a list of available fullscreen modes */ | |
574 SDL_modelist = DSp_BuildModeList (SDL_Display); | |
575 if (SDL_modelist == NULL) { | |
576 SDL_SetError ("DrawSprocket could not build a mode list"); | |
577 return (-1); | |
578 } | |
579 | |
580 /* Check for VRAM and AGP GWorlds for HW Blitting */ | |
581 DSp_IsHWAvailable (this, vformat); | |
582 | |
583 this->info.wm_available = 0; | |
584 | |
585 if (dsp_vram_available || dsp_agp_available) { | |
586 | |
587 this->info.hw_available = SDL_TRUE; | |
588 | |
589 this->CheckHWBlit = DSp_CheckHWBlit; | |
590 this->info.blit_hw = SDL_TRUE; | |
591 | |
592 this->FillHWRect = DSp_FillHWRect; | |
593 this->info.blit_fill = SDL_TRUE; | |
594 | |
595 #ifdef DSP_TRY_CC_AND_AA | |
596 this->SetHWColorKey = DSp_SetHWColorKey; | |
597 this->info.blit_hw_CC = SDL_TRUE; | |
598 | |
599 this->SetHWAlpha = DSp_SetHWAlpha; | |
600 this->info.blit_hw_A = SDL_TRUE; | |
601 #endif | |
602 | |
603 } | |
604 | |
605 return(0); | |
606 } | |
607 | |
608 static SDL_Rect **DSp_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags) | |
609 { | |
610 static SDL_Rect *dsp_modes[16]; | |
611 int i = 0, j = 0; | |
612 | |
613 if ( format->BitsPerPixel == 0 ) | |
614 return ( (SDL_Rect**) NULL ); | |
615 | |
616 while (SDL_modelist[i] != NULL) { | |
617 | |
618 if (SDL_modelist[i]->x & format->BitsPerPixel) { | |
619 dsp_modes[j] = SDL_modelist[i]; | |
620 j++; | |
621 } | |
622 i++; | |
623 } | |
624 | |
625 dsp_modes[j] = NULL; | |
626 | |
627 return dsp_modes; | |
628 } | |
629 | |
630 /* Various screen update functions available */ | |
631 static void DSp_DirectUpdate(_THIS, int numrects, SDL_Rect *rects); | |
632 | |
1133
609c060fd2a2
The MacOSX Carbon/Cocoa/X11 all in one library patch. Relevant emails:
Ryan C. Gordon <icculus@icculus.org>
parents:
1032
diff
changeset
|
633 #if ! TARGET_API_MAC_OSX |
609c060fd2a2
The MacOSX Carbon/Cocoa/X11 all in one library patch. Relevant emails:
Ryan C. Gordon <icculus@icculus.org>
parents:
1032
diff
changeset
|
634 |
0 | 635 static volatile unsigned int retrace_count = 0; /* -dw- need volatile because it updates asychronously */ |
636 | |
637 Boolean DSp_VBLProc ( DSpContextReference context, void *ref_con ) | |
638 { | |
639 retrace_count++; | |
640 | |
641 return 1; /* Darrell, is this right? */ | |
642 } | |
643 | |
644 static void DSp_SetHWError (OSStatus err, int is_agp) | |
645 { | |
646 char message[1024]; | |
647 const char *fmt, *mem; | |
648 | |
649 if ( is_agp ) { | |
650 mem = "AGP Memory"; | |
651 } else { | |
652 mem = "VRAM"; | |
653 } | |
654 switch(err) { | |
655 case memFullErr: | |
656 fmt = "Hardware surface possible but not enough %s available"; | |
657 break; | |
658 case cDepthErr: | |
659 fmt = "Hardware surface possible but invalid color depth"; | |
660 break; | |
661 default: | |
662 fmt = "Hardware surface could not be allocated in %s - unknown error"; | |
663 break; | |
664 } | |
665 sprintf(message, fmt, mem); | |
666 SDL_SetError(message); | |
667 } | |
1133
609c060fd2a2
The MacOSX Carbon/Cocoa/X11 all in one library patch. Relevant emails:
Ryan C. Gordon <icculus@icculus.org>
parents:
1032
diff
changeset
|
668 #endif // TARGET_API_MAC_OSX |
0 | 669 |
670 /* put up a dialog to verify display change */ | |
671 static int DSp_ConfirmSwitch () { | |
672 | |
673 /* resource id's for dialog */ | |
674 const int rDialog = 1002; | |
675 const int bCancel = 1; | |
676 const int bOK = 2; | |
677 | |
678 DialogPtr dialog; | |
679 OSStatus err; | |
680 SInt32 response; | |
681 DialogItemIndex item = 0; | |
682 GrafPtr savePort; | |
683 | |
684 GetPort (&savePort); | |
685 | |
686 dialog = GetNewDialog (rDialog, NULL, (WindowPtr) -1); | |
687 if (dialog == NULL) | |
688 return (0); | |
689 | |
1133
609c060fd2a2
The MacOSX Carbon/Cocoa/X11 all in one library patch. Relevant emails:
Ryan C. Gordon <icculus@icculus.org>
parents:
1032
diff
changeset
|
690 #if TARGET_API_CARBON |
609c060fd2a2
The MacOSX Carbon/Cocoa/X11 all in one library patch. Relevant emails:
Ryan C. Gordon <icculus@icculus.org>
parents:
1032
diff
changeset
|
691 SetPort (GetDialogPort(dialog)); |
609c060fd2a2
The MacOSX Carbon/Cocoa/X11 all in one library patch. Relevant emails:
Ryan C. Gordon <icculus@icculus.org>
parents:
1032
diff
changeset
|
692 #else |
609c060fd2a2
The MacOSX Carbon/Cocoa/X11 all in one library patch. Relevant emails:
Ryan C. Gordon <icculus@icculus.org>
parents:
1032
diff
changeset
|
693 SetPort ((WindowPtr) dialog); |
609c060fd2a2
The MacOSX Carbon/Cocoa/X11 all in one library patch. Relevant emails:
Ryan C. Gordon <icculus@icculus.org>
parents:
1032
diff
changeset
|
694 #endif |
0 | 695 |
696 SetDialogDefaultItem (dialog, bCancel); | |
697 SetDialogCancelItem (dialog, bCancel); | |
698 | |
699 SetEventMask (everyEvent); | |
700 FlushEvents (everyEvent, 0); | |
701 | |
702 /* On MacOS 8.5 or later, we can make the dialog go away after 15 seconds */ | |
703 /* This is good since it's possible user can't even see the dialog! */ | |
704 /* Requires linking to DialogsLib */ | |
705 err = Gestalt(gestaltSystemVersion,&response); | |
706 if (err == noErr && response >= 0x00000850) { | |
707 SetDialogTimeout(dialog, bCancel, 15); | |
708 } | |
709 | |
710 do { | |
711 | |
712 ModalDialog ( NULL, &item ); | |
713 | |
714 } while ( item != bCancel && item != bOK && err != noErr); | |
715 | |
1133
609c060fd2a2
The MacOSX Carbon/Cocoa/X11 all in one library patch. Relevant emails:
Ryan C. Gordon <icculus@icculus.org>
parents:
1032
diff
changeset
|
716 |
609c060fd2a2
The MacOSX Carbon/Cocoa/X11 all in one library patch. Relevant emails:
Ryan C. Gordon <icculus@icculus.org>
parents:
1032
diff
changeset
|
717 DisposeDialog (dialog); |
0 | 718 SetPort (savePort); |
719 | |
720 SetEventMask(everyEvent - autoKeyMask); | |
721 FlushEvents(everyEvent, 0); | |
722 | |
723 return (item - 1); | |
724 } | |
725 | |
726 static void DSp_UnsetVideoMode(_THIS, SDL_Surface *current) | |
727 { | |
728 | |
729 | |
730 if ( current->flags & SDL_OPENGL ) { | |
731 Mac_GL_Quit (this); | |
732 } | |
733 | |
734 if (dsp_context != NULL) { | |
735 | |
736 GWorldPtr front; | |
737 DSpContext_GetFrontBuffer (dsp_context, &front); | |
738 | |
739 if (front != dsp_back_buffer) | |
740 DisposeGWorld (dsp_back_buffer); | |
741 | |
742 if (current->hwdata) | |
743 free (current->hwdata); | |
744 | |
745 DSpContext_SetState (dsp_context, kDSpContextState_Inactive ); | |
746 DSpContext_Release (dsp_context); | |
747 | |
748 dsp_context = NULL; | |
749 } | |
750 | |
751 if (SDL_Window != NULL) { | |
752 DisposeWindow (SDL_Window); | |
753 SDL_Window = NULL; | |
754 } | |
755 | |
756 current->pixels = NULL; | |
757 current->flags = 0; | |
758 } | |
759 | |
760 static SDL_Surface *DSp_SetVideoMode(_THIS, | |
761 SDL_Surface *current, int width, int height, int bpp, Uint32 flags) | |
762 { | |
763 | |
1133
609c060fd2a2
The MacOSX Carbon/Cocoa/X11 all in one library patch. Relevant emails:
Ryan C. Gordon <icculus@icculus.org>
parents:
1032
diff
changeset
|
764 #if !TARGET_API_MAC_OSX |
609c060fd2a2
The MacOSX Carbon/Cocoa/X11 all in one library patch. Relevant emails:
Ryan C. Gordon <icculus@icculus.org>
parents:
1032
diff
changeset
|
765 DisplayIDType display_id; |
609c060fd2a2
The MacOSX Carbon/Cocoa/X11 all in one library patch. Relevant emails:
Ryan C. Gordon <icculus@icculus.org>
parents:
1032
diff
changeset
|
766 Fixed freq; |
609c060fd2a2
The MacOSX Carbon/Cocoa/X11 all in one library patch. Relevant emails:
Ryan C. Gordon <icculus@icculus.org>
parents:
1032
diff
changeset
|
767 #endif |
0 | 768 DSpContextAttributes attrib; |
769 OSStatus err; | |
770 UInt32 rmask = 0, gmask = 0, bmask = 0; | |
771 | |
772 int page_count; | |
773 int double_buf; | |
774 int hw_surface; | |
775 int use_dsp_back_buffer; | |
776 | |
777 DSp_UnsetVideoMode (this, current); | |
778 | |
779 if (bpp != dsp_old_depth) | |
780 DSp_DestroyPalette (this); | |
781 | |
782 double_buf = (flags & SDL_DOUBLEBUF) != 0; | |
783 hw_surface = (flags & SDL_HWSURFACE) != 0; | |
784 use_dsp_back_buffer = !dsp_vram_available || !hw_surface ; | |
785 | |
786 current->flags |= SDL_FULLSCREEN; | |
787 | |
788 rebuild: | |
789 | |
790 if ( double_buf && use_dsp_back_buffer ) { | |
791 page_count = 2; | |
792 } else { | |
793 page_count = 1; | |
794 } | |
795 | |
796 memset (&attrib, 0, sizeof (DSpContextAttributes)); | |
797 attrib.displayWidth = width; | |
798 attrib.displayHeight = height; | |
799 attrib.displayBestDepth = bpp; | |
800 attrib.backBufferBestDepth = bpp; | |
801 attrib.displayDepthMask = kDSpDepthMask_All; | |
802 attrib.backBufferDepthMask = kDSpDepthMask_All; | |
803 attrib.colorNeeds = kDSpColorNeeds_Require; | |
804 attrib.colorTable = 0; | |
805 attrib.pageCount = page_count; | |
1135
cf6133247d34
Mac Classic and CodeWarrior patches.
Ryan C. Gordon <icculus@icculus.org>
parents:
1133
diff
changeset
|
806 #if TARGET_API_MAC_OSX || UNIVERSAL_INTERFACES_VERSION == 0x0320 |
0 | 807 |
808 if ( DSpFindBestContext (&attrib, &dsp_context) != noErr ) { | |
809 SDL_SetError ("DrawSprocket couldn't find a context"); | |
810 return NULL; | |
811 } | |
812 | |
813 #else | |
814 if ( noErr != DMGetDisplayIDByGDevice (SDL_Display, &display_id, SDL_FALSE) ) { | |
815 SDL_SetError ("Display Manager couldn't associate GDevice with display_id"); | |
816 return NULL; | |
817 } | |
1032
c1c2efca4548
Date: Mon, 24 Jan 2005 21:37:56 +0800
Sam Lantinga <slouken@libsdl.org>
parents:
769
diff
changeset
|
818 if ( DSpFindBestContextOnDisplayID(&attrib, &dsp_context, display_id) != noErr ) { |
0 | 819 SDL_SetError ("DrawSprocket couldn't find a suitable context on given display"); |
820 return NULL; | |
821 } | |
822 | |
823 #endif | |
824 if ( DSpContext_Reserve (dsp_context, &attrib) != noErr ) { | |
825 SDL_SetError ("DrawSprocket couldn't get the needed resources to build the display"); | |
826 return NULL; | |
827 } | |
828 | |
829 if ( (err = DSpContext_SetState (dsp_context, kDSpContextState_Active)) != noErr ) { | |
830 | |
831 if (err == kDSpConfirmSwitchWarning) { | |
832 | |
833 if ( ! DSp_ConfirmSwitch () ) { | |
834 | |
835 DSpContext_Release (dsp_context); | |
836 dsp_context = NULL; | |
837 SDL_SetError ("User cancelled display switch"); | |
838 return NULL; | |
839 } | |
840 else | |
841 /* Have to reactivate context. Why? */ | |
842 DSpContext_SetState (dsp_context, kDSpContextState_Active); | |
843 | |
844 } | |
845 else { | |
846 SDL_SetError ("DrawSprocket couldn't activate the context"); | |
847 return NULL; | |
848 } | |
849 } | |
850 | |
851 | |
852 if (bpp != dsp_old_depth) { | |
853 | |
854 DSp_CreatePalette (this); | |
855 | |
856 /* update format if display depth changed */ | |
857 if (bpp == 16) { | |
858 | |
859 rmask = 0x00007c00; | |
860 gmask = 0x000003e0; | |
861 bmask = 0x0000001f; | |
862 } | |
863 if ( ! SDL_ReallocFormat (current, bpp, rmask, gmask, bmask, 0 ) ) { | |
864 | |
865 SDL_SetError ("Could not reallocate video format."); | |
866 return(NULL); | |
867 } | |
868 } | |
869 | |
870 if (!double_buf) { | |
871 | |
872 /* single-buffer context */ | |
873 DSpContext_GetFrontBuffer (dsp_context, &dsp_back_buffer); | |
874 | |
875 current->hwdata = (private_hwdata*) malloc (sizeof (private_hwdata)); | |
876 if (current ->hwdata == NULL) { | |
877 SDL_OutOfMemory (); | |
878 return NULL; | |
879 } | |
880 current->hwdata->offscreen = dsp_back_buffer; | |
881 current->flags |= SDL_HWSURFACE; | |
882 this->UpdateRects = DSp_DirectUpdate; | |
883 } | |
884 else if ( use_dsp_back_buffer ) { | |
885 | |
886 DSpContext_GetBackBuffer (dsp_context, kDSpBufferKind_Normal, &dsp_back_buffer); | |
887 | |
888 current->flags |= SDL_DOUBLEBUF | SDL_SWSURFACE; /* only front buffer is in VRAM */ | |
889 this->UpdateRects = DSp_DSpUpdate; | |
890 } | |
891 else if ( DSp_NewHWSurface(this, &dsp_back_buffer, bpp, width-1, height-1) == 0 ) { | |
892 | |
893 current->hwdata = (private_hwdata*) malloc (sizeof (private_hwdata)); | |
894 if (current ->hwdata == NULL) { | |
895 SDL_OutOfMemory (); | |
896 return NULL; | |
897 } | |
898 | |
899 memset (current->hwdata, 0, sizeof (private_hwdata)); | |
900 current->hwdata->offscreen = dsp_back_buffer; | |
901 current->flags |= SDL_DOUBLEBUF | SDL_HWSURFACE; | |
902 this->UpdateRects = DSp_DirectUpdate; /* hardware doesn't do update rects, must be page-flipped */ | |
903 } | |
904 else { | |
905 | |
906 DSpContext_Release (dsp_context); | |
907 use_dsp_back_buffer = SDL_TRUE; | |
908 goto rebuild; | |
909 } | |
910 | |
911 current->pitch = GetPortPixRowBytes(dsp_back_buffer) & 0x3FFF; | |
912 current->pixels = GetPixBaseAddr(GetPortPixMap(dsp_back_buffer)); | |
913 | |
914 current->w = width; | |
915 current->h = height; | |
916 | |
917 #if ! TARGET_API_MAC_OSX | |
918 | |
919 if (use_dsp_back_buffer) { | |
920 | |
921 DSpContext_GetMonitorFrequency (dsp_context, &freq); | |
922 DSpContext_SetMaxFrameRate (dsp_context, freq >> 16); | |
923 } | |
924 | |
925 | |
926 if ( (current->flags & SDL_HWSURFACE) || (current->flags & SDL_OPENGL) ) | |
927 DSpContext_SetVBLProc (dsp_context, DSp_VBLProc, NULL); | |
928 #endif | |
929 | |
930 if (bpp == 8) | |
931 current->flags |= SDL_HWPALETTE; | |
932 | |
933 if (flags & SDL_OPENGL) { | |
934 | |
935 Rect rect; | |
936 RGBColor rgb = { 0.0, 0.0, 0.0 }; | |
937 GrafPtr save_port; | |
938 | |
939 SetRect (&rect, 0, 0, width, height); | |
940 SDL_Window = NewCWindow(nil, &( (**SDL_Display).gdRect), "\p", SDL_TRUE, plainDBox, (WindowPtr)-1, SDL_FALSE, 0); | |
941 | |
942 if (SDL_Window == NULL) { | |
943 | |
944 SDL_SetError ("DSp_SetVideoMode : OpenGL window could not be created."); | |
945 return NULL; | |
946 } | |
947 | |
948 /* Set window color to black to avoid white flash*/ | |
949 GetPort (&save_port); | |
1133
609c060fd2a2
The MacOSX Carbon/Cocoa/X11 all in one library patch. Relevant emails:
Ryan C. Gordon <icculus@icculus.org>
parents:
1032
diff
changeset
|
950 #if TARGET_API_MAC_CARBON |
609c060fd2a2
The MacOSX Carbon/Cocoa/X11 all in one library patch. Relevant emails:
Ryan C. Gordon <icculus@icculus.org>
parents:
1032
diff
changeset
|
951 SetPort (GetWindowPort(SDL_Window)); |
609c060fd2a2
The MacOSX Carbon/Cocoa/X11 all in one library patch. Relevant emails:
Ryan C. Gordon <icculus@icculus.org>
parents:
1032
diff
changeset
|
952 #else |
0 | 953 SetPort (SDL_Window); |
1133
609c060fd2a2
The MacOSX Carbon/Cocoa/X11 all in one library patch. Relevant emails:
Ryan C. Gordon <icculus@icculus.org>
parents:
1032
diff
changeset
|
954 #endif |
0 | 955 RGBForeColor (&rgb); |
956 PaintRect (&rect); | |
957 SetPort (save_port); | |
958 | |
959 SetPortWindowPort (SDL_Window); | |
960 SelectWindow (SDL_Window); | |
961 | |
962 if ( Mac_GL_Init (this) < 0 ) { | |
963 | |
964 SDL_SetError ("DSp_SetVideoMode : could not create OpenGL context."); | |
965 return NULL; | |
966 } | |
967 | |
968 current->flags |= SDL_OPENGL; | |
969 } | |
970 | |
971 return current; | |
972 } | |
973 | |
974 #ifdef DSP_TRY_CC_AND_AA | |
975 | |
976 static int DSp_MakeHWMask (_THIS, SDL_Surface *surface) | |
977 { | |
978 GDHandle save_device; | |
979 CGrafPtr save_port; | |
980 GWorldPtr temp; | |
981 RGBColor black = { 0, 0, 0 }; | |
982 RGBColor white = { 0xFFFF, 0xFFFF, 0xFFFF }; | |
983 Rect rect; | |
984 | |
985 Uint32 depth = GetPixDepth ( GetGDevPixMap (SDL_Display) ); | |
986 | |
987 SetRect (&rect, 0, 0, surface->w, surface->h); | |
988 | |
989 if ( noErr != NewGWorld (&(surface->hwdata->mask), depth, &rect, 0, SDL_Display, 0 ) < 0 ) { | |
990 | |
991 SDL_OutOfMemory (); | |
992 return (-1); | |
993 } | |
994 | |
995 if ( noErr != NewGWorld (&temp, depth, &rect, 0 , SDL_Display, 0 ) ) { | |
996 | |
997 SDL_OutOfMemory (); | |
998 return (-1); | |
999 } | |
1000 | |
1001 | |
1002 GetGWorld (&save_port, &save_device); | |
1003 SetGWorld (surface->hwdata->mask, SDL_Display); | |
1004 | |
1005 RGBForeColor (&white); | |
1006 PaintRect (&rect); | |
1007 | |
1008 RGBBackColor (&(surface->hwdata->trans)); | |
1009 | |
1010 CopyBits ( GetPortBitMapForCopyBits(surface->hwdata->offscreen), | |
1011 GetPortBitMapForCopyBits(surface->hwdata->mask), | |
1012 &rect, &rect, transparent, NULL ); | |
1013 | |
1014 SetGWorld (surface->hwdata->mask, SDL_Display); | |
1015 SetGWorld (save_port, save_device); | |
1016 return (0); | |
1017 } | |
1018 | |
1019 static int DSp_SetHWAlpha(_THIS, SDL_Surface *surface, UInt8 alpha) | |
1020 { | |
1021 surface->hwdata->alpha.red = (alpha / 255.0) * 65535; | |
1022 surface->hwdata->alpha.blue = (alpha / 255.0) * 65535; | |
1023 surface->hwdata->alpha.green = (alpha / 255.0) * 65535; | |
1024 | |
1025 surface->flags |= SDL_SRCALPHA; | |
1026 | |
1027 if (surface->flags & SDL_SRCCOLORKEY) { | |
1028 return(DSp_MakeHWMask (this, surface)); | |
1029 } | |
1030 return(0); | |
1031 } | |
1032 | |
1033 static int DSp_SetHWColorKey(_THIS, SDL_Surface *surface, Uint32 key) | |
1034 { | |
1035 CGrafPtr save_port; | |
1036 GDHandle save_device; | |
1037 | |
1038 GetGWorld (&save_port, &save_device); | |
1039 SetGWorld (surface->hwdata->offscreen, NULL); | |
1040 | |
1041 Index2Color (key, &(surface->hwdata->trans)); | |
1042 surface->flags |= SDL_SRCCOLORKEY; | |
1043 | |
1044 SetGWorld (save_port, save_device); | |
1045 | |
1046 if ( surface->flags & SDL_SRCALPHA ) { | |
1047 return(DSp_MakeHWMask (this, surface)); | |
1048 } | |
1049 return(0); | |
1050 } | |
1051 | |
1052 #endif /* DSP_TRY_CC_AND_AA */ | |
1053 | |
1054 static int DSp_NewHWSurface(_THIS, CGrafPtr *port, int depth, int width, int height) { | |
1055 | |
1056 OSStatus err; | |
1057 Rect bounds; | |
1058 | |
1059 SetRect (&bounds, 0, 0, width, height); | |
1060 | |
1133
609c060fd2a2
The MacOSX Carbon/Cocoa/X11 all in one library patch. Relevant emails:
Ryan C. Gordon <icculus@icculus.org>
parents:
1032
diff
changeset
|
1061 #if useDistantHdwrMem && useLocalHdwrMem |
0 | 1062 if (dsp_vram_available) { |
1063 /* try VRAM */ | |
1064 err = NewGWorld (port, depth, &bounds, 0 , SDL_Display, useDistantHdwrMem | noNewDevice ); | |
1065 if (err != noErr) | |
1066 DSp_SetHWError (err, SDL_FALSE); | |
1067 else | |
1068 return (0); | |
1069 } | |
1070 | |
1071 if (dsp_agp_available) { | |
1072 /* try AGP */ | |
1073 err = NewGWorld (port, depth, &bounds, 0 , SDL_Display, useLocalHdwrMem | noNewDevice ); | |
1074 | |
1075 if (err != noErr) | |
1076 DSp_SetHWError (err, SDL_TRUE); | |
1077 else | |
1078 return (0); | |
1079 } | |
1133
609c060fd2a2
The MacOSX Carbon/Cocoa/X11 all in one library patch. Relevant emails:
Ryan C. Gordon <icculus@icculus.org>
parents:
1032
diff
changeset
|
1080 #endif |
0 | 1081 |
1082 return (-1); | |
1083 } | |
1084 | |
1085 static int DSp_AllocHWSurface(_THIS, SDL_Surface *surface) | |
1086 { | |
1087 GWorldPtr temp; | |
1088 | |
1089 if ( DSp_NewHWSurface (this, &temp, surface->format->BitsPerPixel, surface->w, surface->h) < 0 ) | |
1090 return (-1); | |
1091 | |
1092 surface->hwdata = (private_hwdata*) malloc (sizeof (private_hwdata)); | |
1093 if (surface->hwdata == NULL) { | |
1094 SDL_OutOfMemory (); | |
1095 return -1; | |
1096 } | |
1097 | |
1098 memset (surface->hwdata, 0, sizeof(private_hwdata)); | |
1099 surface->hwdata->offscreen = temp; | |
1100 surface->pitch = GetPixRowBytes (GetPortPixMap (temp)) & 0x3FFF; | |
1101 surface->pixels = GetPixBaseAddr (GetPortPixMap (temp)); | |
1102 surface->flags |= SDL_HWSURFACE; | |
1103 #ifdef DSP_TRY_CC_AND_AA | |
1104 surface->flags |= SDL_HWACCEL; | |
1105 #endif | |
1106 return 0; | |
1107 } | |
1108 | |
1109 static void DSp_FreeHWSurface(_THIS, SDL_Surface *surface) | |
1110 { | |
1111 if (surface->hwdata->offscreen != NULL) | |
1112 DisposeGWorld (surface->hwdata->offscreen); | |
1113 free (surface->hwdata); | |
1114 | |
1115 surface->pixels = NULL; | |
1116 } | |
1117 | |
1118 static int DSp_CheckHWBlit(_THIS, SDL_Surface *src, SDL_Surface *dest) | |
1119 { | |
1120 int accelerated; | |
1121 | |
1122 /* Set initial acceleration on */ | |
1123 src->flags |= SDL_HWACCEL; | |
1124 | |
1125 /* Set the surface attributes */ | |
1126 if ( (src->flags & SDL_SRCALPHA) == SDL_SRCALPHA ) { | |
1127 if ( ! this->info.blit_hw_A ) { | |
1128 src->flags &= ~SDL_HWACCEL; | |
1129 } | |
1130 } | |
1131 if ( (src->flags & SDL_SRCCOLORKEY) == SDL_SRCCOLORKEY ) { | |
1132 if ( ! this->info.blit_hw_CC ) { | |
1133 src->flags &= ~SDL_HWACCEL; | |
1134 } | |
1135 } | |
1136 | |
1137 /* Check to see if final surface blit is accelerated */ | |
1138 accelerated = !!(src->flags & SDL_HWACCEL); | |
1139 if ( accelerated ) { | |
1140 src->map->hw_blit = DSp_HWAccelBlit; | |
1141 } | |
1142 return(accelerated); | |
1143 } | |
1144 | |
1145 static int DSp_HWAccelBlit(SDL_Surface *src, SDL_Rect *srcrect, | |
1146 SDL_Surface *dst, SDL_Rect *dstrect) | |
1147 { | |
1148 CGrafPtr save_port; | |
1149 GDHandle save_device; | |
1150 Rect src_rect, dst_rect; | |
1151 RGBColor black = { 0, 0, 0 }; | |
1152 RGBColor white = { 0xFFFF, 0xFFFF, 0xFFFF }; | |
1153 | |
1154 #ifdef DSP_TRY_CC_AND_AA | |
1155 UInt32 mode; | |
1156 #endif | |
1157 | |
1158 SetRect (&src_rect, srcrect->x, srcrect->y, srcrect->x + srcrect->w, srcrect->y + srcrect->h); | |
1159 SetRect (&dst_rect, dstrect->x, dstrect->y, dstrect->x + dstrect->w, dstrect->y + dstrect->h); | |
1160 | |
1161 GetGWorld (&save_port, &save_device); | |
1162 SetGWorld (dst->hwdata->offscreen, NULL); | |
1163 | |
1164 RGBForeColor (&black); | |
1165 RGBBackColor (&white); | |
1166 | |
1167 #ifdef DSP_TRY_CC_AND_AA | |
1168 | |
1169 if ( (src->flags & SDL_SRCCOLORKEY) && | |
1170 (src->flags & SDL_SRCALPHA) ) { | |
1171 | |
1172 OpColor (&(src->hwdata->alpha)); | |
1173 | |
1174 CopyDeepMask ( GetPortBitMapForCopyBits(src->hwdata->offscreen), | |
1175 GetPortBitMapForCopyBits(src->hwdata->mask), | |
1176 GetPortBitMapForCopyBits(dst->hwdata->offscreen), | |
1177 &src_rect, &src_rect, &dst_rect, | |
1178 blend, | |
1179 NULL ); | |
1180 } | |
1181 else { | |
1182 | |
1183 if ( src->flags & SDL_SRCCOLORKEY) { | |
1184 RGBBackColor (&(src->hwdata->trans) ); | |
1185 mode = transparent; | |
1186 } | |
1187 else if (src->flags & SDL_SRCALPHA) { | |
1188 | |
1189 OpColor (&(src->hwdata->alpha)); | |
1190 mode = blend; | |
1191 } | |
1192 else { | |
1193 | |
1194 mode = srcCopy; | |
1195 } | |
1196 | |
1197 CopyBits ( GetPortBitMapForCopyBits(src->hwdata->offscreen), | |
1198 GetPortBitMapForCopyBits(dst->hwdata->offscreen), | |
1199 &src_rect, &dst_rect, mode, NULL ); | |
1200 } | |
1201 #else | |
1202 | |
1203 CopyBits ( &(((GrafPtr)(src->hwdata->offscreen))->portBits), | |
1204 &(((GrafPtr)(dst->hwdata->offscreen))->portBits), | |
1205 &src_rect, &dst_rect, srcCopy, NULL ); | |
1206 | |
1207 #endif /* DSP_TRY_CC_AND_AA */ | |
1208 | |
1209 SetGWorld (save_port, save_device); | |
1210 | |
1211 return(0); | |
1212 } | |
1213 | |
1214 static int DSp_FillHWRect(_THIS, SDL_Surface *dst, SDL_Rect *rect, Uint32 color) | |
1215 { | |
1216 CGrafPtr save_port; | |
1217 GDHandle save_device; | |
1218 Rect fill_rect; | |
1219 RGBColor rgb; | |
1220 | |
1221 SetRect (&fill_rect, rect->x, rect->y, rect->x + rect->w, rect->y + rect->h); | |
1222 | |
1223 GetGWorld (&save_port, &save_device); | |
1224 SetGWorld (dst->hwdata->offscreen, NULL); | |
1225 | |
1226 Index2Color (color, &rgb); | |
1227 | |
1228 RGBForeColor (&rgb); | |
1229 PaintRect (&fill_rect); | |
1230 | |
1231 SetGWorld (save_port, save_device); | |
1232 | |
1233 return(0); | |
1234 } | |
1235 | |
1236 static int DSp_FlipHWSurface(_THIS, SDL_Surface *surface) | |
1237 { | |
1238 if ( (surface->flags & SDL_HWSURFACE) ) { | |
1239 CGrafPtr dsp_front_buffer, save_port; | |
1240 Rect rect; | |
1241 | |
1133
609c060fd2a2
The MacOSX Carbon/Cocoa/X11 all in one library patch. Relevant emails:
Ryan C. Gordon <icculus@icculus.org>
parents:
1032
diff
changeset
|
1242 #if ! TARGET_API_MAC_OSX |
0 | 1243 unsigned int old_count; |
1133
609c060fd2a2
The MacOSX Carbon/Cocoa/X11 all in one library patch. Relevant emails:
Ryan C. Gordon <icculus@icculus.org>
parents:
1032
diff
changeset
|
1244 #endif |
609c060fd2a2
The MacOSX Carbon/Cocoa/X11 all in one library patch. Relevant emails:
Ryan C. Gordon <icculus@icculus.org>
parents:
1032
diff
changeset
|
1245 |
0 | 1246 /* pseudo page flipping for VRAM back buffer*/ |
1247 DSpContext_GetFrontBuffer (dsp_context, &dsp_front_buffer); | |
1248 SetRect (&rect, 0, 0, surface->w-1, surface->h-1); | |
1249 | |
1250 GetPort ((GrafPtr *)&save_port); | |
1251 SetPort ((GrafPtr)dsp_front_buffer); | |
1252 | |
1253 /* wait for retrace */ | |
1254 /* I have tried doing the swap in interrupt routine (VBL Proc) to do */ | |
1255 /* it asynchronously, but apparently CopyBits isn't interrupt safe */ | |
1256 | |
1257 #if ! TARGET_API_MAC_OSX | |
1258 #ifndef DSP_NO_SYNC_VBL | |
1259 old_count = retrace_count; | |
1260 while (old_count == retrace_count) | |
1261 ; | |
1262 #endif | |
1263 #endif | |
1264 | |
1265 CopyBits ( GetPortBitMapForCopyBits(dsp_back_buffer), | |
1266 GetPortBitMapForCopyBits(dsp_front_buffer), | |
1267 &rect, &rect, srcCopy, NULL ); | |
1268 | |
1269 SetPort ((GrafPtr)save_port); | |
1270 | |
1271 } else { | |
1272 /* not really page flipping at all: DSp just blits the dirty rectangles from DSp_UpdateRects */ | |
1273 Boolean busy_flag; | |
1274 DSpContext_SwapBuffers (dsp_context, NULL, &busy_flag); /* this waits for VBL */ | |
1275 DSpContext_GetBackBuffer (dsp_context, kDSpBufferKind_Normal, &dsp_back_buffer); | |
1276 surface->pixels = GetPixBaseAddr( GetPortPixMap(dsp_back_buffer) ); | |
1277 } | |
1278 return(0); | |
1279 } | |
1280 | |
1281 static int DSp_LockHWSurface(_THIS, SDL_Surface *surface) | |
1282 { | |
1283 if ( LockPixels (GetGWorldPixMap (surface->hwdata->offscreen)) ) | |
1284 return 0; | |
1285 else | |
1286 return -1; | |
1287 } | |
1288 | |
1289 static void DSp_UnlockHWSurface(_THIS, SDL_Surface *surface) | |
1290 { | |
1291 UnlockPixels (GetGWorldPixMap (surface->hwdata->offscreen)); | |
1292 } | |
1293 | |
1294 static void DSp_DirectUpdate(_THIS, int numrects, SDL_Rect *sdl_rects) | |
1295 { | |
1296 return; | |
1297 } | |
1298 | |
1299 static void DSp_DSpUpdate(_THIS, int numrects, SDL_Rect *sdl_rects) | |
1300 { | |
1301 #if ! TARGET_API_MAC_OSX /* Unsupported DSp in here */ | |
1302 int i; | |
1303 Rect rect; | |
1304 | |
1305 for (i = 0; i < numrects; i++) { | |
1306 | |
1307 rect.top = sdl_rects[i].y; | |
1308 rect.left = sdl_rects[i].x; | |
1309 rect.bottom = sdl_rects[i].h + sdl_rects[i].y; | |
1310 rect.right = sdl_rects[i].w + sdl_rects[i].x; | |
1311 | |
1312 DSpContext_InvalBackBufferRect (dsp_context, &rect); | |
1313 } | |
1314 #endif | |
1315 } | |
1316 | |
1317 static int DSp_CreatePalette(_THIS) { | |
1318 | |
1319 | |
1320 /* Create our palette */ | |
1321 SDL_CTab = (CTabHandle)NewHandle(sizeof(ColorSpec)*256 + 8); | |
1322 if ( SDL_CTab == nil ) { | |
1323 SDL_OutOfMemory(); | |
1324 return(-1); | |
1325 } | |
1326 (**SDL_CTab).ctSeed = GetCTSeed(); | |
1327 (**SDL_CTab).ctFlags = 0; | |
1328 (**SDL_CTab).ctSize = 255; | |
1329 CTabChanged(SDL_CTab); | |
1330 SDL_CPal = NewPalette(256, SDL_CTab, pmExplicit+pmTolerant, 0); | |
1331 | |
1332 return 0; | |
1333 } | |
1334 | |
1335 static int DSp_DestroyPalette(_THIS) { | |
1336 | |
1337 /* Free palette and restore original one */ | |
1338 if ( SDL_CTab != nil ) { | |
1339 DisposeHandle((Handle)SDL_CTab); | |
1340 SDL_CTab = nil; | |
1341 } | |
1342 if ( SDL_CPal != nil ) { | |
1343 DisposePalette(SDL_CPal); | |
1344 SDL_CPal = nil; | |
1345 } | |
1346 RestoreDeviceClut(SDL_Display); | |
1347 | |
1348 return (0); | |
1349 } | |
1350 | |
1351 static int DSp_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors) | |
1352 { | |
1353 CTabHandle cTab; | |
1354 | |
1355 int i; | |
1356 | |
1357 cTab = SDL_CTab; | |
1358 | |
1359 /* Verify the range of colors */ | |
1360 if ( (firstcolor+ncolors) > ((**cTab).ctSize+1) ) { | |
1361 return(0); | |
1362 } | |
1363 | |
1364 /* Set the screen palette and update the display */ | |
1365 for(i = 0; i < ncolors; i++) { | |
1366 int j = firstcolor + i; | |
1367 (**cTab).ctTable[j].value = j; | |
1368 (**cTab).ctTable[j].rgb.red = colors[i].r << 8 | colors[i].r; | |
1369 (**cTab).ctTable[j].rgb.green = colors[i].g << 8 | colors[i].g; | |
1370 (**cTab).ctTable[j].rgb.blue = colors[i].b << 8 | colors[i].b; | |
1371 } | |
1372 | |
1373 SetGDevice(SDL_Display); | |
1374 SetEntries(0, (**cTab).ctSize, (ColorSpec *)&(**cTab).ctTable); | |
1375 | |
1376 return(1); | |
1377 } | |
1378 | |
1379 void DSp_VideoQuit(_THIS) | |
1380 { | |
1381 int i; | |
1382 | |
1383 /* Free current video mode */ | |
1384 DSp_UnsetVideoMode(this, this->screen); | |
1385 | |
1386 /* Free Palette and restore original */ | |
1387 DSp_DestroyPalette (this); | |
1388 | |
1389 /* Free list of video modes */ | |
1390 if ( SDL_modelist != NULL ) { | |
1391 for ( i=0; SDL_modelist[i]; i++ ) { | |
1392 free(SDL_modelist[i]); | |
1393 } | |
1394 free(SDL_modelist); | |
1395 SDL_modelist = NULL; | |
1396 } | |
1397 | |
1398 /* Unload DrawSprocket */ | |
1399 DSpShutdown (); | |
1400 } | |
1401 | |
1402 #ifdef HAVE_OPENGL | |
1403 | |
1404 /* swap buffers with v-sync */ | |
1405 static void DSp_GL_SwapBuffers (_THIS) { | |
1406 | |
1407 #ifndef DSP_NO_SYNC_OPENGL | |
1408 | |
1409 unsigned int old_count; | |
1410 | |
1411 old_count = retrace_count; | |
1412 while (old_count == retrace_count) | |
1413 ; | |
1414 #endif | |
1415 | |
1416 aglSwapBuffers (glContext); | |
1417 } | |
1418 | |
1419 #endif |