Merge remote branch 'origin/7.8'
[mesa.git] / src / gallium / drivers / cell / ppu / cell_pipe_state.c
index 075e0a0c471bf2a5a50583df3a6e3aa303aa1ad0..059ce8597bcf9883fd4a26564d803a4b1d81eb9e 100644 (file)
@@ -1,5 +1,5 @@
 /**************************************************************************
- * 
+ *
  * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
  * All Rights Reserved.
  *
  * distribute, sub license, and/or sell copies of the Software, and to
  * permit persons to whom the Software is furnished to do so, subject to
  * the following conditions:
- * 
+ *
  * The above copyright notice and this permission notice (including the
  * next paragraph) shall be included in all copies or substantial portions
  * of the Software.
- * 
+ *
  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
@@ -22,7 +22,7 @@
  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- * 
+ *
  **************************************************************************/
 
 /* Authors:
  *  Brian Paul
  */
 
-#include "pipe/p_util.h"
-#include "pipe/p_inlines.h"
+#include "util/u_memory.h"
+#include "util/u_inlines.h"
 #include "draw/draw_context.h"
 #include "cell_context.h"
+#include "cell_flush.h"
+#include "cell_pipe_state.h"
 #include "cell_state.h"
 #include "cell_texture.h"
 
@@ -54,8 +56,7 @@ cell_bind_blend_state(struct pipe_context *pipe, void *blend)
 
    draw_flush(cell->draw);
 
-   cell->blend = (const struct pipe_blend_state *)blend;
-
+   cell->blend = (struct pipe_blend_state *) blend;
    cell->dirty |= CELL_NEW_BLEND;
 }
 
@@ -85,36 +86,48 @@ cell_set_blend_color(struct pipe_context *pipe,
 
 static void *
 cell_create_depth_stencil_alpha_state(struct pipe_context *pipe,
-                 const struct pipe_depth_stencil_alpha_state *depth_stencil)
+                 const struct pipe_depth_stencil_alpha_state *dsa)
 {
-   return mem_dup(depth_stencil, sizeof(*depth_stencil));
+   return mem_dup(dsa, sizeof(*dsa));
 }
 
 
 static void
 cell_bind_depth_stencil_alpha_state(struct pipe_context *pipe,
-                                    void *depth_stencil)
+                                    void *dsa)
 {
    struct cell_context *cell = cell_context(pipe);
 
    draw_flush(cell->draw);
 
-   cell->depth_stencil
-      = (const struct pipe_depth_stencil_alpha_state *) depth_stencil;
-
+   cell->depth_stencil = (struct pipe_depth_stencil_alpha_state *) dsa;
    cell->dirty |= CELL_NEW_DEPTH_STENCIL;
 }
 
 
 static void
-cell_delete_depth_stencil_alpha_state(struct pipe_context *pipe, void *depth)
+cell_delete_depth_stencil_alpha_state(struct pipe_context *pipe, void *dsa)
 {
-   FREE(depth);
+   FREE(dsa);
 }
 
 
