summaryrefslogtreecommitdiffstats
path: root/src/gallium/state_trackers/nine/vertexdeclaration9.c
diff options
context:
space:
mode:
authorJoakim Sindholt <[email protected]>2011-08-04 15:14:06 +0200
committerEmil Velikov <[email protected]>2014-11-18 02:02:54 +0000
commitfdd96578ef2dfe9c4ad5aab5858036298d444a64 (patch)
tree3230b0fb321381250a506503825318facb10ca73 /src/gallium/state_trackers/nine/vertexdeclaration9.c
parent7d2573b5376bb4f9ce9a50e0b965e06032b135a9 (diff)
nine: Add state tracker nine for Direct3D9 (v3)
Work of Joakim Sindholt (zhasha) and Christoph Bumiller (chrisbmr). DRI3 port done by Axel Davy (mannerov). v2: - nine_debug.c: klass extended from 32 chars to 96 (for sure) by glennk - Nine improvements by Axel Davy (which also fixed some wine tests) - by Emil Velikov: - convert to static/shared drivers - Sort and cleanup the includes - Use AM_CPPFLAGS for the defines - Add the linker garbage collector - Restrict the exported symbols (think llvm) v3: - small nine fixes - build system improvements by Emil Velikov v4: [Emil Velikov] - Do no link against libudev. No longer needed. Acked-by: Jose Fonseca <[email protected]> Reviewed-by: Marek Olšák <[email protected]> Reviewed-by: Axel Davy <[email protected]> Signed-off-by: David Heidelberg <[email protected]>
Diffstat (limited to 'src/gallium/state_trackers/nine/vertexdeclaration9.c')
-rw-r--r--src/gallium/state_trackers/nine/vertexdeclaration9.c518
1 files changed, 518 insertions, 0 deletions
diff --git a/src/gallium/state_trackers/nine/vertexdeclaration9.c b/src/gallium/state_trackers/nine/vertexdeclaration9.c
new file mode 100644
index 00000000000..1a33e9348c0
--- /dev/null
+++ b/src/gallium/state_trackers/nine/vertexdeclaration9.c
@@ -0,0 +1,518 @@
+/*
+ * Copyright 2011 Joakim Sindholt <[email protected]>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, and/or sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "vertexdeclaration9.h"
+#include "vertexbuffer9.h"
+#include "device9.h"
+#include "nine_helpers.h"
+
+#include "pipe/p_format.h"
+#include "pipe/p_context.h"
+#include "util/u_math.h"
+#include "util/u_format.h"
+#include "util/u_box.h"
+#include "translate/translate.h"
+
+#define DBG_CHANNEL DBG_VERTEXDECLARATION
+
+static INLINE enum pipe_format decltype_format(BYTE type)
+{
+ switch (type) {
+ case D3DDECLTYPE_FLOAT1: return PIPE_FORMAT_R32_FLOAT;
+ case D3DDECLTYPE_FLOAT2: return PIPE_FORMAT_R32G32_FLOAT;
+ case D3DDECLTYPE_FLOAT3: return PIPE_FORMAT_R32G32B32_FLOAT;
+ case D3DDECLTYPE_FLOAT4: return PIPE_FORMAT_R32G32B32A32_FLOAT;
+ case D3DDECLTYPE_D3DCOLOR: return PIPE_FORMAT_B8G8R8A8_UNORM;
+ case D3DDECLTYPE_UBYTE4: return PIPE_FORMAT_R8G8B8A8_USCALED;
+ case D3DDECLTYPE_SHORT2: return PIPE_FORMAT_R16G16_SSCALED;
+ case D3DDECLTYPE_SHORT4: return PIPE_FORMAT_R16G16B16A16_SSCALED;
+ case D3DDECLTYPE_UBYTE4N: return PIPE_FORMAT_R8G8B8A8_UNORM;
+ case D3DDECLTYPE_SHORT2N: return PIPE_FORMAT_R16G16_SNORM;
+ case D3DDECLTYPE_SHORT4N: return PIPE_FORMAT_R16G16B16A16_SNORM;
+ case D3DDECLTYPE_USHORT2N: return PIPE_FORMAT_R16G16_UNORM;
+ case D3DDECLTYPE_USHORT4N: return PIPE_FORMAT_R16G16B16A16_UNORM;
+ case D3DDECLTYPE_UDEC3: return PIPE_FORMAT_R10G10B10X2_USCALED;
+ case D3DDECLTYPE_DEC3N: return PIPE_FORMAT_R10G10B10X2_SNORM;
+ case D3DDECLTYPE_FLOAT16_2: return PIPE_FORMAT_R16G16_FLOAT;
+ case D3DDECLTYPE_FLOAT16_4: return PIPE_FORMAT_R16G16B16A16_FLOAT;
+ default:
+ assert(!"Implementation error !");
+ }
+ return PIPE_FORMAT_NONE;
+}
+
+static INLINE unsigned decltype_size(BYTE type)
+{
+ switch (type) {
+ case D3DDECLTYPE_FLOAT1: return 1 * sizeof(float);
+ case D3DDECLTYPE_FLOAT2: return 2 * sizeof(float);
+ case D3DDECLTYPE_FLOAT3: return 3 * sizeof(float);
+ case D3DDECLTYPE_FLOAT4: return 4 * sizeof(float);
+ case D3DDECLTYPE_D3DCOLOR: return 1 * sizeof(DWORD);
+ case D3DDECLTYPE_UBYTE4: return 4 * sizeof(BYTE);
+ case D3DDECLTYPE_SHORT2: return 2 * sizeof(short);
+ case D3DDECLTYPE_SHORT4: return 4 * sizeof(short);
+ case D3DDECLTYPE_UBYTE4N: return 4 * sizeof(BYTE);
+ case D3DDECLTYPE_SHORT2N: return 2 * sizeof(short);
+ case D3DDECLTYPE_SHORT4N: return 4 * sizeof(short);
+ case D3DDECLTYPE_USHORT2N: return 2 * sizeof(short);
+ case D3DDECLTYPE_USHORT4N: return 4 * sizeof(short);
+ case D3DDECLTYPE_UDEC3: return 4;
+ case D3DDECLTYPE_DEC3N: return 4;
+ case D3DDECLTYPE_FLOAT16_2: return 2 * 2;
+ case D3DDECLTYPE_FLOAT16_4: return 4 * 2;
+ default:
+ assert(!"Implementation error !");
+ }
+ return 0;
+}
+
+/* Actually, arbitrary usage index values are permitted, but a
+ * simple lookup table won't work in that case. Let's just wait
+ * with making this more generic until we need it.
+ */
+static INLINE boolean
+nine_d3ddeclusage_check(unsigned usage, unsigned usage_idx)
+{
+ switch (usage) {
+ case D3DDECLUSAGE_POSITIONT:
+ case D3DDECLUSAGE_PSIZE:
+ case D3DDECLUSAGE_TESSFACTOR:
+ case D3DDECLUSAGE_DEPTH:
+ case D3DDECLUSAGE_FOG:
+ case D3DDECLUSAGE_SAMPLE:
+ return usage_idx <= 0;
+ case D3DDECLUSAGE_NORMAL:
+ case D3DDECLUSAGE_TANGENT:
+ case D3DDECLUSAGE_BINORMAL:
+ return usage_idx <= 1;
+ case D3DDECLUSAGE_POSITION:
+ case D3DDECLUSAGE_BLENDWEIGHT:
+ case D3DDECLUSAGE_BLENDINDICES:
+ case D3DDECLUSAGE_COLOR:
+ return usage_idx <= 4;
+ case D3DDECLUSAGE_TEXCOORD:
+ return usage_idx <= 15;
+ default:
+ return FALSE;
+ }
+}
+
+#define NINE_DECLUSAGE_CASE0(n) case D3DDECLUSAGE_##n: return NINE_DECLUSAGE_##n
+#define NINE_DECLUSAGE_CASEi(n) case D3DDECLUSAGE_##n: return NINE_DECLUSAGE_##n(usage_idx)
+INLINE unsigned
+nine_d3d9_to_nine_declusage(unsigned usage, unsigned usage_idx)
+{
+ if (!nine_d3ddeclusage_check(usage, usage_idx))
+ ERR("D3DDECLUSAGE_%u[%u]\n",usage,usage_idx);
+ assert(nine_d3ddeclusage_check(usage, usage_idx));
+ switch (usage) {
+ NINE_DECLUSAGE_CASEi(POSITION);
+ NINE_DECLUSAGE_CASEi(BLENDWEIGHT);
+ NINE_DECLUSAGE_CASEi(BLENDINDICES);
+ NINE_DECLUSAGE_CASEi(NORMAL);
+ NINE_DECLUSAGE_CASE0(PSIZE);
+ NINE_DECLUSAGE_CASEi(TEXCOORD);
+ NINE_DECLUSAGE_CASEi(TANGENT);
+ NINE_DECLUSAGE_CASEi(BINORMAL);
+ NINE_DECLUSAGE_CASE0(TESSFACTOR);
+ NINE_DECLUSAGE_CASE0(POSITIONT);
+ NINE_DECLUSAGE_CASEi(COLOR);
+ NINE_DECLUSAGE_CASE0(DEPTH);
+ NINE_DECLUSAGE_CASE0(FOG);
+ NINE_DECLUSAGE_CASE0(SAMPLE);
+ default:
+ assert(!"Invalid DECLUSAGE.");
+ return NINE_DECLUSAGE_NONE;
+ }
+}
+
+static const char *nine_declusage_names[] =
+{
+ [NINE_DECLUSAGE_POSITION(0)] = "POSITION",
+ [NINE_DECLUSAGE_POSITION(1)] = "POSITION1",
+ [NINE_DECLUSAGE_POSITION(2)] = "POSITION2",
+ [NINE_DECLUSAGE_POSITION(3)] = "POSITION3",
+ [NINE_DECLUSAGE_POSITION(4)] = "POSITION4",
+ [NINE_DECLUSAGE_BLENDWEIGHT(0)] = "BLENDWEIGHT",
+ [NINE_DECLUSAGE_BLENDWEIGHT(1)] = "BLENDWEIGHT1",
+ [NINE_DECLUSAGE_BLENDWEIGHT(2)] = "BLENDWEIGHT2",
+ [NINE_DECLUSAGE_BLENDWEIGHT(3)] = "BLENDWEIGHT3",
+ [NINE_DECLUSAGE_BLENDINDICES(0)] = "BLENDINDICES",
+ [NINE_DECLUSAGE_BLENDINDICES(1)] = "BLENDINDICES1",
+ [NINE_DECLUSAGE_BLENDINDICES(2)] = "BLENDINDICES2",
+ [NINE_DECLUSAGE_BLENDINDICES(3)] = "BLENDINDICES3",
+ [NINE_DECLUSAGE_NORMAL(0)] = "NORMAL",
+ [NINE_DECLUSAGE_NORMAL(1)] = "NORMAL1",
+ [NINE_DECLUSAGE_PSIZE] = "PSIZE",
+ [NINE_DECLUSAGE_TEXCOORD(0)] = "TEXCOORD0",
+ [NINE_DECLUSAGE_TEXCOORD(1)] = "TEXCOORD1",
+ [NINE_DECLUSAGE_TEXCOORD(2)] = "TEXCOORD2",
+ [NINE_DECLUSAGE_TEXCOORD(3)] = "TEXCOORD3",
+ [NINE_DECLUSAGE_TEXCOORD(4)] = "TEXCOORD4",
+ [NINE_DECLUSAGE_TEXCOORD(5)] = "TEXCOORD5",
+ [NINE_DECLUSAGE_TEXCOORD(6)] = "TEXCOORD6",
+ [NINE_DECLUSAGE_TEXCOORD(7)] = "TEXCOORD7",
+ [NINE_DECLUSAGE_TEXCOORD(8)] = "TEXCOORD8",
+ [NINE_DECLUSAGE_TEXCOORD(9)] = "TEXCOORD9",
+ [NINE_DECLUSAGE_TEXCOORD(10)] = "TEXCOORD10",
+ [NINE_DECLUSAGE_TEXCOORD(11)] = "TEXCOORD11",
+ [NINE_DECLUSAGE_TEXCOORD(12)] = "TEXCOORD12",
+ [NINE_DECLUSAGE_TEXCOORD(13)] = "TEXCOORD13",
+ [NINE_DECLUSAGE_TEXCOORD(14)] = "TEXCOORD14",
+ [NINE_DECLUSAGE_TEXCOORD(15)] = "TEXCOORD15",
+ [NINE_DECLUSAGE_TANGENT(0)] = "TANGENT",
+ [NINE_DECLUSAGE_TANGENT(1)] = "TANGENT1",
+ [NINE_DECLUSAGE_BINORMAL(0)] = "BINORMAL",
+ [NINE_DECLUSAGE_BINORMAL(1)] = "BINORMAL1",
+ [NINE_DECLUSAGE_TESSFACTOR] = "TESSFACTOR",
+ [NINE_DECLUSAGE_POSITIONT] = "POSITIONT",
+ [NINE_DECLUSAGE_COLOR(0)] = "DIFFUSE",
+ [NINE_DECLUSAGE_COLOR(1)] = "SPECULAR",
+ [NINE_DECLUSAGE_COLOR(2)] = "COLOR2",
+ [NINE_DECLUSAGE_COLOR(3)] = "COLOR3",
+ [NINE_DECLUSAGE_COLOR(4)] = "COLOR4",
+ [NINE_DECLUSAGE_DEPTH] = "DEPTH",
+ [NINE_DECLUSAGE_FOG] = "FOG",
+ [NINE_DECLUSAGE_NONE] = "(NONE)",
+ [NINE_DECLUSAGE_COUNT] = "(OOB)"
+};
+static INLINE const char *
+nine_declusage_name(unsigned ndcl)
+{
+ return nine_declusage_names[MIN2(ndcl, Elements(nine_declusage_names) - 1)];
+}
+
+HRESULT
+NineVertexDeclaration9_ctor( struct NineVertexDeclaration9 *This,
+ struct NineUnknownParams *pParams,
+ const D3DVERTEXELEMENT9 *pElements )
+{
+ const D3DCAPS9 *caps;
+ unsigned i;
+
+ HRESULT hr = NineUnknown_ctor(&This->base, pParams);
+ if (FAILED(hr)) { return hr; }
+
+ for (This->nelems = 0;
+ pElements[This->nelems].Type != D3DDECLTYPE_UNUSED &&
+ pElements[This->nelems].Stream != 0xFF; /* wine */
+ ++This->nelems);
+
+ caps = NineDevice9_GetCaps(This->base.device);
+ user_assert(This->nelems <= caps->MaxStreams, D3DERR_INVALIDCALL);
+
+ This->decls = CALLOC(This->nelems+1, sizeof(D3DVERTEXELEMENT9));
+ This->elems = CALLOC(This->nelems, sizeof(struct pipe_vertex_element));
+ if (!This->decls || !This->elems) { return E_OUTOFMEMORY; }
+ memcpy(This->decls, pElements, sizeof(D3DVERTEXELEMENT9)*(This->nelems+1));
+
+ memset(This->usage_map, 0xff, sizeof(This->usage_map));
+
+ for (i = 0; i < This->nelems; ++i) {
+ uint8_t usage = nine_d3d9_to_nine_declusage(This->decls[i].Usage,
+ This->decls[i].UsageIndex);
+ This->usage_map[usage] = i;
+
+ This->elems[i].src_offset = This->decls[i].Offset;
+ This->elems[i].instance_divisor = 0;
+ This->elems[i].vertex_buffer_index = This->decls[i].Stream;
+ This->elems[i].src_format = decltype_format(This->decls[i].Type);
+ /* XXX Remember Method (tesselation), Usage, UsageIndex */
+
+ DBG("VERTEXELEMENT[%u]: Stream=%u Offset=%u Type=%s DeclUsage=%s\n", i,
+ This->decls[i].Stream,
+ This->decls[i].Offset,
+ util_format_name(This->elems[i].src_format),
+ nine_declusage_name(usage));
+ }
+
+ return D3D_OK;
+}
+
+void
+NineVertexDeclaration9_dtor( struct NineVertexDeclaration9 *This )
+{
+ if (This->decls)
+ FREE(This->decls);
+ if (This->elems)
+ FREE(This->elems);
+
+ NineUnknown_dtor(&This->base);
+}
+
+HRESULT WINAPI
+NineVertexDeclaration9_GetDeclaration( struct NineVertexDeclaration9 *This,
+ D3DVERTEXELEMENT9 *pElement,
+ UINT *pNumElements )
+{
+ if (!pElement) {
+ user_assert(pNumElements, D3DERR_INVALIDCALL);
+ *pNumElements = This->nelems+1;
+ return D3D_OK;
+ }
+ if (pNumElements) { *pNumElements = This->nelems+1; }
+ memcpy(pElement, This->decls, sizeof(D3DVERTEXELEMENT9)*(This->nelems+1));
+ return D3D_OK;
+}
+
+IDirect3DVertexDeclaration9Vtbl NineVertexDeclaration9_vtable = {
+ (void *)NineUnknown_QueryInterface,
+ (void *)NineUnknown_AddRef,
+ (void *)NineUnknown_Release,
+ (void *)NineUnknown_GetDevice, /* actually part of VertexDecl9 iface */
+ (void *)NineVertexDeclaration9_GetDeclaration
+};
+
+static const GUID *NineVertexDeclaration9_IIDs[] = {
+ &IID_IDirect3DVertexDeclaration9,
+ &IID_IUnknown,
+ NULL
+};
+
+HRESULT
+NineVertexDeclaration9_new( struct NineDevice9 *pDevice,
+ const D3DVERTEXELEMENT9 *pElements,
+ struct NineVertexDeclaration9 **ppOut )
+{
+ NINE_DEVICE_CHILD_NEW(VertexDeclaration9, ppOut, /* args */ pDevice, pElements);
+}
+
+HRESULT
+NineVertexDeclaration9_new_from_fvf( struct NineDevice9 *pDevice,
+ DWORD FVF,
+ struct NineVertexDeclaration9 **ppOut )
+{
+ D3DVERTEXELEMENT9 elems[16], decl_end = D3DDECL_END();
+ unsigned texcount, i, betas, nelems = 0;
+ BYTE beta_index = 0xFF;
+
+ switch (FVF & D3DFVF_POSITION_MASK) {
+ case D3DFVF_XYZ: /* simple XYZ */
+ case D3DFVF_XYZB1:
+ case D3DFVF_XYZB2:
+ case D3DFVF_XYZB3:
+ case D3DFVF_XYZB4:
+ case D3DFVF_XYZB5: /* XYZ with beta values */
+ elems[nelems].Type = D3DDECLTYPE_FLOAT3;
+ elems[nelems].Usage = D3DDECLUSAGE_POSITION;
+ elems[nelems].UsageIndex = 0;
+ ++nelems;
+ /* simple XYZ has no beta values. break. */
+ if ((FVF & D3DFVF_POSITION_MASK) == D3DFVF_XYZ) { break; }
+
+ betas = (((FVF & D3DFVF_XYZB5)-D3DFVF_XYZB1)>>1)+1;
+ if (FVF & D3DFVF_LASTBETA_D3DCOLOR) {
+ beta_index = D3DDECLTYPE_D3DCOLOR;
+ } else if (FVF & D3DFVF_LASTBETA_UBYTE4) {
+ beta_index = D3DDECLTYPE_UBYTE4;
+ } else if ((FVF & D3DFVF_XYZB5) == D3DFVF_XYZB5) {
+ beta_index = D3DDECLTYPE_FLOAT1;
+ }
+ if (beta_index != 0xFF) { --betas; }
+
+ if (betas > 0) {
+ switch (betas) {
+ case 1: elems[nelems].Type = D3DDECLTYPE_FLOAT1; break;
+ case 2: elems[nelems].Type = D3DDECLTYPE_FLOAT2; break;
+ case 3: elems[nelems].Type = D3DDECLTYPE_FLOAT3; break;
+ case 4: elems[nelems].Type = D3DDECLTYPE_FLOAT4; break;
+ default:
+ assert(!"Implementation error!");
+ }
+ elems[nelems].Usage = D3DDECLUSAGE_BLENDWEIGHT;
+ elems[nelems].UsageIndex = 0;
+ ++nelems;
+ }
+
+ if (beta_index != 0xFF) {
+ elems[nelems].Type = beta_index;
+ elems[nelems].Usage = D3DDECLUSAGE_BLENDINDICES;
+ elems[nelems].UsageIndex = 0;
+ ++nelems;
+ }
+ break;
+
+ case D3DFVF_XYZW: /* simple XYZW */
+ case D3DFVF_XYZRHW: /* pretransformed XYZW */
+ elems[nelems].Type = D3DDECLTYPE_FLOAT4;
+ elems[nelems].Usage =
+ ((FVF & D3DFVF_POSITION_MASK) == D3DFVF_XYZW) ?
+ D3DDECLUSAGE_POSITION : D3DDECLUSAGE_POSITIONT;
+ elems[nelems].UsageIndex = 0;
+ ++nelems;
+ break;
+
+ default:
+ (void)user_error(!"Position doesn't match any known combination");
+ }
+
+ /* normals, psize and colors */
+ if (FVF & D3DFVF_NORMAL) {
+ elems[nelems].Type = D3DDECLTYPE_FLOAT3;
+ elems[nelems].Usage = D3DDECLUSAGE_NORMAL;
+ elems[nelems].UsageIndex = 0;
+ ++nelems;
+ }
+ if (FVF & D3DFVF_PSIZE) {
+ elems[nelems].Type = D3DDECLTYPE_FLOAT1;
+ elems[nelems].Usage = D3DDECLUSAGE_PSIZE;
+ elems[nelems].UsageIndex = 0;
+ ++nelems;
+ }
+ if (FVF & D3DFVF_DIFFUSE) {
+ elems[nelems].Type = D3DDECLTYPE_D3DCOLOR;
+ elems[nelems].Usage = D3DDECLUSAGE_COLOR;
+ elems[nelems].UsageIndex = 0;
+ ++nelems;
+ }
+ if (FVF & D3DFVF_SPECULAR) {
+ elems[nelems].Type = D3DDECLTYPE_D3DCOLOR;
+ elems[nelems].Usage = D3DDECLUSAGE_COLOR;
+ elems[nelems].UsageIndex = 1;
+ ++nelems;
+ }
+
+ /* textures */
+ texcount = (FVF & D3DFVF_TEXCOUNT_MASK) >> D3DFVF_TEXCOUNT_SHIFT;
+ if (user_error(texcount <= 8)) { texcount = 8; }
+
+ for (i = 0; i < texcount; ++i) {
+ switch ((FVF >> (16+i*2)) & 0x3) {
+ case D3DFVF_TEXTUREFORMAT1:
+ elems[nelems].Type = D3DDECLTYPE_FLOAT1;
+ break;
+
+ case D3DFVF_TEXTUREFORMAT2:
+ elems[nelems].Type = D3DDECLTYPE_FLOAT2;
+ break;
+
+ case D3DFVF_TEXTUREFORMAT3:
+ elems[nelems].Type = D3DDECLTYPE_FLOAT3;
+ break;
+
+ case D3DFVF_TEXTUREFORMAT4:
+ elems[nelems].Type = D3DDECLTYPE_FLOAT4;
+ break;
+
+ default:
+ assert(!"Implementation error!");
+ }
+ elems[nelems].Usage = D3DDECLUSAGE_TEXCOORD;
+ elems[nelems].UsageIndex = i;
+ ++nelems;
+ }
+
+ /* fill out remaining data */
+ for (i = 0; i < nelems; ++i) {
+ elems[i].Stream = 0;
+ elems[i].Offset = (i == 0) ? 0 : (elems[i-1].Offset +
+ decltype_size(elems[i-1].Type));
+ elems[i].Method = D3DDECLMETHOD_DEFAULT;
+ }
+ elems[nelems++] = decl_end;
+
+ NINE_DEVICE_CHILD_NEW(VertexDeclaration9, ppOut, /* args */ pDevice, elems);
+}
+
+/* ProcessVertices runs stream output into a temporary buffer to capture
+ * all outputs.
+ * Now we have to convert them to the format and order set by the vertex
+ * declaration, for which we use u_translate.
+ * This is necessary if the vertex declaration contains elements using a
+ * non float32 format, because stream output only supports f32/u32/s32.
+ */
+HRESULT
+NineVertexDeclaration9_ConvertStreamOutput(
+ struct NineVertexDeclaration9 *This,
+ struct NineVertexBuffer9 *pDstBuf,
+ UINT DestIndex,
+ UINT VertexCount,
+ struct pipe_resource *pSrcBuf,
+ const struct pipe_stream_output_info *so )
+{
+ struct pipe_context *pipe = This->base.device->pipe;
+ struct pipe_transfer *transfer = NULL;
+ struct translate *translate;
+ struct translate_key transkey;
+ struct pipe_box box;
+ HRESULT hr;
+ unsigned i;
+ void *src_map;
+ void *dst_map;
+
+ transkey.output_stride = 0;
+ for (i = 0; i < This->nelems; ++i) {
+ enum pipe_format format;
+
+ switch (so->output[i].num_components) {
+ case 1: format = PIPE_FORMAT_R32_FLOAT; break;
+ case 2: format = PIPE_FORMAT_R32G32_FLOAT; break;
+ case 3: format = PIPE_FORMAT_R32G32B32_FLOAT; break;
+ default:
+ assert(so->output[i].num_components == 4);
+ format = PIPE_FORMAT_R32G32B32A32_FLOAT;
+ break;
+ }
+ transkey.element[i].type = TRANSLATE_ELEMENT_NORMAL;
+ transkey.element[i].input_format = format;
+ transkey.element[i].input_buffer = 0;
+ transkey.element[i].input_offset = so->output[i].dst_offset * 4;
+ transkey.element[i].instance_divisor = 0;
+
+ transkey.element[i].output_format = This->elems[i].src_format;
+ transkey.element[i].output_offset = This->elems[i].src_offset;
+ transkey.output_stride +=
+ util_format_get_blocksize(This->elems[i].src_format);
+
+ assert(!(transkey.output_stride & 3));
+ }
+ transkey.nr_elements = This->nelems;
+
+ translate = translate_create(&transkey);
+ if (!translate)
+ return E_OUTOFMEMORY;
+
+ hr = NineVertexBuffer9_Lock(pDstBuf,
+ transkey.output_stride * DestIndex,
+ transkey.output_stride * VertexCount,
+ &dst_map, D3DLOCK_DISCARD);
+ if (FAILED(hr))
+ goto out;
+
+ src_map = pipe->transfer_map(pipe, pSrcBuf, 0, PIPE_TRANSFER_READ, &box,
+ &transfer);
+ if (!src_map) {
+ hr = D3DERR_DRIVERINTERNALERROR;
+ goto out;
+ }
+ translate->set_buffer(translate, 0, src_map, so->stride[0], ~0);
+
+ translate->run(translate, 0, VertexCount, 0, 0, dst_map);
+
+ NineVertexBuffer9_Unlock(pDstBuf);
+out:
+ if (transfer)
+ pipe->transfer_unmap(pipe, transfer);
+ translate->release(translate); /* TODO: cache these */
+ return hr;
+}