1
0
Fork 0
mirror of https://github.com/yshui/picom.git synced 2024-11-11 13:51:02 -05:00

Merge pull request #648 from tryone144/fix-pixmap-texture-nvidia

nvidia driver does not support attaching pixmap texture to fbo
This commit is contained in:
yshui 2021-07-06 12:44:20 +01:00 committed by GitHub
commit 049d347f52
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 114 additions and 13 deletions

View file

@ -241,6 +241,7 @@ _gl_average_texture_color(backend_t *base, GLuint source_texture, GLuint destina
glBindTexture(GL_TEXTURE_2D, destination_texture); glBindTexture(GL_TEXTURE_2D, destination_texture);
glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
destination_texture, 0); destination_texture, 0);
gl_check_fb_complete(GL_FRAMEBUFFER);
// Bind source texture as downscaling shader uniform input // Bind source texture as downscaling shader uniform input
glBindTexture(GL_TEXTURE_2D, source_texture); glBindTexture(GL_TEXTURE_2D, source_texture);
@ -605,8 +606,7 @@ bool gl_kernel_blur(backend_t *base, double opacity, void *ctx, const rect_t *ex
glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
GL_TEXTURE_2D, bctx->blur_textures[!curr], 0); GL_TEXTURE_2D, bctx->blur_textures[!curr], 0);
glDrawBuffer(GL_COLOR_ATTACHMENT0); glDrawBuffer(GL_COLOR_ATTACHMENT0);
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) { if (!gl_check_fb_complete(GL_FRAMEBUFFER)) {
log_error("Framebuffer attachment failed.");
return false; return false;
} }
@ -794,9 +794,7 @@ bool gl_blur(backend_t *base, double opacity, void *ctx, const region_t *reg_blu
glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER,
GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
bctx->blur_textures[i], 0); bctx->blur_textures[i], 0);
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != if (!gl_check_fb_complete(GL_FRAMEBUFFER)) {
GL_FRAMEBUFFER_COMPLETE) {
log_error("Framebuffer attachment failed.");
glBindFramebuffer(GL_FRAMEBUFFER, 0); glBindFramebuffer(GL_FRAMEBUFFER, 0);
return false; return false;
} }
@ -1063,6 +1061,8 @@ static void _gl_fill(backend_t *base, struct color c, const region_t *clip, GLui
glDeleteBuffers(2, bo); glDeleteBuffers(2, bo);
free(indices); free(indices);
free(coord); free(coord);
gl_check_err();
} }
void gl_fill(backend_t *base, struct color c, const region_t *clip) { void gl_fill(backend_t *base, struct color c, const region_t *clip) {
@ -1698,6 +1698,9 @@ bool gl_init(struct gl_data *gd, session_t *ps) {
glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
gd->back_texture, 0); gd->back_texture, 0);
glDrawBuffer(GL_COLOR_ATTACHMENT0); glDrawBuffer(GL_COLOR_ATTACHMENT0);
if (!gl_check_fb_complete(GL_FRAMEBUFFER)) {
return false;
}
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
gd->logger = gl_string_marker_logger_new(); gd->logger = gl_string_marker_logger_new();
@ -1762,18 +1765,84 @@ static inline void gl_image_decouple(backend_t *base, struct backend_image *img)
new_tex->refcount = 1; new_tex->refcount = 1;
new_tex->user_data = gd->decouple_texture_user_data(base, inner->user_data); 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; GLuint fbo;
glGenFramebuffers(1, &fbo); glGenFramebuffers(1, &fbo);
glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo); glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo);
glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
inner->texture, 0); new_tex->texture, 0);
glReadBuffer(GL_COLOR_ATTACHMENT0); glDrawBuffer(GL_COLOR_ATTACHMENT0);
glBindTexture(GL_TEXTURE_2D, new_tex->texture); gl_check_fb_complete(GL_DRAW_FRAMEBUFFER);
glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 0, 0, new_tex->width, new_tex->height, 0);
glBindTexture(GL_TEXTURE_2D, 0); glClearColor(0, 0, 0, 0);
glBindFramebuffer(GL_READ_FRAMEBUFFER, 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); glDeleteFramebuffers(1, &fbo);
glBindTexture(GL_TEXTURE_2D, 0);
glUseProgram(0);
gl_check_err();
img->inner = (struct backend_image_inner_base *)new_tex; img->inner = (struct backend_image_inner_base *)new_tex;
inner->refcount--; inner->refcount--;
} }

View file

@ -136,6 +136,14 @@ static inline const char *gl_get_err_str(GLenum err) {
CASESTRRET(GL_OUT_OF_MEMORY); CASESTRRET(GL_OUT_OF_MEMORY);
CASESTRRET(GL_STACK_UNDERFLOW); CASESTRRET(GL_STACK_UNDERFLOW);
CASESTRRET(GL_STACK_OVERFLOW); CASESTRRET(GL_STACK_OVERFLOW);
CASESTRRET(GL_FRAMEBUFFER_UNDEFINED);
CASESTRRET(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT);
CASESTRRET(GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT);
CASESTRRET(GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER);
CASESTRRET(GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER);
CASESTRRET(GL_FRAMEBUFFER_UNSUPPORTED);
CASESTRRET(GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE);
CASESTRRET(GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS);
} }
return NULL; return NULL;
} }
@ -167,6 +175,30 @@ static inline void gl_clear_err(void) {
#define gl_check_err() gl_check_err_(__func__, __LINE__) #define gl_check_err() gl_check_err_(__func__, __LINE__)
/**
* Check for GL framebuffer completeness.
*/
static inline bool gl_check_fb_complete_(const char *func, int line, GLenum fb) {
GLenum status = glCheckFramebufferStatus(fb);
if (status == GL_FRAMEBUFFER_COMPLETE) {
return true;
}
const char *stattext = gl_get_err_str(status);
if (stattext) {
log_printf(tls_logger, LOG_LEVEL_ERROR, func,
"Framebuffer attachment failed at line %d: %s", line, stattext);
} else {
log_printf(tls_logger, LOG_LEVEL_ERROR, func,
"Framebuffer attachment failed at line %d: %d", line, status);
}
return false;
}
#define gl_check_fb_complete(fb) gl_check_fb_complete_(__func__, __LINE__, (fb))
/** /**
* Check if a GLX extension exists. * Check if a GLX extension exists.
*/ */