st/mesa: fix the texture format in st_context_teximage
[mesa.git] / src / mesa / state_tracker / st_manager.c
index 0307b48978b14e1c10a52b90bd3f4685a2061888..d5228d387f7471e7a0910254cc125ac6fca441ca 100644 (file)
@@ -38,6 +38,7 @@
 
 #include "main/mtypes.h"
 #include "main/context.h"
+#include "main/mfeatures.h"
 #include "main/texobj.h"
 #include "main/teximage.h"
 #include "main/texstate.h"
@@ -137,24 +138,65 @@ buffer_index_to_attachment(gl_buffer_index index)
    return statt;
 }
 
+/**
+ * Make sure a context picks up the latest cached state of the
+ * drawables it binds to.
+ */
+static void
+st_context_validate(struct st_context *st,
+                    struct st_framebuffer *stdraw,
+                    struct st_framebuffer *stread)
+{
+    if (stdraw && stdraw->stamp != st->draw_stamp) {
+       st->dirty.st |= ST_NEW_FRAMEBUFFER;
+       _mesa_resize_framebuffer(st->ctx, &stdraw->Base,
+                                stdraw->Base.Width,
+                                stdraw->Base.Height);
+       st->draw_stamp = stdraw->stamp;
+    }
+
+    if (stread && stread->stamp != st->read_stamp) {
+       if (stread != stdraw) {
+          st->dirty.st |= ST_NEW_FRAMEBUFFER;
+          _mesa_resize_framebuffer(st->ctx, &stread->Base,
+                                   stread->Base.Width,
+                                   stread->Base.Height);
+       }
+       st->read_stamp = stread->stamp;
+    }
+}
+
 /**
  * Validate a framebuffer to make sure up-to-date pipe_textures are used.
+ * The context we need to pass in is s dummy context needed only to be
+ * able to get a pipe context to create pipe surfaces, and to have a
+ * context to call _mesa_resize_framebuffer():
+ * (That should probably be rethought, since those surfaces become
+ * drawable state, not context state, and can be freed by another pipe
+ * context).
  */
 static void
-st_framebuffer_validate(struct st_framebuffer *stfb, struct st_context *st)
+st_framebuffer_validate(struct st_framebuffer *stfb,
+                        struct st_context *st)
 {
-   struct pipe_context *pipe = st->pipe;
    struct pipe_resource *textures[ST_ATTACHMENT_COUNT];
    uint width, height;
    unsigned i;
    boolean changed = FALSE;
+   int32_t new_stamp = p_atomic_read(&stfb->iface->stamp);
 
-   if (!p_atomic_read(&stfb->revalidate))
+   if (stfb->iface_stamp == new_stamp)
       return;
 
    /* validate the fb */
-   if (!stfb->iface->validate(stfb->iface, stfb->statts, stfb->num_statts, textures))
-      return;
+   do {
+      if (!stfb->iface->validate(stfb->iface, stfb->statts,
+                                stfb->num_statts, textures))
+        return;
+
+      stfb->iface_stamp = new_stamp;
+      new_stamp = p_atomic_read(&stfb->iface->stamp);
+   } while(stfb->iface_stamp != new_stamp);
 
    width = stfb->Base.Width;
    height = stfb->Base.Height;
@@ -183,7 +225,7 @@ st_framebuffer_validate(struct st_framebuffer *stfb, struct st_context *st)
       memset(&surf_tmpl, 0, sizeof(surf_tmpl));
       u_surface_default_template(&surf_tmpl, textures[i],
                                  PIPE_BIND_RENDER_TARGET);
-      ps = pipe->create_surface(pipe, textures[i], &surf_tmpl);
+      ps = st->pipe->create_surface(st->pipe, textures[i], &surf_tmpl);
       if (ps) {
          pipe_surface_reference(&strb->surface, ps);
          pipe_resource_reference(&strb->texture, ps->texture);
@@ -203,14 +245,9 @@ st_framebuffer_validate(struct st_framebuffer *stfb, struct st_context *st)
    }
 
    if (changed) {
-      st->dirty.st |= ST_NEW_FRAMEBUFFER;
+      ++stfb->stamp;
       _mesa_resize_framebuffer(st->ctx, &stfb->Base, width, height);
-
-      assert(stfb->Base.Width == width);
-      assert(stfb->Base.Height == height);
    }
-
-   p_atomic_set(&stfb->revalidate, FALSE);
 }
 
 /**
@@ -235,8 +272,7 @@ st_framebuffer_update_attachments(struct st_framebuffer *stfb)
           st_visual_have_buffers(stfb->iface->visual, 1 << statt))
          stfb->statts[stfb->num_statts++] = statt;
    }
-
-   p_atomic_set(&stfb->revalidate, TRUE);
+   stfb->stamp++;
 }
 
 /**
@@ -425,19 +461,13 @@ st_framebuffer_create(struct st_framebuffer_iface *stfbi)
    struct gl_config mode;
    gl_buffer_index idx;
 
+   if (!stfbi)
+      return NULL;
+
    stfb = CALLOC_STRUCT(st_framebuffer);
    if (!stfb)
       return NULL;
 
-   /* for FBO-only context */
-   if (!stfbi) {
-      struct gl_framebuffer *base = _mesa_get_incomplete_framebuffer();
-
-      stfb->Base = *base;
-
-      return stfb;
-   }
-
    st_visual_to_context_mode(stfbi->visual, &mode);
    _mesa_initialize_window_framebuffer(&stfb->Base, &mode);
 
