Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  1. /*
  2.  * Copyright 2011 Joakim Sindholt <opensource@zhasha.com>
  3.  *
  4.  * Permission is hereby granted, free of charge, to any person obtaining a
  5.  * copy of this software and associated documentation files (the "Software"),
  6.  * to deal in the Software without restriction, including without limitation
  7.  * on the rights to use, copy, modify, merge, publish, distribute, sub
  8.  * license, and/or sell copies of the Software, and to permit persons to whom
  9.  * the Software is furnished to do so, subject to the following conditions:
  10.  *
  11.  * The above copyright notice and this permission notice (including the next
  12.  * paragraph) shall be included in all copies or substantial portions of the
  13.  * Software.
  14.  *
  15.  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  16.  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  17.  * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
  18.  * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
  19.  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
  20.  * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
  21.  * USE OR OTHER DEALINGS IN THE SOFTWARE. */
  22.  
  23. #include "vertexdeclaration9.h"
  24. #include "vertexbuffer9.h"
  25. #include "device9.h"
  26. #include "nine_helpers.h"
  27.  
  28. #include "pipe/p_format.h"
  29. #include "pipe/p_context.h"
  30. #include "util/u_math.h"
  31. #include "util/u_format.h"
  32. #include "util/u_box.h"
  33. #include "translate/translate.h"
  34.  
  35. #define DBG_CHANNEL DBG_VERTEXDECLARATION
  36.  
  37. static INLINE enum pipe_format decltype_format(BYTE type)
  38. {
  39.     switch (type) {
  40.     case D3DDECLTYPE_FLOAT1:    return PIPE_FORMAT_R32_FLOAT;
  41.     case D3DDECLTYPE_FLOAT2:    return PIPE_FORMAT_R32G32_FLOAT;
  42.     case D3DDECLTYPE_FLOAT3:    return PIPE_FORMAT_R32G32B32_FLOAT;
  43.     case D3DDECLTYPE_FLOAT4:    return PIPE_FORMAT_R32G32B32A32_FLOAT;
  44.     case D3DDECLTYPE_D3DCOLOR:  return PIPE_FORMAT_B8G8R8A8_UNORM;
  45.     case D3DDECLTYPE_UBYTE4:    return PIPE_FORMAT_R8G8B8A8_USCALED;
  46.     case D3DDECLTYPE_SHORT2:    return PIPE_FORMAT_R16G16_SSCALED;
  47.     case D3DDECLTYPE_SHORT4:    return PIPE_FORMAT_R16G16B16A16_SSCALED;
  48.     case D3DDECLTYPE_UBYTE4N:   return PIPE_FORMAT_R8G8B8A8_UNORM;
  49.     case D3DDECLTYPE_SHORT2N:   return PIPE_FORMAT_R16G16_SNORM;
  50.     case D3DDECLTYPE_SHORT4N:   return PIPE_FORMAT_R16G16B16A16_SNORM;
  51.     case D3DDECLTYPE_USHORT2N:  return PIPE_FORMAT_R16G16_UNORM;
  52.     case D3DDECLTYPE_USHORT4N:  return PIPE_FORMAT_R16G16B16A16_UNORM;
  53.     case D3DDECLTYPE_UDEC3:     return PIPE_FORMAT_R10G10B10X2_USCALED;
  54.     case D3DDECLTYPE_DEC3N:     return PIPE_FORMAT_R10G10B10X2_SNORM;
  55.     case D3DDECLTYPE_FLOAT16_2: return PIPE_FORMAT_R16G16_FLOAT;
  56.     case D3DDECLTYPE_FLOAT16_4: return PIPE_FORMAT_R16G16B16A16_FLOAT;
  57.     default:
  58.         assert(!"Implementation error !");
  59.     }
  60.     return PIPE_FORMAT_NONE;
  61. }
  62.  
  63. static INLINE unsigned decltype_size(BYTE type)
  64. {
  65.     switch (type) {
  66.     case D3DDECLTYPE_FLOAT1: return 1 * sizeof(float);
  67.     case D3DDECLTYPE_FLOAT2: return 2 * sizeof(float);
  68.     case D3DDECLTYPE_FLOAT3: return 3 * sizeof(float);
  69.     case D3DDECLTYPE_FLOAT4: return 4 * sizeof(float);
  70.     case D3DDECLTYPE_D3DCOLOR: return 1 * sizeof(DWORD);
  71.     case D3DDECLTYPE_UBYTE4: return 4 * sizeof(BYTE);
  72.     case D3DDECLTYPE_SHORT2: return 2 * sizeof(short);
  73.     case D3DDECLTYPE_SHORT4: return 4 * sizeof(short);
  74.     case D3DDECLTYPE_UBYTE4N: return 4 * sizeof(BYTE);
  75.     case D3DDECLTYPE_SHORT2N: return 2 * sizeof(short);
  76.     case D3DDECLTYPE_SHORT4N: return 4 * sizeof(short);
  77.     case D3DDECLTYPE_USHORT2N: return 2 * sizeof(short);
  78.     case D3DDECLTYPE_USHORT4N: return 4 * sizeof(short);
  79.     case D3DDECLTYPE_UDEC3: return 4;
  80.     case D3DDECLTYPE_DEC3N: return 4;
  81.     case D3DDECLTYPE_FLOAT16_2: return 2 * 2;
  82.     case D3DDECLTYPE_FLOAT16_4: return 4 * 2;
  83.     default:
  84.         assert(!"Implementation error !");
  85.     }
  86.     return 0;
  87. }
  88.  
  89. /* Actually, arbitrary usage index values are permitted, but a
  90.  * simple lookup table won't work in that case. Let's just wait
  91.  * with making this more generic until we need it.
  92.  */
  93. static INLINE boolean
  94. nine_d3ddeclusage_check(unsigned usage, unsigned usage_idx)
  95. {
  96.     switch (usage) {
  97.     case D3DDECLUSAGE_POSITIONT:
  98.     case D3DDECLUSAGE_TESSFACTOR:
  99.     case D3DDECLUSAGE_DEPTH:
  100.     case D3DDECLUSAGE_NORMAL:
  101.     case D3DDECLUSAGE_TANGENT:
  102.     case D3DDECLUSAGE_BINORMAL:
  103.     case D3DDECLUSAGE_POSITION:
  104.     case D3DDECLUSAGE_BLENDWEIGHT:
  105.     case D3DDECLUSAGE_BLENDINDICES:
  106.     case D3DDECLUSAGE_COLOR:
  107.         return TRUE;
  108.     case D3DDECLUSAGE_PSIZE:
  109.     case D3DDECLUSAGE_FOG:
  110.     case D3DDECLUSAGE_SAMPLE:
  111.         return usage_idx <= 0;
  112.     case D3DDECLUSAGE_TEXCOORD:
  113.         return usage_idx <= 15;
  114.     default:
  115.         return FALSE;
  116.     }
  117. }
  118.  
  119. #define NINE_DECLUSAGE_CASE0(n) case D3DDECLUSAGE_##n: return NINE_DECLUSAGE_##n
  120. #define NINE_DECLUSAGE_CASEi(n) case D3DDECLUSAGE_##n: return NINE_DECLUSAGE_i(n, usage_idx)
  121. uint16_t
  122. nine_d3d9_to_nine_declusage(unsigned usage, unsigned usage_idx)
  123. {
  124.     if (!nine_d3ddeclusage_check(usage, usage_idx))
  125.         ERR("D3DDECLUSAGE_%u[%u]\n",usage,usage_idx);
  126.     assert(nine_d3ddeclusage_check(usage, usage_idx));
  127.     switch (usage) {
  128.     NINE_DECLUSAGE_CASEi(POSITION);
  129.     NINE_DECLUSAGE_CASEi(BLENDWEIGHT);
  130.     NINE_DECLUSAGE_CASEi(BLENDINDICES);
  131.     NINE_DECLUSAGE_CASEi(NORMAL);
  132.     NINE_DECLUSAGE_CASE0(PSIZE);
  133.     NINE_DECLUSAGE_CASEi(TEXCOORD);
  134.     NINE_DECLUSAGE_CASEi(TANGENT);
  135.     NINE_DECLUSAGE_CASEi(BINORMAL);
  136.     NINE_DECLUSAGE_CASE0(TESSFACTOR);
  137.     NINE_DECLUSAGE_CASEi(POSITIONT);
  138.     NINE_DECLUSAGE_CASEi(COLOR);
  139.     NINE_DECLUSAGE_CASE0(DEPTH);
  140.     NINE_DECLUSAGE_CASE0(FOG);
  141.     NINE_DECLUSAGE_CASE0(SAMPLE);
  142.     default:
  143.         assert(!"Invalid DECLUSAGE.");
  144.         return NINE_DECLUSAGE_NONE;
  145.     }
  146. }
  147.  
  148. static const char *nine_declusage_names[] =
  149. {
  150.     [NINE_DECLUSAGE_POSITION]        = "POSITION",
  151.     [NINE_DECLUSAGE_BLENDWEIGHT]     = "BLENDWEIGHT",
  152.     [NINE_DECLUSAGE_BLENDINDICES]    = "BLENDINDICES",
  153.     [NINE_DECLUSAGE_NORMAL]          = "NORMAL",
  154.     [NINE_DECLUSAGE_PSIZE]           = "PSIZE",
  155.     [NINE_DECLUSAGE_TEXCOORD]        = "TEXCOORD",
  156.     [NINE_DECLUSAGE_TANGENT]         = "TANGENT",
  157.     [NINE_DECLUSAGE_BINORMAL]        = "BINORMAL",
  158.     [NINE_DECLUSAGE_TESSFACTOR]      = "TESSFACTOR",
  159.     [NINE_DECLUSAGE_POSITIONT]       = "POSITIONT",
  160.     [NINE_DECLUSAGE_COLOR]           = "DIFFUSE",
  161.     [NINE_DECLUSAGE_DEPTH]           = "DEPTH",
  162.     [NINE_DECLUSAGE_FOG]             = "FOG",
  163.     [NINE_DECLUSAGE_NONE]            = "(NONE)",
  164. };
  165. static INLINE const char *
  166. nine_declusage_name(unsigned ndcl)
  167. {
  168.     return nine_declusage_names[ndcl % NINE_DECLUSAGE_COUNT];
  169. }
  170.  
  171. HRESULT
  172. NineVertexDeclaration9_ctor( struct NineVertexDeclaration9 *This,
  173.                              struct NineUnknownParams *pParams,
  174.                              const D3DVERTEXELEMENT9 *pElements )
  175. {
  176.     const D3DCAPS9 *caps;
  177.     unsigned i;
  178.  
  179.     DBG("This=%p pParams=%p pElements=%p\n", This, pParams, pElements);
  180.  
  181.     HRESULT hr = NineUnknown_ctor(&This->base, pParams);
  182.     if (FAILED(hr)) { return hr; }
  183.  
  184.     /* wine */
  185.     for (This->nelems = 0;
  186.          pElements[This->nelems].Stream != 0xFF;
  187.          ++This->nelems) {
  188.         user_assert(pElements[This->nelems].Type != D3DDECLTYPE_UNUSED, E_FAIL);
  189.         user_assert(!(pElements[This->nelems].Offset & 3), E_FAIL);
  190.     }
  191.  
  192.     caps = NineDevice9_GetCaps(This->base.device);
  193.     user_assert(This->nelems <= caps->MaxStreams, D3DERR_INVALIDCALL);
  194.  
  195.     This->decls = CALLOC(This->nelems+1, sizeof(D3DVERTEXELEMENT9));
  196.     This->elems = CALLOC(This->nelems, sizeof(struct pipe_vertex_element));
  197.     This->usage_map = CALLOC(This->nelems, sizeof(uint16_t));
  198.     if (!This->decls || !This->elems || !This->usage_map) { return E_OUTOFMEMORY; }
  199.     memcpy(This->decls, pElements, sizeof(D3DVERTEXELEMENT9)*(This->nelems+1));
  200.  
  201.     for (i = 0; i < This->nelems; ++i) {
  202.         uint16_t usage = nine_d3d9_to_nine_declusage(This->decls[i].Usage,
  203.                                                      This->decls[i].UsageIndex);
  204.         This->usage_map[i] = usage;
  205.  
  206.         This->elems[i].src_offset = This->decls[i].Offset;
  207.         This->elems[i].instance_divisor = 0;
  208.         This->elems[i].vertex_buffer_index = This->decls[i].Stream;
  209.         This->elems[i].src_format = decltype_format(This->decls[i].Type);
  210.         /* XXX Remember Method (tesselation), Usage, UsageIndex */
  211.  
  212.         DBG("VERTEXELEMENT[%u]: Stream=%u Offset=%u Type=%s DeclUsage=%s%d\n", i,
  213.             This->decls[i].Stream,
  214.             This->decls[i].Offset,
  215.             util_format_name(This->elems[i].src_format),
  216.             nine_declusage_name(usage),
  217.             usage / NINE_DECLUSAGE_COUNT);
  218.     }
  219.  
  220.     return D3D_OK;
  221. }
  222.  
  223. void
  224. NineVertexDeclaration9_dtor( struct NineVertexDeclaration9 *This )
  225. {
  226.     FREE(This->decls);
  227.     FREE(This->elems);
  228.     FREE(This->usage_map);
  229.  
  230.     NineUnknown_dtor(&This->base);
  231. }
  232.  
  233. HRESULT WINAPI
  234. NineVertexDeclaration9_GetDeclaration( struct NineVertexDeclaration9 *This,
  235.                                        D3DVERTEXELEMENT9 *pElement,
  236.                                        UINT *pNumElements )
  237. {
  238.     if (!pElement) {
  239.         user_assert(pNumElements, D3DERR_INVALIDCALL);
  240.         *pNumElements = This->nelems+1;
  241.         return D3D_OK;
  242.     }
  243.     if (pNumElements) { *pNumElements = This->nelems+1; }
  244.     memcpy(pElement, This->decls, sizeof(D3DVERTEXELEMENT9)*(This->nelems+1));
  245.     return D3D_OK;
  246. }
  247.  
  248. IDirect3DVertexDeclaration9Vtbl NineVertexDeclaration9_vtable = {
  249.     (void *)NineUnknown_QueryInterface,
  250.     (void *)NineUnknown_AddRef,
  251.     (void *)NineUnknown_Release,
  252.     (void *)NineUnknown_GetDevice, /* actually part of VertexDecl9 iface */
  253.     (void *)NineVertexDeclaration9_GetDeclaration
  254. };
  255.  
  256. static const GUID *NineVertexDeclaration9_IIDs[] = {
  257.     &IID_IDirect3DVertexDeclaration9,
  258.     &IID_IUnknown,
  259.     NULL
  260. };
  261.  
  262. HRESULT
  263. NineVertexDeclaration9_new( struct NineDevice9 *pDevice,
  264.                             const D3DVERTEXELEMENT9 *pElements,
  265.                             struct NineVertexDeclaration9 **ppOut )
  266. {
  267.     NINE_DEVICE_CHILD_NEW(VertexDeclaration9, ppOut, /* args */ pDevice, pElements);
  268. }
  269.  
  270. HRESULT
  271. NineVertexDeclaration9_new_from_fvf( struct NineDevice9 *pDevice,
  272.                                      DWORD FVF,
  273.                                      struct NineVertexDeclaration9 **ppOut )
  274. {
  275.     D3DVERTEXELEMENT9 elems[16], decl_end = D3DDECL_END();
  276.     unsigned texcount, i, betas, nelems = 0;
  277.     BYTE beta_index = 0xFF;
  278.  
  279.     switch (FVF & D3DFVF_POSITION_MASK) {
  280.         case D3DFVF_XYZ: /* simple XYZ */
  281.         case D3DFVF_XYZB1:
  282.         case D3DFVF_XYZB2:
  283.         case D3DFVF_XYZB3:
  284.         case D3DFVF_XYZB4:
  285.         case D3DFVF_XYZB5: /* XYZ with beta values */
  286.             elems[nelems].Type = D3DDECLTYPE_FLOAT3;
  287.             elems[nelems].Usage = D3DDECLUSAGE_POSITION;
  288.             elems[nelems].UsageIndex = 0;
  289.             ++nelems;
  290.             /* simple XYZ has no beta values. break. */
  291.             if ((FVF & D3DFVF_POSITION_MASK) == D3DFVF_XYZ) { break; }
  292.  
  293.             betas = (((FVF & D3DFVF_XYZB5)-D3DFVF_XYZB1)>>1)+1;
  294.             if (FVF & D3DFVF_LASTBETA_D3DCOLOR) {
  295.                 beta_index = D3DDECLTYPE_D3DCOLOR;
  296.             } else if (FVF & D3DFVF_LASTBETA_UBYTE4) {
  297.                 beta_index = D3DDECLTYPE_UBYTE4;
  298.             } else if ((FVF & D3DFVF_XYZB5) == D3DFVF_XYZB5) {
  299.                 beta_index = D3DDECLTYPE_FLOAT1;
  300.             }
  301.             if (beta_index != 0xFF) { --betas; }
  302.  
  303.             if (betas > 0) {
  304.                 switch (betas) {
  305.                     case 1: elems[nelems].Type = D3DDECLTYPE_FLOAT1; break;
  306.                     case 2: elems[nelems].Type = D3DDECLTYPE_FLOAT2; break;
  307.                     case 3: elems[nelems].Type = D3DDECLTYPE_FLOAT3; break;
  308.                     case 4: elems[nelems].Type = D3DDECLTYPE_FLOAT4; break;
  309.                     default:
  310.                         assert(!"Implementation error!");
  311.                 }
  312.                 elems[nelems].Usage = D3DDECLUSAGE_BLENDWEIGHT;
  313.                 elems[nelems].UsageIndex = 0;
  314.                 ++nelems;
  315.             }
  316.  
  317.             if (beta_index != 0xFF) {
  318.                 elems[nelems].Type = beta_index;
  319.                 elems[nelems].Usage = D3DDECLUSAGE_BLENDINDICES;
  320.                 elems[nelems].UsageIndex = 0;
  321.                 ++nelems;
  322.             }
  323.             break;
  324.  
  325.         case D3DFVF_XYZW: /* simple XYZW */
  326.         case D3DFVF_XYZRHW: /* pretransformed XYZW */
  327.             elems[nelems].Type = D3DDECLTYPE_FLOAT4;
  328.             elems[nelems].Usage =
  329.                 ((FVF & D3DFVF_POSITION_MASK) == D3DFVF_XYZW) ?
  330.                 D3DDECLUSAGE_POSITION : D3DDECLUSAGE_POSITIONT;
  331.             elems[nelems].UsageIndex = 0;
  332.             ++nelems;
  333.             break;
  334.  
  335.         default:
  336.             (void)user_error(!"Position doesn't match any known combination");
  337.     }
  338.  
  339.     /* normals, psize and colors */
  340.     if (FVF & D3DFVF_NORMAL) {
  341.         elems[nelems].Type = D3DDECLTYPE_FLOAT3;
  342.         elems[nelems].Usage = D3DDECLUSAGE_NORMAL;
  343.         elems[nelems].UsageIndex = 0;
  344.         ++nelems;
  345.     }
  346.     if (FVF & D3DFVF_PSIZE) {
  347.         elems[nelems].Type = D3DDECLTYPE_FLOAT1;
  348.         elems[nelems].Usage = D3DDECLUSAGE_PSIZE;
  349.         elems[nelems].UsageIndex = 0;
  350.         ++nelems;
  351.     }
  352.     if (FVF & D3DFVF_DIFFUSE) {
  353.         elems[nelems].Type = D3DDECLTYPE_D3DCOLOR;
  354.         elems[nelems].Usage = D3DDECLUSAGE_COLOR;
  355.         elems[nelems].UsageIndex = 0;
  356.         ++nelems;
  357.     }
  358.     if (FVF & D3DFVF_SPECULAR) {
  359.         elems[nelems].Type = D3DDECLTYPE_D3DCOLOR;
  360.         elems[nelems].Usage = D3DDECLUSAGE_COLOR;
  361.         elems[nelems].UsageIndex = 1;
  362.         ++nelems;
  363.     }
  364.  
  365.     /* textures */
  366.     texcount = (FVF & D3DFVF_TEXCOUNT_MASK) >> D3DFVF_TEXCOUNT_SHIFT;
  367.     if (user_error(texcount <= 8)) { texcount = 8; }
  368.  
  369.     for (i = 0; i < texcount; ++i) {
  370.         switch ((FVF >> (16+i*2)) & 0x3) {
  371.             case D3DFVF_TEXTUREFORMAT1:
  372.                 elems[nelems].Type = D3DDECLTYPE_FLOAT1;
  373.                 break;
  374.  
  375.             case D3DFVF_TEXTUREFORMAT2:
  376.                 elems[nelems].Type = D3DDECLTYPE_FLOAT2;
  377.                 break;
  378.  
  379.             case D3DFVF_TEXTUREFORMAT3:
  380.                 elems[nelems].Type = D3DDECLTYPE_FLOAT3;
  381.                 break;
  382.  
  383.             case D3DFVF_TEXTUREFORMAT4:
  384.                 elems[nelems].Type = D3DDECLTYPE_FLOAT4;
  385.                 break;
  386.  
  387.             default:
  388.                 assert(!"Implementation error!");
  389.         }
  390.         elems[nelems].Usage = D3DDECLUSAGE_TEXCOORD;
  391.         elems[nelems].UsageIndex = i;
  392.         ++nelems;
  393.     }
  394.  
  395.     /* fill out remaining data */
  396.     for (i = 0; i < nelems; ++i) {
  397.         elems[i].Stream = 0;
  398.         elems[i].Offset = (i == 0) ? 0 : (elems[i-1].Offset +
  399.                                           decltype_size(elems[i-1].Type));
  400.         elems[i].Method = D3DDECLMETHOD_DEFAULT;
  401.     }
  402.     elems[nelems++] = decl_end;
  403.  
  404.     NINE_DEVICE_CHILD_NEW(VertexDeclaration9, ppOut, /* args */ pDevice, elems);
  405. }
  406.  
  407. /* ProcessVertices runs stream output into a temporary buffer to capture
  408.  * all outputs.
  409.  * Now we have to convert them to the format and order set by the vertex
  410.  * declaration, for which we use u_translate.
  411.  * This is necessary if the vertex declaration contains elements using a
  412.  * non float32 format, because stream output only supports f32/u32/s32.
  413.  */
  414. HRESULT
  415. NineVertexDeclaration9_ConvertStreamOutput(
  416.     struct NineVertexDeclaration9 *This,
  417.     struct NineVertexBuffer9 *pDstBuf,
  418.     UINT DestIndex,
  419.     UINT VertexCount,
  420.     struct pipe_resource *pSrcBuf,
  421.     const struct pipe_stream_output_info *so )
  422. {
  423.     struct pipe_context *pipe = This->base.device->pipe;
  424.     struct pipe_transfer *transfer = NULL;
  425.     struct translate *translate;
  426.     struct translate_key transkey;
  427.     struct pipe_box box;
  428.     HRESULT hr;
  429.     unsigned i;
  430.     void *src_map;
  431.     void *dst_map;
  432.  
  433.     DBG("This=%p pDstBuf=%p DestIndex=%u VertexCount=%u pSrcBuf=%p so=%p\n",
  434.         This, pDstBuf, DestIndex, VertexCount, pSrcBuf, so);
  435.  
  436.     transkey.output_stride = 0;
  437.     for (i = 0; i < This->nelems; ++i) {
  438.         enum pipe_format format;
  439.  
  440.         switch (so->output[i].num_components) {
  441.         case 1: format = PIPE_FORMAT_R32_FLOAT; break;
  442.         case 2: format = PIPE_FORMAT_R32G32_FLOAT; break;
  443.         case 3: format = PIPE_FORMAT_R32G32B32_FLOAT; break;
  444.         default:
  445.             assert(so->output[i].num_components == 4);
  446.             format = PIPE_FORMAT_R32G32B32A32_FLOAT;
  447.             break;
  448.         }
  449.         transkey.element[i].type = TRANSLATE_ELEMENT_NORMAL;
  450.         transkey.element[i].input_format = format;
  451.         transkey.element[i].input_buffer = 0;
  452.         transkey.element[i].input_offset = so->output[i].dst_offset * 4;
  453.         transkey.element[i].instance_divisor = 0;
  454.  
  455.         transkey.element[i].output_format = This->elems[i].src_format;
  456.         transkey.element[i].output_offset = This->elems[i].src_offset;
  457.         transkey.output_stride +=
  458.             util_format_get_blocksize(This->elems[i].src_format);
  459.  
  460.         assert(!(transkey.output_stride & 3));
  461.     }
  462.     transkey.nr_elements = This->nelems;
  463.  
  464.     translate = translate_create(&transkey);
  465.     if (!translate)
  466.         return E_OUTOFMEMORY;
  467.  
  468.     hr = NineVertexBuffer9_Lock(pDstBuf,
  469.                                 transkey.output_stride * DestIndex,
  470.                                 transkey.output_stride * VertexCount,
  471.                                 &dst_map, D3DLOCK_DISCARD);
  472.     if (FAILED(hr))
  473.         goto out;
  474.  
  475.     src_map = pipe->transfer_map(pipe, pSrcBuf, 0, PIPE_TRANSFER_READ, &box,
  476.                                  &transfer);
  477.     if (!src_map) {
  478.         hr = D3DERR_DRIVERINTERNALERROR;
  479.         goto out;
  480.     }
  481.     translate->set_buffer(translate, 0, src_map, so->stride[0], ~0);
  482.  
  483.     translate->run(translate, 0, VertexCount, 0, 0, dst_map);
  484.  
  485.     NineVertexBuffer9_Unlock(pDstBuf);
  486. out:
  487.     if (transfer)
  488.         pipe->transfer_unmap(pipe, transfer);
  489.     translate->release(translate); /* TODO: cache these */
  490.     return hr;
  491. }
  492.