Subversion Repositories Kolibri OS

Rev

Rev 4358 | Go to most recent revision | 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_inlines.h"
  31. #include "util/u_transfer.h"
  32. #include "util/u_string.h"
  33. #include "util/u_surface.h"
  34.  
  35. #include "freedreno_resource.h"
  36. #include "freedreno_screen.h"
  37. #include "freedreno_surface.h"
  38. #include "freedreno_context.h"
  39. #include "freedreno_util.h"
  40.  
  41. static void fd_resource_transfer_flush_region(struct pipe_context *pctx,
  42.                 struct pipe_transfer *ptrans,
  43.                 const struct pipe_box *box)
  44. {
  45.         struct fd_context *ctx = fd_context(pctx);
  46.         struct fd_resource *rsc = fd_resource(ptrans->resource);
  47.  
  48.         if (rsc->dirty)
  49.                 fd_context_render(pctx);
  50.  
  51.         if (rsc->timestamp) {
  52.                 fd_pipe_wait(ctx->screen->pipe, rsc->timestamp);
  53.                 rsc->timestamp = 0;
  54.         }
  55. }
  56.  
  57. static void
  58. fd_resource_transfer_unmap(struct pipe_context *pctx,
  59.                 struct pipe_transfer *ptrans)
  60. {
  61.         struct fd_context *ctx = fd_context(pctx);
  62.         struct fd_resource *rsc = fd_resource(ptrans->resource);
  63.         if (!(ptrans->usage & PIPE_TRANSFER_UNSYNCHRONIZED))
  64.                 fd_bo_cpu_fini(rsc->bo);
  65.         pipe_resource_reference(&ptrans->resource, NULL);
  66.         util_slab_free(&ctx->transfer_pool, ptrans);
  67. }
  68.  
  69. static void *
  70. fd_resource_transfer_map(struct pipe_context *pctx,
  71.                 struct pipe_resource *prsc,
  72.                 unsigned level, unsigned usage,
  73.                 const struct pipe_box *box,
  74.                 struct pipe_transfer **pptrans)
  75. {
  76.         struct fd_context *ctx = fd_context(pctx);
  77.         struct fd_resource *rsc = fd_resource(prsc);
  78.         struct pipe_transfer *ptrans = util_slab_alloc(&ctx->transfer_pool);
  79.         enum pipe_format format = prsc->format;
  80.         uint32_t op = 0;
  81.         char *buf;
  82.  
  83.         if (!ptrans)
  84.                 return NULL;
  85.  
  86.         /* util_slab_alloc() doesn't zero: */
  87.         memset(ptrans, 0, sizeof(*ptrans));
  88.  
  89.         pipe_resource_reference(&ptrans->resource, prsc);
  90.         ptrans->level = level;
  91.         ptrans->usage = usage;
  92.         ptrans->box = *box;
  93.         ptrans->stride = rsc->pitch * rsc->cpp;
  94.         ptrans->layer_stride = ptrans->stride;
  95.  
  96.         /* some state trackers (at least XA) don't do this.. */
  97.         if (!(usage & PIPE_TRANSFER_FLUSH_EXPLICIT))
  98.                 fd_resource_transfer_flush_region(pctx, ptrans, box);
  99.  
  100.         buf = fd_bo_map(rsc->bo);
  101.         if (!buf) {
  102.                 fd_resource_transfer_unmap(pctx, ptrans);
  103.                 return NULL;
  104.         }
  105.  
  106.         if (usage & PIPE_TRANSFER_READ)
  107.                 op |= DRM_FREEDRENO_PREP_READ;
  108.  
  109.         if (usage & PIPE_TRANSFER_WRITE)
  110.                 op |= DRM_FREEDRENO_PREP_WRITE;
  111.  
  112.         if (!(usage & PIPE_TRANSFER_UNSYNCHRONIZED))
  113.                 fd_bo_cpu_prep(rsc->bo, ctx->screen->pipe, op);
  114.  
  115.         *pptrans = ptrans;
  116.  
  117.         return buf +
  118.                 box->y / util_format_get_blockheight(format) * ptrans->stride +
  119.                 box->x / util_format_get_blockwidth(format) * rsc->cpp;
  120. }
  121.  
  122. static void
  123. fd_resource_destroy(struct pipe_screen *pscreen,
  124.                 struct pipe_resource *prsc)
  125. {
  126.         struct fd_resource *rsc = fd_resource(prsc);
  127.         fd_bo_del(rsc->bo);
  128.         FREE(rsc);
  129. }
  130.  
  131. static boolean
  132. fd_resource_get_handle(struct pipe_screen *pscreen,
  133.                 struct pipe_resource *prsc,
  134.                 struct winsys_handle *handle)
  135. {
  136.         struct fd_resource *rsc = fd_resource(prsc);
  137.  
  138.         return fd_screen_bo_get_handle(pscreen, rsc->bo,
  139.                         rsc->pitch * rsc->cpp, handle);
  140. }
  141.  
  142.  
  143. static const struct u_resource_vtbl fd_resource_vtbl = {
  144.                 .resource_get_handle      = fd_resource_get_handle,
  145.                 .resource_destroy         = fd_resource_destroy,
  146.                 .transfer_map             = fd_resource_transfer_map,
  147.                 .transfer_flush_region    = fd_resource_transfer_flush_region,
  148.                 .transfer_unmap           = fd_resource_transfer_unmap,
  149.                 .transfer_inline_write    = u_default_transfer_inline_write,
  150. };
  151.  
  152. /**
  153.  * Create a new texture object, using the given template info.
  154.  */
  155. static struct pipe_resource *
  156. fd_resource_create(struct pipe_screen *pscreen,
  157.                 const struct pipe_resource *tmpl)
  158. {
  159.         struct fd_screen *screen = fd_screen(pscreen);
  160.         struct fd_resource *rsc = CALLOC_STRUCT(fd_resource);
  161.         struct pipe_resource *prsc = &rsc->base.b;
  162.         uint32_t flags, size;
  163.  
  164.         DBG("target=%d, format=%s, %ux%u@%u, array_size=%u, last_level=%u, "
  165.                         "nr_samples=%u, usage=%u, bind=%x, flags=%x",
  166.                         tmpl->target, util_format_name(tmpl->format),
  167.                         tmpl->width0, tmpl->height0, tmpl->depth0,
  168.                         tmpl->array_size, tmpl->last_level, tmpl->nr_samples,
  169.                         tmpl->usage, tmpl->bind, tmpl->flags);
  170.  
  171.         if (!rsc)
  172.                 return NULL;
  173.  
  174.         *prsc = *tmpl;
  175.  
  176.         pipe_reference_init(&prsc->reference, 1);
  177.         prsc->screen = pscreen;
  178.  
  179.         rsc->base.vtbl = &fd_resource_vtbl;
  180.         rsc->pitch = align(tmpl->width0, 32);
  181.         rsc->cpp = util_format_get_blocksize(tmpl->format);
  182.  
  183.         assert(rsc->cpp);
  184.  
  185.         size = rsc->pitch * tmpl->height0 * rsc->cpp;
  186.         flags = DRM_FREEDRENO_GEM_CACHE_WCOMBINE |
  187.                         DRM_FREEDRENO_GEM_TYPE_KMEM; /* TODO */
  188.  
  189.         rsc->bo = fd_bo_new(screen->dev, size, flags);
  190.  
  191.         return prsc;
  192. }
  193.  
  194. /**
  195.  * Create a texture from a winsys_handle. The handle is often created in
  196.  * another process by first creating a pipe texture and then calling
  197.  * resource_get_handle.
  198.  */
  199. static struct pipe_resource *
  200. fd_resource_from_handle(struct pipe_screen *pscreen,
  201.                 const struct pipe_resource *tmpl,
  202.                 struct winsys_handle *handle)
  203. {
  204.         struct fd_resource *rsc = CALLOC_STRUCT(fd_resource);
  205.         struct pipe_resource *prsc = &rsc->base.b;
  206.  
  207.         DBG("target=%d, format=%s, %ux%u@%u, array_size=%u, last_level=%u, "
  208.                         "nr_samples=%u, usage=%u, bind=%x, flags=%x",
  209.                         tmpl->target, util_format_name(tmpl->format),
  210.                         tmpl->width0, tmpl->height0, tmpl->depth0,
  211.                         tmpl->array_size, tmpl->last_level, tmpl->nr_samples,
  212.                         tmpl->usage, tmpl->bind, tmpl->flags);
  213.  
  214.         if (!rsc)
  215.                 return NULL;
  216.  
  217.         *prsc = *tmpl;
  218.  
  219.         pipe_reference_init(&prsc->reference, 1);
  220.         prsc->screen = pscreen;
  221.  
  222.         rsc->bo = fd_screen_bo_from_handle(pscreen, handle, &rsc->pitch);
  223.  
  224.         rsc->base.vtbl = &fd_resource_vtbl;
  225.         rsc->cpp = util_format_get_blocksize(tmpl->format);
  226.         rsc->pitch /= rsc->cpp;
  227.  
  228.         assert(rsc->cpp);
  229.  
  230.         return prsc;
  231. }
  232.  
  233. static bool render_blit(struct pipe_context *pctx, struct pipe_blit_info *info);
  234.  
  235. /**
  236.  * Copy a block of pixels from one resource to another.
  237.  * The resource must be of the same format.
  238.  * Resources with nr_samples > 1 are not allowed.
  239.  */
  240. static void
  241. fd_resource_copy_region(struct pipe_context *pctx,
  242.                 struct pipe_resource *dst,
  243.                 unsigned dst_level,
  244.                 unsigned dstx, unsigned dsty, unsigned dstz,
  245.                 struct pipe_resource *src,
  246.                 unsigned src_level,
  247.                 const struct pipe_box *src_box)
  248. {
  249.         /* TODO if we have 2d core, or other DMA engine that could be used
  250.          * for simple copies and reasonably easily synchronized with the 3d
  251.          * core, this is where we'd plug it in..
  252.          */
  253.         struct pipe_blit_info info = {
  254.                 .dst = {
  255.                         .resource = dst,
  256.                         .box = {
  257.                                 .x      = dstx,
  258.                                 .y      = dsty,
  259.                                 .z      = dstz,
  260.                                 .width  = src_box->width,
  261.                                 .height = src_box->height,
  262.                                 .depth  = src_box->depth,
  263.                         },
  264.                         .format = util_format_linear(dst->format),
  265.                 },
  266.                 .src = {
  267.                         .resource = src,
  268.                         .box      = *src_box,
  269.                         .format   = util_format_linear(src->format),
  270.                 },
  271.                 .mask = PIPE_MASK_RGBA,
  272.                 .filter = PIPE_TEX_FILTER_NEAREST,
  273.         };
  274.         render_blit(pctx, &info);
  275. }
  276.  
  277. /* Optimal hardware path for blitting pixels.
  278.  * Scaling, format conversion, up- and downsampling (resolve) are allowed.
  279.  */
  280. static void
  281. fd_blit(struct pipe_context *pctx, const struct pipe_blit_info *blit_info)
  282. {
  283.         struct pipe_blit_info info = *blit_info;
  284.  
  285.         if (info.src.resource->nr_samples > 1 &&
  286.                         info.dst.resource->nr_samples <= 1 &&
  287.                         !util_format_is_depth_or_stencil(info.src.resource->format) &&
  288.                         !util_format_is_pure_integer(info.src.resource->format)) {
  289.                 DBG("color resolve unimplemented");
  290.                 return;
  291.         }
  292.  
  293.         if (util_try_blit_via_copy_region(pctx, &info)) {
  294.                 return; /* done */
  295.         }
  296.  
  297.         if (info.mask & PIPE_MASK_S) {
  298.                 DBG("cannot blit stencil, skipping");
  299.                 info.mask &= ~PIPE_MASK_S;
  300.         }
  301.  
  302.         render_blit(pctx, &info);
  303. }
  304.  
  305. static bool
  306. render_blit(struct pipe_context *pctx, struct pipe_blit_info *info)
  307. {
  308.         struct fd_context *ctx = fd_context(pctx);
  309.  
  310.         if (!util_blitter_is_blit_supported(ctx->blitter, info)) {
  311.                 DBG("blit unsupported %s -> %s",
  312.                                 util_format_short_name(info->src.resource->format),
  313.                                 util_format_short_name(info->dst.resource->format));
  314.                 return false;
  315.         }
  316.  
  317.         util_blitter_save_vertex_buffer_slot(ctx->blitter, ctx->vertexbuf.vb);
  318.         util_blitter_save_vertex_elements(ctx->blitter, ctx->vtx);
  319.         util_blitter_save_vertex_shader(ctx->blitter, ctx->prog.vp);
  320.         util_blitter_save_rasterizer(ctx->blitter, ctx->rasterizer);
  321.         util_blitter_save_viewport(ctx->blitter, &ctx->viewport);
  322.         util_blitter_save_scissor(ctx->blitter, &ctx->scissor);
  323.         util_blitter_save_fragment_shader(ctx->blitter, ctx->prog.fp);
  324.         util_blitter_save_blend(ctx->blitter, ctx->blend);
  325.         util_blitter_save_depth_stencil_alpha(ctx->blitter, ctx->zsa);
  326.         util_blitter_save_stencil_ref(ctx->blitter, &ctx->stencil_ref);
  327.         util_blitter_save_sample_mask(ctx->blitter, ctx->sample_mask);
  328.         util_blitter_save_framebuffer(ctx->blitter, &ctx->framebuffer);
  329.         util_blitter_save_fragment_sampler_states(ctx->blitter,
  330.                         ctx->fragtex.num_samplers,
  331.                         (void **)ctx->fragtex.samplers);
  332.         util_blitter_save_fragment_sampler_views(ctx->blitter,
  333.                         ctx->fragtex.num_textures, ctx->fragtex.textures);
  334.  
  335.         util_blitter_blit(ctx->blitter, info);
  336.  
  337.         return true;
  338. }
  339.  
  340. void
  341. fd_resource_screen_init(struct pipe_screen *pscreen)
  342. {
  343.         pscreen->resource_create = fd_resource_create;
  344.         pscreen->resource_from_handle = fd_resource_from_handle;
  345.         pscreen->resource_get_handle = u_resource_get_handle_vtbl;
  346.         pscreen->resource_destroy = u_resource_destroy_vtbl;
  347. }
  348.  
  349. void
  350. fd_resource_context_init(struct pipe_context *pctx)
  351. {
  352.         pctx->transfer_map = u_transfer_map_vtbl;
  353.         pctx->transfer_flush_region = u_transfer_flush_region_vtbl;
  354.         pctx->transfer_unmap = u_transfer_unmap_vtbl;
  355.         pctx->transfer_inline_write = u_transfer_inline_write_vtbl;
  356.         pctx->create_surface = fd_create_surface;
  357.         pctx->surface_destroy = fd_surface_destroy;
  358.         pctx->resource_copy_region = fd_resource_copy_region;
  359.         pctx->blit = fd_blit;
  360. }
  361.