fullscreen fixes and GUI support for vo_gl

git-svn-id: svn://svn.mplayerhq.hu/mplayer/trunk@13844 b3059339-0415-0410-9bf9-f77b7e298cf2
This commit is contained in:
reimar 2004-11-01 20:24:37 +00:00
parent 0e49449d13
commit 1a7a3f8b38
5 changed files with 209 additions and 57 deletions

View File

@ -17,3 +17,101 @@ void glAdjustAlignment(int stride) {
glPixelStorei (GL_UNPACK_ALIGNMENT, gl_alignment);
}
#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

View File

@ -1,8 +1,29 @@
#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);
//! 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
int setGlWindow(XVisualInfo **vinfo, GLXContext *context, Window win);
#endif
#endif

View File

@ -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 @@ static vo_info_t info =
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 @@ static int find_gl_format (uint32_t format)
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 @@ config(uint32_t width, uint32_t height, uint32_t d_width, uint32_t d_height, uin
// 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 @@ config(uint32_t width, uint32_t height, uint32_t d_width, uint32_t d_height, uin
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 @@ config(uint32_t width, uint32_t height, uint32_t d_width, uint32_t d_height, uin
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 @@ config(uint32_t width, uint32_t height, uint32_t d_width, uint32_t d_height, uin
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_sizepos(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 @@ static void
uninit(void)
{
if ( !vo_config_count ) return;
releaseGlContext(&gl_vinfo, &gl_context);
vo_x11_uninit();
}
@ -612,6 +627,8 @@ static uint32_t control(uint32_t request, void *data, ...)
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;

View File

@ -1133,6 +1133,21 @@ int vo_x11_check_events(Display * mydisplay)
return ret;
}
/**
* \brief sets the size and position of the non-fullscreen window.
*/
void vo_x11_nofs_sizepos(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;

View File

@ -52,6 +52,7 @@ extern void vo_hidecursor ( Display* , Window );
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_sizepos(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);