softpipe: reformatting, clean-ups, comments
[mesa.git] / src / gallium / drivers / softpipe / sp_texture.c
index 3eed0d0d2934d024574b88dd7c922a26b7b03f32..9a3f8f3d53b0d6d0fbad4f0fe4ac3d491f522cbe 100644 (file)
 #include "sp_texture.h"
 #include "sp_tile_cache.h"
 #include "sp_screen.h"
+#include "sp_winsys.h"
 
 
 /* Simple, maximally packed layout.
  */
 
-static unsigned minify( unsigned d )
-{
-   return MAX2(1, d>>1);
-}
 
-
-/* Conventional allocation path for non-display textures:
+/**
+ * Conventional allocation path for non-display textures:
  */
 static boolean
 softpipe_texture_layout(struct pipe_screen *screen,
                         struct softpipe_texture * spt)
 {
-   struct pipe_winsys *ws = screen->winsys;
    struct pipe_texture *pt = &spt->base;
    unsigned level;
    unsigned width = pt->width[0];
@@ -87,38 +83,40 @@ softpipe_texture_layout(struct pipe_screen *screen,
       depth = minify(depth);
    }
 
-   spt->buffer = ws->buffer_create(ws, 32,
-                                   PIPE_BUFFER_USAGE_PIXEL,
-                                   buffer_size);
+   spt->buffer = screen->buffer_create(screen, 32,
+                                       PIPE_BUFFER_USAGE_PIXEL,
+                                       buffer_size);
 
    return spt->buffer != NULL;
 }
 
+
+/**
+ * Texture layout for simple color buffers.
+ */
 static boolean
 softpipe_displaytarget_layout(struct pipe_screen *screen,
                               struct softpipe_texture * spt)
 {
-   struct pipe_winsys *ws = screen->winsys;
    unsigned usage = (PIPE_BUFFER_USAGE_CPU_READ_WRITE |
                      PIPE_BUFFER_USAGE_GPU_READ_WRITE);
+   unsigned tex_usage = spt->base.tex_usage;
 
    spt->base.nblocksx[0] = pf_get_nblocksx(&spt->base.block, spt->base.width[0]);  
    spt->base.nblocksy[0] = pf_get_nblocksy(&spt->base.block, spt->base.height[0]);  
 
-   spt->buffer = ws->surface_buffer_create( ws, 
-                                            spt->base.width[0], 
-                                            spt->base.height[0],
-                                            spt->base.format,
-                                            usage,
-                                            &spt->stride[0]);
+   spt->buffer = screen->surface_buffer_create( screen, 
+                                                spt->base.width[0], 
+                                                spt->base.height[0],
+                                                spt->base.format,
+                                                usage,
+                                                tex_usage,
+                                                &spt->stride[0]);
 
    return spt->buffer != NULL;
 }
 
 
-
-
-
 static struct pipe_texture *
 softpipe_texture_create(struct pipe_screen *screen,
                         const struct pipe_texture *templat)
