From 8a868919b50bdca4dc697d61e220a8fb50764f8e Mon Sep 17 00:00:00 2001 From: Brian Date: Wed, 22 Aug 2007 12:41:59 -0600 Subject: [PATCH] Improved pipe_region/surface_reference() functions Now dereferences the old object first. Target object may be NULL to clear the pointer. --- src/mesa/pipe/p_context.h | 66 +++++++++++++++++++++++++------------- src/mesa/state_tracker/st_cb_fbo.c | 2 +- 2 files changed, 45 insertions(+), 23 deletions(-) diff --git a/src/mesa/pipe/p_context.h b/src/mesa/pipe/p_context.h index 0d90a96..ec99733 100644 --- a/src/mesa/pipe/p_context.h +++ b/src/mesa/pipe/p_context.h @@ -213,38 +213,60 @@ struct pipe_context { }; - +/** + * Set 'ptr' to point to 'region' and update reference counting. + * The old thing pointed to, if any, will be unreferenced first. + * 'region' may be NULL. + */ static INLINE void -pipe_region_reference(struct pipe_region **dst, struct pipe_region *src) +pipe_region_reference(struct pipe_region **ptr, struct pipe_region *region) { - assert(*dst == NULL); - if (src) { - src->refcount++; - *dst = src; + assert(ptr); + if (*ptr) { + /* unreference the old thing */ + struct pipe_region *oldReg = *ptr; + oldReg->refcount--; + assert(oldReg->refcount >= 0); + if (oldReg->refcount == 0) { + /* free the old region */ + assert(oldReg->map_refcount == 0); + /* XXX dereference the region->buffer */ + free(oldReg); + } + *ptr = NULL; + } + if (region) { + /* reference the new thing */ + region->refcount++; + *ptr = region; } } +/** + * \sa pipe_region_reference + */ static INLINE void -pipe_surface_reference(struct pipe_surface **dst, struct pipe_surface *src) +pipe_surface_reference(struct pipe_surface **ptr, struct pipe_surface *surf) { - assert(*dst == NULL); - if (src) { - src->refcount++; - *dst = src; + assert(ptr); + if (*ptr) { + /* unreference the old thing */ + struct pipe_surface *oldSurf = *ptr; + oldSurf->refcount--; + assert(oldSurf->refcount >= 0); + if (oldSurf->refcount == 0) { + /* free the old region */ + pipe_region_reference(&oldSurf->region, NULL); + free(oldSurf); + } + *ptr = NULL; } -} - -static INLINE void -pipe_surface_unreference(struct pipe_surface **ps) -{ - assert(*ps); - (*ps)->refcount--; - if ((*ps)->refcount <= 0) { - /* XXX need a proper surface->free method */ - free(*ps); + if (surf) { + /* reference the new thing */ + surf->refcount++; + *ptr = surf; } - *ps = NULL; } diff --git a/src/mesa/state_tracker/st_cb_fbo.c b/src/mesa/state_tracker/st_cb_fbo.c index 2b9aa3e..430ac71 100644 --- a/src/mesa/state_tracker/st_cb_fbo.c +++ b/src/mesa/state_tracker/st_cb_fbo.c @@ -351,7 +351,7 @@ st_finish_render_texture(GLcontext *ctx, printf("FINISH RENDER TO TEXTURE surf=%p\n", strb->surface); */ - pipe_surface_unreference(&strb->surface); + pipe_surface_reference(&strb->surface, NULL); _mesa_reference_renderbuffer(&att->Renderbuffer, NULL); -- 2.7.4