diff --git a/glamor/glamor_core.c b/glamor/glamor_core.c index 6b10e97ab..a6a603973 100644 --- a/glamor/glamor_core.c +++ b/glamor/glamor_core.c @@ -106,6 +106,19 @@ Bool glamor_prepare_access(DrawablePtr drawable, glamor_access_t access) { PixmapPtr pixmap = glamor_get_drawable_pixmap(drawable); + glamor_pixmap_private *pixmap_priv = glamor_get_pixmap_private(pixmap); + + if (pixmap->devPrivate.ptr) { + /* Already mapped, nothing needs to be done. Note that we + * aren't allowing promotion from RO to RW, because it would + * require re-mapping the PBO. + */ + assert(!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv) || + access == GLAMOR_ACCESS_RO || + pixmap_priv->base.mapped_for_write); + return TRUE; + } + pixmap_priv->base.map_access = access; return glamor_download_pixmap_to_cpu(pixmap, access); } @@ -301,7 +314,15 @@ glamor_finish_access(DrawablePtr drawable, glamor_access_t access_mode) if (!GLAMOR_PIXMAP_PRIV_HAS_FBO_DOWNLOADED(pixmap_priv)) return; - if (access_mode != GLAMOR_ACCESS_RO) { + /* If we are doing a series of unmaps from a nested map, we're + * done. None of the callers do any rendering to maps after + * starting an unmap sequence, so we don't need to delay until the + * last nested unmap. + */ + if (!pixmap->devPrivate.ptr) + return; + + if (pixmap_priv->base.map_access == GLAMOR_ACCESS_RW) { glamor_restore_pixmap_to_texture(pixmap); } diff --git a/glamor/glamor_priv.h b/glamor/glamor_priv.h index 3cc0d2407..776de06ef 100644 --- a/glamor/glamor_priv.h +++ b/glamor/glamor_priv.h @@ -410,6 +410,12 @@ typedef struct glamor_pixmap_clipped_regions { typedef struct glamor_pixmap_private_base { glamor_pixmap_type_t type; enum glamor_fbo_state gl_fbo; + /** + * If devPrivate.ptr is non-NULL (meaning we're within + * glamor_prepare_access), determies whether we should re-upload + * that data on glamor_finish_access(). + */ + glamor_access_t map_access; unsigned char is_picture:1; unsigned char gl_tex:1; glamor_pixmap_fbo *fbo;