Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | RSS feed

  1. /*
  2.  * Copyright 2010 Jerome Glisse <glisse@freedesktop.org>
  3.  *
  4.  * Permission is hereby granted, free of charge, to any person obtaining a
  5.  * copy of this software and associated documentation files (the "Software"),
  6.  * to deal in the Software without restriction, including without limitation
  7.  * on the rights to use, copy, modify, merge, publish, distribute, sub
  8.  * license, and/or sell copies of the Software, and to permit persons to whom
  9.  * the Software is furnished to do so, subject to the following conditions:
  10.  *
  11.  * The above copyright notice and this permission notice (including the next
  12.  * paragraph) shall be included in all copies or substantial portions of the
  13.  * Software.
  14.  *
  15.  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  16.  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  17.  * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
  18.  * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
  19.  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
  20.  * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
  21.  * USE OR OTHER DEALINGS IN THE SOFTWARE.
  22.  *
  23.  * Authors:
  24.  *      Jerome Glisse
  25.  *      Corbin Simpson
  26.  */
  27. #include <errno.h>
  28. #include "pipe/p_screen.h"
  29. #include "util/u_format.h"
  30. #include "util/u_format_s3tc.h"
  31. #include "util/u_math.h"
  32. #include "util/u_inlines.h"
  33. #include "util/u_memory.h"
  34. #include "pipebuffer/pb_buffer.h"
  35. #include "radeonsi_pipe.h"
  36. #include "r600_resource.h"
  37. #include "sid.h"
  38.  
  39. /* Copy from a full GPU texture to a transfer's staging one. */
  40. static void r600_copy_to_staging_texture(struct pipe_context *ctx, struct r600_transfer *rtransfer)
  41. {
  42.         struct pipe_transfer *transfer = (struct pipe_transfer*)rtransfer;
  43.         struct pipe_resource *texture = transfer->resource;
  44.  
  45.         ctx->resource_copy_region(ctx, rtransfer->staging,
  46.                                 0, 0, 0, 0, texture, transfer->level,
  47.                                 &transfer->box);
  48. }
  49.  
  50. /* Copy from a transfer's staging texture to a full GPU one. */
  51. static void r600_copy_from_staging_texture(struct pipe_context *ctx, struct r600_transfer *rtransfer)
  52. {
  53.         struct pipe_transfer *transfer = (struct pipe_transfer*)rtransfer;
  54.         struct pipe_resource *texture = transfer->resource;
  55.         struct pipe_box sbox;
  56.  
  57.         u_box_3d(0, 0, 0, transfer->box.width, transfer->box.height, transfer->box.depth, &sbox);
  58.  
  59.         ctx->resource_copy_region(ctx, texture, transfer->level,
  60.                                   transfer->box.x, transfer->box.y, transfer->box.z,
  61.                                   rtransfer->staging,
  62.                                   0, &sbox);
  63. }
  64.  
  65. static unsigned r600_texture_get_offset(struct r600_resource_texture *rtex,
  66.                                         unsigned level, unsigned layer)
  67. {
  68.         return rtex->surface.level[level].offset +
  69.                layer * rtex->surface.level[level].slice_size;
  70. }
  71.  
  72. static int r600_init_surface(struct r600_screen *rscreen,
  73.                              struct radeon_surface *surface,
  74.                              const struct pipe_resource *ptex,
  75.                              unsigned array_mode,
  76.                              bool is_flushed_depth)
  77. {
  78.         const struct util_format_description *desc =
  79.                 util_format_description(ptex->format);
  80.         bool is_depth, is_stencil;
  81.  
  82.         is_depth = util_format_has_depth(desc);
  83.         is_stencil = util_format_has_stencil(desc);
  84.  
  85.         surface->npix_x = ptex->width0;
  86.         surface->npix_y = ptex->height0;
  87.         surface->npix_z = ptex->depth0;
  88.         surface->blk_w = util_format_get_blockwidth(ptex->format);
  89.         surface->blk_h = util_format_get_blockheight(ptex->format);
  90.         surface->blk_d = 1;
  91.         surface->array_size = 1;
  92.         surface->last_level = ptex->last_level;
  93.  
  94.         if (!is_flushed_depth &&
  95.             ptex->format == PIPE_FORMAT_Z32_FLOAT_S8X24_UINT) {
  96.                 surface->bpe = 4; /* stencil is allocated separately on evergreen */
  97.         } else {
  98.                 surface->bpe = util_format_get_blocksize(ptex->format);
  99.                 /* align byte per element on dword */
  100.                 if (surface->bpe == 3) {
  101.                         surface->bpe = 4;
  102.                 }
  103.         }
  104.  
  105.         surface->nsamples = 1;
  106.         surface->flags = 0;
  107.         switch (array_mode) {
  108.         case V_009910_ARRAY_1D_TILED_THIN1:
  109.                 surface->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_1D, MODE);
  110.                 break;
  111.         case V_009910_ARRAY_2D_TILED_THIN1:
  112.                 surface->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_2D, MODE);
  113.                 break;
  114.         case V_009910_ARRAY_LINEAR_ALIGNED:
  115.                 surface->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_LINEAR_ALIGNED, MODE);
  116.                 break;
  117.         case V_009910_ARRAY_LINEAR_GENERAL:
  118.         default:
  119.                 surface->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_LINEAR, MODE);
  120.                 break;
  121.         }
  122.         switch (ptex->target) {
  123.         case PIPE_TEXTURE_1D:
  124.                 surface->flags |= RADEON_SURF_SET(RADEON_SURF_TYPE_1D, TYPE);
  125.                 break;
  126.         case PIPE_TEXTURE_RECT:
  127.         case PIPE_TEXTURE_2D:
  128.                 surface->flags |= RADEON_SURF_SET(RADEON_SURF_TYPE_2D, TYPE);
  129.                 break;
  130.         case PIPE_TEXTURE_3D:
  131.                 surface->flags |= RADEON_SURF_SET(RADEON_SURF_TYPE_3D, TYPE);
  132.                 break;
  133.         case PIPE_TEXTURE_1D_ARRAY:
  134.                 surface->flags |= RADEON_SURF_SET(RADEON_SURF_TYPE_1D_ARRAY, TYPE);
  135.                 surface->array_size = ptex->array_size;
  136.                 break;
  137.         case PIPE_TEXTURE_2D_ARRAY:
  138.                 surface->flags |= RADEON_SURF_SET(RADEON_SURF_TYPE_2D_ARRAY, TYPE);
  139.                 surface->array_size = ptex->array_size;
  140.                 break;
  141.         case PIPE_TEXTURE_CUBE:
  142.                 surface->flags |= RADEON_SURF_SET(RADEON_SURF_TYPE_CUBEMAP, TYPE);
  143.                 break;
  144.         case PIPE_BUFFER:
  145.         default:
  146.                 return -EINVAL;
  147.         }
  148.         if (ptex->bind & PIPE_BIND_SCANOUT) {
  149.                 surface->flags |= RADEON_SURF_SCANOUT;
  150.         }
  151.  
  152.         if (!is_flushed_depth && is_depth) {
  153.                 surface->flags |= RADEON_SURF_ZBUFFER;
  154.                 if (is_stencil) {
  155.                         surface->flags |= RADEON_SURF_SBUFFER |
  156.                                 RADEON_SURF_HAS_SBUFFER_MIPTREE;
  157.                 }
  158.         }
  159.         surface->flags |= RADEON_SURF_HAS_TILE_MODE_INDEX;
  160.         return 0;
  161. }
  162.  
  163. static int r600_setup_surface(struct pipe_screen *screen,
  164.                               struct r600_resource_texture *rtex,
  165.                               unsigned array_mode,
  166.                               unsigned pitch_in_bytes_override)
  167. {
  168.         struct r600_screen *rscreen = (struct r600_screen*)screen;
  169.         int r;
  170.  
  171.         r = rscreen->ws->surface_init(rscreen->ws, &rtex->surface);
  172.         if (r) {
  173.                 return r;
  174.         }
  175.         if (pitch_in_bytes_override && pitch_in_bytes_override != rtex->surface.level[0].pitch_bytes) {
  176.                 /* old ddx on evergreen over estimate alignment for 1d, only 1 level
  177.                  * for those
  178.                  */
  179.                 rtex->surface.level[0].nblk_x = pitch_in_bytes_override / rtex->surface.bpe;
  180.                 rtex->surface.level[0].pitch_bytes = pitch_in_bytes_override;
  181.                 rtex->surface.level[0].slice_size = pitch_in_bytes_override * rtex->surface.level[0].nblk_y;
  182.                 if (rtex->surface.flags & RADEON_SURF_SBUFFER) {
  183.                         rtex->surface.stencil_offset =
  184.                         rtex->surface.stencil_level[0].offset = rtex->surface.level[0].slice_size;
  185.                 }
  186.         }
  187.         return 0;
  188. }
  189.  
  190. static boolean r600_texture_get_handle(struct pipe_screen* screen,
  191.                                         struct pipe_resource *ptex,
  192.                                         struct winsys_handle *whandle)
  193. {
  194.         struct r600_resource_texture *rtex = (struct r600_resource_texture*)ptex;
  195.         struct si_resource *resource = &rtex->resource;
  196.         struct radeon_surface *surface = &rtex->surface;
  197.         struct r600_screen *rscreen = (struct r600_screen*)screen;
  198.  
  199.         rscreen->ws->buffer_set_tiling(resource->buf,
  200.                                        NULL,
  201.                                        surface->level[0].mode >= RADEON_SURF_MODE_1D ?
  202.                                        RADEON_LAYOUT_TILED : RADEON_LAYOUT_LINEAR,
  203.                                        surface->level[0].mode >= RADEON_SURF_MODE_2D ?
  204.                                        RADEON_LAYOUT_TILED : RADEON_LAYOUT_LINEAR,
  205.                                        surface->bankw, surface->bankh,
  206.                                        surface->tile_split,
  207.                                        surface->stencil_tile_split,
  208.                                        surface->mtilea,
  209.                                        surface->level[0].pitch_bytes);
  210.  
  211.         return rscreen->ws->buffer_get_handle(resource->buf,
  212.                                               surface->level[0].pitch_bytes, whandle);
  213. }
  214.  
  215. static void r600_texture_destroy(struct pipe_screen *screen,
  216.                                  struct pipe_resource *ptex)
  217. {
  218.         struct r600_resource_texture *rtex = (struct r600_resource_texture*)ptex;
  219.         struct si_resource *resource = &rtex->resource;
  220.  
  221.         if (rtex->flushed_depth_texture)
  222.                 si_resource_reference((struct si_resource **)&rtex->flushed_depth_texture, NULL);
  223.  
  224.         pb_reference(&resource->buf, NULL);
  225.         FREE(rtex);
  226. }
  227.  
  228. static void *si_texture_transfer_map(struct pipe_context *ctx,
  229.                                      struct pipe_resource *texture,
  230.                                      unsigned level,
  231.                                      unsigned usage,
  232.                                      const struct pipe_box *box,
  233.                                      struct pipe_transfer **ptransfer)
  234. {
  235.         struct r600_context *rctx = (struct r600_context *)ctx;
  236.         struct r600_resource_texture *rtex = (struct r600_resource_texture*)texture;
  237.         struct r600_transfer *trans;
  238.         boolean use_staging_texture = FALSE;
  239.         struct radeon_winsys_cs_handle *buf;
  240.         enum pipe_format format = texture->format;
  241.         unsigned offset = 0;
  242.         char *map;
  243.  
  244.         /* We cannot map a tiled texture directly because the data is
  245.          * in a different order, therefore we do detiling using a blit.
  246.          *
  247.          * Also, use a temporary in GTT memory for read transfers, as
  248.          * the CPU is much happier reading out of cached system memory
  249.          * than uncached VRAM.
  250.          */
  251.         if (rtex->surface.level[level].mode != RADEON_SURF_MODE_LINEAR_ALIGNED &&
  252.             rtex->surface.level[level].mode != RADEON_SURF_MODE_LINEAR)
  253.                 use_staging_texture = TRUE;
  254.  
  255.         /* XXX: Use a staging texture for uploads if the underlying BO
  256.          * is busy.  No interface for checking that currently? so do
  257.          * it eagerly whenever the transfer doesn't require a readback
  258.          * and might block.
  259.          */
  260.         if ((usage & PIPE_TRANSFER_WRITE) &&
  261.                         !(usage & (PIPE_TRANSFER_READ |
  262.                                         PIPE_TRANSFER_DONTBLOCK |
  263.                                         PIPE_TRANSFER_UNSYNCHRONIZED)))
  264.                 use_staging_texture = TRUE;
  265.  
  266.         if (texture->flags & R600_RESOURCE_FLAG_TRANSFER)
  267.                 use_staging_texture = FALSE;
  268.  
  269.         if (use_staging_texture && (usage & PIPE_TRANSFER_MAP_DIRECTLY))
  270.                 return NULL;
  271.  
  272.         trans = CALLOC_STRUCT(r600_transfer);
  273.         if (trans == NULL)
  274.                 return NULL;
  275.         pipe_resource_reference(&trans->transfer.resource, texture);
  276.         trans->transfer.level = level;
  277.         trans->transfer.usage = usage;
  278.         trans->transfer.box = *box;
  279.         if (rtex->is_depth) {
  280.                 /* XXX: only readback the rectangle which is being mapped?
  281.                 */
  282.                 /* XXX: when discard is true, no need to read back from depth texture
  283.                 */
  284.                 struct r600_resource_texture *staging_depth;
  285.  
  286.                 if (!r600_init_flushed_depth_texture(ctx, texture, &staging_depth)) {
  287.                         R600_ERR("failed to create temporary texture to hold untiled copy\n");
  288.                         pipe_resource_reference(&trans->transfer.resource, NULL);
  289.                         FREE(trans);
  290.                         return NULL;
  291.                 }
  292.                 si_blit_uncompress_depth(ctx, rtex, staging_depth,
  293.                                          level, level,
  294.                                          box->z, box->z + box->depth - 1);
  295.                 trans->transfer.stride = staging_depth->surface.level[level].pitch_bytes;
  296.                 trans->transfer.layer_stride = staging_depth->surface.level[level].slice_size;
  297.                 trans->offset = r600_texture_get_offset(staging_depth, level, box->z);
  298.  
  299.                 trans->staging = &staging_depth->resource.b.b;
  300.         } else if (use_staging_texture) {
  301.                 struct pipe_resource resource;
  302.                 struct r600_resource_texture *staging;
  303.  
  304.                 memset(&resource, 0, sizeof(resource));
  305.                 resource.format = texture->format;
  306.                 resource.width0 = box->width;
  307.                 resource.height0 = box->height;
  308.                 resource.depth0 = 1;
  309.                 resource.array_size = 1;
  310.                 resource.usage = PIPE_USAGE_STAGING;
  311.                 resource.flags = R600_RESOURCE_FLAG_TRANSFER;
  312.  
  313.                 /* We must set the correct texture target and dimensions if needed for a 3D transfer. */
  314.                 if (box->depth > 1 && util_max_layer(texture, level) > 0)
  315.                         resource.target = texture->target;
  316.                 else
  317.                         resource.target = PIPE_TEXTURE_2D;
  318.  
  319.                 switch (resource.target) {
  320.                 case PIPE_TEXTURE_1D_ARRAY:
  321.                 case PIPE_TEXTURE_2D_ARRAY:
  322.                 case PIPE_TEXTURE_CUBE_ARRAY:
  323.                         resource.array_size = box->depth;
  324.                         break;
  325.                 case PIPE_TEXTURE_3D:
  326.                         resource.depth0 = box->depth;
  327.                         break;
  328.                 default:;
  329.                 }
  330.                 /* Create the temporary texture. */
  331.                 staging = (struct r600_resource_texture*)ctx->screen->resource_create(ctx->screen, &resource);
  332.                 if (staging == NULL) {
  333.                         R600_ERR("failed to create temporary texture to hold untiled copy\n");
  334.                         pipe_resource_reference(&trans->transfer.resource, NULL);
  335.                         FREE(trans);
  336.                         return NULL;
  337.                 }
  338.  
  339.                 trans->staging = &staging->resource.b.b;
  340.                 trans->transfer.stride = staging->surface.level[0].pitch_bytes;
  341.                 trans->transfer.layer_stride = staging->surface.level[0].slice_size;
  342.                 if (usage & PIPE_TRANSFER_READ) {
  343.                         r600_copy_to_staging_texture(ctx, trans);
  344.                         /* Always referenced in the blit. */
  345.                         radeonsi_flush(ctx, NULL, 0);
  346.                 }
  347.         } else {
  348.                 trans->transfer.stride = rtex->surface.level[level].pitch_bytes;
  349.                 trans->transfer.layer_stride = rtex->surface.level[level].slice_size;
  350.                 trans->offset = r600_texture_get_offset(rtex, level, box->z);
  351.         }
  352.  
  353.         if (trans->staging) {
  354.                 buf = si_resource(trans->staging)->cs_buf;
  355.         } else {
  356.                 buf = rtex->resource.cs_buf;
  357.         }
  358.  
  359.         if (rtex->is_depth || !trans->staging)
  360.                 offset = trans->offset +
  361.                         box->y / util_format_get_blockheight(format) * trans->transfer.stride +
  362.                         box->x / util_format_get_blockwidth(format) * util_format_get_blocksize(format);
  363.  
  364.         if (!(map = rctx->ws->buffer_map(buf, rctx->cs, usage))) {
  365.                 pipe_resource_reference(&trans->staging, NULL);
  366.                 pipe_resource_reference(&trans->transfer.resource, NULL);
  367.                 FREE(trans);
  368.                 return NULL;
  369.         }
  370.  
  371.         *ptransfer = &trans->transfer;
  372.         return map + offset;
  373. }
  374.  
  375. static void si_texture_transfer_unmap(struct pipe_context *ctx,
  376.                                       struct pipe_transfer* transfer)
  377. {
  378.         struct r600_transfer *rtransfer = (struct r600_transfer*)transfer;
  379.         struct r600_context *rctx = (struct r600_context*)ctx;
  380.         struct radeon_winsys_cs_handle *buf;
  381.         struct pipe_resource *texture = transfer->resource;
  382.         struct r600_resource_texture *rtex = (struct r600_resource_texture*)texture;
  383.  
  384.         if (rtransfer->staging) {
  385.                 buf = si_resource(rtransfer->staging)->cs_buf;
  386.         } else {
  387.                 buf = si_resource(transfer->resource)->cs_buf;
  388.         }
  389.         rctx->ws->buffer_unmap(buf);
  390.  
  391.         if ((transfer->usage & PIPE_TRANSFER_WRITE) && rtransfer->staging) {
  392.                 if (rtex->is_depth) {
  393.                         ctx->resource_copy_region(ctx, texture, transfer->level,
  394.                                                   transfer->box.x, transfer->box.y, transfer->box.z,
  395.                                                   &si_resource(rtransfer->staging)->b.b, transfer->level,
  396.                                                   &transfer->box);
  397.                 } else {
  398.                         r600_copy_from_staging_texture(ctx, rtransfer);
  399.                 }
  400.         }
  401.  
  402.         if (rtransfer->staging)
  403.                 pipe_resource_reference((struct pipe_resource**)&rtransfer->staging, NULL);
  404.  
  405.         pipe_resource_reference(&transfer->resource, NULL);
  406.         FREE(transfer);
  407. }
  408.  
  409. static const struct u_resource_vtbl r600_texture_vtbl =
  410. {
  411.         r600_texture_get_handle,        /* get_handle */
  412.         r600_texture_destroy,           /* resource_destroy */
  413.         si_texture_transfer_map,        /* transfer_map */
  414.         u_default_transfer_flush_region,/* transfer_flush_region */
  415.         si_texture_transfer_unmap,      /* transfer_unmap */
  416.         NULL    /* transfer_inline_write */
  417. };
  418.  
  419. DEBUG_GET_ONCE_BOOL_OPTION(print_texdepth, "RADEON_PRINT_TEXDEPTH", FALSE);
  420.  
  421. static struct r600_resource_texture *
  422. r600_texture_create_object(struct pipe_screen *screen,
  423.                            const struct pipe_resource *base,
  424.                            unsigned array_mode,
  425.                            unsigned pitch_in_bytes_override,
  426.                            unsigned max_buffer_size,
  427.                            struct pb_buffer *buf,
  428.                            boolean alloc_bo,
  429.                            struct radeon_surface *surface)
  430. {
  431.         struct r600_resource_texture *rtex;
  432.         struct si_resource *resource;
  433.         struct r600_screen *rscreen = (struct r600_screen*)screen;
  434.         int r;
  435.  
  436.         rtex = CALLOC_STRUCT(r600_resource_texture);
  437.         if (rtex == NULL)
  438.                 return NULL;
  439.  
  440.         resource = &rtex->resource;
  441.         resource->b.b = *base;
  442.         resource->b.vtbl = &r600_texture_vtbl;
  443.         pipe_reference_init(&resource->b.b.reference, 1);
  444.         resource->b.b.screen = screen;
  445.         rtex->pitch_override = pitch_in_bytes_override;
  446.         rtex->real_format = base->format;
  447.  
  448.         /* don't include stencil-only formats which we don't support for rendering */
  449.         rtex->is_depth = util_format_has_depth(util_format_description(rtex->resource.b.b.format));
  450.  
  451.         rtex->surface = *surface;
  452.         r = r600_setup_surface(screen, rtex, array_mode, pitch_in_bytes_override);
  453.         if (r) {
  454.                 FREE(rtex);
  455.                 return NULL;
  456.         }
  457.  
  458.         /* Now create the backing buffer. */
  459.         if (!buf && alloc_bo) {
  460.                 unsigned base_align = rtex->surface.bo_alignment;
  461.                 unsigned size = rtex->surface.bo_size;
  462.  
  463.                 base_align = rtex->surface.bo_alignment;
  464.                 if (!si_init_resource(rscreen, resource, size, base_align, FALSE, base->usage)) {
  465.                         FREE(rtex);
  466.                         return NULL;
  467.                 }
  468.         } else if (buf) {
  469.                 resource->buf = buf;
  470.                 resource->cs_buf = rscreen->ws->buffer_get_cs_handle(buf);
  471.                 resource->domains = RADEON_DOMAIN_GTT | RADEON_DOMAIN_VRAM;
  472.         }
  473.  
  474.         if (debug_get_option_print_texdepth() && rtex->is_depth) {
  475.                 printf("Texture: npix_x=%u, npix_y=%u, npix_z=%u, blk_w=%u, "
  476.                        "blk_h=%u, blk_d=%u, array_size=%u, last_level=%u, "
  477.                        "bpe=%u, nsamples=%u, flags=%u\n",
  478.                        rtex->surface.npix_x, rtex->surface.npix_y,
  479.                        rtex->surface.npix_z, rtex->surface.blk_w,
  480.                        rtex->surface.blk_h, rtex->surface.blk_d,
  481.                        rtex->surface.array_size, rtex->surface.last_level,
  482.                        rtex->surface.bpe, rtex->surface.nsamples,
  483.                        rtex->surface.flags);
  484.                 if (rtex->surface.flags & RADEON_SURF_ZBUFFER) {
  485.                         for (int i = 0; i <= rtex->surface.last_level; i++) {
  486.                                 printf("  Z %i: offset=%llu, slice_size=%llu, npix_x=%u, "
  487.                                        "npix_y=%u, npix_z=%u, nblk_x=%u, nblk_y=%u, "
  488.                                        "nblk_z=%u, pitch_bytes=%u, mode=%u\n",
  489.                                        i, rtex->surface.level[i].offset,
  490.                                        rtex->surface.level[i].slice_size,
  491.                                        rtex->surface.level[i].npix_x,
  492.                                        rtex->surface.level[i].npix_y,
  493.                                        rtex->surface.level[i].npix_z,
  494.                                        rtex->surface.level[i].nblk_x,
  495.                                        rtex->surface.level[i].nblk_y,
  496.                                        rtex->surface.level[i].nblk_z,
  497.                                        rtex->surface.level[i].pitch_bytes,
  498.                                        rtex->surface.level[i].mode);
  499.                         }
  500.                 }
  501.                 if (rtex->surface.flags & RADEON_SURF_SBUFFER) {
  502.                         for (int i = 0; i <= rtex->surface.last_level; i++) {
  503.                                 printf("  S %i: offset=%llu, slice_size=%llu, npix_x=%u, "
  504.                                        "npix_y=%u, npix_z=%u, nblk_x=%u, nblk_y=%u, "
  505.                                        "nblk_z=%u, pitch_bytes=%u, mode=%u\n",
  506.                                        i, rtex->surface.stencil_level[i].offset,
  507.                                        rtex->surface.stencil_level[i].slice_size,
  508.                                        rtex->surface.stencil_level[i].npix_x,
  509.                                        rtex->surface.stencil_level[i].npix_y,
  510.                                        rtex->surface.stencil_level[i].npix_z,
  511.                                        rtex->surface.stencil_level[i].nblk_x,
  512.                                        rtex->surface.stencil_level[i].nblk_y,
  513.                                        rtex->surface.stencil_level[i].nblk_z,
  514.                                        rtex->surface.stencil_level[i].pitch_bytes,
  515.                                        rtex->surface.stencil_level[i].mode);
  516.                         }
  517.                 }
  518.         }
  519.         return rtex;
  520. }
  521.  
  522. struct pipe_resource *si_texture_create(struct pipe_screen *screen,
  523.                                         const struct pipe_resource *templ)
  524. {
  525.         struct r600_screen *rscreen = (struct r600_screen*)screen;
  526.         struct radeon_surface surface;
  527.         unsigned array_mode = V_009910_ARRAY_LINEAR_ALIGNED;
  528.         int r;
  529.  
  530.         if (!(templ->flags & R600_RESOURCE_FLAG_TRANSFER) &&
  531.             !(templ->bind & PIPE_BIND_SCANOUT)) {
  532.                 if (util_format_is_compressed(templ->format)) {
  533.                         array_mode = V_009910_ARRAY_1D_TILED_THIN1;
  534.                 } else {
  535.                         if (rscreen->chip_class >= CIK)
  536.                                 array_mode = V_009910_ARRAY_1D_TILED_THIN1; /* XXX fix me */
  537.                         else
  538.                                 array_mode = V_009910_ARRAY_2D_TILED_THIN1;
  539.                 }
  540.         }
  541.  
  542.         r = r600_init_surface(rscreen, &surface, templ, array_mode,
  543.                               templ->flags & R600_RESOURCE_FLAG_FLUSHED_DEPTH);
  544.         if (r) {
  545.                 return NULL;
  546.         }
  547.         r = rscreen->ws->surface_best(rscreen->ws, &surface);
  548.         if (r) {
  549.                 return NULL;
  550.         }
  551.         return (struct pipe_resource *)r600_texture_create_object(screen, templ, array_mode,
  552.                                                                   0, 0, NULL, TRUE, &surface);
  553. }
  554.  
  555. static struct pipe_surface *r600_create_surface(struct pipe_context *pipe,
  556.                                                 struct pipe_resource *texture,
  557.                                                 const struct pipe_surface *surf_tmpl)
  558. {
  559.         struct r600_resource_texture *rtex = (struct r600_resource_texture*)texture;
  560.         struct r600_surface *surface = CALLOC_STRUCT(r600_surface);
  561.         unsigned level = surf_tmpl->u.tex.level;
  562.  
  563.         assert(surf_tmpl->u.tex.first_layer <= util_max_layer(texture, surf_tmpl->u.tex.level));
  564.         assert(surf_tmpl->u.tex.last_layer <= util_max_layer(texture, surf_tmpl->u.tex.level));
  565.         assert(surf_tmpl->u.tex.first_layer == surf_tmpl->u.tex.last_layer);
  566.         if (surface == NULL)
  567.                 return NULL;
  568.         /* XXX no offset */
  569. /*      offset = r600_texture_get_offset(rtex, level, surf_tmpl->u.tex.first_layer);*/
  570.         pipe_reference_init(&surface->base.reference, 1);
  571.         pipe_resource_reference(&surface->base.texture, texture);
  572.         surface->base.context = pipe;
  573.         surface->base.format = surf_tmpl->format;
  574.         surface->base.width = rtex->surface.level[level].npix_x;
  575.         surface->base.height = rtex->surface.level[level].npix_y;
  576.         surface->base.texture = texture;
  577.         surface->base.u.tex.first_layer = surf_tmpl->u.tex.first_layer;
  578.         surface->base.u.tex.last_layer = surf_tmpl->u.tex.last_layer;
  579.         surface->base.u.tex.level = level;
  580.  
  581.         return &surface->base;
  582. }
  583.  
  584. static void r600_surface_destroy(struct pipe_context *pipe,
  585.                                  struct pipe_surface *surface)
  586. {
  587.         pipe_resource_reference(&surface->texture, NULL);
  588.         FREE(surface);
  589. }
  590.  
  591. struct pipe_resource *si_texture_from_handle(struct pipe_screen *screen,
  592.                                              const struct pipe_resource *templ,
  593.                                              struct winsys_handle *whandle)
  594. {
  595.         struct r600_screen *rscreen = (struct r600_screen*)screen;
  596.         struct pb_buffer *buf = NULL;
  597.         unsigned stride = 0;
  598.         unsigned array_mode = V_009910_ARRAY_LINEAR_ALIGNED;
  599.         enum radeon_bo_layout micro, macro;
  600.         struct radeon_surface surface;
  601.         int r;
  602.  
  603.         /* Support only 2D textures without mipmaps */
  604.         if ((templ->target != PIPE_TEXTURE_2D && templ->target != PIPE_TEXTURE_RECT) ||
  605.               templ->depth0 != 1 || templ->last_level != 0)
  606.                 return NULL;
  607.  
  608.         buf = rscreen->ws->buffer_from_handle(rscreen->ws, whandle, &stride);
  609.         if (!buf)
  610.                 return NULL;
  611.  
  612.         rscreen->ws->buffer_get_tiling(buf, &micro, &macro,
  613.                                        &surface.bankw, &surface.bankh,
  614.                                        &surface.tile_split,
  615.                                        &surface.stencil_tile_split,
  616.                                        &surface.mtilea);
  617.  
  618.         if (macro == RADEON_LAYOUT_TILED)
  619.                 array_mode = V_009910_ARRAY_2D_TILED_THIN1;
  620.         else if (micro == RADEON_LAYOUT_TILED)
  621.                 array_mode = V_009910_ARRAY_1D_TILED_THIN1;
  622.         else
  623.                 array_mode = V_009910_ARRAY_LINEAR_ALIGNED;
  624.  
  625.         r = r600_init_surface(rscreen, &surface, templ, array_mode, false);
  626.         if (r) {
  627.                 return NULL;
  628.         }
  629.         /* always set the scanout flags */
  630.         surface.flags |= RADEON_SURF_SCANOUT;
  631.         return (struct pipe_resource *)r600_texture_create_object(screen, templ, array_mode,
  632.                                                                   stride, 0, buf, FALSE, &surface);
  633. }
  634.  
  635. bool r600_init_flushed_depth_texture(struct pipe_context *ctx,
  636.                                      struct pipe_resource *texture,
  637.                                      struct r600_resource_texture **staging)
  638. {
  639.         struct r600_resource_texture *rtex = (struct r600_resource_texture*)texture;
  640.         struct pipe_resource resource;
  641.         struct r600_resource_texture **flushed_depth_texture = staging ?
  642.                         staging : &rtex->flushed_depth_texture;
  643.  
  644.         if (!staging && rtex->flushed_depth_texture)
  645.                 return true; /* it's ready */
  646.  
  647.         resource.target = texture->target;
  648.         resource.format = texture->format;
  649.         resource.width0 = texture->width0;
  650.         resource.height0 = texture->height0;
  651.         resource.depth0 = texture->depth0;
  652.         resource.array_size = texture->array_size;
  653.         resource.last_level = texture->last_level;
  654.         resource.nr_samples = texture->nr_samples;
  655.         resource.usage = staging ? PIPE_USAGE_DYNAMIC : PIPE_USAGE_DEFAULT;
  656.         resource.bind = texture->bind & ~PIPE_BIND_DEPTH_STENCIL;
  657.         resource.flags = texture->flags | R600_RESOURCE_FLAG_FLUSHED_DEPTH;
  658.  
  659.         if (staging)
  660.                 resource.flags |= R600_RESOURCE_FLAG_TRANSFER;
  661.         else
  662.                 rtex->dirty_db_mask = (1 << (resource.last_level+1)) - 1;
  663.  
  664.         *flushed_depth_texture = (struct r600_resource_texture *)ctx->screen->resource_create(ctx->screen, &resource);
  665.         if (*flushed_depth_texture == NULL) {
  666.                 R600_ERR("failed to create temporary texture to hold flushed depth\n");
  667.                 return false;
  668.         }
  669.  
  670.         (*flushed_depth_texture)->is_flushing_texture = TRUE;
  671.         return true;
  672. }
  673.  
  674. void si_init_surface_functions(struct r600_context *r600)
  675. {
  676.         r600->context.create_surface = r600_create_surface;
  677.         r600->context.surface_destroy = r600_surface_destroy;
  678. }
  679.