summaryrefslogtreecommitdiffstats
path: root/libvo
diff options
context:
space:
mode:
authorKovensky <diogomfranco@gmail.com>2012-01-27 01:31:33 +0000
committerwm4 <wm4@mplayer2.org>2012-03-31 02:58:52 +0200
commit59125ce71e378ae169eaecc8ac04d72bda3d130d (patch)
tree16768bcf5a0b41e627c8a45fd88ac0ca170fa8bc /libvo
parent666915a6f01b01a4b5c087e78e92a5a7304f5598 (diff)
downloadmpv-59125ce71e378ae169eaecc8ac04d72bda3d130d.tar.bz2
mpv-59125ce71e378ae169eaecc8ac04d72bda3d130d.tar.xz
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.
Diffstat (limited to 'libvo')
-rw-r--r--libvo/gl_common.c85
-rw-r--r--libvo/gl_common.h23
2 files changed, 107 insertions, 1 deletions
diff --git a/libvo/gl_common.c b/libvo/gl_common.c
index ee82b5bbeb..fc83ab9f7f 100644
--- a/libvo/gl_common.c
+++ b/libvo/gl_common.c
@@ -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;
diff --git a/libvo/gl_common.h b/libvo/gl_common.h
index a045321d71..5b35e0aa63 100644
--- a/libvo/gl_common.h
+++ b/libvo/gl_common.h
@@ -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 */