[PATCH] Add an initial implementation of WGL_ARB_create_context. This should allow OpenGL3 programs to work. I haven't been able to test it with apps beside my own test app since there are no public OpenGL3 apps. Further as mentioned before the spec isn't properly implemented by drivers yet either.

Roderick Colenbrander thunderbird2k at gmx.net
Mon Oct 27 17:37:10 CDT 2008


---
 dlls/gdi32/driver.c               |    1 +
 dlls/gdi32/gdi_private.h          |    1 +
 dlls/gdi32/opengl.c               |   23 ++++++-
 dlls/winex11.drv/opengl.c         |  139 ++++++++++++++++++++++++++++++++++++-
 dlls/winex11.drv/winex11.drv.spec |    1 +
 5 files changed, 162 insertions(+), 3 deletions(-)

diff --git a/dlls/gdi32/driver.c b/dlls/gdi32/driver.c
index 21342bb..bcf8ba9 100644
--- a/dlls/gdi32/driver.c
+++ b/dlls/gdi32/driver.c
@@ -198,6 +198,7 @@ static struct graphics_driver *create_driver( HMODULE module )
 
         /* OpenGL32 */
         GET_FUNC(wglCreateContext);
+        GET_FUNC(wglCreateContextAttribsARB);
         GET_FUNC(wglDeleteContext);
         GET_FUNC(wglGetProcAddress);
         GET_FUNC(wglGetPbufferDCARB);
diff --git a/dlls/gdi32/gdi_private.h b/dlls/gdi32/gdi_private.h
index 325c708..a8fb487 100644
--- a/dlls/gdi32/gdi_private.h
+++ b/dlls/gdi32/gdi_private.h
@@ -225,6 +225,7 @@ typedef struct tagDC_FUNCS
     /* OpenGL32 */
     BOOL     (*pwglCopyContext)(HGLRC, HGLRC, UINT);
     HGLRC    (*pwglCreateContext)(PHYSDEV);
+    HGLRC    (*pwglCreateContextAttribsARB)(PHYSDEV, HGLRC, const int*);
     BOOL     (*pwglDeleteContext)(HGLRC);
     PROC     (*pwglGetProcAddress)(LPCSTR);
     HDC      (*pwglGetPbufferDCARB)(PHYSDEV, void*);
diff --git a/dlls/gdi32/opengl.c b/dlls/gdi32/opengl.c
index 022fc2c..cebb889 100644
--- a/dlls/gdi32/opengl.c
+++ b/dlls/gdi32/opengl.c
@@ -104,6 +104,25 @@ HGLRC WINAPI wglCreateContext(HDC hdc)
     return ret;
 }
 
+/***********************************************************************
+ *      wglCreateContextAttribsARB
+ */
+HGLRC WINAPI wglCreateContextAttribsARB(HDC hdc, HGLRC hShareContext, const int *attributeList)
+{
+    HGLRC ret = 0;
+    DC * dc = get_dc_ptr( hdc );
+
+    TRACE("(%p)\n",hdc);
+
+    if (!dc) return 0;
+
+    update_dc( dc );
+    if (!dc->funcs->pwglCreateContextAttribsARB) FIXME(" :stub\n");
+    else ret = dc->funcs->pwglCreateContextAttribsARB(dc->physDev, hShareContext, attributeList);
+
+    release_dc_ptr( dc );
+    return ret;
+}
 
 /***********************************************************************
  *		wglDeleteContext (OPENGL32.@)
@@ -350,7 +369,9 @@ PROC WINAPI wglGetProcAddress(LPCSTR func)
      * when a non-NULL value is returned by wglGetProcAddress), we return the address
      * of a wrapper function which will handle the HDC->PhysDev conversion.
      */
-    if(ret && strcmp(func, "wglMakeContextCurrentARB") == 0)
+    if(ret && strcmp(func, "wglCreateContextAttribsARB") == 0)
+        return (PROC)wglCreateContextAttribsARB;
+    else if(ret && strcmp(func, "wglMakeContextCurrentARB") == 0)
         return (PROC)wglMakeContextCurrentARB;
     else if(ret && strcmp(func, "wglGetPbufferDCARB") == 0)
         return (PROC)wglGetPbufferDCARB;
diff --git a/dlls/winex11.drv/opengl.c b/dlls/winex11.drv/opengl.c
index b4845ad..2f3d776 100644
--- a/dlls/winex11.drv/opengl.c
+++ b/dlls/winex11.drv/opengl.c
@@ -4,7 +4,7 @@
  * Copyright 2000 Lionel Ulmer
  * Copyright 2005 Alex Woods
  * Copyright 2005 Raphael Junqueira
- * Copyright 2006 Roderick Colenbrander
+ * Copyright 2006-2008 Roderick Colenbrander
  * Copyright 2006 Tomas Carnecky
  *
  * This library is free software; you can redistribute it and/or
