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