[PATCH 2/5] winemac: Implement wglCreateContextAttribsARB.

Matteo Bruni mbruni at codeweavers.com
Mon Jan 5 10:17:52 CST 2015


It also allows to create core profile contexts.

As an aside, reported WGL extensions don't depend on the specific
GL context (e.g. WGL_ARB_pbuffer is reported as supported even on core
profile contexts).
---
 dlls/winemac.drv/opengl.c | 480 +++++++++++++++++++++++++++++-----------------
 1 file changed, 302 insertions(+), 178 deletions(-)

diff --git a/dlls/winemac.drv/opengl.c b/dlls/winemac.drv/opengl.c
index 0187822..04c1f82 100644
--- a/dlls/winemac.drv/opengl.c
+++ b/dlls/winemac.drv/opengl.c
@@ -70,6 +70,7 @@ struct wgl_context
     BOOL                    sharing;
     LONG                    update_swap_interval;
     DWORD                   last_flush_time;
+    BOOL                    core;
 };
 
 static struct list context_list = LIST_INIT(context_list);
@@ -1272,6 +1273,175 @@ static BOOL init_gl_info(void)
 }
 
 
+static int get_dc_pixel_format(HDC hdc)
+{
+    int format;
+    HWND hwnd;
+
+    if ((hwnd = WindowFromDC(hdc)))
+    {
+        struct macdrv_win_data *data;
+
+        if (!(data = get_win_data(hwnd)))
+        {
+            FIXME("DC for window %p of other process: not implemented\n", hwnd);
+            return 0;
+        }
+
+        format = data->pixel_format;
+        release_win_data(data);
+    }
+    else
+    {
+        struct wgl_pbuffer *pbuffer;
+
+        EnterCriticalSection(&dc_pbuffers_section);
+        pbuffer = (struct wgl_pbuffer*)CFDictionaryGetValue(dc_pbuffers, hdc);
+        if (pbuffer)
+            format = pbuffer->format;
+        else
+        {
+            WARN("no window or pbuffer for DC %p\n", hdc);
+            format = 0;
+        }
+        LeaveCriticalSection(&dc_pbuffers_section);
+    }
+
+    return format;
+}
+
+
+/**********************************************************************
+ *              create_context
+ */
+static BOOL create_context(struct wgl_context *context, CGLContextObj share, BOOL core)
+{
+    const pixel_format *pf;
+    CGLPixelFormatAttribute attribs[64];
+    int n = 0;
+    CGLPixelFormatObj pix;
+    GLint virtualScreens;
+    CGLError err;
+
+#if !defined(MAC_OS_X_VERSION_10_7) || MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_7
+    if (core)
+    {
+        WARN("OS X version >= 10.7 is required to be able to create core contexts\n",
+             err, CGLErrorString(err));
+        return FALSE;
+    }
+#endif
+
+    pf = get_pixel_format(context->format, TRUE /* non-displayable */);
+    if (!pf)
+    {
+        ERR("Invalid pixel format %d, expect problems!\n", context->format);
+        SetLastError(ERROR_INVALID_PIXEL_FORMAT);
+        return FALSE;
+    }
+
+    attribs[n++] = kCGLPFAMinimumPolicy;
+    attribs[n++] = kCGLPFAClosestPolicy;
+
+    if (pf->accelerated)
+    {
+        attribs[n++] = kCGLPFAAccelerated;
+        attribs[n++] = kCGLPFANoRecovery;
+    }
+    else
+    {
+        attribs[n++] = kCGLPFARendererID;
+        attribs[n++] = kCGLRendererGenericFloatID;
+    }
+
+    if (pf->double_buffer)
+        attribs[n++] = kCGLPFADoubleBuffer;
+
+    attribs[n++] = kCGLPFAAuxBuffers;
+    attribs[n++] = pf->aux_buffers;
+
+    attribs[n++] = kCGLPFAColorSize;
+    attribs[n++] = color_modes[pf->color_mode].color_bits;
+    attribs[n++] = kCGLPFAAlphaSize;
+    attribs[n++] = color_modes[pf->color_mode].alpha_bits;
+    if (color_modes[pf->color_mode].is_float)
+        attribs[n++] = kCGLPFAColorFloat;
+
+    attribs[n++] = kCGLPFADepthSize;
+    attribs[n++] = pf->depth_bits;
+
+    attribs[n++] = kCGLPFAStencilSize;
+    attribs[n++] = pf->stencil_bits;
+
+    if (pf->stereo)
+        attribs[n++] = kCGLPFAStereo;
+
+    if (pf->accum_mode)
+    {
+        attribs[n++] = kCGLPFAAccumSize;
+        attribs[n++] = color_modes[pf->accum_mode - 1].color_bits;
+    }
+
+    /* Explicitly requesting pbuffers in CGLChoosePixelFormat fails with core contexts. */
+    if (pf->pbuffer && !core)
+        attribs[n++] = kCGLPFAPBuffer;
+
+    if (pf->sample_buffers && pf->samples)
+    {
+        attribs[n++] = kCGLPFASampleBuffers;
+        attribs[n++] = pf->sample_buffers;
+        attribs[n++] = kCGLPFASamples;
+        attribs[n++] = pf->samples;
+    }
+
+    if (pf->backing_store)
+        attribs[n++] = kCGLPFABackingStore;
+
+    if (core)
+    {
+        attribs[n++] = kCGLPFAOpenGLProfile;
+        attribs[n++] = (int)kCGLOGLPVersion_3_2_Core;
+    }
+
+    attribs[n] = 0;
+
+    err = CGLChoosePixelFormat(attribs, &pix, &virtualScreens);
+    if (err != kCGLNoError || !pix)
+    {
+        WARN("CGLChoosePixelFormat() failed with error %d %s\n", err, CGLErrorString(err));
+        SetLastError(ERROR_INVALID_OPERATION);
+        return FALSE;
+    }
+
+    err = CGLCreateContext(pix, share, &context->cglcontext);
+    CGLReleasePixelFormat(pix);
+    if (err != kCGLNoError || !context->cglcontext)
+    {
+        context->cglcontext = NULL;
+        WARN("CGLCreateContext() failed with error %d %s\n", err, CGLErrorString(err));
+        SetLastError(ERROR_INVALID_OPERATION);
+        return FALSE;
+    }
+
+    context->context = macdrv_create_opengl_context(context->cglcontext);
+    CGLReleaseContext(context->cglcontext);
+    if (!context->context)
+    {
+        WARN("macdrv_create_opengl_context() failed\n");
+        SetLastError(ERROR_INVALID_OPERATION);
+        return FALSE;
+    }
+    context->core = core;
+
+    if (allow_vsync)
+        InterlockedExchange(&context->update_swap_interval, TRUE);
+
+    TRACE("created context %p/%p/%p\n", context, context->context, context->cglcontext);
+
+    return TRUE;
+}
+
+
 static BOOL get_gl_view_window_rect(struct macdrv_win_data *data, macdrv_window *window, RECT *rect)
 {
     BOOL ret = TRUE;
@@ -2076,6 +2246,133 @@ cant_match:
 }
 
 
