summaryrefslogtreecommitdiffstats
path: root/libvo/vo_gl.c
diff options
context:
space:
mode:
authorwm4 <wm4@mplayer2.org>2011-09-25 11:18:07 +0200
committerUoti Urpala <uau@mplayer2.org>2011-10-24 06:13:17 +0300
commitc852246cdf3e2604d1a3bff1fccd981d7b3b58c9 (patch)
tree132f089b74befd752483e8c399e432427fe25270 /libvo/vo_gl.c
parent821a313ba183b9eed8b280cbfda84a3f95a2ab2e (diff)
downloadmpv-c852246cdf3e2604d1a3bff1fccd981d7b3b58c9.tar.bz2
mpv-c852246cdf3e2604d1a3bff1fccd981d7b3b58c9.tar.xz
vo_gl: convert to new API, clean up code
Reformat vo_gl.c, gl_common.c, gl_common.h. Remove all global variables and move them into a context struct (the Windows and SDL backends still refer to global_vo though). Change vo_gl.c to use the "new" VO API.
Diffstat (limited to 'libvo/vo_gl.c')
-rw-r--r--libvo/vo_gl.c2485
1 files changed, 1336 insertions, 1149 deletions
diff --git a/libvo/vo_gl.c b/libvo/vo_gl.c
index cb1ccc593b..7a7c718c88 100644
--- a/libvo/vo_gl.c
+++ b/libvo/vo_gl.c
@@ -28,13 +28,21 @@
#include <stdbool.h>
#include "config.h"
+#include "talloc.h"
#include "mp_msg.h"
#include "subopt-helper.h"
#include "video_out.h"
-#include "video_out_internal.h"
+#include "libmpcodecs/vfcap.h"
+#include "libmpcodecs/mp_image.h"
+#include "geometry.h"
+#include "osd.h"
#include "sub/font_load.h"
#include "sub/sub.h"
+#ifdef CONFIG_GL_X11
+#include "x11_common.h"
+#endif
+
#include "gl_common.h"
#include "aspect.h"
#include "fastmemcpy.h"
@@ -48,298 +56,296 @@
#endif
#endif
-static const vo_info_t info =
-{
- "OpenGL",
- "gl",
- "Reimar Doeffinger <Reimar.Doeffinger@gmx.de>",
- ""
-};
-
-const LIBVO_EXTERN(gl)
-
-
-static const vo_info_t info_nosw =
-{
- "OpenGL no software rendering",
- "gl_nosw",
- "Reimar Doeffinger <Reimar.Doeffinger@gmx.de>",
- ""
-};
-static int preinit_nosw(const char *arg);
-const struct vo_driver video_out_gl_nosw =
-{
- .is_new = 0,
- .info = &info_nosw,
- .preinit = old_vo_preinit,
- .config = old_vo_config,
- .control = old_vo_control,
- .draw_slice = old_vo_draw_slice,
- .draw_osd = old_vo_draw_osd,
- .flip_page = old_vo_flip_page,
- .check_events = old_vo_check_events,
- .uninit = old_vo_uninit,
- .old_functions = &(struct vo_old_functions){
- preinit_nosw,
- config,
- control,
- draw_frame,
- draw_slice,
- draw_osd,
- flip_page,
- check_events,
- uninit,
- }
-};
-static MPGLContext glctx;
+static int preinit_nosw(struct vo *vo, const char *arg);
-static int use_osd;
-static int scaled_osd;
//! How many parts the OSD may consist of at most
#define MAX_OSD_PARTS 20
-//! Textures for OSD
-static GLuint osdtex[MAX_OSD_PARTS];
-#ifndef FAST_OSD
-//! Alpha textures for OSD
-static GLuint osdatex[MAX_OSD_PARTS];
-#endif
-static GLuint *eosdtex;
+
#define LARGE_EOSD_TEX_SIZE 512
#define TINYTEX_SIZE 16
-#define TINYTEX_COLS (LARGE_EOSD_TEX_SIZE/TINYTEX_SIZE)
-#define TINYTEX_MAX (TINYTEX_COLS*TINYTEX_COLS)
+#define TINYTEX_COLS (LARGE_EOSD_TEX_SIZE / TINYTEX_SIZE)
+#define TINYTEX_MAX (TINYTEX_COLS * TINYTEX_COLS)
#define SMALLTEX_SIZE 32
-#define SMALLTEX_COLS (LARGE_EOSD_TEX_SIZE/SMALLTEX_SIZE)
-#define SMALLTEX_MAX (SMALLTEX_COLS*SMALLTEX_COLS)
-static GLuint largeeosdtex[2];
-//! Display lists that draw the OSD parts
-static GLuint osdDispList[MAX_OSD_PARTS];
-#ifndef FAST_OSD
-static GLuint osdaDispList[MAX_OSD_PARTS];
-#endif
-static GLuint eosdDispList;
-//! How many parts the OSD currently consists of
-static int osdtexCnt;
-static int eosdtexCnt;
-static int osd_color;
-
-static int use_aspect;
-static int use_ycbcr;
+#define SMALLTEX_COLS (LARGE_EOSD_TEX_SIZE / SMALLTEX_SIZE)
+#define SMALLTEX_MAX (SMALLTEX_COLS * SMALLTEX_COLS)
+
+//for gl_priv.use_yuv
#define MASK_ALL_YUV (~(1 << YUV_CONVERSION_NONE))
#define MASK_NOT_COMBINERS (~((1 << YUV_CONVERSION_NONE) | (1 << YUV_CONVERSION_COMBINERS)))
#define MASK_GAMMA_SUPPORT (MASK_NOT_COMBINERS & ~(1 << YUV_CONVERSION_FRAGMENT))
-static int use_yuv;
-static struct mp_csp_details colorspace = MP_CSP_DETAILS_DEFAULTS;
-static int user_colorspace; //essentially unused; legacy warning
-static int levelconv; //essentially unused; legacy warning
-static int is_yuv;
-static int lscale;
-static int cscale;
-static float filter_strength;
-static int yuvconvtype;
-static int use_rectangle;
-static int err_shown;
-static uint32_t image_width;
-static uint32_t image_height;
-static uint32_t image_format;
-static int many_fmts;
-static int ati_hack;
-static int force_pbo;
-static int mesa_buffer;
-static int use_glFinish;
-static int swap_interval;
-static GLenum gl_target;
-static GLint gl_texfmt;
-static GLenum gl_format;
-static GLenum gl_type;
-static GLuint gl_buffer;
-static GLuint gl_buffer_uv[2];
-static int gl_buffersize;
-static int gl_buffersize_uv;
-static void *gl_bufferptr;
-static void *gl_bufferptr_uv[2];
-static int mesa_buffersize;
-static void *mesa_bufferptr;
-static GLuint fragprog;
-static GLuint default_texs[22];
-static char *custom_prog;
-static char *custom_tex;
-static int custom_tlin;
-static int custom_trect;
-static int mipmap_gen;
-static int stereo_mode;
-
-static int int_pause;
-
-static struct mp_csp_equalizer video_eq;
-
-static int texture_width;
-static int texture_height;
-static int mpi_flipped;
-static int vo_flipped;
-static int ass_border_x, ass_border_y;
-
-static unsigned int slice_height = 1;
-
-static void redraw(void);
-
-static void resize(int x,int y){
- mp_msg(MSGT_VO, MSGL_V, "[gl] Resize: %dx%d\n",x,y);
- if (WinID >= 0) {
- int left = 0, top = 0, w = x, h = y;
- geometry(&left, &top, &w, &h, vo_dwidth, vo_dheight);
- top = y - h - top;
- mpglViewport(left, top, w, h);
- } else
- mpglViewport( 0, 0, x, y );
-
- mpglMatrixMode(GL_PROJECTION);
- mpglLoadIdentity();
- ass_border_x = ass_border_y = 0;
- if (aspect_scaling() && use_aspect) {
- int new_w, new_h;
- GLdouble scale_x, scale_y;
- aspect(&new_w, &new_h, A_WINZOOM);
- panscan_calc_windowed();
- new_w += vo_panscan_x;
- new_h += vo_panscan_y;
- scale_x = (GLdouble)new_w / (GLdouble)x;
- scale_y = (GLdouble)new_h / (GLdouble)y;
- mpglScaled(scale_x, scale_y, 1);
- ass_border_x = (vo_dwidth - new_w) / 2;
- ass_border_y = (vo_dheight - new_h) / 2;
- }
- mpglOrtho(0, image_width, image_height, 0, -1,1);
-
- mpglMatrixMode(GL_MODELVIEW);
- mpglLoadIdentity();
-
- if (!scaled_osd) {
+
+struct gl_priv {
+ MPGLContext *glctx;
+ GL *gl;
+
+ int use_osd;
+ int scaled_osd;
+ //! Textures for OSD
+ GLuint osdtex[MAX_OSD_PARTS];
+#ifndef FAST_OSD
+ //! Alpha textures for OSD
+ GLuint osdatex[MAX_OSD_PARTS];
+#endif
+ GLuint *eosdtex;
+ GLuint largeeosdtex[2];
+ //! Display lists that draw the OSD parts
+ GLuint osdDispList[MAX_OSD_PARTS];
+#ifndef FAST_OSD
+ GLuint osdaDispList[MAX_OSD_PARTS];
+#endif
+ GLuint eosdDispList;
+ //! How many parts the OSD currently consists of
+ int osdtexCnt;
+ int eosdtexCnt;
+ int osd_color;
+
+ int use_aspect;
+ int use_ycbcr;
+ int use_yuv;
+ struct mp_csp_details colorspace;
+ int is_yuv;
+ int lscale;
+ int cscale;
+ float filter_strength;
+ int yuvconvtype;
+ int use_rectangle;
+ int err_shown;
+ uint32_t image_width;
+ uint32_t image_height;
+ uint32_t image_format;
+ uint32_t image_d_width;
+ uint32_t image_d_height;
+ int many_fmts;
+ int ati_hack;
+ int force_pbo;
+ int mesa_buffer;
+ int use_glFinish;
+ int swap_interval;
+ GLenum target;
+ GLint texfmt;
+ GLenum gl_format;
+ GLenum gl_type;
+ GLuint buffer;
+ GLuint buffer_uv[2];
+ int buffersize;
+ int buffersize_uv;
+ void *bufferptr;
+ void *bufferptr_uv[2];
+ int mesa_buffersize;
+ void *mesa_bufferptr;
+ GLuint fragprog;
+ GLuint default_texs[22];
+ char *custom_prog;
+ char *custom_tex;
+ int custom_tlin;
+ int custom_trect;
+ int mipmap_gen;
+ int stereo_mode;
+
+ int int_pause;
+
+ struct mp_csp_equalizer video_eq;
+
+ int texture_width;
+ int texture_height;
+ int mpi_flipped;
+ int vo_flipped;
+ int ass_border_x, ass_border_y;
+
+ unsigned int slice_height;
+};
+
+static void redraw(struct vo *vo);
+
+static void resize(struct vo *vo, int x, int y)
+{
+ struct gl_priv *p = vo->priv;
+ GL *gl = p->gl;
+
+ mp_msg(MSGT_VO, MSGL_V, "[gl] Resize: %dx%d\n", x, y);
+ if (WinID >= 0) {
+ int left = 0, top = 0, w = x, h = y;
+ geometry(&left, &top, &w, &h, vo->dwidth, vo->dheight);
+ top = y - h - top;
+ gl->Viewport(left, top, w, h);
+ } else
+ gl->Viewport(0, 0, x, y);
+
+ gl->MatrixMode(GL_PROJECTION);
+ gl->LoadIdentity();
+ p->ass_border_x = p->ass_border_y = 0;
+ if (aspect_scaling() && p->use_aspect) {
+ int new_w, new_h;
+ GLdouble scale_x, scale_y;
+ aspect(vo, &new_w, &new_h, A_WINZOOM);
+ panscan_calc_windowed(vo);
+ new_w += vo->panscan_x;
+ new_h += vo->panscan_y;
+ scale_x = (GLdouble)new_w / (GLdouble)x;
+ scale_y = (GLdouble)new_h / (GLdouble)y;
+ gl->Scaled(scale_x, scale_y, 1);
+ p->ass_border_x = (vo->dwidth - new_w) / 2;
+ p->ass_border_y = (vo->dheight - new_h) / 2;
+ }
+ gl->Ortho(0, p->image_width, p->image_height, 0, -1, 1);
+
+ gl->MatrixMode(GL_MODELVIEW);
+ gl->LoadIdentity();
+
+ if (!p->scaled_osd) {
#ifdef CONFIG_FREETYPE
- // adjust font size to display size
- force_load_font = 1;
+ // adjust font size to display size
+ force_load_font = 1;
#endif
- vo_osd_changed(OSDTYPE_OSD);
- }
- mpglClear(GL_COLOR_BUFFER_BIT);
- redraw();
+ vo_osd_changed(OSDTYPE_OSD);
+ }
+ gl->Clear(GL_COLOR_BUFFER_BIT);
+ redraw(vo);
}
-static void texSize(int w, int h, int *texw, int *texh) {
- if (use_rectangle) {
- *texw = w; *texh = h;
- } else {
- *texw = 32;
- while (*texw < w)
- *texw *= 2;
- *texh = 32;
- while (*texh < h)
- *texh *= 2;
- }
- if (mesa_buffer) *texw = (*texw + 63) & ~63;
- else if (ati_hack) *texw = (*texw + 511) & ~511;
+static void texSize(struct vo *vo, int w, int h, int *texw, int *texh)
+{
+ struct gl_priv *p = vo->priv;
+
+ if (p->use_rectangle) {
+ *texw = w;
+ *texh = h;
+ } else {
+ *texw = 32;
+ while (*texw < w)
+ *texw *= 2;
+ *texh = 32;
+ while (*texh < h)
+ *texh *= 2;
+ }
+ if (p->mesa_buffer)
+ *texw = (*texw + 63) & ~63;
+ else if (p->ati_hack)
+ *texw = (*texw + 511) & ~511;
}
//! maximum size of custom fragment program
#define MAX_CUSTOM_PROG_SIZE (1024 * 1024)
-static void update_yuvconv(void) {
- int xs, ys, depth;
- struct mp_csp_params cparams = { .colorspace = colorspace };
- mp_csp_copy_equalizer_values(&cparams, &video_eq);
- gl_conversion_params_t params = {gl_target, yuvconvtype, cparams,
- texture_width, texture_height, 0, 0, filter_strength};
- mp_get_chroma_shift(image_format, &xs, &ys, &depth);
- params.chrom_texw = params.texw >> xs;
- params.chrom_texh = params.texh >> ys;
- params.csp_params.input_shift = -depth & 7;
- glSetupYUVConversion(&params);
- if (custom_prog) {
- FILE *f = fopen(custom_prog, "rb");
- if (!f) {
- mp_msg(MSGT_VO, MSGL_WARN,
- "[gl] Could not read customprog %s\n", custom_prog);
- } else {
- char *prog = calloc(1, MAX_CUSTOM_PROG_SIZE + 1);
- fread(prog, 1, MAX_CUSTOM_PROG_SIZE, f);
- fclose(f);
- loadGPUProgram(GL_FRAGMENT_PROGRAM, prog);
- free(prog);
+static void update_yuvconv(struct vo *vo)
+{
+ struct gl_priv *p = vo->priv;
+ GL *gl = p->gl;
+
+ int xs, ys, depth;
+ struct mp_csp_params cparams = { .colorspace = p->colorspace };
+ mp_csp_copy_equalizer_values(&cparams, &p->video_eq);
+ gl_conversion_params_t params = {
+ p->target, p->yuvconvtype, cparams,
+ p->texture_width, p->texture_height, 0, 0, p->filter_strength
+ };
+ mp_get_chroma_shift(p->image_format, &xs, &ys, &depth);
+ params.chrom_texw = params.texw >> xs;
+ params.chrom_texh = params.texh >> ys;
+ params.csp_params.input_shift = -depth & 7;
+ glSetupYUVConversion(gl, &params);
+ if (p->custom_prog) {
+ FILE *f = fopen(p->custom_prog, "rb");
+ if (!f) {
+ mp_msg(MSGT_VO, MSGL_WARN,
+ "[gl] Could not read customprog %s\n", p->custom_prog);
+ } else {
+ char *prog = calloc(1, MAX_CUSTOM_PROG_SIZE + 1);
+ fread(prog, 1, MAX_CUSTOM_PROG_SIZE, f);
+ fclose(f);
+ loadGPUProgram(gl, GL_FRAGMENT_PROGRAM, prog);
+ free(prog);
+ }
+ gl->ProgramEnvParameter4f(GL_FRAGMENT_PROGRAM, 0,
+ 1.0 / p->texture_width,
+ 1.0 / p->texture_height,
+ p->texture_width, p->texture_height);
}
- mpglProgramEnvParameter4f(GL_FRAGMENT_PROGRAM, 0,
- 1.0 / texture_width, 1.0 / texture_height,
- texture_width, texture_height);
- }
- if (custom_tex) {
- FILE *f = fopen(custom_tex, "rb");
- if (!f) {
- mp_msg(MSGT_VO, MSGL_WARN,
- "[gl] Could not read customtex %s\n", custom_tex);
- } else {
- int width, height, maxval;
- mpglActiveTexture(GL_TEXTURE3);
- if (glCreatePPMTex(custom_trect?GL_TEXTURE_RECTANGLE:GL_TEXTURE_2D, 0,
- custom_tlin?GL_LINEAR:GL_NEAREST,
- f, &width, &height, &maxval)) {
- mpglProgramEnvParameter4f(GL_FRAGMENT_PROGRAM, 1,
- 1.0 / width, 1.0 / height, width, height);
- } else
- mp_msg(MSGT_VO, MSGL_WARN,
- "[gl] Error parsing customtex %s\n", custom_tex);
- fclose(f);
- mpglActiveTexture(GL_TEXTURE0);
+ if (p->custom_tex) {
+ FILE *f = fopen(p->custom_tex, "rb");
+ if (!f) {
+ mp_msg(MSGT_VO, MSGL_WARN,
+ "[gl] Could not read customtex %s\n", p->custom_tex);
+ } else {
+ int width, height, maxval;
+ gl->ActiveTexture(GL_TEXTURE3);
+ if (glCreatePPMTex(gl, p->custom_trect ? GL_TEXTURE_RECTANGLE : GL_TEXTURE_2D,
+ 0, p->custom_tlin ? GL_LINEAR : GL_NEAREST,
+ f, &width, &height, &maxval)) {
+ gl->ProgramEnvParameter4f(GL_FRAGMENT_PROGRAM, 1,
+ 1.0 / width, 1.0 / height,
+ width, height);
+ } else
+ mp_msg(MSGT_VO, MSGL_WARN,
+ "[gl] Error parsing customtex %s\n", p->custom_tex);
+ fclose(f);
+ gl->ActiveTexture(GL_TEXTURE0);
+ }
}
- }
}
/**
* \brief remove all OSD textures and display-lists, thus clearing it.
*/
-static void clearOSD(void) {
- int i;
- if (!osdtexCnt)
- return;
- mpglDeleteTextures(osdtexCnt, osdtex);
+static void clearOSD(struct vo *vo)
+{
+ struct gl_priv *p = vo->priv;
+ GL *gl = p->gl;
+
+ int i;
+ if (!p->osdtexCnt)
+ return;
+ gl->DeleteTextures(p->osdtexCnt, p->osdtex);
#ifndef FAST_OSD
- mpglDeleteTextures(osdtexCnt, osdatex);
- for (i = 0; i < osdtexCnt; i++)
- mpglDeleteLists(osdaDispList[i], 1);
+ gl->DeleteTextures(p->osdtexCnt, p->osdatex);
+ for (i = 0; i < p->osdtexCnt; i++)
+ gl->DeleteLists(p->osdaDispList[i], 1);
#endif
- for (i = 0; i < osdtexCnt; i++)
- mpglDeleteLists(osdDispList[i], 1);
- osdtexCnt = 0;
+ for (i = 0; i < p->osdtexCnt; i++)
+ gl->DeleteLists(p->osdDispList[i], 1);
+ p->osdtexCnt = 0;
}
/**
* \brief remove textures, display list and free memory used by EOSD
*/
-static void clearEOSD(void) {
- if (eosdDispList)
- mpglDeleteLists(eosdDispList, 1);
- eosdDispList = 0;
- if (eosdtexCnt)
- mpglDeleteTextures(eosdtexCnt, eosdtex);
- eosdtexCnt = 0;
- free(eosdtex);
- eosdtex = NULL;
+static void clearEOSD(struct vo *vo)
+{
+ struct gl_priv *p = vo->priv;
+ GL *gl = p->gl;
+
+ if (p->eosdDispList)
+ gl->DeleteLists(p->eosdDispList, 1);
+ p->eosdDispList = 0;
+ if (p->eosdtexCnt)
+ gl->DeleteTextures(p->eosdtexCnt, p->eosdtex);
+ p->eosdtexCnt = 0;
+ free(p->eosdtex);
+ p->eosdtex = NULL;
}
-static inline int is_tinytex(ASS_Image *i, int tinytexcur) {
- return i->w < TINYTEX_SIZE && i->h < TINYTEX_SIZE && tinytexcur < TINYTEX_MAX;
+static inline int is_tinytex(ASS_Image *i, int tinytexcur)
+{
+ return i->w < TINYTEX_SIZE && i->h < TINYTEX_SIZE
+ && tinytexcur < TINYTEX_MAX;
}
-static inline int is_smalltex(ASS_Image *i, int smalltexcur) {
- return i->w < SMALLTEX_SIZE && i->h < SMALLTEX_SIZE && smalltexcur < SMALLTEX_MAX;
+static inline int is_smalltex(ASS_Image *i, int smalltexcur)
+{
+ return i->w < SMALLTEX_SIZE && i->h < SMALLTEX_SIZE
+ && smalltexcur < SMALLTEX_MAX;
}
-static inline void tinytex_pos(int tinytexcur, int *x, int *y) {
- *x = (tinytexcur % TINYTEX_COLS) * TINYTEX_SIZE;
- *y = (tinytexcur / TINYTEX_COLS) * TINYTEX_SIZE;
+static inline void tinytex_pos(int tinytexcur, int *x, int *y)
+{
+ *x = (tinytexcur % TINYTEX_COLS) * TINYTEX_SIZE;
+ *y = (tinytexcur / TINYTEX_COLS) * TINYTEX_SIZE;
}
-static inline void smalltex_pos(int smalltexcur, int *x, int *y) {
- *x = (smalltexcur % SMALLTEX_COLS) * SMALLTEX_SIZE;
- *y = (smalltexcur / SMALLTEX_COLS) * SMALLTEX_SIZE;
+static inline void smalltex_pos(int smalltexcur, int *x, int *y)
+{
+ *x = (smalltexcur % SMALLTEX_COLS) * SMALLTEX_SIZE;
+ *y = (smalltexcur / SMALLTEX_COLS) * SMALLTEX_SIZE;
}
/**
@@ -347,438 +353,495 @@ static inline void smalltex_pos(int smalltexcur, int *x, int *y) {
* \param img image list to create OSD from.
* A value of NULL has the same effect as clearEOSD()
*/
-static void genEOSD(mp_eosd_images_t *imgs) {
- int sx, sy;
- int tinytexcur = 0;
- int smalltexcur = 0;
- GLuint *curtex;
- GLint scale_type = scaled_osd ? GL_LINEAR : GL_NEAREST;
- ASS_Image *img = imgs->imgs;
- ASS_Image *i;
-
- if (imgs->changed == 0) // there are elements, but they are unchanged
- return;
- if (img && imgs->changed == 1) // there are elements, but they just moved
- goto skip_upload;
-
- clearEOSD();
- if (!img)
- return;
- if (!largeeosdtex[0]) {
- mpglGenTextures(2, largeeosdtex);
- mpglBindTexture(gl_target, largeeosdtex[0]);
- glCreateClearTex(gl_target, GL_ALPHA, GL_ALPHA, GL_UNSIGNED_BYTE, scale_type, LARGE_EOSD_TEX_SIZE, LARGE_EOSD_TEX_SIZE, 0);
- mpglBindTexture(gl_target, largeeosdtex[1]);
- glCreateClearTex(gl_target, GL_ALPHA, GL_ALPHA, GL_UNSIGNED_BYTE, scale_type, LARGE_EOSD_TEX_SIZE, LARGE_EOSD_TEX_SIZE, 0);
- }
- for (i = img; i; i = i->next)
- {
- if (i->w <= 0 || i->h <= 0 || i->stride < i->w)
- continue;
- if (is_tinytex(i, tinytexcur))
- tinytexcur++;
- else if (is_smalltex(i, smalltexcur))
- smalltexcur++;
- else
- eosdtexCnt++;
- }
- mp_msg(MSGT_VO, MSGL_DBG2, "EOSD counts (tiny, small, all): %i, %i, %i\n",
- tinytexcur, smalltexcur, eosdtexCnt);
- if (eosdtexCnt) {
- eosdtex = calloc(eosdtexCnt, sizeof(GLuint));
- mpglGenTextures(eosdtexCnt, eosdtex);
- }
- tinytexcur = smalltexcur = 0;
- for (i = img, curtex = eosdtex; i; i = i->next) {
- int x = 0, y = 0;
- if (i->w <= 0 || i->h <= 0 || i->stride < i->w) {
- mp_msg(MSGT_VO, MSGL_V, "Invalid dimensions OSD for part!\n");
- continue;
+static void genEOSD(struct vo *vo, mp_eosd_images_t *imgs)
+{
+ struct gl_priv *p = vo->priv;
+ GL *gl = p->gl;
+
+ int sx, sy;
+ int tinytexcur = 0;
+ int smalltexcur = 0;
+ GLuint *curtex;
+ GLint scale_type = p->scaled_osd ? GL_LINEAR : GL_NEAREST;
+ ASS_Image *img = imgs->imgs;
+ ASS_Image *i;
+
+ if (imgs->changed == 0) // there are elements, but they are unchanged
+ return;
+ if (img && imgs->changed == 1) // there are elements, but they just moved
+ goto skip_upload;
+
+ clearEOSD(vo);
+ if (!img)
+ return;
+ if (!p->largeeosdtex[0]) {
+ gl->GenTextures(2, p->largeeosdtex);
+ for (int n = 0; n < 2; n++) {
+ gl->BindTexture(p->target, p->largeeosdtex[n]);
+ glCreateClearTex(gl, p->target, GL_ALPHA, GL_ALPHA,
+ GL_UNSIGNED_BYTE, scale_type,
+ LARGE_EOSD_TEX_SIZE, LARGE_EOSD_TEX_SIZE, 0);
+ }
}
- if (is_tinytex(i, tinytexcur)) {
- tinytex_pos(tinytexcur, &x, &y);
- mpglBindTexture(gl_target, largeeosdtex[0]);
- tinytexcur++;
- } else if (is_smalltex(i, smalltexcur)) {
- smalltex_pos(smalltexcur, &x, &y);
- mpglBindTexture(gl_target, largeeosdtex[1]);
- smalltexcur++;
- } else {
- texSize(i->w, i->h, &sx, &sy);
- mpglBindTexture(gl_target, *curtex++);
- glCreateClearTex(gl_target, GL_ALPHA, GL_ALPHA, GL_UNSIGNED_BYTE, scale_type, sx, sy, 0);
+ for (i = img; i; i = i->next) {
+ if (i->w <= 0 || i->h <= 0 || i->stride < i->w)
+ continue;
+ if (is_tinytex(i, tinytexcur))
+ tinytexcur++;
+ else if (is_smalltex(i, smalltexcur))
+ smalltexcur++;
+ else
+ p->eosdtexCnt++;
+ }
+ mp_msg(MSGT_VO, MSGL_DBG2, "EOSD counts (tiny, small, all): %i, %i, %i\n",
+ tinytexcur, smalltexcur, p->eosdtexCnt);
+ if (p->eosdtexCnt) {
+ p->eosdtex = calloc(p->eosdtexCnt, sizeof(GLuint));
+ gl->GenTextures(p->eosdtexCnt, p->eosdtex);
}
- glUploadTex(gl_target, GL_ALPHA, GL_UNSIGNED_BYTE, i->bitmap, i->stride,
- x, y, i->w, i->h, 0);
- }
- eosdDispList = mpglGenLists(1);
+ tinytexcur = smalltexcur = 0;
+ for (i = img, curtex = p->eosdtex; i; i = i->next) {
+ int x = 0, y = 0;
+ if (i->w <= 0 || i->h <= 0 || i->stride < i->w) {
+ mp_msg(MSGT_VO, MSGL_V, "Invalid dimensions OSD for part!\n");
+ continue;
+ }
+ if (is_tinytex(i, tinytexcur)) {
+ tinytex_pos(tinytexcur, &x, &y);
+ gl->BindTexture(p->target, p->largeeosdtex[0]);
+ tinytexcur++;
+ } else if (is_smalltex(i, smalltexcur)) {
+ smalltex_pos(smalltexcur, &x, &y);
+ gl->BindTexture(p->target, p->largeeosdtex[1]);
+ smalltexcur++;
+ } else {
+ texSize(vo, i->w, i->h, &sx, &sy);
+ gl->BindTexture(p->target, *curtex++);
+ glCreateClearTex(gl, p->target, GL_ALPHA, GL_ALPHA,
+ GL_UNSIGNED_BYTE, scale_type, sx, sy, 0);
+ }
+ glUploadTex(gl, p->target, GL_ALPHA, GL_UNSIGNED_BYTE, i->bitmap,
+ i->stride, x, y, i->w, i->h, 0);
+ }
+ p->eosdDispList = gl->GenLists(1);
skip_upload:
- mpglNewList(eosdDispList, GL_COMPILE);
- tinytexcur = smalltexcur = 0;
- for (i = img, curtex = eosdtex; i; i = i->next) {
- int x = 0, y = 0;
- if (i->w <= 0 || i->h <= 0 || i->stride < i->w)
- continue;
- mpglColor4ub(i->color >> 24, (i->color >> 16) & 0xff, (i->color >> 8) & 0xff, 255 - (i->color & 0xff));
- if (is_tinytex(i, tinytexcur)) {
- tinytex_pos(tinytexcur, &x, &y);
- sx = sy = LARGE_EOSD_TEX_SIZE;
- mpglBindTexture(gl_target, largeeosdtex[0]);
- tinytexcur++;
- } else if (is_smalltex(i, smalltexcur)) {
- smalltex_pos(smalltexcur, &x, &y);
- sx = sy = LARGE_EOSD_TEX_SIZE;
- mpglBindTexture(gl_target, largeeosdtex[1]);
- smalltexcur++;
- } else {
- texSize(i->w, i->h, &sx, &sy);
- mpglBindTexture(gl_target, *curtex++);
+ gl->NewList(p->eosdDispList, GL_COMPILE);
+ tinytexcur = smalltexcur = 0;
+ for (i = img, curtex = p->eosdtex; i; i = i->next) {
+ int x = 0, y = 0;
+ if (i->w <= 0 || i->h <= 0 || i->stride < i->w)
+ continue;
+ gl->Color4ub(i->color >> 24, (i->color >> 16) & 0xff,
+ (i->color >> 8) & 0xff, 255 - (i->color & 0xff));
+ if (is_tinytex(i, tinytexcur)) {
+ tinytex_pos(tinytexcur, &x, &y);
+ sx = sy = LARGE_EOSD_TEX_SIZE;
+ gl->BindTexture(p->target, p->largeeosdtex[0]);
+ tinytexcur++;
+ } else if (is_smalltex(i, smalltexcur)) {
+ smalltex_pos(smalltexcur, &x, &y);
+ sx = sy = LARGE_EOSD_TEX_SIZE;
+ gl->BindTexture(p->target, p->largeeosdtex[1]);
+ smalltexcur++;
+ } else {
+ texSize(vo, i->w, i->h, &sx, &sy);
+ gl->BindTexture(p->target, *curtex++);
+ }
+ glDrawTex(gl, i->dst_x, i->dst_y, i->w, i->h, x, y, i->w, i->h, sx, sy,
+ p->use_rectangle == 1, 0, 0);
}
- glDrawTex(i->dst_x, i->dst_y, i->w, i->h, x, y, i->w, i->h, sx, sy, use_rectangle == 1, 0, 0);
- }
- mpglEndList();
- mpglBindTexture(gl_target, 0);
+ gl->EndList();
+ gl->BindTexture(p->target, 0);
}
/**
* \brief uninitialize OpenGL context, freeing textures, buffers etc.
*/
-static void uninitGl(void) {
- int i = 0;
- if (mpglDeletePrograms && fragprog)
- mpglDeletePrograms(1, &fragprog);
- fragprog = 0;
- while (default_texs[i] != 0)
- i++;
- if (i)
- mpglDeleteTextures(i, default_texs);
- default_texs[0] = 0;
- clearOSD();
- clearEOSD();
- if (largeeosdtex[0])
- mpglDeleteTextures(2, largeeosdtex);
- largeeosdtex[0] = 0;
- if (mpglDeleteBuffers && gl_buffer)
- mpglDeleteBuffers(1, &gl_buffer);
- gl_buffer = 0; gl_buffersize = 0;
- gl_bufferptr = NULL;
- if (mpglDeleteBuffers && gl_buffer_uv[0])
- mpglDeleteBuffers(2, gl_buffer_uv);
- gl_buffer_uv[0] = gl_buffer_uv[1] = 0; gl_buffersize_uv = 0;
- gl_bufferptr_uv[0] = gl_bufferptr_uv[1] = 0;
+static void uninitGl(struct vo *vo)
+{
+ struct gl_priv *p = vo->priv;
+ GL *gl = p->gl;
+
+ int i = 0;
+ if (gl->DeletePrograms && p->fragprog)
+ gl->DeletePrograms(1, &p->fragprog);
+ p->fragprog = 0;
+ while (p->default_texs[i] != 0)
+ i++;
+ if (i)
+ gl->DeleteTextures(i, p->default_texs);
+ p->default_texs[0] = 0;
+ clearOSD(vo);
+ clearEOSD(vo);
+ if (p->largeeosdtex[0])
+ gl->DeleteTextures(2, p->largeeosdtex);
+ p->largeeosdtex[0] = 0;
+ if (gl->DeleteBuffers && p->buffer)
+ gl->DeleteBuffers(1, &p->buffer);
+ p->buffer = 0;
+ p->buffersize = 0;
+ p->bufferptr = NULL;
+ if (gl->DeleteBuffers && p->buffer_uv[0])
+ gl->DeleteBuffers(2, p->buffer_uv);
+ p->buffer_uv[0] = p->buffer_uv[1] = 0;
+ p->buffersize_uv = 0;
+ p->bufferptr_uv[0] = p->bufferptr_uv[1] = 0;
#ifdef CONFIG_GL_X11
- if (mesa_bufferptr)
- mpglFreeMemoryMESA(mDisplay, mScreen, mesa_bufferptr);
+ if (p->mesa_bufferptr)
+ gl->FreeMemoryMESA(vo->x11->display, vo->x11->screen,
+ p->mesa_bufferptr);
#endif
- mesa_bufferptr = NULL;
- err_shown = 0;
+ p->mesa_bufferptr = NULL;
+ p->err_shown = 0;
}
-static int isSoftwareGl(void)
+static int isSoftwareGl(struct vo *vo)
{
- const char *renderer = mpglGetString(GL_RENDERER);
- return !renderer || strcmp(renderer, "Software Rasterizer") == 0 ||
- strstr(renderer, "llvmpipe");
+ struct gl_priv *p = vo->priv;
+ const char *renderer = p->gl->GetString(GL_RENDERER);
+ return !renderer || strcmp(renderer, "Software Rasterizer") == 0 ||
+ strstr(renderer, "llvmpipe");
}
-static void autodetectGlExtensions(void) {
- const char *extensions = mpglGetString(GL_EXTENSIONS);
- const char *vendor = mpglGetString(GL_VENDOR);
- const char *version = mpglGetString(GL_VERSION);
- const char *renderer = mpglGetString(GL_RENDERER);
- int is_ati = vendor && strstr(vendor, "ATI") != NULL;
- int ati_broken_pbo = 0;
- mp_msg(MSGT_VO, MSGL_V, "[gl] Running on OpenGL '%s' by '%s', version '%s'\n", renderer, vendor, version);
- if (is_ati && strncmp(version, "2.1.", 4) == 0) {
- int ver = atoi(version + 4);
- mp_msg(MSGT_VO, MSGL_V, "[gl] Detected ATI driver version: %i\n", ver);
- ati_broken_pbo = ver && ver < 8395;
- }
- if (ati_hack == -1) ati_hack = ati_broken_pbo;
- if (force_pbo == -1) {
- force_pbo = 0;
- if (extensions && strstr(extensions, "_pixel_buffer_object"))
- force_pbo = is_ati;
- }
- if (use_rectangle == -1) {
- use_rectangle = 0;
- if (extensions) {
+static void autodetectGlExtensions(struct vo *vo)
+{
+ struct gl_priv *p = vo->priv;
+ GL *gl = p->gl;
+
+ const char *extensions = gl->GetString(GL_EXTENSIONS);
+ const char *vendor = gl->GetString(GL_VENDOR);
+ const char *version = gl->GetString(GL_VERSION);
+ const char *renderer = gl->GetString(GL_RENDERER);
+ int is_ati = vendor && strstr(vendor, "ATI") != NULL;
+ int ati_broken_pbo = 0;
+ mp_msg(MSGT_VO, MSGL_V, "[gl] Running on OpenGL '%s' by '%s', version '%s'\n",
+ renderer, vendor, version);
+ if (is_ati && strncmp(version, "2.1.", 4) == 0) {
+ int ver = atoi(version + 4);
+ mp_msg(MSGT_VO, MSGL_V, "[gl] Detected ATI driver version: %i\n", ver);
+ ati_broken_pbo = ver && ver < 8395;
+ }
+ if (p->ati_hack == -1)
+ p->ati_hack = ati_broken_pbo;
+ if (p->force_pbo == -1) {
+ p->force_pbo = 0;
+ if (extensions && strstr(extensions, "_pixel_buffer_object"))
+ p->force_pbo = is_ati;
+ }
+ if (p->use_rectangle == -1) {
+ p->use_rectangle = 0;
+ if (extensions) {
// if (strstr(extensions, "_texture_non_power_of_two"))
- if (strstr(extensions, "_texture_rectangle"))
- use_rectangle = renderer && strstr(renderer, "Mesa DRI R200") ? 1 : 0;
+ if (strstr(extensions, "_texture_rectangle"))
+ p->use_rectangle = renderer
+ && strstr(renderer, "Mesa DRI R200") ? 1 : 0;
+ }
+ }
+ if (p->use_osd == -1)
+ p->use_osd = gl->BindTexture != NULL;
+ if (p->use_yuv == -1)
+ p->use_yuv = glAutodetectYUVConversion(gl);
+
+ int eq_caps = 0;
+ int yuv_mask = (1 << p->use_yuv);
+ if (!(yuv_mask & MASK_NOT_COMBINERS)) {
+ // combiners
+ eq_caps = (1 << MP_CSP_EQ_HUE) | (1 << MP_CSP_EQ_SATURATION);
+ } else if (yuv_mask & MASK_ALL_YUV) {
+ eq_caps = MP_CSP_EQ_CAPS_COLORMATRIX;
+ if (yuv_mask & MASK_GAMMA_SUPPORT)
+ eq_caps |= MP_CSP_EQ_CAPS_GAMMA;
}
- }
- if (use_osd == -1)
- use_osd = mpglBindTexture != NULL;
- if (use_yuv == -1)
- use_yuv = glAutodetectYUVConversion();
-
- int eq_caps = 0;
- int yuv_mask = (1 << use_yuv);
- if (!(yuv_mask & MASK_NOT_COMBINERS)) {
- // combiners
- eq_caps = (1 << MP_CSP_EQ_HUE) | (1 << MP_CSP_EQ_SATURATION);
- } else if (yuv_mask & MASK_ALL_YUV) {
- eq_caps = MP_CSP_EQ_CAPS_COLORMATRIX;
- if (yuv_mask & MASK_GAMMA_SUPPORT)
- eq_caps |= MP_CSP_EQ_CAPS_GAMMA;
- }
- video_eq.capabilities = eq_caps;
-
- if (is_ati && (lscale == 1 || lscale == 2 || cscale == 1 || cscale == 2))
- mp_msg(MSGT_VO, MSGL_WARN, "[gl] Selected scaling mode may be broken on ATI cards.\n"
- "Tell _them_ to fix GL_REPEAT if you have issues.\n");
- mp_msg(MSGT_VO, MSGL_V, "[gl] Settings after autodetection: ati-hack = %i, force-pbo = %i, rectangle = %i, yuv = %i\n",
- ati_hack, force_pbo, use_rectangle, use_yuv);
+ p->video_eq.capabilities = eq_caps;
+
+ if (is_ati && (p->lscale == 1 || p->lscale == 2 || p->cscale == 1 || p->cscale == 2))
+ mp_msg(MSGT_VO, MSGL_WARN, "[gl] Selected scaling mode may be broken on"
+ " ATI cards.\n"
+ "Tell _them_ to fix GL_REPEAT if you have issues.\n");
+ mp_msg(MSGT_VO, MSGL_V, "[gl] Settings after autodetection: ati-hack = %i, "
+ "force-pbo = %i, rectangle = %i, yuv = %i\n",
+ p->ati_hack, p->force_pbo, p->use_rectangle, p->use_yuv);
}
-static GLint get_scale_type(int chroma) {
- int nearest = (chroma ? cscale : lscale) & 64;
- if (nearest)
- return mipmap_gen ? GL_NEAREST_MIPMAP_NEAREST : GL_NEAREST;
- return mipmap_gen ? GL_LINEAR_MIPMAP_NEAREST : GL_LINEAR;
+static GLint get_scale_type(struct vo *vo, int chroma)
+{
+ struct gl_priv *p = vo->priv;
+
+ int nearest = (chroma ? p->cscale : p->lscale) & 64;
+ if (nearest)
+ return p->mipmap_gen ? GL_NEAREST_MIPMAP_NEAREST : GL_NEAREST;
+ return p->mipmap_gen ? GL_LINEAR_MIPMAP_NEAREST : GL_LINEAR;
}
/**
* \brief Initialize a (new or reused) OpenGL context.
* set global gl-related variables to their default values
*/
-static int initGl(uint32_t d_width, uint32_t d_height) {
- GLint scale_type = get_scale_type(0);
- autodetectGlExtensions();
- gl_target = use_rectangle == 1 ? GL_TEXTURE_RECTANGLE : GL_TEXTURE_2D;
- yuvconvtype = SET_YUV_CONVERSION(use_yuv) |
- SET_YUV_LUM_SCALER(lscale) |
- SET_YUV_CHROM_SCALER(cscale);
-
- texSize(image_width, image_height, &texture_width, &texture_height);
-
- mpglDisable(GL_BLEND);
- mpglDisable(GL_DEPTH_TEST);
- mpglDepthMask(GL_FALSE);
- mpglDisable(GL_CULL_FACE);
- mpglEnable(gl_target);
- mpglDrawBuffer(vo_doublebuffering?GL_BACK:GL_FRONT);
- mpglTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
-
- mp_msg(MSGT_VO, MSGL_V, "[gl] Creating %dx%d texture...\n",
- texture_width, texture_height);
-
- glCreateClearTex(gl_target, gl_texfmt, gl_format, gl_type, scale_type,
- texture_width, texture_height, 0);
- if (mipmap_gen)
- mpglTexParameteri(gl_target, GL_GENERATE_MIPMAP, GL_TRUE);
-
- if (is_yuv) {
- int i;
- int xs, ys, depth;
- int chroma_clear_val = 128;
- scale_type = get_scale_type(1);