summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/gallium/include/state_tracker/st_api.h5
-rw-r--r--src/gallium/state_trackers/dri/dri_drawable.c4
-rw-r--r--src/gallium/state_trackers/wgl/stw_st.c4
-rw-r--r--src/mesa/state_tracker/st_context.c20
-rw-r--r--src/mesa/state_tracker/st_context.h8
-rw-r--r--src/mesa/state_tracker/st_manager.c59
-rw-r--r--src/mesa/state_tracker/st_manager.h4
7 files changed, 93 insertions, 11 deletions
diff --git a/src/gallium/include/state_tracker/st_api.h b/src/gallium/include/state_tracker/st_api.h
index d641092aa23..3fd5f011f7d 100644
--- a/src/gallium/include/state_tracker/st_api.h
+++ b/src/gallium/include/state_tracker/st_api.h
@@ -311,6 +311,11 @@ struct st_framebuffer_iface
int32_t stamp;
/**
+ * Identifier that uniquely identifies the framebuffer interface object.
+ */
+ uint32_t ID;
+
+ /**
* Available for the state tracker manager to use.
*/
void *st_manager_private;
diff --git a/src/gallium/state_trackers/dri/dri_drawable.c b/src/gallium/state_trackers/dri/dri_drawable.c
index 3c2e3075249..0cfdc305583 100644
--- a/src/gallium/state_trackers/dri/dri_drawable.c
+++ b/src/gallium/state_trackers/dri/dri_drawable.c
@@ -38,6 +38,8 @@
#include "util/u_memory.h"
#include "util/u_inlines.h"
+static uint32_t drifb_ID = 0;
+
static void
swap_fences_unref(struct dri_drawable *draw);
@@ -155,6 +157,7 @@ dri_create_buffer(__DRIscreen * sPriv,
dPriv->driverPrivate = (void *)drawable;
p_atomic_set(&drawable->base.stamp, 1);
+ drawable->base.ID = p_atomic_inc_return(&drifb_ID);
return GL_TRUE;
fail:
@@ -177,6 +180,7 @@ dri_destroy_buffer(__DRIdrawable * dPriv)
swap_fences_unref(drawable);
+ drawable->base.ID = 0;
FREE(drawable);
}
diff --git a/src/gallium/state_trackers/wgl/stw_st.c b/src/gallium/state_trackers/wgl/stw_st.c
index 7806a2a10e3..c2844b04c4e 100644
--- a/src/gallium/state_trackers/wgl/stw_st.c
+++ b/src/gallium/state_trackers/wgl/stw_st.c
@@ -46,7 +46,7 @@ struct stw_st_framebuffer {
unsigned texture_mask;
};
-
+static uint32_t stwfb_ID = 0;
/**
* Is the given mutex held by the calling thread?
@@ -234,6 +234,7 @@ stw_st_create_framebuffer(struct stw_framebuffer *fb)
stwfb->fb = fb;
stwfb->stvis = fb->pfi->stvis;
+ stwfb->base.ID = p_atomic_inc_return(&stwfb_ID);
stwfb->base.visual = &stwfb->stvis;
p_atomic_set(&stwfb->base.stamp, 1);
@@ -255,6 +256,7 @@ stw_st_destroy_framebuffer_locked(struct st_framebuffer_iface *stfb)
for (i = 0; i < ST_ATTACHMENT_COUNT; i++)
pipe_resource_reference(&stwfb->textures[i], NULL);
+ stwfb->base.ID = 0;
FREE(stwfb);
}
diff --git a/src/mesa/state_tracker/st_context.c b/src/mesa/state_tracker/st_context.c
index f5351398474..0b353551da3 100644
--- a/src/mesa/state_tracker/st_context.c
+++ b/src/mesa/state_tracker/st_context.c
@@ -38,6 +38,7 @@
#include "program/prog_cache.h"
#include "vbo/vbo.h"
#include "glapi/glapi.h"
+#include "st_manager.h"
#include "st_context.h"
#include "st_debug.h"
#include "st_cb_bitmap.h"
@@ -571,6 +572,9 @@ struct st_context *st_create_context(gl_api api, struct pipe_context *pipe,
_mesa_destroy_context(ctx);
}
+ /* Initialize context's winsys buffers list */
+ LIST_INITHEAD(&st->winsys_buffers);
+
return st;
}
@@ -591,6 +595,17 @@ destroy_tex_sampler_cb(GLuint id, void *data, void *userData)
void st_destroy_context( struct st_context *st )
{
struct gl_context *ctx = st->ctx;
+ struct st_framebuffer *stfb, *next;
+
+ GET_CURRENT_CONTEXT(curctx);
+ if (curctx == NULL) {
+
+ /* No current context, but we need one to release
+ * renderbuffer surface when we release framebuffer.
+ * So temporarily bind the context.
+ */
+ _mesa_make_current(ctx, NULL, NULL);
+ }
/* This must be called first so that glthread has a chance to finish */
_mesa_glthread_destroy(ctx);
@@ -604,6 +619,11 @@ void st_destroy_context( struct st_context *st )
st_reference_prog(st, &st->tep, NULL);
st_reference_compprog(st, &st->cp, NULL);
+ /* release framebuffer in the winsys buffers list */
+ LIST_FOR_EACH_ENTRY_SAFE_REV(stfb, next, &st->winsys_buffers, head) {
+ st_framebuffer_reference(&stfb, NULL);
+ }
+
pipe_sampler_view_reference(&st->pixel_xfer.pixelmap_sampler_view, NULL);
pipe_resource_reference(&st->pixel_xfer.pixelmap_texture, NULL);
diff --git a/src/mesa/state_tracker/st_context.h b/src/mesa/state_tracker/st_context.h
index af9149ebe41..43c8b0853bf 100644
--- a/src/mesa/state_tracker/st_context.h
+++ b/src/mesa/state_tracker/st_context.h
@@ -33,6 +33,7 @@
#include "main/fbobject.h"
#include "state_tracker/st_atom.h"
#include "util/u_inlines.h"
+#include "util/list.h"
#ifdef __cplusplus
@@ -277,6 +278,9 @@ struct st_context
*/
struct st_bound_handles bound_texture_handles[PIPE_SHADER_TYPES];
struct st_bound_handles bound_image_handles[PIPE_SHADER_TYPES];
+
+ /* Winsys buffers */
+ struct list_head winsys_buffers;
};
@@ -301,6 +305,10 @@ struct st_framebuffer
unsigned num_statts;
int32_t stamp;
int32_t iface_stamp;
+ uint32_t iface_ID;
+
+ /* list of framebuffer objects */
+ struct list_head head;
};
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);
diff --git a/src/mesa/state_tracker/st_manager.h b/src/mesa/state_tracker/st_manager.h
index 65874b00401..68adf2fa1a4 100644
--- a/src/mesa/state_tracker/st_manager.h
+++ b/src/mesa/state_tracker/st_manager.h
@@ -33,6 +33,7 @@
#include "pipe/p_compiler.h"
struct st_context;
+struct st_framebuffer;
void
st_manager_flush_frontbuffer(struct st_context *st);
@@ -44,4 +45,7 @@ boolean
st_manager_add_color_renderbuffer(struct st_context *st, struct gl_framebuffer *fb,
gl_buffer_index idx);
+void
+st_framebuffer_reference(struct st_framebuffer **ptr,
+ struct st_framebuffer *stfb);
#endif /* ST_MANAGER_H */