new glx: always use GL_TEXTURE_2D

Rectangle textures was used as a fallback when the driver doesn't
support non-power-of-two (NPOT) textures. Since we are using OpenGL 3.0 now,
which includes support for NPOT textures, we don't need this fallback
anymore.

Signed-off-by: Yuxuan Shui <yshuiv7@gmail.com>
This commit is contained in:
Yuxuan Shui 2019-03-10 20:38:34 +00:00
parent e1c5e7ab8d
commit cabd0b0801
No known key found for this signature in database
GPG Key ID: 37C999F617EA1A47
3 changed files with 60 additions and 93 deletions

View File

@ -181,7 +181,7 @@ void gl_compose(backend_t *base, void *image_data, int dst_x, int dst_y,
// It's required by legacy versions of OpenGL to enable texture target
// before specifying environment. Thanks to madsy for telling me.
glEnable(ptex->target);
glEnable(GL_TEXTURE_2D);
if (gd->win_shader.prog) {
glUseProgram(gd->win_shader.prog);
if (gd->win_shader.unifm_opacity >= 0) {
@ -202,10 +202,10 @@ void gl_compose(backend_t *base, void *image_data, int dst_x, int dst_y,
// x, y, width, height, dx, dy, ptex->width, ptex->height, z);
// Bind texture
glBindTexture(ptex->target, ptex->texture);
glBindTexture(GL_TEXTURE_2D, ptex->texture);
if (dual_texture) {
glActiveTexture(GL_TEXTURE1);
glBindTexture(ptex->target, ptex->texture);
glBindTexture(GL_TEXTURE_2D, ptex->texture);
glActiveTexture(GL_TEXTURE0);
}
@ -235,13 +235,12 @@ void gl_compose(backend_t *base, void *image_data, int dst_x, int dst_y,
texture_y2 = ptex->height - texture_y2;
}
if (ptex->target == GL_TEXTURE_2D) {
// GL_TEXTURE_2D coordinates are normalized
texture_x1 /= ptex->width;
texture_y1 /= ptex->height;
texture_x2 /= ptex->width;
texture_y2 /= ptex->height;
}
// GL_TEXTURE_2D coordinates are normalized
// TODO use texelFetch
texture_x1 /= ptex->width;
texture_y1 /= ptex->height;
texture_x2 /= ptex->width;
texture_y2 /= ptex->height;
// Vertex coordinates
GLint vx1 = crect.x1;
@ -266,15 +265,15 @@ void gl_compose(backend_t *base, void *image_data, int dst_x, int dst_y,
glEnd();
// Cleanup
glBindTexture(ptex->target, 0);
glBindTexture(GL_TEXTURE_2D, 0);
glColor4f(0.0f, 0.0f, 0.0f, 0.0f);
glDisable(GL_COLOR_LOGIC_OP);
glDisable(ptex->target);
glDisable(GL_TEXTURE_2D);
if (dual_texture) {
glActiveTexture(GL_TEXTURE1);
glBindTexture(ptex->target, 0);
glDisable(ptex->target);
glBindTexture(GL_TEXTURE_2D, 0);
glDisable(GL_TEXTURE_2D);
glActiveTexture(GL_TEXTURE0);
}
@ -304,10 +303,10 @@ bool gl_blur(backend_t *base, double opacity, const region_t *reg_blur,
int curr = 0;
glReadBuffer(GL_BACK);
glEnable(gd->blur_texture_target);
glBindTexture(gd->blur_texture_target, gd->blur_texture[0]);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, gd->blur_texture[0]);
// Copy the area to be blurred into tmp buffer
glCopyTexSubImage2D(gd->blur_texture_target, 0, 0, 0, extent->x1, dst_y, width, height);
glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, extent->x1, dst_y, width, height);
for (int i = 0; i < gd->npasses; ++i) {
assert(i < MAX_BLUR_PASS - 1);
@ -315,7 +314,7 @@ bool gl_blur(backend_t *base, double opacity, const region_t *reg_blur,
assert(p->prog);
assert(gd->blur_texture[curr]);
glBindTexture(gd->blur_texture_target, gd->blur_texture[curr]);
glBindTexture(GL_TEXTURE_2D, gd->blur_texture[curr]);
glUseProgram(p->prog);
if (i < gd->npasses - 1) {
@ -323,8 +322,7 @@ bool gl_blur(backend_t *base, double opacity, const region_t *reg_blur,
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, gd->blur_fbo);
glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
gd->blur_texture_target,
gd->blur_texture[!curr], 0);
GL_TEXTURE_2D, gd->blur_texture[!curr], 0);
glDrawBuffer(GL_COLOR_ATTACHMENT0);
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
log_error("Framebuffer attachment failed.");
@ -338,13 +336,8 @@ bool gl_blur(backend_t *base, double opacity, const region_t *reg_blur,
glUniform1f(p->unifm_opacity, opacity);
}
if (gd->blur_texture_target == GL_TEXTURE_2D) {
glUniform1f(p->unifm_offset_x, 1.0 / gd->width);
glUniform1f(p->unifm_offset_y, 1.0 / gd->height);
} else {
glUniform1f(p->unifm_offset_x, 1.0);
glUniform1f(p->unifm_offset_y, 1.0);
}
glUniform1f(p->unifm_offset_x, 1.0 / gd->width);
glUniform1f(p->unifm_offset_y, 1.0 / gd->height);
// XXX use multiple draw calls is probably going to be slow than
// just simply blur the whole area.
@ -366,12 +359,10 @@ bool gl_blur(backend_t *base, double opacity, const region_t *reg_blur,
GLfloat texture_x2 = texture_x1 + (crect.x2 - crect.x1);
GLfloat texture_y2 = texture_y1 + (crect.y1 - crect.y2);
if (gd->blur_texture_target == GL_TEXTURE_2D) {
texture_x1 /= gd->width;
texture_x2 /= gd->width;
texture_y1 /= gd->height;
texture_y2 /= gd->height;
}
texture_x1 /= gd->width;
texture_x2 /= gd->width;
texture_y1 /= gd->height;
texture_y2 /= gd->height;
// Vertex coordinates
// For passes before the last one, we are drawing into a buffer,
@ -407,8 +398,8 @@ bool gl_blur(backend_t *base, double opacity, const region_t *reg_blur,
end:
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glBindTexture(gd->blur_texture_target, 0);
glDisable(gd->blur_texture_target);
glBindTexture(GL_TEXTURE_2D, 0);
glDisable(GL_TEXTURE_2D);
gl_check_err();
@ -464,13 +455,13 @@ void gl_resize(struct gl_data *gd, int width, int height) {
if (gd->npasses > 0) {
// Resize the temporary textures used for blur
glBindTexture(gd->blur_texture_target, gd->blur_texture[0]);
glTexImage2D(gd->blur_texture_target, 0, GL_RGBA8, gd->width, gd->height,
0, GL_BGRA, GL_UNSIGNED_BYTE, NULL);
glBindTexture(GL_TEXTURE_2D, gd->blur_texture[0]);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, gd->width, gd->height, 0,
GL_BGRA, GL_UNSIGNED_BYTE, NULL);
if (gd->npasses > 1) {
glBindTexture(gd->blur_texture_target, gd->blur_texture[1]);
glTexImage2D(gd->blur_texture_target, 0, GL_RGBA8, gd->width,
gd->height, 0, GL_BGRA, GL_UNSIGNED_BYTE, NULL);
glBindTexture(GL_TEXTURE_2D, gd->blur_texture[1]);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, gd->width, gd->height, 0,
GL_BGRA, GL_UNSIGNED_BYTE, NULL);
}
}
}
@ -508,7 +499,7 @@ static bool gl_init_blur(struct gl_data *gd, conv *const *const kernels) {
%s\n // other extension pragmas
uniform float offset_x;
uniform float offset_y;
uniform %s tex_scr;
uniform sampler2D tex_scr;
uniform float opacity;
out vec4 out_color;
void main() {
@ -519,19 +510,13 @@ static bool gl_init_blur(struct gl_data *gd, conv *const *const kernels) {
);
static const char *FRAG_SHADER_BLUR_ADD = QUOTE(
sum += float(%.7g) *
%s(tex_scr, vec2(gl_TexCoord[0].x + offset_x * float(%d),
texture2D(tex_scr, vec2(gl_TexCoord[0].x + offset_x * float(%d),
gl_TexCoord[0].y + offset_y * float(%d)));
);
// clang-format on
const bool use_texture_rect = !gd->non_power_of_two_texture;
const char *sampler_type = (use_texture_rect ? "sampler2DRect" : "sampler2D");
const char *texture_func = (use_texture_rect ? "texture2DRect" : "texture2D");
const char *shader_add = FRAG_SHADER_BLUR_ADD;
char *extension = strdup("");
if (use_texture_rect) {
mstrextend(&extension, "#extension GL_ARB_texture_rectangle : require\n");
}
gl_blur_shader_t *passes = gd->blur_shader;
for (int i = 0; i < MAX_BLUR_PASS && kernels[i]; gd->npasses = ++i) {
@ -539,7 +524,7 @@ static bool gl_init_blur(struct gl_data *gd, conv *const *const kernels) {
// Build shader
int width = kern->w, height = kern->h;
int nele = width * height - 1;
size_t body_len = (strlen(shader_add) + strlen(texture_func) + 42) * nele;
size_t body_len = (strlen(shader_add) + 42) * nele;
char *shader_body = ccalloc(body_len, char);
char *pc = shader_body;
@ -557,19 +542,19 @@ static bool gl_init_blur(struct gl_data *gd, conv *const *const kernels) {
}
sum += val;
pc += snprintf(pc, body_len - (pc - shader_body),
FRAG_SHADER_BLUR_ADD, val, texture_func,
k - width / 2, j - height / 2);
FRAG_SHADER_BLUR_ADD, val, k - width / 2,
j - height / 2);
assert(pc < shader_body + body_len);
}
}
auto pass = passes + i;
size_t shader_len = strlen(FRAG_SHADER_BLUR) + strlen(extension) +
strlen(sampler_type) + strlen(shader_body) +
10 /* sum */ + 1 /* null terminator */;
strlen(shader_body) + 10 /* sum */ +
1 /* null terminator */;
char *shader_str = ccalloc(shader_len, char);
size_t real_shader_len = snprintf(shader_str, shader_len, FRAG_SHADER_BLUR,
extension, sampler_type, shader_body, sum);
size_t real_shader_len = snprintf(
shader_str, shader_len, FRAG_SHADER_BLUR, extension, shader_body, sum);
assert(real_shader_len < shader_len);
free(shader_body);
@ -591,21 +576,16 @@ static bool gl_init_blur(struct gl_data *gd, conv *const *const kernels) {
}
free(extension);
// Generate FBO and textures if needed
gd->blur_texture_target = GL_TEXTURE_RECTANGLE;
if (gd->non_power_of_two_texture) {
gd->blur_texture_target = GL_TEXTURE_2D;
}
// Texture size will be defined by gl_resize
glGenTextures(gd->npasses > 1 ? 2 : 1, gd->blur_texture);
glBindTexture(gd->blur_texture_target, gd->blur_texture[0]);
glTexParameteri(gd->blur_texture_target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(gd->blur_texture_target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glBindTexture(GL_TEXTURE_2D, gd->blur_texture[0]);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
if (gd->npasses > 1) {
glBindTexture(gd->blur_texture_target, gd->blur_texture[1]);
glTexParameteri(gd->blur_texture_target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(gd->blur_texture_target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glBindTexture(GL_TEXTURE_2D, gd->blur_texture[1]);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
// Generate FBO and textures when needed
glGenFramebuffers(1, &gd->blur_fbo);
if (!gd->blur_fbo) {
log_error("Failed to generate framebuffer object for blur");
@ -651,9 +631,6 @@ bool gl_init(struct gl_data *gd, session_t *ps) {
gd->blur_shader[i] = (gl_blur_shader_t){.prog = 0};
}
gd->non_power_of_two_texture =
gl_has_extension("GL_ARB_texture_non_power_of_two");
glDisable(GL_DEPTH_TEST);
glDepthMask(GL_FALSE);

View File

@ -37,7 +37,6 @@ typedef struct gl_texture {
double dim;
int *refcount;
GLuint texture;
GLenum target;
// The size of the backing texture
int width, height;
// The effective size of the texture
@ -55,7 +54,6 @@ struct gl_data {
int npasses;
gl_win_shader_t win_shader;
gl_blur_shader_t blur_shader[MAX_BLUR_PASS];
bool non_power_of_two_texture;
// Temporary textures used for blurring. They are always the same size as the
// target, so they are always big enough without resizing.
@ -63,7 +61,6 @@ struct gl_data {
GLuint blur_texture[2];
// Temporary fbo used for blurring
GLuint blur_fbo;
GLenum blur_texture_target;
};
typedef struct {

View File

@ -168,9 +168,9 @@ void glx_release_image(backend_t *base, void *image_data) {
}
// Release binding
if (wd->glpixmap && wd->texture.texture) {
glBindTexture(wd->texture.target, wd->texture.texture);
glBindTexture(GL_TEXTURE_2D, wd->texture.texture);
glXReleaseTexImageEXT(gd->display, wd->glpixmap, GLX_FRONT_LEFT_EXT);
glBindTexture(wd->texture.target, 0);
glBindTexture(GL_TEXTURE_2D, 0);
}
// Free GLX Pixmap
@ -368,29 +368,22 @@ glx_bind_pixmap(backend_t *base, xcb_pixmap_t pixmap, struct xvisual_info fmt, b
// Choose a suitable texture target for our pixmap.
// Refer to GLX_EXT_texture_om_pixmap spec to see what are the mean
// of the bits in texture_tgts
GLenum tex_tgt = 0;
if (GLX_TEXTURE_2D_BIT_EXT & fbcfg->texture_tgts && gd->gl.non_power_of_two_texture)
tex_tgt = GLX_TEXTURE_2D_EXT;
else if (GLX_TEXTURE_RECTANGLE_BIT_EXT & fbcfg->texture_tgts)
tex_tgt = GLX_TEXTURE_RECTANGLE_EXT;
else if (!(GLX_TEXTURE_2D_BIT_EXT & fbcfg->texture_tgts))
tex_tgt = GLX_TEXTURE_RECTANGLE_EXT;
else
tex_tgt = GLX_TEXTURE_2D_EXT;
if (!(fbcfg->texture_tgts & GLX_TEXTURE_2D_EXT)) {
log_error("Cannot bind pixmap to GL_TEXTURE_2D, giving up");
goto err;
}
log_debug("depth %d, tgt %#x, rgba %d", fmt.visual_depth, tex_tgt,
(GLX_TEXTURE_FORMAT_RGBA_EXT == fbcfg->texture_fmt));
log_debug("depth %d, rgba %d", fmt.visual_depth,
(fbcfg->texture_fmt = GLX_TEXTURE_FORMAT_RGBA_EXT));
GLint attrs[] = {
GLX_TEXTURE_FORMAT_EXT,
fbcfg->texture_fmt,
GLX_TEXTURE_TARGET_EXT,
tex_tgt,
GLX_TEXTURE_2D_EXT,
0,
};
wd->texture.target =
(GLX_TEXTURE_2D_EXT == tex_tgt ? GL_TEXTURE_2D : GL_TEXTURE_RECTANGLE);
wd->texture.y_inverted = fbcfg->y_inverted;
wd->glpixmap = glXCreatePixmap(gd->display, fbcfg->cfg, wd->pixmap, attrs);
@ -402,7 +395,7 @@ glx_bind_pixmap(backend_t *base, xcb_pixmap_t pixmap, struct xvisual_info fmt, b
}
// Create texture
wd->texture.texture = gl_new_texture(wd->texture.target);
wd->texture.texture = gl_new_texture(GL_TEXTURE_2D);
wd->texture.opacity = 1;
wd->texture.depth = fmt.visual_depth;
wd->texture.color_inverted = false;
@ -411,9 +404,9 @@ glx_bind_pixmap(backend_t *base, xcb_pixmap_t pixmap, struct xvisual_info fmt, b
wd->texture.refcount = ccalloc(1, int);
*wd->texture.refcount = 1;
wd->owned = owned;
glBindTexture(wd->texture.target, wd->texture.texture);
glBindTexture(GL_TEXTURE_2D, wd->texture.texture);
glXBindTexImageEXT(gd->display, wd->glpixmap, GLX_FRONT_LEFT_EXT, NULL);
glBindTexture(wd->texture.target, 0);
glBindTexture(GL_TEXTURE_2D, 0);
gl_check_err();
return wd;