diff options
author | wm4 <wm4@mplayer2.org> | 2011-09-25 11:18:07 +0200 |
---|---|---|
committer | Uoti Urpala <uau@mplayer2.org> | 2011-10-24 06:13:17 +0300 |
commit | c852246cdf3e2604d1a3bff1fccd981d7b3b58c9 (patch) | |
tree | 132f089b74befd752483e8c399e432427fe25270 /libvo/vo_gl.c | |
parent | 821a313ba183b9eed8b280cbfda84a3f95a2ab2e (diff) | |
download | mpv-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.c | 2485 |
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(¶ms); - 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, ¶ms); + 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) - mpgl |