dxgi: Create d3d11 swapchain textures directly from d3d11_swapchain_init().
[wine.git] / dlls / win32u / driver.c
blob5bae77da5f4526378c7a33feca1e3b0bb4cb0943
1 /*
2 * Graphics driver management functions
4 * Copyright 1994 Bob Amstadt
5 * Copyright 1996, 2001 Alexandre Julliard
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 #if 0
23 #pragma makedep unix
24 #endif
26 #include <assert.h>
27 #include <pthread.h>
29 #include "ntstatus.h"
30 #define WIN32_NO_STATUS
31 #include "ntgdi_private.h"
32 #include "ntuser_private.h"
33 #include "wine/winbase16.h"
34 #include "wine/list.h"
35 #include "wine/debug.h"
37 WINE_DEFAULT_DEBUG_CHANNEL(driver);
38 WINE_DECLARE_DEBUG_CHANNEL(winediag);
40 struct d3dkmt_adapter
42 D3DKMT_HANDLE handle; /* Kernel mode graphics adapter handle */
43 struct list entry; /* List entry */
46 struct d3dkmt_device
48 D3DKMT_HANDLE handle; /* Kernel mode graphics device handle*/
49 struct list entry; /* List entry */
52 static const struct user_driver_funcs lazy_load_driver;
53 static struct user_driver_funcs null_user_driver;
55 static struct list d3dkmt_adapters = LIST_INIT( d3dkmt_adapters );
56 static struct list d3dkmt_devices = LIST_INIT( d3dkmt_devices );
58 static pthread_mutex_t driver_lock = PTHREAD_MUTEX_INITIALIZER;
59 static WCHAR driver_load_error[80];
61 static INT CDECL nulldrv_AbortDoc( PHYSDEV dev )
63 return 0;
66 static BOOL CDECL nulldrv_Arc( PHYSDEV dev, INT left, INT top, INT right, INT bottom,
67 INT xstart, INT ystart, INT xend, INT yend )
69 return TRUE;
72 static BOOL CDECL nulldrv_Chord( PHYSDEV dev, INT left, INT top, INT right, INT bottom,
73 INT xstart, INT ystart, INT xend, INT yend )
75 return TRUE;
78 static BOOL CDECL nulldrv_CreateCompatibleDC( PHYSDEV orig, PHYSDEV *pdev )
80 if (!user_driver->dc_funcs.pCreateCompatibleDC) return TRUE;
81 return user_driver->dc_funcs.pCreateCompatibleDC( NULL, pdev );
84 static BOOL CDECL nulldrv_CreateDC( PHYSDEV *dev, LPCWSTR device, LPCWSTR output,
85 const DEVMODEW *devmode )
87 assert(0); /* should never be called */
88 return FALSE;
91 static BOOL CDECL nulldrv_DeleteDC( PHYSDEV dev )
93 assert(0); /* should never be called */
94 return TRUE;
97 static BOOL CDECL nulldrv_DeleteObject( PHYSDEV dev, HGDIOBJ obj )
99 return TRUE;
102 static BOOL CDECL nulldrv_Ellipse( PHYSDEV dev, INT left, INT top, INT right, INT bottom )
104 return TRUE;
107 static INT CDECL nulldrv_EndDoc( PHYSDEV dev )
109 return 0;
112 static INT CDECL nulldrv_EndPage( PHYSDEV dev )
114 return 0;
117 static BOOL CDECL nulldrv_EnumFonts( PHYSDEV dev, LOGFONTW *logfont, FONTENUMPROCW proc, LPARAM lParam )
119 return TRUE;
122 static INT CDECL nulldrv_ExtEscape( PHYSDEV dev, INT escape, INT in_size, const void *in_data,
123 INT out_size, void *out_data )
125 return 0;
128 static BOOL CDECL nulldrv_ExtFloodFill( PHYSDEV dev, INT x, INT y, COLORREF color, UINT type )
130 return TRUE;
133 static BOOL CDECL nulldrv_FontIsLinked( PHYSDEV dev )
135 return FALSE;
138 static UINT CDECL nulldrv_GetBoundsRect( PHYSDEV dev, RECT *rect, UINT flags )
140 return DCB_RESET;
143 static BOOL CDECL nulldrv_GetCharABCWidths( PHYSDEV dev, UINT first, UINT count,
144 WCHAR *chars, ABC *abc )
146 return FALSE;
149 static BOOL CDECL nulldrv_GetCharABCWidthsI( PHYSDEV dev, UINT first, UINT count, WORD *indices, LPABC abc )
151 return FALSE;
154 static BOOL CDECL nulldrv_GetCharWidth( PHYSDEV dev, UINT first, UINT count,
155 const WCHAR *chars, INT *buffer )
157 return FALSE;
160 static BOOL CDECL nulldrv_GetCharWidthInfo( PHYSDEV dev, void *info )
162 return FALSE;
165 static INT CDECL nulldrv_GetDeviceCaps( PHYSDEV dev, INT cap )
167 int bpp;
169 switch (cap)
171 case DRIVERVERSION: return 0x4000;
172 case TECHNOLOGY: return DT_RASDISPLAY;
173 case HORZSIZE: return muldiv( NtGdiGetDeviceCaps( dev->hdc, HORZRES ), 254,
174 NtGdiGetDeviceCaps( dev->hdc, LOGPIXELSX ) * 10 );
175 case VERTSIZE: return muldiv( NtGdiGetDeviceCaps( dev->hdc, VERTRES ), 254,
176 NtGdiGetDeviceCaps( dev->hdc, LOGPIXELSY ) * 10 );
177 case HORZRES:
179 DC *dc = get_nulldrv_dc( dev );
180 RECT rect;
181 int ret;
183 if (dc->display[0])
185 rect = get_display_rect( dc->display );
186 if (!IsRectEmpty( &rect )) return rect.right - rect.left;
189 ret = get_system_metrics( SM_CXSCREEN );
190 return ret ? ret : 640;
192 case VERTRES:
194 DC *dc = get_nulldrv_dc( dev );
195 RECT rect;
196 int ret;
198 if (dc->display[0])
200 rect = get_display_rect( dc->display );
201 if (!IsRectEmpty( &rect )) return rect.bottom - rect.top;
204 ret = get_system_metrics( SM_CYSCREEN );
205 return ret ? ret : 480;
207 case BITSPIXEL:
209 UNICODE_STRING display;
210 DC *dc;
212 if (NtGdiGetDeviceCaps( dev->hdc, TECHNOLOGY ) == DT_RASDISPLAY)
214 dc = get_nulldrv_dc( dev );
215 RtlInitUnicodeString( &display, dc->display );
216 return get_display_depth( &display );
218 return 32;
220 case PLANES: return 1;
221 case NUMBRUSHES: return -1;
222 case NUMPENS: return -1;
223 case NUMMARKERS: return 0;
224 case NUMFONTS: return 0;
225 case PDEVICESIZE: return 0;
226 case CURVECAPS: return (CC_CIRCLES | CC_PIE | CC_CHORD | CC_ELLIPSES | CC_WIDE |
227 CC_STYLED | CC_WIDESTYLED | CC_INTERIORS | CC_ROUNDRECT);
228 case LINECAPS: return (LC_POLYLINE | LC_MARKER | LC_POLYMARKER | LC_WIDE |
229 LC_STYLED | LC_WIDESTYLED | LC_INTERIORS);
230 case POLYGONALCAPS: return (PC_POLYGON | PC_RECTANGLE | PC_WINDPOLYGON | PC_SCANLINE |
231 PC_WIDE | PC_STYLED | PC_WIDESTYLED | PC_INTERIORS);
232 case TEXTCAPS: return (TC_OP_CHARACTER | TC_OP_STROKE | TC_CP_STROKE |
233 TC_CR_ANY | TC_SF_X_YINDEP | TC_SA_DOUBLE | TC_SA_INTEGER |
234 TC_SA_CONTIN | TC_UA_ABLE | TC_SO_ABLE | TC_RA_ABLE | TC_VA_ABLE);
235 case CLIPCAPS: return CP_RECTANGLE;
236 case RASTERCAPS: return (RC_BITBLT | RC_BITMAP64 | RC_GDI20_OUTPUT | RC_DI_BITMAP | RC_DIBTODEV |
237 RC_BIGFONT | RC_STRETCHBLT | RC_FLOODFILL | RC_STRETCHDIB | RC_DEVBITS |
238 (NtGdiGetDeviceCaps( dev->hdc, SIZEPALETTE ) ? RC_PALETTE : 0));
239 case ASPECTX: return 36;
240 case ASPECTY: return 36;
241 case ASPECTXY: return (int)(hypot( NtGdiGetDeviceCaps( dev->hdc, ASPECTX ),
242 NtGdiGetDeviceCaps( dev->hdc, ASPECTY )) + 0.5);
243 case CAPS1: return 0;
244 case SIZEPALETTE: return 0;
245 case NUMRESERVED: return 20;
246 case PHYSICALWIDTH: return 0;
247 case PHYSICALHEIGHT: return 0;
248 case PHYSICALOFFSETX: return 0;
249 case PHYSICALOFFSETY: return 0;
250 case SCALINGFACTORX: return 0;
251 case SCALINGFACTORY: return 0;
252 case VREFRESH:
254 UNICODE_STRING display;
255 DEVMODEW devmode;
256 DC *dc;
258 if (NtGdiGetDeviceCaps( dev->hdc, TECHNOLOGY ) != DT_RASDISPLAY)
259 return 0;
261 dc = get_nulldrv_dc( dev );
263 memset( &devmode, 0, sizeof(devmode) );
264 devmode.dmSize = sizeof(devmode);
265 RtlInitUnicodeString( &display, dc->display );
266 if (NtUserEnumDisplaySettings( &display, ENUM_CURRENT_SETTINGS, &devmode, 0 ) &&
267 devmode.dmDisplayFrequency)
268 return devmode.dmDisplayFrequency;
269 return 1;
271 case DESKTOPHORZRES:
272 if (NtGdiGetDeviceCaps( dev->hdc, TECHNOLOGY ) == DT_RASDISPLAY)
274 RECT rect = get_virtual_screen_rect( 0 );
275 return rect.right - rect.left;
277 return NtGdiGetDeviceCaps( dev->hdc, HORZRES );
278 case DESKTOPVERTRES:
279 if (NtGdiGetDeviceCaps( dev->hdc, TECHNOLOGY ) == DT_RASDISPLAY)
281 RECT rect = get_virtual_screen_rect( 0 );
282 return rect.bottom - rect.top;
284 return NtGdiGetDeviceCaps( dev->hdc, VERTRES );
285 case BLTALIGNMENT: return 0;
286 case SHADEBLENDCAPS: return 0;
287 case COLORMGMTCAPS: return 0;
288 case LOGPIXELSX:
289 case LOGPIXELSY: return get_system_dpi();
290 case NUMCOLORS:
291 bpp = NtGdiGetDeviceCaps( dev->hdc, BITSPIXEL );
292 /* Newer versions of Windows return -1 for 8-bit and higher */
293 return (bpp > 4) ? -1 : (1 << bpp);
294 case COLORRES:
295 /* The observed correspondence between BITSPIXEL and COLORRES is:
296 * BITSPIXEL: 8 -> COLORRES: 18
297 * BITSPIXEL: 16 -> COLORRES: 16
298 * BITSPIXEL: 24 -> COLORRES: 24
299 * BITSPIXEL: 32 -> COLORRES: 24 */
300 bpp = NtGdiGetDeviceCaps( dev->hdc, BITSPIXEL );
301 return (bpp <= 8) ? 18 : min( 24, bpp );
302 default:
303 FIXME("(%p): unsupported capability %d, will return 0\n", dev->hdc, cap );
304 return 0;
308 static BOOL CDECL nulldrv_GetDeviceGammaRamp( PHYSDEV dev, void *ramp )
310 RtlSetLastWin32Error( ERROR_INVALID_PARAMETER );
311 return FALSE;
314 static DWORD CDECL nulldrv_GetFontData( PHYSDEV dev, DWORD table, DWORD offset, LPVOID buffer, DWORD length )
316 return FALSE;
319 static BOOL CDECL nulldrv_GetFontRealizationInfo( PHYSDEV dev, void *info )
321 return FALSE;
324 static DWORD CDECL nulldrv_GetFontUnicodeRanges( PHYSDEV dev, LPGLYPHSET glyphs )
326 return 0;
329 static DWORD CDECL nulldrv_GetGlyphIndices( PHYSDEV dev, LPCWSTR str, INT count, LPWORD indices, DWORD flags )
331 return GDI_ERROR;
334 static DWORD CDECL nulldrv_GetGlyphOutline( PHYSDEV dev, UINT ch, UINT format, LPGLYPHMETRICS metrics,
335 DWORD size, LPVOID buffer, const MAT2 *mat )
337 return GDI_ERROR;
340 static BOOL CDECL nulldrv_GetICMProfile( PHYSDEV dev, BOOL allow_default, LPDWORD size, LPWSTR filename )
342 return FALSE;
345 static DWORD CDECL nulldrv_GetImage( PHYSDEV dev, BITMAPINFO *info, struct gdi_image_bits *bits,
346 struct bitblt_coords *src )
348 return ERROR_NOT_SUPPORTED;
351 static DWORD CDECL nulldrv_GetKerningPairs( PHYSDEV dev, DWORD count, LPKERNINGPAIR pairs )
353 return 0;
356 static UINT CDECL nulldrv_GetOutlineTextMetrics( PHYSDEV dev, UINT size, LPOUTLINETEXTMETRICW otm )
358 return 0;
361 static UINT CDECL nulldrv_GetTextCharsetInfo( PHYSDEV dev, LPFONTSIGNATURE fs, DWORD flags )
363 return DEFAULT_CHARSET;
366 static BOOL CDECL nulldrv_GetTextExtentExPoint( PHYSDEV dev, LPCWSTR str, INT count, INT *dx )
368 return FALSE;
371 static BOOL CDECL nulldrv_GetTextExtentExPointI( PHYSDEV dev, const WORD *indices, INT count, INT *dx )
373 return FALSE;
376 static INT CDECL nulldrv_GetTextFace( PHYSDEV dev, INT size, LPWSTR name )
378 INT ret = 0;
379 LOGFONTW font;
380 DC *dc = get_nulldrv_dc( dev );
382 if (NtGdiExtGetObjectW( dc->hFont, sizeof(font), &font ))
384 ret = lstrlenW( font.lfFaceName ) + 1;
385 if (name)
387 lstrcpynW( name, font.lfFaceName, size );
388 ret = min( size, ret );
391 return ret;
394 static BOOL CDECL nulldrv_GetTextMetrics( PHYSDEV dev, TEXTMETRICW *metrics )
396 return FALSE;
399 static BOOL CDECL nulldrv_LineTo( PHYSDEV dev, INT x, INT y )
401 return TRUE;
404 static BOOL CDECL nulldrv_MoveTo( PHYSDEV dev, INT x, INT y )
406 return TRUE;
409 static BOOL CDECL nulldrv_PaintRgn( PHYSDEV dev, HRGN rgn )
411 return TRUE;
414 static BOOL CDECL nulldrv_PatBlt( PHYSDEV dev, struct bitblt_coords *dst, DWORD rop )
416 return TRUE;
419 static BOOL CDECL nulldrv_Pie( PHYSDEV dev, INT left, INT top, INT right, INT bottom,
420 INT xstart, INT ystart, INT xend, INT yend )
422 return TRUE;
425 static BOOL CDECL nulldrv_PolyPolygon( PHYSDEV dev, const POINT *points, const INT *counts, UINT polygons )
427 return TRUE;
430 static BOOL CDECL nulldrv_PolyPolyline( PHYSDEV dev, const POINT *points, const DWORD *counts, DWORD lines )
432 return TRUE;
435 static DWORD CDECL nulldrv_PutImage( PHYSDEV dev, HRGN clip, BITMAPINFO *info,
436 const struct gdi_image_bits *bits, struct bitblt_coords *src,
437 struct bitblt_coords *dst, DWORD rop )
439 return ERROR_SUCCESS;
442 static UINT CDECL nulldrv_RealizeDefaultPalette( PHYSDEV dev )
444 return 0;
447 static UINT CDECL nulldrv_RealizePalette( PHYSDEV dev, HPALETTE palette, BOOL primary )
449 return 0;
452 static BOOL CDECL nulldrv_Rectangle( PHYSDEV dev, INT left, INT top, INT right, INT bottom )
454 return TRUE;
457 static BOOL CDECL nulldrv_ResetDC( PHYSDEV dev, const DEVMODEW *devmode )
459 return FALSE;
462 static BOOL CDECL nulldrv_RoundRect( PHYSDEV dev, INT left, INT top, INT right, INT bottom,
463 INT ell_width, INT ell_height )
465 return TRUE;
468 static HBITMAP CDECL nulldrv_SelectBitmap( PHYSDEV dev, HBITMAP bitmap )
470 return bitmap;
473 static HBRUSH CDECL nulldrv_SelectBrush( PHYSDEV dev, HBRUSH brush, const struct brush_pattern *pattern )
475 return brush;
478 static HFONT CDECL nulldrv_SelectFont( PHYSDEV dev, HFONT font, UINT *aa_flags )
480 return font;
483 static HPEN CDECL nulldrv_SelectPen( PHYSDEV dev, HPEN pen, const struct brush_pattern *pattern )
485 return pen;
488 static COLORREF CDECL nulldrv_SetBkColor( PHYSDEV dev, COLORREF color )
490 return color;
493 static UINT CDECL nulldrv_SetBoundsRect( PHYSDEV dev, RECT *rect, UINT flags )
495 return DCB_RESET;
498 static COLORREF CDECL nulldrv_SetDCBrushColor( PHYSDEV dev, COLORREF color )
500 return color;
503 static COLORREF CDECL nulldrv_SetDCPenColor( PHYSDEV dev, COLORREF color )
505 return color;
508 static void CDECL nulldrv_SetDeviceClipping( PHYSDEV dev, HRGN rgn )
512 static BOOL CDECL nulldrv_SetDeviceGammaRamp( PHYSDEV dev, void *ramp )
514 RtlSetLastWin32Error( ERROR_INVALID_PARAMETER );
515 return FALSE;
518 static COLORREF CDECL nulldrv_SetPixel( PHYSDEV dev, INT x, INT y, COLORREF color )
520 return color;
523 static COLORREF CDECL nulldrv_SetTextColor( PHYSDEV dev, COLORREF color )
525 return color;
528 static INT CDECL nulldrv_StartDoc( PHYSDEV dev, const DOCINFOW *info )
530 return 0;
533 static INT CDECL nulldrv_StartPage( PHYSDEV dev )
535 return 1;
538 static BOOL CDECL nulldrv_UnrealizePalette( HPALETTE palette )
540 return FALSE;
543 static NTSTATUS CDECL nulldrv_D3DKMTCheckVidPnExclusiveOwnership( const D3DKMT_CHECKVIDPNEXCLUSIVEOWNERSHIP *desc )
545 return STATUS_PROCEDURE_NOT_FOUND;
548 static NTSTATUS CDECL nulldrv_D3DKMTCloseAdapter( const D3DKMT_CLOSEADAPTER *desc )
550 return STATUS_PROCEDURE_NOT_FOUND;
553 static NTSTATUS CDECL nulldrv_D3DKMTOpenAdapterFromLuid( D3DKMT_OPENADAPTERFROMLUID *desc )
555 return STATUS_PROCEDURE_NOT_FOUND;
558 static NTSTATUS CDECL nulldrv_D3DKMTQueryVideoMemoryInfo( D3DKMT_QUERYVIDEOMEMORYINFO *desc )
560 return STATUS_PROCEDURE_NOT_FOUND;
563 static NTSTATUS CDECL nulldrv_D3DKMTSetVidPnSourceOwner( const D3DKMT_SETVIDPNSOURCEOWNER *desc )
565 return STATUS_PROCEDURE_NOT_FOUND;
568 const struct gdi_dc_funcs null_driver =
570 nulldrv_AbortDoc, /* pAbortDoc */
571 nulldrv_AbortPath, /* pAbortPath */
572 nulldrv_AlphaBlend, /* pAlphaBlend */
573 nulldrv_AngleArc, /* pAngleArc */
574 nulldrv_Arc, /* pArc */
575 nulldrv_ArcTo, /* pArcTo */
576 nulldrv_BeginPath, /* pBeginPath */
577 nulldrv_BlendImage, /* pBlendImage */
578 nulldrv_Chord, /* pChord */
579 nulldrv_CloseFigure, /* pCloseFigure */
580 nulldrv_CreateCompatibleDC, /* pCreateCompatibleDC */
581 nulldrv_CreateDC, /* pCreateDC */
582 nulldrv_DeleteDC, /* pDeleteDC */
583 nulldrv_DeleteObject, /* pDeleteObject */
584 nulldrv_Ellipse, /* pEllipse */
585 nulldrv_EndDoc, /* pEndDoc */
586 nulldrv_EndPage, /* pEndPage */
587 nulldrv_EndPath, /* pEndPath */
588 nulldrv_EnumFonts, /* pEnumFonts */
589 nulldrv_ExtEscape, /* pExtEscape */
590 nulldrv_ExtFloodFill, /* pExtFloodFill */
591 nulldrv_ExtTextOut, /* pExtTextOut */
592 nulldrv_FillPath, /* pFillPath */
593 nulldrv_FillRgn, /* pFillRgn */
594 nulldrv_FontIsLinked, /* pFontIsLinked */
595 nulldrv_FrameRgn, /* pFrameRgn */
596 nulldrv_GetBoundsRect, /* pGetBoundsRect */
597 nulldrv_GetCharABCWidths, /* pGetCharABCWidths */
598 nulldrv_GetCharABCWidthsI, /* pGetCharABCWidthsI */
599 nulldrv_GetCharWidth, /* pGetCharWidth */
600 nulldrv_GetCharWidthInfo, /* pGetCharWidthInfo */
601 nulldrv_GetDeviceCaps, /* pGetDeviceCaps */
602 nulldrv_GetDeviceGammaRamp, /* pGetDeviceGammaRamp */
603 nulldrv_GetFontData, /* pGetFontData */
604 nulldrv_GetFontRealizationInfo, /* pGetFontRealizationInfo */
605 nulldrv_GetFontUnicodeRanges, /* pGetFontUnicodeRanges */
606 nulldrv_GetGlyphIndices, /* pGetGlyphIndices */
607 nulldrv_GetGlyphOutline, /* pGetGlyphOutline */
608 nulldrv_GetICMProfile, /* pGetICMProfile */
609 nulldrv_GetImage, /* pGetImage */
610 nulldrv_GetKerningPairs, /* pGetKerningPairs */
611 nulldrv_GetNearestColor, /* pGetNearestColor */
612 nulldrv_GetOutlineTextMetrics, /* pGetOutlineTextMetrics */
613 nulldrv_GetPixel, /* pGetPixel */
614 nulldrv_GetSystemPaletteEntries, /* pGetSystemPaletteEntries */
615 nulldrv_GetTextCharsetInfo, /* pGetTextCharsetInfo */
616 nulldrv_GetTextExtentExPoint, /* pGetTextExtentExPoint */
617 nulldrv_GetTextExtentExPointI, /* pGetTextExtentExPointI */
618 nulldrv_GetTextFace, /* pGetTextFace */
619 nulldrv_GetTextMetrics, /* pGetTextMetrics */
620 nulldrv_GradientFill, /* pGradientFill */
621 nulldrv_InvertRgn, /* pInvertRgn */
622 nulldrv_LineTo, /* pLineTo */
623 nulldrv_MoveTo, /* pMoveTo */
624 nulldrv_PaintRgn, /* pPaintRgn */
625 nulldrv_PatBlt, /* pPatBlt */
626 nulldrv_Pie, /* pPie */
627 nulldrv_PolyBezier, /* pPolyBezier */
628 nulldrv_PolyBezierTo, /* pPolyBezierTo */
629 nulldrv_PolyDraw, /* pPolyDraw */
630 nulldrv_PolyPolygon, /* pPolyPolygon */
631 nulldrv_PolyPolyline, /* pPolyPolyline */
632 nulldrv_PolylineTo, /* pPolylineTo */
633 nulldrv_PutImage, /* pPutImage */
634 nulldrv_RealizeDefaultPalette, /* pRealizeDefaultPalette */
635 nulldrv_RealizePalette, /* pRealizePalette */
636 nulldrv_Rectangle, /* pRectangle */
637 nulldrv_ResetDC, /* pResetDC */
638 nulldrv_RoundRect, /* pRoundRect */
639 nulldrv_SelectBitmap, /* pSelectBitmap */
640 nulldrv_SelectBrush, /* pSelectBrush */
641 nulldrv_SelectFont, /* pSelectFont */
642 nulldrv_SelectPen, /* pSelectPen */
643 nulldrv_SetBkColor, /* pSetBkColor */
644 nulldrv_SetBoundsRect, /* pSetBoundsRect */
645 nulldrv_SetDCBrushColor, /* pSetDCBrushColor */
646 nulldrv_SetDCPenColor, /* pSetDCPenColor */
647 nulldrv_SetDIBitsToDevice, /* pSetDIBitsToDevice */
648 nulldrv_SetDeviceClipping, /* pSetDeviceClipping */
649 nulldrv_SetDeviceGammaRamp, /* pSetDeviceGammaRamp */
650 nulldrv_SetPixel, /* pSetPixel */
651 nulldrv_SetTextColor, /* pSetTextColor */
652 nulldrv_StartDoc, /* pStartDoc */
653 nulldrv_StartPage, /* pStartPage */
654 nulldrv_StretchBlt, /* pStretchBlt */
655 nulldrv_StretchDIBits, /* pStretchDIBits */
656 nulldrv_StrokeAndFillPath, /* pStrokeAndFillPath */
657 nulldrv_StrokePath, /* pStrokePath */
658 nulldrv_UnrealizePalette, /* pUnrealizePalette */
659 nulldrv_D3DKMTCheckVidPnExclusiveOwnership, /* pD3DKMTCheckVidPnExclusiveOwnership */
660 nulldrv_D3DKMTCloseAdapter, /* pD3DKMTCloseAdapter */
661 nulldrv_D3DKMTOpenAdapterFromLuid, /* pD3DKMTOpenAdapterFromLuid */
662 nulldrv_D3DKMTQueryVideoMemoryInfo, /* pD3DKMTQueryVideoMemoryInfo */
663 nulldrv_D3DKMTSetVidPnSourceOwner, /* pD3DKMTSetVidPnSourceOwner */
665 GDI_PRIORITY_NULL_DRV /* priority */
669 /**********************************************************************
670 * Null user driver
672 * These are fallbacks for entry points that are not implemented in the real driver.
675 static BOOL nulldrv_ActivateKeyboardLayout( HKL layout, UINT flags )
677 return TRUE;
680 static void nulldrv_Beep(void)
684 static UINT nulldrv_GetKeyboardLayoutList( INT size, HKL *layouts )
686 return ~0; /* use default implementation */
689 static INT nulldrv_GetKeyNameText( LONG lparam, LPWSTR buffer, INT size )
691 return -1; /* use default implementation */
694 static UINT nulldrv_MapVirtualKeyEx( UINT code, UINT type, HKL layout )
696 return -1; /* use default implementation */
699 static BOOL nulldrv_RegisterHotKey( HWND hwnd, UINT modifiers, UINT vk )
701 return TRUE;
704 static INT nulldrv_ToUnicodeEx( UINT virt, UINT scan, const BYTE *state, LPWSTR str,
705 int size, UINT flags, HKL layout )
707 return -2; /* use default implementation */
710 static void nulldrv_UnregisterHotKey( HWND hwnd, UINT modifiers, UINT vk )
714 static SHORT nulldrv_VkKeyScanEx( WCHAR ch, HKL layout )
716 return -256; /* use default implementation */
719 static LRESULT nulldrv_DesktopWindowProc( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam )
721 return default_window_proc( hwnd, msg, wparam, lparam, FALSE );
724 static void nulldrv_DestroyCursorIcon( HCURSOR cursor )
728 static void nulldrv_SetCursor( HCURSOR cursor )
732 static BOOL nulldrv_GetCursorPos( LPPOINT pt )
734 return TRUE;
737 static BOOL nulldrv_SetCursorPos( INT x, INT y )
739 return TRUE;
742 static BOOL nulldrv_ClipCursor( LPCRECT clip )
744 return TRUE;
747 static void nulldrv_UpdateClipboard(void)
751 static LONG nulldrv_ChangeDisplaySettings( LPDEVMODEW displays, LPCWSTR primary_name, HWND hwnd,
752 DWORD flags, LPVOID lparam )
754 return E_NOTIMPL; /* use default implementation */
757 static BOOL nulldrv_GetCurrentDisplaySettings( LPCWSTR name, BOOL is_primary, LPDEVMODEW mode )
759 return FALSE; /* use default implementation */
762 static INT nulldrv_GetDisplayDepth( LPCWSTR name, BOOL is_primary )
764 return -1; /* use default implementation */
767 static BOOL nulldrv_UpdateDisplayDevices( const struct gdi_device_manager *manager, BOOL force, void *param )
769 return FALSE;
772 static BOOL nulldrv_CreateDesktopWindow( HWND hwnd )
774 return TRUE;
777 static BOOL nodrv_CreateWindow( HWND hwnd )
779 static int warned;
780 HWND parent = NtUserGetAncestor( hwnd, GA_PARENT );
782 /* HWND_MESSAGE windows don't need a graphics driver */
783 if (!parent || parent == UlongToHandle( NtUserGetThreadInfo()->msg_window )) return TRUE;
784 if (warned++) return FALSE;
786 ERR_(winediag)( "Application tried to create a window, but no driver could be loaded.\n" );
787 if (driver_load_error[0]) ERR_(winediag)( "%s\n", debugstr_w(driver_load_error) );
788 return FALSE;
791 static BOOL nulldrv_CreateWindow( HWND hwnd )
793 return TRUE;
796 static void nulldrv_DestroyWindow( HWND hwnd )
800 static void nulldrv_FlashWindowEx( FLASHWINFO *info )
804 static void nulldrv_GetDC( HDC hdc, HWND hwnd, HWND top_win, const RECT *win_rect,
805 const RECT *top_rect, DWORD flags )
809 static BOOL nulldrv_ProcessEvents( DWORD mask )
811 return FALSE;
814 static void nulldrv_ReleaseDC( HWND hwnd, HDC hdc )
818 static BOOL nulldrv_ScrollDC( HDC hdc, INT dx, INT dy, HRGN update )
820 RECT rect;
822 NtGdiGetAppClipBox( hdc, &rect );
823 return NtGdiBitBlt( hdc, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top,
824 hdc, rect.left - dx, rect.top - dy, SRCCOPY, 0, 0 );
827 static void nulldrv_SetCapture( HWND hwnd, UINT flags )
831 static void nulldrv_SetFocus( HWND hwnd )
835 static void nulldrv_SetLayeredWindowAttributes( HWND hwnd, COLORREF key, BYTE alpha, DWORD flags )
839 static void nulldrv_SetParent( HWND hwnd, HWND parent, HWND old_parent )
843 static void nulldrv_SetWindowRgn( HWND hwnd, HRGN hrgn, BOOL redraw )
847 static void nulldrv_SetWindowIcon( HWND hwnd, UINT type, HICON icon )
851 static void nulldrv_SetWindowStyle( HWND hwnd, INT offset, STYLESTRUCT *style )
855 static void nulldrv_SetWindowText( HWND hwnd, LPCWSTR text )
859 static UINT nulldrv_ShowWindow( HWND hwnd, INT cmd, RECT *rect, UINT swp )
861 return ~0; /* use default implementation */
864 static LRESULT nulldrv_SysCommand( HWND hwnd, WPARAM wparam, LPARAM lparam )
866 return -1;
869 static BOOL nulldrv_UpdateLayeredWindow( HWND hwnd, const UPDATELAYEREDWINDOWINFO *info,
870 const RECT *window_rect )
872 return TRUE;
875 static LRESULT nulldrv_WindowMessage( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam )
877 return 0;
880 static BOOL nulldrv_WindowPosChanging( HWND hwnd, HWND insert_after, UINT swp_flags,
881 const RECT *window_rect, const RECT *client_rect,
882 RECT *visible_rect, struct window_surface **surface )
884 return FALSE;
887 static void nulldrv_WindowPosChanged( HWND hwnd, HWND insert_after, UINT swp_flags,
888 const RECT *window_rect, const RECT *client_rect,
889 const RECT *visible_rect, const RECT *valid_rects,
890 struct window_surface *surface )
894 static BOOL nulldrv_SystemParametersInfo( UINT action, UINT int_param, void *ptr_param, UINT flags )
896 return FALSE;
899 static const struct vulkan_funcs *nulldrv_wine_get_vulkan_driver( UINT version )
901 return NULL;
904 static struct opengl_funcs *nulldrv_wine_get_wgl_driver( UINT version )
906 return (void *)-1;
909 static void nulldrv_ThreadDetach( void )
913 static const WCHAR guid_key_prefixW[] =
915 '\\','R','e','g','i','s','t','r','y',
916 '\\','M','a','c','h','i','n','e',
917 '\\','S','y','s','t','e','m',
918 '\\','C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t',
919 '\\','C','o','n','t','r','o','l',
920 '\\','V','i','d','e','o','\\','{'
922 static const WCHAR guid_key_suffixW[] = {'}','\\','0','0','0','0'};
924 static BOOL load_desktop_driver( HWND hwnd )
926 static const WCHAR guid_nullW[] = {'0','0','0','0','0','0','0','0','-','0','0','0','0','-','0','0','0','0','-',
927 '0','0','0','0','-','0','0','0','0','0','0','0','0','0','0','0','0',0};
928 WCHAR key[ARRAYSIZE(guid_key_prefixW) + 40 + ARRAYSIZE(guid_key_suffixW)], *ptr;
929 char buf[4096];
930 KEY_VALUE_PARTIAL_INFORMATION *info = (void *)buf;
931 ATOM_BASIC_INFORMATION *abi = (ATOM_BASIC_INFORMATION *)buf;
932 BOOL ret = FALSE;
933 HKEY hkey;
934 DWORD size;
935 UINT guid_atom;
937 static const WCHAR prop_nameW[] =
938 {'_','_','w','i','n','e','_','d','i','s','p','l','a','y','_','d','e','v','i','c','e',
939 '_','g','u','i','d',0};
941 user_check_not_lock();
943 asciiz_to_unicode( driver_load_error, "The explorer process failed to start." ); /* default error */
944 /* wait for graphics driver to be ready */
945 send_message( hwnd, WM_NULL, 0, 0 );
947 guid_atom = HandleToULong( NtUserGetProp( hwnd, prop_nameW ));
948 memcpy( key, guid_key_prefixW, sizeof(guid_key_prefixW) );
949 ptr = key + ARRAYSIZE(guid_key_prefixW);
950 if (NtQueryInformationAtom( guid_atom, AtomBasicInformation, buf, sizeof(buf), NULL ))
952 wcscpy( ptr, guid_nullW );
953 ptr += ARRAY_SIZE(guid_nullW) - 1;
955 else
957 memcpy( ptr, abi->Name, abi->NameLength );
958 ptr += abi->NameLength / sizeof(WCHAR);
960 memcpy( ptr, guid_key_suffixW, sizeof(guid_key_suffixW) );
961 ptr += ARRAY_SIZE(guid_key_suffixW);
963 if (!(hkey = reg_open_key( NULL, key, (ptr - key) * sizeof(WCHAR) ))) return FALSE;
965 if ((size = query_reg_ascii_value( hkey, "GraphicsDriver", info, sizeof(buf) )))
967 static const WCHAR nullW[] = {'n','u','l','l',0};
968 TRACE( "trying driver %s\n", debugstr_wn( (const WCHAR *)info->Data,
969 info->DataLength / sizeof(WCHAR) ));
970 if (info->DataLength != sizeof(nullW) || memcmp( info->Data, nullW, sizeof(nullW) ))
972 void *ret_ptr;
973 ULONG ret_len;
974 ret = KeUserModeCallback( NtUserLoadDriver, info->Data, info->DataLength,
975 &ret_ptr, &ret_len );
977 else
979 __wine_set_user_driver( &null_user_driver, WINE_GDI_DRIVER_VERSION );
980 ret = TRUE;
983 else if ((size = query_reg_ascii_value( hkey, "DriverError", info, sizeof(buf) )))
985 memcpy( driver_load_error, info->Data, min( info->DataLength, sizeof(driver_load_error) ));
986 driver_load_error[ARRAYSIZE(driver_load_error) - 1] = 0;
989 NtClose( hkey );
990 return ret;
993 /**********************************************************************
994 * Lazy loading user driver
996 * Initial driver used before another driver is loaded.
997 * Each entry point simply loads the real driver and chains to it.
1000 static const struct user_driver_funcs *load_driver(void)
1002 USEROBJECTFLAGS flags;
1003 HWINSTA winstation;
1005 if (!load_desktop_driver( get_desktop_window() ) || user_driver == &lazy_load_driver)
1007 winstation = NtUserGetProcessWindowStation();
1008 if (!NtUserGetObjectInformation( winstation, UOI_FLAGS, &flags, sizeof(flags), NULL )
1009 || (flags.dwFlags & WSF_VISIBLE))
1010 null_user_driver.pCreateWindow = nodrv_CreateWindow;
1012 __wine_set_user_driver( &null_user_driver, WINE_GDI_DRIVER_VERSION );
1015 return user_driver;
1018 /**********************************************************************
1019 * get_display_driver
1021 const struct gdi_dc_funcs *get_display_driver(void)
1023 if (user_driver == &lazy_load_driver) load_driver();
1024 return &user_driver->dc_funcs;
1027 static BOOL loaderdrv_ActivateKeyboardLayout( HKL layout, UINT flags )
1029 return load_driver()->pActivateKeyboardLayout( layout, flags );
1032 static void loaderdrv_Beep(void)
1034 load_driver()->pBeep();
1037 static INT loaderdrv_GetKeyNameText( LONG lparam, LPWSTR buffer, INT size )
1039 return load_driver()->pGetKeyNameText( lparam, buffer, size );
1042 static UINT loaderdrv_GetKeyboardLayoutList( INT size, HKL *layouts )
1044 return load_driver()->pGetKeyboardLayoutList( size, layouts );
1047 static UINT loaderdrv_MapVirtualKeyEx( UINT code, UINT type, HKL layout )
1049 return load_driver()->pMapVirtualKeyEx( code, type, layout );
1052 static INT loaderdrv_ToUnicodeEx( UINT virt, UINT scan, const BYTE *state, LPWSTR str,
1053 int size, UINT flags, HKL layout )
1055 return load_driver()->pToUnicodeEx( virt, scan, state, str, size, flags, layout );
1058 static BOOL loaderdrv_RegisterHotKey( HWND hwnd, UINT modifiers, UINT vk )
1060 return load_driver()->pRegisterHotKey( hwnd, modifiers, vk );
1063 static void loaderdrv_UnregisterHotKey( HWND hwnd, UINT modifiers, UINT vk )
1065 load_driver()->pUnregisterHotKey( hwnd, modifiers, vk );
1068 static SHORT loaderdrv_VkKeyScanEx( WCHAR ch, HKL layout )
1070 return load_driver()->pVkKeyScanEx( ch, layout );
1073 static LONG loaderdrv_ChangeDisplaySettings( LPDEVMODEW displays, LPCWSTR primary_name, HWND hwnd,
1074 DWORD flags, LPVOID lparam )
1076 return load_driver()->pChangeDisplaySettings( displays, primary_name, hwnd, flags, lparam );
1079 static BOOL loaderdrv_GetCurrentDisplaySettings( LPCWSTR name, BOOL is_primary, LPDEVMODEW mode )
1081 return load_driver()->pGetCurrentDisplaySettings( name, is_primary, mode );
1084 static INT loaderdrv_GetDisplayDepth( LPCWSTR name, BOOL is_primary )
1086 return load_driver()->pGetDisplayDepth( name, is_primary );
1089 static void loaderdrv_SetCursor( HCURSOR cursor )
1091 load_driver()->pSetCursor( cursor );
1094 static BOOL loaderdrv_GetCursorPos( POINT *pt )
1096 return load_driver()->pGetCursorPos( pt );
1099 static BOOL loaderdrv_SetCursorPos( INT x, INT y )
1101 return load_driver()->pSetCursorPos( x, y );
1104 static BOOL loaderdrv_ClipCursor( const RECT *clip )
1106 return load_driver()->pClipCursor( clip );
1109 static LRESULT nulldrv_ClipboardWindowProc( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam )
1111 return 0;
1114 static void loaderdrv_UpdateClipboard(void)
1116 load_driver()->pUpdateClipboard();
1119 static BOOL loaderdrv_UpdateDisplayDevices( const struct gdi_device_manager *manager, BOOL force, void *param )
1121 return load_driver()->pUpdateDisplayDevices( manager, force, param );
1124 static BOOL loaderdrv_CreateDesktopWindow( HWND hwnd )
1126 return load_driver()->pCreateDesktopWindow( hwnd );
1129 static BOOL loaderdrv_CreateWindow( HWND hwnd )
1131 return load_driver()->pCreateWindow( hwnd );
1134 static void loaderdrv_GetDC( HDC hdc, HWND hwnd, HWND top_win, const RECT *win_rect,
1135 const RECT *top_rect, DWORD flags )
1137 load_driver()->pGetDC( hdc, hwnd, top_win, win_rect, top_rect, flags );
1140 static void loaderdrv_FlashWindowEx( FLASHWINFO *info )
1142 load_driver()->pFlashWindowEx( info );
1145 static void loaderdrv_SetLayeredWindowAttributes( HWND hwnd, COLORREF key, BYTE alpha, DWORD flags )
1147 load_driver()->pSetLayeredWindowAttributes( hwnd, key, alpha, flags );
1150 static void loaderdrv_SetWindowRgn( HWND hwnd, HRGN hrgn, BOOL redraw )
1152 load_driver()->pSetWindowRgn( hwnd, hrgn, redraw );
1155 static BOOL loaderdrv_UpdateLayeredWindow( HWND hwnd, const UPDATELAYEREDWINDOWINFO *info,
1156 const RECT *window_rect )
1158 return load_driver()->pUpdateLayeredWindow( hwnd, info, window_rect );
1161 static const struct vulkan_funcs * loaderdrv_wine_get_vulkan_driver( UINT version )
1163 return load_driver()->pwine_get_vulkan_driver( version );
1166 static const struct user_driver_funcs lazy_load_driver =
1168 { NULL },
1169 /* keyboard functions */
1170 loaderdrv_ActivateKeyboardLayout,
1171 loaderdrv_Beep,
1172 loaderdrv_GetKeyNameText,
1173 loaderdrv_GetKeyboardLayoutList,
1174 loaderdrv_MapVirtualKeyEx,
1175 loaderdrv_RegisterHotKey,
1176 loaderdrv_ToUnicodeEx,
1177 loaderdrv_UnregisterHotKey,
1178 loaderdrv_VkKeyScanEx,
1179 /* cursor/icon functions */
1180 nulldrv_DestroyCursorIcon,
1181 loaderdrv_SetCursor,
1182 loaderdrv_GetCursorPos,
1183 loaderdrv_SetCursorPos,
1184 loaderdrv_ClipCursor,
1185 /* clipboard functions */
1186 nulldrv_ClipboardWindowProc,
1187 loaderdrv_UpdateClipboard,
1188 /* display modes */
1189 loaderdrv_ChangeDisplaySettings,
1190 loaderdrv_GetCurrentDisplaySettings,
1191 loaderdrv_GetDisplayDepth,
1192 loaderdrv_UpdateDisplayDevices,
1193 /* windowing functions */
1194 loaderdrv_CreateDesktopWindow,
1195 loaderdrv_CreateWindow,
1196 nulldrv_DesktopWindowProc,
1197 nulldrv_DestroyWindow,
1198 loaderdrv_FlashWindowEx,
1199 loaderdrv_GetDC,
1200 nulldrv_ProcessEvents,
1201 nulldrv_ReleaseDC,
1202 nulldrv_ScrollDC,
1203 nulldrv_SetCapture,
1204 nulldrv_SetFocus,
1205 loaderdrv_SetLayeredWindowAttributes,
1206 nulldrv_SetParent,
1207 loaderdrv_SetWindowRgn,
1208 nulldrv_SetWindowIcon,
1209 nulldrv_SetWindowStyle,
1210 nulldrv_SetWindowText,
1211 nulldrv_ShowWindow,
1212 nulldrv_SysCommand,
1213 loaderdrv_UpdateLayeredWindow,
1214 nulldrv_WindowMessage,
1215 nulldrv_WindowPosChanging,
1216 nulldrv_WindowPosChanged,
1217 /* system parameters */
1218 nulldrv_SystemParametersInfo,
1219 /* vulkan support */
1220 loaderdrv_wine_get_vulkan_driver,
1221 /* opengl support */
1222 nulldrv_wine_get_wgl_driver,
1223 /* thread management */
1224 nulldrv_ThreadDetach,
1227 const struct user_driver_funcs *user_driver = &lazy_load_driver;
1229 /******************************************************************************
1230 * __wine_set_user_driver (win32u.so)
1232 void __wine_set_user_driver( const struct user_driver_funcs *funcs, UINT version )
1234 struct user_driver_funcs *driver, *prev;
1236 if (version != WINE_GDI_DRIVER_VERSION)
1238 ERR( "version mismatch, driver wants %u but win32u has %u\n",
1239 version, WINE_GDI_DRIVER_VERSION );
1240 return;
1243 driver = malloc( sizeof(*driver) );
1244 *driver = funcs ? *funcs : null_user_driver;
1246 #define SET_USER_FUNC(name) \
1247 do { if (!driver->p##name) driver->p##name = nulldrv_##name; } while(0)
1249 SET_USER_FUNC(ActivateKeyboardLayout);
1250 SET_USER_FUNC(Beep);
1251 SET_USER_FUNC(GetKeyNameText);
1252 SET_USER_FUNC(GetKeyboardLayoutList);
1253 SET_USER_FUNC(MapVirtualKeyEx);
1254 SET_USER_FUNC(RegisterHotKey);
1255 SET_USER_FUNC(ToUnicodeEx);
1256 SET_USER_FUNC(UnregisterHotKey);
1257 SET_USER_FUNC(VkKeyScanEx);
1258 SET_USER_FUNC(DestroyCursorIcon);
1259 SET_USER_FUNC(SetCursor);
1260 SET_USER_FUNC(GetCursorPos);
1261 SET_USER_FUNC(SetCursorPos);
1262 SET_USER_FUNC(ClipCursor);
1263 SET_USER_FUNC(ClipboardWindowProc);
1264 SET_USER_FUNC(UpdateClipboard);
1265 SET_USER_FUNC(ChangeDisplaySettings);
1266 SET_USER_FUNC(GetCurrentDisplaySettings);
1267 SET_USER_FUNC(GetDisplayDepth);
1268 SET_USER_FUNC(UpdateDisplayDevices);
1269 SET_USER_FUNC(CreateDesktopWindow);
1270 SET_USER_FUNC(CreateWindow);
1271 SET_USER_FUNC(DesktopWindowProc);
1272 SET_USER_FUNC(DestroyWindow);
1273 SET_USER_FUNC(FlashWindowEx);
1274 SET_USER_FUNC(GetDC);
1275 SET_USER_FUNC(ProcessEvents);
1276 SET_USER_FUNC(ReleaseDC);
1277 SET_USER_FUNC(ScrollDC);
1278 SET_USER_FUNC(SetCapture);
1279 SET_USER_FUNC(SetFocus);
1280 SET_USER_FUNC(SetLayeredWindowAttributes);
1281 SET_USER_FUNC(SetParent);
1282 SET_USER_FUNC(SetWindowRgn);
1283 SET_USER_FUNC(SetWindowIcon);
1284 SET_USER_FUNC(SetWindowStyle);
1285 SET_USER_FUNC(SetWindowText);
1286 SET_USER_FUNC(ShowWindow);
1287 SET_USER_FUNC(SysCommand);
1288 SET_USER_FUNC(UpdateLayeredWindow);
1289 SET_USER_FUNC(WindowMessage);
1290 SET_USER_FUNC(WindowPosChanging);
1291 SET_USER_FUNC(WindowPosChanged);
1292 SET_USER_FUNC(SystemParametersInfo);
1293 SET_USER_FUNC(wine_get_vulkan_driver);
1294 SET_USER_FUNC(wine_get_wgl_driver);
1295 SET_USER_FUNC(ThreadDetach);
1296 #undef SET_USER_FUNC
1298 prev = InterlockedCompareExchangePointer( (void **)&user_driver, driver, (void *)&lazy_load_driver );
1299 if (prev != &lazy_load_driver)
1301 /* another thread beat us to it */
1302 free( driver );
1303 driver = prev;
1307 /******************************************************************************
1308 * NtGdiExtEscape (win32u.@)
1310 * Access capabilities of a particular device that are not available through GDI.
1312 INT WINAPI NtGdiExtEscape( HDC hdc, WCHAR *driver, int driver_id, INT escape, INT input_size,
1313 const char *input, INT output_size, char *output )
1315 PHYSDEV physdev;
1316 INT ret;
1317 DC * dc = get_dc_ptr( hdc );
1319 if (!dc) return 0;
1320 update_dc( dc );
1321 physdev = GET_DC_PHYSDEV( dc, pExtEscape );
1322 ret = physdev->funcs->pExtEscape( physdev, escape, input_size, input, output_size, output );
1323 release_dc_ptr( dc );
1324 return ret;
1328 /******************************************************************************
1329 * NtGdiDdDDIOpenAdapterFromHdc (win32u.@)
1331 NTSTATUS WINAPI NtGdiDdDDIOpenAdapterFromHdc( D3DKMT_OPENADAPTERFROMHDC *desc )
1333 FIXME( "(%p): stub\n", desc );
1334 return STATUS_NO_MEMORY;
1337 /******************************************************************************
1338 * NtGdiDdDDIEscape (win32u.@)
1340 NTSTATUS WINAPI NtGdiDdDDIEscape( const D3DKMT_ESCAPE *desc )
1342 FIXME( "(%p): stub\n", desc );
1343 return STATUS_NO_MEMORY;
1346 /******************************************************************************
1347 * NtGdiDdDDICloseAdapter (win32u.@)
1349 NTSTATUS WINAPI NtGdiDdDDICloseAdapter( const D3DKMT_CLOSEADAPTER *desc )
1351 NTSTATUS status = STATUS_INVALID_PARAMETER;
1352 struct d3dkmt_adapter *adapter;
1354 TRACE("(%p)\n", desc);
1356 if (!desc || !desc->hAdapter)
1357 return STATUS_INVALID_PARAMETER;
1359 if (get_display_driver()->pD3DKMTCloseAdapter)
1360 get_display_driver()->pD3DKMTCloseAdapter( desc );
1362 pthread_mutex_lock( &driver_lock );
1363 LIST_FOR_EACH_ENTRY( adapter, &d3dkmt_adapters, struct d3dkmt_adapter, entry )
1365 if (adapter->handle == desc->hAdapter)
1367 list_remove( &adapter->entry );
1368 free( adapter );
1369 status = STATUS_SUCCESS;
1370 break;
1373 pthread_mutex_unlock( &driver_lock );
1375 return status;
1378 /******************************************************************************
1379 * NtGdiDdDDIOpenAdapterFromDeviceName (win32u.@)
1381 NTSTATUS WINAPI NtGdiDdDDIOpenAdapterFromDeviceName( D3DKMT_OPENADAPTERFROMDEVICENAME *desc )
1383 D3DKMT_OPENADAPTERFROMLUID desc_luid;
1384 NTSTATUS status;
1386 FIXME( "desc %p stub.\n", desc );
1388 if (!desc || !desc->pDeviceName) return STATUS_INVALID_PARAMETER;
1390 memset( &desc_luid, 0, sizeof( desc_luid ));
1391 if ((status = NtGdiDdDDIOpenAdapterFromLuid( &desc_luid ))) return status;
1393 desc->AdapterLuid = desc_luid.AdapterLuid;
1394 desc->hAdapter = desc_luid.hAdapter;
1395 return STATUS_SUCCESS;
1398 /******************************************************************************
1399 * NtGdiDdDDIOpenAdapterFromLuid (win32u.@)
1401 NTSTATUS WINAPI NtGdiDdDDIOpenAdapterFromLuid( D3DKMT_OPENADAPTERFROMLUID *desc )
1403 static D3DKMT_HANDLE handle_start = 0;
1404 struct d3dkmt_adapter *adapter;
1406 if (!(adapter = malloc( sizeof( *adapter ) ))) return STATUS_NO_MEMORY;
1408 pthread_mutex_lock( &driver_lock );
1409 desc->hAdapter = adapter->handle = ++handle_start;
1410 list_add_tail( &d3dkmt_adapters, &adapter->entry );
1411 pthread_mutex_unlock( &driver_lock );
1413 if (get_display_driver()->pD3DKMTOpenAdapterFromLuid)
1414 get_display_driver()->pD3DKMTOpenAdapterFromLuid( desc );
1416 return STATUS_SUCCESS;
1419 /******************************************************************************
1420 * NtGdiDdDDICreateDevice (win32u.@)
1422 NTSTATUS WINAPI NtGdiDdDDICreateDevice( D3DKMT_CREATEDEVICE *desc )
1424 static D3DKMT_HANDLE handle_start = 0;
1425 struct d3dkmt_adapter *adapter;
1426 struct d3dkmt_device *device;
1427 BOOL found = FALSE;
1429 TRACE("(%p)\n", desc);
1431 if (!desc)
1432 return STATUS_INVALID_PARAMETER;
1434 pthread_mutex_lock( &driver_lock );
1435 LIST_FOR_EACH_ENTRY( adapter, &d3dkmt_adapters, struct d3dkmt_adapter, entry )
1437 if (adapter->handle == desc->hAdapter)
1439 found = TRUE;
1440 break;
1443 pthread_mutex_unlock( &driver_lock );
1445 if (!found)
1446 return STATUS_INVALID_PARAMETER;
1448 if (desc->Flags.LegacyMode || desc->Flags.RequestVSync || desc->Flags.DisableGpuTimeout)
1449 FIXME("Flags unsupported.\n");
1451 device = calloc( 1, sizeof( *device ) );
1452 if (!device)
1453 return STATUS_NO_MEMORY;
1455 pthread_mutex_lock( &driver_lock );
1456 device->handle = ++handle_start;
1457 list_add_tail( &d3dkmt_devices, &device->entry );
1458 pthread_mutex_unlock( &driver_lock );
1460 desc->hDevice = device->handle;
1461 return STATUS_SUCCESS;
1464 /******************************************************************************
1465 * NtGdiDdDDIDestroyDevice (win32u.@)
1467 NTSTATUS WINAPI NtGdiDdDDIDestroyDevice( const D3DKMT_DESTROYDEVICE *desc )
1469 NTSTATUS status = STATUS_INVALID_PARAMETER;
1470 D3DKMT_SETVIDPNSOURCEOWNER set_owner_desc;
1471 struct d3dkmt_device *device;
1473 TRACE("(%p)\n", desc);
1475 if (!desc || !desc->hDevice)
1476 return STATUS_INVALID_PARAMETER;
1478 pthread_mutex_lock( &driver_lock );
1479 LIST_FOR_EACH_ENTRY( device, &d3dkmt_devices, struct d3dkmt_device, entry )
1481 if (device->handle == desc->hDevice)
1483 memset( &set_owner_desc, 0, sizeof(set_owner_desc) );
1484 set_owner_desc.hDevice = desc->hDevice;
1485 NtGdiDdDDISetVidPnSourceOwner( &set_owner_desc );
1486 list_remove( &device->entry );
1487 free( device );
1488 status = STATUS_SUCCESS;
1489 break;
1492 pthread_mutex_unlock( &driver_lock );
1494 return status;
1497 /******************************************************************************
1498 * NtGdiDdDDIQueryStatistics (win32u.@)
1500 NTSTATUS WINAPI NtGdiDdDDIQueryStatistics( D3DKMT_QUERYSTATISTICS *stats )
1502 FIXME("(%p): stub\n", stats);
1503 return STATUS_SUCCESS;
1506 /******************************************************************************
1507 * NtGdiDdDDIQueryVideoMemoryInfo (win32u.@)
1509 NTSTATUS WINAPI NtGdiDdDDIQueryVideoMemoryInfo( D3DKMT_QUERYVIDEOMEMORYINFO *desc )
1511 OBJECT_BASIC_INFORMATION info;
1512 NTSTATUS status;
1514 TRACE("(%p)\n", desc);
1516 if (!desc || !desc->hAdapter ||
1517 (desc->MemorySegmentGroup != D3DKMT_MEMORY_SEGMENT_GROUP_LOCAL &&
1518 desc->MemorySegmentGroup != D3DKMT_MEMORY_SEGMENT_GROUP_NON_LOCAL))
1519 return STATUS_INVALID_PARAMETER;
1521 /* FIXME: Wine currently doesn't support linked adapters */
1522 if (desc->PhysicalAdapterIndex > 0)
1523 return STATUS_INVALID_PARAMETER;
1525 status = NtQueryObject(desc->hProcess ? desc->hProcess : GetCurrentProcess(),
1526 ObjectBasicInformation, &info, sizeof(info), NULL);
1527 if (status != STATUS_SUCCESS)
1528 return status;
1529 if (!(info.GrantedAccess & PROCESS_QUERY_INFORMATION))
1530 return STATUS_ACCESS_DENIED;
1532 if (!get_display_driver()->pD3DKMTQueryVideoMemoryInfo)
1533 return STATUS_PROCEDURE_NOT_FOUND;
1534 return get_display_driver()->pD3DKMTQueryVideoMemoryInfo(desc);
1537 /******************************************************************************
1538 * NtGdiDdDDISetQueuedLimit (win32u.@)
1540 NTSTATUS WINAPI NtGdiDdDDISetQueuedLimit( D3DKMT_SETQUEUEDLIMIT *desc )
1542 FIXME( "(%p): stub\n", desc );
1543 return STATUS_NOT_IMPLEMENTED;
1546 /******************************************************************************
1547 * NtGdiDdDDISetVidPnSourceOwner (win32u.@)
1549 NTSTATUS WINAPI NtGdiDdDDISetVidPnSourceOwner( const D3DKMT_SETVIDPNSOURCEOWNER *desc )
1551 TRACE("(%p)\n", desc);
1553 if (!get_display_driver()->pD3DKMTSetVidPnSourceOwner)
1554 return STATUS_PROCEDURE_NOT_FOUND;
1556 if (!desc || !desc->hDevice || (desc->VidPnSourceCount && (!desc->pType || !desc->pVidPnSourceId)))
1557 return STATUS_INVALID_PARAMETER;
1559 /* Store the VidPN source ownership info in the graphics driver because
1560 * the graphics driver needs to change ownership sometimes. For example,
1561 * when a new window is moved to a VidPN source with an exclusive owner,
1562 * such an exclusive owner will be released before showing the new window */
1563 return get_display_driver()->pD3DKMTSetVidPnSourceOwner( desc );
1566 /******************************************************************************
1567 * NtGdiDdDDICheckVidPnExclusiveOwnership (win32u.@)
1569 NTSTATUS WINAPI NtGdiDdDDICheckVidPnExclusiveOwnership( const D3DKMT_CHECKVIDPNEXCLUSIVEOWNERSHIP *desc )
1571 TRACE("(%p)\n", desc);
1573 if (!get_display_driver()->pD3DKMTCheckVidPnExclusiveOwnership)
1574 return STATUS_PROCEDURE_NOT_FOUND;
1576 if (!desc || !desc->hAdapter)
1577 return STATUS_INVALID_PARAMETER;
1579 return get_display_driver()->pD3DKMTCheckVidPnExclusiveOwnership( desc );