mirror of https://github.com/mpv-player/mpv
vo_opengl: read framebuffer depth from actual FBO used for rendering
In some cases, such as when using the libmpv opengl-cb API, or with certain vo_opengl backends, the main framebuffer is never accessed. Instead, rendering is done to a FBO that acts as back buffer. This meant an incorrect/broken bit depth could be used for dithering. Change it to read the framebuffer depth lazily on the first render call. Also move the main FBO field out of the GL struct to MPGLContext, because the renderer's init function does not need to access it anymore.
This commit is contained in:
parent
03fe50651b
commit
8fb9cc2534
|
@ -94,7 +94,6 @@ struct GL {
|
|||
char *extensions; // Equivalent to GL_EXTENSIONS
|
||||
int mpgl_caps; // Bitfield of MPGL_CAP_* constants
|
||||
bool debug_context; // use of e.g. GLX_CONTEXT_DEBUG_BIT_ARB
|
||||
GLuint main_fb; // framebuffer to render to (normally 0)
|
||||
|
||||
void (GLAPIENTRY *Viewport)(GLint, GLint, GLsizei, GLsizei);
|
||||
void (GLAPIENTRY *Clear)(GLbitfield);
|
||||
|
|
|
@ -88,6 +88,9 @@ typedef struct MPGLContext {
|
|||
// Flip the rendered image vertically. This is useful for dxinterop.
|
||||
bool flip_v;
|
||||
|
||||
// framebuffer to render to (normally 0)
|
||||
GLuint main_fb;
|
||||
|
||||
// For free use by the mpgl_driver.
|
||||
void *priv;
|
||||
} MPGLContext;
|
||||
|
|
|
@ -294,7 +294,7 @@ static int d3d_size_dependent_create(MPGLContext *ctx)
|
|||
return -1;
|
||||
}
|
||||
|
||||
gl->BindFramebuffer(GL_FRAMEBUFFER, gl->main_fb);
|
||||
gl->BindFramebuffer(GL_FRAMEBUFFER, ctx->main_fb);
|
||||
gl->FramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
|
||||
GL_TEXTURE_2D, p->texture, 0);
|
||||
gl->BindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
|
@ -506,7 +506,7 @@ static int dxinterop_init(struct MPGLContext *ctx, int flags)
|
|||
goto fail;
|
||||
|
||||
// Create the shared framebuffer
|
||||
gl->GenFramebuffers(1, &gl->main_fb);
|
||||
gl->GenFramebuffers(1, &ctx->main_fb);
|
||||
|
||||
current_ctx = ctx;
|
||||
gl->SwapInterval = dxinterop_swap_interval;
|
||||
|
|
|
@ -311,7 +311,7 @@ static void glx_next_framebuffer(struct MPGLContext *ctx)
|
|||
VdpStatus vdp_st;
|
||||
GL *gl = ctx->gl;
|
||||
|
||||
ctx->gl->main_fb = 0;
|
||||
ctx->main_fb = 0;
|
||||
|
||||
int current_surface = p->current_surface++;
|
||||
p->current_surface = p->current_surface % p->num_surfaces;
|
||||
|
@ -348,7 +348,7 @@ static void glx_next_framebuffer(struct MPGLContext *ctx)
|
|||
|
||||
gl->VDPAUMapSurfacesNV(1, &surface->registered);
|
||||
surface->mapped = true;
|
||||
gl->main_fb = surface->fbo;
|
||||
ctx->main_fb = surface->fbo;
|
||||
ctx->flip_v = true;
|
||||
}
|
||||
|
||||
|
|
|
@ -100,15 +100,15 @@ void gl_upload_tex(GL *gl, GLenum target, GLenum format, GLenum type,
|
|||
gl->PixelStorei(GL_UNPACK_ALIGNMENT, 4);
|
||||
}
|
||||
|
||||
mp_image_t *gl_read_window_contents(GL *gl, int w, int h)
|
||||
mp_image_t *gl_read_fbo_contents(GL *gl, int fbo, int w, int h)
|
||||
{
|
||||
if (gl->es)
|
||||
return NULL; // ES can't read from front buffer
|
||||
mp_image_t *image = mp_image_alloc(IMGFMT_RGB24, w, h);
|
||||
if (!image)
|
||||
return NULL;
|
||||
gl->BindFramebuffer(GL_FRAMEBUFFER, gl->main_fb);
|
||||
GLenum obj = gl->main_fb ? GL_COLOR_ATTACHMENT0 : GL_FRONT;
|
||||
gl->BindFramebuffer(GL_FRAMEBUFFER, fbo);
|
||||
GLenum obj = fbo ? GL_COLOR_ATTACHMENT0 : GL_FRONT;
|
||||
gl->PixelStorei(GL_PACK_ALIGNMENT, 1);
|
||||
gl->ReadBuffer(obj);
|
||||
//flip image while reading (and also avoid stride-related trouble)
|
||||
|
|
|
@ -30,7 +30,7 @@ void gl_upload_tex(GL *gl, GLenum target, GLenum format, GLenum type,
|
|||
const void *dataptr, int stride,
|
||||
int x, int y, int w, int h);
|
||||
|
||||
mp_image_t *gl_read_window_contents(GL *gl, int w, int h);
|
||||
mp_image_t *gl_read_fbo_contents(GL *gl, int fbo, int w, int h);
|
||||
|
||||
const char* mp_sampler_type(GLenum texture_target);
|
||||
|
||||
|
|
|
@ -2643,6 +2643,17 @@ void gl_video_render_frame(struct gl_video *p, struct vo_frame *frame, int fbo)
|
|||
return;
|
||||
}
|
||||
|
||||
if (p->fb_depth == 0) {
|
||||
debug_check_gl(p, "before retrieving framebuffer depth");
|
||||
p->fb_depth = gl_get_fb_depth(gl, fbo);
|
||||
debug_check_gl(p, "retrieving framebuffer depth");
|
||||
if (p->fb_depth > 0) {
|
||||
MP_VERBOSE(p, "Reported display depth: %d\n", p->fb_depth);
|
||||
} else {
|
||||
p->fb_depth = 8;
|
||||
}
|
||||
}
|
||||
|
||||
p->broken_frame = false;
|
||||
|
||||
gl->BindFramebuffer(GL_FRAMEBUFFER, fbo);
|
||||
|
@ -3127,15 +3138,6 @@ static void init_gl(struct gl_video *p)
|
|||
if (p->texture_16bit_depth > 0)
|
||||
MP_VERBOSE(p, "16 bit texture depth: %d.\n", p->texture_16bit_depth);
|
||||
|
||||
debug_check_gl(p, "before retrieving framebuffer depth");
|
||||
p->fb_depth = gl_get_fb_depth(gl, gl->main_fb);
|
||||
debug_check_gl(p, "retrieving framebuffer depth");
|
||||
if (p->fb_depth > 0) {
|
||||
MP_VERBOSE(p, "Reported display depth: %d\n", p->fb_depth);
|
||||
} else {
|
||||
p->fb_depth = 8;
|
||||
}
|
||||
|
||||
p->upload_timer = gl_timer_create(p->gl);
|
||||
p->render_timer = gl_timer_create(p->gl);
|
||||
p->present_timer = gl_timer_create(p->gl);
|
||||
|
|
|
@ -128,7 +128,7 @@ static void draw_frame(struct vo *vo, struct vo_frame *frame)
|
|||
p->vsync_fences[p->num_vsync_fences++] = fence;
|
||||
}
|
||||
|
||||
gl_video_render_frame(p->renderer, frame, gl->main_fb);
|
||||
gl_video_render_frame(p->renderer, frame, p->glctx->main_fb);
|
||||
|
||||
if (p->opts.use_glFinish)
|
||||
gl->Finish();
|
||||
|
@ -270,8 +270,8 @@ static int control(struct vo *vo, uint32_t request, void *data)
|
|||
return VO_NOTIMPL;
|
||||
}
|
||||
case VOCTRL_SCREENSHOT_WIN: {
|
||||
struct mp_image *screen =
|
||||
gl_read_window_contents(p->gl, vo->dwidth, vo->dheight);
|
||||
struct mp_image *screen = gl_read_fbo_contents(p->gl, p->glctx->main_fb,
|
||||
vo->dwidth, vo->dheight);
|
||||
if (!screen)
|
||||
break; // redirect to backend
|
||||
// set image parameters according to the display, if possible
|
||||
|
|
Loading…
Reference in New Issue