Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  1. /* -*- mode: C; c-file-style: "k&r"; tab-width 4; indent-tabs-mode: t; -*- */
  2.  
  3. /*
  4.  * Copyright (C) 2012 Rob Clark <robclark@freedesktop.org>
  5.  *
  6.  * Permission is hereby granted, free of charge, to any person obtaining a
  7.  * copy of this software and associated documentation files (the "Software"),
  8.  * to deal in the Software without restriction, including without limitation
  9.  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  10.  * and/or sell copies of the Software, and to permit persons to whom the
  11.  * Software is furnished to do so, subject to the following conditions:
  12.  *
  13.  * The above copyright notice and this permission notice (including the next
  14.  * paragraph) shall be included in all copies or substantial portions of the
  15.  * Software.
  16.  *
  17.  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  18.  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  19.  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  20.  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  21.  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  22.  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  23.  * SOFTWARE.
  24.  *
  25.  * Authors:
  26.  *    Rob Clark <robclark@freedesktop.org>
  27.  */
  28.  
  29. #include "util/u_format.h"
  30. #include "util/u_format_zs.h"
  31. #include "util/u_inlines.h"
  32. #include "util/u_transfer.h"
  33. #include "util/u_string.h"
  34. #include "util/u_surface.h"
  35.  
  36. #include "freedreno_resource.h"
  37. #include "freedreno_screen.h"
  38. #include "freedreno_surface.h"
  39. #include "freedreno_context.h"
  40. #include "freedreno_query_hw.h"
  41. #include "freedreno_util.h"
  42.  
  43. #include <errno.h>
  44.  
  45. static void
  46. fd_invalidate_resource(struct fd_context *ctx, struct pipe_resource *prsc)
  47. {
  48.         int i;
  49.  
  50.         /* Go through the entire state and see if the resource is bound
  51.          * anywhere. If it is, mark the relevant state as dirty. This is called on
  52.          * realloc_bo.
  53.          */
  54.  
  55.         /* Constbufs */
  56.         for (i = 1; i < PIPE_MAX_CONSTANT_BUFFERS && !(ctx->dirty & FD_DIRTY_CONSTBUF); i++) {
  57.                 if (ctx->constbuf[PIPE_SHADER_VERTEX].cb[i].buffer == prsc)
  58.                         ctx->dirty |= FD_DIRTY_CONSTBUF;
  59.                 if (ctx->constbuf[PIPE_SHADER_FRAGMENT].cb[i].buffer == prsc)
  60.                         ctx->dirty |= FD_DIRTY_CONSTBUF;
  61.         }
  62.  
  63.         /* VBOs */
  64.         for (i = 0; i < ctx->vtx.vertexbuf.count && !(ctx->dirty & FD_DIRTY_VTXBUF); i++) {
  65.                 if (ctx->vtx.vertexbuf.vb[i].buffer == prsc)
  66.                         ctx->dirty |= FD_DIRTY_VTXBUF;
  67.         }
  68.  
  69.         /* Index buffer */
  70.         if (ctx->indexbuf.buffer == prsc)
  71.                 ctx->dirty |= FD_DIRTY_INDEXBUF;
  72.  
  73.         /* Textures */
  74.         for (i = 0; i < ctx->verttex.num_textures && !(ctx->dirty & FD_DIRTY_VERTTEX); i++) {
  75.                 if (ctx->verttex.textures[i]->texture == prsc)
  76.                         ctx->dirty |= FD_DIRTY_VERTTEX;
  77.         }
  78.         for (i = 0; i < ctx->fragtex.num_textures && !(ctx->dirty & FD_DIRTY_FRAGTEX); i++) {
  79.                 if (ctx->fragtex.textures[i]->texture == prsc)
  80.                         ctx->dirty |= FD_DIRTY_FRAGTEX;
  81.         }
  82. }
  83.  
  84. static void
  85. realloc_bo(struct fd_resource *rsc, uint32_t size)
  86. {
  87.         struct fd_screen *screen = fd_screen(rsc->base.b.screen);
  88.         uint32_t flags = DRM_FREEDRENO_GEM_CACHE_WCOMBINE |
  89.                         DRM_FREEDRENO_GEM_TYPE_KMEM; /* TODO */
  90.  
  91.         /* if we start using things other than write-combine,
  92.          * be sure to check for PIPE_RESOURCE_FLAG_MAP_COHERENT
  93.          */
  94.  
  95.         if (rsc->bo)
  96.                 fd_bo_del(rsc->bo);
  97.  
  98.         rsc->bo = fd_bo_new(screen->dev, size, flags);
  99.         rsc->timestamp = 0;
  100.         rsc->dirty = rsc->reading = false;
  101.         list_delinit(&rsc->list);
  102.         util_range_set_empty(&rsc->valid_buffer_range);
  103. }
  104.  
  105. /* Currently this is only used for flushing Z32_S8 texture transfers, but
  106.  * eventually it should handle everything.
  107.  */
  108. static void
  109. fd_resource_flush(struct fd_transfer *trans, const struct pipe_box *box)
  110. {
  111.         struct fd_resource *rsc = fd_resource(trans->base.resource);
  112.         struct fd_resource_slice *slice = fd_resource_slice(rsc, trans->base.level);
  113.         struct fd_resource_slice *sslice = fd_resource_slice(rsc->stencil, trans->base.level);
  114.         enum pipe_format format = trans->base.resource->format;
  115.  
  116.         float *depth = fd_bo_map(rsc->bo) + slice->offset +
  117.                 (trans->base.box.y + box->y) * slice->pitch * 4 + (trans->base.box.x + box->x) * 4;
  118.         uint8_t *stencil = fd_bo_map(rsc->stencil->bo) + sslice->offset +
  119.                 (trans->base.box.y + box->y) * sslice->pitch + trans->base.box.x + box->x;
  120.  
  121.         assert(format == PIPE_FORMAT_Z32_FLOAT_S8X24_UINT ||
  122.                    format == PIPE_FORMAT_X32_S8X24_UINT);
  123.  
  124.         if (format != PIPE_FORMAT_X32_S8X24_UINT)
  125.                 util_format_z32_float_s8x24_uint_unpack_z_float(
  126.                                 depth, slice->pitch * 4,
  127.                                 trans->staging, trans->base.stride,
  128.                                 box->width, box->height);
  129.  
  130.         util_format_z32_float_s8x24_uint_unpack_s_8uint(
  131.                         stencil, sslice->pitch,
  132.                         trans->staging, trans->base.stride,
  133.                         box->width, box->height);
  134. }
  135.  
  136. static void fd_resource_transfer_flush_region(struct pipe_context *pctx,
  137.                 struct pipe_transfer *ptrans,
  138.                 const struct pipe_box *box)
  139. {
  140.         struct fd_resource *rsc = fd_resource(ptrans->resource);
  141.         struct fd_transfer *trans = fd_transfer(ptrans);
  142.  
  143.         if (ptrans->resource->target == PIPE_BUFFER)
  144.                 util_range_add(&rsc->valid_buffer_range,
  145.                                            ptrans->box.x + box->x,
  146.                                            ptrans->box.x + box->x + box->width);
  147.  
  148.         if (trans->staging)
  149.                 fd_resource_flush(trans, box);
  150. }
  151.  
  152. static void
  153. fd_resource_transfer_unmap(struct pipe_context *pctx,
  154.                 struct pipe_transfer *ptrans)
  155. {
  156.         struct fd_context *ctx = fd_context(pctx);
  157.         struct fd_resource *rsc = fd_resource(ptrans->resource);
  158.         struct fd_transfer *trans = fd_transfer(ptrans);
  159.  
  160.         if (trans->staging && !(ptrans->usage & PIPE_TRANSFER_FLUSH_EXPLICIT)) {
  161.                 struct pipe_box box;
  162.                 u_box_2d(0, 0, ptrans->box.width, ptrans->box.height, &box);
  163.                 fd_resource_flush(trans, &box);
  164.         }
  165.  
  166.         if (!(ptrans->usage & PIPE_TRANSFER_UNSYNCHRONIZED)) {
  167.                 fd_bo_cpu_fini(rsc->bo);
  168.                 if (rsc->stencil)
  169.                         fd_bo_cpu_fini(rsc->stencil->bo);
  170.         }
  171.  
  172.         util_range_add(&rsc->valid_buffer_range,
  173.                                    ptrans->box.x,
  174.                                    ptrans->box.x + ptrans->box.width);
  175.  
  176.         pipe_resource_reference(&ptrans->resource, NULL);
  177.         util_slab_free(&ctx->transfer_pool, ptrans);
  178.  
  179.         if (trans->staging)
  180.                 free(trans->staging);
  181. }
  182.  
  183. static void *
  184. fd_resource_transfer_map(struct pipe_context *pctx,
  185.                 struct pipe_resource *prsc,
  186.                 unsigned level, unsigned usage,
  187.                 const struct pipe_box *box,
  188.                 struct pipe_transfer **pptrans)
  189. {
  190.         struct fd_context *ctx = fd_context(pctx);
  191.         struct fd_resource *rsc = fd_resource(prsc);
  192.         struct fd_resource_slice *slice = fd_resource_slice(rsc, level);
  193.         struct fd_transfer *trans;
  194.         struct pipe_transfer *ptrans;
  195.         enum pipe_format format = prsc->format;
  196.         uint32_t op = 0;
  197.         uint32_t offset;
  198.         char *buf;
  199.         int ret = 0;
  200.  
  201.         DBG("prsc=%p, level=%u, usage=%x, box=%dx%d+%d,%d", prsc, level, usage,
  202.                 box->width, box->height, box->x, box->y);
  203.  
  204.         ptrans = util_slab_alloc(&ctx->transfer_pool);
  205.         if (!ptrans)
  206.                 return NULL;
  207.  
  208.         /* util_slab_alloc() doesn't zero: */
  209.         trans = fd_transfer(ptrans);
  210.         memset(trans, 0, sizeof(*trans));
  211.  
  212.         pipe_resource_reference(&ptrans->resource, prsc);
  213.         ptrans->level = level;
  214.         ptrans->usage = usage;
  215.         ptrans->box = *box;
  216.         ptrans->stride = slice->pitch * rsc->cpp;
  217.         ptrans->layer_stride = slice->size0;
  218.  
  219.         if (usage & PIPE_TRANSFER_READ)
  220.                 op |= DRM_FREEDRENO_PREP_READ;
  221.  
  222.         if (usage & PIPE_TRANSFER_WRITE)
  223.                 op |= DRM_FREEDRENO_PREP_WRITE;
  224.  
  225.         if (usage & PIPE_TRANSFER_DISCARD_WHOLE_RESOURCE) {
  226.                 realloc_bo(rsc, fd_bo_size(rsc->bo));
  227.                 if (rsc->stencil)
  228.                         realloc_bo(rsc->stencil, fd_bo_size(rsc->stencil->bo));
  229.                 fd_invalidate_resource(ctx, prsc);
  230.         } else if ((usage & PIPE_TRANSFER_WRITE) &&
  231.                            prsc->target == PIPE_BUFFER &&
  232.                            !util_ranges_intersect(&rsc->valid_buffer_range,
  233.                                                                           box->x, box->x + box->width)) {
  234.                 /* We are trying to write to a previously uninitialized range. No need
  235.                  * to wait.
  236.                  */
  237.         } else if (!(usage & PIPE_TRANSFER_UNSYNCHRONIZED)) {
  238.                 /* If the GPU is writing to the resource, or if it is reading from the
  239.                  * resource and we're trying to write to it, flush the renders.
  240.                  */
  241.                 if (rsc->dirty || (rsc->stencil && rsc->stencil->dirty) ||
  242.                         ((ptrans->usage & PIPE_TRANSFER_WRITE) && rsc->reading))
  243.                         fd_context_render(pctx);
  244.  
  245.                 /* The GPU keeps track of how the various bo's are being used, and
  246.                  * will wait if necessary for the proper operation to have
  247.                  * completed.
  248.                  */
  249.                 ret = fd_bo_cpu_prep(rsc->bo, ctx->screen->pipe, op);
  250.                 if (ret)
  251.                         goto fail;
  252.         }
  253.  
  254.         buf = fd_bo_map(rsc->bo);
  255.         if (!buf) {
  256.                 fd_resource_transfer_unmap(pctx, ptrans);
  257.                 return NULL;
  258.         }
  259.  
  260.         if (rsc->layer_first) {
  261.                 offset = slice->offset +
  262.                         box->y / util_format_get_blockheight(format) * ptrans->stride +
  263.                         box->x / util_format_get_blockwidth(format) * rsc->cpp +
  264.                         box->z * rsc->layer_size;
  265.         } else {
  266.                 offset = slice->offset +
  267.                         box->y / util_format_get_blockheight(format) * ptrans->stride +
  268.                         box->x / util_format_get_blockwidth(format) * rsc->cpp +
  269.                         box->z * slice->size0;
  270.         }
  271.  
  272.         if (prsc->format == PIPE_FORMAT_Z32_FLOAT_S8X24_UINT ||
  273.                 prsc->format == PIPE_FORMAT_X32_S8X24_UINT) {
  274.                 trans->base.stride = trans->base.box.width * rsc->cpp * 2;
  275.                 trans->staging = malloc(trans->base.stride * trans->base.box.height);
  276.                 if (!trans->staging)
  277.                         goto fail;
  278.  
  279.                 /* if we're not discarding the whole range (or resource), we must copy
  280.                  * the real data in.
  281.                  */
  282.                 if (!(usage & (PIPE_TRANSFER_DISCARD_WHOLE_RESOURCE |
  283.                                            PIPE_TRANSFER_DISCARD_RANGE))) {
  284.                         struct fd_resource_slice *sslice =
  285.                                 fd_resource_slice(rsc->stencil, level);
  286.                         void *sbuf = fd_bo_map(rsc->stencil->bo);
  287.                         if (!sbuf)
  288.                                 goto fail;
  289.  
  290.                         float *depth = (float *)(buf + slice->offset +
  291.                                 box->y * slice->pitch * 4 + box->x * 4);
  292.                         uint8_t *stencil = sbuf + sslice->offset +
  293.                                 box->y * sslice->pitch + box->x;
  294.  
  295.                         if (format != PIPE_FORMAT_X32_S8X24_UINT)
  296.                                 util_format_z32_float_s8x24_uint_pack_z_float(
  297.                                                 trans->staging, trans->base.stride,
  298.                                                 depth, slice->pitch * 4,
  299.                                                 box->width, box->height);
  300.  
  301.                         util_format_z32_float_s8x24_uint_pack_s_8uint(
  302.                                         trans->staging, trans->base.stride,
  303.                                         stencil, sslice->pitch,
  304.                                         box->width, box->height);
  305.                 }
  306.  
  307.                 buf = trans->staging;
  308.                 offset = 0;
  309.         }
  310.  
  311.         *pptrans = ptrans;
  312.  
  313.         return buf + offset;
  314.  
  315. fail:
  316.         fd_resource_transfer_unmap(pctx, ptrans);
  317.         return NULL;
  318. }
  319.  
  320. static void
  321. fd_resource_destroy(struct pipe_screen *pscreen,
  322.                 struct pipe_resource *prsc)
  323. {
  324.         struct fd_resource *rsc = fd_resource(prsc);
  325.         if (rsc->bo)
  326.                 fd_bo_del(rsc->bo);
  327.         list_delinit(&rsc->list);
  328.         util_range_destroy(&rsc->valid_buffer_range);
  329.         FREE(rsc);
  330. }
  331.  
  332. static boolean
  333. fd_resource_get_handle(struct pipe_screen *pscreen,
  334.                 struct pipe_resource *prsc,
  335.                 struct winsys_handle *handle)
  336. {
  337.         struct fd_resource *rsc = fd_resource(prsc);
  338.  
  339.         return fd_screen_bo_get_handle(pscreen, rsc->bo,
  340.                         rsc->slices[0].pitch * rsc->cpp, handle);
  341. }
  342.  
  343.  
  344. static const struct u_resource_vtbl fd_resource_vtbl = {
  345.                 .resource_get_handle      = fd_resource_get_handle,
  346.                 .resource_destroy         = fd_resource_destroy,
  347.                 .transfer_map             = fd_resource_transfer_map,
  348.                 .transfer_flush_region    = fd_resource_transfer_flush_region,
  349.                 .transfer_unmap           = fd_resource_transfer_unmap,
  350.                 .transfer_inline_write    = u_default_transfer_inline_write,
  351. };
  352.  
  353. static uint32_t
  354. setup_slices(struct fd_resource *rsc, uint32_t alignment)
  355. {
  356.         struct pipe_resource *prsc = &rsc->base.b;
  357.         uint32_t level, size = 0;
  358.         uint32_t width = prsc->width0;
  359.         uint32_t height = prsc->height0;
  360.         uint32_t depth = prsc->depth0;
  361.         /* in layer_first layout, the level (slice) contains just one
  362.          * layer (since in fact the layer contains the slices)
  363.          */
  364.         uint32_t layers_in_level = rsc->layer_first ? 1 : prsc->array_size;
  365.  
  366.         for (level = 0; level <= prsc->last_level; level++) {
  367.                 struct fd_resource_slice *slice = fd_resource_slice(rsc, level);
  368.  
  369.                 slice->pitch = width = align(width, 32);
  370.                 slice->offset = size;
  371.                 /* 1d array and 2d array textures must all have the same layer size
  372.                  * for each miplevel on a3xx. 3d textures can have different layer
  373.                  * sizes for high levels, but the hw auto-sizer is buggy (or at least
  374.                  * different than what this code does), so as soon as the layer size
  375.                  * range gets into range, we stop reducing it.
  376.                  */
  377.                 if (prsc->target == PIPE_TEXTURE_3D && (
  378.                                         level == 1 ||
  379.                                         (level > 1 && rsc->slices[level - 1].size0 > 0xf000)))
  380.                         slice->size0 = align(slice->pitch * height * rsc->cpp, alignment);
  381.                 else if (level == 0 || rsc->layer_first || alignment == 1)
  382.                         slice->size0 = align(slice->pitch * height * rsc->cpp, alignment);
  383.                 else
  384.                         slice->size0 = rsc->slices[level - 1].size0;
  385.  
  386.                 size += slice->size0 * depth * layers_in_level;
  387.  
  388.                 width = u_minify(width, 1);
  389.                 height = u_minify(height, 1);
  390.                 depth = u_minify(depth, 1);
  391.         }
  392.  
  393.         return size;
  394. }
  395.  
  396. static uint32_t
  397. slice_alignment(struct pipe_screen *pscreen, const struct pipe_resource *tmpl)
  398. {
  399.         /* on a3xx, 2d array and 3d textures seem to want their
  400.          * layers aligned to page boundaries:
  401.          */
  402.         switch (tmpl->target) {
  403.         case PIPE_TEXTURE_3D:
  404.         case PIPE_TEXTURE_1D_ARRAY:
  405.         case PIPE_TEXTURE_2D_ARRAY:
  406.                 return 4096;
  407.         default:
  408.                 return 1;
  409.         }
  410. }
  411.  
  412. /**
  413.  * Create a new texture object, using the given template info.
  414.  */
  415. static struct pipe_resource *
  416. fd_resource_create(struct pipe_screen *pscreen,
  417.                 const struct pipe_resource *tmpl)
  418. {
  419.         struct fd_resource *rsc = CALLOC_STRUCT(fd_resource);
  420.         struct pipe_resource *prsc = &rsc->base.b;
  421.         uint32_t size;
  422.  
  423.         DBG("target=%d, format=%s, %ux%ux%u, array_size=%u, last_level=%u, "
  424.                         "nr_samples=%u, usage=%u, bind=%x, flags=%x",
  425.                         tmpl->target, util_format_name(tmpl->format),
  426.                         tmpl->width0, tmpl->height0, tmpl->depth0,
  427.                         tmpl->array_size, tmpl->last_level, tmpl->nr_samples,
  428.                         tmpl->usage, tmpl->bind, tmpl->flags);
  429.  
  430.         if (!rsc)
  431.                 return NULL;
  432.  
  433.         *prsc = *tmpl;
  434.  
  435.         pipe_reference_init(&prsc->reference, 1);
  436.         list_inithead(&rsc->list);
  437.         prsc->screen = pscreen;
  438.  
  439.         util_range_init(&rsc->valid_buffer_range);
  440.  
  441.         rsc->base.vtbl = &fd_resource_vtbl;
  442.         if (tmpl->format == PIPE_FORMAT_Z32_FLOAT_S8X24_UINT)
  443.                 rsc->cpp = util_format_get_blocksize(PIPE_FORMAT_Z32_FLOAT);
  444.         else
  445.                 rsc->cpp = util_format_get_blocksize(tmpl->format);
  446.  
  447.         assert(rsc->cpp);
  448.  
  449.         if (is_a4xx(fd_screen(pscreen))) {
  450.                 switch (tmpl->target) {
  451.                 case PIPE_TEXTURE_3D:
  452.                         /* TODO 3D_ARRAY? */
  453.                         rsc->layer_first = false;
  454.                         break;
  455.                 default:
  456.                         rsc->layer_first = true;
  457.                         break;
  458.                 }
  459.         }
  460.  
  461.         size = setup_slices(rsc, slice_alignment(pscreen, tmpl));
  462.  
  463.         if (rsc->layer_first) {
  464.                 rsc->layer_size = align(size, 4096);
  465.                 size = rsc->layer_size * prsc->array_size;
  466.         }
  467.  
  468.         realloc_bo(rsc, size);
  469.         if (!rsc->bo)
  470.                 goto fail;
  471.  
  472.         /* There is no native Z32F_S8 sampling or rendering format, so this must
  473.          * be emulated via two separate textures. The depth texture still keeps
  474.          * its Z32F_S8 format though, and we also keep a reference to a separate
  475.          * S8 texture.
  476.          */
  477.         if (tmpl->format == PIPE_FORMAT_Z32_FLOAT_S8X24_UINT) {
  478.                 struct pipe_resource stencil = *tmpl;
  479.                 stencil.format = PIPE_FORMAT_S8_UINT;
  480.                 rsc->stencil = fd_resource(fd_resource_create(pscreen, &stencil));
  481.                 if (!rsc->stencil)
  482.                         goto fail;
  483.         }
  484.  
  485.         return prsc;
  486. fail:
  487.         fd_resource_destroy(pscreen, prsc);
  488.         return NULL;
  489. }
  490.  
  491. /**
  492.  * Create a texture from a winsys_handle. The handle is often created in
  493.  * another process by first creating a pipe texture and then calling
  494.  * resource_get_handle.
  495.  */
  496. static struct pipe_resource *
  497. fd_resource_from_handle(struct pipe_screen *pscreen,
  498.                 const struct pipe_resource *tmpl,
  499.                 struct winsys_handle *handle)
  500. {
  501.         struct fd_resource *rsc = CALLOC_STRUCT(fd_resource);
  502.         struct fd_resource_slice *slice = &rsc->slices[0];
  503.         struct pipe_resource *prsc = &rsc->base.b;
  504.  
  505.         DBG("target=%d, format=%s, %ux%ux%u, array_size=%u, last_level=%u, "
  506.                         "nr_samples=%u, usage=%u, bind=%x, flags=%x",
  507.                         tmpl->target, util_format_name(tmpl->format),
  508.                         tmpl->width0, tmpl->height0, tmpl->depth0,
  509.                         tmpl->array_size, tmpl->last_level, tmpl->nr_samples,
  510.                         tmpl->usage, tmpl->bind, tmpl->flags);
  511.  
  512.         if (!rsc)
  513.                 return NULL;
  514.  
  515.         *prsc = *tmpl;
  516.  
  517.         pipe_reference_init(&prsc->reference, 1);
  518.         list_inithead(&rsc->list);
  519.         prsc->screen = pscreen;
  520.  
  521.         util_range_init(&rsc->valid_buffer_range);
  522.  
  523.         rsc->bo = fd_screen_bo_from_handle(pscreen, handle, &slice->pitch);
  524.         if (!rsc->bo)
  525.                 goto fail;
  526.  
  527.         rsc->base.vtbl = &fd_resource_vtbl;
  528.         rsc->cpp = util_format_get_blocksize(tmpl->format);
  529.         slice->pitch /= rsc->cpp;
  530.  
  531.         assert(rsc->cpp);
  532.  
  533.         return prsc;
  534.  
  535. fail:
  536.         fd_resource_destroy(pscreen, prsc);
  537.         return NULL;
  538. }
  539.  
  540. static void fd_blitter_pipe_begin(struct fd_context *ctx);
  541. static void fd_blitter_pipe_end(struct fd_context *ctx);
  542.  
  543. /**
  544.  * _copy_region using pipe (3d engine)
  545.  */
  546. static bool
  547. fd_blitter_pipe_copy_region(struct fd_context *ctx,
  548.                 struct pipe_resource *dst,
  549.                 unsigned dst_level,
  550.                 unsigned dstx, unsigned dsty, unsigned dstz,
  551.                 struct pipe_resource *src,
  552.                 unsigned src_level,
  553.                 const struct pipe_box *src_box)
  554. {
  555.         /* not until we allow rendertargets to be buffers */
  556.         if (dst->target == PIPE_BUFFER || src->target == PIPE_BUFFER)
  557.                 return false;
  558.  
  559.         if (!util_blitter_is_copy_supported(ctx->blitter, dst, src))
  560.                 return false;
  561.  
  562.         fd_blitter_pipe_begin(ctx);
  563.         util_blitter_copy_texture(ctx->blitter,
  564.                         dst, dst_level, dstx, dsty, dstz,
  565.                         src, src_level, src_box);
  566.         fd_blitter_pipe_end(ctx);
  567.  
  568.         return true;
  569. }
  570.  
  571. /**
  572.  * Copy a block of pixels from one resource to another.
  573.  * The resource must be of the same format.
  574.  * Resources with nr_samples > 1 are not allowed.
  575.  */
  576. static void
  577. fd_resource_copy_region(struct pipe_context *pctx,
  578.                 struct pipe_resource *dst,
  579.                 unsigned dst_level,
  580.                 unsigned dstx, unsigned dsty, unsigned dstz,
  581.                 struct pipe_resource *src,
  582.                 unsigned src_level,
  583.                 const struct pipe_box *src_box)
  584. {
  585.         struct fd_context *ctx = fd_context(pctx);
  586.  
  587.         /* TODO if we have 2d core, or other DMA engine that could be used
  588.          * for simple copies and reasonably easily synchronized with the 3d
  589.          * core, this is where we'd plug it in..
  590.          */
  591.  
  592.         /* try blit on 3d pipe: */
  593.         if (fd_blitter_pipe_copy_region(ctx,
  594.                         dst, dst_level, dstx, dsty, dstz,
  595.                         src, src_level, src_box))
  596.                 return;
  597.  
  598.         /* else fallback to pure sw: */
  599.         util_resource_copy_region(pctx,
  600.                         dst, dst_level, dstx, dsty, dstz,
  601.                         src, src_level, src_box);
  602. }
  603.  
  604. /**
  605.  * Optimal hardware path for blitting pixels.
  606.  * Scaling, format conversion, up- and downsampling (resolve) are allowed.
  607.  */
  608. static void
  609. fd_blit(struct pipe_context *pctx, const struct pipe_blit_info *blit_info)
  610. {
  611.         struct fd_context *ctx = fd_context(pctx);
  612.         struct pipe_blit_info info = *blit_info;
  613.  
  614.         if (info.src.resource->nr_samples > 1 &&
  615.                         info.dst.resource->nr_samples <= 1 &&
  616.                         !util_format_is_depth_or_stencil(info.src.resource->format) &&
  617.                         !util_format_is_pure_integer(info.src.resource->format)) {
  618.                 DBG("color resolve unimplemented");
  619.                 return;
  620.         }
  621.  
  622.         if (util_try_blit_via_copy_region(pctx, &info)) {
  623.                 return; /* done */
  624.         }
  625.  
  626.         if (info.mask & PIPE_MASK_S) {
  627.                 DBG("cannot blit stencil, skipping");
  628.                 info.mask &= ~PIPE_MASK_S;
  629.         }
  630.  
  631.         if (!util_blitter_is_blit_supported(ctx->blitter, &info)) {
  632.                 DBG("blit unsupported %s -> %s",
  633.                                 util_format_short_name(info.src.resource->format),
  634.                                 util_format_short_name(info.dst.resource->format));
  635.                 return;
  636.         }
  637.  
  638.         fd_blitter_pipe_begin(ctx);
  639.         util_blitter_blit(ctx->blitter, &info);
  640.         fd_blitter_pipe_end(ctx);
  641. }
  642.  
  643. static void
  644. fd_blitter_pipe_begin(struct fd_context *ctx)
  645. {
  646.         util_blitter_save_vertex_buffer_slot(ctx->blitter, ctx->vtx.vertexbuf.vb);
  647.         util_blitter_save_vertex_elements(ctx->blitter, ctx->vtx.vtx);
  648.         util_blitter_save_vertex_shader(ctx->blitter, ctx->prog.vp);
  649.         util_blitter_save_rasterizer(ctx->blitter, ctx->rasterizer);
  650.         util_blitter_save_viewport(ctx->blitter, &ctx->viewport);
  651.         util_blitter_save_scissor(ctx->blitter, &ctx->scissor);
  652.         util_blitter_save_fragment_shader(ctx->blitter, ctx->prog.fp);
  653.         util_blitter_save_blend(ctx->blitter, ctx->blend);
  654.         util_blitter_save_depth_stencil_alpha(ctx->blitter, ctx->zsa);
  655.         util_blitter_save_stencil_ref(ctx->blitter, &ctx->stencil_ref);
  656.         util_blitter_save_sample_mask(ctx->blitter, ctx->sample_mask);
  657.         util_blitter_save_framebuffer(ctx->blitter, &ctx->framebuffer);
  658.         util_blitter_save_fragment_sampler_states(ctx->blitter,
  659.                         ctx->fragtex.num_samplers,
  660.                         (void **)ctx->fragtex.samplers);
  661.         util_blitter_save_fragment_sampler_views(ctx->blitter,
  662.                         ctx->fragtex.num_textures, ctx->fragtex.textures);
  663.  
  664.         fd_hw_query_set_stage(ctx, ctx->ring, FD_STAGE_BLIT);
  665. }
  666.  
  667. static void
  668. fd_blitter_pipe_end(struct fd_context *ctx)
  669. {
  670.         fd_hw_query_set_stage(ctx, ctx->ring, FD_STAGE_NULL);
  671. }
  672.  
  673. static void
  674. fd_flush_resource(struct pipe_context *pctx, struct pipe_resource *prsc)
  675. {
  676.         struct fd_resource *rsc = fd_resource(prsc);
  677.  
  678.         if (rsc->dirty || (rsc->stencil && rsc->stencil->dirty))
  679.                 fd_context_render(pctx);
  680. }
  681.  
  682. void
  683. fd_resource_screen_init(struct pipe_screen *pscreen)
  684. {
  685.         pscreen->resource_create = fd_resource_create;
  686.         pscreen->resource_from_handle = fd_resource_from_handle;
  687.         pscreen->resource_get_handle = u_resource_get_handle_vtbl;
  688.         pscreen->resource_destroy = u_resource_destroy_vtbl;
  689. }
  690.  
  691. void
  692. fd_resource_context_init(struct pipe_context *pctx)
  693. {
  694.         pctx->transfer_map = u_transfer_map_vtbl;
  695.         pctx->transfer_flush_region = u_transfer_flush_region_vtbl;
  696.         pctx->transfer_unmap = u_transfer_unmap_vtbl;
  697.         pctx->transfer_inline_write = u_transfer_inline_write_vtbl;
  698.         pctx->create_surface = fd_create_surface;
  699.         pctx->surface_destroy = fd_surface_destroy;
  700.         pctx->resource_copy_region = fd_resource_copy_region;
  701.         pctx->blit = fd_blit;
  702.         pctx->flush_resource = fd_flush_resource;
  703. }
  704.