1 #ifdef __REACTOS__
2 #include "precomp.h"
3 #else
4 /*
5 * Copyright (C) 2012 Józef Kucia
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20 *
21 */
22
23
24 #include "d3dx9_private.h"
25 #endif /* __REACTOS__ */
26
27 WINE_DEFAULT_DEBUG_CHANNEL(d3dx);
28
29 struct device_state
30 {
31 DWORD num_render_targets;
32 IDirect3DSurface9 **render_targets;
33 IDirect3DSurface9 *depth_stencil;
34 D3DVIEWPORT9 viewport;
35 };
36
device_state_init(IDirect3DDevice9 * device,struct device_state * state)37 static HRESULT device_state_init(IDirect3DDevice9 *device, struct device_state *state)
38 {
39 HRESULT hr;
40 D3DCAPS9 caps;
41 unsigned int i;
42
43 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
44 if (FAILED(hr)) return hr;
45
46 state->num_render_targets = caps.NumSimultaneousRTs;
47 state->render_targets = HeapAlloc(GetProcessHeap(), 0,
48 state->num_render_targets * sizeof(IDirect3DSurface9 *));
49 if (!state->render_targets)
50 return E_OUTOFMEMORY;
51
52 for (i = 0; i < state->num_render_targets; i++)
53 state->render_targets[i] = NULL;
54 state->depth_stencil = NULL;
55 return D3D_OK;
56 }
57
device_state_capture(IDirect3DDevice9 * device,struct device_state * state)58 static void device_state_capture(IDirect3DDevice9 *device, struct device_state *state)
59 {
60 HRESULT hr;
61 unsigned int i;
62
63 IDirect3DDevice9_GetViewport(device, &state->viewport);
64
65 for (i = 0; i < state->num_render_targets; i++)
66 {
67 hr = IDirect3DDevice9_GetRenderTarget(device, i, &state->render_targets[i]);
68 if (FAILED(hr)) state->render_targets[i] = NULL;
69 }
70
71 hr = IDirect3DDevice9_GetDepthStencilSurface(device, &state->depth_stencil);
72 if (FAILED(hr)) state->depth_stencil = NULL;
73 }
74
device_state_restore(IDirect3DDevice9 * device,struct device_state * state)75 static void device_state_restore(IDirect3DDevice9 *device, struct device_state *state)
76 {
77 unsigned int i;
78
79 for (i = 0; i < state->num_render_targets; i++)
80 {
81 IDirect3DDevice9_SetRenderTarget(device, i, state->render_targets[i]);
82 if (state->render_targets[i])
83 IDirect3DSurface9_Release(state->render_targets[i]);
84 state->render_targets[i] = NULL;
85 }
86
87 IDirect3DDevice9_SetDepthStencilSurface(device, state->depth_stencil);
88 if (state->depth_stencil)
89 {
90 IDirect3DSurface9_Release(state->depth_stencil);
91 state->depth_stencil = NULL;
92 }
93
94 IDirect3DDevice9_SetViewport(device, &state->viewport);
95 }
96
device_state_release(struct device_state * state)97 static void device_state_release(struct device_state *state)
98 {
99 unsigned int i;
100
101 for (i = 0; i < state->num_render_targets; i++)
102 {
103 if (state->render_targets[i])
104 IDirect3DSurface9_Release(state->render_targets[i]);
105 }
106
107 HeapFree(GetProcessHeap(), 0, state->render_targets);
108
109 if (state->depth_stencil) IDirect3DSurface9_Release(state->depth_stencil);
110 }
111
112 struct render_to_surface
113 {
114 ID3DXRenderToSurface ID3DXRenderToSurface_iface;
115 LONG ref;
116
117 IDirect3DDevice9 *device;
118 D3DXRTS_DESC desc;
119
120 IDirect3DSurface9 *dst_surface;
121
122 IDirect3DSurface9 *render_target;
123 IDirect3DSurface9 *depth_stencil;
124
125 struct device_state previous_state;
126 };
127
impl_from_ID3DXRenderToSurface(ID3DXRenderToSurface * iface)128 static inline struct render_to_surface *impl_from_ID3DXRenderToSurface(ID3DXRenderToSurface *iface)
129 {
130 return CONTAINING_RECORD(iface, struct render_to_surface, ID3DXRenderToSurface_iface);
131 }
132
D3DXRenderToSurface_QueryInterface(ID3DXRenderToSurface * iface,REFIID riid,void ** out)133 static HRESULT WINAPI D3DXRenderToSurface_QueryInterface(ID3DXRenderToSurface *iface,
134 REFIID riid,
135 void **out)
136 {
137 TRACE("iface %p, riid %s, out %p\n", iface, debugstr_guid(riid), out);
138
139 if (IsEqualGUID(riid, &IID_ID3DXRenderToSurface)
140 || IsEqualGUID(riid, &IID_IUnknown))
141 {
142 IUnknown_AddRef(iface);
143 *out = iface;
144 return S_OK;
145 }
146
147 WARN("%s not implemented, returning E_NOINTERFACE\n", debugstr_guid(riid));
148
149 *out = NULL;
150 return E_NOINTERFACE;
151 }
152
D3DXRenderToSurface_AddRef(ID3DXRenderToSurface * iface)153 static ULONG WINAPI D3DXRenderToSurface_AddRef(ID3DXRenderToSurface *iface)
154 {
155 struct render_to_surface *render = impl_from_ID3DXRenderToSurface(iface);
156 ULONG ref = InterlockedIncrement(&render->ref);
157
158 TRACE("%p increasing refcount to %u\n", iface, ref);
159
160 return ref;
161 }
162
D3DXRenderToSurface_Release(ID3DXRenderToSurface * iface)163 static ULONG WINAPI D3DXRenderToSurface_Release(ID3DXRenderToSurface *iface)
164 {
165 struct render_to_surface *render = impl_from_ID3DXRenderToSurface(iface);
166 ULONG ref = InterlockedDecrement(&render->ref);
167
168 TRACE("%p decreasing refcount to %u\n", iface, ref);
169
170 if (!ref)
171 {
172 if (render->dst_surface) IDirect3DSurface9_Release(render->dst_surface);
173
174 if (render->render_target) IDirect3DSurface9_Release(render->render_target);
175 if (render->depth_stencil) IDirect3DSurface9_Release(render->depth_stencil);
176
177 device_state_release(&render->previous_state);
178
179 IDirect3DDevice9_Release(render->device);
180
181 HeapFree(GetProcessHeap(), 0, render);
182 }
183
184 return ref;
185 }
186
D3DXRenderToSurface_GetDevice(ID3DXRenderToSurface * iface,IDirect3DDevice9 ** device)187 static HRESULT WINAPI D3DXRenderToSurface_GetDevice(ID3DXRenderToSurface *iface,
188 IDirect3DDevice9 **device)
189 {
190 struct render_to_surface *render = impl_from_ID3DXRenderToSurface(iface);
191
192 TRACE("(%p)->(%p)\n", iface, device);
193
194 if (!device) return D3DERR_INVALIDCALL;
195
196 IDirect3DDevice9_AddRef(render->device);
197 *device = render->device;
198 return D3D_OK;
199 }
200
D3DXRenderToSurface_GetDesc(ID3DXRenderToSurface * iface,D3DXRTS_DESC * desc)201 static HRESULT WINAPI D3DXRenderToSurface_GetDesc(ID3DXRenderToSurface *iface,
202 D3DXRTS_DESC *desc)
203 {
204 struct render_to_surface *render = impl_from_ID3DXRenderToSurface(iface);
205
206 TRACE("(%p)->(%p)\n", iface, desc);
207
208 if (!desc) return D3DERR_INVALIDCALL;
209
210 *desc = render->desc;
211 return D3D_OK;
212 }
213
D3DXRenderToSurface_BeginScene(ID3DXRenderToSurface * iface,IDirect3DSurface9 * surface,const D3DVIEWPORT9 * viewport)214 static HRESULT WINAPI D3DXRenderToSurface_BeginScene(ID3DXRenderToSurface *iface,
215 IDirect3DSurface9 *surface,
216 const D3DVIEWPORT9 *viewport)
217 {
218 struct render_to_surface *render = impl_from_ID3DXRenderToSurface(iface);
219 unsigned int i;
220 IDirect3DDevice9 *device;
221 D3DSURFACE_DESC surface_desc;
222 HRESULT hr = D3DERR_INVALIDCALL;
223 D3DMULTISAMPLE_TYPE multi_sample_type = D3DMULTISAMPLE_NONE;
224 DWORD multi_sample_quality = 0;
225
226 TRACE("(%p)->(%p, %p)\n", iface, surface, viewport);
227
228 if (!surface || render->dst_surface) return D3DERR_INVALIDCALL;
229
230 IDirect3DSurface9_GetDesc(surface, &surface_desc);
231 if (surface_desc.Format != render->desc.Format
232 || surface_desc.Width != render->desc.Width
233 || surface_desc.Height != render->desc.Height)
234 return D3DERR_INVALIDCALL;
235
236 if (viewport)
237 {
238 if (viewport->X > render->desc.Width || viewport->Y > render->desc.Height
239 || viewport->X + viewport->Width > render->desc.Width
240 || viewport->Y + viewport->Height > render->desc.Height)
241 return D3DERR_INVALIDCALL;
242
243 if (!(surface_desc.Usage & D3DUSAGE_RENDERTARGET)
244 && (viewport->X != 0 || viewport->Y != 0
245 || viewport->Width != render->desc.Width
246 || viewport->Height != render->desc.Height))
247 return D3DERR_INVALIDCALL;
248 }
249
250 device = render->device;
251
252 device_state_capture(device, &render->previous_state);
253
254 /* prepare for rendering to surface */
255 for (i = 1; i < render->previous_state.num_render_targets; i++)
256 IDirect3DDevice9_SetRenderTarget(device, i, NULL);
257
258 if (surface_desc.Usage & D3DUSAGE_RENDERTARGET)
259 {
260 hr = IDirect3DDevice9_SetRenderTarget(device, 0, surface);
261 multi_sample_type = surface_desc.MultiSampleType;
262 multi_sample_quality = surface_desc.MultiSampleQuality;
263 }
264 else
265 {
266 hr = IDirect3DDevice9_CreateRenderTarget(device, render->desc.Width, render->desc.Height,
267 render->desc.Format, multi_sample_type, multi_sample_quality, FALSE,
268 &render->render_target, NULL);
269 if (FAILED(hr)) goto cleanup;
270 hr = IDirect3DDevice9_SetRenderTarget(device, 0, render->render_target);
271 }
272
273 if (FAILED(hr)) goto cleanup;
274
275 if (render->desc.DepthStencil)
276 {
277 hr = IDirect3DDevice9_CreateDepthStencilSurface(device, render->desc.Width, render->desc.Height,
278 render->desc.DepthStencilFormat, multi_sample_type, multi_sample_quality, TRUE,
279 &render->depth_stencil, NULL);
280 }
281 else render->depth_stencil = NULL;
282
283 if (FAILED(hr)) goto cleanup;
284
285 hr = IDirect3DDevice9_SetDepthStencilSurface(device, render->depth_stencil);
286 if (FAILED(hr)) goto cleanup;
287
288 if (viewport) IDirect3DDevice9_SetViewport(device, viewport);
289
290 IDirect3DSurface9_AddRef(surface);
291 render->dst_surface = surface;
292 return IDirect3DDevice9_BeginScene(device);
293
294 cleanup:
295 device_state_restore(device, &render->previous_state);
296
297 if (render->dst_surface) IDirect3DSurface9_Release(render->dst_surface);
298 render->dst_surface = NULL;
299
300 if (render->render_target) IDirect3DSurface9_Release(render->render_target);
301 render->render_target = NULL;
302 if (render->depth_stencil) IDirect3DSurface9_Release(render->depth_stencil);
303 render->depth_stencil = NULL;
304
305 return hr;
306 }
307
D3DXRenderToSurface_EndScene(ID3DXRenderToSurface * iface,DWORD filter)308 static HRESULT WINAPI D3DXRenderToSurface_EndScene(ID3DXRenderToSurface *iface,
309 DWORD filter)
310 {
311 struct render_to_surface *render = impl_from_ID3DXRenderToSurface(iface);
312 HRESULT hr;
313
314 TRACE("(%p)->(%#x)\n", iface, filter);
315
316 if (!render->dst_surface) return D3DERR_INVALIDCALL;
317
318 hr = IDirect3DDevice9_EndScene(render->device);
319
320 /* copy render target data to destination surface, if needed */
321 if (render->render_target)
322 {
323 hr = D3DXLoadSurfaceFromSurface(render->dst_surface, NULL, NULL,
324 render->render_target, NULL, NULL, filter, 0);
325 if (FAILED(hr)) ERR("Copying render target data to surface failed %#x\n", hr);
326 }
327
328 device_state_restore(render->device, &render->previous_state);
329
330 /* release resources */
331 if (render->render_target)
332 {
333 IDirect3DSurface9_Release(render->render_target);
334 render->render_target = NULL;
335 }
336
337 if (render->depth_stencil)
338 {
339 IDirect3DSurface9_Release(render->depth_stencil);
340 render->depth_stencil = NULL;
341 }
342
343 IDirect3DSurface9_Release(render->dst_surface);
344 render->dst_surface = NULL;
345
346 return hr;
347 }
348
D3DXRenderToSurface_OnLostDevice(ID3DXRenderToSurface * iface)349 static HRESULT WINAPI D3DXRenderToSurface_OnLostDevice(ID3DXRenderToSurface *iface)
350 {
351 FIXME("(%p)->(): stub\n", iface);
352 return D3D_OK;
353 }
354
D3DXRenderToSurface_OnResetDevice(ID3DXRenderToSurface * iface)355 static HRESULT WINAPI D3DXRenderToSurface_OnResetDevice(ID3DXRenderToSurface *iface)
356 {
357 FIXME("(%p)->(): stub\n", iface);
358 return D3D_OK;
359 }
360
361 static const ID3DXRenderToSurfaceVtbl render_to_surface_vtbl =
362 {
363 /* IUnknown methods */
364 D3DXRenderToSurface_QueryInterface,
365 D3DXRenderToSurface_AddRef,
366 D3DXRenderToSurface_Release,
367 /* ID3DXRenderToSurface methods */
368 D3DXRenderToSurface_GetDevice,
369 D3DXRenderToSurface_GetDesc,
370 D3DXRenderToSurface_BeginScene,
371 D3DXRenderToSurface_EndScene,
372 D3DXRenderToSurface_OnLostDevice,
373 D3DXRenderToSurface_OnResetDevice
374 };
375
D3DXCreateRenderToSurface(IDirect3DDevice9 * device,UINT width,UINT height,D3DFORMAT format,BOOL depth_stencil,D3DFORMAT depth_stencil_format,ID3DXRenderToSurface ** out)376 HRESULT WINAPI D3DXCreateRenderToSurface(IDirect3DDevice9 *device,
377 UINT width,
378 UINT height,
379 D3DFORMAT format,
380 BOOL depth_stencil,
381 D3DFORMAT depth_stencil_format,
382 ID3DXRenderToSurface **out)
383 {
384 HRESULT hr;
385 struct render_to_surface *render;
386
387 TRACE("(%p, %u, %u, %#x, %d, %#x, %p)\n", device, width, height, format,
388 depth_stencil, depth_stencil_format, out);
389
390 if (!device || !out) return D3DERR_INVALIDCALL;
391
392 render = HeapAlloc(GetProcessHeap(), 0, sizeof(struct render_to_surface));
393 if (!render) return E_OUTOFMEMORY;
394
395 render->ID3DXRenderToSurface_iface.lpVtbl = &render_to_surface_vtbl;
396 render->ref = 1;
397
398 render->desc.Width = width;
399 render->desc.Height = height;
400 render->desc.Format = format;
401 render->desc.DepthStencil = depth_stencil;
402 render->desc.DepthStencilFormat = depth_stencil_format;
403
404 render->dst_surface = NULL;
405 render->render_target = NULL;
406 render->depth_stencil = NULL;
407
408 hr = device_state_init(device, &render->previous_state);
409 if (FAILED(hr))
410 {
411 HeapFree(GetProcessHeap(), 0, render);
412 return hr;
413 }
414
415 IDirect3DDevice9_AddRef(device);
416 render->device = device;
417
418 *out = &render->ID3DXRenderToSurface_iface;
419 return D3D_OK;
420 }
421
422
423 enum render_state
424 {
425 INITIAL,
426
427 CUBE_BEGIN,
428 CUBE_FACE
429 };
430
431 struct render_to_envmap
432 {
433 ID3DXRenderToEnvMap ID3DXRenderToEnvMap_iface;
434 LONG ref;
435
436 IDirect3DDevice9 *device;
437 D3DXRTE_DESC desc;
438
439 enum render_state state;
440 struct device_state previous_device_state;
441
442 D3DCUBEMAP_FACES face;
443 DWORD filter;
444
445 IDirect3DSurface9 *render_target;
446 IDirect3DSurface9 *depth_stencil;
447
448 IDirect3DCubeTexture9 *dst_cube_texture;
449 };
450
copy_render_target_to_cube_texture_face(IDirect3DCubeTexture9 * cube_texture,D3DCUBEMAP_FACES face,IDirect3DSurface9 * render_target,DWORD filter)451 static void copy_render_target_to_cube_texture_face(IDirect3DCubeTexture9 *cube_texture,
452 D3DCUBEMAP_FACES face, IDirect3DSurface9 *render_target, DWORD filter)
453 {
454 HRESULT hr;
455 IDirect3DSurface9 *cube_surface;
456
457 IDirect3DCubeTexture9_GetCubeMapSurface(cube_texture, face, 0, &cube_surface);
458
459 hr = D3DXLoadSurfaceFromSurface(cube_surface, NULL, NULL, render_target, NULL, NULL, filter, 0);
460 if (FAILED(hr)) ERR("Copying render target data to surface failed %#x\n", hr);
461
462 IDirect3DSurface9_Release(cube_surface);
463 }
464
impl_from_ID3DXRenderToEnvMap(ID3DXRenderToEnvMap * iface)465 static inline struct render_to_envmap *impl_from_ID3DXRenderToEnvMap(ID3DXRenderToEnvMap *iface)
466 {
467 return CONTAINING_RECORD(iface, struct render_to_envmap, ID3DXRenderToEnvMap_iface);
468 }
469
D3DXRenderToEnvMap_QueryInterface(ID3DXRenderToEnvMap * iface,REFIID riid,void ** out)470 static HRESULT WINAPI D3DXRenderToEnvMap_QueryInterface(ID3DXRenderToEnvMap *iface,
471 REFIID riid,
472 void **out)
473 {
474 TRACE("iface %p, riid %s, out %p\n", iface, debugstr_guid(riid), out);
475
476 if (IsEqualGUID(riid, &IID_ID3DXRenderToEnvMap)
477 || IsEqualGUID(riid, &IID_IUnknown))
478 {
479 IUnknown_AddRef(iface);
480 *out = iface;
481 return S_OK;
482 }
483
484 WARN("%s not implemented, returning E_NOINTERFACE\n", debugstr_guid(riid));
485
486 *out = NULL;
487 return E_NOINTERFACE;
488 }
489
D3DXRenderToEnvMap_AddRef(ID3DXRenderToEnvMap * iface)490 static ULONG WINAPI D3DXRenderToEnvMap_AddRef(ID3DXRenderToEnvMap *iface)
491 {
492 struct render_to_envmap *render = impl_from_ID3DXRenderToEnvMap(iface);
493 ULONG ref = InterlockedIncrement(&render->ref);
494
495 TRACE("%p increasing refcount to %u\n", iface, ref);
496
497 return ref;
498 }
499
D3DXRenderToEnvMap_Release(ID3DXRenderToEnvMap * iface)500 static ULONG WINAPI D3DXRenderToEnvMap_Release(ID3DXRenderToEnvMap *iface)
501 {
502 struct render_to_envmap *render = impl_from_ID3DXRenderToEnvMap(iface);
503 ULONG ref = InterlockedDecrement(&render->ref);
504
505 TRACE("%p decreasing refcount to %u\n", iface, ref);
506
507 if (!ref)
508 {
509 if (render->dst_cube_texture) IDirect3DSurface9_Release(render->dst_cube_texture);
510
511 if (render->render_target) IDirect3DSurface9_Release(render->render_target);
512 if (render->depth_stencil) IDirect3DSurface9_Release(render->depth_stencil);
513
514 device_state_release(&render->previous_device_state);
515
516 IDirect3DDevice9_Release(render->device);
517
518 HeapFree(GetProcessHeap(), 0, render);
519 }
520
521 return ref;
522 }
523
D3DXRenderToEnvMap_GetDevice(ID3DXRenderToEnvMap * iface,IDirect3DDevice9 ** device)524 static HRESULT WINAPI D3DXRenderToEnvMap_GetDevice(ID3DXRenderToEnvMap *iface,
525 IDirect3DDevice9 **device)
526 {
527 struct render_to_envmap *render = impl_from_ID3DXRenderToEnvMap(iface);
528
529 TRACE("(%p)->(%p)\n", iface, device);
530
531 if (!device) return D3DERR_INVALIDCALL;
532
533 IDirect3DDevice9_AddRef(render->device);
534 *device = render->device;
535 return D3D_OK;
536 }
537
D3DXRenderToEnvMap_GetDesc(ID3DXRenderToEnvMap * iface,D3DXRTE_DESC * desc)538 static HRESULT WINAPI D3DXRenderToEnvMap_GetDesc(ID3DXRenderToEnvMap *iface,
539 D3DXRTE_DESC *desc)
540 {
541 struct render_to_envmap *render = impl_from_ID3DXRenderToEnvMap(iface);
542
543 TRACE("(%p)->(%p)\n", iface, desc);
544
545 if (!desc) return D3DERR_INVALIDCALL;
546
547 *desc = render->desc;
548 return D3D_OK;
549 }
550
D3DXRenderToEnvMap_BeginCube(ID3DXRenderToEnvMap * iface,IDirect3DCubeTexture9 * texture)551 static HRESULT WINAPI D3DXRenderToEnvMap_BeginCube(ID3DXRenderToEnvMap *iface,
552 IDirect3DCubeTexture9 *texture)
553 {
554 struct render_to_envmap *render = impl_from_ID3DXRenderToEnvMap(iface);
555 HRESULT hr;
556 D3DSURFACE_DESC level_desc;
557
558 TRACE("(%p)->(%p)\n", iface, texture);
559
560 if (!texture) return D3DERR_INVALIDCALL;
561
562 if (render->state != INITIAL) return D3DERR_INVALIDCALL;
563
564 IDirect3DCubeTexture9_GetLevelDesc(texture, 0, &level_desc);
565 if (level_desc.Format != render->desc.Format || level_desc.Width != render->desc.Size)
566 return D3DERR_INVALIDCALL;
567
568 if (!(level_desc.Usage & D3DUSAGE_RENDERTARGET))
569 {
570 hr = IDirect3DDevice9_CreateRenderTarget(render->device, level_desc.Width, level_desc.Height,
571 level_desc.Format, level_desc.MultiSampleType, level_desc.MultiSampleQuality,
572 TRUE, &render->render_target, NULL);
573 if (FAILED(hr)) goto cleanup;
574 IDirect3DCubeTexture9_GetLevelDesc(texture, 0, &level_desc);
575 }
576
577 if (render->desc.DepthStencil)
578 {
579 hr = IDirect3DDevice9_CreateDepthStencilSurface(render->device, level_desc.Width, level_desc.Height,
580 render->desc.DepthStencilFormat, level_desc.MultiSampleType, level_desc.MultiSampleQuality,
581 TRUE, &render->depth_stencil, NULL);
582 if (FAILED(hr)) goto cleanup;
583 }
584
585 IDirect3DCubeTexture9_AddRef(texture);
586 render->dst_cube_texture = texture;
587 render->state = CUBE_BEGIN;
588 return D3D_OK;
589
590 cleanup:
591 if (render->dst_cube_texture) IDirect3DSurface9_Release(render->dst_cube_texture);
592 render->dst_cube_texture = NULL;
593
594 if (render->render_target) IDirect3DSurface9_Release(render->render_target);
595 render->render_target = NULL;
596 if (render->depth_stencil) IDirect3DSurface9_Release(render->depth_stencil);
597 render->depth_stencil = NULL;
598
599 return hr;
600 }
601
D3DXRenderToEnvMap_BeginSphere(ID3DXRenderToEnvMap * iface,IDirect3DTexture9 * texture)602 static HRESULT WINAPI D3DXRenderToEnvMap_BeginSphere(ID3DXRenderToEnvMap *iface,
603 IDirect3DTexture9 *texture)
604 {
605 FIXME("(%p)->(%p): stub\n", iface, texture);
606 return E_NOTIMPL;
607 }
608
D3DXRenderToEnvMap_BeginHemisphere(ID3DXRenderToEnvMap * iface,IDirect3DTexture9 * pos_z_texture,IDirect3DTexture9 * neg_z_texture)609 static HRESULT WINAPI D3DXRenderToEnvMap_BeginHemisphere(ID3DXRenderToEnvMap *iface,
610 IDirect3DTexture9 *pos_z_texture,
611 IDirect3DTexture9 *neg_z_texture)
612 {
613 FIXME("(%p)->(%p, %p): stub\n", iface, pos_z_texture, neg_z_texture);
614 return E_NOTIMPL;
615 }
616
D3DXRenderToEnvMap_BeginParabolic(ID3DXRenderToEnvMap * iface,IDirect3DTexture9 * pos_z_texture,IDirect3DTexture9 * neg_z_texture)617 static HRESULT WINAPI D3DXRenderToEnvMap_BeginParabolic(ID3DXRenderToEnvMap *iface,
618 IDirect3DTexture9 *pos_z_texture,
619 IDirect3DTexture9 *neg_z_texture)
620 {
621 FIXME("(%p)->(%p, %p): stub\n", iface, pos_z_texture, neg_z_texture);
622 return E_NOTIMPL;
623 }
624
D3DXRenderToEnvMap_Face(ID3DXRenderToEnvMap * iface,D3DCUBEMAP_FACES face,DWORD filter)625 static HRESULT WINAPI D3DXRenderToEnvMap_Face(ID3DXRenderToEnvMap *iface,
626 D3DCUBEMAP_FACES face,
627 DWORD filter)
628 {
629 struct render_to_envmap *render = impl_from_ID3DXRenderToEnvMap(iface);
630 HRESULT hr;
631 unsigned int i;
632
633 TRACE("(%p)->(%u, %#x)\n", iface, face, filter);
634
635 if (render->state == CUBE_FACE)
636 {
637 IDirect3DDevice9_EndScene(render->device);
638 if (render->render_target)
639 copy_render_target_to_cube_texture_face(render->dst_cube_texture, render->face,
640 render->render_target, render->filter);
641
642 device_state_restore(render->device, &render->previous_device_state);
643
644 render->state = CUBE_BEGIN;
645 }
646 else if (render->state != CUBE_BEGIN)
647 return D3DERR_INVALIDCALL;
648
649 device_state_capture(render->device, &render->previous_device_state);
650
651 for (i = 1; i < render->previous_device_state.num_render_targets; i++)
652 IDirect3DDevice9_SetRenderTarget(render->device, i, NULL);
653
654 if (!render->render_target)
655 {
656 IDirect3DSurface9 *render_target;
657 IDirect3DCubeTexture9_GetCubeMapSurface(render->dst_cube_texture, face, 0, &render_target);
658 hr = IDirect3DDevice9_SetRenderTarget(render->device, 0, render_target);
659 IDirect3DSurface9_Release(render_target);
660 }
661 else hr = IDirect3DDevice9_SetRenderTarget(render->device, 0, render->render_target);
662
663 if (FAILED(hr)) goto cleanup;
664
665 hr = IDirect3DDevice9_SetDepthStencilSurface(render->device, render->depth_stencil);
666 if (FAILED(hr)) goto cleanup;
667
668 render->state = CUBE_FACE;
669 render->face = face;
670 render->filter = filter;
671 return IDirect3DDevice9_BeginScene(render->device);
672
673 cleanup:
674 device_state_restore(render->device, &render->previous_device_state);
675 return hr;
676 }
677
D3DXRenderToEnvMap_End(ID3DXRenderToEnvMap * iface,DWORD filter)678 static HRESULT WINAPI D3DXRenderToEnvMap_End(ID3DXRenderToEnvMap *iface,
679 DWORD filter)
680 {
681 struct render_to_envmap *render = impl_from_ID3DXRenderToEnvMap(iface);
682
683 TRACE("(%p)->(%#x)\n", iface, filter);
684
685 if (render->state == INITIAL) return D3DERR_INVALIDCALL;
686
687 if (render->state == CUBE_FACE)
688 {
689 IDirect3DDevice9_EndScene(render->device);
690 if (render->render_target)
691 copy_render_target_to_cube_texture_face(render->dst_cube_texture, render->face,
692 render->render_target, render->filter);
693
694 device_state_restore(render->device, &render->previous_device_state);
695 }
696
697 D3DXFilterTexture((IDirect3DBaseTexture9 *)render->dst_cube_texture, NULL, 0, filter);
698
699 if (render->render_target)
700 {
701 IDirect3DSurface9_Release(render->render_target);
702 render->render_target = NULL;
703 }
704
705 if (render->depth_stencil)
706 {
707 IDirect3DSurface9_Release(render->depth_stencil);
708 render->depth_stencil = NULL;
709 }
710
711 IDirect3DSurface9_Release(render->dst_cube_texture);
712 render->dst_cube_texture = NULL;
713
714 render->state = INITIAL;
715 return D3D_OK;
716 }
717
D3DXRenderToEnvMap_OnLostDevice(ID3DXRenderToEnvMap * iface)718 static HRESULT WINAPI D3DXRenderToEnvMap_OnLostDevice(ID3DXRenderToEnvMap *iface)
719 {
720 FIXME("(%p)->(): stub\n", iface);
721 return D3D_OK;
722 }
723
D3DXRenderToEnvMap_OnResetDevice(ID3DXRenderToEnvMap * iface)724 static HRESULT WINAPI D3DXRenderToEnvMap_OnResetDevice(ID3DXRenderToEnvMap *iface)
725 {
726 FIXME("(%p)->(): stub\n", iface);
727 return D3D_OK;
728 }
729
730 static const ID3DXRenderToEnvMapVtbl render_to_envmap_vtbl =
731 {
732 /* IUnknown methods */
733 D3DXRenderToEnvMap_QueryInterface,
734 D3DXRenderToEnvMap_AddRef,
735 D3DXRenderToEnvMap_Release,
736 /* ID3DXRenderToEnvMap methods */
737 D3DXRenderToEnvMap_GetDevice,
738 D3DXRenderToEnvMap_GetDesc,
739 D3DXRenderToEnvMap_BeginCube,
740 D3DXRenderToEnvMap_BeginSphere,
741 D3DXRenderToEnvMap_BeginHemisphere,
742 D3DXRenderToEnvMap_BeginParabolic,
743 D3DXRenderToEnvMap_Face,
744 D3DXRenderToEnvMap_End,
745 D3DXRenderToEnvMap_OnLostDevice,
746 D3DXRenderToEnvMap_OnResetDevice
747 };
748
D3DXCreateRenderToEnvMap(IDirect3DDevice9 * device,UINT size,UINT mip_levels,D3DFORMAT format,BOOL depth_stencil,D3DFORMAT depth_stencil_format,ID3DXRenderToEnvMap ** out)749 HRESULT WINAPI D3DXCreateRenderToEnvMap(IDirect3DDevice9 *device,
750 UINT size,
751 UINT mip_levels,
752 D3DFORMAT format,
753 BOOL depth_stencil,
754 D3DFORMAT depth_stencil_format,
755 ID3DXRenderToEnvMap **out)
756 {
757 HRESULT hr;
758 struct render_to_envmap *render;
759
760 TRACE("(%p, %u, %u, %#x, %d, %#x, %p)\n", device, size, mip_levels,
761 format, depth_stencil, depth_stencil_format, out);
762
763 if (!device || !out) return D3DERR_INVALIDCALL;
764
765 hr = D3DXCheckTextureRequirements(device, &size, &size, &mip_levels,
766 D3DUSAGE_RENDERTARGET, &format, D3DPOOL_DEFAULT);
767 if (FAILED(hr)) return hr;
768
769 render = HeapAlloc(GetProcessHeap(), 0, sizeof(struct render_to_envmap));
770 if (!render) return E_OUTOFMEMORY;
771
772 render->ID3DXRenderToEnvMap_iface.lpVtbl = &render_to_envmap_vtbl;
773 render->ref = 1;
774
775 render->desc.Size = size;
776 render->desc.MipLevels = mip_levels;
777 render->desc.Format = format;
778 render->desc.DepthStencil = depth_stencil;
779 render->desc.DepthStencilFormat = depth_stencil_format;
780
781 render->state = INITIAL;
782 render->render_target = NULL;
783 render->depth_stencil = NULL;
784 render->dst_cube_texture = NULL;
785
786 hr = device_state_init(device, &render->previous_device_state);
787 if (FAILED(hr))
788 {
789 HeapFree(GetProcessHeap(), 0, render);
790 return hr;
791 }
792
793 IDirect3DDevice9_AddRef(device);
794 render->device = device;
795
796 *out = &render->ID3DXRenderToEnvMap_iface;
797 return D3D_OK;
798 }
799