Subversion Repositories Kolibri OS

Rev

Go to most recent revision | 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 *svga_hwtnl_create( struct svga_context *svga,
  46.                                       struct u_upload_mgr *upload_ib,
  47.                                       struct svga_winsys_context *swc )
  48. {
  49.    struct svga_hwtnl *hwtnl = CALLOC_STRUCT(svga_hwtnl);
  50.    if (hwtnl == NULL)
  51.       goto fail;
  52.  
  53.    hwtnl->svga = svga;
  54.    hwtnl->upload_ib = upload_ib;
  55.    
  56.    hwtnl->cmd.swc = swc;
  57.  
  58.    return hwtnl;
  59.  
  60. fail:
  61.    return NULL;
  62. }
  63.  
  64. void 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,
  71.                                 NULL );
  72.       }
  73.    }
  74.  
  75.    for (i = 0; i < hwtnl->cmd.vdecl_count; i++)
  76.       pipe_resource_reference(&hwtnl->cmd.vdecl_vb[i], NULL);
  77.  
  78.    for (i = 0; i < hwtnl->cmd.prim_count; i++)
  79.       pipe_resource_reference(&hwtnl->cmd.prim_ib[i], NULL);
  80.      
  81.  
  82.    FREE(hwtnl);
  83. }
  84.  
  85.  
  86. void svga_hwtnl_set_flatshade( struct svga_hwtnl *hwtnl,
  87.                                boolean flatshade,
  88.                                boolean flatshade_first )
  89. {
  90.    hwtnl->hw_pv = PV_FIRST;
  91.    hwtnl->api_pv = (flatshade && !flatshade_first) ? PV_LAST : PV_FIRST;
  92. }                              
  93.  
  94. void svga_hwtnl_set_unfilled( struct svga_hwtnl *hwtnl,
  95.                               unsigned mode )
  96. {
  97.    hwtnl->api_fillmode = mode;
  98. }                              
  99.  
  100. void svga_hwtnl_reset_vdecl( struct svga_hwtnl *hwtnl,
  101.                              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],
  109.                             NULL);
  110.    }
  111.  
  112.    hwtnl->cmd.vdecl_count = count;
  113. }
  114.  
  115.  
  116. void svga_hwtnl_vdecl( struct svga_hwtnl *hwtnl,
  117.                        unsigned i,
  118.                        const SVGA3dVertexDecl *decl,
  119.                        struct pipe_resource *vb)
  120. {
  121.    assert(hwtnl->cmd.prim_count == 0);
  122.  
  123.    assert( i < hwtnl->cmd.vdecl_count );
  124.  
  125.    hwtnl->cmd.vdecl[i] = *decl;
  126.  
  127.    pipe_resource_reference(&hwtnl->cmd.vdecl_vb[i], vb);  
  128. }
  129.  
  130.  
  131. /**
  132.  * Determine whether the specified buffer is referred in the primitive queue,
  133.  * for which no commands have been written yet.
  134.  */
  135. boolean
  136. svga_hwtnl_is_buffer_referred( struct svga_hwtnl *hwtnl,
  137.                                struct pipe_resource *buffer)
  138. {
  139.    unsigned i;
  140.  
  141.    if (svga_buffer_is_user_buffer(buffer)) {
  142.       return FALSE;
  143.    }
  144.  
  145.    if (!hwtnl->cmd.prim_count) {
  146.       return FALSE;
  147.    }
  148.  
  149.    for (i = 0; i < hwtnl->cmd.vdecl_count; ++i) {
  150.       if (hwtnl->cmd.vdecl_vb[i] == buffer) {
  151.          return TRUE;
  152.       }
  153.    }
  154.  
  155.    for (i = 0; i < hwtnl->cmd.prim_count; ++i) {
  156.       if (hwtnl->cmd.prim_ib[i] == buffer) {
  157.          return TRUE;
  158.       }
  159.    }
  160.  
  161.    return FALSE;
  162. }
  163.  
  164.  
  165. enum pipe_error
  166. svga_hwtnl_flush( struct svga_hwtnl *hwtnl )
  167. {
  168.    struct svga_winsys_context *swc = hwtnl->cmd.swc;
  169.    struct svga_context *svga = hwtnl->svga;
  170.    enum pipe_error ret;
  171.  
  172.    if (hwtnl->cmd.prim_count) {
  173.       struct svga_winsys_surface *vb_handle[SVGA3D_INPUTREG_MAX];
  174.       struct svga_winsys_surface *ib_handle[QSZ];
  175.       struct svga_winsys_surface *handle;
  176.       SVGA3dVertexDecl *vdecl;
  177.       SVGA3dPrimitiveRange *prim;
  178.       unsigned i;
  179.  
  180.       /* Unmap upload manager vertex buffers */
  181.       u_upload_unmap(svga->upload_vb);
  182.  
  183.       for (i = 0; i < hwtnl->cmd.vdecl_count; i++) {
  184.          handle = svga_buffer_handle(svga, hwtnl->cmd.vdecl_vb[i]);
  185.          if (handle == NULL)
  186.             return PIPE_ERROR_OUT_OF_MEMORY;
  187.  
  188.          vb_handle[i] = handle;
  189.       }
  190.  
  191.       /* Unmap upload manager index buffers */
  192.       u_upload_unmap(svga->upload_ib);
  193.  
  194.       for (i = 0; i < hwtnl->cmd.prim_count; i++) {
  195.          if (hwtnl->cmd.prim_ib[i]) {
  196.             handle = svga_buffer_handle(svga, hwtnl->cmd.prim_ib[i]);
  197.             if (handle == NULL)
  198.                return PIPE_ERROR_OUT_OF_MEMORY;
  199.          }
  200.          else
  201.             handle = NULL;
  202.  
  203.          ib_handle[i] = handle;
  204.       }
  205.  
  206.       if (svga->rebind.rendertargets) {
  207.          ret = svga_reemit_framebuffer_bindings(svga);
  208.          if (ret != PIPE_OK) {
  209.             return ret;
  210.          }
  211.       }
  212.  
  213.       if (svga->rebind.texture_samplers) {
  214.          ret = svga_reemit_tss_bindings(svga);
  215.          if (ret != PIPE_OK) {
  216.             return ret;
  217.          }
  218.       }
  219.  
  220.       SVGA_DBG(DEBUG_DMA, "draw to sid %p, %d prims\n",
  221.                svga->curr.framebuffer.cbufs[0] ?
  222.                svga_surface(svga->curr.framebuffer.cbufs[0])->handle : NULL,
  223.                hwtnl->cmd.prim_count);
  224.  
  225.       ret = SVGA3D_BeginDrawPrimitives(swc,
  226.                                        &vdecl,
  227.                                        hwtnl->cmd.vdecl_count,
  228.                                        &prim,
  229.                                        hwtnl->cmd.prim_count);
  230.       if (ret != PIPE_OK)
  231.          return ret;
  232.  
  233.      
  234.       memcpy( vdecl,
  235.               hwtnl->cmd.vdecl,
  236.               hwtnl->cmd.vdecl_count * sizeof hwtnl->cmd.vdecl[0]);
  237.  
  238.       for (i = 0; i < hwtnl->cmd.vdecl_count; i++) {
  239.          /* Given rangeHint is considered to be relative to indexBias, and
  240.           * indexBias varies per primitive, we cannot accurately supply an
  241.           * rangeHint when emitting more than one primitive per draw command.
  242.           */
  243.          if (hwtnl->cmd.prim_count == 1) {
  244.             vdecl[i].rangeHint.first = hwtnl->cmd.min_index[0];
  245.             vdecl[i].rangeHint.last = hwtnl->cmd.max_index[0] + 1;
  246.          }
  247.          else {
  248.             vdecl[i].rangeHint.first = 0;
  249.             vdecl[i].rangeHint.last = 0;
  250.          }
  251.  
  252.          swc->surface_relocation(swc,
  253.                                  &vdecl[i].array.surfaceId,
  254.                                  vb_handle[i],
  255.                                  SVGA_RELOC_READ);
  256.       }
  257.  
  258.       memcpy( prim,
  259.               hwtnl->cmd.prim,
  260.               hwtnl->cmd.prim_count * sizeof hwtnl->cmd.prim[0]);
  261.  
  262.       for (i = 0; i < hwtnl->cmd.prim_count; i++) {
  263.          swc->surface_relocation(swc,
  264.                                  &prim[i].indexArray.surfaceId,
  265.                                  ib_handle[i],
  266.                                  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 svga_hwtnl_set_index_bias( struct svga_hwtnl *hwtnl,
  279.                                 int index_bias)
  280. {
  281.    hwtnl->index_bias = index_bias;
  282. }
  283.  
  284.  
  285.  
  286. /***********************************************************************
  287.  * Internal functions:
  288.  */
  289.  
  290. enum pipe_error svga_hwtnl_prim( struct svga_hwtnl *hwtnl,
  291.                                  const SVGA3dPrimitiveRange *range,
  292.                                  unsigned min_index,
  293.                                  unsigned max_index,
  294.                                  struct pipe_resource *ib )
  295. {
  296.    enum pipe_error ret = PIPE_OK;
  297.  
  298. #ifdef DEBUG
  299.    {
  300.       unsigned i;
  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. #endif
  423.  
  424.    if (hwtnl->cmd.prim_count+1 >= QSZ) {
  425.       ret = svga_hwtnl_flush( hwtnl );
  426.       if (ret != PIPE_OK)
  427.          return ret;
  428.    }
  429.    
  430.    /* min/max indices are relative to bias */
  431.    hwtnl->cmd.min_index[hwtnl->cmd.prim_count] = min_index;
  432.    hwtnl->cmd.max_index[hwtnl->cmd.prim_count] = max_index;
  433.  
  434.    hwtnl->cmd.prim[hwtnl->cmd.prim_count] = *range;
  435.    hwtnl->cmd.prim[hwtnl->cmd.prim_count].indexBias += hwtnl->index_bias;
  436.  
  437.    pipe_resource_reference(&hwtnl->cmd.prim_ib[hwtnl->cmd.prim_count], ib);
  438.    hwtnl->cmd.prim_count++;
  439.  
  440.    return ret;
  441. }
  442.