diff options
-rw-r--r-- | glamor/glamor.c | 36 | ||||
-rw-r--r-- | glamor/glamor_composite_glyphs.c | 3 | ||||
-rw-r--r-- | glamor/glamor_copy.c | 8 | ||||
-rw-r--r-- | glamor/glamor_dash.c | 3 | ||||
-rw-r--r-- | glamor/glamor_fbo.c | 4 | ||||
-rw-r--r-- | glamor/glamor_priv.h | 28 | ||||
-rw-r--r-- | glamor/glamor_program.c | 4 | ||||
-rw-r--r-- | glamor/glamor_render.c | 21 | ||||
-rw-r--r-- | glamor/glamor_spans.c | 3 | ||||
-rw-r--r-- | glamor/glamor_transfer.c | 3 | ||||
-rw-r--r-- | glamor/glamor_transform.c | 12 | ||||
-rw-r--r-- | glamor/glamor_transform.h | 4 |
12 files changed, 103 insertions, 26 deletions
diff --git a/glamor/glamor.c b/glamor/glamor.c index 477bc0e60..62b5c3a19 100644 --- a/glamor/glamor.c +++ b/glamor/glamor.c @@ -140,6 +140,42 @@ glamor_get_pixmap_texture(PixmapPtr pixmap) return pixmap_priv->fbo->tex; } +void +glamor_bind_texture(glamor_screen_private *glamor_priv, GLenum texture, + glamor_pixmap_fbo *fbo, Bool destination_red) +{ + glActiveTexture(texture); + glBindTexture(GL_TEXTURE_2D, fbo->tex); + + /* If we're pulling data from a GL_RED texture, then whether we + * want to make it an A,0,0,0 result or a 0,0,0,R result depends + * on whether the destination is also a GL_RED texture. + * + * For GL_RED destinations, we need to leave the bits in the R + * channel. For all other destinations, we need to clear out the R + * channel so that it returns zero for R, G and B. + * + * Note that we're leaving the SWIZZLE_A value alone; for GL_RED + * destinations, that means we'll actually be returning R,0,0,R, + * but it doesn't matter as the bits in the alpha channel aren't + * going anywhere. + */ + + /* Is the operand a GL_RED fbo? + */ + + if (glamor_fbo_red_is_alpha(glamor_priv, fbo)) { + + /* If destination is also GL_RED, then preserve the bits in + * the R channel */ + + if (destination_red) + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_R, GL_RED); + else + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_R, GL_ZERO); + } +} + PixmapPtr glamor_create_pixmap(ScreenPtr screen, int w, int h, int depth, unsigned int usage) diff --git a/glamor/glamor_composite_glyphs.c b/glamor/glamor_composite_glyphs.c index f51ff6dad..50fd02645 100644 --- a/glamor/glamor_composite_glyphs.c +++ b/glamor/glamor_composite_glyphs.c @@ -246,8 +246,7 @@ glamor_glyphs_flush(CARD8 op, PicturePtr src, PicturePtr dst, glamor_put_vbo_space(drawable->pScreen); glEnable(GL_SCISSOR_TEST); - glActiveTexture(GL_TEXTURE1); - glBindTexture(GL_TEXTURE_2D, atlas_fbo->tex); + glamor_bind_texture(glamor_priv, GL_TEXTURE1, atlas_fbo, FALSE); for (;;) { if (!glamor_use_program_render(prog, op, src, dst)) diff --git a/glamor/glamor_copy.c b/glamor/glamor_copy.c index 5fed89f0c..3501a0d24 100644 --- a/glamor/glamor_copy.c +++ b/glamor/glamor_copy.c @@ -38,8 +38,8 @@ use_copyarea(PixmapPtr dst, GCPtr gc, glamor_program *prog, void *arg) struct copy_args *args = arg; glamor_pixmap_fbo *src = args->src; - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, src->tex); + glamor_bind_texture(glamor_get_screen_private(dst->drawable.pScreen), + GL_TEXTURE0, src, TRUE); glUniform2f(prog->fill_offset_uniform, args->dx, args->dy); glUniform2f(prog->fill_size_inv_uniform, 1.0f/src->width, 1.0f/src->height); @@ -67,8 +67,8 @@ use_copyplane(PixmapPtr dst, GCPtr gc, glamor_program *prog, void *arg) struct copy_args *args = arg; glamor_pixmap_fbo *src = args->src; - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, src->tex); + glamor_bind_texture(glamor_get_screen_private(dst->drawable.pScreen), + GL_TEXTURE0, src, TRUE); glUniform2f(prog->fill_offset_uniform, args->dx, args->dy); glUniform2f(prog->fill_size_inv_uniform, 1.0f/src->width, 1.0f/src->height); diff --git a/glamor/glamor_dash.c b/glamor/glamor_dash.c index a6a11c1a2..3c19dba32 100644 --- a/glamor/glamor_dash.c +++ b/glamor/glamor_dash.c @@ -188,8 +188,7 @@ glamor_dash_setup(DrawablePtr drawable, GCPtr gc) /* Set the dash pattern as texture 1 */ - glActiveTexture(GL_TEXTURE1); - glBindTexture(GL_TEXTURE_2D, dash_priv->fbo->tex); + glamor_bind_texture(glamor_priv, GL_TEXTURE1, dash_priv->fbo, FALSE); glUniform1i(prog->dash_uniform, 1); glUniform1f(prog->dash_length_uniform, dash_pixmap->drawable.width); diff --git a/glamor/glamor_fbo.c b/glamor/glamor_fbo.c index f4f874981..a531f6052 100644 --- a/glamor/glamor_fbo.c +++ b/glamor/glamor_fbo.c @@ -352,10 +352,8 @@ _glamor_create_tex(glamor_screen_private *glamor_priv, glBindTexture(GL_TEXTURE_2D, tex); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - if (format == glamor_priv->one_channel_format && format == GL_RED) { - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_R, GL_ZERO); + if (format == glamor_priv->one_channel_format && format == GL_RED) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_A, GL_RED); - } glamor_priv->suppress_gl_out_of_memory_logging = true; glTexImage2D(GL_TEXTURE_2D, 0, format, w, h, 0, format, GL_UNSIGNED_BYTE, NULL); diff --git a/glamor/glamor_priv.h b/glamor/glamor_priv.h index 8f994ea19..c34eb84c0 100644 --- a/glamor/glamor_priv.h +++ b/glamor/glamor_priv.h @@ -573,6 +573,34 @@ void glamor_fini_pixmap_fbo(ScreenPtr screen); Bool glamor_pixmap_fbo_fixup(ScreenPtr screen, PixmapPtr pixmap); void glamor_fbo_expire(glamor_screen_private *glamor_priv); +/* Return whether 'picture' is alpha-only */ +static inline Bool glamor_picture_is_alpha(PicturePtr picture) +{ + return picture->format == PICT_a1 || picture->format == PICT_a8; +} + +/* Return whether 'fbo' is storing alpha bits in the red channel */ +static inline Bool +glamor_fbo_red_is_alpha(glamor_screen_private *glamor_priv, glamor_pixmap_fbo *fbo) +{ + /* True when the format is GL_RED (that can only happen when our one channel format is GL_RED */ + return fbo->format == GL_RED; +} + +/* Return whether 'picture' is storing alpha bits in the red channel */ +static inline Bool +glamor_picture_red_is_alpha(PicturePtr picture) +{ + /* True when the picture is alpha only and the screen is using GL_RED for alpha pictures */ + return glamor_picture_is_alpha(picture) && + glamor_get_screen_private(picture->pDrawable->pScreen)->one_channel_format == GL_RED; +} + +void glamor_bind_texture(glamor_screen_private *glamor_priv, + GLenum texture, + glamor_pixmap_fbo *fbo, + Bool destination_red); + glamor_pixmap_fbo *glamor_create_fbo_array(glamor_screen_private *glamor_priv, int w, int h, GLenum format, int flag, int block_w, int block_h, diff --git a/glamor/glamor_program.c b/glamor/glamor_program.c index 322d1983d..dec116c75 100644 --- a/glamor/glamor_program.c +++ b/glamor/glamor_program.c @@ -531,6 +531,7 @@ use_source_picture(CARD8 op, PicturePtr src, PicturePtr dst, glamor_program *pro glamor_set_blend(op, prog->alpha, dst); return glamor_set_texture((PixmapPtr) src->pDrawable, + glamor_picture_red_is_alpha(dst), 0, 0, prog->fill_offset_uniform, prog->fill_size_inv_uniform); @@ -549,7 +550,8 @@ use_source_1x1_picture(CARD8 op, PicturePtr src, PicturePtr dst, glamor_program { glamor_set_blend(op, prog->alpha, dst); - return glamor_set_texture_pixmap((PixmapPtr) src->pDrawable); + return glamor_set_texture_pixmap((PixmapPtr) src->pDrawable, + glamor_picture_red_is_alpha(dst)); } static const glamor_facet glamor_source_1x1_picture = { diff --git a/glamor/glamor_render.c b/glamor/glamor_render.c index a67965e1c..9c5cca67e 100644 --- a/glamor/glamor_render.c +++ b/glamor/glamor_render.c @@ -512,15 +512,24 @@ static void glamor_set_composite_texture(glamor_screen_private *glamor_priv, int unit, PicturePtr picture, PixmapPtr pixmap, - GLuint wh_location, GLuint repeat_location) + GLuint wh_location, GLuint repeat_location, + glamor_pixmap_private *dest_priv) { glamor_pixmap_private *pixmap_priv = glamor_get_pixmap_private(pixmap); + glamor_pixmap_fbo *fbo = pixmap_priv->fbo; float wh[4]; int repeat_type; glamor_make_current(glamor_priv); - glActiveTexture(GL_TEXTURE0 + unit); - glBindTexture(GL_TEXTURE_2D, pixmap_priv->fbo->tex); + + /* The red channel swizzling doesn't depend on whether we're using + * 'fbo' as source or mask as we must have the same answer in case + * the same fbo is being used for both. That means the mask + * channel will sometimes get red bits in the R channel, and + * sometimes get zero bits in the R channel, which is harmless. + */ + glamor_bind_texture(glamor_priv, GL_TEXTURE0 + unit, fbo, + glamor_fbo_red_is_alpha(glamor_priv, dest_priv->fbo)); repeat_type = picture->repeatType; switch (picture->repeatType) { case RepeatNone: @@ -1075,7 +1084,8 @@ glamor_composite_set_shader_blend(glamor_screen_private *glamor_priv, glamor_set_composite_texture(glamor_priv, 0, shader->source, shader->source_pixmap, shader->source_wh, - shader->source_repeat_mode); + shader->source_repeat_mode, + dest_priv); } if (key->mask != SHADER_MASK_NONE) { @@ -1087,7 +1097,8 @@ glamor_composite_set_shader_blend(glamor_screen_private *glamor_priv, glamor_set_composite_texture(glamor_priv, 1, shader->mask, shader->mask_pixmap, shader->mask_wh, - shader->mask_repeat_mode); + shader->mask_repeat_mode, + dest_priv); } } diff --git a/glamor/glamor_spans.c b/glamor/glamor_spans.c index 89a9c5102..5217d0434 100644 --- a/glamor/glamor_spans.c +++ b/glamor/glamor_spans.c @@ -294,8 +294,7 @@ glamor_set_spans_gl(DrawablePtr drawable, GCPtr gc, char *src, BoxPtr box = glamor_pixmap_box_at(pixmap_priv, box_index); glamor_pixmap_fbo *fbo = glamor_pixmap_fbo_at(pixmap_priv, box_index); - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, fbo->tex); + glamor_bind_texture(glamor_priv, GL_TEXTURE0, fbo, TRUE); s = src; for (n = 0; n < numPoints; n++) { diff --git a/glamor/glamor_transfer.c b/glamor/glamor_transfer.c index ed81195b6..d788d06f4 100644 --- a/glamor/glamor_transfer.c +++ b/glamor/glamor_transfer.c @@ -83,8 +83,7 @@ glamor_upload_boxes(PixmapPtr pixmap, BoxPtr in_boxes, int in_nbox, BoxPtr boxes = in_boxes; int nbox = in_nbox; - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, fbo->tex); + glamor_bind_texture(glamor_priv, GL_TEXTURE0, fbo, TRUE); while (nbox--) { diff --git a/glamor/glamor_transform.c b/glamor/glamor_transform.c index fc96fd670..eff500c6d 100644 --- a/glamor/glamor_transform.c +++ b/glamor/glamor_transform.c @@ -158,7 +158,7 @@ glamor_set_solid(PixmapPtr pixmap, } Bool -glamor_set_texture_pixmap(PixmapPtr texture) +glamor_set_texture_pixmap(PixmapPtr texture, Bool destination_red) { glamor_pixmap_private *texture_priv; @@ -170,8 +170,9 @@ glamor_set_texture_pixmap(PixmapPtr texture) if (glamor_pixmap_priv_is_large(texture_priv)) return FALSE; - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, texture_priv->fbo->tex); + glamor_bind_texture(glamor_get_screen_private(texture->drawable.pScreen), + GL_TEXTURE0, + texture_priv->fbo, destination_red); /* we're not setting the sampler uniform here as we always use * GL_TEXTURE0, and the default value for uniforms is zero. So, @@ -182,12 +183,13 @@ glamor_set_texture_pixmap(PixmapPtr texture) Bool glamor_set_texture(PixmapPtr texture, + Bool destination_red, int off_x, int off_y, GLint offset_uniform, GLint size_inv_uniform) { - if (!glamor_set_texture_pixmap(texture)) + if (!glamor_set_texture_pixmap(texture, destination_red)) return FALSE; glUniform2f(offset_uniform, off_x, off_y); @@ -208,6 +210,7 @@ glamor_set_tiled(PixmapPtr pixmap, return FALSE; return glamor_set_texture(gc->tile.pixmap, + TRUE, -gc->patOrg.x, -gc->patOrg.y, offset_uniform, @@ -289,6 +292,7 @@ glamor_set_stippled(PixmapPtr pixmap, return FALSE; return glamor_set_texture(stipple, + FALSE, -gc->patOrg.x, -gc->patOrg.y, offset_uniform, diff --git a/glamor/glamor_transform.h b/glamor/glamor_transform.h index 5a520ebb0..70d2c1671 100644 --- a/glamor/glamor_transform.h +++ b/glamor/glamor_transform.h @@ -48,10 +48,12 @@ glamor_set_color(PixmapPtr pixmap, } Bool -glamor_set_texture_pixmap(PixmapPtr texture); +glamor_set_texture_pixmap(PixmapPtr texture, + Bool destination_red); Bool glamor_set_texture(PixmapPtr texture, + Bool destination_red, int off_x, int off_y, GLint offset_uniform, |