-static void cell_set_clip_state( struct pipe_context *pipe,
-                            const struct pipe_clip_state *clip )
+static void
+cell_set_stencil_ref(struct pipe_context *pipe,
+                     const struct pipe_stencil_ref *stencil_ref)
+{
+   struct cell_context *cell = cell_context(pipe);
+
+   draw_flush(cell->draw);
+
+   cell->stencil_ref = *stencil_ref;
+
+   cell->dirty |= CELL_NEW_DEPTH_STENCIL;
+}
+
+static void
+cell_set_clip_state(struct pipe_context *pipe,
+                    const struct pipe_clip_state *clip)
 {
    struct cell_context *cell = cell_context(pipe);
 
@@ -170,24 +183,23 @@ cell_set_polygon_stipple( struct pipe_context *pipe,
 
 static void *
 cell_create_rasterizer_state(struct pipe_context *pipe,
-                             const struct pipe_rasterizer_state *setup)
+                             const struct pipe_rasterizer_state *rasterizer)
 {
-   struct pipe_rasterizer_state *state
-      = MALLOC(sizeof(struct pipe_rasterizer_state));
-   memcpy(state, setup, sizeof(struct pipe_rasterizer_state));
-   return state;
+   return mem_dup(rasterizer, sizeof(*rasterizer));
 }
 
 
 static void
-cell_bind_rasterizer_state(struct pipe_context *pipe, void *setup)
+cell_bind_rasterizer_state(struct pipe_context *pipe, void *rast)
 {
+   struct pipe_rasterizer_state *rasterizer =
+      (struct pipe_rasterizer_state *) rast;
    struct cell_context *cell = cell_context(pipe);
 
    /* pass-through to draw module */
-   draw_set_rasterizer_state(cell->draw, setup);
+   draw_set_rasterizer_state(cell->draw, rasterizer);
 
-   cell->rasterizer = (struct pipe_rasterizer_state *)setup;
+   cell->rasterizer = rasterizer;
 
    cell->dirty |= CELL_NEW_RASTERIZER;
 }
@@ -210,17 +222,28 @@ cell_create_sampler_state(struct pipe_context *pipe,
 
 
 static void
-cell_bind_sampler_state(struct pipe_context *pipe,
-                            unsigned unit, void *sampler)
+cell_bind_sampler_states(struct pipe_context *pipe,
+                         unsigned num, void **samplers)
 {
    struct cell_context *cell = cell_context(pipe);
+   uint i, changed = 0x0;
+
+   assert(num <= CELL_MAX_SAMPLERS);
 
    draw_flush(cell->draw);
 
-   assert(unit < PIPE_MAX_SAMPLERS);
-   cell->sampler[unit] = (struct pipe_sampler_state *)sampler;
+   for (i = 0; i < CELL_MAX_SAMPLERS; i++) {
+      struct pipe_sampler_state *new_samp = i < num ? samplers[i] : NULL;
+      if (cell->sampler[i] != new_samp) {
+         cell->sampler[i] = new_samp;
+         changed |= (1 << i);
+      }
+   }
 
-   cell->dirty |= CELL_NEW_SAMPLER;
+   if (changed) {
+      cell->dirty |= CELL_NEW_SAMPLER;
+      cell->dirty_samplers |= changed;
+   }
 }
 
 
@@ -234,23 +257,142 @@ cell_delete_sampler_state(struct pipe_context *pipe,
 
 
 static void
-cell_set_sampler_texture(struct pipe_context *pipe,
-                         unsigned sampler,
-                         struct pipe_texture *texture)
+cell_set_fragment_sampler_views(struct pipe_context *pipe,
+                                unsigned num,
+                                struct pipe_sampler_view **views)
 {
    struct cell_context *cell = cell_context(pipe);
+   uint i, changed = 0x0;
 
-   draw_flush(cell->draw);
+   assert(num <= CELL_MAX_SAMPLERS);
 
-   pipe_texture_reference((struct pipe_texture **) &cell->texture[sampler],
-                          texture);
+   for (i = 0; i < CELL_MAX_SAMPLERS; i++) {
+      struct pipe_sampler_view *new_view = i < num ? views[i] : NULL;
+      struct pipe_sampler_view *old_view = cell->fragment_sampler_views[i];
 
-   cell_update_texture_mapping(cell);
+      if (old_view != new_view) {
+         struct pipe_texture *new_tex = new_view ? new_view->texture : NULL;
+
+         pipe_sampler_view_reference(&cell->fragment_sampler_views[i],
+                                     views[i]);
+         pipe_texture_reference((struct pipe_texture **) &cell->texture[i],
+                                (struct pipe_texture *) new_tex);
+
+         changed |= (1 << i);
+      }
+   }
 
-   cell->dirty |= CELL_NEW_TEXTURE;
+   cell->num_textures = num;
+
+   if (changed) {
+      cell->dirty |= CELL_NEW_TEXTURE;
+      cell->dirty_textures |= changed;
+   }
 }
 
 
+static struct pipe_sampler_view *
+cell_create_sampler_view(struct pipe_context *pipe,
+                         struct pipe_texture *texture,
+                         const struct pipe_sampler_view *templ)
+{
+   struct pipe_sampler_view *view = CALLOC_STRUCT(pipe_sampler_view);
+
+   if (view) {
+      *view = *templ;
+      view->reference.count = 1;
+      view->texture = NULL;
+      pipe_texture_reference(&view->texture, texture);
+      view->context = pipe;
+   }
+
+   return view;
+}
+
+
+static void
+cell_sampler_view_destroy(struct pipe_context *pipe,
+                          struct pipe_sampler_view *view)
+{
+   pipe_texture_reference(&view->texture, NULL);
+   FREE(view);
+}
+
+
+/**
+ * Map color and z/stencil framebuffer surfaces.
+ */
+static void
+cell_map_surfaces(struct cell_context *cell)
+{
+#if 0
+   struct pipe_screen *screen = cell->pipe.screen;
+#endif
+   uint i;
+
+   for (i = 0; i < 1; i++) {
+      struct pipe_surface *ps = cell->framebuffer.cbufs[i];
+      if (ps) {
+         struct cell_texture *ct = cell_texture(ps->texture);
+#if 0
+         cell->cbuf_map[i] = screen->buffer_map(screen,
+                                                ct->buffer,
+                                                (PIPE_BUFFER_USAGE_GPU_READ |
+                                                 PIPE_BUFFER_USAGE_GPU_WRITE));
+#else
+         cell->cbuf_map[i] = ct->data;
+#endif
+      }
+   }
+
+   {
+      struct pipe_surface *ps = cell->framebuffer.zsbuf;
+      if (ps) {
+         struct cell_texture *ct = cell_texture(ps->texture);
+#if 0
+         cell->zsbuf_map = screen->buffer_map(screen,
+                                              ct->buffer,
+                                              (PIPE_BUFFER_USAGE_GPU_READ |
+                                               PIPE_BUFFER_USAGE_GPU_WRITE));
+#else
+         cell->zsbuf_map = ct->data;
+#endif
+      }
+   }
+}
+
+
+/**
+ * Unmap color and z/stencil framebuffer surfaces.
+ */
+static void
+cell_unmap_surfaces(struct cell_context *cell)
+{
+   /*struct pipe_screen *screen = cell->pipe.screen;*/
+   uint i;
+
+   for (i = 0; i < PIPE_MAX_COLOR_BUFS; i++) {
+      struct pipe_surface *ps = cell->framebuffer.cbufs[i];
+      if (ps && cell->cbuf_map[i]) {
+         /*struct cell_texture *ct = cell_texture(ps->texture);*/
+         assert(ps->texture);
+         /*assert(ct->buffer);*/
+
+         /*screen->buffer_unmap(screen, ct->buffer);*/
+         cell->cbuf_map[i] = NULL;
+      }
+   }
+
+   {
+      struct pipe_surface *ps = cell->framebuffer.zsbuf;
+      if (ps && cell->zsbuf_map) {
+         /*struct cell_texture *ct = cell_texture(ps->texture);*/
+         /*screen->buffer_unmap(screen, ct->buffer);*/
+         cell->zsbuf_map = NULL;
+      }
+   }
+}
+
 
 static void
 cell_set_framebuffer_state(struct pipe_context *pipe,
@@ -259,32 +401,29 @@ cell_set_framebuffer_state(struct pipe_context *pipe,
    struct cell_context *cell = cell_context(pipe);
 
    if (1 /*memcmp(&cell->framebuffer, fb, sizeof(*fb))*/) {
-      struct pipe_surface *csurf = fb->cbufs[0];
-      struct pipe_surface *zsurf = fb->zsbuf;
       uint i;
 
       /* unmap old surfaces */
+      cell_unmap_surfaces(cell);
+
+      /* Finish any pending rendering to the current surface before
+       * installing a new surface!
+       */
+      cell_flush_int(cell, CELL_FLUSH_WAIT);
+
+      /* update my state
+       * (this is also where old surfaces will finally get freed)
+       */
+      cell->framebuffer.width = fb->width;
+      cell->framebuffer.height = fb->height;
+      cell->framebuffer.nr_cbufs = fb->nr_cbufs;
       for (i = 0; i < PIPE_MAX_COLOR_BUFS; i++) {
-         if (cell->framebuffer.cbufs[i] && cell->cbuf_map[i]) {
-            pipe_surface_unmap(cell->framebuffer.cbufs[i]);
-            cell->cbuf_map[i] = NULL;
-         }
-      }
-
-      if (cell->framebuffer.zsbuf && cell->zsbuf_map) {
-         pipe_surface_unmap(cell->framebuffer.zsbuf);
-         cell->zsbuf_map = NULL;
+         pipe_surface_reference(&cell->framebuffer.cbufs[i], fb->cbufs[i]);
       }
-
-      /* update my state */
-      cell->framebuffer = *fb;
+      pipe_surface_reference(&cell->framebuffer.zsbuf, fb->zsbuf);
 
       /* map new surfaces */
-      if (csurf)
-         cell->cbuf_map[0] = pipe_surface_map(csurf);
-
-      if (zsurf)
-         cell->zsbuf_map = pipe_surface_map(zsurf);
+      cell_map_surfaces(cell);
 
       cell->dirty |= CELL_NEW_FRAMEBUFFER;
    }
@@ -300,10 +439,12 @@ cell_init_state_functions(struct cell_context *cell)
    cell->pipe.delete_blend_state = cell_delete_blend_state;
 
    cell->pipe.create_sampler_state = cell_create_sampler_state;
-   cell->pipe.bind_sampler_state   = cell_bind_sampler_state;
+   cell->pipe.bind_fragment_sampler_states = cell_bind_sampler_states;
    cell->pipe.delete_sampler_state = cell_delete_sampler_state;
 
-   cell->pipe.set_sampler_texture = cell_set_sampler_texture;
+   cell->pipe.set_fragment_sampler_views = cell_set_fragment_sampler_views;
+   cell->pipe.create_sampler_view = cell_create_sampler_view;
+   cell->pipe.sampler_view_destroy = cell_sampler_view_destroy;
 
    cell->pipe.create_depth_stencil_alpha_state = cell_create_depth_stencil_alpha_state;
    cell->pipe.bind_depth_stencil_alpha_state   = cell_bind_depth_stencil_alpha_state;
@@ -314,6 +455,7 @@ cell_init_state_functions(struct cell_context *cell)
    cell->pipe.delete_rasterizer_state = cell_delete_rasterizer_state;
 
    cell->pipe.set_blend_color = cell_set_blend_color;
+   cell->pipe.set_stencil_ref = cell_set_stencil_ref;
    cell->pipe.set_clip_state = cell_set_clip_state;
 
    cell->pipe.set_framebuffer_state = cell_set_framebuffer_state;
@@ -322,4 +464,3 @@ cell_init_state_functions(struct cell_context *cell)
    cell->pipe.set_scissor_state = cell_set_scissor_state;
    cell->pipe.set_viewport_state = cell_set_viewport_state;
 }
-