[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