OpenGL OSD rendering for vo_gl

git-svn-id: svn://svn.mplayerhq.hu/mplayer/trunk@13586 b3059339-0415-0410-9bf9-f77b7e298cf2
This commit is contained in:
reimar 2004-10-08 19:53:11 +00:00
parent 9f3bc811f4
commit 274c433f07
2 changed files with 154 additions and 4 deletions

View File

@ -2521,17 +2521,21 @@ Use svga with VIDIX.
.TP
.B gl\ \ \ \ \
OpenGL video output driver.
Very simple version, no OSD support and video size must be smaller than
Simple version, video size must be smaller than
the maximum texture size of your OpenGL implementation.
Intended to work even with the most simple OpenGL implementations.
.PD 0
.RSs
.IPs (no)manyfmts
Enables support for more (RGB and BGR) color formats.
Needs OpenGL version >= 1.2, NOT yet WORKING correctly.
Needs OpenGL version >= 1.2.
.IPs slice-height=<0\-...>
Number of lines copied to texture in one piece (default: 4).
0 for whole image.
.IPs (no)osd
Enable or disable support for OSD rendering via OpenGL.
Mostly for testing, you should use \-osdlevel 0 to disable OSD.
Default: enabled
.RE
.PD 1
.

View File

@ -10,6 +10,8 @@
#include "config.h"
#include "video_out.h"
#include "video_out_internal.h"
#include "font_load.h"
#include "sub.h"
#include <X11/Xlib.h>
#include <X11/Xutil.h>
@ -40,6 +42,14 @@ static int wsGLXAttrib[] = { GLX_RGBA,
GLX_DOUBLEBUFFER,
None };
int use_osd;
#define MAX_OSD_PARTS 20
GLuint osdtex[MAX_OSD_PARTS];
#ifndef FAST_OSD
GLuint osdatex[MAX_OSD_PARTS];
#endif
GLuint osdDispList[MAX_OSD_PARTS];
int osdtexCnt = 0;
static uint32_t image_width;
static uint32_t image_height;
@ -66,6 +76,12 @@ static void resize(int x,int y){
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
#ifdef HAVE_FREETYPE
// adjust font size to display size
force_load_font = 1;
#endif
vo_osd_changed(1);
}
static int find_gl_format (uint32_t format)
@ -162,6 +178,7 @@ config(uint32_t width, uint32_t height, uint32_t d_width, uint32_t d_height, uin
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;
aspect_save_orig(width,height);
@ -291,8 +308,110 @@ static void check_events(void)
if(e&VO_EVENT_EXPOSE && int_pause) flip_page();
}
/**
* Creates the textures and the display list needed for displaying
* an OSD part.
* Callback function for vo_draw_text().
*/
static void create_osd_texture(int x0, int y0, int w, int h,
unsigned char *src, unsigned char *srca,
int stride)
{
int sx = 1, sy = 1;
GLfloat xcov, ycov;
char *clearTexture;
while (sx < w) sx *= 2;
while (sy < h) sy *= 2;
xcov = (GLfloat) w / (GLfloat) sx;
ycov = (GLfloat) h / (GLfloat) sy;
if (osdtexCnt >= MAX_OSD_PARTS) {
mp_msg(MSGT_VO, MSGL_ERR, "Too many OSD parts, contact the developers!\n");
return;
}
clearTexture = malloc(sx * sy);
memset(clearTexture, 0, sx * sy);
// create Textures for OSD part
glGenTextures(1, &osdtex[osdtexCnt]);
glBindTexture(GL_TEXTURE_2D, osdtex[osdtexCnt]);
glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, sx, sy, 0,
GL_LUMINANCE, GL_UNSIGNED_BYTE, clearTexture);
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glPixelStorei(GL_UNPACK_ROW_LENGTH, stride);
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, w, h, GL_LUMINANCE,
GL_UNSIGNED_BYTE, src);
glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
#ifndef FAST_OSD
glGenTextures(1, &osdatex[osdtexCnt]);
glBindTexture(GL_TEXTURE_2D, osdatex[osdtexCnt]);
glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, sx, sy, 0,
GL_LUMINANCE, GL_UNSIGNED_BYTE, clearTexture);
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glPixelStorei(GL_UNPACK_ROW_LENGTH, stride);
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, w, h, GL_ALPHA,
GL_UNSIGNED_BYTE, srca);
glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
#endif
glBindTexture(GL_TEXTURE_2D, 0);
free(clearTexture);
// Create a list for rendering this OSD part
osdDispList[osdtexCnt] = glGenLists(1);
glNewList(osdDispList[osdtexCnt], GL_COMPILE);
#ifndef FAST_OSD
// render alpha
glBlendFunc(GL_ZERO, GL_SRC_ALPHA);
glBindTexture(GL_TEXTURE_2D, osdatex[osdtexCnt]);
glBegin(GL_QUADS);
glTexCoord2f (0, 0);
glVertex2f (x0, y0);
glTexCoord2f (0, ycov);
glVertex2f (x0, y0 + h);
glTexCoord2f (xcov, ycov);
glVertex2f (x0 + w, y0 + h);
glTexCoord2f (xcov, 0);
glVertex2f (x0 + w, y0);
glEnd();
#endif
// render OSD
glBlendFunc (GL_ONE, GL_ONE);
glBindTexture(GL_TEXTURE_2D, osdtex[osdtexCnt]);
glBegin(GL_QUADS);
glTexCoord2f (0, 0);
glVertex2f (x0, y0);
glTexCoord2f (0, ycov);
glVertex2f (x0, y0 + h);
glTexCoord2f (xcov, ycov);
glVertex2f (x0 + w, y0 + h);
glTexCoord2f (xcov, 0);
glVertex2f (x0 + w, y0);
glEnd();
glEndList();
osdtexCnt++;
}
static void draw_osd(void)
{
int i;
if (!use_osd) return;
if (vo_osd_changed(0)) {
for (i = 0; i < osdtexCnt; i++) {
glDeleteTextures(1, &osdtex[i]);
#ifndef FAST_OSD
glDeleteTextures(1, &osdatex[i]);
#endif
glDeleteLists(osdDispList[i], 1);
}
osdtexCnt = 0;
// draw OSD with full resolution
vo_draw_text(vo_dwidth, vo_dheight, create_osd_texture);
}
}
static void
@ -310,6 +429,21 @@ flip_page(void)
glTexCoord2f(1,0);glVertex2i(texture_width,0);
glEnd();
if (osdtexCnt > 0) {
// set special rendering parameters
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();
glOrtho(0, vo_dwidth, vo_dheight, 0, -1, 1);
glEnable(GL_BLEND);
// draw OSD
glCallLists(osdtexCnt, GL_UNSIGNED_INT, osdDispList);
// set rendering parameters back to defaults
glDisable (GL_BLEND);
glPopMatrix();
glBindTexture(GL_TEXTURE_2D, 0);
}
// glFlush();
glFinish();
glXSwapBuffers( mDisplay,vo_window );
@ -352,10 +486,13 @@ uint8_t *ImageData=src[0];
static uint32_t
query_format(uint32_t format)
{
int caps = VFCAP_CSP_SUPPORTED | VFCAP_CSP_SUPPORTED_BY_HW;
if (use_osd)
caps |= VFCAP_OSD;
if ((format == IMGFMT_RGB24) || (format == IMGFMT_RGBA))
return VFCAP_CSP_SUPPORTED | VFCAP_CSP_SUPPORTED_BY_HW;
return caps;
if (many_fmts && find_gl_format(format))
return VFCAP_CSP_SUPPORTED | VFCAP_CSP_SUPPORTED_BY_HW;
return caps;
return 0;
}
@ -372,6 +509,7 @@ static uint32_t preinit(const char *arg)
int parse_err = 0;
unsigned int parse_pos = 0;
many_fmts = 0;
use_osd = 1;
slice_height = 4;
if(arg)
{
@ -382,6 +520,12 @@ static uint32_t preinit(const char *arg)
} else if (strncmp (&arg[parse_pos], "nomanyfmts", 10) == 0) {
parse_pos += 10;
many_fmts = 0;
} else if (strncmp (&arg[parse_pos], "osd", 3) == 0) {
parse_pos += 3;
use_osd = 1;
} else if (strncmp (&arg[parse_pos], "noosd", 5) == 0) {
parse_pos += 5;
use_osd = 0;
} else if (strncmp (&arg[parse_pos], "slice-height=", 13) == 0) {
int val;
char *end;
@ -411,6 +555,8 @@ static uint32_t preinit(const char *arg)
" Enable extended color formats for OpenGL 1.2 and later\n"
" slice-height=<0-...>\n"
" Slice size for texture transfer, 0 for whole image\n"
" noosd\n"
" Do not use OpenGL OSD code\n"
"\n" );
return -1;
}