+#define VALID_PROFILE_BITS_MASK (WGL_CONTEXT_CORE_PROFILE_BIT_ARB | WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB)
+
+/***********************************************************************
+ *              macdrv_wglCreateContextAttribsARB
+ *
+ * WGL_ARB_create_context: wglCreateContextAttribsARB
+ */
+static struct wgl_context *macdrv_wglCreateContextAttribsARB(HDC hdc,
+                                                             struct wgl_context *share_context,
+                                                             const int *attrib_list)
+{
+    int format;
+    struct wgl_context *context;
+    const int *iptr;
+    int major = 1, minor = 0, profile = WGL_CONTEXT_CORE_PROFILE_BIT_ARB, flags = 0;
+    BOOL core = FALSE;
+
+    TRACE("hdc %p, share_context %p, attrib_list %p\n", hdc, share_context, attrib_list);
+
+    format = get_dc_pixel_format(hdc);
+
+    if (!is_valid_pixel_format(format))
+    {
+        ERR("Invalid pixel format %d, expect problems!\n", format);
+        SetLastError(ERROR_INVALID_PIXEL_FORMAT);
+        return NULL;
+    }
+
+    for (iptr = attrib_list; iptr && *iptr; iptr += 2)
+    {
+        int attr = iptr[0];
+        int value = iptr[1];
+
+        TRACE("%s\n", debugstr_attrib(attr, value));
+
+        switch (attr)
+        {
+            case WGL_CONTEXT_MAJOR_VERSION_ARB:
+                major = value;
+                break;
+
+            case WGL_CONTEXT_MINOR_VERSION_ARB:
+                minor = value;
+                break;
+
+            case WGL_CONTEXT_LAYER_PLANE_ARB:
+                WARN("WGL_CONTEXT_LAYER_PLANE_ARB attribute ignored\n");
+                break;
+
+            case WGL_CONTEXT_FLAGS_ARB:
+                flags = value;
+                if (flags & ~WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB)
+                    WARN("WGL_CONTEXT_FLAGS_ARB attributes %#x ignored\n",
+                         flags & ~WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB);
+                break;
+
+            case WGL_CONTEXT_PROFILE_MASK_ARB:
+                if ((value & ~VALID_PROFILE_BITS_MASK) || !value ||
+                    (value & VALID_PROFILE_BITS_MASK) == VALID_PROFILE_BITS_MASK)
+                {
+                    WARN("WGL_CONTEXT_PROFILE_MASK_ARB bits %#x invalid\n", value);
+                    SetLastError(ERROR_INVALID_PROFILE_ARB);
+                    return NULL;
+                }
+                profile = value;
+                break;
+
+            default:
+                WARN("Unknown attribute %s.\n", debugstr_attrib(attr, value));
+                SetLastError(ERROR_INVALID_PARAMETER);
+                return NULL;
+        }
+    }
+
+    if (major > 3 || (major == 3 && minor >= 2))
+    {
+        if (!(flags & WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB))
+        {
+            WARN("OS X only supports forward-compatible 3.2+ contexts\n");
+            SetLastError(ERROR_INVALID_VERSION_ARB);
+            return NULL;
+        }
+        if (profile != WGL_CONTEXT_CORE_PROFILE_BIT_ARB)
+        {
+            WARN("Compatibility profiles for GL version >= 3.2 not supported\n");
+            SetLastError(ERROR_INVALID_PROFILE_ARB);
+            return NULL;
+        }
+        core = TRUE;
+    }
+    else if (major == 3)
+    {
+        WARN("OS X doesn't support 3.0 or 3.1 contexts\n");
+        SetLastError(ERROR_INVALID_VERSION_ARB);
+        return NULL;
+    }
+    else if (major < 1 || (major == 1 && (minor < 0 || minor > 5)) ||
+             (major == 2 && (minor < 0 || minor > 1)))
+    {
+        WARN("Invalid GL version requested\n");
+        SetLastError(ERROR_INVALID_VERSION_ARB);
+        return NULL;
+    }
+    if (!core && flags & WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB)
+    {
+        WARN("Forward compatible context requested for GL version < 3\n");
+        SetLastError(ERROR_INVALID_VERSION_ARB);
+        return NULL;
+    }
+
+    if (!(context = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*context)))) return NULL;
+
+    context->format = format;
+    if (!create_context(context, share_context ? share_context->cglcontext : NULL, core))
+    {
+        HeapFree(GetProcessHeap(), 0, context);
+        return NULL;
+    }
+
+    EnterCriticalSection(&context_section);
+    list_add_tail(&context_list, &context->entry);
+    LeaveCriticalSection(&context_section);
+
+    return context;
+}
+
+
 /**********************************************************************
  *              macdrv_wglCreatePbufferARB
  *
@@ -3142,10 +3439,9 @@ static void load_extensions(void)
             register_extension("WGL_NV_render_texture_rectangle");
     }
 
-    /* TODO:
-        WGL_ARB_create_context: wglCreateContextAttribsARB
-        WGL_ARB_create_context_profile
-     */
+    register_extension("WGL_ARB_create_context");
+    register_extension("WGL_ARB_create_context_profile");
+    opengl_funcs.ext.p_wglCreateContextAttribsARB = macdrv_wglCreateContextAttribsARB;
 
     /*
      * EXT Extensions
@@ -3276,157 +3572,6 @@ void sync_gl_view(struct macdrv_win_data *data)
 }
 
 
-static int get_dc_pixel_format(HDC hdc)
-{
-    int format;
-    HWND hwnd;
-
-    if ((hwnd = WindowFromDC(hdc)))
-    {
-        struct macdrv_win_data *data;
-
-        if (!(data = get_win_data(hwnd)))
-        {
-            FIXME("DC for window %p of other process: not implemented\n", hwnd);
-            return 0;
-        }
-
-        format = data->pixel_format;
-        release_win_data(data);
-    }
-    else
-    {
-        struct wgl_pbuffer *pbuffer;
-
-        EnterCriticalSection(&dc_pbuffers_section);
-        pbuffer = (struct wgl_pbuffer*)CFDictionaryGetValue(dc_pbuffers, hdc);
-        if (pbuffer)
-            format = pbuffer->format;
-        else
-        {
-            WARN("no window or pbuffer for DC %p\n", hdc);
-            format = 0;
-        }
-        LeaveCriticalSection(&dc_pbuffers_section);
-    }
-
-    return format;
-}
-
-
-/**********************************************************************
- *              create_context
- */
-static BOOL create_context(struct wgl_context *context, CGLContextObj share)
-{
-    const pixel_format *pf;
-    CGLPixelFormatAttribute attribs[64];
-    int n = 0;
-    CGLPixelFormatObj pix;
-    GLint virtualScreens;
-    CGLError err;
-
-    pf = get_pixel_format(context->format, TRUE /* non-displayable */);
-    if (!pf)
-    {
-        ERR("Invalid pixel format %d, expect problems!\n", context->format);
-        SetLastError(ERROR_INVALID_PIXEL_FORMAT);
-        return FALSE;
-    }
-
-    attribs[n++] = kCGLPFAMinimumPolicy;
-    attribs[n++] = kCGLPFAClosestPolicy;
-
-    if (pf->accelerated)
-    {
-        attribs[n++] = kCGLPFAAccelerated;
-        attribs[n++] = kCGLPFANoRecovery;
-    }
-    else
-    {
-        attribs[n++] = kCGLPFARendererID;
-        attribs[n++] = kCGLRendererGenericFloatID;
-    }
-
-    if (pf->double_buffer)
-        attribs[n++] = kCGLPFADoubleBuffer;
-
-    attribs[n++] = kCGLPFAAuxBuffers;
-    attribs[n++] = pf->aux_buffers;
-
-    attribs[n++] = kCGLPFAColorSize;
-    attribs[n++] = color_modes[pf->color_mode].color_bits;
-    attribs[n++] = kCGLPFAAlphaSize;
-    attribs[n++] = color_modes[pf->color_mode].alpha_bits;
-    if (color_modes[pf->color_mode].is_float)
-        attribs[n++] = kCGLPFAColorFloat;
-
-    attribs[n++] = kCGLPFADepthSize;
-    attribs[n++] = pf->depth_bits;
-
-    attribs[n++] = kCGLPFAStencilSize;
-    attribs[n++] = pf->stencil_bits;
-
-    if (pf->stereo)
-        attribs[n++] = kCGLPFAStereo;
-
-    if (pf->accum_mode)
-    {
-        attribs[n++] = kCGLPFAAccumSize;
-        attribs[n++] = color_modes[pf->accum_mode - 1].color_bits;
-    }
-
-    if (pf->window)
-        attribs[n++] = kCGLPFAWindow;
-    if (pf->pbuffer)
-        attribs[n++] = kCGLPFAPBuffer;
-
-    if (pf->sample_buffers && pf->samples)
-    {
-        attribs[n++] = kCGLPFASampleBuffers;
-        attribs[n++] = pf->sample_buffers;
-        attribs[n++] = kCGLPFASamples;
-        attribs[n++] = pf->samples;
-    }
-
-    if (pf->backing_store)
-        attribs[n++] = kCGLPFABackingStore;
-
-    attribs[n] = 0;
-
-    err = CGLChoosePixelFormat(attribs, &pix, &virtualScreens);
-    if (err != kCGLNoError || !pix)
-    {
-        WARN("CGLChoosePixelFormat() failed with error %d %s\n", err, CGLErrorString(err));
-        return FALSE;
-    }
-
-    err = CGLCreateContext(pix, share, &context->cglcontext);
-    CGLReleasePixelFormat(pix);
-    if (err != kCGLNoError || !context->cglcontext)
-    {
-        context->cglcontext = NULL;
-        WARN("CGLCreateContext() failed with error %d %s\n", err, CGLErrorString(err));
-        return FALSE;
-    }
-
-    context->context = macdrv_create_opengl_context(context->cglcontext);
-    CGLReleaseContext(context->cglcontext);
-    if (!context->context)
-    {
-        WARN("macdrv_create_opengl_context() failed\n");
-        return FALSE;
-    }
-
-    if (allow_vsync)
-        InterlockedExchange(&context->update_swap_interval, TRUE);
-
-    TRACE("created context %p/%p/%p\n", context, context->context, context->cglcontext);
-
-    return TRUE;
-}
-
-
 /**********************************************************************
  *              macdrv_wglDescribePixelFormat
  */
