2 * Graphics driver management functions
4 * Copyright 1996 Alexandre Julliard
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 #include "wine/port.h"
30 #include "win16drv/win16drv.h"
31 #include "wine/debug.h"
33 WINE_DEFAULT_DEBUG_CHANNEL(driver);
35 struct graphics_driver
37 struct graphics_driver *next;
38 struct graphics_driver *prev;
39 HMODULE module; /* module handle */
40 unsigned int count; /* reference count */
44 static struct graphics_driver *first_driver;
45 static struct graphics_driver *display_driver;
46 static const DC_FUNCTIONS *win16_driver;
47 static CRITICAL_SECTION driver_section = CRITICAL_SECTION_INIT( "driver_section" );
49 /**********************************************************************
52 * Allocate and fill the driver structure for a given module.
54 static struct graphics_driver *create_driver( HMODULE module )
56 struct graphics_driver *driver;
58 if (!(driver = HeapAlloc( GetProcessHeap(), 0, sizeof(*driver)))) return NULL;
61 driver->module = module;
64 /* fill the function table */
66 #define GET_FUNC(name) driver->funcs.p##name = (void*)GetProcAddress( module, #name )
75 GET_FUNC(ChoosePixelFormat);
77 GET_FUNC(CloseFigure);
78 GET_FUNC(CreateBitmap);
80 GET_FUNC(CreateDIBSection);
81 GET_FUNC(DeleteBitmap);
83 GET_FUNC(DescribePixelFormat);
84 GET_FUNC(DeviceCapabilities);
89 GET_FUNC(EnumDeviceFonts);
90 GET_FUNC(ExcludeClipRect);
91 GET_FUNC(ExtDeviceMode);
93 GET_FUNC(ExtFloodFill);
94 GET_FUNC(ExtSelectClipRgn);
98 GET_FUNC(FlattenPath);
100 GET_FUNC(GetBitmapBits);
101 GET_FUNC(GetCharWidth);
102 GET_FUNC(GetDCOrgEx);
103 GET_FUNC(GetDIBColorTable);
105 GET_FUNC(GetDeviceCaps);
106 GET_FUNC(GetDeviceGammaRamp);
107 GET_FUNC(GetNearestColor);
109 GET_FUNC(GetPixelFormat);
110 GET_FUNC(GetSystemPaletteEntries);
111 GET_FUNC(GetTextExtentPoint);
112 GET_FUNC(GetTextMetrics);
113 GET_FUNC(IntersectClipRect);
117 GET_FUNC(OffsetClipRgn);
118 GET_FUNC(OffsetViewportOrg);
119 GET_FUNC(OffsetWindowOrg);
123 GET_FUNC(PolyBezier);
124 GET_FUNC(PolyBezierTo);
126 GET_FUNC(PolyPolygon);
127 GET_FUNC(PolyPolyline);
130 GET_FUNC(PolylineTo);
131 GET_FUNC(RealizeDefaultPalette);
132 GET_FUNC(RealizePalette);
138 GET_FUNC(ScaleViewportExt);
139 GET_FUNC(ScaleWindowExt);
140 GET_FUNC(SelectBitmap);
141 GET_FUNC(SelectBrush);
142 GET_FUNC(SelectClipPath);
143 GET_FUNC(SelectFont);
144 GET_FUNC(SelectPalette);
146 GET_FUNC(SetBitmapBits);
147 GET_FUNC(SetBkColor);
150 GET_FUNC(SetDIBColorTable);
152 GET_FUNC(SetDIBitsToDevice);
153 GET_FUNC(SetDeviceClipping);
154 GET_FUNC(SetDeviceGammaRamp);
155 GET_FUNC(SetMapMode);
156 GET_FUNC(SetMapperFlags);
158 GET_FUNC(SetPixelFormat);
159 GET_FUNC(SetPolyFillMode);
162 GET_FUNC(SetStretchBltMode);
163 GET_FUNC(SetTextAlign);
164 GET_FUNC(SetTextCharacterExtra);
165 GET_FUNC(SetTextColor);
166 GET_FUNC(SetTextJustification);
167 GET_FUNC(SetViewportExt);
168 GET_FUNC(SetViewportOrg);
169 GET_FUNC(SetWindowExt);
170 GET_FUNC(SetWindowOrg);
173 GET_FUNC(StretchBlt);
174 GET_FUNC(StretchDIBits);
175 GET_FUNC(StrokeAndFillPath);
176 GET_FUNC(StrokePath);
177 GET_FUNC(SwapBuffers);
181 /* add it to the list */
183 if ((driver->next = first_driver)) driver->next->prev = driver;
184 first_driver = driver;
189 /**********************************************************************
190 * load_display_driver
192 * Special case for loading the display driver: get the name from the config file
194 static struct graphics_driver *load_display_driver(void)
196 char buffer[MAX_PATH];
200 if (display_driver) /* already loaded */
202 display_driver->count++;
203 return display_driver;
206 strcpy( buffer, "x11drv" ); /* default value */
207 if (!RegOpenKeyA( HKEY_LOCAL_MACHINE, "Software\\Wine\\Wine\\Config\\Wine", &hkey ))
209 DWORD type, count = sizeof(buffer);
210 RegQueryValueExA( hkey, "GraphicsDriver", 0, &type, buffer, &count );
214 if (!(module = LoadLibraryA( buffer )))
216 MESSAGE( "Could not load graphics driver '%s'\n", buffer );
220 if (!(display_driver = create_driver( module )))
222 MESSAGE( "Could not create graphics driver '%s'\n", buffer );
223 FreeLibrary( module );
227 display_driver->count++; /* we don't want to free it */
228 return display_driver;
232 /**********************************************************************
235 const DC_FUNCTIONS *DRIVER_load_driver( LPCSTR name )
238 struct graphics_driver *driver;
240 RtlEnterCriticalSection( &driver_section );
242 /* display driver is a special case */
243 if (!strcasecmp( name, "display" ))
245 driver = load_display_driver();
246 RtlLeaveCriticalSection( &driver_section );
247 return &driver->funcs;
250 if ((module = GetModuleHandleA( name )))
252 for (driver = first_driver; driver; driver = driver->next)
254 if (driver->module == module)
257 RtlLeaveCriticalSection( &driver_section );
258 return &driver->funcs;
263 if (!(module = LoadLibraryA( name )))
265 if (!win16_driver) win16_driver = WIN16DRV_Init();
266 RtlLeaveCriticalSection( &driver_section );
270 if (!(driver = create_driver( module )))
272 FreeLibrary( module );
273 RtlLeaveCriticalSection( &driver_section );
277 TRACE( "loaded driver %p for %s\n", driver, name );
278 RtlLeaveCriticalSection( &driver_section );
279 return &driver->funcs;
283 /**********************************************************************
286 * Get a new copy of an existing driver.
288 const DC_FUNCTIONS *DRIVER_get_driver( const DC_FUNCTIONS *funcs )
290 struct graphics_driver *driver;
292 RtlEnterCriticalSection( &driver_section );
293 if (funcs != win16_driver)
295 for (driver = first_driver; driver; driver = driver->next)
296 if (&driver->funcs == funcs) break;
297 if (!driver) ERR( "driver not found, trouble ahead\n" );
300 RtlLeaveCriticalSection( &driver_section );
305 /**********************************************************************
306 * DRIVER_release_driver
308 * Release a driver by decrementing ref count and freeing it if needed.
310 void DRIVER_release_driver( const DC_FUNCTIONS *funcs )
312 struct graphics_driver *driver;
314 RtlEnterCriticalSection( &driver_section );
316 if (funcs == win16_driver) goto done;
318 for (driver = first_driver; driver; driver = driver->next)
319 if (&driver->funcs == funcs) break;
321 if (!driver) goto done;
322 if (--driver->count) goto done;
324 /* removed last reference, free it */
325 if (driver->next) driver->next->prev = driver->prev;
326 if (driver->prev) driver->prev->next = driver->next;
327 else first_driver = driver->next;
328 if (driver == display_driver) display_driver = NULL;
330 FreeLibrary( driver->module );
331 HeapFree( GetProcessHeap(), 0, driver );
333 RtlLeaveCriticalSection( &driver_section );
337 /*****************************************************************************
338 * DRIVER_GetDriverName
341 BOOL DRIVER_GetDriverName( LPCSTR device, LPSTR driver, DWORD size )
344 size = GetProfileStringA("devices", device, "", driver, size);
346 WARN("Unable to find '%s' in [devices] section of win.ini\n", device);
349 p = strchr(driver, ',');
352 WARN("'%s' entry in [devices] section of win.ini is malformed.\n", device);
356 TRACE("Found '%s' for '%s'\n", driver, device);
360 /*****************************************************************************
363 * This should thunk to 16-bit and simply call the proc with the given args.
365 INT WINAPI GDI_CallDevInstall16( FARPROC16 lpfnDevInstallProc, HWND hWnd,
366 LPSTR lpModelName, LPSTR OldPort, LPSTR NewPort )
368 FIXME("(%p, %p, %s, %s, %s)\n", lpfnDevInstallProc, hWnd, lpModelName, OldPort, NewPort );
372 /*****************************************************************************
375 * This should load the correct driver for lpszDevice and calls this driver's
376 * ExtDeviceModePropSheet proc.
378 * Note: The driver calls a callback routine for each property sheet page; these
379 * pages are supposed to be filled into the structure pointed to by lpPropSheet.
380 * The layout of this structure is:
386 * HPROPSHEETPAGE pages[10];
389 INT WINAPI GDI_CallExtDeviceModePropSheet16( HWND hWnd, LPCSTR lpszDevice,
390 LPCSTR lpszPort, LPVOID lpPropSheet )
392 FIXME("(%p, %s, %s, %p)\n", hWnd, lpszDevice, lpszPort, lpPropSheet );
396 /*****************************************************************************
399 * This should load the correct driver for lpszDevice and calls this driver's
400 * ExtDeviceMode proc.
402 INT WINAPI GDI_CallExtDeviceMode16( HWND hwnd,
403 LPDEVMODEA lpdmOutput, LPSTR lpszDevice,
404 LPSTR lpszPort, LPDEVMODEA lpdmInput,
405 LPSTR lpszProfile, DWORD fwMode )
411 INT (*pExtDeviceMode)(LPSTR,HWND,LPDEVMODEA,LPSTR,LPSTR,LPDEVMODEA,LPSTR,DWORD);
413 TRACE("(%p, %p, %s, %s, %p, %s, %ld)\n",
414 hwnd, lpdmOutput, lpszDevice, lpszPort, lpdmInput, lpszProfile, fwMode );
416 if(!DRIVER_GetDriverName( lpszDevice, buf, sizeof(buf) )) return -1;
418 if (!(hdc = CreateICA( buf, lpszDevice, lpszPort, NULL ))) return -1;
420 if ((dc = DC_GetDCPtr( hdc )))
422 pExtDeviceMode = dc->funcs->pExtDeviceMode;
423 GDI_ReleaseObj( hdc );
425 ret = pExtDeviceMode(buf, hwnd, lpdmOutput, lpszDevice, lpszPort,
426 lpdmInput, lpszProfile, fwMode);
432 /****************************************************************************
435 * This should load the correct driver for lpszDevice and calls this driver's
436 * AdvancedSetupDialog proc.
438 INT WINAPI GDI_CallAdvancedSetupDialog16( HWND hwnd, LPSTR lpszDevice,
439 LPDEVMODEA devin, LPDEVMODEA devout )
441 TRACE("(%p, %s, %p, %p)\n", hwnd, lpszDevice, devin, devout );
445 /*****************************************************************************
448 * This should load the correct driver for lpszDevice and calls this driver's
449 * DeviceCapabilities proc.
451 DWORD WINAPI GDI_CallDeviceCapabilities16( LPCSTR lpszDevice, LPCSTR lpszPort,
452 WORD fwCapability, LPSTR lpszOutput,
460 TRACE("(%s, %s, %d, %p, %p)\n", lpszDevice, lpszPort, fwCapability, lpszOutput, lpdm );
462 if(!DRIVER_GetDriverName( lpszDevice, buf, sizeof(buf) )) return -1;
464 if (!(hdc = CreateICA( buf, lpszDevice, lpszPort, NULL ))) return -1;
466 if ((dc = DC_GetDCPtr( hdc )))
468 if (dc->funcs->pDeviceCapabilities)
469 ret = dc->funcs->pDeviceCapabilities( buf, lpszDevice, lpszPort,
470 fwCapability, lpszOutput, lpdm );
471 GDI_ReleaseObj( hdc );