1bf215546Sopenharmony_ci/************************************************************************** 2bf215546Sopenharmony_ci * 3bf215546Sopenharmony_ci * Copyright 2008 VMware, Inc. 4bf215546Sopenharmony_ci * All Rights Reserved. 5bf215546Sopenharmony_ci * 6bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a 7bf215546Sopenharmony_ci * copy of this software and associated documentation files (the 8bf215546Sopenharmony_ci * "Software"), to deal in the Software without restriction, including 9bf215546Sopenharmony_ci * without limitation the rights to use, copy, modify, merge, publish, 10bf215546Sopenharmony_ci * distribute, sub license, and/or sell copies of the Software, and to 11bf215546Sopenharmony_ci * permit persons to whom the Software is furnished to do so, subject to 12bf215546Sopenharmony_ci * the following conditions: 13bf215546Sopenharmony_ci * 14bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the 15bf215546Sopenharmony_ci * next paragraph) shall be included in all copies or substantial portions 16bf215546Sopenharmony_ci * of the Software. 17bf215546Sopenharmony_ci * 18bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 19bf215546Sopenharmony_ci * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 20bf215546Sopenharmony_ci * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 21bf215546Sopenharmony_ci * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR 22bf215546Sopenharmony_ci * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 23bf215546Sopenharmony_ci * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 24bf215546Sopenharmony_ci * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 25bf215546Sopenharmony_ci * 26bf215546Sopenharmony_ci **************************************************************************/ 27bf215546Sopenharmony_ci 28bf215546Sopenharmony_ci#include <windows.h> 29bf215546Sopenharmony_ci 30bf215546Sopenharmony_ci#include "glapi/glapi.h" 31bf215546Sopenharmony_ci#include "util/debug.h" 32bf215546Sopenharmony_ci#include "util/u_debug.h" 33bf215546Sopenharmony_ci#include "util/u_math.h" 34bf215546Sopenharmony_ci#include "util/u_memory.h" 35bf215546Sopenharmony_ci#include "util/u_driconf.h" 36bf215546Sopenharmony_ci#include "util/driconf.h" 37bf215546Sopenharmony_ci#include "pipe/p_screen.h" 38bf215546Sopenharmony_ci 39bf215546Sopenharmony_ci#include "stw_device.h" 40bf215546Sopenharmony_ci#include "stw_winsys.h" 41bf215546Sopenharmony_ci#include "stw_pixelformat.h" 42bf215546Sopenharmony_ci#include "gldrv.h" 43bf215546Sopenharmony_ci#include "stw_tls.h" 44bf215546Sopenharmony_ci#include "stw_framebuffer.h" 45bf215546Sopenharmony_ci#include "stw_st.h" 46bf215546Sopenharmony_ci 47bf215546Sopenharmony_ci 48bf215546Sopenharmony_cistruct stw_device *stw_dev = NULL; 49bf215546Sopenharmony_ci 50bf215546Sopenharmony_cistatic int 51bf215546Sopenharmony_cistw_get_param(struct st_manager *smapi, 52bf215546Sopenharmony_ci enum st_manager_param param) 53bf215546Sopenharmony_ci{ 54bf215546Sopenharmony_ci switch (param) { 55bf215546Sopenharmony_ci case ST_MANAGER_BROKEN_INVALIDATE: 56bf215546Sopenharmony_ci /* 57bf215546Sopenharmony_ci * Force framebuffer validation on glViewport. 58bf215546Sopenharmony_ci * 59bf215546Sopenharmony_ci * Certain applications, like Rhinoceros 4, uses glReadPixels 60bf215546Sopenharmony_ci * exclusively (never uses SwapBuffers), so framebuffers never get 61bf215546Sopenharmony_ci * resized unless we check on glViewport. 62bf215546Sopenharmony_ci */ 63bf215546Sopenharmony_ci return 1; 64bf215546Sopenharmony_ci default: 65bf215546Sopenharmony_ci return 0; 66bf215546Sopenharmony_ci } 67bf215546Sopenharmony_ci} 68bf215546Sopenharmony_ci 69bf215546Sopenharmony_ci 70bf215546Sopenharmony_ci/** Get the refresh rate for the monitor, in Hz */ 71bf215546Sopenharmony_cistatic int 72bf215546Sopenharmony_ciget_refresh_rate(void) 73bf215546Sopenharmony_ci{ 74bf215546Sopenharmony_ci DEVMODE devModes; 75bf215546Sopenharmony_ci 76bf215546Sopenharmony_ci if (EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &devModes)) { 77bf215546Sopenharmony_ci /* clamp the value, just in case we get garbage */ 78bf215546Sopenharmony_ci return CLAMP(devModes.dmDisplayFrequency, 30, 120); 79bf215546Sopenharmony_ci } 80bf215546Sopenharmony_ci else { 81bf215546Sopenharmony_ci /* reasonable default */ 82bf215546Sopenharmony_ci return 60; 83bf215546Sopenharmony_ci } 84bf215546Sopenharmony_ci} 85bf215546Sopenharmony_ci 86bf215546Sopenharmony_cistatic bool 87bf215546Sopenharmony_ciinit_screen(const struct stw_winsys *stw_winsys, HDC hdc) 88bf215546Sopenharmony_ci{ 89bf215546Sopenharmony_ci struct pipe_screen *screen = stw_winsys->create_screen(hdc); 90bf215546Sopenharmony_ci if (!screen) 91bf215546Sopenharmony_ci return false; 92bf215546Sopenharmony_ci 93bf215546Sopenharmony_ci if (stw_winsys->get_adapter_luid) 94bf215546Sopenharmony_ci stw_winsys->get_adapter_luid(screen, hdc, &stw_dev->AdapterLuid); 95bf215546Sopenharmony_ci 96bf215546Sopenharmony_ci stw_dev->smapi->screen = screen; 97bf215546Sopenharmony_ci stw_dev->screen = screen; 98bf215546Sopenharmony_ci stw_dev->zink = !memcmp(screen->get_name(screen), "zink", 4); 99bf215546Sopenharmony_ci 100bf215546Sopenharmony_ci stw_dev->max_2d_length = screen->get_param(screen, 101bf215546Sopenharmony_ci PIPE_CAP_MAX_TEXTURE_2D_SIZE); 102bf215546Sopenharmony_ci return true; 103bf215546Sopenharmony_ci} 104bf215546Sopenharmony_ci 105bf215546Sopenharmony_cistatic void 106bf215546Sopenharmony_ciinit_options() 107bf215546Sopenharmony_ci{ 108bf215546Sopenharmony_ci const driOptionDescription gallium_driconf[] = { 109bf215546Sopenharmony_ci #include "pipe-loader/driinfo_gallium.h" 110bf215546Sopenharmony_ci }; 111bf215546Sopenharmony_ci 112bf215546Sopenharmony_ci const char *driver_name = stw_dev->stw_winsys->get_name ? stw_dev->stw_winsys->get_name() : NULL; 113bf215546Sopenharmony_ci driParseOptionInfo(&stw_dev->option_info, gallium_driconf, ARRAY_SIZE(gallium_driconf)); 114bf215546Sopenharmony_ci driParseConfigFiles(&stw_dev->option_cache, &stw_dev->option_info, 0, 115bf215546Sopenharmony_ci driver_name ? driver_name : "", NULL, NULL, NULL, 0, NULL, 0); 116bf215546Sopenharmony_ci 117bf215546Sopenharmony_ci u_driconf_fill_st_options(&stw_dev->st_options, &stw_dev->option_cache); 118bf215546Sopenharmony_ci} 119bf215546Sopenharmony_ci 120bf215546Sopenharmony_ciboolean 121bf215546Sopenharmony_cistw_init(const struct stw_winsys *stw_winsys) 122bf215546Sopenharmony_ci{ 123bf215546Sopenharmony_ci static struct stw_device stw_dev_storage; 124bf215546Sopenharmony_ci 125bf215546Sopenharmony_ci if (env_var_as_boolean("WGL_DISABLE_ERROR_DIALOGS", false)) 126bf215546Sopenharmony_ci debug_disable_win32_error_dialogs(); 127bf215546Sopenharmony_ci 128bf215546Sopenharmony_ci assert(!stw_dev); 129bf215546Sopenharmony_ci 130bf215546Sopenharmony_ci stw_tls_init(); 131bf215546Sopenharmony_ci 132bf215546Sopenharmony_ci stw_dev = &stw_dev_storage; 133bf215546Sopenharmony_ci memset(stw_dev, 0, sizeof(*stw_dev)); 134bf215546Sopenharmony_ci 135bf215546Sopenharmony_ci stw_dev->stw_winsys = stw_winsys; 136bf215546Sopenharmony_ci 137bf215546Sopenharmony_ci stw_dev->stapi = stw_st_create_api(); 138bf215546Sopenharmony_ci stw_dev->smapi = CALLOC_STRUCT(st_manager); 139bf215546Sopenharmony_ci if (!stw_dev->stapi || !stw_dev->smapi) 140bf215546Sopenharmony_ci goto error1; 141bf215546Sopenharmony_ci 142bf215546Sopenharmony_ci stw_dev->smapi->get_param = stw_get_param; 143bf215546Sopenharmony_ci 144bf215546Sopenharmony_ci InitializeCriticalSection(&stw_dev->screen_mutex); 145bf215546Sopenharmony_ci InitializeCriticalSection(&stw_dev->ctx_mutex); 146bf215546Sopenharmony_ci InitializeCriticalSection(&stw_dev->fb_mutex); 147bf215546Sopenharmony_ci 148bf215546Sopenharmony_ci stw_dev->ctx_table = handle_table_create(); 149bf215546Sopenharmony_ci if (!stw_dev->ctx_table) { 150bf215546Sopenharmony_ci goto error1; 151bf215546Sopenharmony_ci } 152bf215546Sopenharmony_ci 153bf215546Sopenharmony_ci /* env var override for WGL_EXT_swap_control, useful for testing/debugging */ 154bf215546Sopenharmony_ci const char *s = os_get_option("WGL_SWAP_INTERVAL"); 155bf215546Sopenharmony_ci if (s) { 156bf215546Sopenharmony_ci stw_dev->swap_interval = atoi(s); 157bf215546Sopenharmony_ci } 158bf215546Sopenharmony_ci stw_dev->refresh_rate = get_refresh_rate(); 159bf215546Sopenharmony_ci 160bf215546Sopenharmony_ci stw_dev->initialized = true; 161bf215546Sopenharmony_ci 162bf215546Sopenharmony_ci return TRUE; 163bf215546Sopenharmony_ci 164bf215546Sopenharmony_cierror1: 165bf215546Sopenharmony_ci FREE(stw_dev->smapi); 166bf215546Sopenharmony_ci if (stw_dev->stapi) 167bf215546Sopenharmony_ci stw_dev->stapi->destroy(stw_dev->stapi); 168bf215546Sopenharmony_ci 169bf215546Sopenharmony_ci stw_dev = NULL; 170bf215546Sopenharmony_ci return FALSE; 171bf215546Sopenharmony_ci} 172bf215546Sopenharmony_ci 173bf215546Sopenharmony_ciboolean 174bf215546Sopenharmony_cistw_init_screen(HDC hdc) 175bf215546Sopenharmony_ci{ 176bf215546Sopenharmony_ci EnterCriticalSection(&stw_dev->screen_mutex); 177bf215546Sopenharmony_ci 178bf215546Sopenharmony_ci if (!stw_dev->screen_initialized) { 179bf215546Sopenharmony_ci stw_dev->screen_initialized = true; 180bf215546Sopenharmony_ci if (!init_screen(stw_dev->stw_winsys, hdc)) { 181bf215546Sopenharmony_ci LeaveCriticalSection(&stw_dev->screen_mutex); 182bf215546Sopenharmony_ci return false; 183bf215546Sopenharmony_ci } 184bf215546Sopenharmony_ci init_options(); 185bf215546Sopenharmony_ci stw_pixelformat_init(); 186bf215546Sopenharmony_ci } 187bf215546Sopenharmony_ci 188bf215546Sopenharmony_ci LeaveCriticalSection(&stw_dev->screen_mutex); 189bf215546Sopenharmony_ci return stw_dev->screen != NULL; 190bf215546Sopenharmony_ci} 191bf215546Sopenharmony_ci 192bf215546Sopenharmony_cistruct stw_device * 193bf215546Sopenharmony_cistw_get_device(void) 194bf215546Sopenharmony_ci{ 195bf215546Sopenharmony_ci return stw_dev; 196bf215546Sopenharmony_ci} 197bf215546Sopenharmony_ci 198bf215546Sopenharmony_ciboolean 199bf215546Sopenharmony_cistw_init_thread(void) 200bf215546Sopenharmony_ci{ 201bf215546Sopenharmony_ci return stw_tls_init_thread(); 202bf215546Sopenharmony_ci} 203bf215546Sopenharmony_ci 204bf215546Sopenharmony_ci 205bf215546Sopenharmony_civoid 206bf215546Sopenharmony_cistw_cleanup_thread(void) 207bf215546Sopenharmony_ci{ 208bf215546Sopenharmony_ci stw_tls_cleanup_thread(); 209bf215546Sopenharmony_ci} 210bf215546Sopenharmony_ci 211bf215546Sopenharmony_ci 212bf215546Sopenharmony_civoid 213bf215546Sopenharmony_cistw_cleanup(void) 214bf215546Sopenharmony_ci{ 215bf215546Sopenharmony_ci DHGLRC dhglrc; 216bf215546Sopenharmony_ci 217bf215546Sopenharmony_ci debug_printf("%s\n", __FUNCTION__); 218bf215546Sopenharmony_ci 219bf215546Sopenharmony_ci if (!stw_dev) 220bf215546Sopenharmony_ci return; 221bf215546Sopenharmony_ci 222bf215546Sopenharmony_ci /* 223bf215546Sopenharmony_ci * Abort cleanup if there are still active contexts. In some situations 224bf215546Sopenharmony_ci * this DLL may be unloaded before the DLL that is using GL contexts is. 225bf215546Sopenharmony_ci */ 226bf215546Sopenharmony_ci stw_lock_contexts(stw_dev); 227bf215546Sopenharmony_ci dhglrc = handle_table_get_first_handle(stw_dev->ctx_table); 228bf215546Sopenharmony_ci stw_unlock_contexts(stw_dev); 229bf215546Sopenharmony_ci if (dhglrc) { 230bf215546Sopenharmony_ci debug_printf("%s: contexts still active -- cleanup aborted\n", __FUNCTION__); 231bf215546Sopenharmony_ci stw_dev = NULL; 232bf215546Sopenharmony_ci return; 233bf215546Sopenharmony_ci } 234bf215546Sopenharmony_ci 235bf215546Sopenharmony_ci free(stw_dev->st_options.force_gl_vendor); 236bf215546Sopenharmony_ci free(stw_dev->st_options.force_gl_renderer); 237bf215546Sopenharmony_ci free(stw_dev->st_options.mesa_extension_override); 238bf215546Sopenharmony_ci driDestroyOptionCache(&stw_dev->option_cache); 239bf215546Sopenharmony_ci driDestroyOptionInfo(&stw_dev->option_info); 240bf215546Sopenharmony_ci 241bf215546Sopenharmony_ci handle_table_destroy(stw_dev->ctx_table); 242bf215546Sopenharmony_ci 243bf215546Sopenharmony_ci stw_framebuffer_cleanup(); 244bf215546Sopenharmony_ci 245bf215546Sopenharmony_ci DeleteCriticalSection(&stw_dev->fb_mutex); 246bf215546Sopenharmony_ci DeleteCriticalSection(&stw_dev->ctx_mutex); 247bf215546Sopenharmony_ci DeleteCriticalSection(&stw_dev->screen_mutex); 248bf215546Sopenharmony_ci 249bf215546Sopenharmony_ci if (stw_dev->smapi->destroy) 250bf215546Sopenharmony_ci stw_dev->smapi->destroy(stw_dev->smapi); 251bf215546Sopenharmony_ci 252bf215546Sopenharmony_ci FREE(stw_dev->smapi); 253bf215546Sopenharmony_ci stw_dev->stapi->destroy(stw_dev->stapi); 254bf215546Sopenharmony_ci 255bf215546Sopenharmony_ci stw_dev->screen->destroy(stw_dev->screen); 256bf215546Sopenharmony_ci 257bf215546Sopenharmony_ci /* glapi is statically linked: we can call the local destroy function. */ 258bf215546Sopenharmony_ci#ifdef _GLAPI_NO_EXPORTS 259bf215546Sopenharmony_ci _glapi_destroy_multithread(); 260bf215546Sopenharmony_ci#endif 261bf215546Sopenharmony_ci 262bf215546Sopenharmony_ci stw_tls_cleanup(); 263bf215546Sopenharmony_ci 264bf215546Sopenharmony_ci util_dynarray_fini(&stw_dev->pixelformats); 265bf215546Sopenharmony_ci 266bf215546Sopenharmony_ci stw_dev = NULL; 267bf215546Sopenharmony_ci} 268bf215546Sopenharmony_ci 269bf215546Sopenharmony_ci 270bf215546Sopenharmony_civoid APIENTRY 271bf215546Sopenharmony_ciDrvSetCallbackProcs(INT nProcs, PROC *pProcs) 272bf215546Sopenharmony_ci{ 273bf215546Sopenharmony_ci size_t size; 274bf215546Sopenharmony_ci 275bf215546Sopenharmony_ci if (stw_dev == NULL) 276bf215546Sopenharmony_ci return; 277bf215546Sopenharmony_ci 278bf215546Sopenharmony_ci size = MIN2(nProcs * sizeof *pProcs, sizeof stw_dev->callbacks); 279bf215546Sopenharmony_ci memcpy(&stw_dev->callbacks, pProcs, size); 280bf215546Sopenharmony_ci 281bf215546Sopenharmony_ci return; 282bf215546Sopenharmony_ci} 283bf215546Sopenharmony_ci 284bf215546Sopenharmony_ci 285bf215546Sopenharmony_ciBOOL APIENTRY 286bf215546Sopenharmony_ciDrvValidateVersion(ULONG ulVersion) 287bf215546Sopenharmony_ci{ 288bf215546Sopenharmony_ci /* ulVersion is the version reported by the KMD: 289bf215546Sopenharmony_ci * - via D3DKMTQueryAdapterInfo(KMTQAITYPE_UMOPENGLINFO) on WDDM, 290bf215546Sopenharmony_ci * - or ExtEscape on XPDM and can be used to ensure the KMD and OpenGL ICD 291bf215546Sopenharmony_ci * versions match. 292bf215546Sopenharmony_ci * 293bf215546Sopenharmony_ci * We should get the expected version number from the winsys, but for now 294bf215546Sopenharmony_ci * ignore it. 295bf215546Sopenharmony_ci */ 296bf215546Sopenharmony_ci (void)ulVersion; 297bf215546Sopenharmony_ci return TRUE; 298bf215546Sopenharmony_ci} 299