| /* |
| * Mac graphics driver initialisation functions |
| * |
| * Copyright 1996 Alexandre Julliard |
| * Copyright 2011, 2012, 2013 Ken Thomases for CodeWeavers, Inc. |
| * |
| * This library is free software; you can redistribute it and/or |
| * modify it under the terms of the GNU Lesser General Public |
| * License as published by the Free Software Foundation; either |
| * version 2.1 of the License, or (at your option) any later version. |
| * |
| * This library is distributed in the hope that it will be useful, |
| * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| * Lesser General Public License for more details. |
| * |
| * You should have received a copy of the GNU Lesser General Public |
| * License along with this library; if not, write to the Free Software |
| * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA |
| */ |
| |
| #include "config.h" |
| |
| #include "macdrv.h" |
| #include "winreg.h" |
| |
| WINE_DEFAULT_DEBUG_CHANNEL(macdrv); |
| |
| |
| typedef struct |
| { |
| struct gdi_physdev dev; |
| } MACDRV_PDEVICE; |
| |
| static inline MACDRV_PDEVICE *get_macdrv_dev(PHYSDEV dev) |
| { |
| return (MACDRV_PDEVICE*)dev; |
| } |
| |
| |
| /* a few dynamic device caps */ |
| static CGRect desktop_rect; /* virtual desktop rectangle */ |
| static int horz_size; /* horz. size of screen in millimeters */ |
| static int vert_size; /* vert. size of screen in millimeters */ |
| static int horz_res; /* width in pixels of screen */ |
| static int vert_res; /* height in pixels of screen */ |
| static int desktop_horz_res; /* width in pixels of virtual desktop */ |
| static int desktop_vert_res; /* height in pixels of virtual desktop */ |
| static int bits_per_pixel; /* pixel depth of screen */ |
| static int device_data_valid; /* do the above variables have up-to-date values? */ |
| |
| int retina_on = FALSE; |
| |
| static CRITICAL_SECTION device_data_section; |
| static CRITICAL_SECTION_DEBUG critsect_debug = |
| { |
| 0, 0, &device_data_section, |
| { &critsect_debug.ProcessLocksList, &critsect_debug.ProcessLocksList }, |
| 0, 0, { (DWORD_PTR)(__FILE__ ": device_data_section") } |
| }; |
| static CRITICAL_SECTION device_data_section = { &critsect_debug, -1, 0, 0, 0, 0 }; |
| |
| |
| static const struct gdi_dc_funcs macdrv_funcs; |
| |
| /*********************************************************************** |
| * compute_desktop_rect |
| */ |
| static void compute_desktop_rect(void) |
| { |
| CGDirectDisplayID displayIDs[32]; |
| uint32_t count, i; |
| |
| desktop_rect = CGRectNull; |
| if (CGGetActiveDisplayList(sizeof(displayIDs)/sizeof(displayIDs[0]), |
| displayIDs, &count) != kCGErrorSuccess || |
| !count) |
| { |
| displayIDs[0] = CGMainDisplayID(); |
| count = 1; |
| } |
| |
| for (i = 0; i < count; i++) |
| desktop_rect = CGRectUnion(desktop_rect, CGDisplayBounds(displayIDs[i])); |
| desktop_rect = cgrect_win_from_mac(desktop_rect); |
| } |
| |
| |
| /*********************************************************************** |
| * macdrv_get_desktop_rect |
| * |
| * Returns the rectangle encompassing all the screens. |
| */ |
| CGRect macdrv_get_desktop_rect(void) |
| { |
| CGRect ret; |
| |
| EnterCriticalSection(&device_data_section); |
| |
| if (!device_data_valid) |
| { |
| check_retina_status(); |
| compute_desktop_rect(); |
| } |
| ret = desktop_rect; |
| |
| LeaveCriticalSection(&device_data_section); |
| |
| TRACE("%s\n", wine_dbgstr_cgrect(ret)); |
| |
| return ret; |
| } |
| |
| |
| /********************************************************************** |
| * device_init |
| * |
| * Perform initializations needed upon creation of the first device. |
| */ |
| static void device_init(void) |
| { |
| CGDirectDisplayID mainDisplay = CGMainDisplayID(); |
| CGSize size_mm = CGDisplayScreenSize(mainDisplay); |
| CGDisplayModeRef mode = CGDisplayCopyDisplayMode(mainDisplay); |
| |
| check_retina_status(); |
| |
| /* Initialize device caps */ |
| horz_size = size_mm.width; |
| vert_size = size_mm.height; |
| |
| bits_per_pixel = 32; |
| if (mode) |
| { |
| CFStringRef pixelEncoding = CGDisplayModeCopyPixelEncoding(mode); |
| |
| horz_res = CGDisplayModeGetWidth(mode); |
| vert_res = CGDisplayModeGetHeight(mode); |
| |
| if (pixelEncoding) |
| { |
| if (CFEqual(pixelEncoding, CFSTR(IO32BitDirectPixels))) |
| bits_per_pixel = 32; |
| else if (CFEqual(pixelEncoding, CFSTR(IO16BitDirectPixels))) |
| bits_per_pixel = 16; |
| else if (CFEqual(pixelEncoding, CFSTR(IO8BitIndexedPixels))) |
| bits_per_pixel = 8; |
| CFRelease(pixelEncoding); |
| } |
| |
| CGDisplayModeRelease(mode); |
| } |
| else |
| { |
| horz_res = CGDisplayPixelsWide(mainDisplay); |
| vert_res = CGDisplayPixelsHigh(mainDisplay); |
| } |
| |
| if (retina_on) |
| { |
| horz_res *= 2; |
| vert_res *= 2; |
| } |
| |
| compute_desktop_rect(); |
| desktop_horz_res = desktop_rect.size.width; |
| desktop_vert_res = desktop_rect.size.height; |
| |
| device_data_valid = TRUE; |
| } |
| |
| |
| void macdrv_reset_device_metrics(void) |
| { |
| EnterCriticalSection(&device_data_section); |
| device_data_valid = FALSE; |
| LeaveCriticalSection(&device_data_section); |
| } |
| |
| |
| static MACDRV_PDEVICE *create_mac_physdev(void) |
| { |
| MACDRV_PDEVICE *physDev; |
| |
| EnterCriticalSection(&device_data_section); |
| if (!device_data_valid) device_init(); |
| LeaveCriticalSection(&device_data_section); |
| |
| if (!(physDev = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*physDev)))) return NULL; |
| |
| return physDev; |
| } |
| |
| |
| /********************************************************************** |
| * CreateDC (MACDRV.@) |
| */ |
| static BOOL macdrv_CreateDC(PHYSDEV *pdev, LPCWSTR driver, LPCWSTR device, |
| LPCWSTR output, const DEVMODEW* initData) |
| { |
| MACDRV_PDEVICE *physDev = create_mac_physdev(); |
| |
| TRACE("pdev %p hdc %p driver %s device %s output %s initData %p\n", pdev, |
| (*pdev)->hdc, debugstr_w(driver),debugstr_w(device), debugstr_w(output), |
| initData); |
| |
| if (!physDev) return FALSE; |
| |
| push_dc_driver(pdev, &physDev->dev, &macdrv_funcs); |
| return TRUE; |
| } |
| |
| |
| /********************************************************************** |
| * CreateCompatibleDC (MACDRV.@) |
| */ |
| static BOOL macdrv_CreateCompatibleDC(PHYSDEV orig, PHYSDEV *pdev) |
| { |
| MACDRV_PDEVICE *physDev = create_mac_physdev(); |
| |
| TRACE("orig %p orig->hdc %p pdev %p pdev->hdc %p\n", orig, (orig ? orig->hdc : NULL), pdev, |
| ((pdev && *pdev) ? (*pdev)->hdc : NULL)); |
| |
| if (!physDev) return FALSE; |
| |
| push_dc_driver(pdev, &physDev->dev, &macdrv_funcs); |
| return TRUE; |
| } |
| |
| |
| /********************************************************************** |
| * DeleteDC (MACDRV.@) |
| */ |
| static BOOL macdrv_DeleteDC(PHYSDEV dev) |
| { |
| MACDRV_PDEVICE *physDev = get_macdrv_dev(dev); |
| |
| TRACE("hdc %p\n", dev->hdc); |
| |
| HeapFree(GetProcessHeap(), 0, physDev); |
| return TRUE; |
| } |
| |
| |
| /*********************************************************************** |
| * GetDeviceCaps (MACDRV.@) |
| */ |
| static INT macdrv_GetDeviceCaps(PHYSDEV dev, INT cap) |
| { |
| INT ret; |
| |
| EnterCriticalSection(&device_data_section); |
| |
| if (!device_data_valid) device_init(); |
| |
| switch(cap) |
| { |
| case HORZSIZE: |
| ret = horz_size; |
| break; |
| case VERTSIZE: |
| ret = vert_size; |
| break; |
| case HORZRES: |
| ret = horz_res; |
| break; |
| case VERTRES: |
| ret = vert_res; |
| break; |
| case DESKTOPHORZRES: |
| ret = desktop_horz_res; |
| break; |
| case DESKTOPVERTRES: |
| ret = desktop_vert_res; |
| break; |
| case BITSPIXEL: |
| ret = bits_per_pixel; |
| break; |
| default: |
| LeaveCriticalSection(&device_data_section); |
| dev = GET_NEXT_PHYSDEV( dev, pGetDeviceCaps ); |
| return dev->funcs->pGetDeviceCaps( dev, cap ); |
| } |
| |
| TRACE("cap %d -> %d\n", cap, ret); |
| |
| LeaveCriticalSection(&device_data_section); |
| return ret; |
| } |
| |
| |
| static const struct gdi_dc_funcs macdrv_funcs = |
| { |
| NULL, /* pAbortDoc */ |
| NULL, /* pAbortPath */ |
| NULL, /* pAlphaBlend */ |
| NULL, /* pAngleArc */ |
| NULL, /* pArc */ |
| NULL, /* pArcTo */ |
| NULL, /* pBeginPath */ |
| NULL, /* pBlendImage */ |
| NULL, /* pChord */ |
| NULL, /* pCloseFigure */ |
| macdrv_CreateCompatibleDC, /* pCreateCompatibleDC */ |
| macdrv_CreateDC, /* pCreateDC */ |
| macdrv_DeleteDC, /* pDeleteDC */ |
| NULL, /* pDeleteObject */ |
| NULL, /* pDeviceCapabilities */ |
| NULL, /* pEllipse */ |
| NULL, /* pEndDoc */ |
| NULL, /* pEndPage */ |
| NULL, /* pEndPath */ |
| NULL, /* pEnumFonts */ |
| NULL, /* pEnumICMProfiles */ |
| NULL, /* pExcludeClipRect */ |
| NULL, /* pExtDeviceMode */ |
| NULL, /* pExtEscape */ |
| NULL, /* pExtFloodFill */ |
| NULL, /* pExtSelectClipRgn */ |
| NULL, /* pExtTextOut */ |
| NULL, /* pFillPath */ |
| NULL, /* pFillRgn */ |
| NULL, /* pFlattenPath */ |
| NULL, /* pFontIsLinked */ |
| NULL, /* pFrameRgn */ |
| NULL, /* pGdiComment */ |
| NULL, /* pGetBoundsRect */ |
| NULL, /* pGetCharABCWidths */ |
| NULL, /* pGetCharABCWidthsI */ |
| NULL, /* pGetCharWidth */ |
| macdrv_GetDeviceCaps, /* pGetDeviceCaps */ |
| macdrv_GetDeviceGammaRamp, /* pGetDeviceGammaRamp */ |
| NULL, /* pGetFontData */ |
| NULL, /* pGetFontRealizationInfo */ |
| NULL, /* pGetFontUnicodeRanges */ |
| NULL, /* pGetGlyphIndices */ |
| NULL, /* pGetGlyphOutline */ |
| NULL, /* pGetICMProfile */ |
| NULL, /* pGetImage */ |
| NULL, /* pGetKerningPairs */ |
| NULL, /* pGetNearestColor */ |
| NULL, /* pGetOutlineTextMetrics */ |
| NULL, /* pGetPixel */ |
| NULL, /* pGetSystemPaletteEntries */ |
| NULL, /* pGetTextCharsetInfo */ |
| NULL, /* pGetTextExtentExPoint */ |
| NULL, /* pGetTextExtentExPointI */ |
| NULL, /* pGetTextFace */ |
| NULL, /* pGetTextMetrics */ |
| NULL, /* pGradientFill */ |
| NULL, /* pIntersectClipRect */ |
| NULL, /* pInvertRgn */ |
| NULL, /* pLineTo */ |
| NULL, /* pModifyWorldTransform */ |
| NULL, /* pMoveTo */ |
| NULL, /* pOffsetClipRgn */ |
| NULL, /* pOffsetViewportOrg */ |
| NULL, /* pOffsetWindowOrg */ |
| NULL, /* pPaintRgn */ |
| NULL, /* pPatBlt */ |
| NULL, /* pPie */ |
| NULL, /* pPolyBezier */ |
| NULL, /* pPolyBezierTo */ |
| NULL, /* pPolyDraw */ |
| NULL, /* pPolyPolygon */ |
| NULL, /* pPolyPolyline */ |
| NULL, /* pPolygon */ |
| NULL, /* pPolyline */ |
| NULL, /* pPolylineTo */ |
| NULL, /* pPutImage */ |
| NULL, /* pRealizeDefaultPalette */ |
| NULL, /* pRealizePalette */ |
| NULL, /* pRectangle */ |
| NULL, /* pResetDC */ |
| NULL, /* pRestoreDC */ |
| NULL, /* pRoundRect */ |
| NULL, /* pSaveDC */ |
| NULL, /* pScaleViewportExt */ |
| NULL, /* pScaleWindowExt */ |
| NULL, /* pSelectBitmap */ |
| NULL, /* pSelectBrush */ |
| NULL, /* pSelectClipPath */ |
| NULL, /* pSelectFont */ |
| NULL, /* pSelectPalette */ |
| NULL, /* pSelectPen */ |
| NULL, /* pSetArcDirection */ |
| NULL, /* pSetBkColor */ |
| NULL, /* pSetBkMode */ |
| NULL, /* pSetBoundsRect */ |
| NULL, /* pSetDCBrushColor */ |
| NULL, /* pSetDCPenColor */ |
| NULL, /* pSetDIBitsToDevice */ |
| NULL, /* pSetDeviceClipping */ |
| macdrv_SetDeviceGammaRamp, /* pSetDeviceGammaRamp */ |
| NULL, /* pSetLayout */ |
| NULL, /* pSetMapMode */ |
| NULL, /* pSetMapperFlags */ |
| NULL, /* pSetPixel */ |
| NULL, /* pSetPolyFillMode */ |
| NULL, /* pSetROP2 */ |
| NULL, /* pSetRelAbs */ |
| NULL, /* pSetStretchBltMode */ |
| NULL, /* pSetTextAlign */ |
| NULL, /* pSetTextCharacterExtra */ |
| NULL, /* pSetTextColor */ |
| NULL, /* pSetTextJustification */ |
| NULL, /* pSetViewportExt */ |
| NULL, /* pSetViewportOrg */ |
| NULL, /* pSetWindowExt */ |
| NULL, /* pSetWindowOrg */ |
| NULL, /* pSetWorldTransform */ |
| NULL, /* pStartDoc */ |
| NULL, /* pStartPage */ |
| NULL, /* pStretchBlt */ |
| NULL, /* pStretchDIBits */ |
| NULL, /* pStrokeAndFillPath */ |
| NULL, /* pStrokePath */ |
| NULL, /* pUnrealizePalette */ |
| NULL, /* pWidenPath */ |
| macdrv_wine_get_wgl_driver, /* wine_get_wgl_driver */ |
| GDI_PRIORITY_GRAPHICS_DRV /* priority */ |
| }; |
| |
| |
| /****************************************************************************** |
| * macdrv_get_gdi_driver |
| */ |
| const struct gdi_dc_funcs * CDECL macdrv_get_gdi_driver(unsigned int version) |
| { |
| if (version != WINE_GDI_DRIVER_VERSION) |
| { |
| ERR("version mismatch, gdi32 wants %u but winemac has %u\n", version, WINE_GDI_DRIVER_VERSION); |
| return NULL; |
| } |
| return &macdrv_funcs; |
| } |