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 "stw_winsys.h" 41#include "stw_device.h" 42#include "gdi/gdi_sw_winsys.h" 43 44#include "softpipe/sp_texture.h" 45#include "softpipe/sp_screen.h" 46#include "softpipe/sp_public.h" 47 48#ifdef HAVE_LLVMPIPE 49#include "llvmpipe/lp_texture.h" 50#include "llvmpipe/lp_screen.h" 51#include "llvmpipe/lp_public.h" 52#endif 53 54#ifdef HAVE_SWR 55#include "swr/swr_public.h" 56#endif 57 58static boolean use_llvmpipe = FALSE; 59static boolean use_swr = FALSE; 60 61static struct pipe_screen * 62gdi_screen_create(void) 63{ 64 const char *default_driver; 65 const char *driver; 66 struct pipe_screen *screen = NULL; 67 struct sw_winsys *winsys; 68 69 winsys = gdi_create_sw_winsys(); 70 if(!winsys) 71 goto no_winsys; 72 73#ifdef HAVE_LLVMPIPE 74 default_driver = "llvmpipe"; 75#elif HAVE_SWR 76 default_driver = "swr"; 77#else 78 default_driver = "softpipe"; 79#endif 80 81 driver = debug_get_option("GALLIUM_DRIVER", default_driver); 82 83#ifdef HAVE_LLVMPIPE 84 if (strcmp(driver, "llvmpipe") == 0) { 85 screen = llvmpipe_create_screen( winsys ); 86 if (screen) 87 use_llvmpipe = TRUE; 88 } 89#endif 90#ifdef HAVE_SWR 91 if (strcmp(driver, "swr") == 0) { 92 screen = swr_create_screen( winsys ); 93 if (screen) 94 use_swr = TRUE; 95 } 96#endif 97 (void) driver; 98 99 if (screen == NULL) { 100 screen = softpipe_create_screen( winsys ); 101 } 102 103 if(!screen) 104 goto no_screen; 105 106 return screen; 107 108no_screen: 109 winsys->destroy(winsys); 110no_winsys: 111 return NULL; 112} 113 114 115static void 116gdi_present(struct pipe_screen *screen, 117 struct pipe_resource *res, 118 HDC hDC) 119{ 120 /* This will fail if any interposing layer (trace, debug, etc) has 121 * been introduced between the state-trackers and the pipe driver. 122 * 123 * Ideally this would get replaced with a call to 124 * pipe_screen::flush_frontbuffer(). 125 * 126 * Failing that, it may be necessary for intervening layers to wrap 127 * other structs such as this stw_winsys as well... 128 */ 129 130 struct sw_winsys *winsys = NULL; 131 struct sw_displaytarget *dt = NULL; 132 133#ifdef HAVE_LLVMPIPE 134 if (use_llvmpipe) { 135 winsys = llvmpipe_screen(screen)->winsys; 136 dt = llvmpipe_resource(res)->dt; 137 gdi_sw_display(winsys, dt, hDC); 138 return; 139 } 140#endif 141 142#ifdef HAVE_SWR 143 if (use_swr) { 144 swr_gdi_swap(screen, res, hDC); 145 return; 146 } 147#endif 148 149 winsys = softpipe_screen(screen)->winsys, 150 dt = softpipe_resource(res)->dt, 151 gdi_sw_display(winsys, dt, hDC); 152} 153 154 155static const struct stw_winsys stw_winsys = { 156 &gdi_screen_create, 157 &gdi_present, 158 NULL, /* get_adapter_luid */ 159 NULL, /* shared_surface_open */ 160 NULL, /* shared_surface_close */ 161 NULL /* compose */ 162}; 163 164 165EXTERN_C BOOL WINAPI 166DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved); 167 168 169BOOL WINAPI 170DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) 171{ 172 switch (fdwReason) { 173 case DLL_PROCESS_ATTACH: 174 stw_init(&stw_winsys); 175 stw_init_thread(); 176 break; 177 178 case DLL_THREAD_ATTACH: 179 stw_init_thread(); 180 break; 181 182 case DLL_THREAD_DETACH: 183 stw_cleanup_thread(); 184 break; 185 186 case DLL_PROCESS_DETACH: 187 if (lpvReserved == NULL) { 188 // We're being unloaded from the process. 189 stw_cleanup_thread(); 190 stw_cleanup(); 191 } else { 192 // Process itself is terminating, and all threads and modules are 193 // being detached. 194 // 195 // The order threads (including llvmpipe rasterizer threads) are 196 // destroyed can not be relied up, so it's not safe to cleanup. 197 // 198 // However global destructors (e.g., LLVM's) will still be called, and 199 // if Microsoft OPENGL32.DLL's DllMain is called after us, it will 200 // still try to invoke DrvDeleteContext to destroys all outstanding, 201 // so set stw_dev to NULL to return immediately if that happens. 202 stw_dev = NULL; 203 } 204 break; 205 } 206 return TRUE; 207} 208