@@ -107,6 +107,9 @@ typedef struct wine_glcontext {
     BOOL do_escape;
     XVisualInfo *vis;
     WineGLPixelFormat *fmt;
+    BOOL useCreateContextAttribsARB;
+    int numAttribs; /* This is needed for delaying wglCreateContextAttribsARB */
+    int attribList[16]; /* This is needed for delaying wglCreateContextAttribsARB */
     GLXContext ctx;
     HDC read_hdc;
     Drawable drawables[2];
@@ -239,6 +242,7 @@ MAKE_FUNCPTR(glXQueryDrawable)
 MAKE_FUNCPTR(glXGetCurrentReadDrawable)
 
 /* GLX Extensions */
+static GLXContext (*pglXCreateContextAttribsARB)(Display *dpy, GLXFBConfig config, GLXContext share_context, Bool direct, const int *attrib_list);
 static void* (*pglXGetProcAddressARB)(const GLubyte *);
 static int   (*pglXSwapIntervalSGI)(int);
 
@@ -437,6 +441,8 @@ static BOOL has_opengl(void)
    the associated extension is available (and if a driver reports the extension
    is available but fails to provide the functions, it's quite broken) */
 #define LOAD_FUNCPTR(f) p##f = (void*)pglXGetProcAddressARB((const unsigned char*)#f)
+    /* ARB GLX Extension */
+    LOAD_FUNCPTR(glXCreateContextAttribsARB);
     /* NV GLX Extension */
     LOAD_FUNCPTR(glXAllocateMemoryNV);
     LOAD_FUNCPTR(glXFreeMemoryNV);
@@ -1016,7 +1022,14 @@ static inline void sync_context(Wine_GLContext *context)
 static GLXContext create_glxcontext(Display *display, Wine_GLContext *context, GLXContext shareList, BOOL direct)
 {
     GLXContext ctx;
-    if(context->vis)
+    if(context->useCreateContextAttribsARB)
+    {
+        if(context->numAttribs)
+            ctx = pglXCreateContextAttribsARB(gdi_display, context->fmt->fbconfig, shareList, direct, context->attribList);
+        else
+            ctx = pglXCreateContextAttribsARB(gdi_display, context->fmt->fbconfig, shareList, direct, NULL);
+    }
+    else if(context->vis)
         ctx = pglXCreateContext(gdi_display, context->vis, shareList, direct);
     else /* Create a GLX Context for a pbuffer */
         ctx = pglXCreateNewContext(gdi_display, context->fmt->fbconfig, context->fmt->render_type, shareList, direct);
@@ -1647,6 +1660,8 @@ HGLRC X11DRV_wglCreateContext(X11DRV_PDEVICE *physDev)
     wine_tsx11_unlock();
     ret->hdc = hdc;
     ret->fmt = fmt;
+    ret->useCreateContextAttribsARB = FALSE;
+    ret->numAttribs = 0;
 
     /*ret->vis = vis;*/
     ret->vis = pglXGetVisualFromFBConfig(gdi_display, fmt->fbconfig);
@@ -2133,6 +2148,107 @@ static void WINAPI X11DRV_wglFlush(void)
     if (ctx) ExtEscape(ctx->hdc, X11DRV_ESCAPE, sizeof(code), (LPSTR)&code, 0, NULL );
 }
 
+static int GLXErrorHandler(Display *dpy, XErrorEvent *event, void *arg)
+{
+    int *error_code = (int*)arg;
+    *error_code = event->error_code;
+    return 1;
+}
+
+/**
+ * X11DRV_wglCreateContextAttribsARB
+ *
+ * WGL_ARB_create_context: wglCreateContextAttribsARB
+ */
+HGLRC X11DRV_wglCreateContextAttribsARB(X11DRV_PDEVICE *physDev, HGLRC hShareContext, const int* attribList)
+{
+    Wine_GLContext *ret;
+    WineGLPixelFormat *fmt;
+    int hdcPF = physDev->current_pf;
+    int fmt_count = 0;
+    GLXContext tmpContext;
+    int error_code = 0;
+
+    TRACE("(%p %p %p)\n", physDev, hShareContext, attribList);
+
+    if (!has_opengl()) return 0;
+
+    fmt = ConvertPixelFormatWGLtoGLX(gdi_display, hdcPF, TRUE /* Offscreen */, &fmt_count);
+    /* wglCreateContextAttribsARB supports ALL pixel formats, so also offscreen ones.
+     * If this fails something is very wrong on the system. */
+    if(!fmt) {
+        ERR("Cannot get FB Config for iPixelFormat %d, expect problems!\n", hdcPF);
+        SetLastError(ERROR_INVALID_PIXEL_FORMAT);
+        return NULL;
+    }
+
+    /* The context will be allocated in wglMakeCurrent / wglMakeContextCurrentARB / wglShareLists */
+    wine_tsx11_lock();
+    ret = alloc_context();
+    wine_tsx11_unlock();
+    ret->hdc = physDev->hdc;
+    ret->fmt = fmt;
+    ret->vis = NULL; /* glXCreateContextAttribsARB requires a fbconfig instead of a visual */
+    ret->useCreateContextAttribsARB = TRUE;
+
+    ret->numAttribs = 0;
+    if(attribList)
+    {
+        int *pAttribList = (int*)attribList;
+        int *pContextAttribList = &ret->attribList[0];
+        /* attribList consists of pairs {token, value] terminated with 0 */
+        while(pAttribList[0] != 0)
+        {
+            TRACE("%#x %#x\n", pAttribList[0], pAttribList[1]);
+            switch(pAttribList[0])
+            {
+                case WGL_CONTEXT_MAJOR_VERSION_ARB:
+                case WGL_CONTEXT_MINOR_VERSION_ARB:
+                case WGL_CONTEXT_FLAGS_ARB:
+                    /* The attributes and values are the same on both GLX and WGL */
+                    pContextAttribList[0] = pAttribList[0];
+                    pContextAttribList[1] = pAttribList[1];
+                    break;
+                case WGL_CONTEXT_LAYER_PLANE_ARB:
+                default:
+                    ERR("Unhandled attribList pair: %#x %#x\n", pAttribList[0], pAttribList[1]);
+            }
+
+            ret->numAttribs++;
+            pAttribList += 2;
+            pContextAttribList += 2;
+        }
+    }
+
+    /* Due to the existence of wglShareLists GLX context creation is delayed.
+     * glXCreateContextAttribs can fail in a lot of ways if incorrect parameters are passed.
+     * We need to catch those errors at this point and for that purpose we need a temp GLX context.
+     *
+     * Note X11DRV_expect_error / X11DRV_check_error take care of wine_tsx11_lock and wine_tsx11_unlock.
+     */
+    X11DRV_expect_error(gdi_display, GLXErrorHandler, &error_code);
+    tmpContext = create_glxcontext(gdi_display, ret, NULL, TRUE);
+    XSync(gdi_display, False);
+    if(X11DRV_check_error())
+    {
+        /* Context creation can fail for several reasons. We should map GLX error codes
+         * to WGL ones but at this point both the WGL spec has inconsistencies with the
+         * behavior of other WGL calls regarding invalid HDC / HGLRC. Further the GLX
+         * spec doesn't mention what the return value is when an invalid GL version is specified
+         * without the usage of the forward compatible or glx_render_type flag.
+         */
+        TRACE("Context creation failed with X/GLX error_code: %d\n", error_code);
+        return NULL;
+    }
+
+    wine_tsx11_lock();
+    pglXDestroyContext(gdi_display, tmpContext);
+    wine_tsx11_unlock();
+
+    TRACE(" creating context %p (GL context creation delayed)\n", ret);
+    return (HGLRC) ret;
+}
+
 /**
  * X11DRV_wglGetExtensionsStringARB
  *
@@ -3244,6 +3360,14 @@ static const WineGLExtension WGL_internal_functions =
 };
 
 
+static const WineGLExtension WGL_ARB_create_context =
+{
+  "WGL_ARB_create_context",
+  {
+    { "wglCreateContextAttribsARB", X11DRV_wglCreateContextAttribsARB },
+  }
+};
+
 static const WineGLExtension WGL_ARB_extensions_string =
 {
   "WGL_ARB_extensions_string",
@@ -3344,6 +3468,11 @@ static void X11DRV_WineGL_LoadExtensions(void)
 
     /* ARB Extensions */
 
+    if(glxRequireExtension("GLX_ARB_create_context"))
+    {
+        register_extension(&WGL_ARB_create_context);
+    }
+
     if(glxRequireExtension("GLX_ARB_fbconfig_float"))
     {
         register_extension_string("WGL_ARB_pixel_format_float");
@@ -3628,6 +3757,12 @@ PROC X11DRV_wglGetProcAddress(LPCSTR lpszProc) {
     return NULL;
 }
 
+HGLRC X11DRV_wglCreateContextAttribsARB(X11DRV_PDEVICE *physDev, HGLRC hShareContext, const int* attribList)
+{
+    opengl_error();
+    return NULL;
+}
+
 HDC X11DRV_wglGetPbufferDCARB(X11DRV_PDEVICE *hDevice, void *hPbuffer)
 {
     opengl_error();
diff --git a/dlls/winex11.drv/winex11.drv.spec b/dlls/winex11.drv/winex11.drv.spec
index 7cafaac..f9e2962 100644
--- a/dlls/winex11.drv/winex11.drv.spec
+++ b/dlls/winex11.drv/winex11.drv.spec
@@ -140,6 +140,7 @@
 # OpenGL
 @ cdecl wglCopyContext(long long long) X11DRV_wglCopyContext
 @ cdecl wglCreateContext(ptr) X11DRV_wglCreateContext
+@ cdecl wglCreateContextAttribsARB(ptr long ptr) X11DRV_wglCreateContextAttribsARB
 @ cdecl wglDeleteContext(long) X11DRV_wglDeleteContext
 @ cdecl wglGetProcAddress(str) X11DRV_wglGetProcAddress
 @ cdecl wglGetPbufferDCARB(ptr ptr) X11DRV_wglGetPbufferDCARB
-- 
1.5.3.4


--========GMX6861225147130817731--



More information about the wine-patches mailing list