gl_common: OpenGL 3.x context support on windows

Also include GL/glext.h on windows:

Mingw's (and cygwin's) GL/gl.h has GL/glext.h's inclusion commented
out for some reason. Their glext.h is also ancient, so do yourself
a favor and replace your GL/glext.h with the one from
http://www.opengl.org/registry/api/glext.h .

A workaround is needed for NVidia's broken wglCreateContextAtrribsARB:

It'll return an error if the requested OpenGL version is previous to
3.2 *and* you request a profile... which is exactly *not* what the
wgl_create_context spec says should happen.

Handle it by removing the profile request from attribs[] and retrying
the context creation once more if the first try fails.

And after my first foray into OpenGL I already find a driver quirk.
Oh well.
This commit is contained in:
Kovensky 2012-01-27 01:31:33 +00:00 committed by wm4
parent 666915a6f0
commit 59125ce71e
2 changed files with 107 additions and 1 deletions

View File

@ -487,6 +487,11 @@ static const extfunc_desc_t extfuncs[] = {
DEF_GL3_DESC(UniformMatrix3fv),
DEF_GL3_DESC(UniformMatrix4x3fv),
#ifdef CONFIG_GL_WIN32
DEF_EXT_DESC(wglCreateContextAttribsARB, NULL,
("wglCreateContextAttribsARB")),
#endif
{-1}
};
@ -1812,6 +1817,7 @@ static void cocoa_fullscreen(struct vo *vo)
#ifdef CONFIG_GL_WIN32
#include "w32_common.h"
static int create_window_w32(struct MPGLContext *ctx, uint32_t d_width,
uint32_t d_height, uint32_t flags)
{
@ -1836,6 +1842,83 @@ static void *w32gpa(const GLubyte *procName)
return GetProcAddress(oglmod, procName);
}
static int create_window_w32_gl3(struct MPGLContext *ctx, int gl_flags,
int gl_version, uint32_t d_width,
uint32_t d_height, uint32_t flags) {
if (!vo_w32_config(d_width, d_height, flags))
return -1;
HGLRC *context = &ctx->context.w32;
if (*context) // reuse existing context
return 0; // not reusing it breaks gl3!
HWND win = vo_w32_window;
HDC windc = vo_w32_get_dc(win);
HGLRC new_context = 0;
GL *gl = ctx->gl;
new_context = wglCreateContext(windc);
if (!new_context) {
mp_msg(MSGT_VO, MSGL_FATAL, "[gl] Could not create GL context!\n");
return -1;
}
// set context
if (!wglMakeCurrent(windc, new_context)) {
mp_msg(MSGT_VO, MSGL_FATAL, "[gl] Could not set GL context!\n");
goto out;
}
getFunctions(ctx->gl, w32gpa, NULL, true);
if (!gl->wglCreateContextAttribsARB) {
mp_msg(MSGT_VO, MSGL_ERR, "[gl] The current OpenGL implementation does"
" not support OpenGL 3.x \n");
goto out;
}
int attribs[] = {
WGL_CONTEXT_MAJOR_VERSION_ARB, MPGL_VER_GET_MAJOR(gl_version),
WGL_CONTEXT_MINOR_VERSION_ARB, MPGL_VER_GET_MINOR(gl_version),
WGL_CONTEXT_FLAGS_ARB, WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB,
WGL_CONTEXT_PROFILE_MASK_ARB, WGL_CONTEXT_CORE_PROFILE_BIT_ARB,
0
};
*context = gl->wglCreateContextAttribsARB(windc, 0, attribs);
if (! *context) {
// NVidia, instead of ignoring WGL_CONTEXT_FLAGS_ARB, will error out if
// it's present on pre-3.2 contexts.
// Remove it from attribs and retry the context creation.
attribs[6] = attribs[7] = 0;
*context = gl->wglCreateContextAttribsARB(windc, 0, attribs);
}
if (! *context) {
int err = GetLastError();
mp_msg(MSGT_VO, MSGL_FATAL, "[gl] Could not create an OpenGL 3.x"
" context: error 0x%x\n", err);
goto out;
}
wglMakeCurrent(NULL, NULL);
wglDeleteContext(new_context);
if (!wglMakeCurrent(windc, *context)) {
mp_msg(MSGT_VO, MSGL_FATAL, "[gl] Could not set GL3 context!\n");
wglDeleteContext(*context);
return -1;
}
/* update function pointers */
getFunctions(ctx->gl, w32gpa, NULL, true);
return 0;
out:
wglDeleteContext(new_context);
return -1;
}
static int setGlWindow_w32(MPGLContext *ctx)
{
HWND win = vo_w32_window;
@ -1887,6 +1970,7 @@ static int setGlWindow_w32(MPGLContext *ctx)
wglDeleteContext(*context);
*context = new_context;
*vinfo = new_vinfo;
getFunctions(ctx->gl, w32gpa, NULL, false);
// and inform that reinit is neccessary
@ -2379,6 +2463,7 @@ MPGLContext *init_mpglcontext(enum MPGLType type, struct vo *vo)
#ifdef CONFIG_GL_WIN32
case GLTYPE_W32:
ctx->create_window = create_window_w32;
ctx->create_window_gl3 = create_window_w32_gl3;
ctx->setGlWindow = setGlWindow_w32;
ctx->releaseGlContext = releaseGlContext_w32;
ctx->swapGlBuffers = swapGlBuffers_w32;

View File

@ -46,6 +46,10 @@
#endif
#include <GL/gl.h>
#ifdef CONFIG_GL_WIN32
#include <GL/glext.h>
#endif
// workaround for some gl.h headers
#ifndef GLAPIENTRY
#ifdef APIENTRY
@ -563,7 +567,24 @@ struct GL {
const GLfloat *);
void (GLAPIENTRY *UniformMatrix4x3fv)(GLint, GLsizei, GLboolean,
const GLfloat *);
#ifdef CONFIG_GL_WIN32
HGLRC (GLAPIENTRY *wglCreateContextAttribsARB)(HDC hDC, HGLRC hShareContext,
const int *attribList);
#endif
};
#if defined(CONFIG_GL_WIN32) && !defined(WGL_CONTEXT_MAJOR_VERSION_ARB)
/* these are supposed to be defined in wingdi.h but mingw's is too old */
/* only the bits actually used by mplayer are defined */
/* reference: http://www.opengl.org/registry/specs/ARB/wgl_create_context.txt */
#define WGL_CONTEXT_MAJOR_VERSION_ARB 0x2091
#define WGL_CONTEXT_MINOR_VERSION_ARB 0x2092
#define WGL_CONTEXT_FLAGS_ARB 0x2094
#define WGL_CONTEXT_PROFILE_MASK_ARB 0x9126
#define WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB 0x0002
#define WGL_CONTEXT_CORE_PROFILE_BIT_ARB 0x00000001
#endif
#endif /* MPLAYER_GL_COMMON_H */