d3dx9: Add support for D3DFMT_A16B16G16R16F.
[wine] / dlls / d3dx9_36 / xfile.c
1 /*
2  * Copyright (C) 2012 Christian Costa
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
17  *
18  */
19
20 #include "wine/debug.h"
21
22 #include "d3dx9.h"
23 #include "d3dx9xof.h"
24 #undef MAKE_DDHRESULT
25 #include "dxfile.h"
26
27 WINE_DEFAULT_DEBUG_CHANNEL(d3dx);
28
29 static HRESULT error_dxfile_to_d3dxfile(HRESULT error)
30 {
31     switch (error)
32     {
33         case DXFILEERR_BADFILETYPE:
34             return D3DXFERR_BADFILETYPE;
35         case DXFILEERR_BADFILEVERSION:
36             return D3DXFERR_BADFILEVERSION;
37         case DXFILEERR_BADFILEFLOATSIZE:
38             return D3DXFERR_BADFILEFLOATSIZE;
39         case DXFILEERR_PARSEERROR:
40             return D3DXFERR_PARSEERROR;
41         default:
42             FIXME("Cannot map error %#x\n", error);
43             return E_FAIL;
44     }
45 }
46
47 typedef struct {
48     ID3DXFile ID3DXFile_iface;
49     LONG ref;
50     IDirectXFile *dxfile;
51 } ID3DXFileImpl;
52
53 typedef struct {
54     ID3DXFileEnumObject ID3DXFileEnumObject_iface;
55     LONG ref;
56     ULONG nb_children;
57     ID3DXFileData **children;
58 } ID3DXFileEnumObjectImpl;
59
60 typedef struct {
61     ID3DXFileData ID3DXFileData_iface;
62     LONG ref;
63     IDirectXFileData *dxfile_data;
64 } ID3DXFileDataImpl;
65
66
67 static inline ID3DXFileImpl* impl_from_ID3DXFile(ID3DXFile *iface)
68 {
69     return CONTAINING_RECORD(iface, ID3DXFileImpl, ID3DXFile_iface);
70 }
71
72 static inline ID3DXFileEnumObjectImpl* impl_from_ID3DXFileEnumObject(ID3DXFileEnumObject *iface)
73 {
74     return CONTAINING_RECORD(iface, ID3DXFileEnumObjectImpl, ID3DXFileEnumObject_iface);
75 }
76
77 static inline ID3DXFileDataImpl* impl_from_ID3DXFileData(ID3DXFileData *iface)
78 {
79     return CONTAINING_RECORD(iface, ID3DXFileDataImpl, ID3DXFileData_iface);
80 }
81
82 /*** IUnknown methods ***/
83
84 static HRESULT WINAPI ID3DXFileDataImpl_QueryInterface(ID3DXFileData *iface, REFIID riid, void **ret_iface)
85 {
86     TRACE("(%p)->(%s, %p)\n", iface, debugstr_guid(riid), ret_iface);
87
88     if (IsEqualGUID(riid, &IID_IUnknown) ||
89         IsEqualGUID(riid, &IID_ID3DXFileData))
90     {
91         iface->lpVtbl->AddRef(iface);
92         *ret_iface = iface;
93         return S_OK;
94     }
95
96     WARN("(%p)->(%s, %p), not found\n", iface, debugstr_guid(riid), ret_iface);
97     *ret_iface = NULL;
98     return E_NOINTERFACE;
99 }
100
101 static ULONG WINAPI ID3DXFileDataImpl_AddRef(ID3DXFileData *iface)
102 {
103     ID3DXFileDataImpl *This = impl_from_ID3DXFileData(iface);
104     ULONG ref = InterlockedIncrement(&This->ref);
105
106     TRACE("(%p)->(): new ref = %u\n", iface, ref);
107
108     return ref;
109 }
110
111 static ULONG WINAPI ID3DXFileDataImpl_Release(ID3DXFileData *iface)
112 {
113     ID3DXFileDataImpl *This = impl_from_ID3DXFileData(iface);
114     ULONG ref = InterlockedDecrement(&This->ref);
115
116     TRACE("(%p)->(): new ref = %u\n", iface, ref);
117
118     if (!ref)
119     {
120         IDirectXFileData_Release(This->dxfile_data);
121         HeapFree(GetProcessHeap(), 0, This);
122     }
123
124     return ref;
125 }
126
127
128 /*** ID3DXFileData methods ***/
129
130 static HRESULT WINAPI ID3DXFileDataImpl_GetEnum(ID3DXFileData *iface, ID3DXFileEnumObject **enum_object)
131 {
132     FIXME("(%p)->(%p): stub\n", iface, enum_object);
133
134     return E_NOTIMPL;
135 }
136
137
138 static HRESULT WINAPI ID3DXFileDataImpl_GetName(ID3DXFileData *iface, char *name, SIZE_T *size)
139 {
140     FIXME("(%p)->(%p, %p): stub\n", iface, name, size);
141
142     return E_NOTIMPL;
143 }
144
145
146 static HRESULT WINAPI ID3DXFileDataImpl_GetId(ID3DXFileData *iface, GUID *guid)
147 {
148     FIXME("(%p)->(%p): stub\n", iface, guid);
149
150     return E_NOTIMPL;
151 }
152
153
154 static HRESULT WINAPI ID3DXFileDataImpl_Lock(ID3DXFileData *iface, SIZE_T *size, const void **data)
155 {
156     FIXME("(%p)->(%p, %p): stub\n", iface, size, data);
157
158     return E_NOTIMPL;
159 }
160
161
162 static HRESULT WINAPI ID3DXFileDataImpl_Unlock(ID3DXFileData *iface)
163 {
164     FIXME("(%p)->(): stub\n", iface);
165
166     return E_NOTIMPL;
167 }
168
169
170 static HRESULT WINAPI ID3DXFileDataImpl_GetType(ID3DXFileData *iface, GUID *guid)
171 {
172     ID3DXFileDataImpl *This = impl_from_ID3DXFileData(iface);
173     const GUID *dxfile_guid;
174     HRESULT ret;
175
176     TRACE("(%p)->(%p)\n", iface, guid);
177
178     ret = IDirectXFileData_GetType(This->dxfile_data, &dxfile_guid);
179     if (ret != DXFILE_OK)
180         return error_dxfile_to_d3dxfile(ret);
181
182     *guid = *dxfile_guid;
183
184     return S_OK;
185 }
186
187
188 static BOOL WINAPI ID3DXFileDataImpl_IsReference(ID3DXFileData *iface)
189 {
190     TRACE("(%p)->(): stub\n", iface);
191
192     return E_NOTIMPL;
193 }
194
195
196 static HRESULT WINAPI ID3DXFileDataImpl_GetChildren(ID3DXFileData *iface, SIZE_T *children)
197 {
198     TRACE("(%p)->(%p): stub\n", iface, children);
199
200     return E_NOTIMPL;
201 }
202
203
204 static HRESULT WINAPI ID3DXFileDataImpl_GetChild(ID3DXFileData *iface, SIZE_T id, ID3DXFileData **object)
205 {
206     TRACE("(%p)->(%lu, %p): stub\n", iface, id, object);
207
208     return E_NOTIMPL;
209 }
210
211
212 static const ID3DXFileDataVtbl ID3DXFileData_Vtbl =
213 {
214     ID3DXFileDataImpl_QueryInterface,
215     ID3DXFileDataImpl_AddRef,
216     ID3DXFileDataImpl_Release,
217     ID3DXFileDataImpl_GetEnum,
218     ID3DXFileDataImpl_GetName,
219     ID3DXFileDataImpl_GetId,
220     ID3DXFileDataImpl_Lock,
221     ID3DXFileDataImpl_Unlock,
222     ID3DXFileDataImpl_GetType,
223     ID3DXFileDataImpl_IsReference,
224     ID3DXFileDataImpl_GetChildren,
225     ID3DXFileDataImpl_GetChild
226 };
227
228
229 static HRESULT ID3DXFileDataImpl_Create(IDirectXFileData *dxfile_data, ID3DXFileData **ret_iface)
230 {
231     ID3DXFileDataImpl *object;
232
233     TRACE("(%p, %p)\n", dxfile_data, ret_iface);
234
235     *ret_iface = NULL;
236
237     object = HeapAlloc(GetProcessHeap(), 0, sizeof(*object));
238     if (!object)
239         return E_OUTOFMEMORY;
240
241     object->ID3DXFileData_iface.lpVtbl = &ID3DXFileData_Vtbl;
242     object->ref = 1;
243     object->dxfile_data = dxfile_data;
244
245     *ret_iface = &object->ID3DXFileData_iface;
246
247     return S_OK;
248 }
249
250
251 /*** IUnknown methods ***/
252
253 static HRESULT WINAPI ID3DXFileEnumObjectImpl_QueryInterface(ID3DXFileEnumObject *iface, REFIID riid, void **ret_iface)
254 {
255     TRACE("(%p)->(%s, %p)\n", iface, debugstr_guid(riid), ret_iface);
256
257     if (IsEqualGUID(riid, &IID_IUnknown) ||
258         IsEqualGUID(riid, &IID_ID3DXFileEnumObject))
259     {
260         iface->lpVtbl->AddRef(iface);
261         *ret_iface = iface;
262         return S_OK;
263     }
264
265     WARN("(%p)->(%s, %p), not found\n", iface, debugstr_guid(riid), ret_iface);
266     *ret_iface = NULL;
267     return E_NOINTERFACE;
268 }
269
270 static ULONG WINAPI ID3DXFileEnumObjectImpl_AddRef(ID3DXFileEnumObject *iface)
271 {
272     ID3DXFileEnumObjectImpl *This = impl_from_ID3DXFileEnumObject(iface);
273     ULONG ref = InterlockedIncrement(&This->ref);
274
275     TRACE("(%p)->(): new ref = %u\n", iface, ref);
276
277     return ref;
278 }
279
280 static ULONG WINAPI ID3DXFileEnumObjectImpl_Release(ID3DXFileEnumObject *iface)
281 {
282     ID3DXFileEnumObjectImpl *This = impl_from_ID3DXFileEnumObject(iface);
283     ULONG ref = InterlockedDecrement(&This->ref);
284
285     TRACE("(%p)->(): new ref = %u\n", iface, ref);
286
287     if (!ref)
288     {
289         ULONG i;
290
291         for (i = 0; i < This->nb_children; i++)
292             (This->children[i])->lpVtbl->Release(This->children[i]);
293         HeapFree(GetProcessHeap(), 0, This->children);
294         HeapFree(GetProcessHeap(), 0, This);
295     }
296
297     return ref;
298 }
299
300
301 /*** ID3DXFileEnumObject methods ***/
302
303 static HRESULT WINAPI ID3DXFileEnumObjectImpl_GetFile(ID3DXFileEnumObject *iface, ID3DXFile **file)
304 {
305     FIXME("(%p)->(%p): stub\n", iface, file);
306
307     return E_NOTIMPL;
308 }
309
310
311 static HRESULT WINAPI ID3DXFileEnumObjectImpl_GetChildren(ID3DXFileEnumObject *iface, SIZE_T *children)
312 {
313     ID3DXFileEnumObjectImpl *This = impl_from_ID3DXFileEnumObject(iface);
314
315     TRACE("(%p)->(%p)\n", iface, children);
316
317     if (!children)
318         return E_POINTER;
319
320     *children = This->nb_children;
321
322     return S_OK;
323 }
324
325
326 static HRESULT WINAPI ID3DXFileEnumObjectImpl_GetChild(ID3DXFileEnumObject *iface, SIZE_T id, ID3DXFileData **object)
327 {
328     ID3DXFileEnumObjectImpl *This = impl_from_ID3DXFileEnumObject(iface);
329
330     TRACE("(%p)->(%lu, %p)\n", iface, id, object);
331
332     if (!object)
333         return E_POINTER;
334
335     *object = This->children[id];
336     (*object)->lpVtbl->AddRef(*object);
337
338     return S_OK;
339 }
340
341
342 static HRESULT WINAPI ID3DXFileEnumObjectImpl_GetDataObjectById(ID3DXFileEnumObject *iface, REFGUID guid, ID3DXFileData **object)
343 {
344     FIXME("(%p)->(%s, %p): stub\n", iface, debugstr_guid(guid), object);
345
346     return E_NOTIMPL;
347 }
348
349
350 static HRESULT WINAPI ID3DXFileEnumObjectImpl_GetDataObjectByName(ID3DXFileEnumObject *iface, const char *name, ID3DXFileData **object)
351 {
352     FIXME("(%p)->(%s, %p): stub\n", iface, debugstr_a(name), object);
353
354     return E_NOTIMPL;
355 }
356
357
358 static const ID3DXFileEnumObjectVtbl ID3DXFileEnumObject_Vtbl =
359 {
360     ID3DXFileEnumObjectImpl_QueryInterface,
361     ID3DXFileEnumObjectImpl_AddRef,
362     ID3DXFileEnumObjectImpl_Release,
363     ID3DXFileEnumObjectImpl_GetFile,
364     ID3DXFileEnumObjectImpl_GetChildren,
365     ID3DXFileEnumObjectImpl_GetChild,
366     ID3DXFileEnumObjectImpl_GetDataObjectById,
367     ID3DXFileEnumObjectImpl_GetDataObjectByName
368 };
369
370
371 /*** IUnknown methods ***/
372
373 static HRESULT WINAPI ID3DXFileImpl_QueryInterface(ID3DXFile *iface, REFIID riid, void **ret_iface)
374 {
375     TRACE("(%p)->(%s, %p)\n", iface, debugstr_guid(riid), ret_iface);
376
377     if (IsEqualGUID(riid, &IID_IUnknown) ||
378         IsEqualGUID(riid, &IID_ID3DXFile))
379     {
380         iface->lpVtbl->AddRef(iface);
381         *ret_iface = iface;
382         return S_OK;
383     }
384
385     WARN("(%p)->(%s, %p), not found\n", iface, debugstr_guid(riid), ret_iface);
386     *ret_iface = NULL;
387     return E_NOINTERFACE;
388 }
389
390
391 static ULONG WINAPI ID3DXFileImpl_AddRef(ID3DXFile *iface)
392 {
393     ID3DXFileImpl *This = impl_from_ID3DXFile(iface);
394     ULONG ref = InterlockedIncrement(&This->ref);
395
396     TRACE("(%p)->(): new ref = %u\n", iface, ref);
397
398     return ref;
399 }
400
401
402 static ULONG WINAPI ID3DXFileImpl_Release(ID3DXFile *iface)
403 {
404     ID3DXFileImpl *This = impl_from_ID3DXFile(iface);
405     ULONG ref = InterlockedDecrement(&This->ref);
406
407     TRACE("(%p)->(): new ref = %u\n", iface, ref);
408
409     if (!ref)
410     {
411         IDirectXFile_Release(This->dxfile);
412         HeapFree(GetProcessHeap(), 0, This);
413     }
414
415     return ref;
416 }
417
418
419 /*** ID3DXFile methods ***/
420
421 static HRESULT WINAPI ID3DXFileImpl_CreateEnumObject(ID3DXFile *iface, const void *source, D3DXF_FILELOADOPTIONS options, ID3DXFileEnumObject **enum_object)
422 {
423     ID3DXFileImpl *This = impl_from_ID3DXFile(iface);
424     ID3DXFileEnumObjectImpl *object;
425     IDirectXFileEnumObject *dxfile_enum_object;
426     void *dxfile_source;
427     DXFILELOADOPTIONS dxfile_options;
428     DXFILELOADRESOURCE dxfile_resource;
429     DXFILELOADMEMORY dxfile_memory;
430     IDirectXFileData *data_object;
431     HRESULT ret;
432
433     TRACE("(%p)->(%p, %x, %p)\n", iface, source, options, enum_object);
434
435     if (!enum_object)
436         return E_POINTER;
437
438     *enum_object = NULL;
439
440     if (options == D3DXF_FILELOAD_FROMFILE)
441     {
442         dxfile_source = (void*)source;
443         dxfile_options = DXFILELOAD_FROMFILE;
444     }
445     else if (options == D3DXF_FILELOAD_FROMRESOURCE)
446     {
447         D3DXF_FILELOADRESOURCE *resource = (D3DXF_FILELOADRESOURCE*)source;
448
449         dxfile_resource.hModule = resource->hModule;
450         dxfile_resource.lpName = resource->lpName;
451         dxfile_resource.lpType = resource->lpType;
452         dxfile_source = &dxfile_resource;
453         dxfile_options = DXFILELOAD_FROMRESOURCE;
454     }
455     else if (options == D3DXF_FILELOAD_FROMMEMORY)
456     {
457         D3DXF_FILELOADMEMORY *memory = (D3DXF_FILELOADMEMORY*)source;
458
459         dxfile_memory.lpMemory = memory->lpMemory;
460         dxfile_memory.dSize = memory->dSize;
461         dxfile_source = &dxfile_memory;
462         dxfile_options = DXFILELOAD_FROMMEMORY;
463     }
464     else
465     {
466         FIXME("Source type %u is not handled yet\n", options);
467         return E_NOTIMPL;
468     }
469
470     object = HeapAlloc(GetProcessHeap(), 0, sizeof(*object));
471     if (!object)
472         return E_OUTOFMEMORY;
473
474     object->ID3DXFileEnumObject_iface.lpVtbl = &ID3DXFileEnumObject_Vtbl;
475     object->ref = 1;
476
477     ret = IDirectXFile_CreateEnumObject(This->dxfile, dxfile_source, dxfile_options, &dxfile_enum_object);
478
479     if (ret != S_OK)
480     {
481         HeapFree(GetProcessHeap(), 0, object);
482         return ret;
483     }
484
485     /* Fill enum object with top level data objects */
486     while (SUCCEEDED(ret = IDirectXFileEnumObject_GetNextDataObject(dxfile_enum_object, &data_object)))
487     {
488         if (object->children)
489             object->children = HeapReAlloc(GetProcessHeap(), 0, object->children, sizeof(*object->children) * (object->nb_children + 1));
490         else
491             object->children = HeapAlloc(GetProcessHeap(), 0, sizeof(*object->children));
492         if (!object->children)
493         {
494             ret = E_OUTOFMEMORY;
495             break;
496         }
497         ret = ID3DXFileDataImpl_Create(data_object, &object->children[object->nb_children]);
498         if (ret != S_OK)
499             break;
500         object->nb_children++;
501     }
502
503     IDirectXFileEnumObject_Release(dxfile_enum_object);
504
505     if (ret != DXFILEERR_NOMOREOBJECTS)
506         WARN("Cannot get all top level data objects\n");
507
508     TRACE("Found %u children\n", object->nb_children);
509
510     *enum_object = &object->ID3DXFileEnumObject_iface;
511
512     return S_OK;
513 }
514
515
516 static HRESULT WINAPI ID3DXFileImpl_CreateSaveObject(ID3DXFile *iface, const void *data, D3DXF_FILESAVEOPTIONS options, D3DXF_FILEFORMAT format, ID3DXFileSaveObject **save_object)
517 {
518     FIXME("(%p)->(%p, %x, %u, %p): stub\n", iface, data, options, format, save_object);
519
520     return E_NOTIMPL;
521 }
522
523
524 static HRESULT WINAPI ID3DXFileImpl_RegisterTemplates(ID3DXFile *iface, const void *data, SIZE_T size)
525 {
526     ID3DXFileImpl *This = impl_from_ID3DXFile(iface);
527     HRESULT ret;
528
529     TRACE("(%p)->(%p, %lu)\n", iface, data, size);
530
531     ret = IDirectXFile_RegisterTemplates(This->dxfile, (void*)data, size);
532     if (ret != DXFILE_OK)
533     {
534         WARN("Error %#x\n", ret);
535         return error_dxfile_to_d3dxfile(ret);
536     }
537
538     return S_OK;
539 }
540
541
542 static HRESULT WINAPI ID3DXFileImpl_RegisterEnumTemplates(ID3DXFile *iface, ID3DXFileEnumObject *enum_object)
543 {
544     FIXME("(%p)->(%p): stub\n", iface, enum_object);
545
546     return E_NOTIMPL;
547 }
548
549
550 static const ID3DXFileVtbl ID3DXFile_Vtbl =
551 {
552     ID3DXFileImpl_QueryInterface,
553     ID3DXFileImpl_AddRef,
554     ID3DXFileImpl_Release,
555     ID3DXFileImpl_CreateEnumObject,
556     ID3DXFileImpl_CreateSaveObject,
557     ID3DXFileImpl_RegisterTemplates,
558     ID3DXFileImpl_RegisterEnumTemplates
559 };
560
561 HRESULT WINAPI D3DXFileCreate(ID3DXFile **d3dxfile)
562 {
563     ID3DXFileImpl *object;
564     HRESULT ret;
565
566     TRACE("(%p)\n", d3dxfile);
567
568     if (!d3dxfile)
569         return E_POINTER;
570
571     *d3dxfile = NULL;
572
573     object = HeapAlloc(GetProcessHeap(), 0, sizeof(*object));
574     if (!object)
575         return E_OUTOFMEMORY;
576
577     ret = DirectXFileCreate(&object->dxfile);
578     if (ret != S_OK)
579     {
580         HeapFree(GetProcessHeap(), 0, object);
581         if (ret == E_OUTOFMEMORY)
582             return ret;
583         return E_FAIL;
584     }
585
586     object->ID3DXFile_iface.lpVtbl = &ID3DXFile_Vtbl;
587     object->ref = 1;
588
589     *d3dxfile = &object->ID3DXFile_iface;
590
591     return S_OK;
592 }