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