Merge branch '7.8'
[mesa.git] / src / gallium / drivers / llvmpipe / lp_texture.c
index 8137f29af52d2194c65c9a5bb0ee851bb98eb044..61210de8901bdb2f0889bb3f683146b80d04ad99 100644 (file)
 #include "util/u_format.h"
 #include "util/u_math.h"
 #include "util/u_memory.h"
+#include "util/u_transfer.h"
 
 #include "lp_context.h"
 #include "lp_screen.h"
 #include "lp_flush.h"
 #include "lp_texture.h"
+#include "lp_setup.h"
 #include "lp_tile_size.h"
 #include "state_tracker/sw_winsys.h"
 
  * Simple, maximally packed layout.
  */
 static boolean
-llvmpipe_texture_layout(struct llvmpipe_screen *screen,
-                        struct llvmpipe_texture *lpt)
+llvmpipe_resource_layout(struct llvmpipe_screen *screen,
+                        struct llvmpipe_resource *lpt)
 {
-   struct pipe_texture *pt = &lpt->base;
+   struct pipe_resource *pt = &lpt->base;
    unsigned level;
    unsigned width = pt->width0;
    unsigned height = pt->height0;
@@ -92,7 +94,7 @@ llvmpipe_texture_layout(struct llvmpipe_screen *screen,
 
 static boolean
 llvmpipe_displaytarget_layout(struct llvmpipe_screen *screen,
-                              struct llvmpipe_texture *lpt)
+                              struct llvmpipe_resource *lpt)
 {
    struct sw_winsys *winsys = screen->winsys;
 
@@ -103,7 +105,7 @@ llvmpipe_displaytarget_layout(struct llvmpipe_screen *screen,
    unsigned height = align(lpt->base.height0, TILE_SIZE);
 
    lpt->dt = winsys->displaytarget_create(winsys,
-                                          lpt->base.tex_usage,
+                                          lpt->base.bind,
                                           lpt->base.format,
                                           width, height,
                                           16,
@@ -113,12 +115,12 @@ llvmpipe_displaytarget_layout(struct llvmpipe_screen *screen,
 }
 
 
-static struct pipe_texture *
-llvmpipe_texture_create(struct pipe_screen *_screen,
-                        const struct pipe_texture *templat)
+static struct pipe_resource *
+llvmpipe_resource_create(struct pipe_screen *_screen,
+                        const struct pipe_resource *templat)
 {
    struct llvmpipe_screen *screen = llvmpipe_screen(_screen);
-   struct llvmpipe_texture *lpt = CALLOC_STRUCT(llvmpipe_texture);
+   struct llvmpipe_resource *lpt = CALLOC_STRUCT(llvmpipe_resource);
    if (!lpt)
       return NULL;
 
@@ -126,17 +128,17 @@ llvmpipe_texture_create(struct pipe_screen *_screen,
    pipe_reference_init(&lpt->base.reference, 1);
    lpt->base.screen = &screen->base;
 
-   if (lpt->base.tex_usage & (PIPE_TEXTURE_USAGE_DISPLAY_TARGET |
-                              PIPE_TEXTURE_USAGE_SCANOUT |
-                              PIPE_TEXTURE_USAGE_SHARED)) {
+   if (lpt->base.bind & (PIPE_BIND_DISPLAY_TARGET |
+                         PIPE_BIND_SCANOUT |
+                         PIPE_BIND_SHARED)) {
       if (!llvmpipe_displaytarget_layout(screen, lpt))
          goto fail;
    }
    else {
-      if (!llvmpipe_texture_layout(screen, lpt))
+      if (!llvmpipe_resource_layout(screen, lpt))
          goto fail;
    }
-    
+
    return &lpt->base;
 
  fail:
@@ -146,17 +148,18 @@ llvmpipe_texture_create(struct pipe_screen *_screen,
 
 
 static void
-llvmpipe_texture_destroy(struct pipe_texture *pt)
+llvmpipe_resource_destroy(struct pipe_screen *pscreen,
+                         struct pipe_resource *pt)
 {
-   struct llvmpipe_screen *screen = llvmpipe_screen(pt->screen);
-   struct llvmpipe_texture *lpt = llvmpipe_texture(pt);
+   struct llvmpipe_screen *screen = llvmpipe_screen(pscreen);
+   struct llvmpipe_resource *lpt = llvmpipe_resource(pt);
 
    if (lpt->dt) {
       /* display target */
       struct sw_winsys *winsys = screen->winsys;
       winsys->displaytarget_destroy(winsys, lpt->dt);
    }
-   else {
+   else if (!lpt->userBuffer) {
       /* regular texture */
       align_free(lpt->data);
    }
@@ -169,19 +172,19 @@ llvmpipe_texture_destroy(struct pipe_texture *pt)
  * Map a texture. Without any synchronization.
  */
 void *
-llvmpipe_texture_map(struct pipe_texture *texture,
-                     unsigned face,
-                     unsigned level,
-                     unsigned zslice)
+llvmpipe_resource_map(struct pipe_resource *texture,
+                     unsigned usage,
+                     unsigned face,
+                     unsigned level,
+                     unsigned zslice)
 {
-   struct llvmpipe_texture *lpt = llvmpipe_texture(texture);
+   struct llvmpipe_resource *lpt = llvmpipe_resource(texture);
    uint8_t *map;
 
    if (lpt->dt) {
       /* display target */
       struct llvmpipe_screen *screen = llvmpipe_screen(texture->screen);
       struct sw_winsys *winsys = screen->winsys;
-      const unsigned usage = PIPE_BUFFER_USAGE_CPU_READ_WRITE;
 
       assert(face == 0);
       assert(level == 0);
@@ -204,7 +207,7 @@ llvmpipe_texture_map(struct pipe_texture *texture,
 
       /* XXX shouldn't that rather be
          tex_height = align(u_minify(texture->height0, level), 2)
-         to account for alignment done in llvmpipe_texture_layout ?
+         to account for alignment done in llvmpipe_resource_layout ?
       */
       if (texture->target == PIPE_TEXTURE_CUBE) {
          unsigned tex_height = u_minify(texture->height0, level);
@@ -230,12 +233,12 @@ llvmpipe_texture_map(struct pipe_texture *texture,
  * Unmap a texture. Without any synchronization.
  */
 void
-llvmpipe_texture_unmap(struct pipe_texture *texture,
+llvmpipe_resource_unmap(struct pipe_resource *texture,
                        unsigned face,
                        unsigned level,
                        unsigned zslice)
 {
-   struct llvmpipe_texture *lpt = llvmpipe_texture(texture);
+   struct llvmpipe_resource *lpt = llvmpipe_resource(texture);
 
    if (lpt->dt) {
       /* display target */
@@ -251,13 +254,13 @@ llvmpipe_texture_unmap(struct pipe_texture *texture,
 }
 
 
-static struct pipe_texture *
-llvmpipe_texture_from_handle(struct pipe_screen *screen,
-                             const struct pipe_texture *template,
-                             struct winsys_handle *whandle)
+static struct pipe_resource *
+llvmpipe_resource_from_handle(struct pipe_screen *screen,
+                             const struct pipe_resource *template,
+                             struct winsys_handle *whandle)
 {
    struct sw_winsys *winsys = llvmpipe_screen(screen)->winsys;
-   struct llvmpipe_texture *lpt = CALLOC_STRUCT(llvmpipe_texture);
+   struct llvmpipe_resource *lpt = CALLOC_STRUCT(llvmpipe_resource);
    if (!lpt)
       return NULL;
 
@@ -281,12 +284,12 @@ llvmpipe_texture_from_handle(struct pipe_screen *screen,
 
 
 static boolean
-llvmpipe_texture_get_handle(struct pipe_screen *screen,
-                            struct pipe_texture *pt,
+llvmpipe_resource_get_handle(struct pipe_screen *screen,
+                            struct pipe_resource *pt,
                             struct winsys_handle *whandle)
 {
    struct sw_winsys *winsys = llvmpipe_screen(screen)->winsys;
-   struct llvmpipe_texture *lpt = llvmpipe_texture(pt);
+   struct llvmpipe_resource *lpt = llvmpipe_resource(pt);
 
    assert(lpt->dt);
    if (!lpt->dt)
@@ -298,11 +301,10 @@ llvmpipe_texture_get_handle(struct pipe_screen *screen,
 
 static struct pipe_surface *
 llvmpipe_get_tex_surface(struct pipe_screen *screen,
-                         struct pipe_texture *pt,
+                         struct pipe_resource *pt,
                          unsigned face, unsigned level, unsigned zslice,
                          unsigned usage)
 {
-   struct llvmpipe_texture *lpt = llvmpipe_texture(pt);
    struct pipe_surface *ps;
 
    assert(level <= pt->last_level);
@@ -310,32 +312,12 @@ llvmpipe_get_tex_surface(struct pipe_screen *screen,
    ps = CALLOC_STRUCT(pipe_surface);
    if (ps) {
       pipe_reference_init(&ps->reference, 1);
-      pipe_texture_reference(&ps->texture, pt);
+      pipe_resource_reference(&ps->texture, pt);
       ps->format = pt->format;
       ps->width = u_minify(pt->width0, level);
       ps->height = u_minify(pt->height0, level);
       ps->usage = usage;
 
-      /* Because we are llvmpipe, anything that the state tracker
-       * thought was going to be done with the GPU will actually get
-       * done with the CPU.  Let's adjust the flags to take that into
-       * account.
-       */
-      if (ps->usage & PIPE_BUFFER_USAGE_GPU_WRITE) {
-         /* GPU_WRITE means "render" and that can involve reads (blending) */
-         ps->usage |= PIPE_BUFFER_USAGE_CPU_WRITE | PIPE_BUFFER_USAGE_CPU_READ;
-      }
-
-      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. */
-         lpt->timestamp++;
-         llvmpipe_screen(screen)->timestamp++;
-      }
-
       ps->face = face;
       ps->level = level;
       ps->zslice = zslice;
@@ -352,37 +334,32 @@ llvmpipe_tex_surface_destroy(struct pipe_surface *surf)
     * where it would happen.  For llvmpipe, nothing to do.
     */
    assert(surf->texture);
-   pipe_texture_reference(&surf->texture, NULL);
+   pipe_resource_reference(&surf->texture, NULL);
    FREE(surf);
 }
 
 
 static struct pipe_transfer *
-llvmpipe_get_tex_transfer(struct pipe_context *pipe,
-                          struct pipe_texture *texture,
-                          unsigned face, unsigned level, unsigned zslice,
-                          enum pipe_transfer_usage usage,
-                          unsigned x, unsigned y, unsigned w, unsigned h)
+llvmpipe_get_transfer(struct pipe_context *pipe,
+                     struct pipe_resource *resource,
+                     struct pipe_subresource sr,
+                     unsigned usage,
+                     const struct pipe_box *box)
 {
-   struct llvmpipe_texture *lptex = llvmpipe_texture(texture);
+   struct llvmpipe_resource *lptex = llvmpipe_resource(resource);
    struct llvmpipe_transfer *lpt;
 
-   assert(texture);
-   assert(level <= texture->last_level);
+   assert(resource);
+   assert(sr.level <= resource->last_level);
 
    lpt = CALLOC_STRUCT(llvmpipe_transfer);
    if (lpt) {
       struct pipe_transfer *pt = &lpt->base;
-      pipe_texture_reference(&pt->texture, texture);
-      pt->x = x;
-      pt->y = y;
-      pt->width = align(w, TILE_SIZE);
-      pt->height = align(h, TILE_SIZE);
-      pt->stride = lptex->stride[level];
+      pipe_resource_reference(&pt->resource, resource);
+      pt->box = *box;
+      pt->sr = sr;
+      pt->stride = lptex->stride[sr.level];
       pt->usage = usage;
-      pt->face = face;
-      pt->level = level;
-      pt->zslice = zslice;
 
       return pt;
    }
@@ -391,15 +368,15 @@ llvmpipe_get_tex_transfer(struct pipe_context *pipe,
 
 
 static void 
-llvmpipe_tex_transfer_destroy(struct pipe_context *pipe,
+llvmpipe_transfer_destroy(struct pipe_context *pipe,
                               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 llvmpipe, nothing to do.
     */
-   assert (transfer->texture);
-   pipe_texture_reference(&transfer->texture, NULL);
+   assert (transfer->resource);
+   pipe_resource_reference(&transfer->resource, NULL);
    FREE(transfer);
 }
 
@@ -410,11 +387,11 @@ llvmpipe_transfer_map( struct pipe_context *pipe,
 {
    struct llvmpipe_screen *screen = llvmpipe_screen(pipe->screen);
    ubyte *map;
-   struct llvmpipe_texture *lpt;
+   struct llvmpipe_resource *lpt;
    enum pipe_format format;
 
-   assert(transfer->texture);
-   lpt = llvmpipe_texture(transfer->texture);
+   assert(transfer->resource);
+   lpt = llvmpipe_resource(transfer->resource);
    format = lpt->base.format;
 
    /*
@@ -422,14 +399,19 @@ llvmpipe_transfer_map( struct pipe_context *pipe,
     * context if necessary.
     */
    llvmpipe_flush_texture(pipe,
-                          transfer->texture, transfer->face, transfer->level,
+                          transfer->resource,
+                         transfer->sr.face,
+                         transfer->sr.level,
                           0, /* flush_flags */
                           !(transfer->usage & PIPE_TRANSFER_WRITE), /* read_only */
                           TRUE, /* cpu_access */
                           FALSE); /* do_not_flush */
 
-   map = llvmpipe_texture_map(transfer->texture,
-                              transfer->face, transfer->level, transfer->zslice);
+   map = llvmpipe_resource_map(transfer->resource,
+                              transfer->usage,
+                              transfer->sr.face,
+                              transfer->sr.level,
+                              transfer->box.z);
 
    /* May want to different things here depending on read/write nature
     * of the map:
@@ -441,8 +423,8 @@ llvmpipe_transfer_map( struct pipe_context *pipe,
    }
    
    map +=
-      transfer->y / util_format_get_blockheight(format) * transfer->stride +
-      transfer->x / util_format_get_blockwidth(format) * util_format_get_blocksize(format);
+      transfer->box.y / util_format_get_blockheight(format) * transfer->stride +
+      transfer->box.x / util_format_get_blockwidth(format) * util_format_get_blocksize(format);
 
    return map;
 }
@@ -452,20 +434,68 @@ static void
 llvmpipe_transfer_unmap(struct pipe_context *pipe,
                         struct pipe_transfer *transfer)
 {
-   assert(transfer->texture);
+   assert(transfer->resource);
+
+   llvmpipe_resource_unmap(transfer->resource,
+                          transfer->sr.face,
+                          transfer->sr.level,
+                          transfer->box.z);
+}
+
+static unsigned int
+llvmpipe_is_resource_referenced( struct pipe_context *pipe,
+                               struct pipe_resource *presource,
+                               unsigned face, unsigned level)
+{
+   struct llvmpipe_context *llvmpipe = llvmpipe_context( pipe );
+
+   if (presource->target == PIPE_BUFFER)
+      return PIPE_UNREFERENCED;
+   
+   return lp_setup_is_resource_referenced(llvmpipe->setup, presource);
+}
+
+
+
+/**
+ * Create buffer which wraps user-space data.
+ */
+static struct pipe_resource *
+llvmpipe_user_buffer_create(struct pipe_screen *screen,
+                            void *ptr,
+                            unsigned bytes,
+                           unsigned bind_flags)
+{
+   struct llvmpipe_resource *buffer;
+
+   buffer = CALLOC_STRUCT(llvmpipe_resource);
+   if(!buffer)
+      return NULL;
 
-   llvmpipe_texture_unmap(transfer->texture,
-                          transfer->face, transfer->level, transfer->zslice);
+   pipe_reference_init(&buffer->base.reference, 1);
+   buffer->base.screen = screen;
+   buffer->base.format = PIPE_FORMAT_R8_UNORM; /* ?? */
+   buffer->base.bind = bind_flags;
+   buffer->base._usage = PIPE_USAGE_IMMUTABLE;
+   buffer->base.flags = 0;
+   buffer->base.width0 = bytes;
+   buffer->base.height0 = 1;
+   buffer->base.depth0 = 1;
+   buffer->userBuffer = TRUE;
+   buffer->data = ptr;
+
+   return &buffer->base;
 }
 
 
 void
-llvmpipe_init_screen_texture_funcs(struct pipe_screen *screen)
+llvmpipe_init_screen_resource_funcs(struct pipe_screen *screen)
 {
-   screen->texture_create = llvmpipe_texture_create;
-   screen->texture_destroy = llvmpipe_texture_destroy;
-   screen->texture_from_handle = llvmpipe_texture_from_handle;
-   screen->texture_get_handle = llvmpipe_texture_get_handle;
+   screen->resource_create = llvmpipe_resource_create;
+   screen->resource_destroy = llvmpipe_resource_destroy;
+   screen->resource_from_handle = llvmpipe_resource_from_handle;
+   screen->resource_get_handle = llvmpipe_resource_get_handle;
+   screen->user_buffer_create = llvmpipe_user_buffer_create;
 
    screen->get_tex_surface = llvmpipe_get_tex_surface;
    screen->tex_surface_destroy = llvmpipe_tex_surface_destroy;
@@ -473,10 +503,14 @@ llvmpipe_init_screen_texture_funcs(struct pipe_screen *screen)
 
 
 void
-llvmpipe_init_context_texture_funcs(struct pipe_context *pipe)
+llvmpipe_init_context_resource_funcs(struct pipe_context *pipe)
 {
-   pipe->get_tex_transfer = llvmpipe_get_tex_transfer;
-   pipe->tex_transfer_destroy = llvmpipe_tex_transfer_destroy;
+   pipe->get_transfer = llvmpipe_get_transfer;
+   pipe->transfer_destroy = llvmpipe_transfer_destroy;
    pipe->transfer_map = llvmpipe_transfer_map;
    pipe->transfer_unmap = llvmpipe_transfer_unmap;
+   pipe->is_resource_referenced = llvmpipe_is_resource_referenced;
+   pipe->transfer_flush_region = u_default_transfer_flush_region;
+   pipe->transfer_inline_write = u_default_transfer_inline_write;
 }