summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--libvo/gl_common.c6
-rw-r--r--libvo/gl_common.h7
-rw-r--r--libvo/vo_gl.c256
3 files changed, 124 insertions, 145 deletions
diff --git a/libvo/gl_common.c b/libvo/gl_common.c
index 7cca800d40..aa34521802 100644
--- a/libvo/gl_common.c
+++ b/libvo/gl_common.c
@@ -360,6 +360,12 @@ static const extfunc_desc_t extfuncs[] = {
DEF_FUNC_DESC(ColorMask),
DEF_FUNC_DESC(ReadPixels),
DEF_FUNC_DESC(ReadBuffer),
+ DEF_FUNC_DESC(VertexPointer),
+ DEF_FUNC_DESC(ColorPointer),
+ DEF_FUNC_DESC(TexCoordPointer),
+ DEF_FUNC_DESC(DrawArrays),
+ DEF_FUNC_DESC(EnableClientState),
+ DEF_FUNC_DESC(DisableClientState),
DEF_EXT_DESC(GenBuffers, NULL,
("glGenBuffers", "glGenBuffersARB")),
diff --git a/libvo/gl_common.h b/libvo/gl_common.h
index 8e3294f441..5a0fd9b8a8 100644
--- a/libvo/gl_common.h
+++ b/libvo/gl_common.h
@@ -463,6 +463,13 @@ struct GL {
void (GLAPIENTRY *ReadPixels)(GLint, GLint, GLsizei, GLsizei, GLenum,
GLenum, GLvoid *);
void (GLAPIENTRY *ReadBuffer)(GLenum);
+ void (GLAPIENTRY *VertexPointer)(GLint, GLenum, GLsizei, const GLvoid *);
+ void (GLAPIENTRY *ColorPointer)(GLint, GLenum, GLsizei, const GLvoid *);
+ void (GLAPIENTRY *TexCoordPointer)(GLint, GLenum, GLsizei, const GLvoid *);
+ void (GLAPIENTRY *DrawArrays)(GLenum, GLint, GLsizei);
+ void (GLAPIENTRY *EnableClientState)(GLenum);
+ void (GLAPIENTRY *DisableClientState)(GLenum);
+
// OpenGL extension functions
void (GLAPIENTRY *GenBuffers)(GLsizei, GLuint *);
diff --git a/libvo/vo_gl.c b/libvo/vo_gl.c
index e68465f009..7bf5cf2ec1 100644
--- a/libvo/vo_gl.c
+++ b/libvo/vo_gl.c
@@ -38,6 +38,7 @@
#include "osd.h"
#include "sub/font_load.h"
#include "sub/sub.h"
+#include "eosd_packer.h"
#include "gl_common.h"
#include "aspect.h"
@@ -49,19 +50,17 @@ static int preinit_nosw(struct vo *vo, const char *arg);
//! How many parts the OSD may consist of at most
#define MAX_OSD_PARTS 20
-#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 SMALLTEX_SIZE 32
-#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))
+struct vertex_eosd {
+ float x, y;
+ uint8_t color[4];
+ float u, v;
+};
+
struct gl_priv {
MPGLContext *glctx;
GL *gl;
@@ -74,17 +73,17 @@ struct gl_priv {
//! Alpha textures for OSD
GLuint osdatex[MAX_OSD_PARTS];
#endif
- GLuint *eosdtex;
- GLuint largeeosdtex[2];
+ GLuint eosd_texture;
+ int eosd_texture_width, eosd_texture_height;
+ struct eosd_packer *eosd;
+ struct vertex_eosd *eosd_va;
//! 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_ycbcr;
@@ -285,150 +284,111 @@ static void clearOSD(struct vo *vo)
}
/**
- * \brief remove textures, display list and free memory used by EOSD
+ * \brief construct display list from ass image list
+ * \param img image list to create OSD from.
*/
-static void clearEOSD(struct vo *vo)
+static void genEOSD(struct vo *vo, mp_eosd_images_t *imgs)
{
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;
-}
+ bool need_repos, need_upload, need_allocate;
+ eosd_packer_generate(p->eosd, imgs, &need_repos, &need_upload,
+ &need_allocate);
-static inline int is_tinytex(ASS_Image *i, int tinytexcur)
-{
- return i->w < TINYTEX_SIZE && i->h < TINYTEX_SIZE
- && tinytexcur < TINYTEX_MAX;
-}
+ if (!need_repos)
+ return;
-static inline int is_smalltex(ASS_Image *i, int smalltexcur)
-{
- return i->w < SMALLTEX_SIZE && i->h < SMALLTEX_SIZE
- && smalltexcur < SMALLTEX_MAX;
-}
+ if (!p->eosd_texture)
+ gl->GenTextures(1, &p->eosd_texture);
-static inline void tinytex_pos(int tinytexcur, int *x, int *y)
-{
- *x = (tinytexcur % TINYTEX_COLS) * TINYTEX_SIZE;
- *y = (tinytexcur / TINYTEX_COLS) * TINYTEX_SIZE;
-}
+ gl->BindTexture(p->target, p->eosd_texture);
-static inline void smalltex_pos(int smalltexcur, int *x, int *y)
-{
- *x = (smalltexcur % SMALLTEX_COLS) * SMALLTEX_SIZE;
- *y = (smalltexcur / SMALLTEX_COLS) * SMALLTEX_SIZE;
+ if (need_allocate) {
+ texSize(vo, p->eosd->surface.w, p->eosd->surface.h,
+ &p->eosd_texture_width, &p->eosd_texture_height);
+ // xxx it doesn't need to be cleared, that's a waste of time
+ glCreateClearTex(gl, p->target, GL_ALPHA, GL_ALPHA, GL_UNSIGNED_BYTE,
+ GL_NEAREST, p->eosd_texture_width,
+ p->eosd_texture_height, 0);
+ }
+
+ // 2 triangles primitives per quad = 6 vertices per quad
+ // not using GL_QUADS, as it is deprecated in OpenGL 3.x and later
+ p->eosd_va = talloc_realloc_size(p->eosd, p->eosd_va,
+ p->eosd->targets_count
+ * sizeof(struct vertex_eosd) * 6);
+
+ float eosd_w = p->eosd_texture_width;
+ float eosd_h = p->eosd_texture_height;
+
+ if (p->use_rectangle == 1)
+ eosd_w = eosd_h = 1.0f;
+
+ for (int n = 0; n < p->eosd->targets_count; n++) {
+ struct eosd_target *target = &p->eosd->targets[n];
+ ASS_Image *i = target->ass_img;
+
+ if (need_upload) {
+ glUploadTex(gl, p->target, GL_ALPHA, GL_UNSIGNED_BYTE, i->bitmap,
+ i->stride, target->source.x0, target->source.y0,
+ i->w, i->h, 0);
+ }
+
+ uint8_t color[4] = { i->color >> 24, (i->color >> 16) & 0xff,
+ (i->color >> 8) & 0xff, 255 - (i->color & 0xff) };
+
+ float x0 = target->dest.x0;
+ float y0 = target->dest.y0;
+ float x1 = target->dest.x1;
+ float y1 = target->dest.y1;
+ float tx0 = target->source.x0 / eosd_w;
+ float ty0 = target->source.y0 / eosd_h;
+ float tx1 = target->source.x1 / eosd_w;
+ float ty1 = target->source.y1 / eosd_h;
+
+#define COLOR_INIT {color[0], color[1], color[2], color[3]}
+ struct vertex_eosd *va = &p->eosd_va[n * 6];
+ va[0] = (struct vertex_eosd) { x0, y0, COLOR_INIT, tx0, ty0 };
+ va[1] = (struct vertex_eosd) { x0, y1, COLOR_INIT, tx0, ty1 };
+ va[2] = (struct vertex_eosd) { x1, y0, COLOR_INIT, tx1, ty0 };
+ va[3] = (struct vertex_eosd) { x1, y1, COLOR_INIT, tx1, ty1 };
+ va[4] = va[2];
+ va[5] = va[1];
+#undef COLOR_INIT
+ }
+
+ gl->BindTexture(p->target, 0);
}
-/**
- * \brief construct display list from ass image list
- * \param img image list to create OSD from.
- * A value of NULL has the same effect as clearEOSD()
- */
-static void genEOSD(struct vo *vo, mp_eosd_images_t *imgs)
+// Note: relies on state being setup, like projection matrix and blending
+static void drawEOSD(struct vo *vo)
{
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
+ if (p->eosd->targets_count == 0)
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);
- }
- }
- 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);
- }
- 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:
- 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);
- }
- gl->EndList();
+ gl->BindTexture(p->target, p->eosd_texture);
+
+ struct vertex_eosd *va = p->eosd_va;
+ size_t stride = sizeof(struct vertex_eosd);
+
+ gl->VertexPointer(2, GL_FLOAT, stride, &va[0].x);
+ gl->ColorPointer(4, GL_UNSIGNED_BYTE, stride, &va[0].color[0]);
+ gl->TexCoordPointer(2, GL_FLOAT, stride, &va[0].u);
+
+ gl->EnableClientState(GL_VERTEX_ARRAY);
+ gl->EnableClientState(GL_TEXTURE_COORD_ARRAY);
+ gl->EnableClientState(GL_COLOR_ARRAY);
+
+ gl->DrawArrays(GL_TRIANGLES, 0, p->eosd->targets_count * 6);
+
+ gl->DisableClientState(GL_VERTEX_ARRAY);
+ gl->DisableClientState(GL_TEXTURE_COORD_ARRAY);
+ gl->DisableClientState(GL_COLOR_ARRAY);
+
gl->BindTexture(p->target, 0);
}
@@ -450,10 +410,10 @@ static void uninitGl(struct vo *vo)
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 (p->eosd_texture)
+ gl->DeleteTextures(1, &p->eosd_texture);
+ eosd_packer_reinit(p->eosd, 0, 0);
+ p->eosd_texture = 0;
if (gl->DeleteBuffers && p->buffer)
gl->DeleteBuffers(1, &p->buffer);
p->buffer = 0;
@@ -633,6 +593,10 @@ static int initGl(struct vo *vo, uint32_t d_width, uint32_t d_height)
update_yuvconv(vo);
}
+ GLint max_texture_size;
+ gl->GetIntegerv(GL_MAX_TEXTURE_SIZE, &max_texture_size);
+ eosd_packer_reinit(p->eosd, max_texture_size, max_texture_size);
+
resize(vo, d_width, d_height);
gl->ClearColor(0.0f, 0.0f, 0.0f, 0.0f);
@@ -786,7 +750,7 @@ static void do_render_osd(struct vo *vo, int type)
GL *gl = p->gl;
int draw_osd = (type & RENDER_OSD) && p->osdtexCnt > 0;
- int draw_eosd = (type & RENDER_EOSD) && p->eosdDispList;
+ int draw_eosd = (type & RENDER_EOSD);
if (!draw_osd && !draw_eosd)
return;
// set special rendering parameters
@@ -799,7 +763,7 @@ static void do_render_osd(struct vo *vo, int type)
gl->Enable(GL_BLEND);
if (draw_eosd) {
gl->BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- gl->CallList(p->eosdDispList);
+ drawEOSD(vo);
}
if (draw_osd) {
gl->Color4ub((p->osd_color >> 16) & 0xff, (p->osd_color >> 8) & 0xff,
@@ -1239,6 +1203,8 @@ static int preinit_internal(struct vo *vo, const char *arg, int allow_sw,
.osd_color = 0xffffff,
};
+ p->eosd = eosd_packer_create(vo);
+
//essentially unused; for legacy warnings only
int user_colorspace = 0;
int levelconv = -1;