Merge branch 'mesa_7_6_branch'
[mesa.git] / src / gallium / drivers / llvmpipe / lp_texture.c
index 1c1e015a32675372eb1fc972abd5fcd181798b4e..a00f2495dfc2dab39269f9f22d97c7a824a7b5e3 100644 (file)
 /* Simple, maximally packed layout.
  */
 
-static unsigned minify( unsigned d )
-{
-   return MAX2(1, d>>1);
-}
-
 
 /* Conventional allocation path for non-display textures:
  */
 static boolean
-llvmpipe_texture_layout(struct pipe_screen *screen,
+llvmpipe_texture_layout(struct llvmpipe_screen *screen,
                         struct llvmpipe_texture * lpt)
 {
    struct pipe_texture *pt = &lpt->base;
@@ -71,16 +66,24 @@ llvmpipe_texture_layout(struct pipe_screen *screen,
    pf_get_block(lpt->base.format, &lpt->base.block);
 
    for (level = 0; level <= pt->last_level; level++) {
+      unsigned nblocksx, nblocksy;
+
       pt->width[level] = width;
       pt->height[level] = height;
       pt->depth[level] = depth;
       pt->nblocksx[level] = pf_get_nblocksx(&pt->block, width);  
-      pt->nblocksy[level] = pf_get_nblocksy(&pt->block, height);  
-      lpt->stride[level] = pt->nblocksx[level]*pt->block.size;
+      pt->nblocksy[level] = pf_get_nblocksy(&pt->block, height);
+
+      /* Allocate storage for whole quads. This is particularly important
+       * for depth surfaces, which are currently stored in a swizzled format. */
+      nblocksx = pf_get_nblocksx(&pt->block, align(width, 2));
+      nblocksy = pf_get_nblocksy(&pt->block, align(height, 2));
+
+      lpt->stride[level] = align(nblocksx*pt->block.size, 16);
 
       lpt->level_offset[level] = buffer_size;
 
-      buffer_size += (pt->nblocksy[level] *
+      buffer_size += (nblocksy *
                       ((pt->target == PIPE_TEXTURE_CUBE) ? 6 : depth) *
                       lpt->stride[level]);
 
@@ -89,32 +92,29 @@ llvmpipe_texture_layout(struct pipe_screen *screen,
       depth = minify(depth);
    }
 
-   lpt->buffer = screen->buffer_create(screen, 32,
-                                       PIPE_BUFFER_USAGE_PIXEL,
-                                       buffer_size);
+   lpt->data = align_malloc(buffer_size, 16);
 
-   return lpt->buffer != NULL;
+   return lpt->data != NULL;
 }
 
 static boolean
-llvmpipe_displaytarget_layout(struct pipe_screen *screen,
+llvmpipe_displaytarget_layout(struct llvmpipe_screen *screen,
                               struct llvmpipe_texture * lpt)
 {
-   unsigned usage = (PIPE_BUFFER_USAGE_CPU_READ_WRITE |
-                     PIPE_BUFFER_USAGE_GPU_READ_WRITE);
+   struct llvmpipe_winsys *winsys = screen->winsys;
 
    pf_get_block(lpt->base.format, &lpt->base.block);
    lpt->base.nblocksx[0] = pf_get_nblocksx(&lpt->base.block, lpt->base.width[0]);  
    lpt->base.nblocksy[0] = pf_get_nblocksy(&lpt->base.block, lpt->base.height[0]);  
 
-   lpt->buffer = screen->surface_buffer_create( screen, 
-                                                lpt->base.width[0], 
-                                                lpt->base.height[0],
-                                                lpt->base.format,
-                                                usage,
-                                                &lpt->stride[0]);
+   lpt->dt = winsys->displaytarget_create(winsys,
+                                          lpt->base.format,
+                                          lpt->base.width[0],
+                                          lpt->base.height[0],
+                                          16,
+                                          &lpt->stride[0] );
 
-   return lpt->buffer != NULL;
+   return lpt->dt != NULL;
 }
 
 
@@ -122,18 +122,26 @@ llvmpipe_displaytarget_layout(struct pipe_screen *screen,
 
 
 static struct pipe_texture *
-llvmpipe_texture_create(struct pipe_screen *screen,
+llvmpipe_texture_create(struct pipe_screen *_screen,
                         const struct pipe_texture *templat)
 {
+   struct llvmpipe_screen *screen = llvmpipe_screen(_screen);
    struct llvmpipe_texture *lpt = CALLOC_STRUCT(llvmpipe_texture);
    if (!lpt)
       return NULL;
 
    lpt->base = *templat;
    pipe_reference_init(&lpt->base.reference, 1);
-   lpt->base.screen = screen;
+   lpt->base.screen = &screen->base;
+
+   /* XXX: The xlib state tracker is brain-dead and will request
+    * PIPE_FORMAT_Z16_UNORM no matter how much we tell it we don't support it.
+    */
+   if(lpt->base.format == PIPE_FORMAT_Z16_UNORM)
+      lpt->base.format = PIPE_FORMAT_Z32_UNORM;
 
-   if (lpt->base.tex_usage & PIPE_TEXTURE_USAGE_DISPLAY_TARGET) {
+   if (lpt->base.tex_usage & (PIPE_TEXTURE_USAGE_DISPLAY_TARGET |
+                              PIPE_TEXTURE_USAGE_PRIMARY)) {
       if (!llvmpipe_displaytarget_layout(screen, lpt))
          goto fail;
    }
@@ -156,6 +164,8 @@ llvmpipe_texture_blanket(struct pipe_screen * screen,
                          const unsigned *stride,
                          struct pipe_buffer *buffer)
 {
+   /* FIXME */
+#if 0
    struct llvmpipe_texture *lpt;
    assert(screen);
 
@@ -180,15 +190,25 @@ llvmpipe_texture_blanket(struct pipe_screen * screen,
    pipe_buffer_reference(&lpt->buffer, buffer);
 
    return &lpt->base;
+#else
+   return NULL;
+#endif
 }
 
 
 static void
 llvmpipe_texture_destroy(struct pipe_texture *pt)
 {
+   struct llvmpipe_screen *screen = llvmpipe_screen(pt->screen);
    struct llvmpipe_texture *lpt = llvmpipe_texture(pt);
 
-   pipe_buffer_reference(&lpt->buffer, NULL);
+   if(lpt->dt) {
+      struct llvmpipe_winsys *winsys = screen->winsys;
+      winsys->displaytarget_destroy(winsys, lpt->dt);
+   }
+   else
+      align_free(lpt->data);
+
    FREE(lpt);
 }
 
@@ -329,37 +349,36 @@ llvmpipe_tex_transfer_destroy(struct pipe_transfer *transfer)
 
 
 static void *
-llvmpipe_transfer_map( struct pipe_screen *screen,
+llvmpipe_transfer_map( struct pipe_screen *_screen,
                        struct pipe_transfer *transfer )
 {
+   struct llvmpipe_screen *screen = llvmpipe_screen(_screen);
    ubyte *map, *xfer_map;
    struct llvmpipe_texture *lpt;
-   unsigned flags = 0;
 
    assert(transfer->texture);
    lpt = llvmpipe_texture(transfer->texture);
 
-   if (transfer->usage != PIPE_TRANSFER_READ) {
-      flags |= PIPE_BUFFER_USAGE_CPU_WRITE;
-   }
+   if(lpt->dt) {
+      struct llvmpipe_winsys *winsys = screen->winsys;
 
-   if (transfer->usage != PIPE_TRANSFER_WRITE) {
-      flags |= PIPE_BUFFER_USAGE_CPU_READ;
+      map = winsys->displaytarget_map(winsys, lpt->dt,
+                                      pipe_transfer_buffer_flags(transfer));
+      if (map == NULL)
+         return NULL;
    }
-
-   map = pipe_buffer_map(screen, lpt->buffer, flags);
-   if (map == NULL)
-      return NULL;
+   else
+      map = lpt->data;
 
    /* May want to different things here depending on read/write nature
     * of the map:
     */
-   if (transfer->texture && transfer->usage != PIPE_TRANSFER_READ) 
+   if (transfer->texture && (transfer->usage & PIPE_TRANSFER_WRITE))
    {
       /* Do something to notify sharing contexts of a texture change.
        * In llvmpipe, that would mean flushing the texture cache.
        */
-      llvmpipe_screen(screen)->timestamp++;
+      screen->timestamp++;
    }
    
    xfer_map = map + llvmpipe_transfer(transfer)->offset +
@@ -371,15 +390,19 @@ llvmpipe_transfer_map( struct pipe_screen *screen,
 
 
 static void
-llvmpipe_transfer_unmap(struct pipe_screen *screen,
+llvmpipe_transfer_unmap(struct pipe_screen *_screen,
                        struct pipe_transfer *transfer)
 {
+   struct llvmpipe_screen *screen = llvmpipe_screen(_screen);
    struct llvmpipe_texture *lpt;
 
    assert(transfer->texture);
    lpt = llvmpipe_texture(transfer->texture);
 
-   pipe_buffer_unmap( screen, lpt->buffer );
+   if(lpt->dt) {
+      struct llvmpipe_winsys *winsys = screen->winsys;
+      winsys->displaytarget_unmap(winsys, lpt->dt);
+   }
 }
 
 
@@ -404,22 +427,3 @@ llvmpipe_init_screen_texture_funcs(struct pipe_screen *screen)
    screen->transfer_map = llvmpipe_transfer_map;
    screen->transfer_unmap = llvmpipe_transfer_unmap;
 }
-
-
-boolean
-llvmpipe_get_texture_buffer( struct pipe_texture *texture,
-                             struct pipe_buffer **buf,
-                             unsigned *stride )
-{
-   struct llvmpipe_texture *tex = (struct llvmpipe_texture *)texture;
-
-   if (!tex)
-      return FALSE;
-
-   pipe_buffer_reference(buf, tex->buffer);
-
-   if (stride)
-      *stride = tex->stride[0];
-
-   return TRUE;
-}