2 * Mac graphics driver initialisation functions
4 * Copyright 1996 Alexandre Julliard
5 * Copyright 2011, 2012, 2013 Ken Thomases for CodeWeavers, Inc.
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
27 WINE_DEFAULT_DEBUG_CHANNEL(macdrv
);
32 struct gdi_physdev dev
;
35 static inline MACDRV_PDEVICE
*get_macdrv_dev(PHYSDEV dev
)
37 return (MACDRV_PDEVICE
*)dev
;
41 /* a few dynamic device caps */
42 static CGRect desktop_rect
; /* virtual desktop rectangle */
43 static int log_pixels_x
; /* pixels per logical inch in x direction */
44 static int log_pixels_y
; /* pixels per logical inch in y direction */
45 static int horz_size
; /* horz. size of screen in millimeters */
46 static int vert_size
; /* vert. size of screen in millimeters */
47 static int horz_res
; /* width in pixels of screen */
48 static int vert_res
; /* height in pixels of screen */
49 static int desktop_horz_res
; /* width in pixels of virtual desktop */
50 static int desktop_vert_res
; /* height in pixels of virtual desktop */
51 static int bits_per_pixel
; /* pixel depth of screen */
52 static int device_data_valid
; /* do the above variables have up-to-date values? */
54 int retina_on
= FALSE
;
56 static CRITICAL_SECTION device_data_section
;
57 static CRITICAL_SECTION_DEBUG critsect_debug
=
59 0, 0, &device_data_section
,
60 { &critsect_debug
.ProcessLocksList
, &critsect_debug
.ProcessLocksList
},
61 0, 0, { (DWORD_PTR
)(__FILE__
": device_data_section") }
63 static CRITICAL_SECTION device_data_section
= { &critsect_debug
, -1, 0, 0, 0, 0 };
66 static const WCHAR dpi_key_name
[] = {'S','o','f','t','w','a','r','e','\\','F','o','n','t','s','\0'};
67 static const WCHAR dpi_value_name
[] = {'L','o','g','P','i','x','e','l','s','\0'};
69 static const struct gdi_dc_funcs macdrv_funcs
;
72 /******************************************************************************
75 * get the dpi from the registry
77 static DWORD
get_dpi(void)
82 if (RegOpenKeyW(HKEY_CURRENT_CONFIG
, dpi_key_name
, &hkey
) == ERROR_SUCCESS
)
84 DWORD type
, size
, new_dpi
;
86 size
= sizeof(new_dpi
);
87 if (RegQueryValueExW(hkey
, dpi_value_name
, NULL
, &type
, (void *)&new_dpi
, &size
) == ERROR_SUCCESS
)
89 if (type
== REG_DWORD
&& new_dpi
!= 0)
98 /***********************************************************************
99 * compute_desktop_rect
101 static void compute_desktop_rect(void)
103 CGDirectDisplayID displayIDs
[32];
106 desktop_rect
= CGRectNull
;
107 if (CGGetActiveDisplayList(sizeof(displayIDs
)/sizeof(displayIDs
[0]),
108 displayIDs
, &count
) != kCGErrorSuccess
||
111 displayIDs
[0] = CGMainDisplayID();
115 for (i
= 0; i
< count
; i
++)
116 desktop_rect
= CGRectUnion(desktop_rect
, CGDisplayBounds(displayIDs
[i
]));
117 desktop_rect
= cgrect_win_from_mac(desktop_rect
);
121 /***********************************************************************
122 * macdrv_get_desktop_rect
124 * Returns the rectangle encompassing all the screens.
126 CGRect
macdrv_get_desktop_rect(void)
130 EnterCriticalSection(&device_data_section
);
132 if (!device_data_valid
)
134 check_retina_status();
135 compute_desktop_rect();
139 LeaveCriticalSection(&device_data_section
);
141 TRACE("%s\n", wine_dbgstr_cgrect(ret
));
147 /**********************************************************************
150 * Perform initializations needed upon creation of the first device.
152 static void device_init(void)
154 CGDirectDisplayID mainDisplay
= CGMainDisplayID();
155 CGSize size_mm
= CGDisplayScreenSize(mainDisplay
);
156 CGDisplayModeRef mode
= CGDisplayCopyDisplayMode(mainDisplay
);
158 check_retina_status();
160 /* Initialize device caps */
161 log_pixels_x
= log_pixels_y
= get_dpi();
164 size_t width
= CGDisplayPixelsWide(mainDisplay
);
165 size_t height
= CGDisplayPixelsHigh(mainDisplay
);
169 /* Although CGDisplayPixelsWide/High() claim to report in pixels, they
170 actually report in points. */
175 log_pixels_x
= MulDiv(width
, 254, size_mm
.width
* 10);
176 log_pixels_y
= MulDiv(height
, 254, size_mm
.height
* 10);
179 horz_size
= size_mm
.width
;
180 vert_size
= size_mm
.height
;
185 CFStringRef pixelEncoding
= CGDisplayModeCopyPixelEncoding(mode
);
187 horz_res
= CGDisplayModeGetWidth(mode
);
188 vert_res
= CGDisplayModeGetHeight(mode
);
192 if (CFEqual(pixelEncoding
, CFSTR(IO32BitDirectPixels
)))
194 else if (CFEqual(pixelEncoding
, CFSTR(IO16BitDirectPixels
)))
196 else if (CFEqual(pixelEncoding
, CFSTR(IO8BitIndexedPixels
)))
198 CFRelease(pixelEncoding
);
201 CGDisplayModeRelease(mode
);
205 horz_res
= CGDisplayPixelsWide(mainDisplay
);
206 vert_res
= CGDisplayPixelsHigh(mainDisplay
);
215 compute_desktop_rect();
216 desktop_horz_res
= desktop_rect
.size
.width
;
217 desktop_vert_res
= desktop_rect
.size
.height
;
219 device_data_valid
= TRUE
;
223 void macdrv_reset_device_metrics(void)
225 EnterCriticalSection(&device_data_section
);
226 device_data_valid
= FALSE
;
227 LeaveCriticalSection(&device_data_section
);
231 static MACDRV_PDEVICE
*create_mac_physdev(void)
233 MACDRV_PDEVICE
*physDev
;
235 EnterCriticalSection(&device_data_section
);
236 if (!device_data_valid
) device_init();
237 LeaveCriticalSection(&device_data_section
);
239 if (!(physDev
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*physDev
)))) return NULL
;
245 /**********************************************************************
246 * CreateDC (MACDRV.@)
248 static BOOL
macdrv_CreateDC(PHYSDEV
*pdev
, LPCWSTR driver
, LPCWSTR device
,
249 LPCWSTR output
, const DEVMODEW
* initData
)
251 MACDRV_PDEVICE
*physDev
= create_mac_physdev();
253 TRACE("pdev %p hdc %p driver %s device %s output %s initData %p\n", pdev
,
254 (*pdev
)->hdc
, debugstr_w(driver
),debugstr_w(device
), debugstr_w(output
),
257 if (!physDev
) return FALSE
;
259 push_dc_driver(pdev
, &physDev
->dev
, &macdrv_funcs
);
264 /**********************************************************************
265 * CreateCompatibleDC (MACDRV.@)
267 static BOOL
macdrv_CreateCompatibleDC(PHYSDEV orig
, PHYSDEV
*pdev
)
269 MACDRV_PDEVICE
*physDev
= create_mac_physdev();
271 TRACE("orig %p orig->hdc %p pdev %p pdev->hdc %p\n", orig
, (orig
? orig
->hdc
: NULL
), pdev
,
272 ((pdev
&& *pdev
) ? (*pdev
)->hdc
: NULL
));
274 if (!physDev
) return FALSE
;
276 push_dc_driver(pdev
, &physDev
->dev
, &macdrv_funcs
);
281 /**********************************************************************
282 * DeleteDC (MACDRV.@)
284 static BOOL
macdrv_DeleteDC(PHYSDEV dev
)
286 MACDRV_PDEVICE
*physDev
= get_macdrv_dev(dev
);
288 TRACE("hdc %p\n", dev
->hdc
);
290 HeapFree(GetProcessHeap(), 0, physDev
);
295 /***********************************************************************
296 * GetDeviceCaps (MACDRV.@)
298 static INT
macdrv_GetDeviceCaps(PHYSDEV dev
, INT cap
)
302 EnterCriticalSection(&device_data_section
);
304 if (!device_data_valid
) device_init();
327 ret
= desktop_horz_res
;
330 ret
= desktop_vert_res
;
333 ret
= bits_per_pixel
;
351 /* MSDN: Number of entries in the device's color table, if the device has
352 * a color depth of no more than 8 bits per pixel.For devices with greater
353 * color depths, -1 is returned. */
354 ret
= (bits_per_pixel
> 8) ? -1 : (1 << bits_per_pixel
);
357 ret
= sizeof(MACDRV_PDEVICE
);
360 ret
= (CC_CIRCLES
| CC_PIE
| CC_CHORD
| CC_ELLIPSES
| CC_WIDE
|
361 CC_STYLED
| CC_WIDESTYLED
| CC_INTERIORS
| CC_ROUNDRECT
);
364 ret
= (LC_POLYLINE
| LC_MARKER
| LC_POLYMARKER
| LC_WIDE
|
365 LC_STYLED
| LC_WIDESTYLED
| LC_INTERIORS
);
368 ret
= (PC_POLYGON
| PC_RECTANGLE
| PC_WINDPOLYGON
| PC_SCANLINE
|
369 PC_WIDE
| PC_STYLED
| PC_WIDESTYLED
| PC_INTERIORS
);
372 ret
= (TC_OP_CHARACTER
| TC_OP_STROKE
| TC_CP_STROKE
|
373 TC_CR_ANY
| TC_SF_X_YINDEP
| TC_SA_DOUBLE
| TC_SA_INTEGER
|
374 TC_SA_CONTIN
| TC_UA_ABLE
| TC_SO_ABLE
| TC_RA_ABLE
| TC_VA_ABLE
);
380 /* The observed correspondence between BITSPIXEL and COLORRES is:
381 * BITSPIXEL: 8 -> COLORRES: 18
382 * BITSPIXEL: 16 -> COLORRES: 16
383 * BITSPIXEL: 24 -> COLORRES: 24
384 * (note that bits_per_pixel is never 24)
385 * BITSPIXEL: 32 -> COLORRES: 24 */
386 ret
= (bits_per_pixel
<= 8) ? 18 : (bits_per_pixel
== 32) ? 24 : bits_per_pixel
;
389 ret
= (RC_BITBLT
| RC_BANDING
| RC_SCALING
| RC_BITMAP64
| RC_DI_BITMAP
|
390 RC_DIBTODEV
| RC_BIGFONT
| RC_STRETCHBLT
| RC_STRETCHDIB
| RC_DEVBITS
|
391 (bits_per_pixel
<= 8 ? RC_PALETTE
: 0));
394 ret
= (SB_GRAD_RECT
| SB_GRAD_TRI
| SB_CONST_ALPHA
| SB_PIXEL_ALPHA
);
410 FIXME("(%p): CAPS1 is unimplemented, will return 0\n", dev
->hdc
);
411 /* please see wingdi.h for the possible bit-flag values that need
416 ret
= bits_per_pixel
<= 8 ? 1 << bits_per_pixel
: 0;
421 case PHYSICALOFFSETX
:
422 case PHYSICALOFFSETY
:
430 FIXME("(%p): unsupported capability %d, will return 0\n", dev
->hdc
, cap
);
435 TRACE("cap %d -> %d\n", cap
, ret
);
438 LeaveCriticalSection(&device_data_section
);
443 static const struct gdi_dc_funcs macdrv_funcs
=
445 NULL
, /* pAbortDoc */
446 NULL
, /* pAbortPath */
447 NULL
, /* pAlphaBlend */
448 NULL
, /* pAngleArc */
451 NULL
, /* pBeginPath */
452 NULL
, /* pBlendImage */
454 NULL
, /* pCloseFigure */
455 macdrv_CreateCompatibleDC
, /* pCreateCompatibleDC */
456 macdrv_CreateDC
, /* pCreateDC */
457 macdrv_DeleteDC
, /* pDeleteDC */
458 NULL
, /* pDeleteObject */
459 NULL
, /* pDeviceCapabilities */
464 NULL
, /* pEnumFonts */
465 NULL
, /* pEnumICMProfiles */
466 NULL
, /* pExcludeClipRect */
467 NULL
, /* pExtDeviceMode */
468 NULL
, /* pExtEscape */
469 NULL
, /* pExtFloodFill */
470 NULL
, /* pExtSelectClipRgn */
471 NULL
, /* pExtTextOut */
472 NULL
, /* pFillPath */
474 NULL
, /* pFlattenPath */
475 NULL
, /* pFontIsLinked */
476 NULL
, /* pFrameRgn */
477 NULL
, /* pGdiComment */
478 NULL
, /* pGetBoundsRect */
479 NULL
, /* pGetCharABCWidths */
480 NULL
, /* pGetCharABCWidthsI */
481 NULL
, /* pGetCharWidth */
482 macdrv_GetDeviceCaps
, /* pGetDeviceCaps */
483 macdrv_GetDeviceGammaRamp
, /* pGetDeviceGammaRamp */
484 NULL
, /* pGetFontData */
485 NULL
, /* pGetFontRealizationInfo */
486 NULL
, /* pGetFontUnicodeRanges */
487 NULL
, /* pGetGlyphIndices */
488 NULL
, /* pGetGlyphOutline */
489 NULL
, /* pGetICMProfile */
490 NULL
, /* pGetImage */
491 NULL
, /* pGetKerningPairs */
492 NULL
, /* pGetNearestColor */
493 NULL
, /* pGetOutlineTextMetrics */
494 NULL
, /* pGetPixel */
495 NULL
, /* pGetSystemPaletteEntries */
496 NULL
, /* pGetTextCharsetInfo */
497 NULL
, /* pGetTextExtentExPoint */
498 NULL
, /* pGetTextExtentExPointI */
499 NULL
, /* pGetTextFace */
500 NULL
, /* pGetTextMetrics */
501 NULL
, /* pGradientFill */
502 NULL
, /* pIntersectClipRect */
503 NULL
, /* pInvertRgn */
505 NULL
, /* pModifyWorldTransform */
507 NULL
, /* pOffsetClipRgn */
508 NULL
, /* pOffsetViewportOrg */
509 NULL
, /* pOffsetWindowOrg */
510 NULL
, /* pPaintRgn */
513 NULL
, /* pPolyBezier */
514 NULL
, /* pPolyBezierTo */
515 NULL
, /* pPolyDraw */
516 NULL
, /* pPolyPolygon */
517 NULL
, /* pPolyPolyline */
519 NULL
, /* pPolyline */
520 NULL
, /* pPolylineTo */
521 NULL
, /* pPutImage */
522 NULL
, /* pRealizeDefaultPalette */
523 NULL
, /* pRealizePalette */
524 NULL
, /* pRectangle */
526 NULL
, /* pRestoreDC */
527 NULL
, /* pRoundRect */
529 NULL
, /* pScaleViewportExt */
530 NULL
, /* pScaleWindowExt */
531 NULL
, /* pSelectBitmap */
532 NULL
, /* pSelectBrush */
533 NULL
, /* pSelectClipPath */
534 NULL
, /* pSelectFont */
535 NULL
, /* pSelectPalette */
536 NULL
, /* pSelectPen */
537 NULL
, /* pSetArcDirection */
538 NULL
, /* pSetBkColor */
539 NULL
, /* pSetBkMode */
540 NULL
, /* pSetBoundsRect */
541 NULL
, /* pSetDCBrushColor */
542 NULL
, /* pSetDCPenColor */
543 NULL
, /* pSetDIBitsToDevice */
544 NULL
, /* pSetDeviceClipping */
545 macdrv_SetDeviceGammaRamp
, /* pSetDeviceGammaRamp */
546 NULL
, /* pSetLayout */
547 NULL
, /* pSetMapMode */
548 NULL
, /* pSetMapperFlags */
549 NULL
, /* pSetPixel */
550 NULL
, /* pSetPolyFillMode */
552 NULL
, /* pSetRelAbs */
553 NULL
, /* pSetStretchBltMode */
554 NULL
, /* pSetTextAlign */
555 NULL
, /* pSetTextCharacterExtra */
556 NULL
, /* pSetTextColor */
557 NULL
, /* pSetTextJustification */
558 NULL
, /* pSetViewportExt */
559 NULL
, /* pSetViewportOrg */
560 NULL
, /* pSetWindowExt */
561 NULL
, /* pSetWindowOrg */
562 NULL
, /* pSetWorldTransform */
563 NULL
, /* pStartDoc */
564 NULL
, /* pStartPage */
565 NULL
, /* pStretchBlt */
566 NULL
, /* pStretchDIBits */
567 NULL
, /* pStrokeAndFillPath */
568 NULL
, /* pStrokePath */
569 NULL
, /* pUnrealizePalette */
570 NULL
, /* pWidenPath */
571 macdrv_wine_get_wgl_driver
, /* wine_get_wgl_driver */
572 GDI_PRIORITY_GRAPHICS_DRV
/* priority */
576 /******************************************************************************
577 * macdrv_get_gdi_driver
579 const struct gdi_dc_funcs
* CDECL
macdrv_get_gdi_driver(unsigned int version
)
581 if (version
!= WINE_GDI_DRIVER_VERSION
)
583 ERR("version mismatch, gdi32 wants %u but winemac has %u\n", version
, WINE_GDI_DRIVER_VERSION
);
586 return &macdrv_funcs
;