@@ -448,6 +478,7 @@ st_framebuffer_create(struct st_framebuffer_iface *stfbi)
          &stfb->Base._ColorReadBufferIndex);
 
    stfb->iface = stfbi;
+   stfb->iface_stamp = p_atomic_read(&stfbi->stamp) - 1;
 
    /* add the color buffer */
    idx = stfb->Base._ColorDrawBufferIndexes[0];
@@ -459,6 +490,7 @@ st_framebuffer_create(struct st_framebuffer_iface *stfbi)
    st_framebuffer_add_renderbuffer(stfb, BUFFER_DEPTH);
    st_framebuffer_add_renderbuffer(stfb, BUFFER_ACCUM);
 
+   stfb->stamp = 0;
    st_framebuffer_update_attachments(stfb);
 
    stfb->Base.Initialized = GL_TRUE;
@@ -477,43 +509,19 @@ st_framebuffer_reference(struct st_framebuffer **ptr,
    _mesa_reference_framebuffer((struct gl_framebuffer **) ptr, fb);
 }
 
-static void
-st_context_notify_invalid_framebuffer(struct st_context_iface *stctxi,
-                                      struct st_framebuffer_iface *stfbi)
-{
-   struct st_context *st = (struct st_context *) stctxi;
-   struct st_framebuffer *stfb;
-
-   /* either draw or read winsys fb */
-   stfb = st_ws_framebuffer(st->ctx->WinSysDrawBuffer);
-   if (!stfb || stfb->iface != stfbi)
-      stfb = st_ws_framebuffer(st->ctx->WinSysReadBuffer);
-
-   if (stfb && stfb->iface == stfbi) {
-      p_atomic_set(&stfb->revalidate, TRUE);
-   }
-   else {
-      /* This function is probably getting called when we've detected a
-       * change in a window's size but the currently bound context is
-       * not bound to that window.
-       * If the st_framebuffer_iface structure had a pointer to the
-       * corresponding st_framebuffer we'd be able to handle this.
-       */
-   }
-}
-
 static void
 st_context_flush(struct st_context_iface *stctxi, unsigned flags,
                  struct pipe_fence_handle **fence)
 {
    struct st_context *st = (struct st_context *) stctxi;
-   st_flush(st, flags, fence);
-   if (flags & PIPE_FLUSH_RENDER_CACHE)
+   st_flush(st, fence);
+   if (flags & ST_FLUSH_FRONT)
       st_manager_flush_frontbuffer(st);
 }
 
 static boolean
