gallium: support for array textures and related changes
[mesa.git] / src / gallium / state_trackers / glx / xlib / xm_st.c
index 1c678b4f76054c548b4597481f6fe93238a69257..6bfe8b0788c5012713d239fce2a3c7c6a83c6445 100644 (file)
  *    Chia-I Wu <olv@lunarg.com>
  */
 
-#include "util/u_memory.h"
-#include "util/u_inlines.h"
-
 #include "xm_api.h"
 #include "xm_st.h"
 
+#include "util/u_inlines.h"
+
 struct xmesa_st_framebuffer {
    XMesaDisplay display;
    XMesaBuffer buffer;
    struct pipe_screen *screen;
 
    struct st_visual stvis;
+   enum pipe_texture_target target;
 
    unsigned texture_width, texture_height, texture_mask;
    struct pipe_resource *textures[ST_ATTACHMENT_COUNT];
 
-   struct pipe_surface *display_surface;
+   struct pipe_resource *display_resource;
 };
 
 static INLINE struct xmesa_st_framebuffer *
@@ -60,25 +60,19 @@ xmesa_st_framebuffer_display(struct st_framebuffer_iface *stfbi,
 {
    struct xmesa_st_framebuffer *xstfb = xmesa_st_framebuffer(stfbi);
    struct pipe_resource *ptex = xstfb->textures[statt];
-   struct pipe_surface *psurf;
+   struct pipe_resource *pres;
 
    if (!ptex)
       return TRUE;
 
-   psurf = xstfb->display_surface;
+   pres = xstfb->display_resource;
    /* (re)allocate the surface for the texture to be displayed */
-   if (!psurf || psurf->texture != ptex) {
-      pipe_surface_reference(&xstfb->display_surface, NULL);
-
-      psurf = xstfb->screen->get_tex_surface(xstfb->screen,
-            ptex, 0, 0, 0, PIPE_BIND_DISPLAY_TARGET);
-      if (!psurf)
-         return FALSE;
-
-      xstfb->display_surface = psurf;
+   if (!pres || pres != ptex) {
+      pipe_resource_reference(&xstfb->display_resource, ptex);
+      pres = xstfb->display_resource;
    }
 
-   xstfb->screen->flush_frontbuffer(xstfb->screen, psurf, &xstfb->buffer->ws);
+   xstfb->screen->flush_frontbuffer(xstfb->screen, pres, 0, 0, &xstfb->buffer->ws);
 
    return TRUE;
 }
@@ -96,7 +90,7 @@ xmesa_st_framebuffer_copy_textures(struct st_framebuffer_iface *stfbi,
    struct xmesa_st_framebuffer *xstfb = xmesa_st_framebuffer(stfbi);
    struct pipe_resource *src_ptex = xstfb->textures[src_statt];
    struct pipe_resource *dst_ptex = xstfb->textures[dst_statt];
-   struct pipe_surface *src, *dst;
+   struct pipe_box src_box;
    struct pipe_context *pipe;
 
    if (!src_ptex || !dst_ptex)
@@ -110,20 +104,16 @@ xmesa_st_framebuffer_copy_textures(struct st_framebuffer_iface *stfbi,
       xstfb->display->pipe = pipe;
    }
 
-   src = xstfb->screen->get_tex_surface(xstfb->screen,
-         src_ptex, 0, 0, 0, PIPE_BIND_BLIT_SOURCE);
-   dst = xstfb->screen->get_tex_surface(xstfb->screen,
-         dst_ptex, 0, 0, 0, PIPE_BIND_BLIT_DESTINATION);
-
-   if (src && dst)
-      pipe->surface_copy(pipe, dst, x, y, src, x, y, width, height);
+   u_box_2d(x, y, width, height, &src_box);
 
-   pipe_surface_reference(&src, NULL);
-   pipe_surface_reference(&dst, NULL);
+   if (src_ptex && dst_ptex)
+      pipe->resource_copy_region(pipe, dst_ptex, 0, x, y, 0,
+                                 src_ptex, 0, &src_box);
 }
 
 /**
  * Remove outdated textures and create the requested ones.
+ * This is a helper used during framebuffer validation.
  */
 static boolean
 xmesa_st_framebuffer_validate_textures(struct st_framebuffer_iface *stfbi,
@@ -141,10 +131,11 @@ xmesa_st_framebuffer_validate_textures(struct st_framebuffer_iface *stfbi,
    }
 
    memset(&templ, 0, sizeof(templ));
-   templ.target = PIPE_TEXTURE_2D;
+   templ.target = xstfb->target;
    templ.width0 = width;
    templ.height0 = height;
    templ.depth0 = 1;
+   templ.array_size = 1;
    templ.last_level = 0;
 
    for (i = 0; i < ST_ATTACHMENT_COUNT; i++) {
@@ -195,6 +186,16 @@ xmesa_st_framebuffer_validate_textures(struct st_framebuffer_iface *stfbi,
    return TRUE;
 }
 
+
+/**
+ * Check that a framebuffer's attachments match the window's size.
+ *
+ * Called via st_framebuffer_iface::validate()
+ *
+ * \param statts  array of framebuffer attachments
+ * \param count  number of framebuffer attachments in statts[]
+ * \param out  returns resources for each of the attachments
+ */
 static boolean 
 xmesa_st_framebuffer_validate(struct st_framebuffer_iface *stfbi,
                               const enum st_attachment_type *statts,
@@ -206,12 +207,20 @@ xmesa_st_framebuffer_validate(struct st_framebuffer_iface *stfbi,
    boolean resized;
    boolean ret;
 
+   /* build mask of ST_ATTACHMENT bits */
    statt_mask = 0x0;
    for (i = 0; i < count; i++)
       statt_mask |= 1 << statts[i];
+
    /* record newly allocated textures */
    new_mask = statt_mask & ~xstfb->texture_mask;
 
+   /* If xmesa_strict_invalidate is not set, we will not yet have
+    * called XGetGeometry().  Do so here:
+    */
+   if (!xmesa_strict_invalidate)
+      xmesa_check_buffer_size(xstfb->buffer);
+
    resized = (xstfb->buffer->width != xstfb->texture_width ||
               xstfb->buffer->height != xstfb->texture_height);
 
@@ -245,6 +254,9 @@ xmesa_st_framebuffer_validate(struct st_framebuffer_iface *stfbi,
    return TRUE;
 }
 
+/**
+ * Called via st_framebuffer_iface::flush_front()
+ */
 static boolean
 xmesa_st_framebuffer_flush_front(struct st_framebuffer_iface *stfbi,
                                  enum st_attachment_type statt)
@@ -253,7 +265,8 @@ xmesa_st_framebuffer_flush_front(struct st_framebuffer_iface *stfbi,
    boolean ret;
 
    ret = xmesa_st_framebuffer_display(stfbi, statt);
-   if (ret)
+
+   if (ret && xmesa_strict_invalidate)
       xmesa_check_buffer_size(xstfb->buffer);
 
    return ret;
@@ -281,6 +294,10 @@ xmesa_create_st_framebuffer(XMesaDisplay xmdpy, XMesaBuffer b)
    xstfb->buffer = b;
    xstfb->screen = xmdpy->screen;
    xstfb->stvis = b->xm_visual->stvis;
+   if(xstfb->screen->get_param(xstfb->screen, PIPE_CAP_NPOT_TEXTURES))
+      xstfb->target = PIPE_TEXTURE_2D;
+   else
+      xstfb->target = PIPE_TEXTURE_RECT;
 
    stfbi->visual = &xstfb->stvis;
    stfbi->flush_front = xmesa_st_framebuffer_flush_front;
@@ -296,7 +313,7 @@ xmesa_destroy_st_framebuffer(struct st_framebuffer_iface *stfbi)
    struct xmesa_st_framebuffer *xstfb = xmesa_st_framebuffer(stfbi);
    int i;
 
-   pipe_surface_reference(&xstfb->display_surface, NULL);
+   pipe_resource_reference(&xstfb->display_resource, NULL);
 
    for (i = 0; i < ST_ATTACHMENT_COUNT; i++)
       pipe_resource_reference(&xstfb->textures[i], NULL);
@@ -322,9 +339,14 @@ xmesa_swap_st_framebuffer(struct st_framebuffer_iface *stfbi)
          tmp = *front;
          *front = *back;
          *back = tmp;
+
+         /* the current context should validate the buffer after swapping */
+         if (!xmesa_strict_invalidate)
+            xmesa_notify_invalid_buffer(xstfb->buffer);
       }
 
-      xmesa_check_buffer_size(xstfb->buffer);
+      if (xmesa_strict_invalidate)
+        xmesa_check_buffer_size(xstfb->buffer);
    }
 }