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 "pipe/p_state.h"
  30. #include "util/u_string.h"
  31. #include "util/u_memory.h"
  32. #include "util/u_prim.h"
  33. #include "util/u_format.h"
  34.  
  35. #include "freedreno_draw.h"
  36. #include "freedreno_context.h"
  37. #include "freedreno_state.h"
  38. #include "freedreno_resource.h"
  39. #include "freedreno_query_hw.h"
  40. #include "freedreno_util.h"
  41.  
  42. static void
  43. resource_reading(struct fd_context *ctx, struct pipe_resource *prsc)
  44. {
  45.         struct fd_resource *rsc;
  46.  
  47.         if (!prsc)
  48.                 return;
  49.  
  50.         rsc = fd_resource(prsc);
  51.         rsc->reading = true;
  52.         list_delinit(&rsc->list);
  53.         list_addtail(&rsc->list, &ctx->used_resources);
  54. }
  55.  
  56. static void
  57. fd_draw_vbo(struct pipe_context *pctx, const struct pipe_draw_info *info)
  58. {
  59.         struct fd_context *ctx = fd_context(pctx);
  60.         struct pipe_framebuffer_state *pfb = &ctx->framebuffer;
  61.         struct pipe_scissor_state *scissor = fd_context_get_scissor(ctx);
  62.         unsigned i, buffers = 0;
  63.  
  64.         /* if we supported transform feedback, we'd have to disable this: */
  65.         if (((scissor->maxx - scissor->minx) *
  66.                         (scissor->maxy - scissor->miny)) == 0) {
  67.                 return;
  68.         }
  69.  
  70.         /* emulate unsupported primitives: */
  71.         if (!fd_supported_prim(ctx, info->mode)) {
  72.                 util_primconvert_save_index_buffer(ctx->primconvert, &ctx->indexbuf);
  73.                 util_primconvert_save_rasterizer_state(ctx->primconvert, ctx->rasterizer);
  74.                 util_primconvert_draw_vbo(ctx->primconvert, info);
  75.                 return;
  76.         }
  77.  
  78.         ctx->needs_flush = true;
  79.  
  80.         /*
  81.          * Figure out the buffers/features we need:
  82.          */
  83.  
  84.         if (fd_depth_enabled(ctx)) {
  85.                 buffers |= FD_BUFFER_DEPTH;
  86.                 fd_resource(pfb->zsbuf->texture)->dirty = true;
  87.                 ctx->gmem_reason |= FD_GMEM_DEPTH_ENABLED;
  88.         }
  89.  
  90.         if (fd_stencil_enabled(ctx)) {
  91.                 struct fd_resource *rsc = fd_resource(pfb->zsbuf->texture);
  92.                 buffers |= FD_BUFFER_STENCIL;
  93.                 if (rsc->stencil)
  94.                         rsc->stencil->dirty = true;
  95.                 else
  96.                         rsc->dirty = true;
  97.                 ctx->gmem_reason |= FD_GMEM_STENCIL_ENABLED;
  98.         }
  99.  
  100.         if (fd_logicop_enabled(ctx))
  101.                 ctx->gmem_reason |= FD_GMEM_LOGICOP_ENABLED;
  102.  
  103.         for (i = 0; i < pfb->nr_cbufs; i++) {
  104.                 struct pipe_resource *surf;
  105.  
  106.                 if (!pfb->cbufs[i])
  107.                         continue;
  108.  
  109.                 surf = pfb->cbufs[i]->texture;
  110.  
  111.                 fd_resource(surf)->dirty = true;
  112.                 buffers |= PIPE_CLEAR_COLOR0 << i;
  113.  
  114.                 if (surf->nr_samples > 1)
  115.                         ctx->gmem_reason |= FD_GMEM_MSAA_ENABLED;
  116.  
  117.                 if (fd_blend_enabled(ctx, i))
  118.                         ctx->gmem_reason |= FD_GMEM_BLEND_ENABLED;
  119.         }
  120.  
  121.         /* Skip over buffer 0, that is sent along with the command stream */
  122.         for (i = 1; i < PIPE_MAX_CONSTANT_BUFFERS; i++) {
  123.                 resource_reading(ctx, ctx->constbuf[PIPE_SHADER_VERTEX].cb[i].buffer);
  124.                 resource_reading(ctx, ctx->constbuf[PIPE_SHADER_FRAGMENT].cb[i].buffer);
  125.         }
  126.  
  127.         /* Mark VBOs as being read */
  128.         for (i = 0; i < ctx->vtx.vertexbuf.count; i++) {
  129.                 assert(!ctx->vtx.vertexbuf.vb[i].user_buffer);
  130.                 resource_reading(ctx, ctx->vtx.vertexbuf.vb[i].buffer);
  131.         }
  132.  
  133.         /* Mark index buffer as being read */
  134.         resource_reading(ctx, ctx->indexbuf.buffer);
  135.  
  136.         /* Mark textures as being read */
  137.         for (i = 0; i < ctx->verttex.num_textures; i++)
  138.                 if (ctx->verttex.textures[i])
  139.                         resource_reading(ctx, ctx->verttex.textures[i]->texture);
  140.         for (i = 0; i < ctx->fragtex.num_textures; i++)
  141.                 if (ctx->fragtex.textures[i])
  142.                         resource_reading(ctx, ctx->fragtex.textures[i]->texture);
  143.  
  144.         ctx->num_draws++;
  145.  
  146.         ctx->stats.draw_calls++;
  147.         ctx->stats.prims_emitted +=
  148.                 u_reduced_prims_for_vertices(info->mode, info->count);
  149.  
  150.         /* any buffers that haven't been cleared yet, we need to restore: */
  151.         ctx->restore |= buffers & (FD_BUFFER_ALL & ~ctx->cleared);
  152.         /* and any buffers used, need to be resolved: */
  153.         ctx->resolve |= buffers;
  154.  
  155.         DBG("%x num_draws=%u (%s/%s)", buffers, ctx->num_draws,
  156.                 util_format_short_name(pipe_surface_format(pfb->cbufs[0])),
  157.                 util_format_short_name(pipe_surface_format(pfb->zsbuf)));
  158.  
  159.         fd_hw_query_set_stage(ctx, ctx->ring, FD_STAGE_DRAW);
  160.         ctx->draw_vbo(ctx, info);
  161.  
  162.         /* if an app (or, well, piglit test) does many thousands of draws
  163.          * without flush (or anything which implicitly flushes, like
  164.          * changing render targets), we can exceed the ringbuffer size.
  165.          * Since we don't currently have a sane way to wrapparound, and
  166.          * we use the same buffer for both draw and tiling commands, for
  167.          * now we need to do this hack and trigger flush if we are running
  168.          * low on remaining space for cmds:
  169.          */
  170.         if (((ctx->ring->cur - ctx->ring->start) >
  171.                                 (ctx->ring->size/4 - FD_TILING_COMMANDS_DWORDS)) ||
  172.                         (fd_mesa_debug & FD_DBG_FLUSH))
  173.                 fd_context_render(pctx);
  174. }
  175.  
  176. /* TODO figure out how to make better use of existing state mechanism
  177.  * for clear (and possibly gmem->mem / mem->gmem) so we can (a) keep
  178.  * track of what state really actually changes, and (b) reduce the code
  179.  * in the a2xx/a3xx parts.
  180.  */
  181.  
  182. static void
  183. fd_clear(struct pipe_context *pctx, unsigned buffers,
  184.                 const union pipe_color_union *color, double depth, unsigned stencil)
  185. {
  186.         struct fd_context *ctx = fd_context(pctx);
  187.         struct pipe_framebuffer_state *pfb = &ctx->framebuffer;
  188.         struct pipe_scissor_state *scissor = fd_context_get_scissor(ctx);
  189.         unsigned cleared_buffers;
  190.         int i;
  191.  
  192.         /* for bookkeeping about which buffers have been cleared (and thus
  193.          * can fully or partially skip mem2gmem) we need to ignore buffers
  194.          * that have already had a draw, in case apps do silly things like
  195.          * clear after draw (ie. if you only clear the color buffer, but
  196.          * something like alpha-test causes side effects from the draw in
  197.          * the depth buffer, etc)
  198.          */
  199.         cleared_buffers = buffers & (FD_BUFFER_ALL & ~ctx->restore);
  200.  
  201.         /* do we have full-screen scissor? */
  202.         if (!memcmp(scissor, &ctx->disabled_scissor, sizeof(*scissor))) {
  203.                 ctx->cleared |= cleared_buffers;
  204.         } else {
  205.                 ctx->partial_cleared |= cleared_buffers;
  206.                 if (cleared_buffers & PIPE_CLEAR_COLOR)
  207.                         ctx->cleared_scissor.color = *scissor;
  208.                 if (cleared_buffers & PIPE_CLEAR_DEPTH)
  209.                         ctx->cleared_scissor.depth = *scissor;
  210.                 if (cleared_buffers & PIPE_CLEAR_STENCIL)
  211.                         ctx->cleared_scissor.stencil = *scissor;
  212.         }
  213.         ctx->resolve |= buffers;
  214.         ctx->needs_flush = true;
  215.  
  216.         if (buffers & PIPE_CLEAR_COLOR)
  217.                 for (i = 0; i < pfb->nr_cbufs; i++)
  218.                         if (buffers & (PIPE_CLEAR_COLOR0 << i))
  219.                                 fd_resource(pfb->cbufs[i]->texture)->dirty = true;
  220.  
  221.         if (buffers & (PIPE_CLEAR_DEPTH | PIPE_CLEAR_STENCIL)) {
  222.                 struct fd_resource *rsc = fd_resource(pfb->zsbuf->texture);
  223.                 if (rsc->stencil && buffers & PIPE_CLEAR_STENCIL)
  224.                         rsc->stencil->dirty = true;
  225.                 if (!rsc->stencil || buffers & PIPE_CLEAR_DEPTH)
  226.                         rsc->dirty = true;
  227.  
  228.                 ctx->gmem_reason |= FD_GMEM_CLEARS_DEPTH_STENCIL;
  229.         }
  230.  
  231.         DBG("%x depth=%f, stencil=%u (%s/%s)", buffers, depth, stencil,
  232.                 util_format_short_name(pipe_surface_format(pfb->cbufs[0])),
  233.                 util_format_short_name(pipe_surface_format(pfb->zsbuf)));
  234.  
  235.         fd_hw_query_set_stage(ctx, ctx->ring, FD_STAGE_CLEAR);
  236.  
  237.         ctx->clear(ctx, buffers, color, depth, stencil);
  238.  
  239.         ctx->dirty |= FD_DIRTY_ZSA |
  240.                         FD_DIRTY_VIEWPORT |
  241.                         FD_DIRTY_RASTERIZER |
  242.                         FD_DIRTY_SAMPLE_MASK |
  243.                         FD_DIRTY_PROG |
  244.                         FD_DIRTY_CONSTBUF |
  245.                         FD_DIRTY_BLEND;
  246.  
  247.         if (fd_mesa_debug & FD_DBG_DCLEAR)
  248.                 ctx->dirty = 0xffffffff;
  249. }
  250.  
  251. static void
  252. fd_clear_render_target(struct pipe_context *pctx, struct pipe_surface *ps,
  253.                 const union pipe_color_union *color,
  254.                 unsigned x, unsigned y, unsigned w, unsigned h)
  255. {
  256.         DBG("TODO: x=%u, y=%u, w=%u, h=%u", x, y, w, h);
  257. }
  258.  
  259. static void
  260. fd_clear_depth_stencil(struct pipe_context *pctx, struct pipe_surface *ps,
  261.                 unsigned buffers, double depth, unsigned stencil,
  262.                 unsigned x, unsigned y, unsigned w, unsigned h)
  263. {
  264.         DBG("TODO: buffers=%u, depth=%f, stencil=%u, x=%u, y=%u, w=%u, h=%u",
  265.                         buffers, depth, stencil, x, y, w, h);
  266. }
  267.  
  268. void
  269. fd_draw_init(struct pipe_context *pctx)
  270. {
  271.         list_inithead(&fd_context(pctx)->used_resources);
  272.  
  273.         pctx->draw_vbo = fd_draw_vbo;
  274.         pctx->clear = fd_clear;
  275.         pctx->clear_render_target = fd_clear_render_target;
  276.         pctx->clear_depth_stencil = fd_clear_depth_stencil;
  277. }
  278.