Subversion Repositories Kolibri OS

Rev

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