Home | History | Annotate | Download | only in wgl
      1 /*
      2  * Mesa 3-D graphics library
      3  *
      4  * Copyright (C) 2011 Morgan Armand <morgan.devel (at) gmail.com>
      5  *
      6  * Permission is hereby granted, free of charge, to any person obtaining a
      7  * copy of this software and associated documentation files (the "Software"),
      8  * to deal in the Software without restriction, including without limitation
      9  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
     10  * and/or sell copies of the Software, and to permit persons to whom the
     11  * Software is furnished to do so, subject to the following conditions:
     12  *
     13  * The above copyright notice and this permission notice shall be included
     14  * in all copies or substantial portions of the Software.
     15  *
     16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
     17  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
     19  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
     20  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
     21  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
     22  * OTHER DEALINGS IN THE SOFTWARE.
     23  */
     24 
     25 #include <stdio.h>
     26 #include <windows.h>
     27 
     28 #define WGL_WGLEXT_PROTOTYPES
     29 
     30 #include <GL/gl.h>
     31 #include <GL/wglext.h>
     32 
     33 #include "stw_icd.h"
     34 #include "stw_context.h"
     35 #include "stw_device.h"
     36 #include "stw_ext_context.h"
     37 
     38 #include "util/u_debug.h"
     39 
     40 
     41 wglCreateContext_t wglCreateContext_func = 0;
     42 wglDeleteContext_t wglDeleteContext_func = 0;
     43 
     44 
     45 /**
     46  * The implementation of this function is tricky.  The OPENGL32.DLL library
     47  * remaps the context IDs returned by our stw_create_context_attribs()
     48  * function to different values returned to the caller of wglCreateContext().
     49  * That is, DHGLRC (driver) handles are not equivalent to HGLRC (public)
     50  * handles.
     51  *
     52  * So we need to generate a new HGLRC ID here.  We do that by calling
     53  * the regular wglCreateContext() function.  Then, we replace the newly-
     54  * created stw_context with a new stw_context that reflects the arguments
     55  * to this function.
     56  */
     57 HGLRC WINAPI
     58 wglCreateContextAttribsARB(HDC hDC, HGLRC hShareContext, const int *attribList)
     59 {
     60    HGLRC context;
     61 
     62    int majorVersion = 1, minorVersion = 0, layerPlane = 0;
     63    int contextFlags = 0x0;
     64    int profileMask = WGL_CONTEXT_CORE_PROFILE_BIT_ARB;
     65    int i;
     66    BOOL done = FALSE;
     67    const int contextFlagsAll = (WGL_CONTEXT_DEBUG_BIT_ARB |
     68                                 WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB);
     69 
     70    /* parse attrib_list */
     71    if (attribList) {
     72       for (i = 0; !done && attribList[i]; i++) {
     73          switch (attribList[i]) {
     74          case WGL_CONTEXT_MAJOR_VERSION_ARB:
     75             majorVersion = attribList[++i];
     76             break;
     77          case WGL_CONTEXT_MINOR_VERSION_ARB:
     78             minorVersion = attribList[++i];
     79             break;
     80          case WGL_CONTEXT_LAYER_PLANE_ARB:
     81             layerPlane = attribList[++i];
     82             break;
     83          case WGL_CONTEXT_FLAGS_ARB:
     84             contextFlags = attribList[++i];
     85             break;
     86          case WGL_CONTEXT_PROFILE_MASK_ARB:
     87             profileMask = attribList[++i];
     88             break;
     89          case 0:
     90             /* end of list */
     91             done = TRUE;
     92             break;
     93          default:
     94             /* bad attribute */
     95             SetLastError(ERROR_INVALID_PARAMETER);
     96             return 0;
     97          }
     98       }
     99    }
    100 
    101    /* check contextFlags */
    102    if (contextFlags & ~contextFlagsAll) {
    103       SetLastError(ERROR_INVALID_PARAMETER);
    104       return NULL;
    105    }
    106 
    107    /* check profileMask */
    108    if (profileMask != WGL_CONTEXT_CORE_PROFILE_BIT_ARB &&
    109        profileMask != WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB &&
    110        profileMask != WGL_CONTEXT_ES_PROFILE_BIT_EXT) {
    111       SetLastError(ERROR_INVALID_PROFILE_ARB);
    112       return NULL;
    113    }
    114 
    115    /* check version (generate ERROR_INVALID_VERSION_ARB if bad) */
    116    if (majorVersion <= 0 ||
    117        minorVersion < 0 ||
    118        (profileMask != WGL_CONTEXT_ES_PROFILE_BIT_EXT &&
    119         ((majorVersion == 1 && minorVersion > 5) ||
    120          (majorVersion == 2 && minorVersion > 1) ||
    121          (majorVersion == 3 && minorVersion > 3) ||
    122          (majorVersion == 4 && minorVersion > 5) ||
    123          majorVersion > 4)) ||
    124        (profileMask == WGL_CONTEXT_ES_PROFILE_BIT_EXT &&
    125         ((majorVersion == 1 && minorVersion > 1) ||
    126          (majorVersion == 2 && minorVersion > 0) ||
    127          (majorVersion == 3 && minorVersion > 1) ||
    128          majorVersion > 3))) {
    129       SetLastError(ERROR_INVALID_VERSION_ARB);
    130       return NULL;
    131    }
    132 
    133    if ((contextFlags & WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB) &&
    134        majorVersion < 3) {
    135       SetLastError(ERROR_INVALID_VERSION_ARB);
    136       return 0;
    137    }
    138 
    139    /* Get pointer to OPENGL32.DLL's wglCreate/DeleteContext() functions */
    140    if (!wglCreateContext_func || !wglDeleteContext_func) {
    141       /* Get the OPENGL32.DLL library */
    142       HMODULE opengl_lib = GetModuleHandleA("opengl32.dll");
    143       if (!opengl_lib) {
    144          _debug_printf("wgl: GetModuleHandleA(\"opengl32.dll\") failed\n");
    145          return 0;
    146       }
    147 
    148       /* Get pointer to wglCreateContext() function */
    149       wglCreateContext_func = (wglCreateContext_t)
    150          GetProcAddress(opengl_lib, "wglCreateContext");
    151       if (!wglCreateContext_func) {
    152          _debug_printf("wgl: failed to get wglCreateContext()\n");
    153          return 0;
    154       }
    155 
    156       /* Get pointer to wglDeleteContext() function */
    157       wglDeleteContext_func = (wglDeleteContext_t)
    158          GetProcAddress(opengl_lib, "wglDeleteContext");
    159       if (!wglDeleteContext_func) {
    160          _debug_printf("wgl: failed to get wglDeleteContext()\n");
    161          return 0;
    162       }
    163    }
    164 
    165    /* Call wglCreateContext to get a valid context ID */
    166    context = wglCreateContext_func(hDC);
    167 
    168    if (context) {
    169       /* Now replace the context we just created with a new one that reflects
    170        * the attributes passed to this function.
    171        */
    172       DHGLRC dhglrc, c, share_dhglrc = 0;
    173 
    174       /* Convert public HGLRC to driver DHGLRC */
    175       if (stw_dev && stw_dev->callbacks.wglCbGetDhglrc) {
    176          dhglrc = stw_dev->callbacks.wglCbGetDhglrc(context);
    177          if (hShareContext)
    178             share_dhglrc = stw_dev->callbacks.wglCbGetDhglrc(hShareContext);
    179       }
    180       else {
    181          /* not using ICD */
    182          dhglrc = (DHGLRC) context;
    183          share_dhglrc = (DHGLRC) hShareContext;
    184       }
    185 
    186       c = stw_create_context_attribs(hDC, layerPlane, share_dhglrc,
    187                                      majorVersion, minorVersion,
    188                                      contextFlags, profileMask,
    189                                      dhglrc);
    190       if (!c) {
    191          wglDeleteContext_func(context);
    192          context = 0;
    193       }
    194    }
    195 
    196    return context;
    197 }
    198 
    199 
    200 /** Defined by WGL_ARB_make_current_read */
    201 BOOL APIENTRY
    202 wglMakeContextCurrentARB(HDC hDrawDC, HDC hReadDC, HGLRC hglrc)
    203 {
    204    DHGLRC dhglrc = 0;
    205 
    206    if (stw_dev && stw_dev->callbacks.wglCbGetDhglrc) {
    207       /* Convert HGLRC to DHGLRC */
    208       dhglrc = stw_dev->callbacks.wglCbGetDhglrc(hglrc);
    209    }
    210 
    211    return stw_make_current(hDrawDC, hReadDC, dhglrc);
    212 }
    213