Home | History | Annotate | Download | only in svga
      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    int 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