Mercurial > sdl-ios-xcode
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 } |