@@ -3513,32 +3658,11 @@ static BOOL macdrv_wglCopyContext(struct wgl_context *src, struct wgl_context *d
  */
 static struct wgl_context *macdrv_wglCreateContext(HDC hdc)
 {
-    int format;
     struct wgl_context *context;
 
     TRACE("hdc %p\n", hdc);
 
-    format = get_dc_pixel_format(hdc);
-
-    if (!is_valid_pixel_format(format))
-    {
-        ERR("Invalid pixel format %d, expect problems!\n", format);
-        SetLastError(ERROR_INVALID_PIXEL_FORMAT);
-        return NULL;
-    }
-
-    if (!(context = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*context)))) return NULL;
-
-    context->format = format;
-    if (!create_context(context, NULL))
-    {
-        HeapFree(GetProcessHeap(), 0, context);
-        return NULL;
-    }
-
-    EnterCriticalSection(&context_section);
-    list_add_tail(&context_list, &context->entry);
-    LeaveCriticalSection(&context_section);
+    context = macdrv_wglCreateContextAttribsARB(hdc, NULL, NULL);
 
     return context;
 }
@@ -3658,7 +3782,7 @@ static BOOL macdrv_wglShareLists(struct wgl_context *org, struct wgl_context *de
     saved_cglcontext = dest->cglcontext;
     dest->context = NULL;
     dest->cglcontext = NULL;
-    if (!create_context(dest, org->cglcontext))
+    if (!create_context(dest, org->cglcontext, dest->core))
     {
         dest->context = saved_context;
         dest->cglcontext = saved_cglcontext;
-- 
2.0.5




More information about the wine-patches mailing list