#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"
_mesa_destroy_context(ctx);
}
+ /* Initialize context's winsys buffers list */
+ LIST_INITHEAD(&st->winsys_buffers);
+
return st;
}
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);
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);
#include "util/u_inlines.h"
#include "util/u_atomic.h"
#include "util/u_surface.h"
+#include "util/list.h"
/**
_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 */
/**
* Reference a framebuffer.
*/
-static void
+void
st_framebuffer_reference(struct st_framebuffer **ptr,
struct st_framebuffer *stfb)
{
_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)
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;
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);