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 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 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 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 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 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 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 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 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 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 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 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 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 349 static HRESULT WINAPI D3DXRenderToSurface_OnLostDevice(ID3DXRenderToSurface *iface) 350 { 351 FIXME("(%p)->(): stub\n", iface); 352 return D3D_OK; 353 } 354 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 718 static HRESULT WINAPI D3DXRenderToEnvMap_OnLostDevice(ID3DXRenderToEnvMap *iface) 719 { 720 FIXME("(%p)->(): stub\n", iface); 721 return D3D_OK; 722 } 723 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 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