wgl.c revision 7ec681f3
1/************************************************************************** 2 * 3 * Copyright 2009-2010 VMware, Inc. 4 * All Rights Reserved. 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining a 7 * copy of this software and associated documentation files (the 8 * "Software"), to deal in the Software without restriction, including 9 * without limitation the rights to use, copy, modify, merge, publish, 10 * distribute, sub license, and/or sell copies of the Software, and to 11 * permit persons to whom the Software is furnished to do so, subject to 12 * the following conditions: 13 * 14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL 17 * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, 18 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 19 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 20 * USE OR OTHER DEALINGS IN THE SOFTWARE. 21 * 22 * The above copyright notice and this permission notice (including the 23 * next paragraph) shall be included in all copies or substantial portions 24 * of the Software. 25 * 26 * 27 **************************************************************************/ 28 29/** 30 * @file 31 * Softpipe/LLVMpipe support. 32 * 33 * @author Jose Fonseca <jfonseca@vmware.com> 34 */ 35 36 37#include <windows.h> 38 39#include "util/u_debug.h" 40#include "util/debug.h" 41#include "stw_winsys.h" 42#include "stw_device.h" 43#include "gdi/gdi_sw_winsys.h" 44#include "pipe/p_screen.h" 45#include "pipe/p_context.h" 46 47#ifdef GALLIUM_SOFTPIPE 48#include "softpipe/sp_texture.h" 49#include "softpipe/sp_screen.h" 50#include "softpipe/sp_public.h" 51#endif 52 53#ifdef GALLIUM_LLVMPIPE 54#include "llvmpipe/lp_texture.h" 55#include "llvmpipe/lp_screen.h" 56#include "llvmpipe/lp_public.h" 57#endif 58 59#ifdef GALLIUM_SWR 60#include "swr/swr_public.h" 61#endif 62#ifdef GALLIUM_D3D12 63#include "d3d12/wgl/d3d12_wgl_public.h" 64#endif 65 66#ifdef GALLIUM_ZINK 67#include "zink/zink_public.h" 68#endif 69 70#ifdef GALLIUM_LLVMPIPE 71static boolean use_llvmpipe = FALSE; 72#endif 73#ifdef GALLIUM_SWR 74static boolean use_swr = FALSE; 75#endif 76#ifdef GALLIUM_D3D12 77static boolean use_d3d12 = FALSE; 78#endif 79#ifdef GALLIUM_ZINK 80static boolean use_zink = FALSE; 81#endif 82 83static const char *created_driver_name = NULL; 84 85static struct pipe_screen * 86wgl_screen_create_by_name(HDC hDC, const char* driver, struct sw_winsys *winsys) 87{ 88 struct pipe_screen* screen = NULL; 89 90#ifdef GALLIUM_LLVMPIPE 91 if (strcmp(driver, "llvmpipe") == 0) { 92 screen = llvmpipe_create_screen(winsys); 93 if (screen) 94 use_llvmpipe = TRUE; 95 } 96#endif 97#ifdef GALLIUM_SWR 98 if (strcmp(driver, "swr") == 0) { 99 screen = swr_create_screen(winsys); 100 if (screen) 101 use_swr = TRUE; 102 } 103#endif 104#ifdef GALLIUM_D3D12 105 if (strcmp(driver, "d3d12") == 0) { 106 screen = d3d12_wgl_create_screen(winsys, hDC); 107 if (screen) 108 use_d3d12 = TRUE; 109 } 110#endif 111#ifdef GALLIUM_ZINK 112 if (strcmp(driver, "zink") == 0) { 113 screen = zink_create_screen(winsys); 114 if (screen) 115 use_zink = TRUE; 116 } 117#endif 118#ifdef GALLIUM_SOFTPIPE 119 if (strcmp(driver, "softpipe") == 0) { 120 screen = softpipe_create_screen(winsys); 121 } 122#endif 123 124 return screen; 125} 126 127static struct pipe_screen * 128wgl_screen_create(HDC hDC) 129{ 130 struct sw_winsys *winsys; 131 UNUSED bool sw_only = env_var_as_boolean("LIBGL_ALWAYS_SOFTWARE", false); 132 133 winsys = gdi_create_sw_winsys(); 134 if (!winsys) 135 return NULL; 136 137 const char *const drivers[] = { 138 debug_get_option("GALLIUM_DRIVER", ""), 139#ifdef GALLIUM_D3D12 140 sw_only ? "" : "d3d12", 141#endif 142#if defined(GALLIUM_LLVMPIPE) 143 "llvmpipe", 144#endif 145#if GALLIUM_SWR 146 "swr", 147#endif 148#if defined(GALLIUM_SOFTPIPE) 149 "softpipe", 150#endif 151 }; 152 153 /* If the default driver screen creation fails, fall back to the next option in the 154 * sorted list. Don't do this if GALLIUM_DRIVER is specified. 155 */ 156 for (unsigned i = 0; i < ARRAY_SIZE(drivers); ++i) { 157 struct pipe_screen* screen = wgl_screen_create_by_name(hDC, drivers[i], winsys); 158 if (screen) { 159 created_driver_name = drivers[i]; 160 return screen; 161 } 162 if (i == 0 && drivers[i][0] != '\0') 163 break; 164 } 165 166 winsys->destroy(winsys); 167 return NULL; 168} 169 170 171static void 172wgl_present(struct pipe_screen *screen, 173 struct pipe_context *ctx, 174 struct pipe_resource *res, 175 HDC hDC) 176{ 177 /* This will fail if any interposing layer (trace, debug, etc) has 178 * been introduced between the gallium frontends and the pipe driver. 179 * 180 * Ideally this would get replaced with a call to 181 * pipe_screen::flush_frontbuffer(). 182 * 183 * Failing that, it may be necessary for intervening layers to wrap 184 * other structs such as this stw_winsys as well... 185 */ 186 187 struct sw_winsys *winsys = NULL; 188 struct sw_displaytarget *dt = NULL; 189 190#ifdef GALLIUM_LLVMPIPE 191 if (use_llvmpipe) { 192 winsys = llvmpipe_screen(screen)->winsys; 193 dt = llvmpipe_resource(res)->dt; 194 gdi_sw_display(winsys, dt, hDC); 195 return; 196 } 197#endif 198 199#ifdef GALLIUM_SWR 200 if (use_swr) { 201 swr_gdi_swap(screen, ctx, res, hDC); 202 return; 203 } 204#endif 205 206#ifdef GALLIUM_D3D12 207 if (use_d3d12) { 208 d3d12_wgl_present(screen, ctx, res, hDC); 209 return; 210 } 211#endif 212 213#ifdef GALLIUM_ZINK 214 if (use_zink) { 215 screen->flush_frontbuffer(screen, ctx, res, 0, 0, hDC, NULL); 216 return; 217 } 218#endif 219 220#ifdef GALLIUM_SOFTPIPE 221 winsys = softpipe_screen(screen)->winsys, 222 dt = softpipe_resource(res)->dt, 223 gdi_sw_display(winsys, dt, hDC); 224#endif 225} 226 227 228#if WINVER >= 0xA00 229static boolean 230wgl_get_adapter_luid(struct pipe_screen* screen, 231 HDC hDC, 232 LUID* adapter_luid) 233{ 234 if (!stw_dev || !stw_dev->callbacks.pfnGetAdapterLuid) 235 return false; 236 237 stw_dev->callbacks.pfnGetAdapterLuid(hDC, adapter_luid); 238 return true; 239} 240#endif 241 242 243static unsigned 244wgl_get_pfd_flags(struct pipe_screen *screen) 245{ 246#ifdef GALLIUM_D3D12 247 if (use_d3d12) 248 return d3d12_wgl_get_pfd_flags(screen); 249#endif 250 return stw_pfd_gdi_support; 251} 252 253 254static struct stw_winsys_framebuffer * 255wgl_create_framebuffer(struct pipe_screen *screen, 256 HWND hWnd, 257 int iPixelFormat) 258{ 259#ifdef GALLIUM_D3D12 260 if (use_d3d12) 261 return d3d12_wgl_create_framebuffer(screen, hWnd, iPixelFormat); 262#endif 263 return NULL; 264} 265 266static const char * 267wgl_get_name(void) 268{ 269 return created_driver_name; 270} 271 272 273static const struct stw_winsys stw_winsys = { 274 &wgl_screen_create, 275 &wgl_present, 276#if WINVER >= 0xA00 277 &wgl_get_adapter_luid, 278#else 279 NULL, /* get_adapter_luid */ 280#endif 281 NULL, /* shared_surface_open */ 282 NULL, /* shared_surface_close */ 283 NULL, /* compose */ 284 &wgl_get_pfd_flags, 285 &wgl_create_framebuffer, 286 &wgl_get_name, 287}; 288 289 290EXTERN_C BOOL WINAPI 291DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved); 292 293 294BOOL WINAPI 295DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) 296{ 297 switch (fdwReason) { 298 case DLL_PROCESS_ATTACH: 299 stw_init(&stw_winsys); 300 stw_init_thread(); 301 break; 302 303 case DLL_THREAD_ATTACH: 304 stw_init_thread(); 305 break; 306 307 case DLL_THREAD_DETACH: 308 stw_cleanup_thread(); 309 break; 310 311 case DLL_PROCESS_DETACH: 312 if (lpvReserved == NULL) { 313 // We're being unloaded from the process. 314 stw_cleanup_thread(); 315 stw_cleanup(); 316 } else { 317 // Process itself is terminating, and all threads and modules are 318 // being detached. 319 // 320 // The order threads (including llvmpipe rasterizer threads) are 321 // destroyed can not be relied up, so it's not safe to cleanup. 322 // 323 // However global destructors (e.g., LLVM's) will still be called, and 324 // if Microsoft OPENGL32.DLL's DllMain is called after us, it will 325 // still try to invoke DrvDeleteContext to destroys all outstanding, 326 // so set stw_dev to NULL to return immediately if that happens. 327 stw_dev = NULL; 328 } 329 break; 330 } 331 return TRUE; 332} 333