First import
[xorg_rtime.git] / xorg-server-1.4 / hw / darwin / quartz / fullscreen / fullscreen.c
blob02f6e89a8b929c344492ca9e398cb62adb0090a8
1 /*
2 * Screen routines for full screen Quartz mode
4 * Copyright (c) 2002-2003 Torrey T. Lyons. All Rights Reserved.
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the "Software"),
8 * to deal in the Software without restriction, including without limitation
9 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 * and/or sell copies of the Software, and to permit persons to whom the
11 * Software is furnished to do so, subject to the following conditions:
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * TORREY T. LYONS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
20 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
21 * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 * SOFTWARE.
24 * Except as contained in this notice, the name(s) of the above copyright
25 * holders shall not be used in advertising or otherwise to promote the sale,
26 * use or other dealings in this Software without prior written authorization.
28 #ifdef HAVE_XORG_CONFIG_H
29 #include <xorg-config.h>
30 #endif
31 #include "quartz/quartzCommon.h"
32 #include "darwin.h"
33 #include "quartz/quartz.h"
34 #include "quartz/quartzCursor.h"
35 #include "colormapst.h"
36 #include "scrnintstr.h"
37 #include "micmap.h"
38 #include "shadow.h"
40 // Full screen specific per screen storage structure
41 typedef struct {
42 CGDirectDisplayID displayID;
43 CFDictionaryRef xDisplayMode;
44 CFDictionaryRef aquaDisplayMode;
45 CGDirectPaletteRef xPalette;
46 CGDirectPaletteRef aquaPalette;
47 unsigned char *framebuffer;
48 unsigned char *shadowPtr;
49 } FSScreenRec, *FSScreenPtr;
51 #define FULLSCREEN_PRIV(pScreen) \
52 ((FSScreenPtr)pScreen->devPrivates[fsScreenIndex].ptr)
54 static int fsScreenIndex;
55 static CGDirectDisplayID *quartzDisplayList = NULL;
56 static int quartzNumScreens = 0;
57 static FSScreenPtr quartzScreens[MAXSCREENS];
59 static int darwinCmapPrivateIndex = -1;
60 static unsigned long darwinCmapGeneration = 0;
62 #define CMAP_PRIV(pCmap) \
63 ((CGDirectPaletteRef) (pCmap)->devPrivates[darwinCmapPrivateIndex].ptr)
66 =============================================================================
68 Colormap handling
70 =============================================================================
74 * FSInitCmapPrivates
75 * Colormap privates may be allocated after the default colormap has
76 * already been created for some screens. This initialization procedure
77 * is called for each default colormap that is found.
79 static Bool
80 FSInitCmapPrivates(
81 ColormapPtr pCmap)
83 return TRUE;
88 * FSCreateColormap
89 * This is a callback from X after a new colormap is created.
90 * We allocate a new CoreGraphics pallete for each colormap.
92 static Bool
93 FSCreateColormap(
94 ColormapPtr pCmap)
96 CGDirectPaletteRef pallete;
98 // Allocate private storage for the hardware dependent colormap info.
99 if (darwinCmapGeneration != serverGeneration) {
100 if ((darwinCmapPrivateIndex =
101 AllocateColormapPrivateIndex(FSInitCmapPrivates)) < 0)
103 return FALSE;
105 darwinCmapGeneration = serverGeneration;
108 pallete = CGPaletteCreateDefaultColorPalette();
109 if (!pallete) return FALSE;
111 CMAP_PRIV(pCmap) = pallete;
112 return TRUE;
117 * FSDestroyColormap
118 * This is called by DIX FreeColormap after it has uninstalled a colormap
119 * and notified all interested parties. We deallocated the corresponding
120 * CoreGraphics pallete.
122 static void
123 FSDestroyColormap(
124 ColormapPtr pCmap)
126 CGPaletteRelease( CMAP_PRIV(pCmap) );
131 * FSInstallColormap
132 * Set the current CoreGraphics pallete to the pallete corresponding
133 * to the provided colormap.
135 static void
136 FSInstallColormap(
137 ColormapPtr pCmap)
139 CGDirectPaletteRef palette = CMAP_PRIV(pCmap);
140 ScreenPtr pScreen = pCmap->pScreen;
141 FSScreenPtr fsDisplayInfo = FULLSCREEN_PRIV(pScreen);
143 // Inform all interested parties that the map is being changed.
144 miInstallColormap(pCmap);
146 if (quartzServerVisible)
147 CGDisplaySetPalette(fsDisplayInfo->displayID, palette);
149 fsDisplayInfo->xPalette = palette;
154 * FSStoreColors
155 * This is a callback from X to change the hardware colormap
156 * when using PsuedoColor in full screen mode.
158 static void
159 FSStoreColors(
160 ColormapPtr pCmap,
161 int numEntries,
162 xColorItem *pdefs)
164 CGDirectPaletteRef palette = CMAP_PRIV(pCmap);
165 ScreenPtr pScreen = pCmap->pScreen;
166 FSScreenPtr fsDisplayInfo = FULLSCREEN_PRIV(pScreen);
167 CGDeviceColor color;
168 int i;
170 if (! palette)
171 return;
173 for (i = 0; i < numEntries; i++) {
174 color.red = pdefs[i].red / 65535.0;
175 color.green = pdefs[i].green / 65535.0;
176 color.blue = pdefs[i].blue / 65535.0;
177 CGPaletteSetColorAtIndex(palette, color, pdefs[i].pixel);
180 // Update hardware colormap
181 if (quartzServerVisible)
182 CGDisplaySetPalette(fsDisplayInfo->displayID, palette);
187 =============================================================================
189 Switching between Aqua and X
191 =============================================================================
195 * FSCapture
196 * Capture the screen so we can draw. Called directly from the main thread
197 * to synchronize with hiding the menubar.
199 static void FSCapture(void)
201 int i;
203 if (quartzRootless) return;
205 for (i = 0; i < quartzNumScreens; i++) {
206 FSScreenPtr fsDisplayInfo = quartzScreens[i];
207 CGDirectDisplayID cgID = fsDisplayInfo->displayID;
209 if (!CGDisplayIsCaptured(cgID)) {
210 CGDisplayCapture(cgID);
211 fsDisplayInfo->aquaDisplayMode = CGDisplayCurrentMode(cgID);
212 if (fsDisplayInfo->xDisplayMode != fsDisplayInfo->aquaDisplayMode)
213 CGDisplaySwitchToMode(cgID, fsDisplayInfo->xDisplayMode);
214 if (fsDisplayInfo->xPalette)
215 CGDisplaySetPalette(cgID, fsDisplayInfo->xPalette);
222 * FSRelease
223 * Release the screen so others can draw.
225 static void FSRelease(void)
227 int i;
229 if (quartzRootless) return;
231 for (i = 0; i < quartzNumScreens; i++) {
232 FSScreenPtr fsDisplayInfo = quartzScreens[i];
233 CGDirectDisplayID cgID = fsDisplayInfo->displayID;
235 if (CGDisplayIsCaptured(cgID)) {
236 if (fsDisplayInfo->xDisplayMode != fsDisplayInfo->aquaDisplayMode)
237 CGDisplaySwitchToMode(cgID, fsDisplayInfo->aquaDisplayMode);
238 if (fsDisplayInfo->aquaPalette)
239 CGDisplaySetPalette(cgID, fsDisplayInfo->aquaPalette);
240 CGDisplayRelease(cgID);
247 * FSSuspendScreen
248 * Suspend X11 cursor and drawing to the screen.
250 static void FSSuspendScreen(
251 ScreenPtr pScreen)
253 QuartzSuspendXCursor(pScreen);
254 xf86SetRootClip(pScreen, FALSE);
259 * FSResumeScreen
260 * Resume X11 cursor and drawing to the screen.
262 static void FSResumeScreen(
263 ScreenPtr pScreen,
264 int x, // cursor location
265 int y )
267 QuartzResumeXCursor(pScreen, x, y);
268 xf86SetRootClip(pScreen, TRUE);
273 =============================================================================
275 Screen initialization
277 =============================================================================
281 * FSDisplayInit
282 * Full screen specific initialization called from InitOutput.
284 static void FSDisplayInit(void)
286 static unsigned long generation = 0;
287 CGDisplayCount quartzDisplayCount = 0;
289 ErrorF("Display mode: Full screen Quartz -- Direct Display\n");
291 // Allocate private storage for each screen's mode specific info
292 if (generation != serverGeneration) {
293 fsScreenIndex = AllocateScreenPrivateIndex();
294 generation = serverGeneration;
297 // Find all the CoreGraphics displays
298 CGGetActiveDisplayList(0, NULL, &quartzDisplayCount);
299 quartzDisplayList = xalloc(quartzDisplayCount * sizeof(CGDirectDisplayID));
300 CGGetActiveDisplayList(quartzDisplayCount, quartzDisplayList,
301 &quartzDisplayCount);
303 darwinScreensFound = quartzDisplayCount;
304 atexit(FSRelease);
309 * FSFindDisplayMode
310 * Find the appropriate display mode to use in full screen mode.
311 * If display mode is not the same as the current Aqua mode, switch
312 * to the new mode.
314 static Bool FSFindDisplayMode(
315 FSScreenPtr fsDisplayInfo)
317 CGDirectDisplayID cgID = fsDisplayInfo->displayID;
318 size_t height, width, bpp;
319 boolean_t exactMatch;
321 fsDisplayInfo->aquaDisplayMode = CGDisplayCurrentMode(cgID);
323 // If no user options, use current display mode
324 if (darwinDesiredWidth == 0 && darwinDesiredDepth == -1 &&
325 darwinDesiredRefresh == -1)
327 fsDisplayInfo->xDisplayMode = fsDisplayInfo->aquaDisplayMode;
328 return TRUE;
331 // If the user has no choice for size, use current
332 if (darwinDesiredWidth == 0) {
333 width = CGDisplayPixelsWide(cgID);
334 height = CGDisplayPixelsHigh(cgID);
335 } else {
336 width = darwinDesiredWidth;
337 height = darwinDesiredHeight;
340 switch (darwinDesiredDepth) {
341 case 0:
342 bpp = 8;
343 break;
344 case 1:
345 bpp = 16;
346 break;
347 case 2:
348 bpp = 32;
349 break;
350 default:
351 bpp = CGDisplayBitsPerPixel(cgID);
354 if (darwinDesiredRefresh == -1) {
355 fsDisplayInfo->xDisplayMode =
356 CGDisplayBestModeForParameters(cgID, bpp, width, height,
357 &exactMatch);
358 } else {
359 fsDisplayInfo->xDisplayMode =
360 CGDisplayBestModeForParametersAndRefreshRate(cgID, bpp,
361 width, height, darwinDesiredRefresh, &exactMatch);
363 if (!exactMatch) {
364 fsDisplayInfo->xDisplayMode = fsDisplayInfo->aquaDisplayMode;
365 return FALSE;
368 // Switch to the new display mode
369 CGDisplaySwitchToMode(cgID, fsDisplayInfo->xDisplayMode);
370 return TRUE;
375 * FSAddScreen
376 * Do initialization of each screen for Quartz in full screen mode.
378 static Bool FSAddScreen(
379 int index,
380 ScreenPtr pScreen)
382 DarwinFramebufferPtr dfb = SCREEN_PRIV(pScreen);
383 QuartzScreenPtr displayInfo = QUARTZ_PRIV(pScreen);
384 CGDirectDisplayID cgID = quartzDisplayList[index];
385 CGRect bounds;
386 FSScreenPtr fsDisplayInfo;
388 // Allocate space for private per screen fullscreen specific storage.
389 fsDisplayInfo = xalloc(sizeof(FSScreenRec));
390 FULLSCREEN_PRIV(pScreen) = fsDisplayInfo;
392 displayInfo->displayCount = 1;
393 displayInfo->displayIDs = xrealloc(displayInfo->displayIDs,
394 1 * sizeof(CGDirectDisplayID));
395 displayInfo->displayIDs[0] = cgID;
397 fsDisplayInfo->displayID = cgID;
398 fsDisplayInfo->xDisplayMode = 0;
399 fsDisplayInfo->aquaDisplayMode = 0;
400 fsDisplayInfo->xPalette = 0;
401 fsDisplayInfo->aquaPalette = 0;
403 // Capture full screen because X doesn't like read-only framebuffer.
404 // We need to do this before we (potentially) switch the display mode.
405 CGDisplayCapture(cgID);
407 if (! FSFindDisplayMode(fsDisplayInfo)) {
408 ErrorF("Could not support specified display mode on screen %i.\n",
409 index);
410 xfree(fsDisplayInfo);
411 return FALSE;
414 // Don't need to flip y-coordinate as CoreGraphics treats (0, 0)
415 // as the top left of main screen.
416 bounds = CGDisplayBounds(cgID);
417 dfb->x = bounds.origin.x;
418 dfb->y = bounds.origin.y;
419 dfb->width = bounds.size.width;
420 dfb->height = bounds.size.height;
421 dfb->pitch = CGDisplayBytesPerRow(cgID);
422 dfb->bitsPerPixel = CGDisplayBitsPerPixel(cgID);
424 if (dfb->bitsPerPixel == 8) {
425 if (CGDisplayCanSetPalette(cgID)) {
426 dfb->colorType = PseudoColor;
427 } else {
428 dfb->colorType = StaticColor;
430 dfb->bitsPerComponent = 8;
431 dfb->colorBitsPerPixel = 8;
432 } else {
433 dfb->colorType = TrueColor;
434 dfb->bitsPerComponent = CGDisplayBitsPerSample(cgID);
435 dfb->colorBitsPerPixel = CGDisplaySamplesPerPixel(cgID) *
436 dfb->bitsPerComponent;
439 fsDisplayInfo->framebuffer = CGDisplayBaseAddress(cgID);
441 // allocate shadow framebuffer
442 fsDisplayInfo->shadowPtr = xalloc(dfb->pitch * dfb->height);
443 dfb->framebuffer = fsDisplayInfo->shadowPtr;
445 return TRUE;
450 * FSShadowUpdate
451 * Update the damaged regions of the shadow framebuffer on the display.
453 static void FSShadowUpdate(
454 ScreenPtr pScreen,
455 shadowBufPtr pBuf)
457 DarwinFramebufferPtr dfb = SCREEN_PRIV(pScreen);
458 FSScreenPtr fsDisplayInfo = FULLSCREEN_PRIV(pScreen);
459 RegionPtr damage = &pBuf->damage;
460 int numBox = REGION_NUM_RECTS(damage);
461 BoxPtr pBox = REGION_RECTS(damage);
462 int pitch = dfb->pitch;
463 int bpp = dfb->bitsPerPixel/8;
465 // Don't update if the X server is not visible
466 if (!quartzServerVisible)
467 return;
469 // Loop through all the damaged boxes
470 while (numBox--) {
471 int width, height, offset;
472 unsigned char *src, *dst;
474 width = (pBox->x2 - pBox->x1) * bpp;
475 height = pBox->y2 - pBox->y1;
476 offset = (pBox->y1 * pitch) + (pBox->x1 * bpp);
477 src = fsDisplayInfo->shadowPtr + offset;
478 dst = fsDisplayInfo->framebuffer + offset;
480 while (height--) {
481 memcpy(dst, src, width);
482 dst += pitch;
483 src += pitch;
486 // Get the next box
487 pBox++;
493 * FSSetupScreen
494 * Finalize full screen specific setup of each screen.
496 static Bool FSSetupScreen(
497 int index,
498 ScreenPtr pScreen)
500 DarwinFramebufferPtr dfb = SCREEN_PRIV(pScreen);
501 FSScreenPtr fsDisplayInfo = FULLSCREEN_PRIV(pScreen);
502 CGDirectDisplayID cgID = fsDisplayInfo->displayID;
504 // Initialize shadow framebuffer support
505 if (! shadowInit(pScreen, FSShadowUpdate, NULL)) {
506 ErrorF("Failed to initalize shadow framebuffer for screen %i.\n",
507 index);
508 return FALSE;
511 if (dfb->colorType == PseudoColor) {
512 // Initialize colormap handling
513 size_t aquaBpp;
515 // If Aqua is using 8 bits we need to keep track of its pallete.
516 CFNumberGetValue(CFDictionaryGetValue(fsDisplayInfo->aquaDisplayMode,
517 kCGDisplayBitsPerPixel), kCFNumberLongType, &aquaBpp);
518 if (aquaBpp <= 8)
519 fsDisplayInfo->aquaPalette = CGPaletteCreateWithDisplay(cgID);
521 pScreen->CreateColormap = FSCreateColormap;
522 pScreen->DestroyColormap = FSDestroyColormap;
523 pScreen->InstallColormap = FSInstallColormap;
524 pScreen->StoreColors = FSStoreColors;
528 quartzScreens[quartzNumScreens++] = fsDisplayInfo;
529 return TRUE;
534 * Quartz display mode function list.
536 static QuartzModeProcsRec fsModeProcs = {
537 FSDisplayInit,
538 FSAddScreen,
539 FSSetupScreen,
540 NULL, // Not needed
541 QuartzInitCursor,
542 QuartzReallySetCursor,
543 FSSuspendScreen,
544 FSResumeScreen,
545 FSCapture,
546 FSRelease,
547 NULL, // No dynamic screen change support
548 NULL,
549 NULL,
550 NULL, // No rootless code in fullscreen
551 NULL,
552 NULL,
553 NULL,
554 NULL, // No support for DRI surfaces
555 NULL
560 * QuartzModeBundleInit
561 * Initialize the display mode bundle after loading.
563 Bool
564 QuartzModeBundleInit(void)
566 quartzProcs = &fsModeProcs;
567 quartzOpenGLBundle = NULL; // Only Mesa support for now
568 return TRUE;