gdi32: Don't call GetObjectW() unless necessary.
[wine.git] / dlls / winemac.drv / gdi.c
blobe110227037e61ccfa9a98fe81e296cd029535c73
1 /*
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
22 #include "config.h"
24 #include "macdrv.h"
25 #include "winreg.h"
27 WINE_DEFAULT_DEBUG_CHANNEL(macdrv);
30 typedef struct
32 struct gdi_physdev dev;
33 } MACDRV_PDEVICE;
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 /******************************************************************************
73 * get_dpi
75 * get the dpi from the registry
77 static DWORD get_dpi(void)
79 DWORD dpi = 0;
80 HKEY hkey;
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)
90 dpi = new_dpi;
92 RegCloseKey(hkey);
94 return dpi;
98 /***********************************************************************
99 * compute_desktop_rect
101 static void compute_desktop_rect(void)
103 CGDirectDisplayID displayIDs[32];
104 uint32_t count, i;
106 desktop_rect = CGRectNull;
107 if (CGGetActiveDisplayList(sizeof(displayIDs)/sizeof(displayIDs[0]),
108 displayIDs, &count) != kCGErrorSuccess ||
109 !count)
111 displayIDs[0] = CGMainDisplayID();
112 count = 1;
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)
128 CGRect ret;
130 EnterCriticalSection(&device_data_section);
132 if (!device_data_valid)
134 check_retina_status();
135 compute_desktop_rect();
137 ret = desktop_rect;
139 LeaveCriticalSection(&device_data_section);
141 TRACE("%s\n", wine_dbgstr_cgrect(ret));
143 return ret;
147 /**********************************************************************
148 * device_init
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();
162 if (!log_pixels_x)
164 size_t width = CGDisplayPixelsWide(mainDisplay);
165 size_t height = CGDisplayPixelsHigh(mainDisplay);
167 if (retina_on)
169 /* Although CGDisplayPixelsWide/High() claim to report in pixels, they
170 actually report in points. */
171 width *= 2;
172 height *= 2;
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;
182 bits_per_pixel = 32;
183 if (mode)
185 CFStringRef pixelEncoding = CGDisplayModeCopyPixelEncoding(mode);
187 horz_res = CGDisplayModeGetWidth(mode);
188 vert_res = CGDisplayModeGetHeight(mode);
190 if (pixelEncoding)
192 if (CFEqual(pixelEncoding, CFSTR(IO32BitDirectPixels)))
193 bits_per_pixel = 32;
194 else if (CFEqual(pixelEncoding, CFSTR(IO16BitDirectPixels)))
195 bits_per_pixel = 16;
196 else if (CFEqual(pixelEncoding, CFSTR(IO8BitIndexedPixels)))
197 bits_per_pixel = 8;
198 CFRelease(pixelEncoding);
201 CGDisplayModeRelease(mode);
203 else
205 horz_res = CGDisplayPixelsWide(mainDisplay);
206 vert_res = CGDisplayPixelsHigh(mainDisplay);
209 if (retina_on)
211 horz_res *= 2;
212 vert_res *= 2;
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;
241 return physDev;
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),
255 initData);
257 if (!physDev) return FALSE;
259 push_dc_driver(pdev, &physDev->dev, &macdrv_funcs);
260 return TRUE;
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);
277 return TRUE;
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);
291 return TRUE;
295 /***********************************************************************
296 * GetDeviceCaps (MACDRV.@)
298 static INT macdrv_GetDeviceCaps(PHYSDEV dev, INT cap)
300 INT ret;
302 EnterCriticalSection(&device_data_section);
304 if (!device_data_valid) device_init();
306 switch(cap)
308 case DRIVERVERSION:
309 ret = 0x300;
310 break;
311 case TECHNOLOGY:
312 ret = DT_RASDISPLAY;
313 break;
314 case HORZSIZE:
315 ret = horz_size;
316 break;
317 case VERTSIZE:
318 ret = vert_size;
319 break;
320 case HORZRES:
321 ret = horz_res;
322 break;
323 case VERTRES:
324 ret = vert_res;
325 break;
326 case DESKTOPHORZRES:
327 ret = desktop_horz_res;
328 break;
329 case DESKTOPVERTRES:
330 ret = desktop_vert_res;
331 break;
332 case BITSPIXEL:
333 ret = bits_per_pixel;
334 break;
335 case PLANES:
336 ret = 1;
337 break;
338 case NUMBRUSHES:
339 ret = -1;
340 break;
341 case NUMPENS:
342 ret = -1;
343 break;
344 case NUMMARKERS:
345 ret = 0;
346 break;
347 case NUMFONTS:
348 ret = 0;
349 break;
350 case NUMCOLORS:
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);
355 break;
356 case PDEVICESIZE:
357 ret = sizeof(MACDRV_PDEVICE);
358 break;
359 case CURVECAPS:
360 ret = (CC_CIRCLES | CC_PIE | CC_CHORD | CC_ELLIPSES | CC_WIDE |
361 CC_STYLED | CC_WIDESTYLED | CC_INTERIORS | CC_ROUNDRECT);
362 break;
363 case LINECAPS:
364 ret = (LC_POLYLINE | LC_MARKER | LC_POLYMARKER | LC_WIDE |
365 LC_STYLED | LC_WIDESTYLED | LC_INTERIORS);
366 break;
367 case POLYGONALCAPS:
368 ret = (PC_POLYGON | PC_RECTANGLE | PC_WINDPOLYGON | PC_SCANLINE |
369 PC_WIDE | PC_STYLED | PC_WIDESTYLED | PC_INTERIORS);
370 break;
371 case TEXTCAPS:
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);
375 break;
376 case CLIPCAPS:
377 ret = CP_REGION;
378 break;
379 case COLORRES:
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;
387 break;
388 case RASTERCAPS:
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));
392 break;
393 case SHADEBLENDCAPS:
394 ret = (SB_GRAD_RECT | SB_GRAD_TRI | SB_CONST_ALPHA | SB_PIXEL_ALPHA);
395 break;
396 case ASPECTX:
397 case ASPECTY:
398 ret = 36;
399 break;
400 case ASPECTXY:
401 ret = 51;
402 break;
403 case LOGPIXELSX:
404 ret = log_pixels_x;
405 break;
406 case LOGPIXELSY:
407 ret = log_pixels_y;
408 break;
409 case CAPS1:
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
412 to be returned. */
413 ret = 0;
414 break;
415 case SIZEPALETTE:
416 ret = bits_per_pixel <= 8 ? 1 << bits_per_pixel : 0;
417 break;
418 case NUMRESERVED:
419 case PHYSICALWIDTH:
420 case PHYSICALHEIGHT:
421 case PHYSICALOFFSETX:
422 case PHYSICALOFFSETY:
423 case SCALINGFACTORX:
424 case SCALINGFACTORY:
425 case VREFRESH:
426 case BLTALIGNMENT:
427 ret = 0;
428 break;
429 default:
430 FIXME("(%p): unsupported capability %d, will return 0\n", dev->hdc, cap);
431 ret = 0;
432 goto done;
435 TRACE("cap %d -> %d\n", cap, ret);
437 done:
438 LeaveCriticalSection(&device_data_section);
439 return ret;
443 static const struct gdi_dc_funcs macdrv_funcs =
445 NULL, /* pAbortDoc */
446 NULL, /* pAbortPath */
447 NULL, /* pAlphaBlend */
448 NULL, /* pAngleArc */
449 NULL, /* pArc */
450 NULL, /* pArcTo */
451 NULL, /* pBeginPath */
452 NULL, /* pBlendImage */
453 NULL, /* pChord */
454 NULL, /* pCloseFigure */
455 macdrv_CreateCompatibleDC, /* pCreateCompatibleDC */
456 macdrv_CreateDC, /* pCreateDC */
457 macdrv_DeleteDC, /* pDeleteDC */
458 NULL, /* pDeleteObject */
459 NULL, /* pDeviceCapabilities */
460 NULL, /* pEllipse */
461 NULL, /* pEndDoc */
462 NULL, /* pEndPage */
463 NULL, /* pEndPath */
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 */
473 NULL, /* pFillRgn */
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 */
504 NULL, /* pLineTo */
505 NULL, /* pModifyWorldTransform */
506 NULL, /* pMoveTo */
507 NULL, /* pOffsetClipRgn */
508 NULL, /* pOffsetViewportOrg */
509 NULL, /* pOffsetWindowOrg */
510 NULL, /* pPaintRgn */
511 NULL, /* pPatBlt */
512 NULL, /* pPie */
513 NULL, /* pPolyBezier */
514 NULL, /* pPolyBezierTo */
515 NULL, /* pPolyDraw */
516 NULL, /* pPolyPolygon */
517 NULL, /* pPolyPolyline */
518 NULL, /* pPolygon */
519 NULL, /* pPolyline */
520 NULL, /* pPolylineTo */
521 NULL, /* pPutImage */
522 NULL, /* pRealizeDefaultPalette */
523 NULL, /* pRealizePalette */
524 NULL, /* pRectangle */
525 NULL, /* pResetDC */
526 NULL, /* pRestoreDC */
527 NULL, /* pRoundRect */
528 NULL, /* pSaveDC */
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 */
551 NULL, /* pSetROP2 */
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);
584 return NULL;
586 return &macdrv_funcs;