@@ -128,10 +126,11 @@ softpipe_texture_create(struct pipe_screen *screen,
       return NULL;
 
    spt->base = *templat;
-   spt->base.refcount = 1;
+   pipe_reference_init(&spt->base.reference, 1);
    spt->base.screen = screen;
 
-   if (spt->base.tex_usage & PIPE_TEXTURE_USAGE_DISPLAY_TARGET) {
+   if (spt->base.tex_usage & (PIPE_TEXTURE_USAGE_DISPLAY_TARGET |
+                              PIPE_TEXTURE_USAGE_PRIMARY)) {
       if (!softpipe_displaytarget_layout(screen, spt))
          goto fail;
    }
@@ -140,7 +139,6 @@ softpipe_texture_create(struct pipe_screen *screen,
          goto fail;
    }
     
-   assert(spt->base.refcount == 1);
    return &spt->base;
 
  fail:
@@ -170,32 +168,25 @@ softpipe_texture_blanket(struct pipe_screen * screen,
       return NULL;
 
    spt->base = *base;
-   spt->base.refcount = 1;
+   pipe_reference_init(&spt->base.reference, 1);
    spt->base.screen = screen;
    spt->base.nblocksx[0] = pf_get_nblocksx(&spt->base.block, spt->base.width[0]);  
    spt->base.nblocksy[0] = pf_get_nblocksy(&spt->base.block, spt->base.height[0]);  
    spt->stride[0] = stride[0];
 
-   pipe_buffer_reference(screen, &spt->buffer, buffer);
+   pipe_buffer_reference(&spt->buffer, buffer);
 
    return &spt->base;
 }
 
 
 static void
-softpipe_texture_release(struct pipe_screen *screen,
-                         struct pipe_texture **pt)
+softpipe_texture_destroy(struct pipe_texture *pt)
 {
-   if (!*pt)
-      return;
-
-   if (--(*pt)->refcount <= 0) {
-      struct softpipe_texture *spt = softpipe_texture(*pt);
+   struct softpipe_texture *spt = softpipe_texture(pt);
 
-      pipe_buffer_reference(screen, &spt->buffer, NULL);
-      FREE(spt);
-   }
-   *pt = NULL;
+   pipe_buffer_reference(&spt->buffer, NULL);
+   FREE(spt);
 }
 
 
@@ -212,15 +203,11 @@ softpipe_get_tex_surface(struct pipe_screen *screen,
 
    ps = CALLOC_STRUCT(pipe_surface);
    if (ps) {
-      ps->refcount = 1;
+      pipe_reference_init(&ps->reference, 1);
       pipe_texture_reference(&ps->texture, pt);
       ps->format = pt->format;
-      ps->block = pt->block;
       ps->width = pt->width[level];
       ps->height = pt->height[level];
-      ps->nblocksx = pt->nblocksx[level];
-      ps->nblocksy = pt->nblocksy[level];
-      ps->stride = spt->stride[level];
       ps->offset = spt->level_offset[level];
       ps->usage = usage;
 
@@ -237,20 +224,15 @@ softpipe_get_tex_surface(struct pipe_screen *screen,
       if (ps->usage & PIPE_BUFFER_USAGE_GPU_READ)
          ps->usage |= PIPE_BUFFER_USAGE_CPU_READ;
 
-      if (ps->usage & (PIPE_BUFFER_USAGE_CPU_WRITE |
-                       PIPE_BUFFER_USAGE_GPU_WRITE)) {
-         /* Mark the surface as dirty.  The tile cache will look for this. */
-         spt->modified = TRUE;
-      }
-
       ps->face = face;
       ps->level = level;
       ps->zslice = zslice;
 
-      if (pt->target == PIPE_TEXTURE_CUBE || pt->target == PIPE_TEXTURE_3D) {
-         ps->offset += ((pt->target == PIPE_TEXTURE_CUBE) ? face : zslice) *
-            ps->nblocksy *
-            ps->stride;
+      if (pt->target == PIPE_TEXTURE_CUBE) {
+         ps->offset += face * pt->nblocksy[level] * spt->stride[level];
+      }
+      else if (pt->target == PIPE_TEXTURE_3D) {
+         ps->offset += zslice * pt->nblocksy[level] * spt->stride[level];
       }
       else {
          assert(face == 0);
@@ -262,38 +244,99 @@ softpipe_get_tex_surface(struct pipe_screen *screen,
 
 
 static void 
-softpipe_tex_surface_release(struct pipe_screen *screen, 
-                             struct pipe_surface **s)
+softpipe_tex_surface_destroy(struct pipe_surface *surf)
 {
-   struct pipe_surface *surf = *s;
    /* Effectively do the texture_update work here - if texture images
     * needed post-processing to put them into hardware layout, this is
     * where it would happen.  For softpipe, nothing to do.
     */
    assert(surf->texture);
-   if (--surf->refcount == 0) {
-      pipe_texture_reference(&surf->texture, NULL);
-      FREE(surf);
+   pipe_texture_reference(&surf->texture, NULL);
+   FREE(surf);
+}
+
+
+static struct pipe_transfer *
+softpipe_get_tex_transfer(struct pipe_screen *screen,
+                          struct pipe_texture *texture,
+                          unsigned face, unsigned level, unsigned zslice,
+                          enum pipe_transfer_usage usage,
+                          unsigned x, unsigned y, unsigned w, unsigned h)
+{
+   struct softpipe_texture *sptex = softpipe_texture(texture);
+   struct softpipe_transfer *spt;
+
+   assert(texture);
+   assert(level <= texture->last_level);
+
+   spt = CALLOC_STRUCT(softpipe_transfer);
+   if (spt) {
+      struct pipe_transfer *pt = &spt->base;
+      pipe_texture_reference(&pt->texture, texture);
+      pt->format = texture->format;
+      pt->block = texture->block;
+      pt->x = x;
+      pt->y = y;
+      pt->width = w;
+      pt->height = h;
+      pt->nblocksx = texture->nblocksx[level];
+      pt->nblocksy = texture->nblocksy[level];
+      pt->stride = sptex->stride[level];
+      pt->usage = usage;
+      pt->face = face;
+      pt->level = level;
+      pt->zslice = zslice;
+
+      spt->offset = sptex->level_offset[level];
+
+      if (texture->target == PIPE_TEXTURE_CUBE) {
+         spt->offset += face * pt->nblocksy * pt->stride;
+      }
+      else if (texture->target == PIPE_TEXTURE_3D) {
+         spt->offset += zslice * pt->nblocksy * pt->stride;
+      }
+      else {
+         assert(face == 0);
+         assert(zslice == 0);
+      }
+      return pt;
    }
-   *s = NULL;
+   return NULL;
+}
+
+
+static void 
+softpipe_tex_transfer_destroy(struct pipe_transfer *transfer)
+{
+   /* Effectively do the texture_update work here - if texture images
+    * needed post-processing to put them into hardware layout, this is
+    * where it would happen.  For softpipe, nothing to do.
+    */
+   assert (transfer->texture);
+   pipe_texture_reference(&transfer->texture, NULL);
+   FREE(transfer);
 }
 
 
 static void *
-softpipe_surface_map( struct pipe_screen *screen,
-                      struct pipe_surface *surface,
-                      unsigned flags )
+softpipe_transfer_map( struct pipe_screen *screen,
+                       struct pipe_transfer *transfer )
 {
-   ubyte *map;
+   ubyte *map, *xfer_map;
    struct softpipe_texture *spt;
+   unsigned flags = 0;
 
-   if (flags & ~surface->usage) {
-      assert(0);
-      return NULL;
+   assert(transfer->texture);
+   spt = softpipe_texture(transfer->texture);
+
+   if (transfer->usage != PIPE_TRANSFER_READ) {
+      flags |= PIPE_BUFFER_USAGE_CPU_WRITE;
+   }
+
+   if (transfer->usage != PIPE_TRANSFER_WRITE) {
+      flags |= PIPE_BUFFER_USAGE_CPU_READ;
    }
 
-   assert(surface->texture);
-   spt = softpipe_texture(surface->texture);
    map = pipe_buffer_map(screen, spt->buffer, flags);
    if (map == NULL)
       return NULL;
@@ -301,29 +344,36 @@ softpipe_surface_map( struct pipe_screen *screen,
    /* May want to different things here depending on read/write nature
     * of the map:
     */
-   if (surface->texture &&
-       (flags & PIPE_BUFFER_USAGE_CPU_WRITE)) 
-   {
+   if (transfer->texture && transfer->usage != PIPE_TRANSFER_READ) {
       /* Do something to notify sharing contexts of a texture change.
        * In softpipe, that would mean flushing the texture cache.
        */
       softpipe_screen(screen)->timestamp++;
    }
-   
-   return map + surface->offset;
+
+   xfer_map = map + softpipe_transfer(transfer)->offset +
+      transfer->y / transfer->block.height * transfer->stride +
+      transfer->x / transfer->block.width * transfer->block.size;
+   /*printf("map = %p  xfer map = %p\n", map, xfer_map);*/
+   return xfer_map;
 }
 
 
 static void
-softpipe_surface_unmap(struct pipe_screen *screen,
-                       struct pipe_surface *surface)
+softpipe_transfer_unmap(struct pipe_screen *screen,
+                        struct pipe_transfer *transfer)
 {
    struct softpipe_texture *spt;
 
-   assert(surface->texture);
-   spt = softpipe_texture(surface->texture);
+   assert(transfer->texture);
+   spt = softpipe_texture(transfer->texture);
 
    pipe_buffer_unmap( screen, spt->buffer );
+
+   if (transfer->usage != PIPE_TRANSFER_READ) {
+      /* Mark the texture as dirty to expire the tile caches. */
+      spt->modified = TRUE;
+   }
 }
 
 
@@ -338,11 +388,32 @@ softpipe_init_screen_texture_funcs(struct pipe_screen *screen)
 {
    screen->texture_create = softpipe_texture_create;
    screen->texture_blanket = softpipe_texture_blanket;
-   screen->texture_release = softpipe_texture_release;
+   screen->texture_destroy = softpipe_texture_destroy;
 
    screen->get_tex_surface = softpipe_get_tex_surface;
-   screen->tex_surface_release = softpipe_tex_surface_release;
+   screen->tex_surface_destroy = softpipe_tex_surface_destroy;
+
+   screen->get_tex_transfer = softpipe_get_tex_transfer;
+   screen->tex_transfer_destroy = softpipe_tex_transfer_destroy;
+   screen->transfer_map = softpipe_transfer_map;
+   screen->transfer_unmap = softpipe_transfer_unmap;
+}
+
+
+boolean
+softpipe_get_texture_buffer( struct pipe_texture *texture,
+                             struct pipe_buffer **buf,
+                             unsigned *stride )
+{
+   struct softpipe_texture *tex = (struct softpipe_texture *) texture;
+
+   if (!tex)
+      return FALSE;
+
+   pipe_buffer_reference(buf, tex->buffer);
+
+   if (stride)
+      *stride = tex->stride[0];
 
-   screen->surface_map = softpipe_surface_map;
-   screen->surface_unmap = softpipe_surface_unmap;
+   return TRUE;
 }