diff --git a/video/out/gl_common.c b/video/out/gl_common.c index a8d08d1c4a..73b29c4495 100644 --- a/video/out/gl_common.c +++ b/video/out/gl_common.c @@ -98,27 +98,17 @@ struct feature { static const struct feature features[] = { {MPGL_CAP_GL_LEGACY, "Legacy OpenGL"}, - {MPGL_CAP_GL21, "OpenGL 2.1+"}, + {MPGL_CAP_GL21, "OpenGL 2.1+ (or subset)"}, {MPGL_CAP_FB, "Framebuffers"}, {MPGL_CAP_VAO, "VAOs"}, {MPGL_CAP_SRGB_TEX, "sRGB textures"}, {MPGL_CAP_SRGB_FB, "sRGB framebuffers"}, {MPGL_CAP_FLOAT_TEX, "Float textures"}, {MPGL_CAP_TEX_RG, "RG textures"}, - {MPGL_CAP_NO_SW, "NO_SW"}, + {MPGL_CAP_SW, "suspected software renderer"}, {0}, }; -static void list_features(int set, struct mp_log *log, int msgl, bool invert) -{ - char b[1024] = {0}; - for (const struct feature *f = &features[0]; f->id; f++) { - if (invert == !(f->id & set)) - mp_snprintf_cat(b, sizeof(b), " [%s]", f->name); - } - mp_msg(log, msgl, "%s\n", b); -} - // This guesses if the current GL context is a suspected software renderer. static bool is_software_gl(GL *gl) { @@ -649,11 +639,16 @@ void mpgl_load_functions2(GL *gl, void *(*get_fn)(void *ctx, const char *n), gl->glsl_version = 150; } - if (!is_software_gl(gl)) - gl->mpgl_caps |= MPGL_CAP_NO_SW; + if (is_software_gl(gl)) + gl->mpgl_caps |= MPGL_CAP_SW; - mp_verbose(log, "Detected OpenGL features:"); - list_features(gl->mpgl_caps, log, MSGL_V, false); + if (gl->mpgl_caps) { + mp_verbose(log, "Detected OpenGL features:\n"); + for (const struct feature *f = &features[0]; f->id; f++) { + if ((f->id & gl->mpgl_caps)) + mp_verbose(log, " - %s\n", f->name); + } + } // Provided for simpler handling if no framebuffer support is available. if (!gl->BindFramebuffer) @@ -906,13 +901,14 @@ static MPGLContext *init_backend(struct vo *vo, MPGLSetBackendFn set_backend, .gl = talloc_zero(ctx, GL), .vo = vo, }; - vo->probing = probing; + bool old_probing = vo->probing; + vo->probing = probing; // hack; kill it once backends are separate set_backend(ctx); if (!ctx->vo_init(vo)) { talloc_free(ctx); ctx = NULL; } - vo->probing = false; + vo->probing = old_probing; return ctx; } @@ -933,32 +929,37 @@ static MPGLContext *mpgl_create(struct vo *vo, const char *backend_name) } MPGLContext *mpgl_init(struct vo *vo, const char *backend_name, - int gl_caps, int vo_flags) + int gl_flavor, int vo_flags) { MPGLContext *ctx = mpgl_create(vo, backend_name); if (!ctx) - return NULL; + goto cleanup; - ctx->requested_gl_version = (gl_caps & MPGL_CAP_GL_LEGACY) - ? MPGL_VER(2, 1) : MPGL_VER(3, 0); + // A bit strange; but <300 triggers legacy context creation in mpv code. + ctx->requested_gl_version = gl_flavor < 210 ? 210 : 300; - if (ctx->config_window(ctx, vo_flags | VOFLAG_HIDDEN)) { - int missing = (ctx->gl->mpgl_caps & gl_caps) ^ gl_caps; - if (!missing) - return ctx; + if (!ctx->config_window(ctx, vo_flags | VOFLAG_HIDDEN)) + goto cleanup; - MP_WARN(ctx->vo, "Missing OpenGL features:"); - list_features(missing, ctx->vo->log, MSGL_WARN, false); - if (missing == MPGL_CAP_NO_SW) { - MP_WARN(ctx->vo, "Rejecting suspected software OpenGL renderer.\n"); - } else if ((missing & MPGL_CAP_GL21) && - (ctx->gl->mpgl_caps & MPGL_CAP_GL_LEGACY)) - { - MP_WARN(ctx->vo, "OpenGL version too old. Try: --vo=opengl-old\n"); - } + if (gl_flavor >= 210 && !(ctx->gl->mpgl_caps & MPGL_CAP_GL21)) { + MP_WARN(ctx->vo, "At least OpenGL 2.1 required.\n"); + if (!vo->probing && (ctx->gl->mpgl_caps & MPGL_CAP_GL_LEGACY)) + MP_WARN(ctx->vo, "Try with: --vo=opengl-old\n"); + goto cleanup; + } else if (gl_flavor < 210 && !(ctx->gl->mpgl_caps & MPGL_CAP_GL_LEGACY)) { + MP_WARN(ctx->vo, "OpenGL context creation failed!\n"); + goto cleanup; } - MP_ERR(ctx->vo, "OpenGL context creation failed!\n"); + if (ctx->gl->mpgl_caps & MPGL_CAP_SW) { + MP_WARN(ctx->vo, "Suspected software renderer or indirect context.\n"); + if (vo->probing) + goto cleanup; + } + + return ctx; + +cleanup: mpgl_uninit(ctx); return NULL; } diff --git a/video/out/gl_common.h b/video/out/gl_common.h index e391663b93..f70614972a 100644 --- a/video/out/gl_common.h +++ b/video/out/gl_common.h @@ -79,7 +79,7 @@ enum { MPGL_CAP_TEX_RG = (1 << 10), // GL_ARB_texture_rg / GL 3.x MPGL_CAP_VDPAU = (1 << 11), // GL_NV_vdpau_interop MPGL_CAP_APPLE_RGB_422 = (1 << 12), // GL_APPLE_rgb_422 - MPGL_CAP_NO_SW = (1 << 30), // used to block sw. renderers + MPGL_CAP_SW = (1 << 30), // indirect or sw renderer }; // E.g. 310 means 3.1 @@ -136,11 +136,11 @@ bool mpgl_is_thread_safe(MPGLContext *ctx); // Create a VO window and create a GL context on it. // (Calls config_window_gl3 or config_window+setGlWindow.) -// gl_caps: bitfield of MPGL_CAP_* (required GL version and feature set) +// gl_flavor: 110 for legacy GL, 210 for GL 2.1 or 3.x core // flags: passed to the backend's create window function // Returns success. MPGLContext *mpgl_init(struct vo *vo, const char *backend_name, - int gl_caps, int vo_flags); + int gl_flavor, int vo_flags); void mpgl_uninit(MPGLContext *ctx); // flags: passed to the backend function diff --git a/video/out/gl_x11.c b/video/out/gl_x11.c index 5fe43e54f7..67f87716bd 100644 --- a/video/out/gl_x11.c +++ b/video/out/gl_x11.c @@ -68,9 +68,6 @@ static bool create_context_x11_old(struct MPGLContext *ctx) glx_ctx->context = new_context; - if (!glXIsDirect(vo->x11->display, new_context)) - ctx->gl->mpgl_caps &= ~MPGL_CAP_NO_SW; - return true; } @@ -124,9 +121,6 @@ static bool create_context_x11_gl3(struct MPGLContext *ctx, bool debug) mpgl_load_functions(ctx->gl, (void *)glXGetProcAddress, glxstr, vo->log); - if (!glXIsDirect(vo->x11->display, context)) - ctx->gl->mpgl_caps &= ~MPGL_CAP_NO_SW; - return true; } @@ -260,14 +254,11 @@ static bool config_window_x11(struct MPGLContext *ctx, int flags) success = create_context_x11_gl3(ctx, flags & VOFLAG_GL_DEBUG); if (!success) success = create_context_x11_old(ctx); + if (success && !glXIsDirect(vo->x11->display, glx_ctx->context)) + ctx->gl->mpgl_caps |= MPGL_CAP_SW; return success; } - -/** - * \brief free the VisualInfo and GLXContext of an OpenGL context. - * \ingroup glcontext - */ static void releaseGlContext_x11(MPGLContext *ctx) { struct glx_context *glx_ctx = ctx->priv; diff --git a/video/out/vo.c b/video/out/vo.c index f6dda92532..c2ec6c5813 100644 --- a/video/out/vo.c +++ b/video/out/vo.c @@ -202,7 +202,7 @@ static void dealloc_vo(struct vo *vo) talloc_free(vo); } -static struct vo *vo_create(struct mpv_global *global, +static struct vo *vo_create(bool probing, struct mpv_global *global, struct input_ctx *input_ctx, struct osd_state *osd, struct encode_lavc_context *encode_lavc_ctx, char *name, char **args) @@ -225,6 +225,7 @@ static struct vo *vo_create(struct mpv_global *global, .osd = osd, .event_fd = -1, .monitor_par = 1, + .probing = probing, .in = talloc(vo, struct vo_internal), }; talloc_steal(vo, log); @@ -271,7 +272,8 @@ struct vo *init_best_video_out(struct mpv_global *global, // Something like "-vo name," allows fallback to autoprobing. if (strlen(vo_list[n].name) == 0) goto autoprobe; - struct vo *vo = vo_create(global, input_ctx, osd, encode_lavc_ctx, + bool p = !!vo_list[n + 1].name; + struct vo *vo = vo_create(p, global, input_ctx, osd, encode_lavc_ctx, vo_list[n].name, vo_list[n].attribs); if (vo) return vo; @@ -281,7 +283,7 @@ struct vo *init_best_video_out(struct mpv_global *global, autoprobe: // now try the rest... for (int i = 0; video_out_drivers[i]; i++) { - struct vo *vo = vo_create(global, input_ctx, osd, encode_lavc_ctx, + struct vo *vo = vo_create(true, global, input_ctx, osd, encode_lavc_ctx, (char *)video_out_drivers[i]->name, NULL); if (vo) return vo; diff --git a/video/out/vo_opengl.c b/video/out/vo_opengl.c index ab7d2380c7..bc98f513a7 100644 --- a/video/out/vo_opengl.c +++ b/video/out/vo_opengl.c @@ -408,11 +408,10 @@ static int preinit(struct vo *vo) if (p->use_gl_debug) vo_flags |= VOFLAG_GL_DEBUG; - int mpgl_caps = MPGL_CAP_GL21; - if (!p->allow_sw) - mpgl_caps |= MPGL_CAP_NO_SW; + if (p->allow_sw) + vo->probing = false; - p->glctx = mpgl_init(vo, p->backend, mpgl_caps, vo_flags); + p->glctx = mpgl_init(vo, p->backend, 210, vo_flags); if (!p->glctx) goto err_out; p->gl = p->glctx->gl; diff --git a/video/out/vo_opengl_old.c b/video/out/vo_opengl_old.c index a3a8b69c0a..bf117fdbd9 100644 --- a/video/out/vo_opengl_old.c +++ b/video/out/vo_opengl_old.c @@ -2168,11 +2168,10 @@ static int preinit(struct vo *vo) if (p->stereo_mode == GL_3D_QUADBUFFER) vo_flags |= VOFLAG_STEREO; - int mpgl_caps = MPGL_CAP_GL_LEGACY; - if (!p->allow_sw) - mpgl_caps |= MPGL_CAP_NO_SW; + if (p->allow_sw) + vo->probing = false; - p->glctx = mpgl_init(vo, p->backend_arg, mpgl_caps, vo_flags); + p->glctx = mpgl_init(vo, p->backend_arg, MPGL_CAP_GL_LEGACY, vo_flags); if (!p->glctx) goto err_out; p->gl = p->glctx->gl;