summaryrefslogtreecommitdiffstats
path: root/libvo/vo_gl3.c
diff options
context:
space:
mode:
Diffstat (limited to 'libvo/vo_gl3.c')
-rw-r--r--libvo/vo_gl3.c221
1 files changed, 151 insertions, 70 deletions
diff --git a/libvo/vo_gl3.c b/libvo/vo_gl3.c
index dea0c6637a..329d19370f 100644
--- a/libvo/vo_gl3.c
+++ b/libvo/vo_gl3.c
@@ -148,7 +148,6 @@ struct gl_priv {
struct vo *vo;
MPGLContext *glctx;
GL *gl;
- const char *shader_version;
int use_indirect;
int use_gamma;
@@ -160,7 +159,7 @@ struct gl_priv {
int use_pbo;
int use_glFinish;
int use_gl_debug;
- int use_gl2;
+ int allow_sw;
int dither_depth;
int swap_interval;
@@ -194,6 +193,7 @@ struct gl_priv {
GLuint dither_texture;
float dither_quantization;
float dither_multiply;
+ int dither_size;
uint32_t image_width;
uint32_t image_height;
@@ -305,9 +305,13 @@ static void draw_triangles(struct gl_priv *p, struct vertex *vb, int vert_count)
GL_DYNAMIC_DRAW);
gl->BindBuffer(GL_ARRAY_BUFFER, 0);
- gl->BindVertexArray(p->vao);
+ if (gl->BindVertexArray)
+ gl->BindVertexArray(p->vao);
+
gl->DrawArrays(GL_TRIANGLES, 0, vert_count);
- gl->BindVertexArray(0);
+
+ if (gl->BindVertexArray)
+ gl->BindVertexArray(0);
debug_check_gl(p, "after rendering");
}
@@ -351,10 +355,12 @@ static void write_quad(struct vertex *va,
#undef COLOR_INIT
}
-static void fbotex_init(struct gl_priv *p, struct fbotex *fbo, int w, int h)
+static bool fbotex_init(struct gl_priv *p, struct fbotex *fbo, int w, int h)
{
GL *gl = p->gl;
+ bool res = true;
+ assert(gl->mpgl_caps & MPGL_CAP_FB);
assert(!fbo->fbo);
assert(!fbo->texture);
@@ -375,25 +381,28 @@ static void fbotex_init(struct gl_priv *p, struct fbotex *fbo, int w, int h)
gl->FramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
GL_TEXTURE_2D, fbo->texture, 0);
- if (gl->CheckFramebufferStatus(GL_FRAMEBUFFER)
- != GL_FRAMEBUFFER_COMPLETE)
- {
+ if (gl->CheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
mp_msg(MSGT_VO, MSGL_ERR, "[gl] Error: framebuffer completeness "
"check failed!\n");
+ res = false;
}
gl->BindFramebuffer(GL_FRAMEBUFFER, 0);
debug_check_gl(p, "after creating framebuffer & associated texture");
+
+ return res;
}
static void fbotex_uninit(struct gl_priv *p, struct fbotex *fbo)
{
GL *gl = p->gl;
- gl->DeleteFramebuffers(1, &fbo->fbo);
- gl->DeleteTextures(1, &fbo->texture);
- *fbo = (struct fbotex) {0};
+ if (gl->mpgl_caps & MPGL_CAP_FB) {
+ gl->DeleteFramebuffers(1, &fbo->fbo);
+ gl->DeleteTextures(1, &fbo->texture);
+ *fbo = (struct fbotex) {0};
+ }
}
static void matrix_ortho2d(float m[3][3], float x0, float x1,
@@ -444,9 +453,20 @@ static void update_uniforms(struct gl_priv *p, GLuint program)
1.0 / cparams.ggamma,
1.0 / cparams.bgamma);
- gl->Uniform1i(gl->GetUniformLocation(program, "texture1"), 0);
- gl->Uniform1i(gl->GetUniformLocation(program, "texture2"), 1);
- gl->Uniform1i(gl->GetUniformLocation(program, "texture3"), 2);
+ for (int n = 0; n < p->plane_count; n++) {
+ char textures_n[32];
+ char textures_size_n[32];
+ snprintf(textures_n, sizeof(textures_n), "textures[%d]", n);
+ snprintf(textures_size_n, sizeof(textures_size_n), "textures_size[%d]", n);
+
+ gl->Uniform1i(gl->GetUniformLocation(program, textures_n), n);
+ gl->Uniform2f(gl->GetUniformLocation(program, textures_size_n),
+ p->texture_width >> p->planes[n].shift_x,
+ p->texture_height >> p->planes[n].shift_y);
+ }
+
+ gl->Uniform2f(gl->GetUniformLocation(program, "dither_size"),
+ p->dither_size, p->dither_size);
gl->Uniform1i(gl->GetUniformLocation(program, "lut_3d"), TEXUNIT_3DLUT);
@@ -607,12 +627,12 @@ static void shader_setup_scaler(char **shader, struct scaler *scaler, int pass)
// The direction/pass assignment is rather arbitrary, but fixed in
// other parts of the code (like FBO setup).
const char *direction = pass == 0 ? "0, 1" : "1, 0";
- *shader = talloc_asprintf_append(*shader, "#define %s(p0, p1) "
- "sample_convolution_sep%d(vec2(%s), %s, p0, p1)\n",
+ *shader = talloc_asprintf_append(*shader, "#define %s(p0, p1, p2) "
+ "sample_convolution_sep%d(vec2(%s), %s, p0, p1, p2)\n",
target, size, direction, scaler->lut_name);
} else {
- *shader = talloc_asprintf_append(*shader, "#define %s(p0, p1) "
- "sample_convolution%d(%s, p0, p1)\n",
+ *shader = talloc_asprintf_append(*shader, "#define %s(p0, p1, p2) "
+ "sample_convolution%d(%s, p0, p1, p2)\n",
target, size, scaler->lut_name);
}
}
@@ -642,7 +662,7 @@ static void compile_shaders(struct gl_priv *p)
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,
+ char *header = talloc_asprintf(tmp, "#version %d\n%s", gl->glsl_version,
shader_prelude);
char *header_eosd = talloc_strdup(tmp, header);
@@ -881,6 +901,8 @@ static void init_dither(struct gl_priv *p)
unsigned char dither[256];
make_dither_matrix(dither, size);
+ p->dither_size = size;
+
gl->ActiveTexture(GL_TEXTURE0 + TEXUNIT_DITHER);
gl->GenTextures(1, &p->dither_texture);
gl->BindTexture(GL_TEXTURE_2D, p->dither_texture);
@@ -1081,7 +1103,9 @@ static void do_render(struct gl_priv *p)
float final_texw = p->image_width * source->tex_w / (float)source->vp_w;
float final_texh = p->image_height * source->tex_h / (float)source->vp_h;
- if (p->use_srgb && !p->use_lut_3d)
+ bool use_srgb_fb = p->use_srgb && !p->use_lut_3d;
+
+ if (use_srgb_fb)
gl->Enable(GL_FRAMEBUFFER_SRGB);
if (p->stereo_mode) {
@@ -1122,7 +1146,8 @@ static void do_render(struct gl_priv *p)
draw_triangles(p, vb, VERTICES_PER_QUAD);
}
- gl->Disable(GL_FRAMEBUFFER_SRGB);
+ if (use_srgb_fb)
+ gl->Disable(GL_FRAMEBUFFER_SRGB);
gl->UseProgram(0);
@@ -1583,6 +1608,70 @@ static void draw_eosd(struct gl_priv *p, mp_eosd_images_t *imgs)
gl->Disable(GL_BLEND);
}
+// Disable features that are not supported with the current OpenGL version.
+static void check_gl_features(struct gl_priv *p)
+{
+ GL *gl = p->gl;
+ bool have_float_tex = gl->mpgl_caps & MPGL_CAP_FLOAT_TEX;
+ bool have_fbo = gl->mpgl_caps & MPGL_CAP_FB;
+ bool have_srgb = (gl->mpgl_caps & MPGL_CAP_SRGB_TEX) &&
+ (gl->mpgl_caps & MPGL_CAP_SRGB_FB);
+
+ char *disabled[10];
+ int n_disabled = 0;
+
+ if (have_fbo) {
+ struct fbotex fbo = {0};
+ have_fbo = fbotex_init(p, &fbo, 16, 16);
+ fbotex_uninit(p, &fbo);
+ }
+
+ // Disable these only if the user didn't disable scale-sep on the command
+ // line, so convolution filter can still be forced to be run.
+ // Normally, we want to disable them by default if FBOs are unavailable,
+ // because they will be slow (not critically slow, but still slower).
+ // Without FP textures, we must always disable them.
+ if (!have_float_tex || (!have_fbo && p->use_scale_sep)) {
+ for (int n = 0; n < 2; n++) {
+ struct scaler *scaler = &p->scalers[n];
+ if (mp_find_filter_kernel(scaler->name)) {
+ scaler->name = "bilinear";
+ disabled[n_disabled++]
+ = have_float_tex ? "scaler (FBO)" : "scaler (float tex.)";
+ }
+ }
+ }
+
+ if (!have_srgb && p->use_srgb) {
+ p->use_srgb = false;
+ disabled[n_disabled++] = "sRGB";
+ }
+ if (!have_fbo && p->use_lut_3d) {
+ p->use_lut_3d = false;
+ disabled[n_disabled++] = "color management (FBO)";
+ }
+ if (!have_srgb && p->use_lut_3d) {
+ p->use_lut_3d = false;
+ disabled[n_disabled++] = "color management (sRGB)";
+ }
+
+ if (!have_fbo) {
+ p->use_scale_sep = false;
+ p->use_indirect = false;
+ }
+
+ if (n_disabled) {
+ mp_msg(MSGT_VO, MSGL_ERR, "[gl] Some OpenGL extensions not detected, "
+ "disabling: ");
+ for (int n = 0; n < n_disabled; n++) {
+ if (n)
+ mp_msg(MSGT_VO, MSGL_ERR, ", ");
+ mp_msg(MSGT_VO, MSGL_ERR, "%s", disabled[n]);
+ }
+ mp_msg(MSGT_VO, MSGL_ERR, ".\n");
+ }
+}
+
static void setup_vertex_array(GL *gl)
{
size_t stride = sizeof(struct vertex);
@@ -1616,15 +1705,7 @@ static int init_gl(struct gl_priv *p)
mp_msg(MSGT_VO, MSGL_V, "[gl] Display depth: R=%d, G=%d, B=%d\n",
p->glctx->depth_r, p->glctx->depth_g, p->glctx->depth_b);
- GLint major, minor;
- gl->GetIntegerv(GL_MAJOR_VERSION, &major);
- gl->GetIntegerv(GL_MINOR_VERSION, &minor);
-
- p->shader_version = "130";
-
- // Hack for OSX: it only creates 3.2 contexts.
- if (MPGL_VER(major, minor) >= MPGL_VER(3, 2))
- p->shader_version = "150";
+ check_gl_features(p);
gl->Disable(GL_DITHER);
gl->Disable(GL_BLEND);
@@ -1634,13 +1715,18 @@ static int init_gl(struct gl_priv *p)
gl->DrawBuffer(GL_BACK);
gl->GenBuffers(1, &p->vertex_buffer);
- gl->GenVertexArrays(1, &p->vao);
-
gl->BindBuffer(GL_ARRAY_BUFFER, p->vertex_buffer);
- gl->BindVertexArray(p->vao);
- setup_vertex_array(gl);
+
+ if (gl->BindVertexArray) {
+ gl->GenVertexArrays(1, &p->vao);
+ gl->BindVertexArray(p->vao);
+ setup_vertex_array(gl);
+ gl->BindVertexArray(0);
+ } else {
+ setup_vertex_array(gl);
+ }
+
gl->BindBuffer(GL_ARRAY_BUFFER, 0);
- gl->BindVertexArray(0);
GLint max_texture_size;
gl->GetIntegerv(GL_MAX_TEXTURE_SIZE, &max_texture_size);
@@ -1664,7 +1750,8 @@ static void uninit_gl(struct gl_priv *p)
uninit_video(p);
- gl->DeleteVertexArrays(1, &p->vao);
+ if (gl->DeleteVertexArrays)
+ gl->DeleteVertexArrays(1, &p->vao);
p->vao = 0;
gl->DeleteBuffers(1, &p->vertex_buffer);
p->vertex_buffer = 0;
@@ -1762,26 +1849,19 @@ static int query_format(uint32_t format)
return caps;
}
-static bool config_window(struct gl_priv *p, uint32_t d_width,
+static bool create_window(struct gl_priv *p, uint32_t d_width,
uint32_t d_height, uint32_t flags)
{
if (p->stereo_mode == GL_3D_QUADBUFFER)
flags |= VOFLAG_STEREO;
- int mpgl_version = MPGL_VER(3, 0);
- int mpgl_flags = p->use_gl_debug ? MPGLFLAG_DEBUG : 0;
-
- if (p->use_gl2)
- mpgl_version = MPGL_VER(2, 1);
-
- if (create_mpglcontext(p->glctx, mpgl_flags, mpgl_version, d_width,
- d_height, flags) == SET_WINDOW_FAILED)
- return false;
-
- if (!p->vertex_buffer)
- init_gl(p);
+ if (p->use_gl_debug)
+ flags |= VOFLAG_GL_DEBUG;
- return true;
+ int mpgl_caps = MPGL_CAP_GL21 | MPGL_CAP_TEX_RG;
+ if (!p->allow_sw)
+ mpgl_caps |= MPGL_CAP_NO_SW;
+ return mpgl_create_window(p->glctx, mpgl_caps, d_width, d_height, flags);
}
static int config(struct vo *vo, uint32_t width, uint32_t height,
@@ -1790,9 +1870,12 @@ static int config(struct vo *vo, uint32_t width, uint32_t height,
{
struct gl_priv *p = vo->priv;
- if (!config_window(p, d_width, d_height, flags))
+ if (!create_window(p, d_width, d_height, flags))
return -1;
+ if (!p->vertex_buffer)
+ init_gl(p);
+
p->vo_flipped = !!(flags & VOFLAG_FLIPPING);
if (p->image_format != format || p->image_width != width
@@ -1918,6 +2001,7 @@ static int control(struct vo *vo, uint32_t request, void *data)
char *arg = data;
if (!reparse_cmdline(p, arg))
return false;
+ check_gl_features(p);
reinit_rendering(p);
resize(p);
vo->want_redraw = true;
@@ -1932,7 +2016,7 @@ static void uninit(struct vo *vo)
struct gl_priv *p = vo->priv;
uninit_gl(p);
- uninit_mpglcontext(p->glctx);
+ mpgl_uninit(p->glctx);
p->glctx = NULL;
p->gl = NULL;
}
@@ -2105,6 +2189,7 @@ const struct fbo_format fbo_formats[] = {
{"rgb", GL_RGB},
{"rgba", GL_RGBA},
{"rgb8", GL_RGB8},
+ {"rgb10", GL_RGB10},
{"rgb16", GL_RGB16},
{"rgb16f", GL_RGB16F},
{"rgb32f", GL_RGB32F},
@@ -2224,6 +2309,8 @@ static bool reparse_cmdline(struct gl_priv *p, char *arg)
p->use_scale_sep = opt->use_scale_sep;
p->dither_depth = opt->dither_depth;
+ check_gl_features(p);
+
return true;
}
@@ -2275,11 +2362,11 @@ static int preinit(struct vo *vo, const char *arg)
{"lparam2", OPT_ARG_FLOAT, &p->scaler_params[1]},
{"fancy-downscaling", OPT_ARG_BOOL, &p->use_fancy_downscaling},
{"debug", OPT_ARG_BOOL, &p->use_gl_debug},
- {"force-gl2", OPT_ARG_BOOL, &p->use_gl2},
{"indirect", OPT_ARG_BOOL, &p->use_indirect},
{"scale-sep", OPT_ARG_BOOL, &p->use_scale_sep},
{"fbo-format", OPT_ARG_MSTRZ, &fbo_format, fbo_format_valid},
{"backend", OPT_ARG_MSTRZ, &backend_arg, backend_valid},
+ {"sw", OPT_ARG_BOOL, &p->allow_sw},
{"icc-profile", OPT_ARG_MSTRZ, &icc_profile},
{"icc-cache", OPT_ARG_MSTRZ, &icc_cache},
{"icc-intent", OPT_ARG_INT, &icc_intent},
@@ -2328,23 +2415,20 @@ static int preinit(struct vo *vo, const char *arg)
p->eosd = eosd_packer_create(vo);
- p->glctx = init_mpglcontext(backend, vo);
+ p->glctx = mpgl_init(backend, vo);
if (!p->glctx)
goto err_out;
p->gl = p->glctx->gl;
- if (true) {
- if (!config_window(p, 320, 200, VOFLAG_HIDDEN))
- goto err_out;
- // We created a window to test whether the GL context could be
- // created and so on. Destroy that window to make sure all state
- // associated with it is lost.
- uninit(vo);
- p->glctx = init_mpglcontext(backend, vo);
- if (!p->glctx)
- goto err_out;
- p->gl = p->glctx->gl;
- }
+ if (!create_window(p, 320, 200, VOFLAG_HIDDEN))
+ goto err_out;
+ check_gl_features(p);
+ // We created a window to test whether the GL context could be
+ // created and so on. Destroy that window to make sure all state
+ // associated with it is lost.
+ uninit_gl(p);
+ if (!mpgl_destroy_window(p->glctx))
+ goto err_out;
return 0;
@@ -2464,13 +2548,10 @@ static const char help_text[] =
" This mechanism is disabled on RGB input.\n"
" fbo-format=<fmt>\n"
" Selects the internal format of any FBO textures used.\n"
-" fmt can be one of: rgb, rgba, rgb8, rgb16, rgb16f, rgb32f\n"
+" fmt can be one of: rgb, rgba, rgb8, rgb10, rgb16, rgb16f, rgb32f\n"
" Default: rgb16.\n"
" gamma\n"
" Always enable gamma control. (Disables delayed enabling.)\n"
-" force-gl2\n"
-" Create a legacy GL context. This will randomly malfunction\n"
-" if the proper extensions are not supported.\n"
"Color management:\n"
" icc-profile=<file>\n"
" Load an ICC profile and use it to transform linear RGB to\n"