[MPlayer-dev-eng] [PATCH] vo_gl fullscreen fixes + GUI support
Reimar Döffinger
Reimar.Doeffinger at stud.uni-karlsruhe.de
Mon Nov 1 16:40:34 CET 2004
Hi,
the attached patch seems to fix all fullscreen issues that vo_gl had and
also adds GUI support (where fullscreen switching works correctly when
using the right-click-menu but not with the 'f' key. Stupid thing...).
I'm posting this here because I need a little extra function in
x11_common, is that okay with you? I think it might also be useful for other vo's as well...
I will apply very soon if nobody has objections.
Greetings,
Reimar Döffinger
-------------- next part --------------
diff -u libvo/gl_common.c libvo/gl_common.c
--- libvo/gl_common.c 2004-10-17 15:23:56.000000000 +0200
+++ libvo/gl_common.c 2004-11-01 15:35:36.758840729 +0100
@@ -17,3 +17,108 @@
glPixelStorei (GL_UNPACK_ALIGNMENT, gl_alignment);
}
+//! could not set new window, will continue drawing into the old one.
+#define SET_WINDOW_FAILED -1
+//! new window is set, could even transfer the OpenGL context.
+#define SET_WINDOW_OK 0
+//! new window is set, but the OpenGL context needs to be reinitialized.
+#define SET_WINDOW_REINIT 1
+
+#ifndef GL_WIN32
+/**
+ * Returns the XVisualInfo associated with Window win.
+ * \param win Window whose XVisualInfo is returne.
+ * \return XVisualInfo of the window. Caller must use XFree to free it.
+ */
+static XVisualInfo *getWindowVisualInfo(Window win) {
+ XWindowAttributes xw_attr;
+ XVisualInfo vinfo_template;
+ int tmp;
+ XGetWindowAttributes(mDisplay, win, &xw_attr);
+ vinfo_template.visualid = XVisualIDFromVisual(xw_attr.visual);
+ return XGetVisualInfo(mDisplay, VisualIDMask, &vinfo_template, &tmp);
+}
+
+/**
+ * \brief Changes the window in which video is displayed.
+ * If possible only transfers the context to the new window, otherwise
+ * creates a new one, which must be initialized by the caller.
+ * \param vinfo Currently used visual.
+ * \param context Currently used context.
+ * \param win window that should be used for drawing.
+ * \return one of SET_WINDOW_FAILED, SET_WINDOW_OK or SET_WINDOW_REINIT.
+ * In case of SET_WINDOW_REINIT the context could not be transfered
+ * and the caller must initialize it correctly.
+ */
+int setGlWindow(XVisualInfo **vinfo, GLXContext *context, Window win)
+{
+ XVisualInfo *new_vinfo;
+ GLXContext new_context = NULL;
+ int keep_context = 0;
+
+ // should only be needed when keeping context, but not doing glFinish
+ // can cause flickering even when we do not keep it.
+ glFinish();
+ new_vinfo = getWindowVisualInfo(win);
+ if (*context && *vinfo && new_vinfo &&
+ (*vinfo)->visualid == new_vinfo->visualid) {
+ // we can keep the GLXContext
+ new_context = *context;
+ XFree(new_vinfo);
+ new_vinfo = *vinfo;
+ keep_context = 1;
+ } else {
+ // create a context
+ new_context = glXCreateContext(mDisplay, new_vinfo, NULL, True);
+ if (!new_context) {
+ mp_msg(MSGT_VO, MSGL_FATAL, "[gl] Could not create GLX context!\n");
+ XFree(new_vinfo);
+ return SET_WINDOW_FAILED;
+ }
+ }
+
+ // set context
+ if (!glXMakeCurrent(mDisplay, vo_window, new_context)) {
+ mp_msg (MSGT_VO, MSGL_FATAL, "[gl] Could not set GLX context!\n");
+ if (!keep_context) {
+ glXDestroyContext (mDisplay, new_context);
+ XFree(new_vinfo);
+ }
+ return SET_WINDOW_FAILED;
+ }
+
+ // set new values
+ vo_window = win;
+ {
+ Window root;
+ int tmp;
+ XGetGeometry(mDisplay, vo_window, &root, &tmp, &tmp,
+ &vo_dwidth, &vo_dheight, &tmp, &tmp);
+ }
+ if (!keep_context) {
+ if (*context)
+ glXDestroyContext(mDisplay, *context);
+ *context = new_context;
+ if (*vinfo)
+ XFree(*vinfo);
+ *vinfo = new_vinfo;
+
+ // and inform that reinit is neccessary
+ return SET_WINDOW_REINIT;
+ }
+ return SET_WINDOW_OK;
+}
+
+/**
+ * \brief free the VisualInfo and GLXContext of an OpenGL context.
+ */
+void releaseGlContext(XVisualInfo **vinfo, GLXContext *context) {
+ if (*vinfo)
+ XFree(*vinfo);
+ *vinfo = NULL;
+ if (*context)
+ glXDestroyContext(mDisplay, *context);
+ *context = 0;
+}
+#endif
+
diff -u libvo/gl_common.h libvo/gl_common.h
--- libvo/gl_common.h 2004-10-17 15:23:57.000000000 +0200
+++ libvo/gl_common.h 2004-11-01 13:16:18.000000000 +0100
@@ -1,8 +1,22 @@
#ifndef __GL_COMMON_H__
#define __GL_COMMON_H__
+#include "mp_msg.h"
+#include "config.h"
+
#include <GL/gl.h>
+#include "video_out.h"
+
+#ifndef GL_WIN32
+#include <X11/Xlib.h>
+#include <GL/glx.h>
+#include "x11_common.h"
+#endif
void glAdjustAlignment(int stride);
+#ifndef GL_WIN32
+int setGlWindow(XVisualInfo **vinfo, GLXContext *context, Window win);
+#endif
+
#endif
diff -u libvo/vo_gl.c libvo/vo_gl.c
--- libvo/vo_gl.c 2004-10-17 17:19:48.000000000 +0200
+++ libvo/vo_gl.c 2004-11-01 16:11:52.415724954 +0100
@@ -24,6 +24,9 @@
#include "gl_common.h"
#include "x11_common.h"
#include "aspect.h"
+#ifdef HAVE_NEW_GUI
+#include "Gui/interface.h"
+#endif
static vo_info_t info =
{
@@ -35,7 +38,8 @@
LIBVO_EXTERN(gl)
-static GLXContext wsGLXContext;
+static XVisualInfo *gl_vinfo = NULL;
+static GLXContext gl_context = 0;
static int wsGLXAttrib[] = { GLX_RGBA,
GLX_RED_SIZE,1,
GLX_GREEN_SIZE,1,
@@ -172,26 +176,54 @@
return 1;
}
+/**
+ * \brief Initialize a (new or reused) OpenGL context.
+ */
+static int initGl(uint32_t d_width, uint32_t d_height) {
+ unsigned char *ImageData = NULL;
+ texture_width = 32;
+ while (texture_width < image_width ||
+ texture_width < image_height)
+ texture_width *= 2;
+ texture_height = texture_width;
+
+ glDisable(GL_BLEND);
+ glDisable(GL_DEPTH_TEST);
+ glDepthMask(GL_FALSE);
+ glDisable(GL_CULL_FACE);
+ glEnable(GL_TEXTURE_2D);
+
+ mp_msg(MSGT_VO, MSGL_V, "[gl] Creating %dx%d texture...\n",
+ texture_width, texture_height);
+
+ glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+
+ glAdjustAlignment(texture_width * image_bytes);
+ ImageData = malloc(texture_width * texture_height * image_bytes);
+ memset(ImageData, 0, texture_width * texture_height * image_bytes);
+ glTexImage2D(GL_TEXTURE_2D, 0, gl_texfmt, texture_width, texture_height, 0,
+ gl_format, gl_type, ImageData);
+ free (ImageData);
+
+ // set alignment as default is 4 which will break some files
+ glAdjustAlignment(image_width * image_bytes);
+
+ resize(d_width, d_height);
+
+ glClearColor( 0.0f,0.0f,0.0f,0.0f );
+ glClear( GL_COLOR_BUFFER_BIT );
+}
+
/* connect to server, create and map window,
* allocate colors and (shared) memory
*/
static uint32_t
config(uint32_t width, uint32_t height, uint32_t d_width, uint32_t d_height, uint32_t flags, char *title, uint32_t format)
{
- unsigned char *ImageData=NULL;
-// int screen;
- unsigned int fg, bg;
- XSizeHints hint;
- XVisualInfo *vinfo;
- XEvent xev;
-
-// XGCValues xgcv;
-
image_height = height;
image_width = width;
find_gl_format (format);
- vo_dwidth = d_width;
- vo_dheight = d_height;
sub_bg_alpha = 255; // We need alpha = 255 for invisible part of the OSD
int_pause = 0;
@@ -207,6 +239,26 @@
// aspect(&d_width,&d_height,A_ZOOM);
// }
#endif
+#ifdef HAVE_NEW_GUI
+ if (use_gui) {
+ // GUI creates and manages window for us
+ vo_dwidth = d_width;
+ vo_dheight= d_height;
+ guiGetEvent(guiSetShVideo, 0);
+ setGlWindow(&gl_vinfo, &gl_context, vo_window);
+ initGl(vo_dwidth, vo_dheight);
+ return 0;
+ }
+#endif
+ if ( vo_window == None ) {
+ unsigned int fg, bg;
+ XSizeHints hint;
+ XVisualInfo *vinfo;
+ XEvent xev;
+
+ vo_dwidth = d_width;
+ vo_dheight = d_height;
+
hint.x = 0;
hint.y = 0;
hint.width = d_width;
@@ -229,8 +281,6 @@
- if ( vo_window == None )
- {
vo_window = vo_x11_create_smooth_window(mDisplay, mRootWin, vinfo->visual, hint.x, hint.y, hint.width, hint.height,
vinfo->depth, XCreateColormap(mDisplay, mRootWin, vinfo->visual, AllocNone));
@@ -243,7 +293,6 @@
XSetStandardProperties(mDisplay, vo_window, title, title, None, NULL, 0, &hint);
/* Map window. */
XMapWindow(mDisplay, vo_window);
- if ( flags&1 ) vo_x11_fullscreen();
#ifdef HAVE_XINERAMA
vo_x11_xinerama_move(mDisplay,vo_window);
#endif
@@ -256,56 +305,21 @@
while (xev.type != MapNotify || xev.xmap.event != vo_window);
XSelectInput(mDisplay, vo_window, NoEventMask);
- }
-
- if ( vo_config_count ) glXDestroyContext( mDisplay,wsGLXContext );
- wsGLXContext=glXCreateContext( mDisplay,vinfo,NULL,True );
- glXMakeCurrent( mDisplay,vo_window,wsGLXContext );
XSync(mDisplay, False);
vo_x11_selectinput_witherr(mDisplay, vo_window, StructureNotifyMask | KeyPressMask | PointerMotionMask
| ButtonPressMask | ButtonReleaseMask | ExposureMask
);
-
- texture_width=32;
- while(texture_width<image_width || texture_width<image_height) texture_width*=2;
- texture_height=texture_width;
-
- ImageData=malloc(texture_width*texture_height*image_bytes);
- memset(ImageData,0,texture_width*texture_height*image_bytes);
-
- glDisable(GL_BLEND);
- glDisable(GL_DEPTH_TEST);
- glDepthMask(GL_FALSE);
- glDisable(GL_CULL_FACE);
-
- glEnable(GL_TEXTURE_2D);
-
- // set alignment as default is 4 which will break some files
- glAdjustAlignment(image_width * image_bytes);
-
- mp_msg(MSGT_VO, MSGL_V, "[gl] Creating %dx%d texture...\n",texture_width,texture_height);
-
-#if 1
-// glBindTexture(GL_TEXTURE_2D, texture_id);
- glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER, GL_LINEAR);
- glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER, GL_LINEAR);
- glTexImage2D(GL_TEXTURE_2D, 0, gl_texfmt, texture_width, texture_height, 0,
- gl_format, gl_type, ImageData);
-#endif
-
- free (ImageData);
-
- resize(d_width,d_height);
-
- glClearColor( 0.0f,0.0f,0.0f,0.0f );
- glClear( GL_COLOR_BUFFER_BIT );
-
-// printf("OpenGL setup OK!\n");
-
+ }
if (vo_ontop) vo_x11_setlayer(mDisplay, vo_window, vo_ontop);
+ vo_x11_nofs_pos(0, 0, d_width, d_height);
+ if (vo_fs ^ (flags & VOFLAG_FULLSCREEN))
+ vo_x11_fullscreen();
+ setGlWindow(&gl_vinfo, &gl_context, vo_window);
+ initGl(vo_dwidth, vo_dheight);
+
return 0;
}
@@ -519,6 +533,7 @@
uninit(void)
{
if ( !vo_config_count ) return;
+ releaseGlContext(&gl_vinfo, &gl_context);
vo_x11_uninit();
}
@@ -612,6 +627,8 @@
case VOCTRL_RESUME: return (int_pause=0);
case VOCTRL_QUERY_FORMAT:
return query_format(*((uint32_t*)data));
+ case VOCTRL_GUISUPPORT:
+ return VO_TRUE;
case VOCTRL_ONTOP:
vo_x11_ontop();
return VO_TRUE;
diff -u libvo/x11_common.c libvo/x11_common.c
--- libvo/x11_common.c 2004-11-01 00:17:58.000000000 +0100
+++ libvo/x11_common.c 2004-11-01 15:34:34.668122578 +0100
@@ -1133,6 +1133,21 @@
return ret;
}
+/**
+ * \brief sets the size and position of the non-fullscreen window.
+ */
+void vo_x11_nofs_pos(int x, int y, int width, int height)
+{
+ if (vo_fs) {
+ vo_old_x = x;
+ vo_old_y = y;
+ vo_old_width = width;
+ vo_old_height = height;
+ }
+ else
+ XMoveResizeWindow(mDisplay, vo_window, x, y, width, height);
+}
+
void vo_x11_sizehint(int x, int y, int width, int height, int max)
{
vo_hint.flags = PPosition | PSize | PWinGravity;
diff -u libvo/x11_common.h libvo/x11_common.h
--- libvo/x11_common.h 2004-08-10 21:58:48.000000000 +0200
+++ libvo/x11_common.h 2004-11-01 14:34:03.000000000 +0100
@@ -52,6 +52,7 @@
extern void vo_showcursor( Display *disp, Window win );
extern void vo_x11_decoration( Display * vo_Display,Window w,int d );
extern void vo_x11_classhint( Display * display,Window window,char *name );
+extern void vo_x11_nofs_pos(int x, int y, int width, int height);
extern void vo_x11_sizehint( int x, int y, int width, int height, int max );
extern int vo_x11_check_events(Display *mydisplay);
extern void vo_x11_selectinput_witherr(Display *display, Window w, long event_mask);
More information about the MPlayer-dev-eng
mailing list