diff options
Diffstat (limited to 'libvo/vo_gl3.c')
-rw-r--r-- | libvo/vo_gl3.c | 221 |
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" |