diff options
author | Charmaine Lee <[email protected]> | 2017-07-10 23:06:11 -0700 |
---|---|---|
committer | Charmaine Lee <[email protected]> | 2017-07-11 19:40:17 -0700 |
commit | 147d7fb772a7e6b5207c70d02d133af324b0ccf2 (patch) | |
tree | 43bb9284d387bc85119e76a7a385accdeb6aedf1 /src/mesa/state_tracker/st_manager.c | |
parent | 76acbd07fcc62ea3a6ecd499a553e7a99ec77f47 (diff) |
st/mesa: add a winsys buffers list in st_context
Commit a5e733c6b52e93de3000647d075f5ca2f55fcb71 fixes the dangling
framebuffer object by unreferencing the window system draw/read buffers
when context is released. However this can prematurely destroy the
resources associated with these window system buffers. The problem is
reproducible with Turbine Demo running with VMware driver. In this case,
the depth buffer content was lost when the context is rebound to a
drawable.
To prevent premature destroy of the resources associated with
window system buffers, this patch maintains a list of these buffers in
the context, making sure the reference counts of these buffers will not
reach zero until the associated framebuffer interface objects no
longer exist. This also helps to avoid unnecessary destruction and
re-construction of the resources associated with the framebuffer.
Fixes VMware bug 1909807.
Reviewed-by: Brian Paul <[email protected]>
Diffstat (limited to 'src/mesa/state_tracker/st_manager.c')
-rw-r--r-- | src/mesa/state_tracker/st_manager.c | 59 |
1 files changed, 49 insertions, 10 deletions
diff --git a/src/mesa/state_tracker/st_manager.c b/src/mesa/state_tracker/st_manager.c index 085f54efaa6..de16a3a2cf0 100644 --- a/src/mesa/state_tracker/st_manager.c +++ b/src/mesa/state_tracker/st_manager.c @@ -57,6 +57,7 @@ #include "util/u_inlines.h" #include "util/u_atomic.h" #include "util/u_surface.h" +#include "util/list.h" /** @@ -459,6 +460,7 @@ st_framebuffer_create(struct st_context *st, _mesa_initialize_window_framebuffer(&stfb->Base, &mode); stfb->iface = stfbi; + stfb->iface_ID = stfbi->ID; stfb->iface_stamp = p_atomic_read(&stfbi->stamp) - 1; /* add the color buffer */ @@ -480,7 +482,7 @@ st_framebuffer_create(struct st_context *st, /** * Reference a framebuffer. */ -static void +void st_framebuffer_reference(struct st_framebuffer **ptr, struct st_framebuffer *stfb) { @@ -488,6 +490,29 @@ st_framebuffer_reference(struct st_framebuffer **ptr, _mesa_reference_framebuffer((struct gl_framebuffer **) ptr, fb); } +/** + * Purge the winsys buffers list to remove any references to + * non-existing framebuffer interface objects. + */ +static void +st_framebuffers_purge(struct st_context *st) +{ + struct st_framebuffer *stfb, *next; + + LIST_FOR_EACH_ENTRY_SAFE_REV(stfb, next, &st->winsys_buffers, head) { + /** + * If the corresponding framebuffer interface object no longer exists, + * remove the framebuffer object from the context's winsys buffers list, + * and unreference the framebuffer object, so its resources can be + * deleted. + */ + if (stfb->iface->ID != stfb->iface_ID) { + LIST_DEL(&stfb->head); + st_framebuffer_reference(&stfb, NULL); + } + } +} + static void st_context_flush(struct st_context_iface *stctxi, unsigned flags, struct pipe_fence_handle **fence) @@ -761,17 +786,26 @@ st_framebuffer_reuse_or_create(struct st_context *st, struct gl_framebuffer *fb, struct st_framebuffer_iface *stfbi) { - struct st_framebuffer *cur = st_ws_framebuffer(fb), *stfb = NULL; + struct st_framebuffer *cur = NULL, *stfb = NULL; - /* dummy framebuffers cant be used as st_framebuffer */ - if (cur && &cur->Base != _mesa_get_incomplete_framebuffer() && - cur->iface == stfbi) { - /* reuse the current stfb */ - st_framebuffer_reference(&stfb, cur); + /* Check if there is already a framebuffer object for the specified + * framebuffer interface in this context. If there is one, use it. + */ + LIST_FOR_EACH_ENTRY(cur, &st->winsys_buffers, head) { + if (cur->iface_ID == stfbi->ID) { + st_framebuffer_reference(&stfb, cur); + break; + } } - else { - /* create a new one */ - stfb = st_framebuffer_create(st, stfbi); + + /* If there is not already a framebuffer object, create one */ + if (stfb == NULL) { + cur = st_framebuffer_create(st, stfbi); + + /* add to the context's winsys buffers list */ + LIST_ADD(&cur->head, &st->winsys_buffers); + + st_framebuffer_reference(&stfb, cur); } return stfb; @@ -822,6 +856,11 @@ st_api_make_current(struct st_api *stapi, struct st_context_iface *stctxi, st_framebuffer_reference(&stdraw, NULL); st_framebuffer_reference(&stread, NULL); + + /* Purge the context's winsys_buffers list in case any + * of the referenced drawables no longer exist. + */ + st_framebuffers_purge(st); } else { ret = _mesa_make_current(NULL, NULL, NULL); |