/* * Graphics driver management functions * * Copyright 1996 Alexandre Julliard * * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "config.h" #include "wine/port.h" #include #include "winbase.h" #include "winreg.h" #include "gdi.h" #include "wine/debug.h" WINE_DEFAULT_DEBUG_CHANNEL(driver); struct graphics_driver { struct graphics_driver *next; struct graphics_driver *prev; HMODULE module; /* module handle */ unsigned int count; /* reference count */ DC_FUNCTIONS funcs; }; static struct graphics_driver *first_driver; static struct graphics_driver *display_driver; static CRITICAL_SECTION driver_section = CRITICAL_SECTION_INIT( "driver_section" ); /********************************************************************** * create_driver * * Allocate and fill the driver structure for a given module. */ static struct graphics_driver *create_driver( HMODULE module ) { struct graphics_driver *driver; if (!(driver = HeapAlloc( GetProcessHeap(), 0, sizeof(*driver)))) return NULL; driver->next = NULL; driver->prev = NULL; driver->module = module; driver->count = 1; /* fill the function table */ #define GET_FUNC(name) driver->funcs.p##name = (void*)GetProcAddress( module, #name ) GET_FUNC(AbortDoc); GET_FUNC(AbortPath); GET_FUNC(AngleArc); GET_FUNC(Arc); GET_FUNC(ArcTo); GET_FUNC(BeginPath); GET_FUNC(BitBlt); GET_FUNC(ChoosePixelFormat); GET_FUNC(Chord); GET_FUNC(CloseFigure); GET_FUNC(CreateBitmap); GET_FUNC(CreateDC); GET_FUNC(CreateDIBSection); GET_FUNC(DeleteBitmap); GET_FUNC(DeleteDC); GET_FUNC(DescribePixelFormat); GET_FUNC(DeviceCapabilities); GET_FUNC(Ellipse); GET_FUNC(EndDoc); GET_FUNC(EndPage); GET_FUNC(EndPath); GET_FUNC(EnumDeviceFonts); GET_FUNC(ExcludeClipRect); GET_FUNC(ExtDeviceMode); GET_FUNC(ExtEscape); GET_FUNC(ExtFloodFill); GET_FUNC(ExtSelectClipRgn); GET_FUNC(ExtTextOut); GET_FUNC(FillPath); GET_FUNC(FillRgn); GET_FUNC(FlattenPath); GET_FUNC(FrameRgn); GET_FUNC(GdiComment); GET_FUNC(GetBitmapBits); GET_FUNC(GetCharWidth); GET_FUNC(GetDCOrgEx); GET_FUNC(GetDIBColorTable); GET_FUNC(GetDIBits); GET_FUNC(GetDeviceCaps); GET_FUNC(GetDeviceGammaRamp); GET_FUNC(GetNearestColor); GET_FUNC(GetPixel); GET_FUNC(GetPixelFormat); GET_FUNC(GetSystemPaletteEntries); GET_FUNC(GetTextExtentPoint); GET_FUNC(GetTextMetrics); GET_FUNC(IntersectClipRect); GET_FUNC(InvertRgn); GET_FUNC(LineTo); GET_FUNC(MoveTo); GET_FUNC(OffsetClipRgn); GET_FUNC(OffsetViewportOrg); GET_FUNC(OffsetWindowOrg); GET_FUNC(PaintRgn); GET_FUNC(PatBlt); GET_FUNC(Pie); GET_FUNC(PolyBezier); GET_FUNC(PolyBezierTo); GET_FUNC(PolyDraw); GET_FUNC(PolyPolygon); GET_FUNC(PolyPolyline); GET_FUNC(Polygon); GET_FUNC(Polyline); GET_FUNC(PolylineTo); GET_FUNC(RealizeDefaultPalette); GET_FUNC(RealizePalette); GET_FUNC(Rectangle); GET_FUNC(ResetDC); GET_FUNC(RestoreDC); GET_FUNC(RoundRect); GET_FUNC(SaveDC); GET_FUNC(ScaleViewportExt); GET_FUNC(ScaleWindowExt); GET_FUNC(SelectBitmap); GET_FUNC(SelectBrush); GET_FUNC(SelectClipPath); GET_FUNC(SelectFont); GET_FUNC(SelectPalette); GET_FUNC(SelectPen); GET_FUNC(SetBitmapBits); GET_FUNC(SetBkColor); GET_FUNC(SetBkMode); GET_FUNC(SetDCOrg); GET_FUNC(SetDIBColorTable); GET_FUNC(SetDIBits); GET_FUNC(SetDIBitsToDevice); GET_FUNC(SetDeviceClipping); GET_FUNC(SetDeviceGammaRamp); GET_FUNC(SetMapMode); GET_FUNC(SetMapperFlags); GET_FUNC(SetPixel); GET_FUNC(SetPixelFormat); GET_FUNC(SetPolyFillMode); GET_FUNC(SetROP2); GET_FUNC(SetRelAbs); GET_FUNC(SetStretchBltMode); GET_FUNC(SetTextAlign); GET_FUNC(SetTextCharacterExtra); GET_FUNC(SetTextColor); GET_FUNC(SetTextJustification); GET_FUNC(SetViewportExt); GET_FUNC(SetViewportOrg); GET_FUNC(SetWindowExt); GET_FUNC(SetWindowOrg); GET_FUNC(StartDoc); GET_FUNC(StartPage); GET_FUNC(StretchBlt); GET_FUNC(StretchDIBits); GET_FUNC(StrokeAndFillPath); GET_FUNC(StrokePath); GET_FUNC(SwapBuffers); GET_FUNC(WidenPath); #undef GET_FUNC /* add it to the list */ driver->prev = NULL; if ((driver->next = first_driver)) driver->next->prev = driver; first_driver = driver; return driver; } /********************************************************************** * load_display_driver * * Special case for loading the display driver: get the name from the config file */ static struct graphics_driver *load_display_driver(void) { char buffer[MAX_PATH]; HMODULE module; HKEY hkey; if (display_driver) /* already loaded */ { display_driver->count++; return display_driver; } strcpy( buffer, "x11drv" ); /* default value */ if (!RegOpenKeyA( HKEY_LOCAL_MACHINE, "Software\\Wine\\Wine\\Config\\Wine", &hkey )) { DWORD type, count = sizeof(buffer); RegQueryValueExA( hkey, "GraphicsDriver", 0, &type, buffer, &count ); RegCloseKey( hkey ); } if (!(module = LoadLibraryA( buffer ))) { MESSAGE( "Could not load graphics driver '%s'\n", buffer ); return NULL; } if (!(display_driver = create_driver( module ))) { MESSAGE( "Could not create graphics driver '%s'\n", buffer ); FreeLibrary( module ); return NULL; } display_driver->count++; /* we don't want to free it */ return display_driver; } /********************************************************************** * DRIVER_load_driver */ const DC_FUNCTIONS *DRIVER_load_driver( LPCSTR name ) { HMODULE module; struct graphics_driver *driver; EnterCriticalSection( &driver_section ); /* display driver is a special case */ if (!strcasecmp( name, "display" )) { driver = load_display_driver(); LeaveCriticalSection( &driver_section ); return &driver->funcs; } if ((module = GetModuleHandleA( name ))) { for (driver = first_driver; driver; driver = driver->next) { if (driver->module == module) { driver->count++; LeaveCriticalSection( &driver_section ); return &driver->funcs; } } } if (!(module = LoadLibraryA( name ))) { LeaveCriticalSection( &driver_section ); return NULL; } if (!(driver = create_driver( module ))) { FreeLibrary( module ); LeaveCriticalSection( &driver_section ); return NULL; } TRACE( "loaded driver %p for %s\n", driver, name ); LeaveCriticalSection( &driver_section ); return &driver->funcs; } /********************************************************************** * DRIVER_get_driver * * Get a new copy of an existing driver. */ const DC_FUNCTIONS *DRIVER_get_driver( const DC_FUNCTIONS *funcs ) { struct graphics_driver *driver; EnterCriticalSection( &driver_section ); for (driver = first_driver; driver; driver = driver->next) if (&driver->funcs == funcs) break; if (!driver) ERR( "driver not found, trouble ahead\n" ); driver->count++; LeaveCriticalSection( &driver_section ); return funcs; } /********************************************************************** * DRIVER_release_driver * * Release a driver by decrementing ref count and freeing it if needed. */ void DRIVER_release_driver( const DC_FUNCTIONS *funcs ) { struct graphics_driver *driver; EnterCriticalSection( &driver_section ); for (driver = first_driver; driver; driver = driver->next) if (&driver->funcs == funcs) break; if (!driver) goto done; if (--driver->count) goto done; /* removed last reference, free it */ if (driver->next) driver->next->prev = driver->prev; if (driver->prev) driver->prev->next = driver->next; else first_driver = driver->next; if (driver == display_driver) display_driver = NULL; FreeLibrary( driver->module ); HeapFree( GetProcessHeap(), 0, driver ); done: LeaveCriticalSection( &driver_section ); } /***************************************************************************** * DRIVER_GetDriverName * */ BOOL DRIVER_GetDriverName( LPCSTR device, LPSTR driver, DWORD size ) { char *p; size = GetProfileStringA("devices", device, "", driver, size); if(!size) { WARN("Unable to find '%s' in [devices] section of win.ini\n", device); return FALSE; } p = strchr(driver, ','); if(!p) { WARN("'%s' entry in [devices] section of win.ini is malformed.\n", device); return FALSE; } *p = '\0'; TRACE("Found '%s' for '%s'\n", driver, device); return TRUE; } /***************************************************************************** * @ [GDI32.100] * * This should thunk to 16-bit and simply call the proc with the given args. */ INT WINAPI GDI_CallDevInstall16( FARPROC16 lpfnDevInstallProc, HWND hWnd, LPSTR lpModelName, LPSTR OldPort, LPSTR NewPort ) { FIXME("(%p, %p, %s, %s, %s)\n", lpfnDevInstallProc, hWnd, lpModelName, OldPort, NewPort ); return -1; } /***************************************************************************** * @ [GDI32.101] * * This should load the correct driver for lpszDevice and calls this driver's * ExtDeviceModePropSheet proc. * * Note: The driver calls a callback routine for each property sheet page; these * pages are supposed to be filled into the structure pointed to by lpPropSheet. * The layout of this structure is: * * struct * { * DWORD nPages; * DWORD unknown; * HPROPSHEETPAGE pages[10]; * }; */ INT WINAPI GDI_CallExtDeviceModePropSheet16( HWND hWnd, LPCSTR lpszDevice, LPCSTR lpszPort, LPVOID lpPropSheet ) { FIXME("(%p, %s, %s, %p)\n", hWnd, lpszDevice, lpszPort, lpPropSheet ); return -1; } /***************************************************************************** * @ [GDI32.102] * * This should load the correct driver for lpszDevice and calls this driver's * ExtDeviceMode proc. */ INT WINAPI GDI_CallExtDeviceMode16( HWND hwnd, LPDEVMODEA lpdmOutput, LPSTR lpszDevice, LPSTR lpszPort, LPDEVMODEA lpdmInput, LPSTR lpszProfile, DWORD fwMode ) { char buf[300]; HDC hdc; DC *dc; INT ret = -1; INT (*pExtDeviceMode)(LPSTR,HWND,LPDEVMODEA,LPSTR,LPSTR,LPDEVMODEA,LPSTR,DWORD); TRACE("(%p, %p, %s, %s, %p, %s, %ld)\n", hwnd, lpdmOutput, lpszDevice, lpszPort, lpdmInput, lpszProfile, fwMode ); if(!DRIVER_GetDriverName( lpszDevice, buf, sizeof(buf) )) return -1; if (!(hdc = CreateICA( buf, lpszDevice, lpszPort, NULL ))) return -1; if ((dc = DC_GetDCPtr( hdc ))) { pExtDeviceMode = dc->funcs->pExtDeviceMode; GDI_ReleaseObj( hdc ); if (pExtDeviceMode) ret = pExtDeviceMode(buf, hwnd, lpdmOutput, lpszDevice, lpszPort, lpdmInput, lpszProfile, fwMode); } DeleteDC( hdc ); return ret; } /**************************************************************************** * @ [GDI32.103] * * This should load the correct driver for lpszDevice and calls this driver's * AdvancedSetupDialog proc. */ INT WINAPI GDI_CallAdvancedSetupDialog16( HWND hwnd, LPSTR lpszDevice, LPDEVMODEA devin, LPDEVMODEA devout ) { TRACE("(%p, %s, %p, %p)\n", hwnd, lpszDevice, devin, devout ); return -1; } /***************************************************************************** * @ [GDI32.104] * * This should load the correct driver for lpszDevice and calls this driver's * DeviceCapabilities proc. */ DWORD WINAPI GDI_CallDeviceCapabilities16( LPCSTR lpszDevice, LPCSTR lpszPort, WORD fwCapability, LPSTR lpszOutput, LPDEVMODEA lpdm ) { char buf[300]; HDC hdc; DC *dc; INT ret = -1; TRACE("(%s, %s, %d, %p, %p)\n", lpszDevice, lpszPort, fwCapability, lpszOutput, lpdm ); if(!DRIVER_GetDriverName( lpszDevice, buf, sizeof(buf) )) return -1; if (!(hdc = CreateICA( buf, lpszDevice, lpszPort, NULL ))) return -1; if ((dc = DC_GetDCPtr( hdc ))) { if (dc->funcs->pDeviceCapabilities) ret = dc->funcs->pDeviceCapabilities( buf, lpszDevice, lpszPort, fwCapability, lpszOutput, lpdm ); GDI_ReleaseObj( hdc ); } DeleteDC( hdc ); return ret; }