From 5c4d53c5126bb9f603d04dac6874280b527319f5 Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Wed, 20 Jul 2011 13:06:23 +0800 Subject: [PATCH] glamor: Implement delayed solid filling. When we need to solid fill an entire pixmap with a specific color, we do not need to draw it immediately. We can defer it to the following occasions: 1. The pixmap will be used as source, then we can just use a shader to instead of one copyarea. 2. The pixmap will be used as target, then we can do the filling just before drawing new pixel onto it. The filling and drawing will have the same target texture, we can save one time of fbo context switching. Actually, for the 2nd case, we have opportunity to further optimize it. We can just fill the untouched region. By applying this patch, the cairo-trace for the firefox-planet-gnome's rendering time decrease to 14seconds from 16 seconds. Signed-off-by: Zhigang Gong --- glamor/glamor.c | 5 ++- glamor/glamor_copyarea.c | 69 ++++++++++++++++++++++++++-------------- glamor/glamor_fill.c | 22 ++++++++++--- glamor/glamor_getspans.c | 1 + glamor/glamor_pixmap.c | 68 ++++++++++++++++++++++++++++++++++++--- glamor/glamor_priv.h | 48 ++++++++++++++++++++++++++-- glamor/glamor_putimage.c | 3 +- glamor/glamor_render.c | 48 ++++++++++++++++++---------- glamor/glamor_setspans.c | 3 +- glamor/glamor_tile.c | 56 ++++++++++++++++++-------------- 10 files changed, 246 insertions(+), 77 deletions(-) diff --git a/glamor/glamor.c b/glamor/glamor.c index 2eec6f536..695230885 100644 --- a/glamor/glamor.c +++ b/glamor/glamor.c @@ -98,6 +98,7 @@ glamor_set_screen_pixmap_texture(ScreenPtr screen, int w, int h, unsigned int te glamor_set_pixmap_texture(pixmap, w, h, tex); glamor_priv->screen_fbo = pixmap_priv->fb; + pixmap_priv->pending_op.type = GLAMOR_PENDING_NONE; } @@ -119,7 +120,7 @@ glamor_create_pixmap(ScreenPtr screen, int w, int h, int depth, if (w > 32767 || h > 32767) return NullPixmap; - if (!glamor_check_fbo_width_height(w,h) + if (!glamor_check_fbo_width_height(w,h) || !glamor_check_fbo_depth(depth) || usage == GLAMOR_CREATE_PIXMAP_CPU) { /* MESA can only support upto MAX_WIDTH*MAX_HEIGHT fbo. @@ -201,6 +202,7 @@ glamor_create_screen_pixmap(ScreenPtr screen, int w, int h, int depth, pixmap_priv->gl_fbo = 1; pixmap_priv->gl_tex = 1; pixmap_priv->container = pixmap; + pixmap_priv->pending_op.type = GLAMOR_PENDING_NONE; screen->CreatePixmap = glamor_create_pixmap; return pixmap; @@ -369,6 +371,7 @@ glamor_init(ScreenPtr screen, unsigned int flags) glamor_init_putimage_shaders(screen); glamor_init_finish_access_shaders(screen); glamor_glyphs_init(screen); + glamor_pixmap_init(screen); return TRUE; diff --git a/glamor/glamor_copyarea.c b/glamor/glamor_copyarea.c index 9e2be123e..4cbb3c66b 100644 --- a/glamor/glamor_copyarea.c +++ b/glamor/glamor_copyarea.c @@ -59,6 +59,9 @@ glamor_copy_n_to_n_fbo_blit(DrawablePtr src, src_pixmap_priv = glamor_get_pixmap_private(src_pixmap); + if (src_pixmap_priv->pending_op.type == GLAMOR_PENDING_FILL) + return FALSE; + if (gc) { if (gc->alu != GXcopy) { glamor_delayed_fallback(screen, "non-copy ALU\n"); @@ -78,6 +81,7 @@ glamor_copy_n_to_n_fbo_blit(DrawablePtr src, if (glamor_set_destination_pixmap(dst_pixmap)) { return FALSE; } + glamor_validate_pixmap(dst_pixmap); glBindFramebuffer(GL_READ_FRAMEBUFFER_EXT, src_pixmap_priv->fb); glamor_get_drawable_deltas(dst, dst_pixmap, &dst_x_off, &dst_y_off); @@ -130,6 +134,7 @@ glamor_copy_n_to_n_copypixels(DrawablePtr src, PixmapPtr dst_pixmap = glamor_get_drawable_pixmap(dst); glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); + glamor_pixmap_private *pixmap_priv; int x_off, y_off, i; if (src != dst) { glamor_delayed_fallback(screen, "src != dest\n"); @@ -147,6 +152,9 @@ glamor_copy_n_to_n_copypixels(DrawablePtr src, } } + pixmap_priv = glamor_get_pixmap_private(dst_pixmap); + if (pixmap_priv->pending_op.type == GLAMOR_PENDING_FILL) + return TRUE; if (glamor_set_destination_pixmap(dst_pixmap)) { glamor_delayed_fallback(screen, "dst has no fbo.\n"); return FALSE; @@ -234,37 +242,47 @@ glamor_copy_n_to_n_textured(DrawablePtr src, glamor_set_alu(gc->alu); if (!glamor_set_planemask(dst_pixmap, gc->planemask)) goto fail; + if (gc->alu != GXcopy) { + glamor_set_destination_pixmap_priv_nc(src_pixmap_priv); + glamor_validate_pixmap(src_pixmap); + } + } glamor_set_destination_pixmap_priv_nc(dst_pixmap_priv); + glamor_validate_pixmap(dst_pixmap); + pixmap_priv_get_scale(dst_pixmap_priv, &dst_xscale, &dst_yscale); pixmap_priv_get_scale(src_pixmap_priv, &src_xscale, &src_yscale); glamor_get_drawable_deltas(dst, dst_pixmap, &dst_x_off, &dst_y_off); - glamor_get_drawable_deltas(src, src_pixmap, &src_x_off, &src_y_off); - dx += src_x_off; - dy += src_y_off; - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, src_pixmap_priv->tex); - glEnable(GL_TEXTURE_2D); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glVertexPointer(2, GL_FLOAT, sizeof(float) * 2, vertices); glEnableClientState(GL_VERTEX_ARRAY); - glClientActiveTexture(GL_TEXTURE0); - glTexCoordPointer(2, GL_FLOAT, sizeof(float) * 2, texcoords); - glEnableClientState(GL_TEXTURE_COORD_ARRAY); - - assert(GLEW_ARB_fragment_shader); - glUseProgramObjectARB(glamor_priv->finish_access_prog[0]); - + if (GLAMOR_PIXMAP_PRIV_NO_PENDING(src_pixmap_priv)) { + glamor_get_drawable_deltas(src, src_pixmap, &src_x_off, &src_y_off); + dx += src_x_off; + dy += src_y_off; + pixmap_priv_get_scale(src_pixmap_priv, &src_xscale, &src_yscale); + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, src_pixmap_priv->tex); + glEnable(GL_TEXTURE_2D); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glClientActiveTexture(GL_TEXTURE0); + glTexCoordPointer(2, GL_FLOAT, sizeof(float) * 2, texcoords); + glEnableClientState(GL_TEXTURE_COORD_ARRAY); + glUseProgramObjectARB(glamor_priv->finish_access_prog[0]); + } + else { + GLAMOR_CHECK_PENDING_FILL(glamor_priv, src_pixmap_priv); + } + for (i = 0; i < nbox; i++) { - glamor_set_normalize_vcoords(dst_xscale, dst_yscale, box[i].x1 + dst_x_off, box[i].y1 + dst_y_off, @@ -273,11 +291,12 @@ glamor_copy_n_to_n_textured(DrawablePtr src, glamor_priv->yInverted, vertices); - glamor_set_normalize_tcoords(src_xscale, src_yscale, - box[i].x1 + dx, box[i].y1 + dy, - box[i].x2 + dx, box[i].y2 + dy, - glamor_priv->yInverted, - texcoords); + if (GLAMOR_PIXMAP_PRIV_NO_PENDING(src_pixmap_priv)) + glamor_set_normalize_tcoords(src_xscale, src_yscale, + box[i].x1 + dx, box[i].y1 + dy, + box[i].x2 + dx, box[i].y2 + dy, + glamor_priv->yInverted, + texcoords); glDrawArrays(GL_TRIANGLE_FAN, 0, 4); } @@ -285,8 +304,10 @@ glamor_copy_n_to_n_textured(DrawablePtr src, glUseProgramObjectARB(0); glDisableClientState(GL_VERTEX_ARRAY); - glDisableClientState(GL_TEXTURE_COORD_ARRAY); - glDisable(GL_TEXTURE_2D); + if (GLAMOR_PIXMAP_PRIV_NO_PENDING(src_pixmap_priv)) { + glDisableClientState(GL_TEXTURE_COORD_ARRAY); + glDisable(GL_TEXTURE_2D); + } return TRUE; fail: @@ -352,6 +373,7 @@ glamor_copy_n_to_n(DrawablePtr src, if (!temp_src) goto fail; glamor_transform_boxes(box, nbox, -bound.x1, -bound.y1); + temp_src = &temp_pixmap->drawable; fbCopyNtoN(src, temp_src, gc, box, nbox, temp_dx + bound.x1, temp_dy + bound.y1, reverse, upsidedown, bitplane, @@ -359,7 +381,6 @@ glamor_copy_n_to_n(DrawablePtr src, glamor_transform_boxes(box, nbox, bound.x1, bound.y1); temp_dx = -bound.x1; temp_dy = -bound.y1; - temp_src = &temp_pixmap->drawable; } else { temp_dx = dx; diff --git a/glamor/glamor_fill.c b/glamor/glamor_fill.c index a41837b3a..393f651ed 100644 --- a/glamor/glamor_fill.c +++ b/glamor/glamor_fill.c @@ -154,7 +154,7 @@ glamor_solid(PixmapPtr pixmap, int x, int y, int width, int height, GLfloat xscale, yscale; if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv)) { - glamor_fallback("dest has no fbo.\n"); + glamor_fallback("dest %p has no fbo.\n", pixmap); goto fail; } glamor_set_alu(alu); @@ -163,15 +163,29 @@ glamor_solid(PixmapPtr pixmap, int x, int y, int width, int height, goto fail; } - glamor_set_destination_pixmap_priv_nc(pixmap_priv); - - glUseProgramObjectARB(glamor_priv->solid_prog); glamor_get_rgba_from_pixel(fg_pixel, &color[0], &color[1], &color[2], &color[3], format_for_pixmap(pixmap)); +#ifdef GLAMOR_DELAYED_FILLING + if (x == 0 && y == 0 + && width == pixmap->drawable.width + && height == pixmap->drawable.height + && pixmap_priv->fb != glamor_priv->screen_fbo ) { + pixmap_priv->pending_op.type = GLAMOR_PENDING_FILL; + memcpy(&pixmap_priv->pending_op.fill.color4fv, + color, 4*sizeof(GLfloat)); + pixmap_priv->pending_op.fill.colori = fg_pixel; + return TRUE; + } +#endif + glamor_set_destination_pixmap_priv_nc(pixmap_priv); + glamor_validate_pixmap(pixmap); + + glUseProgramObjectARB(glamor_priv->solid_prog); + glUniform4fvARB(glamor_priv->solid_color_uniform_location, 1, color); glVertexPointer(2, GL_FLOAT, sizeof(float) * 2, vertices); diff --git a/glamor/glamor_getspans.c b/glamor/glamor_getspans.c index 7fe05f993..237c1e789 100644 --- a/glamor/glamor_getspans.c +++ b/glamor/glamor_getspans.c @@ -64,6 +64,7 @@ glamor_get_spans(DrawablePtr drawable, } glamor_set_destination_pixmap_priv_nc(pixmap_priv); + glamor_validate_pixmap(pixmap); glamor_get_drawable_deltas(drawable, pixmap, &x_off, &y_off); for (i = 0; i < count; i++) { diff --git a/glamor/glamor_pixmap.c b/glamor/glamor_pixmap.c index c76920a26..924a17369 100644 --- a/glamor/glamor_pixmap.c +++ b/glamor/glamor_pixmap.c @@ -26,14 +26,71 @@ glamor_get_drawable_deltas(DrawablePtr drawable, PixmapPtr pixmap, *y = 0; } + +static void +_glamor_pixmap_validate_filling(glamor_screen_private *glamor_priv, + glamor_pixmap_private *pixmap_priv) +{ + GLfloat vertices[8]; +// glamor_set_destination_pixmap_priv_nc(pixmap_priv); + glVertexPointer(2, GL_FLOAT, sizeof(float) * 2, vertices); + glEnableClientState(GL_VERTEX_ARRAY); + glUseProgramObjectARB(glamor_priv->solid_prog); + glUniform4fvARB(glamor_priv->solid_color_uniform_location, + 1, pixmap_priv->pending_op.fill.color4fv); + vertices[0] = -1; + vertices[1] = -1; + vertices[2] = 1; + vertices[3] = -1; + vertices[4] = 1; + vertices[5] = 1; + vertices[6] = -1; + vertices[7] = 1; + glDrawArrays(GL_QUADS, 0, 4); + glDisableClientState(GL_VERTEX_ARRAY); + glUseProgramObjectARB(0); + pixmap_priv->pending_op.type = GLAMOR_PENDING_NONE; +} + + +glamor_pixmap_validate_function_t pixmap_validate_funcs[] = { + NULL, + _glamor_pixmap_validate_filling +}; + +void +glamor_pixmap_init(ScreenPtr screen) +{ + glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); + glamor_priv->pixmap_validate_funcs = pixmap_validate_funcs; +} + +void +glamor_validate_pixmap(PixmapPtr pixmap) +{ + glamor_pixmap_validate_function_t validate_op; + glamor_screen_private *glamor_priv = + glamor_get_screen_private(pixmap->drawable.pScreen); + glamor_pixmap_private *pixmap_priv = + glamor_get_pixmap_private(pixmap); + + validate_op = glamor_priv->pixmap_validate_funcs[pixmap_priv->pending_op.type]; + if (validate_op) { + (*validate_op)(glamor_priv, pixmap_priv); + } +} + void glamor_set_destination_pixmap_priv_nc(glamor_pixmap_private *pixmap_priv) { glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, pixmap_priv->fb); + glMatrixMode(GL_PROJECTION); glLoadIdentity(); + glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glViewport(0, 0, pixmap_priv->container->drawable.width, pixmap_priv->container->drawable.height); + } int @@ -49,9 +106,11 @@ glamor_set_destination_pixmap_priv(glamor_pixmap_private *pixmap_priv) int glamor_set_destination_pixmap(PixmapPtr pixmap) { + int err; glamor_pixmap_private *pixmap_priv = glamor_get_pixmap_private(pixmap); - return glamor_set_destination_pixmap_priv(pixmap_priv); + err = glamor_set_destination_pixmap_priv(pixmap_priv); + return err; } Bool @@ -376,7 +435,8 @@ glamor_download_pixmap_to_cpu(PixmapPtr pixmap, glamor_access_t access) if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv)) return TRUE; - + /* XXX we may don't need to validate it on GPU here, + * we can just validate it on CPU. */ if (glamor_get_tex_format_type_from_pixmap(pixmap, &format, &type, @@ -395,7 +455,8 @@ glamor_download_pixmap_to_cpu(PixmapPtr pixmap, glamor_access_t access) pixmap->drawable.depth); stride = pixmap->devKind; - + glamor_set_destination_pixmap_priv_nc(pixmap_priv); + glamor_validate_pixmap(pixmap); switch (access) { case GLAMOR_ACCESS_RO: gl_access = GL_READ_ONLY_ARB; @@ -415,7 +476,6 @@ glamor_download_pixmap_to_cpu(PixmapPtr pixmap, glamor_access_t access) } row_length = (stride * 8) / pixmap->drawable.bitsPerPixel; - glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, pixmap_priv->fb); glPixelStorei(GL_PACK_ALIGNMENT, 1); glPixelStorei(GL_PACK_ROW_LENGTH, row_length); diff --git a/glamor/glamor_priv.h b/glamor/glamor_priv.h index 4b0037333..b7fcfbdeb 100644 --- a/glamor/glamor_priv.h +++ b/glamor/glamor_priv.h @@ -149,6 +149,10 @@ enum shader_in { SHADER_IN_COUNT, }; +struct glamor_screen_private; +struct glamor_pixmap_private; +typedef void (*glamor_pixmap_validate_function_t)(struct glamor_screen_private*, + struct glamor_pixmap_private*); #define GLAMOR_CREATE_PIXMAP_CPU 0x100 typedef struct glamor_screen_private { CloseScreenProcPtr saved_close_screen; @@ -197,7 +201,7 @@ typedef struct glamor_screen_private { [SHADER_IN_COUNT]; Bool has_source_coords, has_mask_coords; int render_nr_verts; - + glamor_pixmap_validate_function_t *pixmap_validate_funcs; glamor_glyph_cache_t glyph_caches[GLAMOR_NUM_GLYPH_CACHES]; char delayed_fallback_string[GLAMOR_DELAYED_STRING_MAX + 1]; int delayed_fallback_pending; @@ -220,9 +224,34 @@ typedef enum glamor_access { * @pbo: attached pbo. * @access_mode: access mode during the prepare/finish pair. * @pict_format: the corresponding picture's format. + * #pending_op: currently only support pending filling. * @container: The corresponding pixmap's pointer. **/ +#define GLAMOR_PIXMAP_PRIV_NEED_VALIDATE(pixmap_priv) \ + (GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv) \ + && (pixmap_priv->pending_op.type != GLAMOR_PENDING_NONE)) + +#define GLAMOR_PIXMAP_PRIV_NO_PENDING(pixmap_priv) \ + (pixmap_priv->pending_op.type == GLAMOR_PENDING_NONE) + +enum _glamor_pending_op_type{ + GLAMOR_PENDING_NONE, + GLAMOR_PENDING_FILL +}; + +typedef struct _glamor_pending_fill { + unsigned int type; + GLfloat color4fv[4]; + CARD32 colori; +} glamor_pending_fill; + +typedef union _glamor_pending_op { + unsigned int type; + glamor_pending_fill fill; +} glamor_pending_op; + + typedef struct glamor_pixmap_private { unsigned char gl_fbo:1; unsigned char gl_tex:1; @@ -233,9 +262,20 @@ typedef struct glamor_pixmap_private { GLuint pbo; glamor_access_t access_mode; PictFormatShort pict_format; + glamor_pending_op pending_op; PixmapPtr container; } glamor_pixmap_private; +#define GLAMOR_CHECK_PENDING_FILL(_glamor_priv_, _pixmap_priv_) do \ + { \ + if (_pixmap_priv_->pending_op.type == GLAMOR_PENDING_FILL) { \ + glUseProgramObjectARB(_glamor_priv_->solid_prog); \ + glUniform4fvARB(_glamor_priv_->solid_color_uniform_location, 1, \ + _pixmap_priv_->pending_op.fill.color4fv); \ + } \ + } while(0) + + /* * Pixmap dynamic status, used by dynamic upload feature. * @@ -678,6 +718,8 @@ glamor_triangles (CARD8 op, /* glamor_pixmap.c */ +void +glamor_pixmap_init(ScreenPtr screen); /** * Download a pixmap's texture to cpu memory. If success, * One copy of current pixmap's texture will be put into @@ -724,7 +766,8 @@ glamor_upload_picture_to_texture(PicturePtr picture); void glamor_destroy_upload_pixmap(PixmapPtr pixmap); - +void +glamor_validate_pixmap(PixmapPtr pixmap); int glamor_create_picture(PicturePtr picture); @@ -753,6 +796,7 @@ glamor_picture_format_fixup(PicturePtr picture, glamor_pixmap_private *pixmap_pr #define GLAMOR_PIXMAP_DYNAMIC_UPLOAD +#define GLAMOR_DELAYED_FILLING #include"glamor_utils.h" diff --git a/glamor/glamor_putimage.c b/glamor/glamor_putimage.c index e61425d11..0a910509c 100644 --- a/glamor/glamor_putimage.c +++ b/glamor/glamor_putimage.c @@ -296,6 +296,8 @@ glamor_put_image(DrawablePtr drawable, GCPtr gc, int depth, int x, int y, } /* XXX consider to reuse a function to do the following work. */ + glamor_set_destination_pixmap_priv_nc(pixmap_priv); + glamor_validate_pixmap(pixmap); glVertexPointer(2, GL_FLOAT, sizeof(float) * 2, vertices); glEnableClientState(GL_VERTEX_ARRAY); @@ -303,7 +305,6 @@ glamor_put_image(DrawablePtr drawable, GCPtr gc, int depth, int x, int y, glTexCoordPointer(2, GL_FLOAT, sizeof(float) * 2, texcoords); glEnableClientState(GL_TEXTURE_COORD_ARRAY); - glamor_set_destination_pixmap_priv_nc(pixmap_priv); glPixelStorei(GL_UNPACK_ALIGNMENT, 1); glPixelStorei(GL_UNPACK_ROW_LENGTH, src_stride * 8 / diff --git a/glamor/glamor_render.c b/glamor/glamor_render.c index 41ee46b7d..f0a6e880c 100644 --- a/glamor/glamor_render.c +++ b/glamor/glamor_render.c @@ -395,16 +395,8 @@ glamor_set_composite_texture(ScreenPtr screen, int unit, PicturePtr picture, } static void -glamor_set_composite_solid(PicturePtr picture, GLint uniform_location) +glamor_set_composite_solid(float *color, GLint uniform_location) { - CARD32 c = picture->pSourcePict->solidFill.color; /* a8r8g8b8 */ - float color[4]; /* rgba */ - - color[0] = ((c >> 16) & 0xff) / 255.0; - color[1] = ((c >> 8) & 0xff) / 255.0; - color[2] = ((c >> 0) & 0xff) / 255.0; - color[3] = ((c >> 24) & 0xff) / 255.0; - glUniform4fvARB(uniform_location, 1, color); } @@ -696,6 +688,7 @@ glamor_composite_with_shader(CARD8 op, enum glamor_pixmap_status mask_status = GLAMOR_NONE; PictFormatShort saved_source_format = 0; float src_matrix[9], mask_matrix[9]; + GLfloat source_solid_color[4], mask_solid_color[4]; dest_pixmap_priv = glamor_get_pixmap_private(dest_pixmap); @@ -707,6 +700,12 @@ glamor_composite_with_shader(CARD8 op, if (!source->pDrawable) { if (source->pSourcePict->type == SourcePictTypeSolidFill) { key.source = SHADER_SOURCE_SOLID; + glamor_get_rgba_from_pixel(source->pSourcePict->solidFill.color, + &source_solid_color[0], + &source_solid_color[1], + &source_solid_color[2], + &source_solid_color[3], + PICT_a8r8g8b8); } else { glamor_fallback("gradient source\n"); goto fail; @@ -718,6 +717,12 @@ glamor_composite_with_shader(CARD8 op, if (!mask->pDrawable) { if (mask->pSourcePict->type == SourcePictTypeSolidFill) { key.mask = SHADER_MASK_SOLID; + glamor_get_rgba_from_pixel(mask->pSourcePict->solidFill.color, + &mask_solid_color[0], + &mask_solid_color[1], + &mask_solid_color[2], + &mask_solid_color[3], + PICT_a8r8g8b8); } else { glamor_fallback("gradient mask\n"); goto fail; @@ -767,6 +772,10 @@ glamor_composite_with_shader(CARD8 op, glamor_fallback("no texture in source\n"); goto fail; #endif + } + else if (source_pixmap_priv->pending_op.type == GLAMOR_PENDING_FILL) { + key.source = SHADER_SOURCE_SOLID; + memcpy(source_solid_color, source_pixmap_priv->pending_op.fill.color4fv, 4 * sizeof(float)); } } if (key.mask == SHADER_MASK_TEXTURE || @@ -785,6 +794,10 @@ glamor_composite_with_shader(CARD8 op, goto fail; #endif } + else if (mask_pixmap_priv->pending_op.type == GLAMOR_PENDING_FILL) { + key.mask = SHADER_MASK_SOLID; + memcpy(mask_solid_color, mask_pixmap_priv->pending_op.fill.color4fv, 4 * sizeof(float)); + } } #ifdef GLAMOR_PIXMAP_DYNAMIC_UPLOAD if (source_status == GLAMOR_UPLOAD_PENDING @@ -853,10 +866,11 @@ glamor_composite_with_shader(CARD8 op, } } #endif + glamor_set_destination_pixmap_priv_nc(dest_pixmap_priv); + glamor_validate_pixmap(dest_pixmap); if (!glamor_set_composite_op(screen, op, dest, mask)) { goto fail; } - glamor_set_destination_pixmap_priv_nc(dest_pixmap_priv); shader = glamor_lookup_composite_shader(screen, &key); if (shader->prog == 0) { @@ -866,13 +880,13 @@ glamor_composite_with_shader(CARD8 op, glUseProgramObjectARB(shader->prog); if (key.source == SHADER_SOURCE_SOLID) { - glamor_set_composite_solid(source, shader->source_uniform_location); + glamor_set_composite_solid(source_solid_color, shader->source_uniform_location); } else { glamor_set_composite_texture(screen, 0, source, source_pixmap_priv); } if (key.mask != SHADER_MASK_NONE) { if (key.mask == SHADER_MASK_SOLID) { - glamor_set_composite_solid(mask, shader->mask_uniform_location); + glamor_set_composite_solid(mask_solid_color, shader->mask_uniform_location); } else { glamor_set_composite_texture(screen, 1, mask, mask_pixmap_priv); } @@ -888,14 +902,14 @@ glamor_composite_with_shader(CARD8 op, - if (source_pixmap) { + if (glamor_priv->has_source_coords) { glamor_get_drawable_deltas(source->pDrawable, source_pixmap, &source_x_off, &source_y_off); pixmap_priv_get_scale(source_pixmap_priv, &src_xscale, &src_yscale); glamor_picture_get_matrixf(source, src_matrix); } - if (mask_pixmap) { + if (glamor_priv->has_mask_coords) { glamor_get_drawable_deltas(mask->pDrawable, mask_pixmap, &mask_x_off, &mask_y_off); pixmap_priv_get_scale(mask_pixmap_priv, &mask_xscale, &mask_yscale); @@ -944,14 +958,14 @@ glamor_composite_with_shader(CARD8 op, y_source += source_y_off; x_mask += mask_x_off; y_mask += mask_y_off; - + box = REGION_RECTS(®ion); for (i = 0; i < REGION_NUM_RECTS(®ion); i++) { int vx1 = box[i].x1 + dest_x_off; int vx2 = box[i].x2 + dest_x_off; int vy1 = box[i].y1 + dest_y_off; int vy2 = box[i].y2 + dest_y_off; - glamor_set_normalize_vcoords(dst_xscale, dst_yscale, vx1, vy1, vx2, vy2, + glamor_set_normalize_vcoords(dst_xscale, dst_yscale, vx1, vy1, vx2, vy2, glamor_priv->yInverted, vertices); if (key.source != SHADER_SOURCE_SOLID) { @@ -1260,7 +1274,7 @@ glamor_create_mask_picture(ScreenPtr screen, pixmap = screen->CreatePixmap(screen, 0, 0, pict_format->depth, - 0); + GLAMOR_CREATE_PIXMAP_CPU); if (!pixmap) return 0; picture = CreatePicture(0, &pixmap->drawable, pict_format, diff --git a/glamor/glamor_setspans.c b/glamor/glamor_setspans.c index 9bc7d1567..14a24378f 100644 --- a/glamor/glamor_setspans.c +++ b/glamor/glamor_setspans.c @@ -52,9 +52,10 @@ glamor_set_spans(DrawablePtr drawable, GCPtr gc, char *src, drawable->depth); goto fail; } - if (glamor_set_destination_pixmap(dest_pixmap)) goto fail; + + glamor_validate_pixmap(dest_pixmap); if (!glamor_set_planemask(dest_pixmap, gc->planemask)) goto fail; glamor_set_alu(gc->alu); diff --git a/glamor/glamor_tile.c b/glamor/glamor_tile.c index 5bfdd7341..a78c30194 100644 --- a/glamor/glamor_tile.c +++ b/glamor/glamor_tile.c @@ -107,7 +107,6 @@ glamor_tile(PixmapPtr pixmap, PixmapPtr tile, glamor_fallback("dest has no fbo.\n"); goto fail; } - if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(src_pixmap_priv)) { /* XXX dynamic uploading candidate. */ glamor_fallback("Non-texture tile pixmap\n"); @@ -118,48 +117,59 @@ glamor_tile(PixmapPtr pixmap, PixmapPtr tile, glamor_fallback("unsupported planemask %lx\n", planemask); goto fail; } - + if (alu != GXcopy) { + glamor_set_destination_pixmap_priv_nc(src_pixmap_priv); + glamor_validate_pixmap(tile); + } + glamor_set_destination_pixmap_priv_nc(dst_pixmap_priv); + glamor_validate_pixmap(pixmap); pixmap_priv_get_scale(dst_pixmap_priv, &dst_xscale, &dst_yscale); - pixmap_priv_get_scale(src_pixmap_priv, &src_xscale, &src_yscale); glamor_set_alu(alu); - glUseProgramObjectARB(glamor_priv->tile_prog); - - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, src_pixmap_priv->tex); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); - glEnable(GL_TEXTURE_2D); + if (GLAMOR_PIXMAP_PRIV_NO_PENDING(src_pixmap_priv)) { + pixmap_priv_get_scale(src_pixmap_priv, &src_xscale, &src_yscale); + glUseProgramObjectARB(glamor_priv->tile_prog); + + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, src_pixmap_priv->tex); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); + glEnable(GL_TEXTURE_2D); + glamor_set_normalize_tcoords(src_xscale, src_yscale, + tile_x1, tile_y1, + tile_x2, tile_y2, + glamor_priv->yInverted, + source_texcoords); + glClientActiveTexture(GL_TEXTURE0); + glTexCoordPointer(2, GL_FLOAT, sizeof(float) * 2, source_texcoords); + glEnableClientState(GL_TEXTURE_COORD_ARRAY); + } + else { + GLAMOR_CHECK_PENDING_FILL(glamor_priv, src_pixmap_priv); + } + glamor_set_normalize_vcoords(dst_xscale, dst_yscale, x1, y1,x2, y2, glamor_priv->yInverted, vertices); - glamor_set_normalize_tcoords(src_xscale, src_yscale, - tile_x1, tile_y1, - tile_x2, tile_y2, - glamor_priv->yInverted, - source_texcoords); - glVertexPointer(2, GL_FLOAT, sizeof(float) * 2, vertices); glEnableClientState(GL_VERTEX_ARRAY); - glClientActiveTexture(GL_TEXTURE0); - glTexCoordPointer(2, GL_FLOAT, sizeof(float) * 2, source_texcoords); - glEnableClientState(GL_TEXTURE_COORD_ARRAY); - glDrawArrays(GL_TRIANGLE_FAN, 0, 4); + if (GLAMOR_PIXMAP_PRIV_NO_PENDING(src_pixmap_priv)) { glClientActiveTexture(GL_TEXTURE0); glDisableClientState(GL_TEXTURE_COORD_ARRAY); + glDisable(GL_TEXTURE_2D); + } glDisableClientState(GL_VERTEX_ARRAY); glUseProgramObjectARB(0); - glDisable(GL_TEXTURE_2D); glamor_set_alu(GXcopy); glamor_set_planemask(pixmap, ~0); return TRUE;