mirror of
https://github.com/mpv-player/mpv
synced 2025-01-01 20:32:13 +00:00
vo_gl3: support RGBA EOSD
This also adds support for multiple EOSD renderers. This capability is unused yet, but important for the following commits.
This commit is contained in:
parent
ffb7a2fe17
commit
3c9c1790fe
@ -64,4 +64,17 @@ static inline void * memcpy_pic2(void * dst, const void * src,
|
||||
return retval;
|
||||
}
|
||||
|
||||
static inline void memset_pic(void *dst, int fill, int bytesPerLine, int height,
|
||||
int stride)
|
||||
{
|
||||
if (bytesPerLine == stride) {
|
||||
memset(dst, fill, stride * height);
|
||||
} else {
|
||||
for (int i = 0; i < height; i++) {
|
||||
memset(dst, fill, bytesPerLine);
|
||||
dst = (uint8_t *)dst + stride;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* MPLAYER_FASTMEMCPY_H */
|
||||
|
@ -427,6 +427,7 @@ static const extfunc_desc_t extfuncs[] = {
|
||||
DEF_GL3_DESC(FramebufferTexture2D),
|
||||
DEF_GL3_DESC(Uniform1f),
|
||||
DEF_GL3_DESC(Uniform3f),
|
||||
DEF_GL3_DESC(Uniform4f),
|
||||
DEF_GL3_DESC(Uniform1i),
|
||||
DEF_GL3_DESC(UniformMatrix3fv),
|
||||
DEF_GL3_DESC(UniformMatrix4x3fv),
|
||||
@ -674,6 +675,31 @@ void glUploadTex(GL *gl, GLenum target, GLenum format, GLenum type,
|
||||
gl->TexSubImage2D(target, 0, x, y, w, y_max - y, format, type, data);
|
||||
}
|
||||
|
||||
// Like glUploadTex, but upload a byte array with all elements set to val.
|
||||
// If scratch is not NULL, points to a resizeable talloc memory block than can
|
||||
// be freely used by the function (for avoiding temporary memory allocations).
|
||||
void glClearTex(GL *gl, GLenum target, GLenum format, GLenum type,
|
||||
int x, int y, int w, int h, uint8_t val, void **scratch)
|
||||
{
|
||||
int bpp = glFmt2bpp(format, type);
|
||||
int stride = w * bpp;
|
||||
int size = h * stride;
|
||||
if (size < 1)
|
||||
return;
|
||||
void *data = scratch ? *scratch : NULL;
|
||||
if (talloc_get_size(data) < size)
|
||||
data = talloc_realloc(NULL, data, char *, size);
|
||||
memset(data, val, size);
|
||||
glAdjustAlignment(gl, stride);
|
||||
gl->PixelStorei(GL_UNPACK_ROW_LENGTH, w);
|
||||
gl->TexSubImage2D(target, 0, x, y, w, h, format, type, data);
|
||||
if (scratch) {
|
||||
*scratch = data;
|
||||
} else {
|
||||
talloc_free(data);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief download a texture, handling things like stride and slices
|
||||
* \param target texture target, usually GL_TEXTURE_2D
|
||||
|
@ -60,6 +60,8 @@ int glCreatePPMTex(GL *gl, GLenum target, GLenum fmt, GLint filter,
|
||||
void glUploadTex(GL *gl, GLenum target, GLenum format, GLenum type,
|
||||
const void *dataptr, int stride,
|
||||
int x, int y, int w, int h, int slice);
|
||||
void glClearTex(GL *gl, GLenum target, GLenum format, GLenum type,
|
||||
int x, int y, int w, int h, uint8_t val, void **scratch);
|
||||
void glDownloadTex(GL *gl, GLenum target, GLenum format, GLenum type,
|
||||
void *dataptr, int stride);
|
||||
void glDrawTex(GL *gl, GLfloat x, GLfloat y, GLfloat w, GLfloat h,
|
||||
@ -351,6 +353,7 @@ struct GL {
|
||||
|
||||
void (GLAPIENTRY *Uniform1f)(GLint, GLfloat);
|
||||
void (GLAPIENTRY *Uniform3f)(GLint, GLfloat, GLfloat, GLfloat);
|
||||
void (GLAPIENTRY *Uniform4f)(GLint, GLfloat, GLfloat, GLfloat, GLfloat);
|
||||
void (GLAPIENTRY *Uniform1i)(GLint, GLint);
|
||||
void (GLAPIENTRY *UniformMatrix3fv)(GLint, GLsizei, GLboolean,
|
||||
const GLfloat *);
|
||||
|
292
libvo/vo_gl3.c
292
libvo/vo_gl3.c
@ -37,6 +37,7 @@
|
||||
#endif
|
||||
|
||||
#include "talloc.h"
|
||||
#include "mpcommon.h"
|
||||
#include "bstr.h"
|
||||
#include "mp_msg.h"
|
||||
#include "subopt-helper.h"
|
||||
@ -46,7 +47,7 @@
|
||||
#include "geometry.h"
|
||||
#include "osd.h"
|
||||
#include "sub/sub.h"
|
||||
#include "eosd_packer.h"
|
||||
#include "bitmap_packer.h"
|
||||
|
||||
#include "gl_common.h"
|
||||
#include "filter_kernels.h"
|
||||
@ -111,7 +112,7 @@ struct vertex {
|
||||
#define VERTEX_ATTRIB_TEXCOORD 2
|
||||
|
||||
// 2 triangles primitives per quad = 6 vertices per quad
|
||||
// (GL_QUAD is deprecated, strips can't be used with EOSD image lists)
|
||||
// (GL_QUAD is deprecated, strips can't be used with OSD image lists)
|
||||
#define VERTICES_PER_QUAD 6
|
||||
|
||||
struct texplane {
|
||||
@ -141,6 +142,17 @@ struct fbotex {
|
||||
int vp_w, vp_h; // viewport of fbo / used part of the texture
|
||||
};
|
||||
|
||||
struct osd_render {
|
||||
enum sub_bitmap_format format;
|
||||
int bitmap_id, bitmap_pos_id;
|
||||
GLuint texture;
|
||||
int width, height;
|
||||
GLuint buffer;
|
||||
int num_vertices;
|
||||
struct vertex *vertices;
|
||||
struct bitmap_packer *packer;
|
||||
};
|
||||
|
||||
struct gl_priv {
|
||||
struct vo *vo;
|
||||
MPGLContext *glctx;
|
||||
@ -171,18 +183,15 @@ struct gl_priv {
|
||||
GLuint vertex_buffer;
|
||||
GLuint vao;
|
||||
|
||||
GLuint osd_program, eosd_program;
|
||||
GLuint osd_programs[SUBBITMAP_COUNT];
|
||||
GLuint indirect_program, scale_sep_program, final_program;
|
||||
|
||||
// old OSD code - should go away
|
||||
GLuint osd_textures[MAX_OSD_PARTS];
|
||||
int osd_textures_count;
|
||||
struct vertex osd_va[MAX_OSD_PARTS * VERTICES_PER_QUAD];
|
||||
|
||||
GLuint eosd_texture;
|
||||
int eosd_texture_width, eosd_texture_height;
|
||||
GLuint eosd_buffer;
|
||||
struct vertex *eosd_va;
|
||||
struct eosd_packer *eosd;
|
||||
struct osd_render *osd[MAX_OSD_PARTS];
|
||||
|
||||
GLuint lut_3d_texture;
|
||||
int lut_3d_w, lut_3d_h, lut_3d_d;
|
||||
@ -231,6 +240,8 @@ struct gl_priv {
|
||||
struct vo_rect dst_rect; // video rectangle on output window
|
||||
int border_x, border_y; // OSD borders
|
||||
int vp_x, vp_y, vp_w, vp_h; // GL viewport
|
||||
|
||||
void *scratch;
|
||||
};
|
||||
|
||||
struct fmt_entry {
|
||||
@ -254,6 +265,25 @@ static const struct fmt_entry mp_to_gl_formats[] = {
|
||||
{0},
|
||||
};
|
||||
|
||||
struct osd_fmt_entry {
|
||||
GLint internal_format;
|
||||
GLint format;
|
||||
int stride; // bytes per pixel
|
||||
GLenum type;
|
||||
const char *shader; // shader entry in the .glsl file
|
||||
};
|
||||
|
||||
static const struct osd_fmt_entry osd_to_gl_formats[] = {
|
||||
[SUBBITMAP_LIBASS]
|
||||
= {GL_RED, GL_RED, 1, GL_UNSIGNED_BYTE, "frag_osd_libass"},
|
||||
[SUBBITMAP_RGBA]
|
||||
= {GL_RGBA, GL_BGRA, 4, GL_UNSIGNED_BYTE, "frag_osd_rgba"},
|
||||
[SUBBITMAP_OLD]
|
||||
= {GL_RG, GL_RG, 2, GL_UNSIGNED_BYTE, "frag_osd_old"},
|
||||
// Make array long enough to contain all formats
|
||||
[SUBBITMAP_COUNT] = {0}
|
||||
};
|
||||
|
||||
|
||||
static const char help_text[];
|
||||
|
||||
@ -464,6 +494,15 @@ static void update_uniforms(struct gl_priv *p, GLuint program)
|
||||
gl->Uniform1f(gl->GetUniformLocation(program, "filter_param1"),
|
||||
isnan(sparam1) ? 0.5f : sparam1);
|
||||
|
||||
loc = gl->GetUniformLocation(program, "osd_color");
|
||||
if (loc >= 0) {
|
||||
int r = (p->osd_color >> 16) & 0xff;
|
||||
int g = (p->osd_color >> 8) & 0xff;
|
||||
int b = p->osd_color & 0xff;
|
||||
int a = 0xff - (p->osd_color >> 24);
|
||||
gl->Uniform4f(loc, r / 255.0f, g / 255.0f, b / 255.0f, a / 255.0f);
|
||||
}
|
||||
|
||||
gl->UseProgram(0);
|
||||
|
||||
debug_check_gl(p, "update_uniforms()");
|
||||
@ -471,8 +510,8 @@ static void update_uniforms(struct gl_priv *p, GLuint program)
|
||||
|
||||
static void update_all_uniforms(struct gl_priv *p)
|
||||
{
|
||||
update_uniforms(p, p->osd_program);
|
||||
update_uniforms(p, p->eosd_program);
|
||||
for (int n = 0; n < SUBBITMAP_COUNT; n++)
|
||||
update_uniforms(p, p->osd_programs[n]);
|
||||
update_uniforms(p, p->indirect_program);
|
||||
update_uniforms(p, p->scale_sep_program);
|
||||
update_uniforms(p, p->final_program);
|
||||
@ -636,20 +675,21 @@ static void compile_shaders(struct gl_priv *p)
|
||||
char *vertex_shader = get_section(tmp, src, "vertex_all");
|
||||
char *shader_prelude = get_section(tmp, src, "prelude");
|
||||
char *s_video = get_section(tmp, src, "frag_video");
|
||||
char *s_eosd = get_section(tmp, src, "frag_eosd");
|
||||
char *s_osd = get_section(tmp, src, "frag_osd");
|
||||
|
||||
char *header = talloc_asprintf(tmp, "#version %s\n%s", p->shader_version,
|
||||
shader_prelude);
|
||||
|
||||
char *header_eosd = talloc_strdup(tmp, header);
|
||||
shader_def_opt(&header_eosd, "USE_3DLUT", p->use_lut_3d);
|
||||
char *header_osd = talloc_strdup(tmp, header);
|
||||
shader_def_opt(&header_osd, "USE_3DLUT", p->use_lut_3d);
|
||||
|
||||
p->eosd_program =
|
||||
create_program(gl, "eosd", header_eosd, vertex_shader, s_eosd);
|
||||
|
||||
p->osd_program =
|
||||
create_program(gl, "osd", header, vertex_shader, s_osd);
|
||||
for (int n = 0; n < SUBBITMAP_COUNT; n++) {
|
||||
struct osd_fmt_entry fmt = osd_to_gl_formats[n];
|
||||
if (fmt.shader) {
|
||||
char *s_osd = get_section(tmp, src, fmt.shader);
|
||||
p->osd_programs[n] =
|
||||
create_program(gl, fmt.shader, header_osd, vertex_shader, s_osd);
|
||||
}
|
||||
}
|
||||
|
||||
char *header_conv = talloc_strdup(tmp, "");
|
||||
char *header_final = talloc_strdup(tmp, "");
|
||||
@ -750,8 +790,8 @@ static void delete_shaders(struct gl_priv *p)
|
||||
{
|
||||
GL *gl = p->gl;
|
||||
|
||||
delete_program(gl, &p->osd_program);
|
||||
delete_program(gl, &p->eosd_program);
|
||||
for (int n = 0; n < SUBBITMAP_COUNT; n++)
|
||||
delete_program(gl, &p->osd_programs[n]);
|
||||
delete_program(gl, &p->indirect_program);
|
||||
delete_program(gl, &p->scale_sep_program);
|
||||
delete_program(gl, &p->final_program);
|
||||
@ -1449,7 +1489,7 @@ static void draw_osd(struct vo *vo, struct osd_state *osd)
|
||||
// OSD bitmaps use premultiplied alpha.
|
||||
gl->BlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
gl->UseProgram(p->osd_program);
|
||||
gl->UseProgram(p->osd_programs[SUBBITMAP_OLD]);
|
||||
|
||||
for (int n = 0; n < p->osd_textures_count; n++) {
|
||||
gl->BindTexture(GL_TEXTURE_2D, p->osd_textures[n]);
|
||||
@ -1464,80 +1504,111 @@ static void draw_osd(struct vo *vo, struct osd_state *osd)
|
||||
}
|
||||
}
|
||||
|
||||
static void gen_eosd(struct gl_priv *p, mp_eosd_images_t *imgs)
|
||||
static void gen_eosd(struct gl_priv *p, struct osd_render *osd,
|
||||
struct sub_bitmaps *imgs)
|
||||
{
|
||||
GL *gl = p->gl;
|
||||
|
||||
bool need_repos, need_upload, need_allocate;
|
||||
eosd_packer_generate(p->eosd, imgs, &need_repos, &need_upload,
|
||||
&need_allocate);
|
||||
|
||||
if (!need_repos)
|
||||
if (imgs->bitmap_pos_id == osd->bitmap_pos_id)
|
||||
return;
|
||||
|
||||
if (!p->eosd_texture) {
|
||||
gl->GenTextures(1, &p->eosd_texture);
|
||||
gl->GenBuffers(1, &p->eosd_buffer);
|
||||
osd->num_vertices = 0;
|
||||
|
||||
if (imgs->format == SUBBITMAP_EMPTY)
|
||||
return;
|
||||
|
||||
bool need_upload = imgs->bitmap_id != osd->bitmap_id;
|
||||
bool need_allocate = false;
|
||||
|
||||
if (imgs->format != osd->format) {
|
||||
packer_reset(osd->packer);
|
||||
osd->format = imgs->format;
|
||||
need_allocate = true;
|
||||
}
|
||||
|
||||
gl->BindTexture(GL_TEXTURE_2D, p->eosd_texture);
|
||||
osd->bitmap_id = imgs->bitmap_id;
|
||||
osd->bitmap_pos_id = imgs->bitmap_pos_id;
|
||||
|
||||
osd->packer->padding = imgs->scaled; // assume 2x2 filter on scaling
|
||||
int r = packer_pack_from_subbitmaps(osd->packer, imgs);
|
||||
if (r < 0) {
|
||||
mp_msg(MSGT_VO, MSGL_ERR, "[gl] EOSD bitmaps do not fit on "
|
||||
"a surface with the maximum supported size %dx%d.\n",
|
||||
osd->packer->w_max, osd->packer->h_max);
|
||||
return;
|
||||
} else if (r > 0) {
|
||||
need_allocate = true;
|
||||
}
|
||||
|
||||
struct osd_fmt_entry fmt = osd_to_gl_formats[imgs->format];
|
||||
assert(fmt.shader);
|
||||
|
||||
if (!osd->texture) {
|
||||
gl->GenTextures(1, &osd->texture);
|
||||
gl->GenBuffers(1, &osd->buffer);
|
||||
}
|
||||
|
||||
gl->BindTexture(GL_TEXTURE_2D, osd->texture);
|
||||
|
||||
if (need_allocate) {
|
||||
tex_size(p, p->eosd->surface.w, p->eosd->surface.h,
|
||||
&p->eosd_texture_width, &p->eosd_texture_height);
|
||||
gl->TexImage2D(GL_TEXTURE_2D, 0, GL_RED,
|
||||
p->eosd_texture_width, p->eosd_texture_height, 0,
|
||||
GL_RED, GL_UNSIGNED_BYTE, NULL);
|
||||
default_tex_params(gl, GL_TEXTURE_2D, GL_NEAREST);
|
||||
gl->BindBuffer(GL_PIXEL_UNPACK_BUFFER, p->eosd_buffer);
|
||||
tex_size(p, osd->packer->w, osd->packer->h, &osd->width, &osd->height);
|
||||
gl->TexImage2D(GL_TEXTURE_2D, 0, fmt.internal_format, osd->width,
|
||||
osd->height, 0, fmt.format, fmt.type, NULL);
|
||||
default_tex_params(gl, GL_TEXTURE_2D, GL_LINEAR);
|
||||
gl->BindBuffer(GL_PIXEL_UNPACK_BUFFER, osd->buffer);
|
||||
gl->BufferData(GL_PIXEL_UNPACK_BUFFER,
|
||||
p->eosd->surface.w * p->eosd->surface.h,
|
||||
NULL,
|
||||
GL_DYNAMIC_COPY);
|
||||
osd->width * osd->height * fmt.stride,
|
||||
NULL, GL_DYNAMIC_COPY);
|
||||
gl->BindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
|
||||
}
|
||||
|
||||
p->eosd_va = talloc_realloc_size(p->eosd, p->eosd_va,
|
||||
p->eosd->targets_count
|
||||
* sizeof(struct vertex)
|
||||
* VERTICES_PER_QUAD);
|
||||
struct pos bb[2];
|
||||
packer_get_bb(osd->packer, bb);
|
||||
|
||||
if (need_upload && p->use_pbo) {
|
||||
gl->BindBuffer(GL_PIXEL_UNPACK_BUFFER, p->eosd_buffer);
|
||||
gl->BindBuffer(GL_PIXEL_UNPACK_BUFFER, osd->buffer);
|
||||
char *data = gl->MapBuffer(GL_PIXEL_UNPACK_BUFFER, GL_WRITE_ONLY);
|
||||
size_t stride = osd->width * fmt.stride;
|
||||
if (!data) {
|
||||
mp_msg(MSGT_VO, MSGL_FATAL, "[gl] Error: can't upload subtitles! "
|
||||
"Subtitles will look corrupted.\n");
|
||||
"Remove the 'pbo' suboption.\n");
|
||||
} else {
|
||||
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 (imgs->scaled) {
|
||||
int w = bb[1].x - bb[0].x;
|
||||
int h = bb[1].y - bb[0].y;
|
||||
memset_pic(data, 0, w * fmt.stride, h, stride);
|
||||
}
|
||||
for (int n = 0; n < osd->packer->count; n++) {
|
||||
struct sub_bitmap *b = &imgs->parts[n];
|
||||
struct pos p = osd->packer->result[n];
|
||||
|
||||
void *pdata = data + target->source.y0 * p->eosd->surface.w
|
||||
+ target->source.x0;
|
||||
|
||||
memcpy_pic(pdata, i->bitmap, i->w, i->h,
|
||||
p->eosd->surface.w, i->stride);
|
||||
void *pdata = data + p.y * stride + p.x * fmt.stride;
|
||||
memcpy_pic(pdata, b->bitmap, b->w * fmt.stride, b->h,
|
||||
stride, b->stride);
|
||||
}
|
||||
if (!gl->UnmapBuffer(GL_PIXEL_UNPACK_BUFFER))
|
||||
mp_msg(MSGT_VO, MSGL_FATAL, "[gl] EOSD PBO upload failed. "
|
||||
"Remove the 'pbo' suboption.\n");
|
||||
struct eosd_rect rc;
|
||||
eosd_packer_calculate_source_bb(p->eosd, &rc);
|
||||
glUploadTex(gl, GL_TEXTURE_2D, GL_RED, GL_UNSIGNED_BYTE, NULL,
|
||||
p->eosd->surface.w, rc.x0, rc.y0,
|
||||
rc.x1 - rc.x0, rc.y1 - rc.y0, 0);
|
||||
glUploadTex(gl, GL_TEXTURE_2D, fmt.format, fmt.type, NULL, stride,
|
||||
bb[0].x, bb[0].y, bb[1].x - bb[0].x, bb[1].y - bb[0].y,
|
||||
0);
|
||||
need_upload = false;
|
||||
}
|
||||
gl->BindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
|
||||
} else if (need_upload) {
|
||||
}
|
||||
if (need_upload) {
|
||||
// non-PBO upload
|
||||
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 (imgs->scaled) {
|
||||
glClearTex(gl, GL_TEXTURE_2D, fmt.format, fmt.type,
|
||||
bb[0].x, bb[0].y, bb[1].x - bb[0].y, bb[1].y - bb[0].y,
|
||||
0, &p->scratch);
|
||||
}
|
||||
for (int n = 0; n < osd->packer->count; n++) {
|
||||
struct sub_bitmap *b = &imgs->parts[n];
|
||||
struct pos p = osd->packer->result[n];
|
||||
|
||||
glUploadTex(gl, GL_TEXTURE_2D, GL_RED, GL_UNSIGNED_BYTE, i->bitmap,
|
||||
i->stride, target->source.x0, target->source.y0,
|
||||
i->w, i->h, 0);
|
||||
glUploadTex(gl, GL_TEXTURE_2D, fmt.format, fmt.type,
|
||||
b->bitmap, b->stride, p.x, p.y, b->w, b->h, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1545,36 +1616,51 @@ static void gen_eosd(struct gl_priv *p, mp_eosd_images_t *imgs)
|
||||
|
||||
debug_check_gl(p, "EOSD upload");
|
||||
|
||||
for (int n = 0; n < p->eosd->targets_count; n++) {
|
||||
struct eosd_target *target = &p->eosd->targets[n];
|
||||
ASS_Image *i = target->ass_img;
|
||||
uint8_t color[4] = { i->color >> 24, (i->color >> 16) & 0xff,
|
||||
(i->color >> 8) & 0xff, 255 - (i->color & 0xff) };
|
||||
osd->vertices = talloc_realloc_size(osd, osd->vertices,
|
||||
osd->packer->count
|
||||
* sizeof(struct vertex)
|
||||
* VERTICES_PER_QUAD);
|
||||
|
||||
write_quad(&p->eosd_va[n * VERTICES_PER_QUAD],
|
||||
target->dest.x0, target->dest.y0,
|
||||
target->dest.x1, target->dest.y1,
|
||||
target->source.x0, target->source.y0,
|
||||
target->source.x1, target->source.y1,
|
||||
p->eosd_texture_width, p->eosd_texture_height,
|
||||
color, false);
|
||||
for (int n = 0; n < osd->packer->count; n++) {
|
||||
struct sub_bitmap *b = &imgs->parts[n];
|
||||
struct pos p = osd->packer->result[n];
|
||||
|
||||
// NOTE: the blend color is used with SUBBITMAP_LIBASS only, so it
|
||||
// doesn't matter that we upload garbage for the other formats
|
||||
uint32_t c = b->libass.color;
|
||||
uint8_t color[4] = { c >> 24, (c >> 16) & 0xff,
|
||||
(c >> 8) & 0xff, 255 - (c & 0xff) };
|
||||
|
||||
write_quad(&osd->vertices[osd->num_vertices],
|
||||
b->x, b->y, b->x + b->dw, b->y + b->dh,
|
||||
p.x, p.y, p.x + b->w, p.y + b->h,
|
||||
osd->width, osd->height, color, false);
|
||||
osd->num_vertices += VERTICES_PER_QUAD;
|
||||
}
|
||||
}
|
||||
|
||||
static void draw_eosd(struct gl_priv *p, mp_eosd_images_t *imgs)
|
||||
static void draw_eosd(struct gl_priv *p, struct sub_bitmaps *imgs)
|
||||
{
|
||||
GL *gl = p->gl;
|
||||
|
||||
gen_eosd(p, imgs);
|
||||
struct osd_render *osd = p->osd[imgs->render_index];
|
||||
|
||||
if (p->eosd->targets_count == 0)
|
||||
gen_eosd(p, osd, imgs);
|
||||
|
||||
if (osd->num_vertices == 0)
|
||||
return;
|
||||
|
||||
assert(osd->format != SUBBITMAP_EMPTY);
|
||||
|
||||
gl->Enable(GL_BLEND);
|
||||
gl->BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
gl->BindTexture(GL_TEXTURE_2D, p->eosd_texture);
|
||||
gl->UseProgram(p->eosd_program);
|
||||
draw_triangles(p, p->eosd_va, p->eosd->targets_count * VERTICES_PER_QUAD);
|
||||
if (osd->format == SUBBITMAP_OLD) {
|
||||
gl->BlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
|
||||
} else {
|
||||
gl->BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
}
|
||||
gl->BindTexture(GL_TEXTURE_2D, osd->texture);
|
||||
gl->UseProgram(p->osd_programs[osd->format]);
|
||||
draw_triangles(p, osd->vertices, osd->num_vertices);
|
||||
gl->UseProgram(0);
|
||||
gl->BindTexture(GL_TEXTURE_2D, 0);
|
||||
gl->Disable(GL_BLEND);
|
||||
@ -1641,7 +1727,18 @@ static int init_gl(struct gl_priv *p)
|
||||
|
||||
GLint max_texture_size;
|
||||
gl->GetIntegerv(GL_MAX_TEXTURE_SIZE, &max_texture_size);
|
||||
eosd_packer_reinit(p->eosd, max_texture_size, max_texture_size);
|
||||
|
||||
for (int n = 0; n < MAX_OSD_PARTS; n++) {
|
||||
assert(!p->osd[n]);
|
||||
struct osd_render *osd = talloc_ptrtype(p, osd);
|
||||
*osd = (struct osd_render) {
|
||||
.packer = talloc_struct(osd, struct bitmap_packer, {
|
||||
.w_max = max_texture_size,
|
||||
.h_max = max_texture_size,
|
||||
}),
|
||||
};
|
||||
p->osd[n] = osd;
|
||||
}
|
||||
|
||||
gl->ClearColor(0.0f, 0.0f, 0.0f, 0.0f);
|
||||
gl->Clear(GL_COLOR_BUFFER_BIT);
|
||||
@ -1667,11 +1764,15 @@ static void uninit_gl(struct gl_priv *p)
|
||||
p->vertex_buffer = 0;
|
||||
|
||||
clear_osd(p);
|
||||
gl->DeleteTextures(1, &p->eosd_texture);
|
||||
p->eosd_texture = 0;
|
||||
gl->DeleteBuffers(1, &p->eosd_buffer);
|
||||
p->eosd_buffer = 0;
|
||||
eosd_packer_reinit(p->eosd, 0, 0);
|
||||
for (int n = 0; n < MAX_OSD_PARTS; n++) {
|
||||
struct osd_render *osd = p->osd[n];
|
||||
if (!osd)
|
||||
continue;
|
||||
gl->DeleteTextures(1, &osd->texture);
|
||||
gl->DeleteBuffers(1, &osd->buffer);
|
||||
talloc_free(osd);
|
||||
p->osd[n] = NULL;
|
||||
}
|
||||
|
||||
gl->DeleteTextures(1, &p->lut_3d_texture);
|
||||
p->lut_3d_texture = 0;
|
||||
@ -1753,7 +1854,7 @@ static int query_format(uint32_t format)
|
||||
{
|
||||
int caps = VFCAP_CSP_SUPPORTED | VFCAP_CSP_SUPPORTED_BY_HW | VFCAP_FLIP |
|
||||
VFCAP_HWSCALE_UP | VFCAP_HWSCALE_DOWN | VFCAP_ACCEPT_STRIDE |
|
||||
VFCAP_OSD | VFCAP_EOSD | VFCAP_EOSD_UNSCALED;
|
||||
VFCAP_OSD | VFCAP_EOSD | VFCAP_EOSD_UNSCALED | VFCAP_EOSD_RGBA;
|
||||
if (!init_format(format, NULL))
|
||||
return 0;
|
||||
return caps;
|
||||
@ -2244,6 +2345,7 @@ static int preinit(struct vo *vo, const char *arg)
|
||||
{ .index = 1, .name = "bilinear" },
|
||||
},
|
||||
.scaler_params = {NAN, NAN},
|
||||
.scratch = talloc_zero_array(p, char *, 1),
|
||||
};
|
||||
|
||||
p->defaults = talloc(p, struct gl_priv);
|
||||
@ -2323,8 +2425,6 @@ static int preinit(struct vo *vo, const char *arg)
|
||||
p->orig_cmdline = talloc(p, struct gl_priv);
|
||||
*p->orig_cmdline = *p;
|
||||
|
||||
p->eosd = eosd_packer_create(vo);
|
||||
|
||||
p->glctx = init_mpglcontext(backend, vo);
|
||||
if (!p->glctx)
|
||||
goto err_out;
|
||||
|
@ -45,7 +45,7 @@ void main() {
|
||||
texcoord = vertex_texcoord;
|
||||
}
|
||||
|
||||
#!section frag_eosd
|
||||
#!section frag_osd_libass
|
||||
uniform sampler2D texture1;
|
||||
|
||||
in vec2 texcoord;
|
||||
@ -56,15 +56,25 @@ void main() {
|
||||
out_color = vec4(color.rgb, color.a * texture(texture1, texcoord).r);
|
||||
}
|
||||
|
||||
#!section frag_osd
|
||||
#!section frag_osd_rgba
|
||||
uniform sampler2D texture1;
|
||||
|
||||
in vec2 texcoord;
|
||||
in vec4 color;
|
||||
out vec4 out_color;
|
||||
|
||||
void main() {
|
||||
out_color = texture(texture1, texcoord).rrrg * color;
|
||||
out_color = texture(texture1, texcoord);
|
||||
}
|
||||
|
||||
#!section frag_osd_old
|
||||
uniform sampler2D texture1;
|
||||
uniform vec4 osd_color;
|
||||
|
||||
in vec2 texcoord;
|
||||
out vec4 out_color;
|
||||
|
||||
void main() {
|
||||
out_color = texture(texture1, texcoord).rrrg * osd_color;
|
||||
}
|
||||
|
||||
#!section frag_video
|
||||
|
Loading…
Reference in New Issue
Block a user