cell: untwiddle surface contents in flush_frontbuffer()
[mesa.git] / src / gallium / drivers / cell / ppu / cell_texture.c
index 998944f77a399717a86e06d5b50f1b794f3432ce..002dd3a9b55f57d56cc84b254784cd51b5a33a66 100644 (file)
@@ -33,8 +33,7 @@
 
 #include "pipe/p_context.h"
 #include "pipe/p_defines.h"
-#include "pipe/p_inlines.h"
-#include "pipe/internal/p_winsys_screen.h"
+#include "util/u_inlines.h"
 
 #include "util/u_format.h"
 #include "util/u_math.h"
 #include "cell_state.h"
 #include "cell_texture.h"
 
+#include "state_tracker/sw_winsys.h"
 
 
-static void
-cell_texture_layout(struct cell_texture *ct)
+
+static boolean
+cell_texture_layout(struct pipe_screen *screen, 
+                    struct cell_texture *ct)
 {
    struct pipe_texture *pt = &ct->base;
    unsigned level;
@@ -83,9 +85,34 @@ cell_texture_layout(struct cell_texture *ct)
       height = u_minify(height, 1);
       depth = u_minify(depth, 1);
    }
+
+   ct->data = align_malloc(ct->buffer_size, 16);
+   return ct->data != NULL;
 }
 
 
+/**
+ * Texture layout for simple color buffers.
+ */
+static boolean
+cell_displaytarget_layout(struct pipe_screen *screen,
+                          struct cell_texture * ct)
+{
+   struct sw_winsys *winsys = cell_screen(screen)->winsys;
+
+   /* Round up the surface size to a multiple of the tile size?
+    */
+   ct->dt = winsys->displaytarget_create(winsys,
+                                          ct->base.format,
+                                          ct->base.width0, 
+                                          ct->base.height0,
+                                          16,
+                                          &ct->dt_stride );
+
+   return ct->dt != NULL;
+}
+
 static struct pipe_texture *
 cell_texture_create(struct pipe_screen *screen,
                     const struct pipe_texture *templat)
@@ -98,31 +125,46 @@ cell_texture_create(struct pipe_screen *screen,
    pipe_reference_init(&ct->base.reference, 1);
    ct->base.screen = screen;
 
-   cell_texture_layout(ct);
+   /* Create both a displaytarget (linear) and regular texture
+    * (twiddled).  Convert twiddled->linear at flush_frontbuffer time.
+    */
+   if (ct->base.tex_usage & (PIPE_TEXTURE_USAGE_DISPLAY_TARGET |
+                             PIPE_TEXTURE_USAGE_SCANOUT |
+                             PIPE_TEXTURE_USAGE_SHARED)) {
+      if (!cell_displaytarget_layout(screen, ct))
+         goto fail;
+   }
 
-   ct->buffer = screen->buffer_create(screen, 32, PIPE_BUFFER_USAGE_PIXEL,
-                                   ct->buffer_size);
+   if (!cell_texture_layout(screen, ct))
+      goto fail;
 
-   if (!ct->buffer) {
-      FREE(ct);
-      return NULL;
+   return &ct->base;
+
+fail:
+   if (ct->dt) {
+      struct sw_winsys winsys = cell_screen(screen)->winsys;
+      winsys->displaytarget_destroy(winsys, ct->dt);
    }
 
-   return &ct->base;
+   FREE(ct);
+
+   return NULL;
 }
 
 
 static void
 cell_texture_destroy(struct pipe_texture *pt)
 {
+   struct cell_screen *screen = cell_screen(pt->screen);
+   struct sw_winsys *winsys = screen->winsys;
    struct cell_texture *ct = cell_texture(pt);
 
-   if (ct->mapped) {
-      pipe_buffer_unmap(ct->buffer->screen, ct->buffer);
-      ct->mapped = NULL;
+   if (ct->dt) {
+      /* display target */
+      winsys->displaytarget_destroy(winsys, ct->dt);
    }
 
-   pipe_buffer_reference(&ct->buffer, NULL);
+   align_free(ct->data);
 
    FREE(ct);
 }
@@ -389,10 +431,8 @@ cell_transfer_map(struct pipe_screen *screen, struct pipe_transfer *transfer)
 
    assert(transfer->texture);
 
-   if (!ct->mapped) {
-      /* map now */
-      ct->mapped = pipe_buffer_map(screen, ct->buffer,
-                                   pipe_transfer_buffer_flags(transfer));
+   if (ct->mapped == NULL) {
+      ct->mapped = ct->data;
    }
 
    /*
@@ -442,9 +482,8 @@ cell_transfer_unmap(struct pipe_screen *screen,
    const uint stride = ct->stride[level];
 
    if (!ct->mapped) {
-      /* map now */
-      ct->mapped = pipe_buffer_map(screen, ct->buffer,
-                                   PIPE_BUFFER_USAGE_CPU_READ);
+      assert(0);
+      return;
    }
 
    if (transfer->usage & PIPE_TRANSFER_WRITE) {
@@ -467,6 +506,48 @@ cell_transfer_unmap(struct pipe_screen *screen,
 }
 
 
+
+/* This used to be overriden by the co-state tracker, but really needs
+ * to be active with sw_winsys.
+ *
+ * Contrasting with llvmpipe and softpipe, this is the only place
+ * where we use the ct->dt display target in any real sense.
+ *
+ * Basically just untwiddle our local data into the linear
+ * displaytarget.
+ */
+static void
+cell_flush_frontbuffer(struct pipe_screen *_screen,
+                       struct pipe_surface *surface,
+                       void *context_private)
+{
+   struct cell_screen *screen = cell_screen(_screen);
+   struct sw_winsys *winsys = screen->winsys;
+   struct cell_texture *ct = cell_texture(surface->texture);
+
+   if (!ct->dt)
+      return;
+
+   /* Need to untwiddle from our internal representation here:
+    */
+   {
+      unsigned *map = winsys->displaytarget_map(winsys, ct->dt);
+      unsigned *src = (unsigned *)(ct->data + ct->level_offset[surface->level]);
+
+      untwiddle_image_uint(surface->width,
+                           surface->height,
+                           TILE_SIZE,
+                           map,
+                           ct->dt_stride,
+                           src);
+
+      winsys->displaytarget_unmap(winsys, c->dt);
+   }
+
+   winsys->displaytarget_display(winsys, ct->dt, context_private);
+}
+
+
 void
 cell_init_screen_texture_funcs(struct pipe_screen *screen)
 {
@@ -481,4 +562,6 @@ cell_init_screen_texture_funcs(struct pipe_screen *screen)
 
    screen->transfer_map = cell_transfer_map;
    screen->transfer_unmap = cell_transfer_unmap;
+
+   screen->flush_frontbuffer = cell_flush_frontbuffer;
 }