mirror of https://github.com/yshui/picom.git
backend: gl_common: Copy texture by explict rendering to framebuffer
At least on nvidia, binding the textures from a glx pixmap to a
framebuffer results in `GL_FRAMEBUFFER_UNSUPPORTED`. Instead of using
binding the source texture to a framebuffer and using `glCopyTexImage2D()`
to copy into a new texture, explicitly render the source texture to the
new texture attached to a framebuffer.
Fixes black/invisible windows on nvidia with `frame-opacity != 1`.
see: #647
related: 2a60836a9b
This commit is contained in:
parent
f11710a885
commit
bf79653fa2
|
@ -1765,18 +1765,84 @@ static inline void gl_image_decouple(backend_t *base, struct backend_image *img)
|
|||
new_tex->refcount = 1;
|
||||
new_tex->user_data = gd->decouple_texture_user_data(base, inner->user_data);
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, new_tex->texture);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, new_tex->width, new_tex->height, 0,
|
||||
GL_BGRA, GL_UNSIGNED_BYTE, NULL);
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
|
||||
assert(gd->present_prog);
|
||||
glUseProgram(gd->present_prog);
|
||||
glBindTexture(GL_TEXTURE_2D, inner->texture);
|
||||
|
||||
GLuint fbo;
|
||||
glGenFramebuffers(1, &fbo);
|
||||
glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo);
|
||||
glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
|
||||
inner->texture, 0);
|
||||
glReadBuffer(GL_COLOR_ATTACHMENT0);
|
||||
glBindTexture(GL_TEXTURE_2D, new_tex->texture);
|
||||
glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 0, 0, new_tex->width, new_tex->height, 0);
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
|
||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo);
|
||||
glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
|
||||
new_tex->texture, 0);
|
||||
glDrawBuffer(GL_COLOR_ATTACHMENT0);
|
||||
gl_check_fb_complete(GL_DRAW_FRAMEBUFFER);
|
||||
|
||||
glClearColor(0, 0, 0, 0);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
|
||||
// clang-format off
|
||||
GLint coord[] = {
|
||||
// top left
|
||||
0, 0, // vertex coord
|
||||
0, 0, // texture coord
|
||||
|
||||
// top right
|
||||
new_tex->width, 0, // vertex coord
|
||||
new_tex->width, 0, // texture coord
|
||||
|
||||
// bottom right
|
||||
new_tex->width, new_tex->height,
|
||||
new_tex->width, new_tex->height,
|
||||
|
||||
// bottom left
|
||||
0, new_tex->height,
|
||||
0, new_tex->height,
|
||||
};
|
||||
// clang-format on
|
||||
GLuint indices[] = {0, 1, 2, 2, 3, 0};
|
||||
|
||||
GLuint vao;
|
||||
glGenVertexArrays(1, &vao);
|
||||
glBindVertexArray(vao);
|
||||
|
||||
GLuint bo[2];
|
||||
glGenBuffers(2, bo);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, bo[0]);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, bo[1]);
|
||||
glBufferData(GL_ARRAY_BUFFER, (long)sizeof(*coord) * 16, coord, GL_STATIC_DRAW);
|
||||
glBufferData(GL_ELEMENT_ARRAY_BUFFER, (long)sizeof(*indices) * 6, indices,
|
||||
GL_STATIC_DRAW);
|
||||
|
||||
glEnableVertexAttribArray(vert_coord_loc);
|
||||
glEnableVertexAttribArray(vert_in_texcoord_loc);
|
||||
glVertexAttribPointer(vert_coord_loc, 2, GL_INT, GL_FALSE, sizeof(GLint) * 4, NULL);
|
||||
glVertexAttribPointer(vert_in_texcoord_loc, 2, GL_INT, GL_FALSE,
|
||||
sizeof(GLint) * 4, (void *)(sizeof(GLint) * 2));
|
||||
|
||||
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, NULL);
|
||||
|
||||
glDisableVertexAttribArray(vert_coord_loc);
|
||||
glDisableVertexAttribArray(vert_in_texcoord_loc);
|
||||
glBindVertexArray(0);
|
||||
glDeleteVertexArrays(1, &vao);
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
|
||||
glDeleteBuffers(2, bo);
|
||||
|
||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
|
||||
glDeleteFramebuffers(1, &fbo);
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
glUseProgram(0);
|
||||
|
||||
gl_check_err();
|
||||
|
||||
img->inner = (struct backend_image_inner_base *)new_tex;
|
||||
inner->refcount--;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue