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