winemac: Fix compilation on Lion and later.
[wine] / dlls / winemac.drv / gdi.c
1 /*
2  * Mac graphics driver initialisation functions
3  *
4  * Copyright 1996 Alexandre Julliard
5  * Copyright 2011, 2012, 2013 Ken Thomases for CodeWeavers, Inc.
6  *
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.
11  *
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.
16  *
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
20  */
21
22 #include "config.h"
23
24 #include "macdrv.h"
25 #include "winreg.h"
26
27 WINE_DEFAULT_DEBUG_CHANNEL(macdrv);
28
29
30 typedef struct
31 {
32     struct gdi_physdev  dev;
33 } MACDRV_PDEVICE;
34
35 static inline MACDRV_PDEVICE *get_macdrv_dev(PHYSDEV dev)
36 {
37     return (MACDRV_PDEVICE*)dev;
38 }
39
40
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 palette_size;        /* number of color entries in palette */
53 static int device_data_valid;   /* do the above variables have up-to-date values? */
54
55 static CRITICAL_SECTION device_data_section;
56 static CRITICAL_SECTION_DEBUG critsect_debug =
57 {
58     0, 0, &device_data_section,
59     { &critsect_debug.ProcessLocksList, &critsect_debug.ProcessLocksList },
60       0, 0, { (DWORD_PTR)(__FILE__ ": device_data_section") }
61 };
62 static CRITICAL_SECTION device_data_section = { &critsect_debug, -1, 0, 0, 0, 0 };
63
64
65 static const WCHAR dpi_key_name[] = {'S','o','f','t','w','a','r','e','\\','F','o','n','t','s','\0'};
66 static const WCHAR dpi_value_name[] = {'L','o','g','P','i','x','e','l','s','\0'};
67
68 static const struct gdi_dc_funcs macdrv_funcs;
69
70
71 /******************************************************************************
72  *              get_dpi
73  *
74  * get the dpi from the registry
75  */
76 static DWORD get_dpi(void)
77 {
78     DWORD dpi = 0;
79     HKEY hkey;
80
81     if (RegOpenKeyW(HKEY_CURRENT_CONFIG, dpi_key_name, &hkey) == ERROR_SUCCESS)
82     {
83         DWORD type, size, new_dpi;
84
85         size = sizeof(new_dpi);
86         if (RegQueryValueExW(hkey, dpi_value_name, NULL, &type, (void *)&new_dpi, &size) == ERROR_SUCCESS)
87         {
88             if (type == REG_DWORD && new_dpi != 0)
89                 dpi = new_dpi;
90         }
91         RegCloseKey(hkey);
92     }
93     return dpi;
94 }
95
96
97 /***********************************************************************
98  *              macdrv_get_desktop_rect
99  *
100  * Returns the rectangle encompassing all the screens.
101  */
102 CGRect macdrv_get_desktop_rect(void)
103 {
104     CGRect ret;
105     CGDirectDisplayID displayIDs[32];
106     uint32_t count, i;
107
108     EnterCriticalSection(&device_data_section);
109
110     if (!device_data_valid)
111     {
112         desktop_rect = CGRectNull;
113         if (CGGetActiveDisplayList(sizeof(displayIDs)/sizeof(displayIDs[0]),
114                                    displayIDs, &count) != kCGErrorSuccess ||
115             !count)
116         {
117             displayIDs[0] = CGMainDisplayID();
118             count = 1;
119         }
120
121         for (i = 0; i < count; i++)
122             desktop_rect = CGRectUnion(desktop_rect, CGDisplayBounds(displayIDs[i]));
123     }
124
125     ret = desktop_rect;
126     LeaveCriticalSection(&device_data_section);
127
128     TRACE("%s\n", wine_dbgstr_cgrect(ret));
129
130     return ret;
131 }
132
133
134 /**********************************************************************
135  *              device_init
136  *
137  * Perform initializations needed upon creation of the first device.
138  */
139 static void device_init(void)
140 {
141     CGDirectDisplayID mainDisplay = CGMainDisplayID();
142     CGSize size_mm = CGDisplayScreenSize(mainDisplay);
143     CGDisplayModeRef mode = CGDisplayCopyDisplayMode(mainDisplay);
144     CGDirectPaletteRef palette;
145
146     /* Initialize device caps */
147     log_pixels_x = log_pixels_y = get_dpi();
148     if (!log_pixels_x)
149     {
150         size_t width = CGDisplayPixelsWide(mainDisplay);
151         size_t height = CGDisplayPixelsHigh(mainDisplay);
152         log_pixels_x = MulDiv(width, 254, size_mm.width * 10);
153         log_pixels_y = MulDiv(height, 254, size_mm.height * 10);
154     }
155
156     horz_size = size_mm.width;
157     vert_size = size_mm.height;
158
159     bits_per_pixel = 32;
160     if (mode)
161     {
162         CFStringRef pixelEncoding = CGDisplayModeCopyPixelEncoding(mode);
163
164         horz_res = CGDisplayModeGetWidth(mode);
165         vert_res = CGDisplayModeGetHeight(mode);
166
167         if (pixelEncoding)
168         {
169             if (CFEqual(pixelEncoding, CFSTR(IO32BitDirectPixels)))
170                 bits_per_pixel = 32;
171             else if (CFEqual(pixelEncoding, CFSTR(IO16BitDirectPixels)))
172                 bits_per_pixel = 16;
173             else if (CFEqual(pixelEncoding, CFSTR(IO8BitIndexedPixels)))
174                 bits_per_pixel = 8;
175             CFRelease(pixelEncoding);
176         }
177
178         CGDisplayModeRelease(mode);
179     }
180     else
181     {
182         horz_res = CGDisplayPixelsWide(mainDisplay);
183         vert_res = CGDisplayPixelsHigh(mainDisplay);
184     }
185
186     macdrv_get_desktop_rect();
187     desktop_horz_res = desktop_rect.size.width;
188     desktop_vert_res = desktop_rect.size.height;
189
190     palette = CGPaletteCreateWithDisplay(mainDisplay);
191     if (palette)
192     {
193         palette_size = CGPaletteGetNumberOfSamples(palette);
194         CGPaletteRelease(palette);
195     }
196     else
197         palette_size = 0;
198
199     device_data_valid = TRUE;
200 }
201
202
203 void macdrv_reset_device_metrics(void)
204 {
205     EnterCriticalSection(&device_data_section);
206     device_data_valid = FALSE;
207     LeaveCriticalSection(&device_data_section);
208 }
209
210
211 static MACDRV_PDEVICE *create_mac_physdev(void)
212 {
213     MACDRV_PDEVICE *physDev;
214
215     EnterCriticalSection(&device_data_section);
216     if (!device_data_valid) device_init();
217     LeaveCriticalSection(&device_data_section);
218
219     if (!(physDev = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*physDev)))) return NULL;
220
221     return physDev;
222 }
223
224
225 /**********************************************************************
226  *              CreateDC (MACDRV.@)
227  */
228 static BOOL macdrv_CreateDC(PHYSDEV *pdev, LPCWSTR driver, LPCWSTR device,
229                             LPCWSTR output, const DEVMODEW* initData)
230 {
231     MACDRV_PDEVICE *physDev = create_mac_physdev();
232
233     TRACE("pdev %p hdc %p driver %s device %s output %s initData %p\n", pdev,
234           (*pdev)->hdc, debugstr_w(driver),debugstr_w(device), debugstr_w(output),
235           initData);
236
237     if (!physDev) return FALSE;
238
239     push_dc_driver(pdev, &physDev->dev, &macdrv_funcs);
240     return TRUE;
241 }
242
243
244 /**********************************************************************
245  *              CreateCompatibleDC (MACDRV.@)
246  */
247 static BOOL macdrv_CreateCompatibleDC(PHYSDEV orig, PHYSDEV *pdev)
248 {
249     MACDRV_PDEVICE *physDev = create_mac_physdev();
250
251     TRACE("orig %p orig->hdc %p pdev %p pdev->hdc %p\n", orig, (orig ? orig->hdc : NULL), pdev,
252           ((pdev && *pdev) ? (*pdev)->hdc : NULL));
253
254     if (!physDev) return FALSE;
255
256     push_dc_driver(pdev, &physDev->dev, &macdrv_funcs);
257     return TRUE;
258 }
259
260
261 /**********************************************************************
262  *              DeleteDC (MACDRV.@)
263  */
264 static BOOL macdrv_DeleteDC(PHYSDEV dev)
265 {
266     MACDRV_PDEVICE *physDev = get_macdrv_dev(dev);
267
268     TRACE("hdc %p\n", dev->hdc);
269
270     HeapFree(GetProcessHeap(), 0, physDev);
271     return TRUE;
272 }
273
274
275 /***********************************************************************
276  *              GetDeviceCaps (MACDRV.@)
277  */
278 static INT macdrv_GetDeviceCaps(PHYSDEV dev, INT cap)
279 {
280     INT ret;
281
282     EnterCriticalSection(&device_data_section);
283
284     if (!device_data_valid) device_init();
285
286     switch(cap)
287     {
288     case DRIVERVERSION:
289         ret = 0x300;
290         break;
291     case TECHNOLOGY:
292         ret = DT_RASDISPLAY;
293         break;
294     case HORZSIZE:
295         ret = horz_size;
296         break;
297     case VERTSIZE:
298         ret = vert_size;
299         break;
300     case HORZRES:
301         ret = horz_res;
302         break;
303     case VERTRES:
304         ret = vert_res;
305         break;
306     case DESKTOPHORZRES:
307         ret = desktop_horz_res;
308         break;
309     case DESKTOPVERTRES:
310         ret = desktop_vert_res;
311         break;
312     case BITSPIXEL:
313         ret = bits_per_pixel;
314         break;
315     case PLANES:
316         ret = 1;
317         break;
318     case NUMBRUSHES:
319         ret = -1;
320         break;
321     case NUMPENS:
322         ret = -1;
323         break;
324     case NUMMARKERS:
325         ret = 0;
326         break;
327     case NUMFONTS:
328         ret = 0;
329         break;
330     case NUMCOLORS:
331         /* MSDN: Number of entries in the device's color table, if the device has
332          * a color depth of no more than 8 bits per pixel.For devices with greater
333          * color depths, -1 is returned. */
334         ret = (bits_per_pixel > 8) ? -1 : (1 << bits_per_pixel);
335         break;
336     case PDEVICESIZE:
337         ret = sizeof(MACDRV_PDEVICE);
338         break;
339     case CURVECAPS:
340         ret = (CC_CIRCLES | CC_PIE | CC_CHORD | CC_ELLIPSES | CC_WIDE |
341                CC_STYLED | CC_WIDESTYLED | CC_INTERIORS | CC_ROUNDRECT);
342         break;
343     case LINECAPS:
344         ret = (LC_POLYLINE | LC_MARKER | LC_POLYMARKER | LC_WIDE |
345                LC_STYLED | LC_WIDESTYLED | LC_INTERIORS);
346         break;
347     case POLYGONALCAPS:
348         ret = (PC_POLYGON | PC_RECTANGLE | PC_WINDPOLYGON | PC_SCANLINE |
349                PC_WIDE | PC_STYLED | PC_WIDESTYLED | PC_INTERIORS);
350         break;
351     case TEXTCAPS:
352         ret = (TC_OP_CHARACTER | TC_OP_STROKE | TC_CP_STROKE |
353                TC_CR_ANY | TC_SF_X_YINDEP | TC_SA_DOUBLE | TC_SA_INTEGER |
354                TC_SA_CONTIN | TC_UA_ABLE | TC_SO_ABLE | TC_RA_ABLE | TC_VA_ABLE);
355         break;
356     case CLIPCAPS:
357         ret = CP_REGION;
358         break;
359     case COLORRES:
360         /* The observed correspondence between BITSPIXEL and COLORRES is:
361          * BITSPIXEL: 8  -> COLORRES: 18
362          * BITSPIXEL: 16 -> COLORRES: 16
363          * BITSPIXEL: 24 -> COLORRES: 24
364          * (note that bits_per_pixel is never 24)
365          * BITSPIXEL: 32 -> COLORRES: 24 */
366         ret = (bits_per_pixel <= 8) ? 18 : (bits_per_pixel == 32) ? 24 : bits_per_pixel;
367         break;
368     case RASTERCAPS:
369         ret = (RC_BITBLT | RC_BANDING | RC_SCALING | RC_BITMAP64 | RC_DI_BITMAP |
370                RC_DIBTODEV | RC_BIGFONT | RC_STRETCHBLT | RC_STRETCHDIB | RC_DEVBITS |
371                (palette_size ? RC_PALETTE : 0));
372         break;
373     case SHADEBLENDCAPS:
374         ret = (SB_GRAD_RECT | SB_GRAD_TRI | SB_CONST_ALPHA | SB_PIXEL_ALPHA);
375         break;
376     case ASPECTX:
377     case ASPECTY:
378         ret = 36;
379         break;
380     case ASPECTXY:
381         ret = 51;
382         break;
383     case LOGPIXELSX:
384         ret = log_pixels_x;
385         break;
386     case LOGPIXELSY:
387         ret = log_pixels_y;
388         break;
389     case CAPS1:
390         FIXME("(%p): CAPS1 is unimplemented, will return 0\n", dev->hdc);
391         /* please see wingdi.h for the possible bit-flag values that need
392            to be returned. */
393         ret = 0;
394         break;
395     case SIZEPALETTE:
396         ret = palette_size;
397         break;
398     case NUMRESERVED:
399     case PHYSICALWIDTH:
400     case PHYSICALHEIGHT:
401     case PHYSICALOFFSETX:
402     case PHYSICALOFFSETY:
403     case SCALINGFACTORX:
404     case SCALINGFACTORY:
405     case VREFRESH:
406     case BLTALIGNMENT:
407         ret = 0;
408         break;
409     default:
410         FIXME("(%p): unsupported capability %d, will return 0\n", dev->hdc, cap);
411         ret = 0;
412         goto done;
413     }
414
415     TRACE("cap %d -> %d\n", cap, ret);
416
417 done:
418     LeaveCriticalSection(&device_data_section);
419     return ret;
420 }
421
422
423 static const struct gdi_dc_funcs macdrv_funcs =
424 {
425     NULL,                                   /* pAbortDoc */
426     NULL,                                   /* pAbortPath */
427     NULL,                                   /* pAlphaBlend */
428     NULL,                                   /* pAngleArc */
429     NULL,                                   /* pArc */
430     NULL,                                   /* pArcTo */
431     NULL,                                   /* pBeginPath */
432     NULL,                                   /* pBlendImage */
433     NULL,                                   /* pChord */
434     NULL,                                   /* pCloseFigure */
435     macdrv_CreateCompatibleDC,              /* pCreateCompatibleDC */
436     macdrv_CreateDC,                        /* pCreateDC */
437     macdrv_DeleteDC,                        /* pDeleteDC */
438     NULL,                                   /* pDeleteObject */
439     NULL,                                   /* pDeviceCapabilities */
440     NULL,                                   /* pEllipse */
441     NULL,                                   /* pEndDoc */
442     NULL,                                   /* pEndPage */
443     NULL,                                   /* pEndPath */
444     NULL,                                   /* pEnumFonts */
445     NULL,                                   /* pEnumICMProfiles */
446     NULL,                                   /* pExcludeClipRect */
447     NULL,                                   /* pExtDeviceMode */
448     NULL,                                   /* pExtEscape */
449     NULL,                                   /* pExtFloodFill */
450     NULL,                                   /* pExtSelectClipRgn */
451     NULL,                                   /* pExtTextOut */
452     NULL,                                   /* pFillPath */
453     NULL,                                   /* pFillRgn */
454     NULL,                                   /* pFlattenPath */
455     NULL,                                   /* pFontIsLinked */
456     NULL,                                   /* pFrameRgn */
457     NULL,                                   /* pGdiComment */
458     NULL,                                   /* pGdiRealizationInfo */
459     NULL,                                   /* pGetBoundsRect */
460     NULL,                                   /* pGetCharABCWidths */
461     NULL,                                   /* pGetCharABCWidthsI */
462     NULL,                                   /* pGetCharWidth */
463     macdrv_GetDeviceCaps,                   /* pGetDeviceCaps */
464     NULL,                                   /* pGetDeviceGammaRamp */
465     NULL,                                   /* pGetFontData */
466     NULL,                                   /* pGetFontUnicodeRanges */
467     NULL,                                   /* pGetGlyphIndices */
468     NULL,                                   /* pGetGlyphOutline */
469     NULL,                                   /* pGetICMProfile */
470     NULL,                                   /* pGetImage */
471     NULL,                                   /* pGetKerningPairs */
472     NULL,                                   /* pGetNearestColor */
473     NULL,                                   /* pGetOutlineTextMetrics */
474     NULL,                                   /* pGetPixel */
475     NULL,                                   /* pGetSystemPaletteEntries */
476     NULL,                                   /* pGetTextCharsetInfo */
477     NULL,                                   /* pGetTextExtentExPoint */
478     NULL,                                   /* pGetTextExtentExPointI */
479     NULL,                                   /* pGetTextFace */
480     NULL,                                   /* pGetTextMetrics */
481     NULL,                                   /* pGradientFill */
482     NULL,                                   /* pIntersectClipRect */
483     NULL,                                   /* pInvertRgn */
484     NULL,                                   /* pLineTo */
485     NULL,                                   /* pModifyWorldTransform */
486     NULL,                                   /* pMoveTo */
487     NULL,                                   /* pOffsetClipRgn */
488     NULL,                                   /* pOffsetViewportOrg */
489     NULL,                                   /* pOffsetWindowOrg */
490     NULL,                                   /* pPaintRgn */
491     NULL,                                   /* pPatBlt */
492     NULL,                                   /* pPie */
493     NULL,                                   /* pPolyBezier */
494     NULL,                                   /* pPolyBezierTo */
495     NULL,                                   /* pPolyDraw */
496     NULL,                                   /* pPolyPolygon */
497     NULL,                                   /* pPolyPolyline */
498     NULL,                                   /* pPolygon */
499     NULL,                                   /* pPolyline */
500     NULL,                                   /* pPolylineTo */
501     NULL,                                   /* pPutImage */
502     NULL,                                   /* pRealizeDefaultPalette */
503     NULL,                                   /* pRealizePalette */
504     NULL,                                   /* pRectangle */
505     NULL,                                   /* pResetDC */
506     NULL,                                   /* pRestoreDC */
507     NULL,                                   /* pRoundRect */
508     NULL,                                   /* pSaveDC */
509     NULL,                                   /* pScaleViewportExt */
510     NULL,                                   /* pScaleWindowExt */
511     NULL,                                   /* pSelectBitmap */
512     NULL,                                   /* pSelectBrush */
513     NULL,                                   /* pSelectClipPath */
514     NULL,                                   /* pSelectFont */
515     NULL,                                   /* pSelectPalette */
516     NULL,                                   /* pSelectPen */
517     NULL,                                   /* pSetArcDirection */
518     NULL,                                   /* pSetBkColor */
519     NULL,                                   /* pSetBkMode */
520     NULL,                                   /* pSetBoundsRect */
521     NULL,                                   /* pSetDCBrushColor */
522     NULL,                                   /* pSetDCPenColor */
523     NULL,                                   /* pSetDIBitsToDevice */
524     NULL,                                   /* pSetDeviceClipping */
525     NULL,                                   /* pSetDeviceGammaRamp */
526     NULL,                                   /* pSetLayout */
527     NULL,                                   /* pSetMapMode */
528     NULL,                                   /* pSetMapperFlags */
529     NULL,                                   /* pSetPixel */
530     NULL,                                   /* pSetPolyFillMode */
531     NULL,                                   /* pSetROP2 */
532     NULL,                                   /* pSetRelAbs */
533     NULL,                                   /* pSetStretchBltMode */
534     NULL,                                   /* pSetTextAlign */
535     NULL,                                   /* pSetTextCharacterExtra */
536     NULL,                                   /* pSetTextColor */
537     NULL,                                   /* pSetTextJustification */
538     NULL,                                   /* pSetViewportExt */
539     NULL,                                   /* pSetViewportOrg */
540     NULL,                                   /* pSetWindowExt */
541     NULL,                                   /* pSetWindowOrg */
542     NULL,                                   /* pSetWorldTransform */
543     NULL,                                   /* pStartDoc */
544     NULL,                                   /* pStartPage */
545     NULL,                                   /* pStretchBlt */
546     NULL,                                   /* pStretchDIBits */
547     NULL,                                   /* pStrokeAndFillPath */
548     NULL,                                   /* pStrokePath */
549     NULL,                                   /* pUnrealizePalette */
550     NULL,                                   /* pWidenPath */
551     macdrv_wine_get_wgl_driver,             /* wine_get_wgl_driver */
552     GDI_PRIORITY_GRAPHICS_DRV               /* priority */
553 };
554
555
556 /******************************************************************************
557  *              macdrv_get_gdi_driver
558  */
559 const struct gdi_dc_funcs * CDECL macdrv_get_gdi_driver(unsigned int version)
560 {
561     if (version != WINE_GDI_DRIVER_VERSION)
562     {
563         ERR("version mismatch, gdi32 wants %u but winemac has %u\n", version, WINE_GDI_DRIVER_VERSION);
564         return NULL;
565     }
566     return &macdrv_funcs;
567 }