-st_context_teximage(struct st_context_iface *stctxi, enum st_texture_type target,
+st_context_teximage(struct st_context_iface *stctxi,
+                    enum st_texture_type target,
                     int level, enum pipe_format internal_format,
                     struct pipe_resource *tex, boolean mipmap)
 {
@@ -579,7 +587,7 @@ st_context_teximage(struct st_context_iface *stctxi, enum st_texture_type target
          internalFormat = GL_RGB;
 
       texFormat = st_ChooseTextureFormat(ctx, internalFormat,
-                                         GL_RGBA, GL_UNSIGNED_BYTE);
+                                         GL_BGRA, GL_UNSIGNED_BYTE);
 
       _mesa_init_teximage_fields(ctx, target, texImage,
                                  tex->width0, tex->height0, 1, 0,
@@ -688,8 +696,9 @@ st_api_create_context(struct st_api *stapi, struct st_manager *smapi,
    if (attribs->major > 1 || attribs->minor > 0) {
       _mesa_compute_version(st->ctx);
 
-      if (st->ctx->VersionMajor < attribs->major ||
-          st->ctx->VersionMajor < attribs->minor) {
+      /* is the actual version less than the requested version? */
+      if (st->ctx->VersionMajor * 10 + st->ctx->VersionMinor <
+          attribs->major * 10 + attribs->minor) {
          st_destroy_context(st);
          return NULL;
       }
@@ -699,8 +708,6 @@ st_api_create_context(struct st_api *stapi, struct st_manager *smapi,
       smapi->get_param(smapi, ST_MANAGER_BROKEN_INVALIDATE);
 
    st->iface.destroy = st_context_destroy;
-   st->iface.notify_invalid_framebuffer =
-      st_context_notify_invalid_framebuffer;
    st->iface.flush = st_context_flush;
    st->iface.teximage = st_context_teximage;
    st->iface.copy = st_context_copy;
@@ -710,38 +717,58 @@ st_api_create_context(struct st_api *stapi, struct st_manager *smapi,
    return &st->iface;
 }
 
+static struct st_context_iface *
+st_api_get_current(struct st_api *stapi)
+{
+   GET_CURRENT_CONTEXT(ctx);
+   struct st_context *st = (ctx) ? ctx->st : NULL;
+
+   return (st) ? &st->iface : NULL;
+}
+
+static struct st_framebuffer *
+st_framebuffer_reuse_or_create(struct gl_framebuffer *fb,
+                               struct st_framebuffer_iface *stfbi)
+{
+   struct st_framebuffer *cur = st_ws_framebuffer(fb), *stfb = NULL;
+
+   if (cur && cur->iface == stfbi) {
+      /* reuse the current stfb */
+      st_framebuffer_reference(&stfb, cur);
+   }
+   else {
+      /* create a new one */
+      stfb = st_framebuffer_create(stfbi);
+   }
+
+   return stfb;
+}
+
 static boolean
 st_api_make_current(struct st_api *stapi, struct st_context_iface *stctxi,
                     struct st_framebuffer_iface *stdrawi,
                     struct st_framebuffer_iface *streadi)
 {
    struct st_context *st = (struct st_context *) stctxi;
-   struct st_framebuffer *stdraw, *stread, *stfb;
+   struct st_framebuffer *stdraw, *stread;
    boolean ret;
 
    _glapi_check_multithread();
 
    if (st) {
-      /* reuse/create the draw fb */
-      stfb = st_ws_framebuffer(st->ctx->WinSysDrawBuffer);
-      if (stfb && stfb->iface == stdrawi) {
-         stdraw = NULL;
-         st_framebuffer_reference(&stdraw, stfb);
+      /* reuse or create the draw fb */
+      stdraw = st_framebuffer_reuse_or_create(st->ctx->WinSysDrawBuffer,
+                                              stdrawi);
+      if (streadi != stdrawi) {
+         /* do the same for the read fb */
+         stread = st_framebuffer_reuse_or_create(st->ctx->WinSysReadBuffer,
+                                                 streadi);
       }
       else {
-         stdraw = st_framebuffer_create(stdrawi);
-      }
-
-      /* reuse/create the read fb */
-      stfb = st_ws_framebuffer(st->ctx->WinSysReadBuffer);
-      if (!stfb || stfb->iface != streadi)
-         stfb = stdraw;
-      if (stfb && stfb->iface == streadi) {
          stread = NULL;
-         st_framebuffer_reference(&stread, stfb);
-      }
-      else {
-         stread = st_framebuffer_create(streadi);
+         /* reuse the draw fb for the read fb */
+         if (stdraw)
+            st_framebuffer_reference(&stread, stdraw);
       }
 
       if (stdraw && stread) {
@@ -760,9 +787,14 @@ st_api_make_current(struct st_api *stapi, struct st_context_iface *stctxi,
          }
 
          ret = _mesa_make_current(st->ctx, &stdraw->Base, &stread->Base);
+
+         st->draw_stamp = stdraw->stamp - 1;
+         st->read_stamp = stread->stamp - 1;
+         st_context_validate(st, stdraw, stread);
       }
       else {
-         ret = FALSE;
+         struct gl_framebuffer *incomplete = _mesa_get_incomplete_framebuffer();
+         ret = _mesa_make_current(st->ctx, incomplete, incomplete);
       }
 
       st_framebuffer_reference(&stdraw, NULL);
@@ -775,15 +807,6 @@ st_api_make_current(struct st_api *stapi, struct st_context_iface *stctxi,
    return ret;
 }
 
-static struct st_context_iface *
-st_api_get_current(struct st_api *stapi)
-{
-   GET_CURRENT_CONTEXT(ctx);
-   struct st_context *st = (ctx) ? ctx->st : NULL;
-
-   return (st) ? &st->iface : NULL;
-}
-
 static st_proc_t
 st_api_get_proc_address(struct st_api *stapi, const char *procname)
 {
@@ -859,13 +882,16 @@ st_manager_validate_framebuffers(struct st_context *st)
       st_framebuffer_validate(stdraw, st);
    if (stread && stread != stdraw)
       st_framebuffer_validate(stread, st);
+
+   st_context_validate(st, stdraw, stread);
 }
 
 /**
  * Add a color renderbuffer on demand.
  */
 boolean
-st_manager_add_color_renderbuffer(struct st_context *st, struct gl_framebuffer *fb,
+st_manager_add_color_renderbuffer(struct st_context *st,
+                                  struct gl_framebuffer *fb,
                                   gl_buffer_index idx)
 {
    struct st_framebuffer *stfb = st_ws_framebuffer(fb);
@@ -892,6 +918,15 @@ st_manager_add_color_renderbuffer(struct st_context *st, struct gl_framebuffer *
       return FALSE;
 
    st_framebuffer_update_attachments(stfb);
+
+   /*
+    * Force a call to the state tracker manager to validate the
+    * new renderbuffer. It might be that there is a window system
+    * renderbuffer available.
+    */
+   if(stfb->iface)
+      stfb->iface_stamp = p_atomic_read(&stfb->iface->stamp) - 1;
+
    st_invalidate_state(st->ctx, _NEW_BUFFERS);
 
    return TRUE;