Mercurial > sdl-ios-xcode
comparison src/video/quartz/SDL_QuartzVideo.m @ 390:19e73568a75c
Date: Sat, 1 Jun 2002 17:56:45 -0500
From: Darrell Walisser <dwaliss1@purdue.edu>
Subject: mac patch
In this patch:
- yuv code
- links to QuickTime
- tabs -> 4 spaces
- mouse events fix
- SDLMain path parsing fix
- BUGS updates
- some miscellaneous docs/comments/code cleanup
author | Sam Lantinga <slouken@libsdl.org> |
---|---|
date | Sat, 01 Jun 2002 23:05:05 +0000 |
parents | f0e5198a1522 |
children | 140798e1e7a6 |
comparison
equal
deleted
inserted
replaced
389:ca655a7a9d80 | 390:19e73568a75c |
---|---|
29 | 29 |
30 /* Include files into one compile unit...break apart eventually */ | 30 /* Include files into one compile unit...break apart eventually */ |
31 #include "SDL_QuartzWM.m" | 31 #include "SDL_QuartzWM.m" |
32 #include "SDL_QuartzEvents.m" | 32 #include "SDL_QuartzEvents.m" |
33 #include "SDL_QuartzWindow.m" | 33 #include "SDL_QuartzWindow.m" |
34 | |
35 | 34 |
36 /* Bootstrap binding, enables entry point into the driver */ | 35 /* Bootstrap binding, enables entry point into the driver */ |
37 VideoBootStrap QZ_bootstrap = { | 36 VideoBootStrap QZ_bootstrap = { |
38 "Quartz", "Mac OS X CoreGraphics", QZ_Available, QZ_CreateDevice | 37 "Quartz", "Mac OS X CoreGraphics", QZ_Available, QZ_CreateDevice |
39 }; | 38 }; |
98 device->SetIcon = QZ_SetIcon; | 97 device->SetIcon = QZ_SetIcon; |
99 device->IconifyWindow = QZ_IconifyWindow; | 98 device->IconifyWindow = QZ_IconifyWindow; |
100 /*device->GetWMInfo = QZ_GetWMInfo;*/ | 99 /*device->GetWMInfo = QZ_GetWMInfo;*/ |
101 device->GrabInput = QZ_GrabInput; | 100 device->GrabInput = QZ_GrabInput; |
102 | 101 |
103 device->free = QZ_DeleteDevice; | 102 device->CreateYUVOverlay = QZ_CreateYUVOverlay; |
103 | |
104 device->free = QZ_DeleteDevice; | |
104 | 105 |
105 return device; | 106 return device; |
106 } | 107 } |
107 | 108 |
108 static void QZ_DeleteDevice (SDL_VideoDevice *device) { | 109 static void QZ_DeleteDevice (SDL_VideoDevice *device) { |
133 | 134 |
134 return 0; | 135 return 0; |
135 } | 136 } |
136 | 137 |
137 static SDL_Rect** QZ_ListModes (_THIS, SDL_PixelFormat *format, Uint32 flags) { | 138 static SDL_Rect** QZ_ListModes (_THIS, SDL_PixelFormat *format, Uint32 flags) { |
138 | 139 |
139 CFIndex num_modes; | 140 CFIndex num_modes; |
140 CFIndex i; | 141 CFIndex i; |
141 | 142 |
142 static SDL_Rect **list = NULL; | 143 static SDL_Rect **list = NULL; |
143 int list_size = 0; | 144 int list_size = 0; |
144 | 145 |
145 /* Any windowed mode is acceptable */ | 146 /* Any windowed mode is acceptable */ |
146 if ( (flags & SDL_FULLSCREEN) == 0 ) | 147 if ( (flags & SDL_FULLSCREEN) == 0 ) |
147 return (SDL_Rect**)-1; | 148 return (SDL_Rect**)-1; |
148 | 149 |
149 /* Free memory from previous call, if any */ | 150 /* Free memory from previous call, if any */ |
150 if ( list != NULL ) { | 151 if ( list != NULL ) { |
151 | 152 |
152 int i; | 153 int i; |
153 | 154 |
154 for (i = 0; list[i] != NULL; i++) | 155 for (i = 0; list[i] != NULL; i++) |
155 free (list[i]); | 156 free (list[i]); |
156 | 157 |
157 free (list); | 158 free (list); |
158 list = NULL; | 159 list = NULL; |
159 } | 160 } |
160 | 161 |
161 num_modes = CFArrayGetCount (mode_list); | 162 num_modes = CFArrayGetCount (mode_list); |
162 | 163 |
163 /* Build list of modes with the requested bpp */ | 164 /* Build list of modes with the requested bpp */ |
164 for (i = 0; i < num_modes; i++) { | 165 for (i = 0; i < num_modes; i++) { |
165 | 166 |
166 CFDictionaryRef onemode; | 167 CFDictionaryRef onemode; |
167 CFNumberRef number; | 168 CFNumberRef number; |
168 int bpp; | 169 int bpp; |
169 | 170 |
170 onemode = CFArrayGetValueAtIndex (mode_list, i); | 171 onemode = CFArrayGetValueAtIndex (mode_list, i); |
171 number = CFDictionaryGetValue (onemode, kCGDisplayBitsPerPixel); | 172 number = CFDictionaryGetValue (onemode, kCGDisplayBitsPerPixel); |
172 CFNumberGetValue (number, kCFNumberSInt32Type, &bpp); | 173 CFNumberGetValue (number, kCFNumberSInt32Type, &bpp); |
173 | 174 |
174 if (bpp == format->BitsPerPixel) { | 175 if (bpp == format->BitsPerPixel) { |
175 | 176 |
176 int intvalue; | 177 int intvalue; |
177 int hasMode; | 178 int hasMode; |
178 int width, height; | 179 int width, height; |
179 | 180 |
180 number = CFDictionaryGetValue (onemode, kCGDisplayWidth); | 181 number = CFDictionaryGetValue (onemode, kCGDisplayWidth); |
181 CFNumberGetValue (number, kCFNumberSInt32Type, &intvalue); | 182 CFNumberGetValue (number, kCFNumberSInt32Type, &intvalue); |
182 width = (Uint16) intvalue; | 183 width = (Uint16) intvalue; |
183 | 184 |
184 number = CFDictionaryGetValue (onemode, kCGDisplayHeight); | 185 number = CFDictionaryGetValue (onemode, kCGDisplayHeight); |
185 CFNumberGetValue (number, kCFNumberSInt32Type, &intvalue); | 186 CFNumberGetValue (number, kCFNumberSInt32Type, &intvalue); |
186 height = (Uint16) intvalue; | 187 height = (Uint16) intvalue; |
187 | 188 |
188 /* Check if mode is already in the list */ | 189 /* Check if mode is already in the list */ |
189 { | 190 { |
190 int i; | 191 int i; |
191 hasMode = SDL_FALSE; | 192 hasMode = SDL_FALSE; |
192 for (i = 0; i < list_size; i++) { | 193 for (i = 0; i < list_size; i++) { |
193 if (list[i]->w == width && list[i]->h == height) { | 194 if (list[i]->w == width && list[i]->h == height) { |
194 hasMode = SDL_TRUE; | 195 hasMode = SDL_TRUE; |
195 break; | 196 break; |
197 } | |
196 } | 198 } |
197 } | 199 } |
198 } | 200 |
199 | 201 /* Grow the list and add mode to the list */ |
200 /* Grow the list and add mode to the list */ | 202 if ( ! hasMode ) { |
201 if ( ! hasMode ) { | 203 |
202 | 204 SDL_Rect *rect; |
203 SDL_Rect *rect; | 205 |
204 | 206 list_size++; |
205 list_size++; | 207 |
206 | 208 if (list == NULL) |
207 if (list == NULL) | 209 list = (SDL_Rect**) malloc (sizeof(*list) * (list_size+1) ); |
208 list = (SDL_Rect**) malloc (sizeof(*list) * (list_size+1) ); | 210 else |
209 else | 211 list = (SDL_Rect**) realloc (list, sizeof(*list) * (list_size+1)); |
210 list = (SDL_Rect**) realloc (list, sizeof(*list) * (list_size+1)); | 212 |
211 | 213 rect = (SDL_Rect*) malloc (sizeof(**list)); |
212 rect = (SDL_Rect*) malloc (sizeof(**list)); | 214 |
213 | 215 if (list == NULL || rect == NULL) { |
214 if (list == NULL || rect == NULL) { | 216 SDL_OutOfMemory (); |
215 SDL_OutOfMemory (); | 217 return NULL; |
216 return NULL; | 218 } |
219 | |
220 rect->w = width; | |
221 rect->h = height; | |
222 | |
223 list[list_size-1] = rect; | |
224 list[list_size] = NULL; | |
217 } | 225 } |
218 | 226 } |
219 rect->w = width; | 227 } |
220 rect->h = height; | 228 |
221 | |
222 list[list_size-1] = rect; | |
223 list[list_size] = NULL; | |
224 } | |
225 } | |
226 } | |
227 | |
228 /* Sort list largest to smallest (by area) */ | 229 /* Sort list largest to smallest (by area) */ |
229 { | 230 { |
230 int i, j; | 231 int i, j; |
231 for (i = 0; i < list_size; i++) { | 232 for (i = 0; i < list_size; i++) { |
232 for (j = 0; j < list_size-1; j++) { | 233 for (j = 0; j < list_size-1; j++) { |
233 | 234 |
234 int area1, area2; | 235 int area1, area2; |
235 area1 = list[j]->w * list[j]->h; | 236 area1 = list[j]->w * list[j]->h; |
236 area2 = list[j+1]->w * list[j+1]->h; | 237 area2 = list[j+1]->w * list[j+1]->h; |
237 | 238 |
238 if (area1 < area2) { | 239 if (area1 < area2) { |
239 SDL_Rect *tmp = list[j]; | 240 SDL_Rect *tmp = list[j]; |
240 list[j] = list[j+1]; | 241 list[j] = list[j+1]; |
241 list[j+1] = tmp; | 242 list[j+1] = tmp; |
242 } | 243 } |
297 /* Fade the display from black to normal */ | 298 /* Fade the display from black to normal */ |
298 /* Restore previously saved gamma values */ | 299 /* Restore previously saved gamma values */ |
299 static UInt32 QZ_FadeGammaIn (_THIS, SDL_QuartzGammaTable *table) { | 300 static UInt32 QZ_FadeGammaIn (_THIS, SDL_QuartzGammaTable *table) { |
300 | 301 |
301 CGGammaValue redTable[QZ_GAMMA_TABLE_SIZE], | 302 CGGammaValue redTable[QZ_GAMMA_TABLE_SIZE], |
302 greenTable[QZ_GAMMA_TABLE_SIZE], | 303 greenTable[QZ_GAMMA_TABLE_SIZE], |
303 blueTable[QZ_GAMMA_TABLE_SIZE]; | 304 blueTable[QZ_GAMMA_TABLE_SIZE]; |
304 | 305 |
305 float percent; | 306 float percent; |
306 int j; | 307 int j; |
307 | 308 |
308 memset (redTable, 0, sizeof(redTable)); | 309 memset (redTable, 0, sizeof(redTable)); |
309 memset (greenTable, 0, sizeof(greenTable)); | 310 memset (greenTable, 0, sizeof(greenTable)); |
310 memset (blueTable, 0, sizeof(greenTable)); | 311 memset (blueTable, 0, sizeof(greenTable)); |
311 | 312 |
312 for (percent = 0.0; percent <= 1.0; percent += 0.01) { | 313 for (percent = 0.0; percent <= 1.0; percent += 0.01) { |
313 | 314 |
314 for (j = 0; j < QZ_GAMMA_TABLE_SIZE; j++) { | 315 for (j = 0; j < QZ_GAMMA_TABLE_SIZE; j++) { |
315 | 316 |
316 redTable[j] = table->red[j] * percent; | 317 redTable[j] = table->red[j] * percent; |
336 | 337 |
337 /* Reset values that may change between switches */ | 338 /* Reset values that may change between switches */ |
338 this->info.blit_fill = 0; | 339 this->info.blit_fill = 0; |
339 this->FillHWRect = NULL; | 340 this->FillHWRect = NULL; |
340 this->UpdateRects = NULL; | 341 this->UpdateRects = NULL; |
341 | 342 |
342 /* Release fullscreen resources */ | 343 /* Release fullscreen resources */ |
343 if ( mode_flags & SDL_FULLSCREEN ) { | 344 if ( mode_flags & SDL_FULLSCREEN ) { |
344 | 345 |
345 SDL_QuartzGammaTable gamma_table; | 346 SDL_QuartzGammaTable gamma_table; |
346 int gamma_error; | 347 int gamma_error; |
349 | 350 |
350 /* Release the OpenGL context */ | 351 /* Release the OpenGL context */ |
351 /* Do this first to avoid trash on the display before fade */ | 352 /* Do this first to avoid trash on the display before fade */ |
352 if ( mode_flags & SDL_OPENGL ) | 353 if ( mode_flags & SDL_OPENGL ) |
353 QZ_TearDownOpenGL (this); | 354 QZ_TearDownOpenGL (this); |
354 | 355 |
355 if (mode_flags & SDL_OPENGL) | 356 if (mode_flags & SDL_OPENGL) |
356 CGLSetFullScreen(NULL); | 357 CGLSetFullScreen(NULL); |
357 | 358 |
358 /* Restore original screen resolution/bpp */ | 359 /* Restore original screen resolution/bpp */ |
359 CGDisplaySwitchToMode (display_id, save_mode); | 360 CGDisplaySwitchToMode (display_id, save_mode); |
360 CGDisplayRelease (display_id); | 361 CGDisplayRelease (display_id); |
361 ShowMenuBar (); | 362 ShowMenuBar (); |
362 | 363 |
363 if (! gamma_error) | 364 if (! gamma_error) |
364 QZ_FadeGammaIn (this, &gamma_table); | 365 QZ_FadeGammaIn (this, &gamma_table); |
365 } | 366 } |
366 /* Release window mode resources */ | 367 /* Release window mode resources */ |
367 else { | 368 else { |
368 if ( (mode_flags & SDL_OPENGL) == 0 ) { | 369 if ( (mode_flags & SDL_OPENGL) == 0 ) { |
369 UnlockPortBits ( [ window_view qdPort ] ); | 370 UnlockPortBits ( [ window_view qdPort ] ); |
370 [ window_view release ]; | 371 [ window_view release ]; |
371 } | 372 } |
372 [ qz_window setContentView:nil ]; | 373 [ qz_window setContentView:nil ]; |
373 [ qz_window setDelegate:nil ]; | 374 [ qz_window setDelegate:nil ]; |
374 [ qz_window close ]; | 375 [ qz_window close ]; |
375 [ qz_window release ]; | 376 [ qz_window release ]; |
376 qz_window = nil; | 377 qz_window = nil; |
377 | 378 |
378 /* Release the OpenGL context */ | 379 /* Release the OpenGL context */ |
379 if ( mode_flags & SDL_OPENGL ) | 380 if ( mode_flags & SDL_OPENGL ) |
380 QZ_TearDownOpenGL (this); | 381 QZ_TearDownOpenGL (this); |
381 } | 382 } |
382 | 383 |
383 /* Restore gamma settings */ | 384 /* Restore gamma settings */ |
384 CGDisplayRestoreColorSyncSettings (); | 385 CGDisplayRestoreColorSyncSettings (); |
385 | 386 |
386 /* Set pixels to null (so other code doesn't try to free it) */ | 387 /* Set pixels to null (so other code doesn't try to free it) */ |
387 if (this->screen != NULL) | 388 if (this->screen != NULL) |
388 this->screen->pixels = NULL; | 389 this->screen->pixels = NULL; |
389 | 390 |
390 /* Ensure the cursor will be visible and working when we quit */ | 391 /* Ensure the cursor will be visible and working when we quit */ |
391 CGDisplayShowCursor (display_id); | 392 CGDisplayShowCursor (display_id); |
392 CGAssociateMouseAndMouseCursorPosition (1); | 393 CGAssociateMouseAndMouseCursorPosition (1); |
393 | 394 |
394 /* Signal successful teardown */ | 395 /* Signal successful teardown */ |
395 video_set = SDL_FALSE; | 396 video_set = SDL_FALSE; |
396 } | 397 } |
397 | 398 |
398 static SDL_Surface* QZ_SetVideoFullScreen (_THIS, SDL_Surface *current, int width, | 399 static SDL_Surface* QZ_SetVideoFullScreen (_THIS, SDL_Surface *current, int width, |
399 int height, int bpp, Uint32 flags) { | 400 int height, int bpp, Uint32 flags) { |
400 int exact_match; | 401 int exact_match; |
401 int gamma_error; | 402 int gamma_error; |
402 SDL_QuartzGammaTable gamma_table; | 403 SDL_QuartzGammaTable gamma_table; |
403 | 404 |
404 /* See if requested mode exists */ | 405 /* See if requested mode exists */ |
405 mode = CGDisplayBestModeForParameters (display_id, bpp, width, | 406 mode = CGDisplayBestModeForParameters (display_id, bpp, width, |
406 height, &exact_match); | 407 height, &exact_match); |
407 | 408 |
408 /* Require an exact match to the requested mode */ | 409 /* Require an exact match to the requested mode */ |
409 if ( ! exact_match ) { | 410 if ( ! exact_match ) { |
410 sprintf (QZ_Error, "Failed to find display resolution: %dx%dx%d", width, height, bpp); | 411 sprintf (QZ_Error, "Failed to find display resolution: %dx%dx%d", width, height, bpp); |
411 SDL_SetError (QZ_Error); | 412 SDL_SetError (QZ_Error); |
412 goto ERR_NO_MATCH; | 413 goto ERR_NO_MATCH; |
419 if ( CGDisplayNoErr != CGDisplayCapture (display_id) ) { | 420 if ( CGDisplayNoErr != CGDisplayCapture (display_id) ) { |
420 SDL_SetError ("Failed capturing display"); | 421 SDL_SetError ("Failed capturing display"); |
421 goto ERR_NO_CAPTURE; | 422 goto ERR_NO_CAPTURE; |
422 } | 423 } |
423 | 424 |
424 | 425 |
425 /* Do the physical switch */ | 426 /* Do the physical switch */ |
426 if ( CGDisplayNoErr != CGDisplaySwitchToMode (display_id, mode) ) { | 427 if ( CGDisplayNoErr != CGDisplaySwitchToMode (display_id, mode) ) { |
427 SDL_SetError ("Failed switching display resolution"); | 428 SDL_SetError ("Failed switching display resolution"); |
428 goto ERR_NO_SWITCH; | 429 goto ERR_NO_SWITCH; |
429 } | 430 } |
432 current->pitch = CGDisplayBytesPerRow (display_id); | 433 current->pitch = CGDisplayBytesPerRow (display_id); |
433 | 434 |
434 current->flags = 0; | 435 current->flags = 0; |
435 current->w = width; | 436 current->w = width; |
436 current->h = height; | 437 current->h = height; |
437 current->flags |= SDL_FULLSCREEN; | 438 current->flags |= SDL_FULLSCREEN; |
438 current->flags |= SDL_HWSURFACE; | 439 current->flags |= SDL_HWSURFACE; |
439 | 440 |
440 this->UpdateRects = QZ_DirectUpdate; | 441 this->UpdateRects = QZ_DirectUpdate; |
441 | 442 |
442 /* Setup some mode-dependant info */ | 443 /* Setup some mode-dependant info */ |
443 if ( CGSDisplayCanHWFill (display_id) ) { | 444 if ( CGSDisplayCanHWFill (display_id) ) { |
444 this->info.blit_fill = 1; | 445 this->info.blit_fill = 1; |
445 this->FillHWRect = QZ_FillHWRect; | 446 this->FillHWRect = QZ_FillHWRect; |
446 } | 447 } |
447 | 448 |
448 if ( CGDisplayCanSetPalette (display_id) ) | 449 if ( CGDisplayCanSetPalette (display_id) ) |
449 current->flags |= SDL_HWPALETTE; | 450 current->flags |= SDL_HWPALETTE; |
450 | 451 |
451 /* Setup OpenGL for a fullscreen context */ | 452 /* Setup OpenGL for a fullscreen context */ |
452 if (flags & SDL_OPENGL) { | 453 if (flags & SDL_OPENGL) { |
453 | 454 |
454 CGLError err; | 455 CGLError err; |
455 CGLContextObj ctx; | 456 CGLContextObj ctx; |
456 | 457 |
457 if ( ! QZ_SetupOpenGL (this, bpp, flags) ) { | 458 if ( ! QZ_SetupOpenGL (this, bpp, flags) ) { |
458 goto ERR_NO_GL; | 459 goto ERR_NO_GL; |
459 } | 460 } |
460 | 461 |
461 ctx = [ gl_context cglContext ]; | 462 ctx = [ gl_context cglContext ]; |
462 err = CGLSetFullScreen (ctx); | 463 err = CGLSetFullScreen (ctx); |
463 | 464 |
464 if (err) { | 465 if (err) { |
465 sprintf (QZ_Error, "Error setting OpenGL fullscreen: %s", CGLErrorString(err)); | 466 sprintf (QZ_Error, "Error setting OpenGL fullscreen: %s", CGLErrorString(err)); |
466 SDL_SetError (QZ_Error); | 467 SDL_SetError (QZ_Error); |
467 goto ERR_NO_GL; | 468 goto ERR_NO_GL; |
468 } | 469 } |
469 | 470 |
470 [ gl_context makeCurrentContext]; | 471 [ gl_context makeCurrentContext]; |
471 | 472 |
472 glClear (GL_COLOR_BUFFER_BIT); | 473 glClear (GL_COLOR_BUFFER_BIT); |
473 | 474 |
474 [ gl_context flushBuffer ]; | 475 [ gl_context flushBuffer ]; |
475 | 476 |
476 current->flags |= SDL_OPENGL; | 477 current->flags |= SDL_OPENGL; |
477 } | 478 } |
478 | 479 |
479 /* If we don't hide menu bar, it will get events and interrupt the program */ | 480 /* If we don't hide menu bar, it will get events and interrupt the program */ |
480 HideMenuBar (); | 481 HideMenuBar (); |
481 | 482 |
482 /* Fade the display to original gamma */ | 483 /* Fade the display to original gamma */ |
483 if (! gamma_error ) | 484 if (! gamma_error ) |
484 QZ_FadeGammaIn (this, &gamma_table); | 485 QZ_FadeGammaIn (this, &gamma_table); |
485 | 486 |
486 /* Save the flags to ensure correct tear-down */ | 487 /* Save the flags to ensure correct tear-down */ |
487 mode_flags = current->flags; | 488 mode_flags = current->flags; |
488 | 489 |
489 return current; | 490 return current; |
490 | 491 |
491 /* Since the blanking window covers *all* windows (even force quit) correct recovery is crucial */ | 492 /* Since the blanking window covers *all* windows (even force quit) correct recovery is crucial */ |
492 ERR_NO_GL: CGDisplaySwitchToMode (display_id, save_mode); | 493 ERR_NO_GL: CGDisplaySwitchToMode (display_id, save_mode); |
493 ERR_NO_SWITCH: CGDisplayRelease (display_id); | 494 ERR_NO_SWITCH: CGDisplayRelease (display_id); |
494 ERR_NO_CAPTURE: if (!gamma_error) { QZ_FadeGammaIn (this, &gamma_table); } | 495 ERR_NO_CAPTURE: if (!gamma_error) { QZ_FadeGammaIn (this, &gamma_table); } |
495 ERR_NO_MATCH: return NULL; | 496 ERR_NO_MATCH: return NULL; |
496 } | 497 } |
497 | 498 |
498 static SDL_Surface* QZ_SetVideoWindowed (_THIS, SDL_Surface *current, int width, | 499 static SDL_Surface* QZ_SetVideoWindowed (_THIS, SDL_Surface *current, int width, |
499 int height, int bpp, Uint32 flags) { | 500 int height, int bpp, Uint32 flags) { |
500 unsigned int style; | 501 unsigned int style; |
501 NSRect rect; | 502 NSRect rect; |
502 rect = NSMakeRect (0, 0, width, height); | 503 rect = NSMakeRect (0, 0, width, height); |
503 | 504 |
504 #if 1 // FIXME - the resize button doesn't show? Also need resize events... | 505 #if 1 // FIXME - the resize button doesn't show? Also need resize events... |
505 flags &= ~SDL_RESIZABLE; | 506 flags &= ~SDL_RESIZABLE; |
506 #endif | 507 #endif |
513 if ( flags & SDL_RESIZABLE ) | 514 if ( flags & SDL_RESIZABLE ) |
514 style |= NSResizableWindowMask; | 515 style |= NSResizableWindowMask; |
515 } | 516 } |
516 | 517 |
517 /* Manually create a window, avoids having a nib file resource */ | 518 /* Manually create a window, avoids having a nib file resource */ |
518 qz_window = [ [ SDL_QuartzWindow alloc ] initWithContentRect:rect | 519 qz_window = [ [ SDL_QuartzWindow alloc ] initWithContentRect:rect |
519 styleMask:style backing:NSBackingStoreBuffered defer:NO ]; | 520 styleMask:style backing:NSBackingStoreBuffered defer:NO ]; |
520 if (qz_window == nil) { | 521 if (qz_window == nil) { |
521 SDL_SetError ("Could not create the Cocoa window"); | 522 SDL_SetError ("Could not create the Cocoa window"); |
522 return NULL; | 523 return NULL; |
523 } | 524 } |
524 | 525 |
525 current->flags = 0; | 526 current->flags = 0; |
526 current->w = width; | 527 current->w = width; |
527 current->h = height; | 528 current->h = height; |
528 | 529 |
529 [ qz_window setReleasedWhenClosed:YES ]; | 530 [ qz_window setReleasedWhenClosed:YES ]; |
530 QZ_SetCaption(this, this->wm_title, this->wm_icon); | 531 QZ_SetCaption(this, this->wm_title, this->wm_icon); |
531 [ qz_window setAcceptsMouseMovedEvents:YES ]; | 532 [ qz_window setAcceptsMouseMovedEvents:YES ]; |
532 [ qz_window setViewsNeedDisplay:NO ]; | 533 [ qz_window setViewsNeedDisplay:NO ]; |
533 [ qz_window center ]; | 534 [ qz_window center ]; |
534 [ qz_window setDelegate: | 535 [ qz_window setDelegate: |
535 [ [ [ SDL_QuartzWindowDelegate alloc ] init ] autorelease ] ]; | 536 [ [ [ SDL_QuartzWindowDelegate alloc ] init ] autorelease ] ]; |
536 | 537 |
537 /* For OpenGL, we set the content view to a NSOpenGLView */ | 538 /* For OpenGL, we set the content view to a NSOpenGLView */ |
538 if ( flags & SDL_OPENGL ) { | 539 if ( flags & SDL_OPENGL ) { |
539 | 540 |
540 if ( ! QZ_SetupOpenGL (this, bpp, flags) ) { | 541 if ( ! QZ_SetupOpenGL (this, bpp, flags) ) { |
541 return NULL; | 542 return NULL; |
542 } | 543 } |
543 | 544 |
544 [ gl_context setView: [ qz_window contentView ] ]; | 545 [ gl_context setView: [ qz_window contentView ] ]; |
545 [ gl_context makeCurrentContext]; | 546 [ gl_context makeCurrentContext]; |
546 [ qz_window makeKeyAndOrderFront:nil ]; | 547 [ qz_window makeKeyAndOrderFront:nil ]; |
547 current->flags |= SDL_OPENGL; | 548 current->flags |= SDL_OPENGL; |
548 } | 549 } |
549 /* For 2D, we set the content view to a NSQuickDrawView */ | 550 /* For 2D, we set the content view to a NSQuickDrawView */ |
550 else { | 551 else { |
551 | 552 |
552 window_view = [ [ SDL_QuartzWindowView alloc ] init ]; | 553 window_view = [ [ SDL_QuartzWindowView alloc ] init ]; |
553 [ qz_window setContentView:window_view ]; | 554 [ qz_window setContentView:window_view ]; |
554 [ qz_window makeKeyAndOrderFront:nil ]; | 555 [ qz_window makeKeyAndOrderFront:nil ]; |
555 | 556 |
556 LockPortBits ( [ window_view qdPort ] ); | 557 LockPortBits ( [ window_view qdPort ] ); |
557 current->pixels = GetPixBaseAddr ( GetPortPixMap ( [ window_view qdPort ] ) ); | 558 current->pixels = GetPixBaseAddr ( GetPortPixMap ( [ window_view qdPort ] ) ); |
558 current->pitch = GetPixRowBytes ( GetPortPixMap ( [ window_view qdPort ] ) ); | 559 current->pitch = GetPixRowBytes ( GetPortPixMap ( [ window_view qdPort ] ) ); |
559 | 560 |
560 current->flags |= SDL_SWSURFACE; | 561 current->flags |= SDL_SWSURFACE; |
561 current->flags |= SDL_PREALLOC; | 562 current->flags |= SDL_PREALLOC; |
562 | 563 |
563 if ( flags & SDL_NOFRAME ) | 564 if ( flags & SDL_NOFRAME ) |
564 current->flags |= SDL_NOFRAME; | 565 current->flags |= SDL_NOFRAME; |
565 if ( flags & SDL_RESIZABLE ) | 566 if ( flags & SDL_RESIZABLE ) |
566 current->flags |= SDL_RESIZABLE; | 567 current->flags |= SDL_RESIZABLE; |
567 | 568 |
568 /* Offset 22 pixels down to fill the full content region */ | 569 /* Offset 22 pixels down to fill the full content region */ |
569 if ( ! (current->flags & SDL_NOFRAME) ) { | 570 if ( ! (current->flags & SDL_NOFRAME) ) { |
570 current->pixels += 22 * current->pitch; | 571 current->pixels += 22 * current->pitch; |
571 } | 572 } |
572 | 573 |
573 this->UpdateRects = QZ_UpdateRects; | 574 this->UpdateRects = QZ_UpdateRects; |
574 } | 575 } |
575 | 576 |
576 /* Save flags to ensure correct teardown */ | 577 /* Save flags to ensure correct teardown */ |
577 mode_flags = current->flags; | 578 mode_flags = current->flags; |
578 | 579 |
579 return current; | 580 return current; |
580 } | 581 } |
581 | 582 |
582 static SDL_Surface* QZ_SetVideoMode (_THIS, SDL_Surface *current, int width, | 583 static SDL_Surface* QZ_SetVideoMode (_THIS, SDL_Surface *current, int width, |
583 int height, int bpp, Uint32 flags) { | 584 int height, int bpp, Uint32 flags) { |
584 | 585 |
585 if (video_set == SDL_TRUE) | 586 if (video_set == SDL_TRUE) |
586 QZ_UnsetVideoMode (this); | 587 QZ_UnsetVideoMode (this); |
587 | 588 |
588 current->flags = 0; | 589 current->flags = 0; |
589 | 590 |
590 /* Setup full screen video */ | 591 /* Setup full screen video */ |
591 if ( flags & SDL_FULLSCREEN ) { | 592 if ( flags & SDL_FULLSCREEN ) { |
592 current = QZ_SetVideoFullScreen (this, current, width, height, bpp, flags ); | 593 current = QZ_SetVideoFullScreen (this, current, width, height, bpp, flags ); |
593 if (current == NULL) | 594 if (current == NULL) |
594 return NULL; | 595 return NULL; |
599 bpp = device_bpp; | 600 bpp = device_bpp; |
600 current = QZ_SetVideoWindowed (this, current, width, height, bpp, flags); | 601 current = QZ_SetVideoWindowed (this, current, width, height, bpp, flags); |
601 if (current == NULL) | 602 if (current == NULL) |
602 return NULL; | 603 return NULL; |
603 } | 604 } |
604 | 605 |
605 /* Setup the new pixel format */ | 606 /* Setup the new pixel format */ |
606 { | 607 { |
607 int amask = 0, | 608 int amask = 0, |
608 rmask = 0, | 609 rmask = 0, |
609 gmask = 0, | 610 gmask = 0, |
610 bmask = 0; | 611 bmask = 0; |
611 | 612 |
612 switch (bpp) { | 613 switch (bpp) { |
613 case 16: /* (1)-5-5-5 RGB */ | 614 case 16: /* (1)-5-5-5 RGB */ |
614 amask = 0; | 615 amask = 0; |
615 rmask = 0x7C00; | 616 rmask = 0x7C00; |
616 gmask = 0x03E0; | 617 gmask = 0x03E0; |
617 bmask = 0x001F; | 618 bmask = 0x001F; |
618 break; | 619 break; |
619 case 24: | 620 case 24: |
624 rmask = 0x00FF0000; | 625 rmask = 0x00FF0000; |
625 gmask = 0x0000FF00; | 626 gmask = 0x0000FF00; |
626 bmask = 0x000000FF; | 627 bmask = 0x000000FF; |
627 break; | 628 break; |
628 } | 629 } |
629 | 630 |
630 if ( ! SDL_ReallocFormat (current, bpp, | 631 if ( ! SDL_ReallocFormat (current, bpp, |
631 rmask, gmask, bmask, amask ) ) { | 632 rmask, gmask, bmask, amask ) ) { |
632 SDL_SetError ("Couldn't reallocate pixel format"); | 633 SDL_SetError ("Couldn't reallocate pixel format"); |
633 return NULL; | 634 return NULL; |
634 } | 635 } |
635 } | 636 } |
636 | 637 |
637 /* Signal successful completion (used internally) */ | 638 /* Signal successful completion (used internally) */ |
638 video_set = SDL_TRUE; | 639 video_set = SDL_TRUE; |
639 | 640 |
640 return current; | 641 return current; |
641 } | 642 } |
642 | 643 |
643 static int QZ_ToggleFullScreen (_THIS, int on) { | 644 static int QZ_ToggleFullScreen (_THIS, int on) { |
644 return -1; | 645 return -1; |
645 } | 646 } |
646 | 647 |
647 static int QZ_SetColors (_THIS, int first_color, int num_colors, | 648 static int QZ_SetColors (_THIS, int first_color, int num_colors, |
648 SDL_Color *colors) { | 649 SDL_Color *colors) { |
649 | 650 |
650 CGTableCount index; | 651 CGTableCount index; |
651 CGDeviceColor color; | 652 CGDeviceColor color; |
652 | 653 |
653 for (index = first_color; index < first_color+num_colors; index++) { | 654 for (index = first_color; index < first_color+num_colors; index++) { |
654 | 655 |
655 /* Clamp colors between 0.0 and 1.0 */ | 656 /* Clamp colors between 0.0 and 1.0 */ |
656 color.red = colors->r / 255.0; | 657 color.red = colors->r / 255.0; |
657 color.blue = colors->b / 255.0; | 658 color.blue = colors->b / 255.0; |
658 color.green = colors->g / 255.0; | 659 color.green = colors->g / 255.0; |
659 | 660 |
660 colors++; | 661 colors++; |
661 | 662 |
662 CGPaletteSetColorAtIndex (palette, color, index); | 663 CGPaletteSetColorAtIndex (palette, color, index); |
663 } | 664 } |
664 | 665 |
665 if ( CGDisplayNoErr != CGDisplaySetPalette (display_id, palette) ) | 666 if ( CGDisplayNoErr != CGDisplaySetPalette (display_id, palette) ) |
666 return 0; | 667 return 0; |
667 | 668 |
668 return 1; | 669 return 1; |
669 } | 670 } |
670 | 671 |
671 static void QZ_DirectUpdate (_THIS, int num_rects, SDL_Rect *rects) { | 672 static void QZ_DirectUpdate (_THIS, int num_rects, SDL_Rect *rects) { |
672 #pragma unused(this,num_rects,rects) | 673 #pragma unused(this,num_rects,rects) |
673 } | 674 } |
674 | 675 |
675 /** | 676 /** |
676 * The obscured code is based on work by Matt Slot fprefect@ambrosiasw.com, | 677 * The obscured code is based on work by Matt Slot fprefect@ambrosiasw.com, |
677 * who supplied sample code for Carbon. | 678 * who supplied sample code for Carbon. |
678 **/ | 679 **/ |
679 static int QZ_IsWindowObscured (NSWindow *window) { | 680 static int QZ_IsWindowObscured (NSWindow *window) { |
680 | 681 |
681 //#define TEST_OBSCURED 1 | 682 //#define TEST_OBSCURED 1 |
682 | 683 |
683 #if TEST_OBSCURED | 684 #if TEST_OBSCURED |
685 | |
686 /* In order to determine if a direct copy to the screen is possible, | |
687 we must figure out if there are any windows covering ours (including shadows). | |
688 This can be done by querying the window server about the on screen | |
689 windows for their screen rectangle and window level. | |
690 The procedure used below is puts accuracy before speed; however, it aims to call | |
691 the window server the fewest number of times possible to keep things reasonable. | |
692 In my testing on a 300mhz G3, this routine typically takes < 2 ms. -DW | |
684 | 693 |
685 /* In order to determine if a direct copy to the screen is possible, | 694 Notes: |
686 we must figure out if there are any windows covering ours (including shadows). | 695 -Calls into the Window Server involve IPC which is slow. |
687 This can be done by querying the window server about the on screen | 696 -Getting a rectangle seems slower than getting the window level |
688 windows for their screen rectangle and window level. | 697 -The window list we get back is in sorted order, top to bottom |
689 The procedure used below is puts accuracy before speed; however, it aims to call | 698 -On average, I suspect, most windows above ours are dock icon windows (hence optimization) |
690 the window server the fewest number of times possible to keep things reasonable. | 699 -Some windows above ours are always there, and cannot move or obscure us (menu bar) |
691 In my testing on a 300mhz G3, this routine typically takes < 2 ms. -DW | |
692 | 700 |
693 Notes: | 701 Bugs: |
694 -Calls into the Window Server involve IPC which is slow. | 702 -no way (yet) to deactivate direct drawing when a window is dragged, |
695 -Getting a rectangle seems slower than getting the window level | 703 or suddenly obscured, so drawing continues and can produce garbage |
696 -The window list we get back is in sorted order, top to bottom | 704 We need some kind of locking mechanism on window movement to prevent this |
697 -On average, I suspect, most windows above ours are dock icon windows (hence optimization) | 705 |
698 -Some windows above ours are always there, and cannot move or obscure us (menu bar) | 706 -deactivated normal windows use activated normal |
699 | 707 window shadows (slight inaccuraccy) |
700 Bugs: | |
701 -no way (yet) to deactivate direct drawing when a window is dragged, | |
702 or suddenly obscured, so drawing continues and can produce garbage | |
703 We need some kind of locking mechanism on window movement to prevent this | |
704 | |
705 -deactivated normal windows use activated normal | |
706 window shadows (slight inaccuraccy) | |
707 */ | 708 */ |
708 | 709 |
709 /* Cache the connection to the window server */ | 710 /* Cache the connection to the window server */ |
710 static CGSConnectionID cgsConnection = (CGSConnectionID) -1; | 711 static CGSConnectionID cgsConnection = (CGSConnectionID) -1; |
711 | 712 |
712 /* Cache the dock icon windows */ | 713 /* Cache the dock icon windows */ |
713 static CGSWindowID dockIcons[kMaxWindows]; | 714 static CGSWindowID dockIcons[kMaxWindows]; |
714 static int numCachedDockIcons = 0; | 715 static int numCachedDockIcons = 0; |
715 | 716 |
716 CGSWindowID windows[kMaxWindows]; | 717 CGSWindowID windows[kMaxWindows]; |
717 CGSWindowCount i, count; | 718 CGSWindowCount i, count; |
718 CGSWindowLevel winLevel; | 719 CGSWindowLevel winLevel; |
719 CGSRect winRect; | 720 CGSRect winRect; |
720 | 721 |
721 CGSRect contentRect; | 722 CGSRect contentRect; |
722 int windowNumber; | 723 int windowNumber; |
723 //int isMainWindow; | 724 //int isMainWindow; |
724 int firstDockIcon; | 725 int firstDockIcon; |
725 int dockIconCacheMiss; | 726 int dockIconCacheMiss; |
726 int windowContentOffset; | 727 int windowContentOffset; |
727 | 728 |
728 int obscured = SDL_TRUE; | 729 int obscured = SDL_TRUE; |
729 | 730 |
730 if ( [ window isVisible ] ) { | 731 if ( [ window isVisible ] ) { |
731 | 732 |
732 /* walk the window list looking for windows over top of | 733 /* walk the window list looking for windows over top of |
733 (or casting a shadow on) ours */ | 734 (or casting a shadow on) ours */ |
734 | 735 |
735 /* Get a connection to the window server */ | 736 /* Get a connection to the window server */ |
736 /* Should probably be moved out into SetVideoMode() or InitVideo() */ | 737 /* Should probably be moved out into SetVideoMode() or InitVideo() */ |
737 if (cgsConnection == (CGSConnectionID) -1) { | 738 if (cgsConnection == (CGSConnectionID) -1) { |
738 cgsConnection = (CGSConnectionID) 0; | 739 cgsConnection = (CGSConnectionID) 0; |
739 cgsConnection = _CGSDefaultConnection (); | 740 cgsConnection = _CGSDefaultConnection (); |
740 } | 741 } |
741 | 742 |
742 if (cgsConnection) { | 743 if (cgsConnection) { |
743 | 744 |
744 if ( ! [ window styleMask ] & NSBorderlessWindowMask ) | 745 if ( ! [ window styleMask ] & NSBorderlessWindowMask ) |
745 windowContentOffset = 22; | 746 windowContentOffset = 22; |
746 else | 747 else |
747 windowContentOffset = 0; | 748 windowContentOffset = 0; |
748 | 749 |
749 windowNumber = [ window windowNumber ]; | 750 windowNumber = [ window windowNumber ]; |
750 //isMainWindow = [ window isMainWindow ]; | 751 //isMainWindow = [ window isMainWindow ]; |
751 | 752 |
752 /* The window list is sorted according to order on the screen */ | 753 /* The window list is sorted according to order on the screen */ |
753 count = 0; | 754 count = 0; |
754 CGSGetOnScreenWindowList (cgsConnection, 0, kMaxWindows, windows, &count); | 755 CGSGetOnScreenWindowList (cgsConnection, 0, kMaxWindows, windows, &count); |
755 CGSGetScreenRectForWindow (cgsConnection, windowNumber, &contentRect); | 756 CGSGetScreenRectForWindow (cgsConnection, windowNumber, &contentRect); |
756 | 757 |
757 /* adjust rect for window title bar (if present) */ | 758 /* adjust rect for window title bar (if present) */ |
758 contentRect.origin.y += windowContentOffset; | 759 contentRect.origin.y += windowContentOffset; |
759 contentRect.size.height -= windowContentOffset; | 760 contentRect.size.height -= windowContentOffset; |
760 | 761 |
761 firstDockIcon = -1; | 762 firstDockIcon = -1; |
762 dockIconCacheMiss = SDL_FALSE; | 763 dockIconCacheMiss = SDL_FALSE; |
763 | 764 |
764 /* The first window is always an empty window with level kCGSWindowLevelTop | 765 /* The first window is always an empty window with level kCGSWindowLevelTop |
765 so start at index 1 */ | 766 so start at index 1 */ |
766 for (i = 1; i < count; i++) { | 767 for (i = 1; i < count; i++) { |
767 | 768 |
768 /* If we reach our window in the list, it cannot be obscured */ | 769 /* If we reach our window in the list, it cannot be obscured */ |
769 if (windows[i] == windowNumber) { | 770 if (windows[i] == windowNumber) { |
770 | 771 |
771 obscured = SDL_FALSE; | 772 obscured = SDL_FALSE; |
772 break; | 773 break; |
773 } | 774 } |
774 else { | 775 else { |
775 | 776 |
776 float shadowSide; | 777 float shadowSide; |
777 float shadowTop; | 778 float shadowTop; |
778 float shadowBottom; | 779 float shadowBottom; |
779 | 780 |
780 CGSGetWindowLevel (cgsConnection, windows[i], &winLevel); | 781 CGSGetWindowLevel (cgsConnection, windows[i], &winLevel); |
781 | 782 |
782 if (winLevel == kCGSWindowLevelDockIcon) { | 783 if (winLevel == kCGSWindowLevelDockIcon) { |
783 | 784 |
784 int j; | 785 int j; |
785 | 786 |
786 if (firstDockIcon < 0) { | 787 if (firstDockIcon < 0) { |
787 | 788 |
788 firstDockIcon = i; | 789 firstDockIcon = i; |
789 | 790 |
790 if (numCachedDockIcons > 0) { | 791 if (numCachedDockIcons > 0) { |
791 | 792 |
792 for (j = 0; j < numCachedDockIcons; j++) { | 793 for (j = 0; j < numCachedDockIcons; j++) { |
793 | 794 |
794 if (windows[i] == dockIcons[j]) | 795 if (windows[i] == dockIcons[j]) |
795 i++; | 796 i++; |
796 else | 797 else |
797 break; | 798 break; |
798 } | 799 } |
799 | 800 |
800 if (j != 0) { | 801 if (j != 0) { |
801 | 802 |
802 i--; | 803 i--; |
803 | 804 |
804 if (j < numCachedDockIcons) { | 805 if (j < numCachedDockIcons) { |
805 | 806 |
806 dockIconCacheMiss = SDL_TRUE; | 807 dockIconCacheMiss = SDL_TRUE; |
807 } | 808 } |
808 } | 809 } |
809 | 810 |
810 } | 811 } |
811 } | 812 } |
812 | 813 |
813 continue; | 814 continue; |
814 } | 815 } |
815 else if (winLevel == kCGSWindowLevelMenuIgnore | 816 else if (winLevel == kCGSWindowLevelMenuIgnore |
816 /* winLevel == kCGSWindowLevelTop */) { | 817 /* winLevel == kCGSWindowLevelTop */) { |
817 | 818 |
818 continue; /* cannot obscure window */ | 819 continue; /* cannot obscure window */ |
819 } | 820 } |
820 else if (winLevel == kCGSWindowLevelDockMenu || | 821 else if (winLevel == kCGSWindowLevelDockMenu || |
821 winLevel == kCGSWindowLevelMenu) { | 822 winLevel == kCGSWindowLevelMenu) { |
822 | 823 |
823 shadowSide = 18; | 824 shadowSide = 18; |
824 shadowTop = 4; | 825 shadowTop = 4; |
825 shadowBottom = 22; | 826 shadowBottom = 22; |
826 } | 827 } |
827 else if (winLevel == kCGSWindowLevelUtility) { | 828 else if (winLevel == kCGSWindowLevelUtility) { |
828 | 829 |
829 shadowSide = 8; | 830 shadowSide = 8; |
830 shadowTop = 4; | 831 shadowTop = 4; |
831 shadowBottom = 12; | 832 shadowBottom = 12; |
832 } | 833 } |
833 else if (winLevel == kCGSWindowLevelNormal) { | 834 else if (winLevel == kCGSWindowLevelNormal) { |
834 | 835 |
835 /* These numbers are for foreground windows, | 836 /* These numbers are for foreground windows, |
836 they are too big (but will work) for background windows */ | 837 they are too big (but will work) for background windows */ |
837 shadowSide = 20; | 838 shadowSide = 20; |
838 shadowTop = 10; | 839 shadowTop = 10; |
839 shadowBottom = 24; | 840 shadowBottom = 24; |
840 } | 841 } |
841 else if (winLevel == kCGSWindowLevelDock) { | 842 else if (winLevel == kCGSWindowLevelDock) { |
842 | 843 |
843 /* Create dock icon cache */ | 844 /* Create dock icon cache */ |
844 if (numCachedDockIcons != (i-firstDockIcon) || | 845 if (numCachedDockIcons != (i-firstDockIcon) || |
845 dockIconCacheMiss) { | 846 dockIconCacheMiss) { |
846 | 847 |
847 numCachedDockIcons = i - firstDockIcon; | 848 numCachedDockIcons = i - firstDockIcon; |
848 memcpy (dockIcons, &(windows[firstDockIcon]), | 849 memcpy (dockIcons, &(windows[firstDockIcon]), |
849 numCachedDockIcons * sizeof(*windows)); | 850 numCachedDockIcons * sizeof(*windows)); |
850 } | 851 } |
851 | 852 |
852 /* no shadow */ | 853 /* no shadow */ |
853 shadowSide = 0; | 854 shadowSide = 0; |
854 shadowTop = 0; | 855 shadowTop = 0; |
855 shadowBottom = 0; | 856 shadowBottom = 0; |
856 } | 857 } |
857 else { | 858 else { |
858 | 859 |
859 /* kCGSWindowLevelDockLabel, | 860 /* kCGSWindowLevelDockLabel, |
860 kCGSWindowLevelDock, | 861 kCGSWindowLevelDock, |
861 kOther??? */ | 862 kOther??? */ |
862 | 863 |
863 /* no shadow */ | 864 /* no shadow */ |
864 shadowSide = 0; | 865 shadowSide = 0; |
865 shadowTop = 0; | 866 shadowTop = 0; |
866 shadowBottom = 0; | 867 shadowBottom = 0; |
867 } | 868 } |
868 | 869 |
869 CGSGetScreenRectForWindow (cgsConnection, windows[i], &winRect); | 870 CGSGetScreenRectForWindow (cgsConnection, windows[i], &winRect); |
870 | 871 |
871 winRect.origin.x -= shadowSide; | 872 winRect.origin.x -= shadowSide; |
872 winRect.origin.y -= shadowTop; | 873 winRect.origin.y -= shadowTop; |
873 winRect.size.width += shadowSide; | 874 winRect.size.width += shadowSide; |
874 winRect.size.height += shadowBottom; | 875 winRect.size.height += shadowBottom; |
875 | 876 |
876 if (NSIntersectsRect (contentRect, winRect)) { | 877 if (NSIntersectsRect (contentRect, winRect)) { |
877 | 878 |
878 obscured = SDL_TRUE; | 879 obscured = SDL_TRUE; |
879 break; | 880 break; |
880 } | 881 } |
881 | 882 |
882 } /* window was not our window */ | 883 } /* window was not our window */ |
883 | 884 |
884 } /* iterate over windows */ | 885 } /* iterate over windows */ |
885 | 886 |
886 } /* get cgsConnection */ | 887 } /* get cgsConnection */ |
887 | 888 |
888 } /* window is visible */ | 889 } /* window is visible */ |
889 | 890 |
890 return obscured; | 891 return obscured; |
891 #else | 892 #else |
892 return SDL_TRUE; | 893 return SDL_TRUE; |
893 #endif | 894 #endif |
894 } | 895 } |
895 | 896 |
896 static void QZ_UpdateRects (_THIS, int numRects, SDL_Rect *rects) { | 897 static void QZ_UpdateRects (_THIS, int numRects, SDL_Rect *rects) { |
897 | 898 |
898 if (SDL_VideoSurface->flags & SDL_OPENGLBLIT) { | 899 if (SDL_VideoSurface->flags & SDL_OPENGLBLIT) { |
899 QZ_GL_SwapBuffers (this); | 900 QZ_GL_SwapBuffers (this); |
900 } | 901 } |
901 else if ( [ qz_window isMiniaturized ] && | 902 else if ( [ qz_window isMiniaturized ] && |
902 ! (SDL_VideoSurface->flags & SDL_OPENGL)) { | 903 ! (SDL_VideoSurface->flags & SDL_OPENGL)) { |
903 | 904 |
904 /** | 905 /** |
905 * Set port alpha opaque so deminiaturize looks right | 906 * Set port alpha opaque so deminiaturize looks right |
906 * This isn't so nice, but there is no | 907 * This isn't so nice, but there is no |
907 * initial deminatureize notification (before demini starts) | 908 * initial deminatureize notification (before demini starts) |
908 **/ | 909 **/ |
909 QZ_SetPortAlphaOpaque ([ [ qz_window contentView ] qdPort], | 910 QZ_SetPortAlphaOpaque ([ [ qz_window contentView ] qdPort], |
910 [ qz_window styleMask ] & NSBorderlessWindowMask); | 911 [ qz_window styleMask ] & NSBorderlessWindowMask); |
911 } | 912 } |
912 else if ( ! QZ_IsWindowObscured (qz_window) ) { | 913 else if ( ! QZ_IsWindowObscured (qz_window) ) { |
913 | 914 |
914 /* Use direct copy to flush contents to the display */ | 915 /* Use direct copy to flush contents to the display */ |
915 CGrafPtr savePort; | 916 CGrafPtr savePort; |
916 CGrafPtr dstPort, srcPort; | 917 CGrafPtr dstPort, srcPort; |
917 const BitMap *dstBits, *srcBits; | 918 const BitMap *dstBits, *srcBits; |
918 Rect dstRect, srcRect; | 919 Rect dstRect, srcRect; |
919 Point offset; | 920 Point offset; |
920 int i; | 921 int i; |
921 | 922 |
922 GetPort (&savePort); | 923 GetPort (&savePort); |
923 | 924 |
924 dstPort = CreateNewPortForCGDisplayID ((UInt32)display_id); | 925 dstPort = CreateNewPortForCGDisplayID ((UInt32)display_id); |
925 srcPort = [ window_view qdPort ]; | 926 srcPort = [ window_view qdPort ]; |
926 | 927 |
927 offset.h = 0; | 928 offset.h = 0; |
928 offset.v = 0; | 929 offset.v = 0; |
929 SetPort (srcPort); | 930 SetPort (srcPort); |
930 LocalToGlobal (&offset); | 931 LocalToGlobal (&offset); |
931 | 932 |
932 SetPort (dstPort); | 933 SetPort (dstPort); |
933 | 934 |
934 LockPortBits (dstPort); | 935 LockPortBits (dstPort); |
935 LockPortBits (srcPort); | 936 LockPortBits (srcPort); |
936 | 937 |
937 dstBits = GetPortBitMapForCopyBits (dstPort); | 938 dstBits = GetPortBitMapForCopyBits (dstPort); |
938 srcBits = GetPortBitMapForCopyBits (srcPort); | 939 srcBits = GetPortBitMapForCopyBits (srcPort); |
939 | 940 |
940 for (i = 0; i < numRects; i++) { | 941 for (i = 0; i < numRects; i++) { |
941 | 942 |
942 SetRect (&srcRect, rects[i].x, rects[i].y, | 943 SetRect (&srcRect, rects[i].x, rects[i].y, |
943 rects[i].x + rects[i].w, | 944 rects[i].x + rects[i].w, |
944 rects[i].y + rects[i].h); | 945 rects[i].y + rects[i].h); |
945 | 946 |
946 SetRect (&dstRect, | 947 SetRect (&dstRect, |
947 rects[i].x + offset.h, | 948 rects[i].x + offset.h, |
948 rects[i].y + offset.v, | 949 rects[i].y + offset.v, |
949 rects[i].x + rects[i].w + offset.h, | 950 rects[i].x + rects[i].w + offset.h, |
950 rects[i].y + rects[i].h + offset.v); | 951 rects[i].y + rects[i].h + offset.v); |
951 | 952 |
952 CopyBits (srcBits, dstBits, | 953 CopyBits (srcBits, dstBits, |
953 &srcRect, &dstRect, srcCopy, NULL); | 954 &srcRect, &dstRect, srcCopy, NULL); |
954 | 955 |
955 } | 956 } |
956 | 957 |
957 SetPort (savePort); | 958 SetPort (savePort); |
958 } | 959 } |
959 else { | 960 else { |
960 | 961 |
961 /* Use QDFlushPortBuffer() to flush content to display */ | 962 /* Use QDFlushPortBuffer() to flush content to display */ |
962 int i; | 963 int i; |
963 RgnHandle dirty = NewRgn (); | 964 RgnHandle dirty = NewRgn (); |
964 RgnHandle temp = NewRgn (); | 965 RgnHandle temp = NewRgn (); |
965 | 966 |
966 SetEmptyRgn (dirty); | 967 SetEmptyRgn (dirty); |
967 | 968 |
968 /* Build the region of dirty rectangles */ | 969 /* Build the region of dirty rectangles */ |
969 for (i = 0; i < numRects; i++) { | 970 for (i = 0; i < numRects; i++) { |
970 | 971 |
971 MacSetRectRgn (temp, rects[i].x, rects[i].y, | 972 MacSetRectRgn (temp, rects[i].x, rects[i].y, |
972 rects[i].x + rects[i].w, rects[i].y + rects[i].h); | 973 rects[i].x + rects[i].w, rects[i].y + rects[i].h); |
973 MacUnionRgn (dirty, temp, dirty); | 974 MacUnionRgn (dirty, temp, dirty); |
974 } | 975 } |
975 | 976 |
976 /* Flush the dirty region */ | 977 /* Flush the dirty region */ |
977 QDFlushPortBuffer ( [ window_view qdPort ], dirty ); | 978 QDFlushPortBuffer ( [ window_view qdPort ], dirty ); |
978 DisposeRgn (dirty); | 979 DisposeRgn (dirty); |
979 DisposeRgn (temp); | 980 DisposeRgn (temp); |
980 } | 981 } |
991 CGSDisplayHWFill (display_id, rect->x, rect->y, rect->w, rect->h, color); | 992 CGSDisplayHWFill (display_id, rect->x, rect->y, rect->w, rect->h, color); |
992 | 993 |
993 return 0; | 994 return 0; |
994 } | 995 } |
995 | 996 |
996 static int QZ_LockHWSurface(_THIS, SDL_Surface *surface) { | 997 static int QZ_LockHWSurface(_THIS, SDL_Surface *surface) { |
997 | 998 |
998 return 1; | 999 return 1; |
999 } | 1000 } |
1000 | 1001 |
1001 static void QZ_UnlockHWSurface(_THIS, SDL_Surface *surface) { | 1002 static void QZ_UnlockHWSurface(_THIS, SDL_Surface *surface) { |
1004 | 1005 |
1005 static void QZ_FreeHWSurface (_THIS, SDL_Surface *surface) { | 1006 static void QZ_FreeHWSurface (_THIS, SDL_Surface *surface) { |
1006 } | 1007 } |
1007 | 1008 |
1008 /* | 1009 /* |
1009 int QZ_FlipHWSurface (_THIS, SDL_Surface *surface) { | 1010 int QZ_FlipHWSurface (_THIS, SDL_Surface *surface) { |
1010 return 0; | 1011 return 0; |
1011 } | 1012 } |
1012 */ | 1013 */ |
1013 | 1014 |
1014 /* Gamma functions */ | 1015 /* Gamma functions */ |
1015 static int QZ_SetGamma (_THIS, float red, float green, float blue) { | 1016 static int QZ_SetGamma (_THIS, float red, float green, float blue) { |
1016 | 1017 |
1017 const CGGammaValue min = 0.0, max = 1.0; | 1018 const CGGammaValue min = 0.0, max = 1.0; |
1028 | 1029 |
1029 if (blue == 0.0) | 1030 if (blue == 0.0) |
1030 blue = FLT_MAX; | 1031 blue = FLT_MAX; |
1031 else | 1032 else |
1032 blue = 1.0 / blue; | 1033 blue = 1.0 / blue; |
1033 | 1034 |
1034 if ( CGDisplayNoErr == CGSetDisplayTransferByFormula | 1035 if ( CGDisplayNoErr == CGSetDisplayTransferByFormula |
1035 (display_id, min, max, red, min, max, green, min, max, blue) ) { | 1036 (display_id, min, max, red, min, max, green, min, max, blue) ) { |
1036 | 1037 |
1037 return 0; | 1038 return 0; |
1038 } | 1039 } |
1039 else { | 1040 else { |
1040 | 1041 |
1041 return -1; | 1042 return -1; |
1042 } | 1043 } |
1043 } | 1044 } |
1044 | 1045 |
1045 static int QZ_GetGamma (_THIS, float *red, float *green, float *blue) { | 1046 static int QZ_GetGamma (_THIS, float *red, float *green, float *blue) { |
1046 | 1047 |
1047 CGGammaValue dummy; | 1048 CGGammaValue dummy; |
1048 if ( CGDisplayNoErr == CGGetDisplayTransferByFormula | 1049 if ( CGDisplayNoErr == CGGetDisplayTransferByFormula |
1049 (display_id, &dummy, &dummy, red, | 1050 (display_id, &dummy, &dummy, red, |
1050 &dummy, &dummy, green, &dummy, &dummy, blue) ) | 1051 &dummy, &dummy, green, &dummy, &dummy, blue) ) |
1051 | 1052 |
1052 return 0; | 1053 return 0; |
1053 else | 1054 else |
1054 return -1; | 1055 return -1; |
1055 } | 1056 } |
1056 | 1057 |
1057 static int QZ_SetGammaRamp (_THIS, Uint16 *ramp) { | 1058 static int QZ_SetGammaRamp (_THIS, Uint16 *ramp) { |
1058 | 1059 |
1059 const CGTableCount tableSize = 255; | 1060 const CGTableCount tableSize = 255; |
1060 CGGammaValue redTable[tableSize]; | 1061 CGGammaValue redTable[tableSize]; |
1061 CGGammaValue greenTable[tableSize]; | 1062 CGGammaValue greenTable[tableSize]; |
1062 CGGammaValue blueTable[tableSize]; | 1063 CGGammaValue blueTable[tableSize]; |
1063 | 1064 |
1064 int i; | 1065 int i; |
1065 | 1066 |
1066 /* Extract gamma values into separate tables, convert to floats between 0.0 and 1.0 */ | 1067 /* Extract gamma values into separate tables, convert to floats between 0.0 and 1.0 */ |
1067 for (i = 0; i < 256; i++) | 1068 for (i = 0; i < 256; i++) |
1068 redTable[i % 256] = ramp[i] / 65535.0; | 1069 redTable[i % 256] = ramp[i] / 65535.0; |
1069 | 1070 |
1070 for (i=256; i < 512; i++) | 1071 for (i=256; i < 512; i++) |
1071 greenTable[i % 256] = ramp[i] / 65535.0; | 1072 greenTable[i % 256] = ramp[i] / 65535.0; |
1072 | 1073 |
1073 for (i=512; i < 768; i++) | 1074 for (i=512; i < 768; i++) |
1074 blueTable[i % 256] = ramp[i] / 65535.0; | 1075 blueTable[i % 256] = ramp[i] / 65535.0; |
1075 | 1076 |
1076 if ( CGDisplayNoErr == CGSetDisplayTransferByTable | 1077 if ( CGDisplayNoErr == CGSetDisplayTransferByTable |
1077 (display_id, tableSize, redTable, greenTable, blueTable) ) | 1078 (display_id, tableSize, redTable, greenTable, blueTable) ) |
1078 return 0; | 1079 return 0; |
1079 else | 1080 else |
1080 return -1; | 1081 return -1; |
1081 } | 1082 } |
1082 | 1083 |
1083 static int QZ_GetGammaRamp (_THIS, Uint16 *ramp) { | 1084 static int QZ_GetGammaRamp (_THIS, Uint16 *ramp) { |
1084 | 1085 |
1085 const CGTableCount tableSize = 255; | 1086 const CGTableCount tableSize = 255; |
1086 CGGammaValue redTable[tableSize]; | 1087 CGGammaValue redTable[tableSize]; |
1087 CGGammaValue greenTable[tableSize]; | 1088 CGGammaValue greenTable[tableSize]; |
1088 CGGammaValue blueTable[tableSize]; | 1089 CGGammaValue blueTable[tableSize]; |
1089 CGTableCount actual; | 1090 CGTableCount actual; |
1090 int i; | 1091 int i; |
1091 | 1092 |
1092 if ( CGDisplayNoErr != CGGetDisplayTransferByTable | 1093 if ( CGDisplayNoErr != CGGetDisplayTransferByTable |
1093 (display_id, tableSize, redTable, greenTable, blueTable, &actual) || | 1094 (display_id, tableSize, redTable, greenTable, blueTable, &actual) || |
1094 actual != tableSize) | 1095 actual != tableSize) |
1095 | 1096 |
1096 return -1; | 1097 return -1; |
1097 | 1098 |
1098 /* Pack tables into one array, with values from 0 to 65535 */ | 1099 /* Pack tables into one array, with values from 0 to 65535 */ |
1099 for (i = 0; i < 256; i++) | 1100 for (i = 0; i < 256; i++) |
1100 ramp[i] = redTable[i % 256] * 65535.0; | 1101 ramp[i] = redTable[i % 256] * 65535.0; |
1101 | 1102 |
1102 for (i=256; i < 512; i++) | 1103 for (i=256; i < 512; i++) |
1103 ramp[i] = greenTable[i % 256] * 65535.0; | 1104 ramp[i] = greenTable[i % 256] * 65535.0; |
1104 | 1105 |
1105 for (i=512; i < 768; i++) | 1106 for (i=512; i < 768; i++) |
1106 ramp[i] = blueTable[i % 256] * 65535.0; | 1107 ramp[i] = blueTable[i % 256] * 65535.0; |
1107 | 1108 |
1108 return 0; | 1109 return 0; |
1109 } | 1110 } |
1110 | 1111 |
1111 /* OpenGL helper functions (used internally) */ | 1112 /* OpenGL helper functions (used internally) */ |
1112 | 1113 |
1113 static int QZ_SetupOpenGL (_THIS, int bpp, Uint32 flags) { | 1114 static int QZ_SetupOpenGL (_THIS, int bpp, Uint32 flags) { |
1116 NSOpenGLPixelFormat *fmt; | 1117 NSOpenGLPixelFormat *fmt; |
1117 int i = 0; | 1118 int i = 0; |
1118 int colorBits = bpp; | 1119 int colorBits = bpp; |
1119 | 1120 |
1120 if ( flags & SDL_FULLSCREEN ) { | 1121 if ( flags & SDL_FULLSCREEN ) { |
1121 | 1122 |
1122 attr[i++] = NSOpenGLPFAFullScreen; | 1123 attr[i++] = NSOpenGLPFAFullScreen; |
1123 } | 1124 } |
1124 /* In windowed mode, the OpenGL pixel depth must match device pixel depth */ | 1125 /* In windowed mode, the OpenGL pixel depth must match device pixel depth */ |
1125 else if ( colorBits != device_bpp ) { | 1126 else if ( colorBits != device_bpp ) { |
1126 | 1127 |
1127 colorBits = device_bpp; | 1128 colorBits = device_bpp; |
1128 } | 1129 } |
1129 | 1130 |
1130 attr[i++] = NSOpenGLPFAColorSize; | 1131 attr[i++] = NSOpenGLPFAColorSize; |
1131 attr[i++] = colorBits; | 1132 attr[i++] = colorBits; |
1132 | 1133 |
1133 attr[i++] = NSOpenGLPFADepthSize; | 1134 attr[i++] = NSOpenGLPFADepthSize; |
1134 attr[i++] = this->gl_config.depth_size; | 1135 attr[i++] = this->gl_config.depth_size; |
1135 | 1136 |
1136 if ( this->gl_config.double_buffer ) { | 1137 if ( this->gl_config.double_buffer ) { |
1137 attr[i++] = NSOpenGLPFADoubleBuffer; | 1138 attr[i++] = NSOpenGLPFADoubleBuffer; |
1138 } | 1139 } |
1139 | 1140 |
1140 if ( this->gl_config.stencil_size != 0 ) { | 1141 if ( this->gl_config.stencil_size != 0 ) { |
1141 attr[i++] = NSOpenGLPFAStencilSize; | 1142 attr[i++] = NSOpenGLPFAStencilSize; |
1142 attr[i++] = this->gl_config.stencil_size; | 1143 attr[i++] = this->gl_config.stencil_size; |
1143 } | 1144 } |
1144 | 1145 |
1145 attr[i++] = NSOpenGLPFAScreenMask; | 1146 attr[i++] = NSOpenGLPFAScreenMask; |
1146 attr[i++] = CGDisplayIDToOpenGLDisplayMask (display_id); | 1147 attr[i++] = CGDisplayIDToOpenGLDisplayMask (display_id); |
1147 attr[i] = 0; | 1148 attr[i] = 0; |
1148 | 1149 |
1149 fmt = [ [ NSOpenGLPixelFormat alloc ] initWithAttributes:attr ]; | 1150 fmt = [ [ NSOpenGLPixelFormat alloc ] initWithAttributes:attr ]; |
1150 if (fmt == nil) { | 1151 if (fmt == nil) { |
1151 SDL_SetError ("Failed creating OpenGL pixel format"); | 1152 SDL_SetError ("Failed creating OpenGL pixel format"); |
1152 return 0; | 1153 return 0; |
1153 } | 1154 } |
1154 | 1155 |
1155 gl_context = [ [ NSOpenGLContext alloc ] initWithFormat:fmt | 1156 gl_context = [ [ NSOpenGLContext alloc ] initWithFormat:fmt |
1156 shareContext:nil]; | 1157 shareContext:nil]; |
1157 | 1158 |
1158 if (gl_context == nil) { | 1159 if (gl_context == nil) { |
1159 SDL_SetError ("Failed creating OpenGL context"); | 1160 SDL_SetError ("Failed creating OpenGL context"); |
1160 return 0; | 1161 return 0; |
1161 } | 1162 } |
1162 | 1163 |
1163 /* Convince SDL that the GL "driver" is loaded */ | 1164 /* Convince SDL that the GL "driver" is loaded */ |
1164 this->gl_config.driver_loaded = 1; | 1165 this->gl_config.driver_loaded = 1; |
1165 | 1166 |
1166 [ fmt release ]; | 1167 [ fmt release ]; |
1167 | 1168 |
1168 return 1; | 1169 return 1; |
1169 } | 1170 } |
1170 | 1171 |
1171 static void QZ_TearDownOpenGL (_THIS) { | 1172 static void QZ_TearDownOpenGL (_THIS) { |
1172 | 1173 |
1185 | 1186 |
1186 static void* QZ_GL_GetProcAddress (_THIS, const char *proc) { | 1187 static void* QZ_GL_GetProcAddress (_THIS, const char *proc) { |
1187 | 1188 |
1188 /* We may want to cache the bundleRef at some point */ | 1189 /* We may want to cache the bundleRef at some point */ |
1189 CFBundleRef bundle; | 1190 CFBundleRef bundle; |
1190 CFURLRef bundleURL = CFURLCreateWithFileSystemPath (kCFAllocatorDefault, | 1191 CFURLRef bundleURL = CFURLCreateWithFileSystemPath (kCFAllocatorDefault, |
1191 CFSTR("/System/Library/Frameworks/OpenGL.framework"), kCFURLPOSIXPathStyle, true); | 1192 CFSTR("/System/Library/Frameworks/OpenGL.framework"), kCFURLPOSIXPathStyle, true); |
1192 | 1193 |
1193 CFStringRef functionName = CFStringCreateWithCString | 1194 CFStringRef functionName = CFStringCreateWithCString |
1194 (kCFAllocatorDefault, proc, kCFStringEncodingASCII); | 1195 (kCFAllocatorDefault, proc, kCFStringEncodingASCII); |
1195 | 1196 |
1196 void *function; | 1197 void *function; |
1197 | 1198 |
1198 bundle = CFBundleCreate (kCFAllocatorDefault, bundleURL); | 1199 bundle = CFBundleCreate (kCFAllocatorDefault, bundleURL); |
1199 assert (bundle != NULL); | 1200 assert (bundle != NULL); |
1200 | 1201 |
1201 function = CFBundleGetFunctionPointerForName (bundle, functionName); | 1202 function = CFBundleGetFunctionPointerForName (bundle, functionName); |
1202 | 1203 |
1203 CFRelease ( bundleURL ); | 1204 CFRelease ( bundleURL ); |
1204 CFRelease ( functionName ); | 1205 CFRelease ( functionName ); |
1205 CFRelease ( bundle ); | 1206 CFRelease ( bundle ); |
1206 | 1207 |
1207 return function; | 1208 return function; |
1208 } | 1209 } |
1209 | 1210 |
1210 static int QZ_GL_GetAttribute (_THIS, SDL_GLattr attrib, int* value) { | 1211 static int QZ_GL_GetAttribute (_THIS, SDL_GLattr attrib, int* value) { |
1211 | 1212 |
1212 GLenum attr = 0; | 1213 GLenum attr = 0; |
1213 | 1214 |
1214 QZ_GL_MakeCurrent (this); | 1215 QZ_GL_MakeCurrent (this); |
1215 | 1216 |
1216 switch (attrib) { | 1217 switch (attrib) { |
1217 case SDL_GL_RED_SIZE: attr = GL_RED_BITS; break; | 1218 case SDL_GL_RED_SIZE: attr = GL_RED_BITS; break; |
1218 case SDL_GL_BLUE_SIZE: attr = GL_BLUE_BITS; break; | 1219 case SDL_GL_BLUE_SIZE: attr = GL_BLUE_BITS; break; |
1219 case SDL_GL_GREEN_SIZE: attr = GL_GREEN_BITS; break; | 1220 case SDL_GL_GREEN_SIZE: attr = GL_GREEN_BITS; break; |
1220 case SDL_GL_ALPHA_SIZE: attr = GL_ALPHA_BITS; break; | 1221 case SDL_GL_ALPHA_SIZE: attr = GL_ALPHA_BITS; break; |
1221 case SDL_GL_DOUBLEBUFFER: attr = GL_DOUBLEBUFFER; break; | 1222 case SDL_GL_DOUBLEBUFFER: attr = GL_DOUBLEBUFFER; break; |
1222 case SDL_GL_DEPTH_SIZE: attr = GL_DEPTH_BITS; break; | 1223 case SDL_GL_DEPTH_SIZE: attr = GL_DEPTH_BITS; break; |
1223 case SDL_GL_STENCIL_SIZE: attr = GL_STENCIL_BITS; break; | 1224 case SDL_GL_STENCIL_SIZE: attr = GL_STENCIL_BITS; break; |
1224 case SDL_GL_ACCUM_RED_SIZE: attr = GL_ACCUM_RED_BITS; break; | 1225 case SDL_GL_ACCUM_RED_SIZE: attr = GL_ACCUM_RED_BITS; break; |
1225 case SDL_GL_ACCUM_GREEN_SIZE: attr = GL_ACCUM_GREEN_BITS; break; | 1226 case SDL_GL_ACCUM_GREEN_SIZE: attr = GL_ACCUM_GREEN_BITS; break; |
1226 case SDL_GL_ACCUM_BLUE_SIZE: attr = GL_ACCUM_BLUE_BITS; break; | 1227 case SDL_GL_ACCUM_BLUE_SIZE: attr = GL_ACCUM_BLUE_BITS; break; |
1227 case SDL_GL_ACCUM_ALPHA_SIZE: attr = GL_ACCUM_ALPHA_BITS; break; | 1228 case SDL_GL_ACCUM_ALPHA_SIZE: attr = GL_ACCUM_ALPHA_BITS; break; |
1228 case SDL_GL_BUFFER_SIZE: | 1229 case SDL_GL_BUFFER_SIZE: |
1229 { | 1230 { |
1230 GLint bits = 0; | 1231 GLint bits = 0; |
1231 GLint component; | 1232 GLint component; |
1232 | 1233 |
1233 /* there doesn't seem to be a single flag in OpenGL for this! */ | 1234 /* there doesn't seem to be a single flag in OpenGL for this! */ |
1252 | 1253 |
1253 static void QZ_GL_SwapBuffers (_THIS) { | 1254 static void QZ_GL_SwapBuffers (_THIS) { |
1254 [ gl_context flushBuffer ]; | 1255 [ gl_context flushBuffer ]; |
1255 } | 1256 } |
1256 | 1257 |
1257 | 1258 static int QZ_LockYUV (_THIS, SDL_Overlay *overlay) { |
1259 | |
1260 return 0; | |
1261 } | |
1262 | |
1263 static void QZ_UnlockYUV (_THIS, SDL_Overlay *overlay) { | |
1264 | |
1265 ; | |
1266 } | |
1267 | |
1268 static int QZ_DisplayYUV (_THIS, SDL_Overlay *overlay, SDL_Rect *dstrect) { | |
1269 | |
1270 OSErr err; | |
1271 CodecFlags flags; | |
1272 | |
1273 if (dstrect->x != 0 || dstrect->y != 0) { | |
1274 | |
1275 SDL_SetError ("Need a dstrect at (0,0)"); | |
1276 return -1; | |
1277 } | |
1278 | |
1279 if (dstrect->w != yuv_width || dstrect->h != yuv_height) { | |
1280 | |
1281 Fixed scale_x, scale_y; | |
1282 | |
1283 scale_x = FixDiv ( Long2Fix (dstrect->w), Long2Fix (overlay->w) ); | |
1284 scale_y = FixDiv ( Long2Fix (dstrect->h), Long2Fix (overlay->h) ); | |
1285 | |
1286 SetIdentityMatrix (yuv_matrix); | |
1287 ScaleMatrix (yuv_matrix, scale_x, scale_y, Long2Fix (0), Long2Fix (0)); | |
1288 | |
1289 SetDSequenceMatrix (yuv_seq, yuv_matrix); | |
1290 | |
1291 yuv_width = dstrect->w; | |
1292 yuv_height = dstrect->h; | |
1293 } | |
1294 | |
1295 if( ( err = DecompressSequenceFrameS( | |
1296 yuv_seq, | |
1297 (void*)yuv_pixmap, | |
1298 sizeof (PlanarPixmapInfoYUV420), | |
1299 codecFlagUseImageBuffer, &flags, nil ) != noErr ) ) | |
1300 { | |
1301 SDL_SetError ("DecompressSequenceFrameS failed"); | |
1302 } | |
1303 | |
1304 return err == noErr; | |
1305 } | |
1306 | |
1307 static void QZ_FreeHWYUV (_THIS, SDL_Overlay *overlay) { | |
1308 | |
1309 CDSequenceEnd (yuv_seq); | |
1310 ExitMovies(); | |
1311 | |
1312 free (overlay->hwfuncs); | |
1313 free (overlay->pitches); | |
1314 free (overlay->pixels); | |
1315 | |
1316 if (SDL_VideoSurface->flags & SDL_FULLSCREEN) { | |
1317 [ qz_window close ]; | |
1318 qz_window = nil; | |
1319 } | |
1320 | |
1321 free (yuv_matrix); | |
1322 DisposeHandle ((Handle)yuv_idh); | |
1323 } | |
1324 | |
1325 #include "SDL_yuvfuncs.h" | |
1326 | |
1327 /** | |
1328 * check for 16 byte alignment, bail otherwise | |
1329 **/ | |
1330 #define CHECK_ALIGN(x) do { if ((Uint32)x & 15) { SDL_SetError("Alignment error"); return NULL; } } while(0) | |
1331 | |
1332 /** | |
1333 * align a byte offset, return how much to add to make it | |
1334 * a multiple of 16 | |
1335 **/ | |
1336 #define ALIGN(x) ((16 - (x & 15)) & 15) | |
1337 | |
1338 static SDL_Overlay* QZ_CreateYUVOverlay (_THIS, int width, int height, | |
1339 Uint32 format, SDL_Surface *display) { | |
1340 | |
1341 Uint32 codec; | |
1342 OSStatus err; | |
1343 CGrafPtr port; | |
1344 SDL_Overlay *overlay; | |
1345 | |
1346 if (format == SDL_YV12_OVERLAY || | |
1347 format == SDL_IYUV_OVERLAY) { | |
1348 | |
1349 codec = kYUV420CodecType; | |
1350 } | |
1351 else { | |
1352 SDL_SetError ("Hardware: unsupported video format"); | |
1353 return NULL; | |
1354 } | |
1355 | |
1356 yuv_idh = (ImageDescriptionHandle) NewHandleClear (sizeof(ImageDescription)); | |
1357 if (yuv_idh == NULL) { | |
1358 SDL_OutOfMemory(); | |
1359 return NULL; | |
1360 } | |
1361 | |
1362 yuv_matrix = (MatrixRecordPtr) malloc (sizeof(MatrixRecord)); | |
1363 if (yuv_matrix == NULL) { | |
1364 SDL_OutOfMemory(); | |
1365 return NULL; | |
1366 } | |
1367 | |
1368 if ( EnterMovies() != noErr ) { | |
1369 SDL_SetError ("Could not init QuickTime for YUV playback"); | |
1370 return NULL; | |
1371 } | |
1372 | |
1373 err = FindCodec (codec, bestSpeedCodec, nil, &yuv_codec); | |
1374 if (err != noErr) { | |
1375 SDL_SetError ("Could not find QuickTime codec for format"); | |
1376 return NULL; | |
1377 } | |
1378 | |
1379 if (SDL_VideoSurface->flags & SDL_FULLSCREEN) { | |
1380 | |
1381 /** | |
1382 * Good acceleration requires a window to be present. | |
1383 * A CGrafPtr that points to the screen isn't good enough | |
1384 **/ | |
1385 NSRect content = NSMakeRect (0, 0, SDL_VideoSurface->w, SDL_VideoSurface->h); | |
1386 | |
1387 qz_window = [ [ SDL_QuartzWindow alloc ] | |
1388 initWithContentRect:content | |
1389 styleMask:NSBorderlessWindowMask | |
1390 backing:NSBackingStoreBuffered defer:NO ]; | |
1391 | |
1392 if (qz_window == nil) { | |
1393 SDL_SetError ("Could not create the Cocoa window"); | |
1394 return NULL; | |
1395 } | |
1396 | |
1397 [ qz_window setContentView:[ [ SDL_QuartzWindowView alloc ] init ] ]; | |
1398 [ qz_window setReleasedWhenClosed:YES ]; | |
1399 [ qz_window center ]; | |
1400 [ qz_window setAcceptsMouseMovedEvents:YES ]; | |
1401 [ qz_window setLevel:CGShieldingWindowLevel() ]; | |
1402 [ qz_window makeKeyAndOrderFront:nil ]; | |
1403 | |
1404 port = [ [ qz_window contentView ] qdPort ]; | |
1405 SetPort (port); | |
1406 // BUG: would like to remove white flash when window kicks in | |
1407 //{ | |
1408 // Rect r; | |
1409 // SetRect (&r, 0, 0, SDL_VideoSurface->w, SDL_VideoSurface->h); | |
1410 // PaintRect (&r); | |
1411 // QDFlushPortBuffer (port, nil); | |
1412 //} | |
1413 | |
1414 } | |
1415 else { | |
1416 port = [ [ qz_window contentView ] qdPort ]; | |
1417 SetPort (port); | |
1418 } | |
1419 | |
1420 SetIdentityMatrix (yuv_matrix); | |
1421 | |
1422 HLock ((Handle)yuv_idh); | |
1423 | |
1424 (**yuv_idh).idSize = sizeof(ImageDescription); | |
1425 (**yuv_idh).cType = codec; | |
1426 (**yuv_idh).version = 1; | |
1427 (**yuv_idh).revisionLevel = 0; | |
1428 (**yuv_idh).width = width; | |
1429 (**yuv_idh).height = height; | |
1430 (**yuv_idh).hRes = Long2Fix(72); | |
1431 (**yuv_idh).vRes = Long2Fix(72); | |
1432 (**yuv_idh).spatialQuality = codecLosslessQuality; | |
1433 (**yuv_idh).frameCount = 1; | |
1434 (**yuv_idh).clutID = -1; | |
1435 (**yuv_idh).dataSize = 0; | |
1436 (**yuv_idh).depth = 12; | |
1437 | |
1438 HUnlock ((Handle)yuv_idh); | |
1439 | |
1440 err = DecompressSequenceBeginS ( | |
1441 &yuv_seq, | |
1442 yuv_idh, | |
1443 NULL, | |
1444 0, | |
1445 port, | |
1446 NULL, | |
1447 NULL, | |
1448 yuv_matrix, | |
1449 0, | |
1450 NULL, | |
1451 codecFlagUseImageBuffer, | |
1452 codecLosslessQuality, | |
1453 yuv_codec); | |
1454 | |
1455 if (err != noErr) { | |
1456 SDL_SetError ("Error trying to start YUV codec."); | |
1457 return NULL; | |
1458 } | |
1459 | |
1460 overlay = (SDL_Overlay*) malloc (sizeof(*overlay)); | |
1461 if (overlay == NULL) { | |
1462 SDL_OutOfMemory(); | |
1463 return NULL; | |
1464 } | |
1465 | |
1466 overlay->format = format; | |
1467 overlay->w = width; | |
1468 overlay->h = height; | |
1469 overlay->planes = 3; | |
1470 overlay->hw_overlay = 1; | |
1471 { | |
1472 int offset; | |
1473 Uint8 **pixels; | |
1474 Uint16 *pitches; | |
1475 int plane2, plane3; | |
1476 | |
1477 if (format == SDL_IYUV_OVERLAY) { | |
1478 | |
1479 plane2 = 1; /* Native codec format */ | |
1480 plane3 = 2; | |
1481 } | |
1482 else if (format == SDL_YV12_OVERLAY) { | |
1483 | |
1484 /* switch the U and V planes */ | |
1485 plane2 = 2; /* U plane maps to plane 3 */ | |
1486 plane3 = 1; /* V plane maps to plane 2 */ | |
1487 } | |
1488 else { | |
1489 SDL_SetError("Unsupported YUV format"); | |
1490 return NULL; | |
1491 } | |
1492 | |
1493 pixels = (Uint8**) malloc (sizeof(*pixels) * 3); | |
1494 pitches = (Uint16*) malloc (sizeof(*pitches) * 3); | |
1495 if (pixels == NULL || pitches == NULL) { | |
1496 SDL_OutOfMemory(); | |
1497 return NULL; | |
1498 } | |
1499 | |
1500 yuv_pixmap = (PlanarPixmapInfoYUV420*) | |
1501 malloc (sizeof(PlanarPixmapInfoYUV420) + | |
1502 (width * height * 2)); | |
1503 if (yuv_pixmap == NULL) { | |
1504 SDL_OutOfMemory (); | |
1505 return NULL; | |
1506 } | |
1507 | |
1508 //CHECK_ALIGN(yuv_pixmap); | |
1509 offset = sizeof(PlanarPixmapInfoYUV420); | |
1510 //offset += ALIGN(offset); | |
1511 //CHECK_ALIGN(offset); | |
1512 | |
1513 pixels[0] = (Uint8*)yuv_pixmap + offset; | |
1514 //CHECK_ALIGN(pixels[0]); | |
1515 | |
1516 pitches[0] = width; | |
1517 yuv_pixmap->componentInfoY.offset = offset; | |
1518 yuv_pixmap->componentInfoY.rowBytes = width; | |
1519 | |
1520 offset += width * height; | |
1521 pixels[plane2] = (Uint8*)yuv_pixmap + offset; | |
1522 pitches[plane2] = width / 2; | |
1523 yuv_pixmap->componentInfoCb.offset = offset; | |
1524 yuv_pixmap->componentInfoCb.rowBytes = width / 2; | |
1525 | |
1526 offset += (width * height / 4); | |
1527 pixels[plane3] = (Uint8*)yuv_pixmap + offset; | |
1528 pitches[plane3] = width / 2; | |
1529 yuv_pixmap->componentInfoCr.offset = offset; | |
1530 yuv_pixmap->componentInfoCr.rowBytes = width / 2; | |
1531 | |
1532 overlay->pixels = pixels; | |
1533 overlay->pitches = pitches; | |
1534 } | |
1535 | |
1536 overlay->hwfuncs = malloc (sizeof(*overlay->hwfuncs)); | |
1537 if (overlay->hwfuncs == NULL) { | |
1538 SDL_OutOfMemory(); | |
1539 return NULL; | |
1540 } | |
1541 | |
1542 overlay->hwfuncs->Lock = QZ_LockYUV; | |
1543 overlay->hwfuncs->Unlock = QZ_UnlockYUV; | |
1544 overlay->hwfuncs->Display = QZ_DisplayYUV; | |
1545 overlay->hwfuncs->FreeHW = QZ_FreeHWYUV; | |
1546 | |
1547 yuv_width = overlay->w; | |
1548 yuv_height = overlay->h; | |
1549 | |
1550 return overlay; | |
1551 } | |
1552 |