comparison src/video/quartz/SDL_QuartzVideo.m @ 761:c5b2b6d2d1fe

Date: Wed, 31 Dec 2003 21:55:30 +0100 From: Max Horn Subject: SDL: video/quartz cleanup while doing some experimental changes in the quartz code, I was annoyed by having to recompile that one big .o file over and over again. So I decided to finally realize one TODO: properly splitting the code over multiple files :-). With two exceptions, I didn't make code changes, only rearranged files and added new headers. Since there are several new files, making a patch didn't work out so well, so I decided to just send you all the new & modified files. The one source change I made is related to showing/hiding the mouse. I renamed cursor_visible to cursor_should_be_visible and cursor_hidden to cursor_visible; I think that makes reading the code easier. Then I added two new functions: QZ_ShowMouse and QZ_HideMouse. They help manage cursor_visible (the former 'cursor_hidden'). Finally I replaced the Carbon ShowCursor/HiderCuror calls by [NSCursor hide] and [NSCursor unhide]. The API docs are not conclusive, but it might be that with those the "cursor_visible" (former 'cursor_hidden') hack may not be necessary anymore; however so far I didn't test this hypothesis, so I left that in. The other change was to remove in_foreground and use [NSApp isActive] instead: Manually keeping track of whether we are in the foreground is error prone. This should work better in some corner cases.
author Sam Lantinga <slouken@libsdl.org>
date Sun, 04 Jan 2004 14:55:35 +0000
parents 5d2f027b3349
children de1b2c3063b9
comparison
equal deleted inserted replaced
760:cf9dd3aa6756 761:c5b2b6d2d1fe
1 /* 1 /*
2 SDL - Simple DirectMedia Layer 2 SDL - Simple DirectMedia Layer
3 Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002 Sam Lantinga 3 Copyright (C) 1997-2003 Sam Lantinga
4 4
5 This library is free software; you can redistribute it and/or 5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Library General Public 6 modify it under the terms of the GNU Library General Public
7 License as published by the Free Software Foundation; either 7 License as published by the Free Software Foundation; either
8 version 2 of the License, or (at your option) any later version. 8 version 2 of the License, or (at your option) any later version.
19 Sam Lantinga 19 Sam Lantinga
20 slouken@libsdl.org 20 slouken@libsdl.org
21 */ 21 */
22 22
23 #include "SDL_QuartzVideo.h" 23 #include "SDL_QuartzVideo.h"
24 24 #include "SDL_QuartzWindow.h"
25 /* Include files into one compile unit...break apart eventually */ 25
26 #include "SDL_QuartzWM.m" 26
27 #include "SDL_QuartzEvents.m" 27 /*
28 #include "SDL_QuartzWindow.m" 28 Add methods to get at private members of NSScreen.
29 Since there is a bug in Apple's screen switching code
30 that does not update this variable when switching
31 to fullscreen, we'll set it manually (but only for the
32 main screen).
33 */
34 @interface NSScreen (NSScreenAccess)
35 - (void) setFrame:(NSRect)frame;
36 @end
37
38 @implementation NSScreen (NSScreenAccess)
39 - (void) setFrame:(NSRect)frame;
40 {
41 _frame = frame;
42 }
43 @end
44
45
46 /*
47 Structure for rez switch gamma fades
48 We can hide the monitor flicker by setting the gamma tables to 0
49 */
50 #define QZ_GAMMA_TABLE_SIZE 256
51
52 typedef struct {
53
54 CGGammaValue red[QZ_GAMMA_TABLE_SIZE];
55 CGGammaValue green[QZ_GAMMA_TABLE_SIZE];
56 CGGammaValue blue[QZ_GAMMA_TABLE_SIZE];
57
58 } SDL_QuartzGammaTable;
59
60
61 /* Bootstrap functions */
62 static int QZ_Available ();
63 static SDL_VideoDevice* QZ_CreateDevice (int device_index);
64 static void QZ_DeleteDevice (SDL_VideoDevice *device);
65
66 /* Initialization, Query, Setup, and Redrawing functions */
67 static int QZ_VideoInit (_THIS, SDL_PixelFormat *video_format);
68
69 static SDL_Rect** QZ_ListModes (_THIS, SDL_PixelFormat *format,
70 Uint32 flags);
71 static void QZ_UnsetVideoMode (_THIS);
72
73 static SDL_Surface* QZ_SetVideoMode (_THIS, SDL_Surface *current,
74 int width, int height, int bpp,
75 Uint32 flags);
76 static int QZ_ToggleFullScreen (_THIS, int on);
77 static int QZ_SetColors (_THIS, int first_color,
78 int num_colors, SDL_Color *colors);
79
80 static int QZ_LockDoubleBuffer (_THIS, SDL_Surface *surface);
81 static void QZ_UnlockDoubleBuffer (_THIS, SDL_Surface *surface);
82 static int QZ_ThreadFlip (_THIS);
83 static int QZ_FlipDoubleBuffer (_THIS, SDL_Surface *surface);
84 static void QZ_DoubleBufferUpdate (_THIS, int num_rects, SDL_Rect *rects);
85
86 static void QZ_DirectUpdate (_THIS, int num_rects, SDL_Rect *rects);
87 static int QZ_LockWindow (_THIS, SDL_Surface *surface);
88 static void QZ_UnlockWindow (_THIS, SDL_Surface *surface);
89 static void QZ_UpdateRects (_THIS, int num_rects, SDL_Rect *rects);
90 static void QZ_VideoQuit (_THIS);
91
92 /* Hardware surface functions (for fullscreen mode only) */
93 #if 0 /* Not used (apparently, it's really slow) */
94 static int QZ_FillHWRect (_THIS, SDL_Surface *dst, SDL_Rect *rect, Uint32 color);
95 #endif
96 static int QZ_LockHWSurface(_THIS, SDL_Surface *surface);
97 static void QZ_UnlockHWSurface(_THIS, SDL_Surface *surface);
98 static void QZ_FreeHWSurface (_THIS, SDL_Surface *surface);
99 /* static int QZ_FlipHWSurface (_THIS, SDL_Surface *surface); */
29 100
30 /* Bootstrap binding, enables entry point into the driver */ 101 /* Bootstrap binding, enables entry point into the driver */
31 VideoBootStrap QZ_bootstrap = { 102 VideoBootStrap QZ_bootstrap = {
32 "Quartz", "Mac OS X CoreGraphics", QZ_Available, QZ_CreateDevice 103 "Quartz", "Mac OS X CoreGraphics", QZ_Available, QZ_CreateDevice
33 }; 104 };
128 199
129 video_format->BitsPerPixel = device_bpp; 200 video_format->BitsPerPixel = device_bpp;
130 201
131 /* Set misc globals */ 202 /* Set misc globals */
132 current_grab_mode = SDL_GRAB_OFF; 203 current_grab_mode = SDL_GRAB_OFF;
133 in_foreground = YES; 204 cursor_should_be_visible = YES;
134 cursor_visible = YES;
135 205
136 /* register for sleep notifications so wake from sleep generates SDL_VIDEOEXPOSE */ 206 /* register for sleep notifications so wake from sleep generates SDL_VIDEOEXPOSE */
137 QZ_RegisterForSleepNotifications (this); 207 QZ_RegisterForSleepNotifications (this);
138 208
139 return 0; 209 return 0;
710 else { 780 else {
711 781
712 /* Only recreate the view if it doesn't already exist */ 782 /* Only recreate the view if it doesn't already exist */
713 if (window_view == nil) { 783 if (window_view == nil) {
714 784
715 window_view = [ [ SDL_QuartzWindowView alloc ] initWithFrame:contentRect ]; 785 window_view = [ [ NSQuickDrawView alloc ] initWithFrame:contentRect ];
716 [ window_view setAutoresizingMask: NSViewMinYMargin ]; 786 [ window_view setAutoresizingMask: NSViewMinYMargin ];
717 [ [ qz_window contentView ] addSubview:window_view ]; 787 [ [ qz_window contentView ] addSubview:window_view ];
718 [ window_view release ]; 788 [ window_view release ];
719 [ qz_window makeKeyAndOrderFront:nil ]; 789 [ qz_window makeKeyAndOrderFront:nil ];
720 } 790 }
849 /* The VBL delay is based on code by Ian R Ollmann's RezLib <iano@cco.caltech.edu> */ 919 /* The VBL delay is based on code by Ian R Ollmann's RezLib <iano@cco.caltech.edu> */
850 static AbsoluteTime QZ_SecondsToAbsolute ( double seconds ) { 920 static AbsoluteTime QZ_SecondsToAbsolute ( double seconds ) {
851 921
852 union 922 union
853 { 923 {
854 UInt64 i; 924 UInt64 i;
855 Nanoseconds ns; 925 Nanoseconds ns;
856 } temp; 926 } temp;
857 927
858 temp.i = seconds * 1000000000.0; 928 temp.i = seconds * 1000000000.0;
859 929
988 1058
989 /* 1059 /*
990 The obscured code is based on work by Matt Slot fprefect@ambrosiasw.com, 1060 The obscured code is based on work by Matt Slot fprefect@ambrosiasw.com,
991 who supplied sample code for Carbon. 1061 who supplied sample code for Carbon.
992 */ 1062 */
1063
1064 //#define TEST_OBSCURED 1
1065
1066 #if TEST_OBSCURED
1067 #include "CGS.h"
1068 #endif
1069
993 static int QZ_IsWindowObscured (NSWindow *window) { 1070 static int QZ_IsWindowObscured (NSWindow *window) {
994 1071
995 //#define TEST_OBSCURED 1
996 1072
997 #if TEST_OBSCURED 1073 #if TEST_OBSCURED
998 1074
999 /* 1075 /*
1000 In order to determine if a direct copy to the screen is possible, 1076 In order to determine if a direct copy to the screen is possible,
1228 static void QZ_UnlockWindow (_THIS, SDL_Surface *surface) { 1304 static void QZ_UnlockWindow (_THIS, SDL_Surface *surface) {
1229 1305
1230 UnlockPortBits ( [ window_view qdPort ] ); 1306 UnlockPortBits ( [ window_view qdPort ] );
1231 } 1307 }
1232 1308
1309 /* Resize icon, BMP format */
1310 static const unsigned char QZ_ResizeIcon[] = {
1311 0x42,0x4d,0x31,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x36,0x00,0x00,0x00,0x28,0x00,
1312 0x00,0x00,0x0d,0x00,0x00,0x00,0x0d,0x00,0x00,0x00,0x01,0x00,0x18,0x00,0x00,0x00,
1313 0x00,0x00,0xfb,0x01,0x00,0x00,0x13,0x0b,0x00,0x00,0x13,0x0b,0x00,0x00,0x00,0x00,
1314 0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
1315 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
1316 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x0b,0xff,0xff,
1317 0xff,0xda,0xda,0xda,0x87,0x87,0x87,0xe8,0xe8,0xe8,0xff,0xff,0xff,0xda,0xda,0xda,
1318 0x87,0x87,0x87,0xe8,0xe8,0xe8,0xff,0xff,0xff,0xda,0xda,0xda,0x87,0x87,0x87,0xe8,
1319 0xe8,0xe8,0xff,0xff,0xff,0x0b,0xff,0xff,0xff,0xff,0xff,0xff,0xda,0xda,0xda,0x87,
1320 0x87,0x87,0xe8,0xe8,0xe8,0xff,0xff,0xff,0xda,0xda,0xda,0x87,0x87,0x87,0xe8,0xe8,
1321 0xe8,0xff,0xff,0xff,0xda,0xda,0xda,0x87,0x87,0x87,0xff,0xff,0xff,0x0b,0xff,0xff,
1322 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xd5,0xd5,0xd5,0x87,0x87,0x87,0xe8,0xe8,0xe8,
1323 0xff,0xff,0xff,0xda,0xda,0xda,0x87,0x87,0x87,0xe8,0xe8,0xe8,0xff,0xff,0xff,0xda,
1324 0xda,0xda,0xff,0xff,0xff,0x0b,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
1325 0xff,0xff,0xd7,0xd7,0xd7,0x87,0x87,0x87,0xe8,0xe8,0xe8,0xff,0xff,0xff,0xda,0xda,
1326 0xda,0x87,0x87,0x87,0xe8,0xe8,0xe8,0xff,0xff,0xff,0xff,0xff,0xff,0x0b,0xff,0xff,
1327 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xd7,0xd7,0xd7,
1328 0x87,0x87,0x87,0xe8,0xe8,0xe8,0xff,0xff,0xff,0xda,0xda,0xda,0x87,0x87,0x87,0xe8,
1329 0xe8,0xe8,0xff,0xff,0xff,0x0b,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
1330 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xd7,0xd7,0xd7,0x87,0x87,0x87,0xe8,0xe8,
1331 0xe8,0xff,0xff,0xff,0xdc,0xdc,0xdc,0x87,0x87,0x87,0xff,0xff,0xff,0x0b,0xff,0xff,
1332 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
1333 0xff,0xff,0xff,0xd9,0xd9,0xd9,0x87,0x87,0x87,0xe8,0xe8,0xe8,0xff,0xff,0xff,0xdc,
1334 0xdc,0xdc,0xff,0xff,0xff,0x0b,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
1335 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xdb,0xdb,
1336 0xdb,0x87,0x87,0x87,0xe8,0xe8,0xe8,0xff,0xff,0xff,0xff,0xff,0xff,0x0b,0xff,0xff,
1337 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
1338 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xdb,0xdb,0xdb,0x87,0x87,0x87,0xe8,
1339 0xe8,0xe8,0xff,0xff,0xff,0x0b,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
1340 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
1341 0xff,0xff,0xff,0xff,0xdc,0xdc,0xdc,0x87,0x87,0x87,0xff,0xff,0xff,0x0b,0xff,0xff,
1342 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
1343 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xdc,
1344 0xdc,0xdc,0xff,0xff,0xff,0x0b,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
1345 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
1346 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x0b
1347 };
1348
1349 static void QZ_DrawResizeIcon (_THIS, RgnHandle dirtyRegion) {
1350
1351 /* Check if we should draw the resize icon */
1352 if (SDL_VideoSurface->flags & SDL_RESIZABLE) {
1353
1354 Rect icon;
1355 SetRect (&icon, SDL_VideoSurface->w - 13, SDL_VideoSurface->h - 13,
1356 SDL_VideoSurface->w, SDL_VideoSurface->h);
1357
1358 if (RectInRgn (&icon, dirtyRegion)) {
1359
1360 SDL_Rect icon_rect;
1361
1362 /* Create the icon image */
1363 if (resize_icon == NULL) {
1364
1365 SDL_RWops *rw;
1366 SDL_Surface *tmp;
1367
1368 rw = SDL_RWFromMem (QZ_ResizeIcon, sizeof(QZ_ResizeIcon));
1369 tmp = SDL_LoadBMP_RW (rw, SDL_TRUE);
1370
1371 resize_icon = SDL_ConvertSurface (tmp, SDL_VideoSurface->format, SDL_SRCCOLORKEY);
1372 SDL_SetColorKey (resize_icon, SDL_SRCCOLORKEY, 0xFFFFFF);
1373
1374 SDL_FreeSurface (tmp);
1375 }
1376
1377 icon_rect.x = SDL_VideoSurface->w - 13;
1378 icon_rect.y = SDL_VideoSurface->h - 13;
1379 icon_rect.w = 13;
1380 icon_rect.h = 13;
1381
1382 SDL_BlitSurface (resize_icon, NULL, SDL_VideoSurface, &icon_rect);
1383 }
1384 }
1385 }
1386
1233 static void QZ_UpdateRects (_THIS, int numRects, SDL_Rect *rects) { 1387 static void QZ_UpdateRects (_THIS, int numRects, SDL_Rect *rects) {
1234 1388
1235 if (SDL_VideoSurface->flags & SDL_OPENGLBLIT) { 1389 if (SDL_VideoSurface->flags & SDL_OPENGLBLIT) {
1236 QZ_GL_SwapBuffers (this); 1390 QZ_GL_SwapBuffers (this);
1237 } 1391 }
1351 return 0; 1505 return 0;
1352 } 1506 }
1353 */ 1507 */
1354 1508
1355 /* Gamma functions */ 1509 /* Gamma functions */
1356 static int QZ_SetGamma (_THIS, float red, float green, float blue) { 1510 int QZ_SetGamma (_THIS, float red, float green, float blue) {
1357 1511
1358 const CGGammaValue min = 0.0, max = 1.0; 1512 const CGGammaValue min = 0.0, max = 1.0;
1359 1513
1360 if (red == 0.0) 1514 if (red == 0.0)
1361 red = FLT_MAX; 1515 red = FLT_MAX;
1381 1535
1382 return -1; 1536 return -1;
1383 } 1537 }
1384 } 1538 }
1385 1539
1386 static int QZ_GetGamma (_THIS, float *red, float *green, float *blue) { 1540 int QZ_GetGamma (_THIS, float *red, float *green, float *blue) {
1387 1541
1388 CGGammaValue dummy; 1542 CGGammaValue dummy;
1389 if ( CGDisplayNoErr == CGGetDisplayTransferByFormula 1543 if ( CGDisplayNoErr == CGGetDisplayTransferByFormula
1390 (display_id, &dummy, &dummy, red, 1544 (display_id, &dummy, &dummy, red,
1391 &dummy, &dummy, green, &dummy, &dummy, blue) ) 1545 &dummy, &dummy, green, &dummy, &dummy, blue) )
1393 return 0; 1547 return 0;
1394 else 1548 else
1395 return -1; 1549 return -1;
1396 } 1550 }
1397 1551
1398 static int QZ_SetGammaRamp (_THIS, Uint16 *ramp) { 1552 int QZ_SetGammaRamp (_THIS, Uint16 *ramp) {
1399 1553
1400 const CGTableCount tableSize = 255; 1554 const CGTableCount tableSize = 255;
1401 CGGammaValue redTable[tableSize]; 1555 CGGammaValue redTable[tableSize];
1402 CGGammaValue greenTable[tableSize]; 1556 CGGammaValue greenTable[tableSize];
1403 CGGammaValue blueTable[tableSize]; 1557 CGGammaValue blueTable[tableSize];
1419 return 0; 1573 return 0;
1420 else 1574 else
1421 return -1; 1575 return -1;
1422 } 1576 }
1423 1577
1424 static int QZ_GetGammaRamp (_THIS, Uint16 *ramp) { 1578 int QZ_GetGammaRamp (_THIS, Uint16 *ramp) {
1425 1579
1426 const CGTableCount tableSize = 255; 1580 const CGTableCount tableSize = 255;
1427 CGGammaValue redTable[tableSize]; 1581 CGGammaValue redTable[tableSize];
1428 CGGammaValue greenTable[tableSize]; 1582 CGGammaValue greenTable[tableSize];
1429 CGGammaValue blueTable[tableSize]; 1583 CGGammaValue blueTable[tableSize];
1447 ramp[i] = blueTable[i % 256] * 65535.0; 1601 ramp[i] = blueTable[i % 256] * 65535.0;
1448 1602
1449 return 0; 1603 return 0;
1450 } 1604 }
1451 1605
1452 /* OpenGL helper functions (used internally) */
1453
1454 static int QZ_SetupOpenGL (_THIS, int bpp, Uint32 flags) {
1455
1456 NSOpenGLPixelFormatAttribute attr[32];
1457 NSOpenGLPixelFormat *fmt;
1458 int i = 0;
1459 int colorBits = bpp;
1460
1461 if ( flags & SDL_FULLSCREEN ) {
1462
1463 attr[i++] = NSOpenGLPFAFullScreen;
1464 }
1465 /* In windowed mode, the OpenGL pixel depth must match device pixel depth */
1466 else if ( colorBits != device_bpp ) {
1467
1468 colorBits = device_bpp;
1469 }
1470
1471 attr[i++] = NSOpenGLPFAColorSize;
1472 attr[i++] = colorBits;
1473
1474 attr[i++] = NSOpenGLPFADepthSize;
1475 attr[i++] = this->gl_config.depth_size;
1476
1477 if ( this->gl_config.double_buffer ) {
1478 attr[i++] = NSOpenGLPFADoubleBuffer;
1479 }
1480
1481 if ( this->gl_config.stereo ) {
1482 attr[i++] = NSOpenGLPFAStereo;
1483 }
1484
1485 if ( this->gl_config.stencil_size != 0 ) {
1486 attr[i++] = NSOpenGLPFAStencilSize;
1487 attr[i++] = this->gl_config.stencil_size;
1488 }
1489
1490 #if NSOPENGL_CURRENT_VERSION > 1 /* What version should this be? */
1491 if ( this->gl_config.multisamplebuffers != 0 ) {
1492 attr[i++] = NSOpenGLPFASampleBuffers;
1493 attr[i++] = this->gl_config.multisamplebuffers;
1494 }
1495
1496 if ( this->gl_config.multisamplesamples != 0 ) {
1497 attr[i++] = NSOpenGLPFASamples;
1498 attr[i++] = this->gl_config.multisamplesamples;
1499 }
1500 #endif
1501
1502 attr[i++] = NSOpenGLPFAScreenMask;
1503 attr[i++] = CGDisplayIDToOpenGLDisplayMask (display_id);
1504 attr[i] = 0;
1505
1506 fmt = [ [ NSOpenGLPixelFormat alloc ] initWithAttributes:attr ];
1507 if (fmt == nil) {
1508 SDL_SetError ("Failed creating OpenGL pixel format");
1509 return 0;
1510 }
1511
1512 gl_context = [ [ NSOpenGLContext alloc ] initWithFormat:fmt
1513 shareContext:nil];
1514
1515 if (gl_context == nil) {
1516 SDL_SetError ("Failed creating OpenGL context");
1517 return 0;
1518 }
1519
1520 /*
1521 * Wisdom from Apple engineer in reference to UT2003's OpenGL performance:
1522 * "You are blowing a couple of the internal OpenGL function caches. This
1523 * appears to be happening in the VAO case. You can tell OpenGL to up
1524 * the cache size by issuing the following calls right after you create
1525 * the OpenGL context. The default cache size is 16." --ryan.
1526 */
1527
1528 #ifndef GLI_ARRAY_FUNC_CACHE_MAX
1529 #define GLI_ARRAY_FUNC_CACHE_MAX 284
1530 #endif
1531
1532 #ifndef GLI_SUBMIT_FUNC_CACHE_MAX
1533 #define GLI_SUBMIT_FUNC_CACHE_MAX 280
1534 #endif
1535
1536 {
1537 long cache_max = 64;
1538 CGLContextObj ctx = [ gl_context cglContext ];
1539 CGLSetParameter (ctx, GLI_SUBMIT_FUNC_CACHE_MAX, &cache_max);
1540 CGLSetParameter (ctx, GLI_ARRAY_FUNC_CACHE_MAX, &cache_max);
1541 }
1542
1543 /* End Wisdom from Apple Engineer section. --ryan. */
1544
1545 /* Convince SDL that the GL "driver" is loaded */
1546 this->gl_config.driver_loaded = 1;
1547
1548 [ fmt release ];
1549
1550 return 1;
1551 }
1552
1553 static void QZ_TearDownOpenGL (_THIS) {
1554
1555 [ NSOpenGLContext clearCurrentContext ];
1556 [ gl_context clearDrawable ];
1557 [ gl_context release ];
1558 }
1559
1560
1561 /* SDL OpenGL functions */
1562
1563 static int QZ_GL_LoadLibrary (_THIS, const char *location) {
1564 this->gl_config.driver_loaded = 1;
1565 return 1;
1566 }
1567
1568 static void* QZ_GL_GetProcAddress (_THIS, const char *proc) {
1569
1570 /* We may want to cache the bundleRef at some point */
1571 CFBundleRef bundle;
1572 CFURLRef bundleURL = CFURLCreateWithFileSystemPath (kCFAllocatorDefault,
1573 CFSTR("/System/Library/Frameworks/OpenGL.framework"), kCFURLPOSIXPathStyle, true);
1574
1575 CFStringRef functionName = CFStringCreateWithCString
1576 (kCFAllocatorDefault, proc, kCFStringEncodingASCII);
1577
1578 void *function;
1579
1580 bundle = CFBundleCreate (kCFAllocatorDefault, bundleURL);
1581 assert (bundle != NULL);
1582
1583 function = CFBundleGetFunctionPointerForName (bundle, functionName);
1584
1585 CFRelease ( bundleURL );
1586 CFRelease ( functionName );
1587 CFRelease ( bundle );
1588
1589 return function;
1590 }
1591
1592 static int QZ_GL_GetAttribute (_THIS, SDL_GLattr attrib, int* value) {
1593
1594 GLenum attr = 0;
1595
1596 QZ_GL_MakeCurrent (this);
1597
1598 switch (attrib) {
1599 case SDL_GL_RED_SIZE: attr = GL_RED_BITS; break;
1600 case SDL_GL_BLUE_SIZE: attr = GL_BLUE_BITS; break;
1601 case SDL_GL_GREEN_SIZE: attr = GL_GREEN_BITS; break;
1602 case SDL_GL_ALPHA_SIZE: attr = GL_ALPHA_BITS; break;
1603 case SDL_GL_DOUBLEBUFFER: attr = GL_DOUBLEBUFFER; break;
1604 case SDL_GL_DEPTH_SIZE: attr = GL_DEPTH_BITS; break;
1605 case SDL_GL_STENCIL_SIZE: attr = GL_STENCIL_BITS; break;
1606 case SDL_GL_ACCUM_RED_SIZE: attr = GL_ACCUM_RED_BITS; break;
1607 case SDL_GL_ACCUM_GREEN_SIZE: attr = GL_ACCUM_GREEN_BITS; break;
1608 case SDL_GL_ACCUM_BLUE_SIZE: attr = GL_ACCUM_BLUE_BITS; break;
1609 case SDL_GL_ACCUM_ALPHA_SIZE: attr = GL_ACCUM_ALPHA_BITS; break;
1610 case SDL_GL_STEREO: attr = GL_STEREO; break;
1611 case SDL_GL_MULTISAMPLEBUFFERS: attr = GL_SAMPLE_BUFFERS_ARB; break;
1612 case SDL_GL_MULTISAMPLESAMPLES: attr = GL_SAMPLES_ARB; break;
1613 case SDL_GL_BUFFER_SIZE:
1614 {
1615 GLint bits = 0;
1616 GLint component;
1617
1618 /* there doesn't seem to be a single flag in OpenGL for this! */
1619 glGetIntegerv (GL_RED_BITS, &component); bits += component;
1620 glGetIntegerv (GL_GREEN_BITS,&component); bits += component;
1621 glGetIntegerv (GL_BLUE_BITS, &component); bits += component;
1622 glGetIntegerv (GL_ALPHA_BITS, &component); bits += component;
1623
1624 *value = bits;
1625 }
1626 return 0;
1627 }
1628
1629 glGetIntegerv (attr, (GLint *)value);
1630 return 0;
1631 }
1632
1633 static int QZ_GL_MakeCurrent (_THIS) {
1634 [ gl_context makeCurrentContext ];
1635 return 0;
1636 }
1637
1638 static void QZ_GL_SwapBuffers (_THIS) {
1639 [ gl_context flushBuffer ];
1640 }
1641
1642 static int QZ_LockYUV (_THIS, SDL_Overlay *overlay) {
1643
1644 return 0;
1645 }
1646
1647 static void QZ_UnlockYUV (_THIS, SDL_Overlay *overlay) {
1648
1649 ;
1650 }
1651
1652 static int QZ_DisplayYUV (_THIS, SDL_Overlay *overlay, SDL_Rect *dstrect) {
1653
1654 OSErr err;
1655 CodecFlags flags;
1656
1657 if (dstrect->x != 0 || dstrect->y != 0) {
1658
1659 SDL_SetError ("Need a dstrect at (0,0)");
1660 return -1;
1661 }
1662
1663 if (dstrect->w != yuv_width || dstrect->h != yuv_height) {
1664
1665 Fixed scale_x, scale_y;
1666
1667 scale_x = FixDiv ( Long2Fix (dstrect->w), Long2Fix (overlay->w) );
1668 scale_y = FixDiv ( Long2Fix (dstrect->h), Long2Fix (overlay->h) );
1669
1670 SetIdentityMatrix (yuv_matrix);
1671 ScaleMatrix (yuv_matrix, scale_x, scale_y, Long2Fix (0), Long2Fix (0));
1672
1673 SetDSequenceMatrix (yuv_seq, yuv_matrix);
1674
1675 yuv_width = dstrect->w;
1676 yuv_height = dstrect->h;
1677 }
1678
1679 if( ( err = DecompressSequenceFrameS(
1680 yuv_seq,
1681 (void*)yuv_pixmap,
1682 sizeof (PlanarPixmapInfoYUV420),
1683 codecFlagUseImageBuffer, &flags, nil ) != noErr ) )
1684 {
1685 SDL_SetError ("DecompressSequenceFrameS failed");
1686 }
1687
1688 return err == noErr;
1689 }
1690
1691 static void QZ_FreeHWYUV (_THIS, SDL_Overlay *overlay) {
1692
1693 CDSequenceEnd (yuv_seq);
1694 ExitMovies();
1695
1696 free (overlay->hwfuncs);
1697 free (overlay->pitches);
1698 free (overlay->pixels);
1699
1700 if (SDL_VideoSurface->flags & SDL_FULLSCREEN) {
1701 [ qz_window close ];
1702 qz_window = nil;
1703 }
1704
1705 free (yuv_matrix);
1706 DisposeHandle ((Handle)yuv_idh);
1707 }
1708
1709 #include "SDL_yuvfuncs.h"
1710
1711 /* check for 16 byte alignment, bail otherwise */
1712 #define CHECK_ALIGN(x) do { if ((Uint32)x & 15) { SDL_SetError("Alignment error"); return NULL; } } while(0)
1713
1714 /* align a byte offset, return how much to add to make it a multiple of 16 */
1715 #define ALIGN(x) ((16 - (x & 15)) & 15)
1716
1717 static SDL_Overlay* QZ_CreateYUVOverlay (_THIS, int width, int height,
1718 Uint32 format, SDL_Surface *display) {
1719
1720 Uint32 codec;
1721 OSStatus err;
1722 CGrafPtr port;
1723 SDL_Overlay *overlay;
1724
1725 if (format == SDL_YV12_OVERLAY ||
1726 format == SDL_IYUV_OVERLAY) {
1727
1728 codec = kYUV420CodecType;
1729 }
1730 else {
1731 SDL_SetError ("Hardware: unsupported video format");
1732 return NULL;
1733 }
1734
1735 yuv_idh = (ImageDescriptionHandle) NewHandleClear (sizeof(ImageDescription));
1736 if (yuv_idh == NULL) {
1737 SDL_OutOfMemory();
1738 return NULL;
1739 }
1740
1741 yuv_matrix = (MatrixRecordPtr) malloc (sizeof(MatrixRecord));
1742 if (yuv_matrix == NULL) {
1743 SDL_OutOfMemory();
1744 return NULL;
1745 }
1746
1747 if ( EnterMovies() != noErr ) {
1748 SDL_SetError ("Could not init QuickTime for YUV playback");
1749 return NULL;
1750 }
1751
1752 err = FindCodec (codec, bestSpeedCodec, nil, &yuv_codec);
1753 if (err != noErr) {
1754 SDL_SetError ("Could not find QuickTime codec for format");
1755 return NULL;
1756 }
1757
1758 if (SDL_VideoSurface->flags & SDL_FULLSCREEN) {
1759
1760 /*
1761 Acceleration requires a window to be present.
1762 A CGrafPtr that points to the screen isn't good enough
1763 */
1764 NSRect content = NSMakeRect (0, 0, SDL_VideoSurface->w, SDL_VideoSurface->h);
1765
1766 qz_window = [ [ SDL_QuartzWindow alloc ]
1767 initWithContentRect:content
1768 styleMask:NSBorderlessWindowMask
1769 backing:NSBackingStoreBuffered defer:NO ];
1770
1771 if (qz_window == nil) {
1772 SDL_SetError ("Could not create the Cocoa window");
1773 return NULL;
1774 }
1775
1776 [ qz_window setContentView:[ [ SDL_QuartzWindowView alloc ] init ] ];
1777 [ qz_window setReleasedWhenClosed:YES ];
1778 [ qz_window center ];
1779 [ qz_window setAcceptsMouseMovedEvents:YES ];
1780 [ qz_window setLevel:CGShieldingWindowLevel() ];
1781 [ qz_window makeKeyAndOrderFront:nil ];
1782
1783 port = [ [ qz_window contentView ] qdPort ];
1784 SetPort (port);
1785
1786 /*
1787 BUG: would like to remove white flash when window kicks in
1788 {
1789 Rect r;
1790 SetRect (&r, 0, 0, SDL_VideoSurface->w, SDL_VideoSurface->h);
1791 PaintRect (&r);
1792 QDFlushPortBuffer (port, nil);
1793 }
1794 */
1795 }
1796 else {
1797 port = [ window_view qdPort ];
1798 SetPort (port);
1799 }
1800
1801 SetIdentityMatrix (yuv_matrix);
1802
1803 HLock ((Handle)yuv_idh);
1804
1805 (**yuv_idh).idSize = sizeof(ImageDescription);
1806 (**yuv_idh).cType = codec;
1807 (**yuv_idh).version = 1;
1808 (**yuv_idh).revisionLevel = 0;
1809 (**yuv_idh).width = width;
1810 (**yuv_idh).height = height;
1811 (**yuv_idh).hRes = Long2Fix(72);
1812 (**yuv_idh).vRes = Long2Fix(72);
1813 (**yuv_idh).spatialQuality = codecLosslessQuality;
1814 (**yuv_idh).frameCount = 1;
1815 (**yuv_idh).clutID = -1;
1816 (**yuv_idh).dataSize = 0;
1817 (**yuv_idh).depth = 24;
1818
1819 HUnlock ((Handle)yuv_idh);
1820
1821 err = DecompressSequenceBeginS (
1822 &yuv_seq,
1823 yuv_idh,
1824 NULL,
1825 0,
1826 port,
1827 NULL,
1828 NULL,
1829 yuv_matrix,
1830 0,
1831 NULL,
1832 codecFlagUseImageBuffer,
1833 codecLosslessQuality,
1834 yuv_codec);
1835
1836 if (err != noErr) {
1837 SDL_SetError ("Error trying to start YUV codec.");
1838 return NULL;
1839 }
1840
1841 overlay = (SDL_Overlay*) malloc (sizeof(*overlay));
1842 if (overlay == NULL) {
1843 SDL_OutOfMemory();
1844 return NULL;
1845 }
1846
1847 overlay->format = format;
1848 overlay->w = width;
1849 overlay->h = height;
1850 overlay->planes = 3;
1851 overlay->hw_overlay = 1;
1852 {
1853 int offset;
1854 Uint8 **pixels;
1855 Uint16 *pitches;
1856 int plane2, plane3;
1857
1858 if (format == SDL_IYUV_OVERLAY) {
1859
1860 plane2 = 1; /* Native codec format */
1861 plane3 = 2;
1862 }
1863 else if (format == SDL_YV12_OVERLAY) {
1864
1865 /* switch the U and V planes */
1866 plane2 = 2; /* U plane maps to plane 3 */
1867 plane3 = 1; /* V plane maps to plane 2 */
1868 }
1869 else {
1870 SDL_SetError("Unsupported YUV format");
1871 return NULL;
1872 }
1873
1874 pixels = (Uint8**) malloc (sizeof(*pixels) * 3);
1875 pitches = (Uint16*) malloc (sizeof(*pitches) * 3);
1876 if (pixels == NULL || pitches == NULL) {
1877 SDL_OutOfMemory();
1878 return NULL;
1879 }
1880
1881 yuv_pixmap = (PlanarPixmapInfoYUV420*)
1882 malloc (sizeof(PlanarPixmapInfoYUV420) +
1883 (width * height * 2));
1884 if (yuv_pixmap == NULL) {
1885 SDL_OutOfMemory ();
1886 return NULL;
1887 }
1888
1889 /* CHECK_ALIGN(yuv_pixmap); */
1890 offset = sizeof(PlanarPixmapInfoYUV420);
1891 /* offset += ALIGN(offset); */
1892 /* CHECK_ALIGN(offset); */
1893
1894 pixels[0] = (Uint8*)yuv_pixmap + offset;
1895 /* CHECK_ALIGN(pixels[0]); */
1896
1897 pitches[0] = width;
1898 yuv_pixmap->componentInfoY.offset = offset;
1899 yuv_pixmap->componentInfoY.rowBytes = width;
1900
1901 offset += width * height;
1902 pixels[plane2] = (Uint8*)yuv_pixmap + offset;
1903 pitches[plane2] = width / 2;
1904 yuv_pixmap->componentInfoCb.offset = offset;
1905 yuv_pixmap->componentInfoCb.rowBytes = width / 2;
1906
1907 offset += (width * height / 4);
1908 pixels[plane3] = (Uint8*)yuv_pixmap + offset;
1909 pitches[plane3] = width / 2;
1910 yuv_pixmap->componentInfoCr.offset = offset;
1911 yuv_pixmap->componentInfoCr.rowBytes = width / 2;
1912
1913 overlay->pixels = pixels;
1914 overlay->pitches = pitches;
1915 }
1916
1917 overlay->hwfuncs = malloc (sizeof(*overlay->hwfuncs));
1918 if (overlay->hwfuncs == NULL) {
1919 SDL_OutOfMemory();
1920 return NULL;
1921 }
1922
1923 overlay->hwfuncs->Lock = QZ_LockYUV;
1924 overlay->hwfuncs->Unlock = QZ_UnlockYUV;
1925 overlay->hwfuncs->Display = QZ_DisplayYUV;
1926 overlay->hwfuncs->FreeHW = QZ_FreeHWYUV;
1927
1928 yuv_width = overlay->w;
1929 yuv_height = overlay->h;
1930
1931 return overlay;
1932 }