1 /*
2  * Copyright © Microsoft Corporation
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice (including the next
12  * paragraph) shall be included in all copies or substantial portions of the
13  * Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21  * IN THE SOFTWARE.
22  */
23 
24 
25 #include <windows.h>
26 
27 #include "util/u_debug.h"
28 #include "stw_winsys.h"
29 #include "stw_device.h"
30 #include "gdi/gdi_sw_winsys.h"
31 
32 #include "softpipe/sp_texture.h"
33 #include "softpipe/sp_screen.h"
34 #include "softpipe/sp_public.h"
35 
36 #ifndef GALLIUM_D3D12
37 #error "This file must be compiled only with the D3D12 driver"
38 #endif
39 #include "d3d12/wgl/d3d12_wgl_public.h"
40 
41 static struct pipe_screen *
gdi_screen_create(HDC hDC)42 gdi_screen_create(HDC hDC)
43 {
44    struct pipe_screen *screen = NULL;
45    struct sw_winsys *winsys;
46 
47    winsys = gdi_create_sw_winsys();
48    if(!winsys)
49       goto no_winsys;
50 
51    screen = d3d12_wgl_create_screen( winsys, hDC );
52 
53    if(!screen)
54       goto no_screen;
55 
56    return screen;
57 
58 no_screen:
59    winsys->destroy(winsys);
60 no_winsys:
61    return NULL;
62 }
63 
64 
65 static void
gdi_present(struct pipe_screen * screen,struct pipe_context * context,struct pipe_resource * res,HDC hDC)66 gdi_present(struct pipe_screen *screen,
67             struct pipe_context *context,
68             struct pipe_resource *res,
69             HDC hDC)
70 {
71    d3d12_wgl_present(screen, context, res, hDC);
72 }
73 
74 
75 static boolean
gdi_get_adapter_luid(struct pipe_screen * screen,HDC hDC,LUID * adapter_luid)76 gdi_get_adapter_luid(struct pipe_screen *screen,
77                      HDC hDC,
78                      LUID *adapter_luid)
79 {
80    if (!stw_dev || !stw_dev->callbacks.pfnGetAdapterLuid)
81       return false;
82 
83    stw_dev->callbacks.pfnGetAdapterLuid(hDC, adapter_luid);
84    return true;
85 }
86 
87 
88 static unsigned
gdi_get_pfd_flags(struct pipe_screen * screen)89 gdi_get_pfd_flags(struct pipe_screen *screen)
90 {
91    return d3d12_wgl_get_pfd_flags(screen);
92 }
93 
94 
95 static struct stw_winsys_framebuffer *
gdi_create_framebuffer(struct pipe_screen * screen,HWND hWnd,int iPixelFormat)96 gdi_create_framebuffer(struct pipe_screen *screen,
97                        HWND hWnd,
98                        int iPixelFormat)
99 {
100    return d3d12_wgl_create_framebuffer(screen, hWnd, iPixelFormat);
101 }
102 
103 static const char *
get_name(void)104 get_name(void)
105 {
106    return "d3d12";
107 }
108 
109 static const struct stw_winsys stw_winsys = {
110    &gdi_screen_create,
111    &gdi_present,
112    &gdi_get_adapter_luid,
113    NULL, /* shared_surface_open */
114    NULL, /* shared_surface_close */
115    NULL, /* compose */
116    &gdi_get_pfd_flags,
117    &gdi_create_framebuffer,
118    &get_name,
119 };
120 
121 
122 EXTERN_C BOOL WINAPI
123 DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved);
124 
125 
126 BOOL WINAPI
DllMain(HINSTANCE hinstDLL,DWORD fdwReason,LPVOID lpvReserved)127 DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
128 {
129    switch (fdwReason) {
130    case DLL_PROCESS_ATTACH:
131       stw_init(&stw_winsys);
132       stw_init_thread();
133       break;
134 
135    case DLL_THREAD_ATTACH:
136       stw_init_thread();
137       break;
138 
139    case DLL_THREAD_DETACH:
140       stw_cleanup_thread();
141       break;
142 
143    case DLL_PROCESS_DETACH:
144       if (lpvReserved == NULL) {
145          // We're being unloaded from the process.
146          stw_cleanup_thread();
147          stw_cleanup();
148       } else {
149          // Process itself is terminating, and all threads and modules are
150          // being detached.
151          //
152          // The order threads (including llvmpipe rasterizer threads) are
153          // destroyed can not be relied up, so it's not safe to cleanup.
154          //
155          // However global destructors (e.g., LLVM's) will still be called, and
156          // if Microsoft OPENGL32.DLL's DllMain is called after us, it will
157          // still try to invoke DrvDeleteContext to destroys all outstanding,
158          // so set stw_dev to NULL to return immediately if that happens.
159          stw_dev = NULL;
160       }
161       break;
162    }
163    return TRUE;
164 }
165