Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  1. /**********************************************************
  2.  * Copyright 2008-2009 VMware, Inc.  All rights reserved.
  3.  *
  4.  * Permission is hereby granted, free of charge, to any person
  5.  * obtaining a copy of this software and associated documentation
  6.  * files (the "Software"), to deal in the Software without
  7.  * restriction, including without limitation the rights to use, copy,
  8.  * modify, merge, publish, distribute, sublicense, and/or sell copies
  9.  * of the Software, and to permit persons to whom the Software is
  10.  * furnished to do so, subject to the following conditions:
  11.  *
  12.  * The above copyright notice and this permission notice shall be
  13.  * included in all copies or substantial portions of the Software.
  14.  *
  15.  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  16.  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  17.  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  18.  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
  19.  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
  20.  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  21.  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  22.  * SOFTWARE.
  23.  *
  24.  **********************************************************/
  25.  
  26. #include "pipe/p_compiler.h"
  27. #include "util/u_inlines.h"
  28. #include "pipe/p_defines.h"
  29. #include "util/u_memory.h"
  30. #include "util/u_math.h"
  31. #include "util/u_upload_mgr.h"
  32.  
  33. #include "svga_context.h"
  34. #include "svga_draw.h"
  35. #include "svga_draw_private.h"
  36. #include "svga_debug.h"
  37. #include "svga_screen.h"
  38. #include "svga_resource_buffer.h"
  39. #include "svga_resource_texture.h"
  40. #include "svga_surface.h"
  41. #include "svga_winsys.h"
  42. #include "svga_cmd.h"
  43.  
  44.  
  45. struct svga_hwtnl *
  46. svga_hwtnl_create(struct svga_context *svga)
  47. {
  48.    struct svga_hwtnl *hwtnl = CALLOC_STRUCT(svga_hwtnl);
  49.    if (hwtnl == NULL)
  50.       goto fail;
  51.  
  52.    hwtnl->svga = svga;
  53.  
  54.    hwtnl->cmd.swc = svga->swc;
  55.  
  56.    return hwtnl;
  57.  
  58. fail:
  59.    return NULL;
  60. }
  61.  
  62.  
  63. void
  64. svga_hwtnl_destroy(struct svga_hwtnl *hwtnl)
  65. {
  66.    unsigned i, j;
  67.  
  68.    for (i = 0; i < PIPE_PRIM_MAX; i++) {
  69.       for (j = 0; j < IDX_CACHE_MAX; j++) {
  70.          pipe_resource_reference(&hwtnl->index_cache[i][j].buffer, NULL);
  71.       }
  72.    }
  73.  
  74.    for (i = 0; i < hwtnl->cmd.vdecl_count; i++)
  75.       pipe_resource_reference(&hwtnl->cmd.vdecl_vb[i], NULL);
  76.  
  77.    for (i = 0; i < hwtnl->cmd.prim_count; i++)
  78.       pipe_resource_reference(&hwtnl->cmd.prim_ib[i], NULL);
  79.  
  80.    FREE(hwtnl);
  81. }
  82.  
  83.  
  84. void
  85. svga_hwtnl_set_flatshade(struct svga_hwtnl *hwtnl,
  86.                          boolean flatshade, boolean flatshade_first)
  87. {
  88.    hwtnl->hw_pv = PV_FIRST;
  89.    hwtnl->api_pv = (flatshade && !flatshade_first) ? PV_LAST : PV_FIRST;
  90. }
  91.  
  92.  
  93. void
  94. svga_hwtnl_set_unfilled(struct svga_hwtnl *hwtnl, unsigned mode)
  95. {
  96.    hwtnl->api_fillmode = mode;
  97. }
  98.  
  99.  
  100. void
  101. svga_hwtnl_reset_vdecl(struct svga_hwtnl *hwtnl, unsigned count)
  102. {
  103.    unsigned i;
  104.  
  105.    assert(hwtnl->cmd.prim_count == 0);
  106.  
  107.    for (i = count; i < hwtnl->cmd.vdecl_count; i++) {
  108.       pipe_resource_reference(&hwtnl->cmd.vdecl_vb[i], NULL);
  109.    }
  110.  
  111.    hwtnl->cmd.vdecl_count = count;
  112. }
  113.  
  114.  
  115. void
  116. svga_hwtnl_vdecl(struct svga_hwtnl *hwtnl,
  117.                  unsigned i,
  118.                  const SVGA3dVertexDecl * decl, struct pipe_resource *vb)
  119. {
  120.    assert(hwtnl->cmd.prim_count == 0);
  121.  
  122.    assert(i < hwtnl->cmd.vdecl_count);
  123.  
  124.    hwtnl->cmd.vdecl[i] = *decl;
  125.  
  126.    pipe_resource_reference(&hwtnl->cmd.vdecl_vb[i], vb);
  127. }
  128.  
  129.  
  130. /**
  131.  * Determine whether the specified buffer is referred in the primitive queue,
  132.  * for which no commands have been written yet.
  133.  */
  134. boolean
  135. svga_hwtnl_is_buffer_referred(struct svga_hwtnl *hwtnl,
  136.                               struct pipe_resource *buffer)
  137. {
  138.    unsigned i;
  139.  
  140.    if (svga_buffer_is_user_buffer(buffer)) {
  141.       return FALSE;
  142.    }
  143.  
  144.    if (!hwtnl->cmd.prim_count) {
  145.       return FALSE;
  146.    }
  147.  
  148.    for (i = 0; i < hwtnl->cmd.vdecl_count; ++i) {
  149.       if (hwtnl->cmd.vdecl_vb[i] == buffer) {
  150.          return TRUE;
  151.       }
  152.    }
  153.  
  154.    for (i = 0; i < hwtnl->cmd.prim_count; ++i) {
  155.       if (hwtnl->cmd.prim_ib[i] == buffer) {
  156.          return TRUE;
  157.       }
  158.    }
  159.  
  160.    return FALSE;
  161. }
  162.  
  163.  
  164. enum pipe_error
  165. svga_hwtnl_flush(struct svga_hwtnl *hwtnl)
  166. {
  167.    struct svga_winsys_context *swc = hwtnl->cmd.swc;
  168.    struct svga_context *svga = hwtnl->svga;
  169.    enum pipe_error ret;
  170.  
  171.    if (hwtnl->cmd.prim_count) {
  172.       struct svga_winsys_surface *vb_handle[SVGA3D_INPUTREG_MAX];
  173.       struct svga_winsys_surface *ib_handle[QSZ];
  174.       struct svga_winsys_surface *handle;
  175.       SVGA3dVertexDecl *vdecl;
  176.       SVGA3dPrimitiveRange *prim;
  177.       unsigned i;
  178.  
  179.       for (i = 0; i < hwtnl->cmd.vdecl_count; i++) {
  180.          assert(!svga_buffer_is_user_buffer(hwtnl->cmd.vdecl_vb[i]));
  181.          handle = svga_buffer_handle(svga, hwtnl->cmd.vdecl_vb[i]);
  182.          if (handle == NULL)
  183.             return PIPE_ERROR_OUT_OF_MEMORY;
  184.  
  185.          vb_handle[i] = handle;
  186.       }
  187.  
  188.       for (i = 0; i < hwtnl->cmd.prim_count; i++) {
  189.          if (hwtnl->cmd.prim_ib[i]) {
  190.             assert(!svga_buffer_is_user_buffer(hwtnl->cmd.prim_ib[i]));
  191.             handle = svga_buffer_handle(svga, hwtnl->cmd.prim_ib[i]);
  192.             if (handle == NULL)
  193.                return PIPE_ERROR_OUT_OF_MEMORY;
  194.          }
  195.          else {
  196.             handle = NULL;
  197.          }
  198.  
  199.          ib_handle[i] = handle;
  200.       }
  201.  
  202.       if (svga->rebind.rendertargets) {
  203.          ret = svga_reemit_framebuffer_bindings(svga);
  204.          if (ret != PIPE_OK) {
  205.             return ret;
  206.          }
  207.       }
  208.  
  209.       if (svga->rebind.texture_samplers) {
  210.          ret = svga_reemit_tss_bindings(svga);
  211.          if (ret != PIPE_OK) {
  212.             return ret;
  213.          }
  214.       }
  215.  
  216.       if (svga->rebind.vs) {
  217.          ret = svga_reemit_vs_bindings(svga);
  218.          if (ret != PIPE_OK) {
  219.             return ret;
  220.          }
  221.       }
  222.  
  223.       if (svga->rebind.fs) {
  224.          ret = svga_reemit_fs_bindings(svga);
  225.          if (ret != PIPE_OK) {
  226.             return ret;
  227.          }
  228.       }
  229.  
  230.       SVGA_DBG(DEBUG_DMA, "draw to sid %p, %d prims\n",
  231.                svga->curr.framebuffer.cbufs[0] ?
  232.                svga_surface(svga->curr.framebuffer.cbufs[0])->handle : NULL,
  233.                hwtnl->cmd.prim_count);
  234.  
  235.       ret = SVGA3D_BeginDrawPrimitives(swc, &vdecl, hwtnl->cmd.vdecl_count,
  236.                                        &prim, hwtnl->cmd.prim_count);
  237.       if (ret != PIPE_OK)
  238.          return ret;
  239.  
  240.       memcpy(vdecl, hwtnl->cmd.vdecl,
  241.              hwtnl->cmd.vdecl_count * sizeof hwtnl->cmd.vdecl[0]);
  242.  
  243.       for (i = 0; i < hwtnl->cmd.vdecl_count; i++) {
  244.          /* Given rangeHint is considered to be relative to indexBias, and
  245.           * indexBias varies per primitive, we cannot accurately supply an
  246.           * rangeHint when emitting more than one primitive per draw command.
  247.           */
  248.          if (hwtnl->cmd.prim_count == 1) {
  249.             vdecl[i].rangeHint.first = hwtnl->cmd.min_index[0];
  250.             vdecl[i].rangeHint.last = hwtnl->cmd.max_index[0] + 1;
  251.          }
  252.          else {
  253.             vdecl[i].rangeHint.first = 0;
  254.             vdecl[i].rangeHint.last = 0;
  255.          }
  256.  
  257.          swc->surface_relocation(swc, &vdecl[i].array.surfaceId, NULL,
  258.                                  vb_handle[i], SVGA_RELOC_READ);
  259.       }
  260.  
  261.       memcpy(prim, hwtnl->cmd.prim,
  262.              hwtnl->cmd.prim_count * sizeof hwtnl->cmd.prim[0]);
  263.  
  264.       for (i = 0; i < hwtnl->cmd.prim_count; i++) {
  265.          swc->surface_relocation(swc, &prim[i].indexArray.surfaceId, NULL,
  266.                                  ib_handle[i], SVGA_RELOC_READ);
  267.          pipe_resource_reference(&hwtnl->cmd.prim_ib[i], NULL);
  268.       }
  269.  
  270.       SVGA_FIFOCommitAll(swc);
  271.       hwtnl->cmd.prim_count = 0;
  272.    }
  273.  
  274.    return PIPE_OK;
  275. }
  276.  
  277.  
  278. void
  279. svga_hwtnl_set_index_bias(struct svga_hwtnl *hwtnl, int index_bias)
  280. {
  281.    hwtnl->index_bias = index_bias;
  282. }
  283.  
  284.  
  285.  
  286. /***********************************************************************
  287.  * Internal functions:
  288.  */
  289.  
  290. /**
  291.  * For debugging only.
  292.  */
  293. static void
  294. check_draw_params(struct svga_hwtnl *hwtnl,
  295.                   const SVGA3dPrimitiveRange *range,
  296.                   unsigned min_index, unsigned max_index,
  297.                   struct pipe_resource *ib)
  298. {
  299.    unsigned i;
  300.  
  301.    for (i = 0; i < hwtnl->cmd.vdecl_count; i++) {
  302.       struct pipe_resource *vb = hwtnl->cmd.vdecl_vb[i];
  303.       unsigned size = vb ? vb->width0 : 0;
  304.       unsigned offset = hwtnl->cmd.vdecl[i].array.offset;
  305.       unsigned stride = hwtnl->cmd.vdecl[i].array.stride;
  306.       int index_bias = (int) range->indexBias + hwtnl->index_bias;
  307.       unsigned width;
  308.  
  309.       assert(vb);
  310.       assert(size);
  311.       assert(offset < size);
  312.       assert(min_index <= max_index);
  313.  
  314.       switch (hwtnl->cmd.vdecl[i].identity.type) {
  315.       case SVGA3D_DECLTYPE_FLOAT1:
  316.          width = 4;
  317.          break;
  318.       case SVGA3D_DECLTYPE_FLOAT2:
  319.          width = 4 * 2;
  320.          break;
  321.       case SVGA3D_DECLTYPE_FLOAT3:
  322.          width = 4 * 3;
  323.          break;
  324.       case SVGA3D_DECLTYPE_FLOAT4:
  325.          width = 4 * 4;
  326.          break;
  327.       case SVGA3D_DECLTYPE_D3DCOLOR:
  328.          width = 4;
  329.          break;
  330.       case SVGA3D_DECLTYPE_UBYTE4:
  331.          width = 1 * 4;
  332.          break;
  333.       case SVGA3D_DECLTYPE_SHORT2:
  334.          width = 2 * 2;
  335.          break;
  336.       case SVGA3D_DECLTYPE_SHORT4:
  337.          width = 2 * 4;
  338.          break;
  339.       case SVGA3D_DECLTYPE_UBYTE4N:
  340.          width = 1 * 4;
  341.          break;
  342.       case SVGA3D_DECLTYPE_SHORT2N:
  343.          width = 2 * 2;
  344.          break;
  345.       case SVGA3D_DECLTYPE_SHORT4N:
  346.          width = 2 * 4;
  347.          break;
  348.       case SVGA3D_DECLTYPE_USHORT2N:
  349.          width = 2 * 2;
  350.          break;
  351.       case SVGA3D_DECLTYPE_USHORT4N:
  352.          width = 2 * 4;
  353.          break;
  354.       case SVGA3D_DECLTYPE_UDEC3:
  355.          width = 4;
  356.          break;
  357.       case SVGA3D_DECLTYPE_DEC3N:
  358.          width = 4;
  359.          break;
  360.       case SVGA3D_DECLTYPE_FLOAT16_2:
  361.          width = 2 * 2;
  362.          break;
  363.       case SVGA3D_DECLTYPE_FLOAT16_4:
  364.          width = 2 * 4;
  365.          break;
  366.       default:
  367.          assert(0);
  368.          width = 0;
  369.          break;
  370.       }
  371.  
  372.       if (index_bias >= 0) {
  373.          assert(offset + index_bias * stride + width <= size);
  374.       }
  375.  
  376.       /*
  377.        * min_index/max_index are merely conservative guesses, so we can't
  378.        * make buffer overflow detection based on their values.
  379.        */
  380.    }
  381.  
  382.    assert(range->indexWidth == range->indexArray.stride);
  383.  
  384.    if (ib) {
  385.       unsigned size = ib->width0;
  386.       unsigned offset = range->indexArray.offset;
  387.       unsigned stride = range->indexArray.stride;
  388.       unsigned count;
  389.  
  390.       assert(size);
  391.       assert(offset < size);
  392.       assert(stride);
  393.  
  394.       switch (range->primType) {
  395.       case SVGA3D_PRIMITIVE_POINTLIST:
  396.          count = range->primitiveCount;
  397.          break;
  398.       case SVGA3D_PRIMITIVE_LINELIST:
  399.          count = range->primitiveCount * 2;
  400.          break;
  401.       case SVGA3D_PRIMITIVE_LINESTRIP:
  402.          count = range->primitiveCount + 1;
  403.          break;
  404.       case SVGA3D_PRIMITIVE_TRIANGLELIST:
  405.          count = range->primitiveCount * 3;
  406.          break;
  407.       case SVGA3D_PRIMITIVE_TRIANGLESTRIP:
  408.          count = range->primitiveCount + 2;
  409.          break;
  410.       case SVGA3D_PRIMITIVE_TRIANGLEFAN:
  411.          count = range->primitiveCount + 2;
  412.          break;
  413.       default:
  414.          assert(0);
  415.          count = 0;
  416.          break;
  417.       }
  418.  
  419.       assert(offset + count * stride <= size);
  420.    }
  421. }
  422.  
  423.  
  424. enum pipe_error
  425. svga_hwtnl_prim(struct svga_hwtnl *hwtnl,
  426.                 const SVGA3dPrimitiveRange * range,
  427.                 unsigned min_index,
  428.                 unsigned max_index, struct pipe_resource *ib)
  429. {
  430.    enum pipe_error ret = PIPE_OK;
  431.  
  432. #ifdef DEBUG
  433.    check_draw_params(hwtnl, range, min_index, max_index, ib);
  434. #endif
  435.  
  436.    if (hwtnl->cmd.prim_count + 1 >= QSZ) {
  437.       ret = svga_hwtnl_flush(hwtnl);
  438.       if (ret != PIPE_OK)
  439.          return ret;
  440.    }
  441.  
  442.    /* min/max indices are relative to bias */
  443.    hwtnl->cmd.min_index[hwtnl->cmd.prim_count] = min_index;
  444.    hwtnl->cmd.max_index[hwtnl->cmd.prim_count] = max_index;
  445.  
  446.    hwtnl->cmd.prim[hwtnl->cmd.prim_count] = *range;
  447.    hwtnl->cmd.prim[hwtnl->cmd.prim_count].indexBias += hwtnl->index_bias;
  448.  
  449.    pipe_resource_reference(&hwtnl->cmd.prim_ib[hwtnl->cmd.prim_count], ib);
  450.    hwtnl->cmd.prim_count++;
  451.  
  452.    return ret;
  453. }
  454.