[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