Blit9.cpp (25833B)
1 // 2 // Copyright 2002 The ANGLE Project Authors. All rights reserved. 3 // Use of this source code is governed by a BSD-style license that can be 4 // found in the LICENSE file. 5 // 6 7 // Blit9.cpp: Surface copy utility class. 8 9 #include "libANGLE/renderer/d3d/d3d9/Blit9.h" 10 11 #include "libANGLE/Context.h" 12 #include "libANGLE/Framebuffer.h" 13 #include "libANGLE/FramebufferAttachment.h" 14 #include "libANGLE/angletypes.h" 15 #include "libANGLE/renderer/d3d/TextureD3D.h" 16 #include "libANGLE/renderer/d3d/d3d9/RenderTarget9.h" 17 #include "libANGLE/renderer/d3d/d3d9/Renderer9.h" 18 #include "libANGLE/renderer/d3d/d3d9/TextureStorage9.h" 19 #include "libANGLE/renderer/d3d/d3d9/formatutils9.h" 20 #include "libANGLE/renderer/d3d/d3d9/renderer9_utils.h" 21 22 namespace 23 { 24 // Precompiled shaders 25 #include "libANGLE/renderer/d3d/d3d9/shaders/compiled/componentmaskpremultps.h" 26 #include "libANGLE/renderer/d3d/d3d9/shaders/compiled/componentmaskps.h" 27 #include "libANGLE/renderer/d3d/d3d9/shaders/compiled/componentmaskunmultps.h" 28 #include "libANGLE/renderer/d3d/d3d9/shaders/compiled/luminancepremultps.h" 29 #include "libANGLE/renderer/d3d/d3d9/shaders/compiled/luminanceps.h" 30 #include "libANGLE/renderer/d3d/d3d9/shaders/compiled/luminanceunmultps.h" 31 #include "libANGLE/renderer/d3d/d3d9/shaders/compiled/passthroughps.h" 32 #include "libANGLE/renderer/d3d/d3d9/shaders/compiled/standardvs.h" 33 34 const BYTE *const g_shaderCode[] = { 35 g_vs20_standardvs, 36 g_ps20_passthroughps, 37 g_ps20_luminanceps, 38 g_ps20_luminancepremultps, 39 g_ps20_luminanceunmultps, 40 g_ps20_componentmaskps, 41 g_ps20_componentmaskpremultps, 42 g_ps20_componentmaskunmultps, 43 }; 44 45 const size_t g_shaderSize[] = { 46 sizeof(g_vs20_standardvs), 47 sizeof(g_ps20_passthroughps), 48 sizeof(g_ps20_luminanceps), 49 sizeof(g_ps20_luminancepremultps), 50 sizeof(g_ps20_luminanceunmultps), 51 sizeof(g_ps20_componentmaskps), 52 sizeof(g_ps20_componentmaskpremultps), 53 sizeof(g_ps20_componentmaskunmultps), 54 }; 55 } // namespace 56 57 namespace rx 58 { 59 60 Blit9::Blit9(Renderer9 *renderer) 61 : mRenderer(renderer), 62 mGeometryLoaded(false), 63 mQuadVertexBuffer(nullptr), 64 mQuadVertexDeclaration(nullptr), 65 mSavedStateBlock(nullptr), 66 mSavedRenderTarget(nullptr), 67 mSavedDepthStencil(nullptr) 68 { 69 memset(mCompiledShaders, 0, sizeof(mCompiledShaders)); 70 } 71 72 Blit9::~Blit9() 73 { 74 SafeRelease(mSavedStateBlock); 75 SafeRelease(mQuadVertexBuffer); 76 SafeRelease(mQuadVertexDeclaration); 77 78 for (int i = 0; i < SHADER_COUNT; i++) 79 { 80 SafeRelease(mCompiledShaders[i]); 81 } 82 } 83 84 angle::Result Blit9::initialize(Context9 *context9) 85 { 86 if (mGeometryLoaded) 87 { 88 return angle::Result::Continue; 89 } 90 91 static const float quad[] = {-1, -1, -1, 1, 1, -1, 1, 1}; 92 93 IDirect3DDevice9 *device = mRenderer->getDevice(); 94 95 HRESULT result = device->CreateVertexBuffer(sizeof(quad), D3DUSAGE_WRITEONLY, 0, 96 D3DPOOL_DEFAULT, &mQuadVertexBuffer, nullptr); 97 98 ANGLE_TRY_HR(context9, result, "Failed to create internal blit vertex shader"); 99 100 void *lockPtr = nullptr; 101 result = mQuadVertexBuffer->Lock(0, 0, &lockPtr, 0); 102 103 ANGLE_TRY_HR(context9, result, "Failed to lock internal blit vertex shader"); 104 ASSERT(lockPtr); 105 106 memcpy(lockPtr, quad, sizeof(quad)); 107 mQuadVertexBuffer->Unlock(); 108 109 static const D3DVERTEXELEMENT9 elements[] = { 110 {0, 0, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, D3DDECL_END()}; 111 112 result = device->CreateVertexDeclaration(elements, &mQuadVertexDeclaration); 113 ANGLE_TRY_HR(context9, result, "Failed to create internal blit vertex shader declaration"); 114 115 mGeometryLoaded = true; 116 return angle::Result::Continue; 117 } 118 119 template <class D3DShaderType> 120 angle::Result Blit9::setShader(Context9 *context9, 121 ShaderId source, 122 const char *profile, 123 angle::Result (Renderer9::*createShader)(d3d::Context *, 124 const DWORD *, 125 size_t length, 126 D3DShaderType **outShader), 127 HRESULT (WINAPI IDirect3DDevice9::*setShader)(D3DShaderType *)) 128 { 129 IDirect3DDevice9 *device = mRenderer->getDevice(); 130 131 D3DShaderType *shader = nullptr; 132 133 if (mCompiledShaders[source] != nullptr) 134 { 135 shader = static_cast<D3DShaderType *>(mCompiledShaders[source]); 136 } 137 else 138 { 139 const BYTE *shaderCode = g_shaderCode[source]; 140 size_t shaderSize = g_shaderSize[source]; 141 ANGLE_TRY((mRenderer->*createShader)(context9, reinterpret_cast<const DWORD *>(shaderCode), 142 shaderSize, &shader)); 143 mCompiledShaders[source] = shader; 144 } 145 146 HRESULT hr = (device->*setShader)(shader); 147 ANGLE_TRY_HR(context9, hr, "Failed to set shader for blit operation"); 148 return angle::Result::Continue; 149 } 150 151 angle::Result Blit9::setVertexShader(Context9 *context9, ShaderId shader) 152 { 153 return setShader<IDirect3DVertexShader9>(context9, shader, "vs_2_0", 154 &Renderer9::createVertexShader, 155 &IDirect3DDevice9::SetVertexShader); 156 } 157 158 angle::Result Blit9::setPixelShader(Context9 *context9, ShaderId shader) 159 { 160 return setShader<IDirect3DPixelShader9>(context9, shader, "ps_2_0", 161 &Renderer9::createPixelShader, 162 &IDirect3DDevice9::SetPixelShader); 163 } 164 165 RECT Blit9::getSurfaceRect(IDirect3DSurface9 *surface) const 166 { 167 D3DSURFACE_DESC desc; 168 surface->GetDesc(&desc); 169 170 RECT rect; 171 rect.left = 0; 172 rect.top = 0; 173 rect.right = desc.Width; 174 rect.bottom = desc.Height; 175 176 return rect; 177 } 178 179 gl::Extents Blit9::getSurfaceSize(IDirect3DSurface9 *surface) const 180 { 181 D3DSURFACE_DESC desc; 182 surface->GetDesc(&desc); 183 184 return gl::Extents(desc.Width, desc.Height, 1); 185 } 186 187 angle::Result Blit9::boxFilter(Context9 *context9, 188 IDirect3DSurface9 *source, 189 IDirect3DSurface9 *dest) 190 { 191 ANGLE_TRY(initialize(context9)); 192 193 angle::ComPtr<IDirect3DBaseTexture9> texture = nullptr; 194 ANGLE_TRY(copySurfaceToTexture(context9, source, getSurfaceRect(source), &texture)); 195 196 IDirect3DDevice9 *device = mRenderer->getDevice(); 197 198 saveState(); 199 200 device->SetTexture(0, texture.Get()); 201 device->SetRenderTarget(0, dest); 202 203 ANGLE_TRY(setVertexShader(context9, SHADER_VS_STANDARD)); 204 ANGLE_TRY(setPixelShader(context9, SHADER_PS_PASSTHROUGH)); 205 206 setCommonBlitState(); 207 device->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR); 208 device->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR); 209 210 setViewportAndShaderConstants(getSurfaceRect(source), getSurfaceSize(source), 211 getSurfaceRect(dest), false); 212 213 render(); 214 215 restoreState(); 216 217 return angle::Result::Continue; 218 } 219 220 angle::Result Blit9::copy2D(const gl::Context *context, 221 const gl::Framebuffer *framebuffer, 222 const RECT &sourceRect, 223 GLenum destFormat, 224 const gl::Offset &destOffset, 225 TextureStorage *storage, 226 GLint level) 227 { 228 Context9 *context9 = GetImplAs<Context9>(context); 229 230 ANGLE_TRY(initialize(context9)); 231 232 const gl::FramebufferAttachment *colorbuffer = framebuffer->getColorAttachment(0); 233 ASSERT(colorbuffer); 234 235 RenderTarget9 *renderTarget9 = nullptr; 236 ANGLE_TRY(colorbuffer->getRenderTarget(context, 0, &renderTarget9)); 237 ASSERT(renderTarget9); 238 239 angle::ComPtr<IDirect3DSurface9> source = renderTarget9->getSurface(); 240 ASSERT(source); 241 242 angle::ComPtr<IDirect3DSurface9> destSurface = nullptr; 243 TextureStorage9 *storage9 = GetAs<TextureStorage9>(storage); 244 ANGLE_TRY( 245 storage9->getSurfaceLevel(context, gl::TextureTarget::_2D, level, true, &destSurface)); 246 ASSERT(destSurface); 247 248 ANGLE_TRY(copy(context9, source.Get(), nullptr, sourceRect, destFormat, destOffset, 249 destSurface.Get(), false, false, false)); 250 return angle::Result::Continue; 251 } 252 253 angle::Result Blit9::copyCube(const gl::Context *context, 254 const gl::Framebuffer *framebuffer, 255 const RECT &sourceRect, 256 GLenum destFormat, 257 const gl::Offset &destOffset, 258 TextureStorage *storage, 259 gl::TextureTarget target, 260 GLint level) 261 { 262 Context9 *context9 = GetImplAs<Context9>(context); 263 264 ANGLE_TRY(initialize(context9)); 265 266 const gl::FramebufferAttachment *colorbuffer = framebuffer->getColorAttachment(0); 267 ASSERT(colorbuffer); 268 269 RenderTarget9 *renderTarget9 = nullptr; 270 ANGLE_TRY(colorbuffer->getRenderTarget(context, 0, &renderTarget9)); 271 ASSERT(renderTarget9); 272 273 angle::ComPtr<IDirect3DSurface9> source = renderTarget9->getSurface(); 274 ASSERT(source); 275 276 angle::ComPtr<IDirect3DSurface9> destSurface = nullptr; 277 TextureStorage9 *storage9 = GetAs<TextureStorage9>(storage); 278 ANGLE_TRY(storage9->getSurfaceLevel(context, target, level, true, &destSurface)); 279 ASSERT(destSurface); 280 281 return copy(context9, source.Get(), nullptr, sourceRect, destFormat, destOffset, 282 destSurface.Get(), false, false, false); 283 } 284 285 angle::Result Blit9::copyTexture(const gl::Context *context, 286 const gl::Texture *source, 287 GLint sourceLevel, 288 const RECT &sourceRect, 289 GLenum destFormat, 290 const gl::Offset &destOffset, 291 TextureStorage *storage, 292 gl::TextureTarget destTarget, 293 GLint destLevel, 294 bool flipY, 295 bool premultiplyAlpha, 296 bool unmultiplyAlpha) 297 { 298 Context9 *context9 = GetImplAs<Context9>(context); 299 ANGLE_TRY(initialize(context9)); 300 301 TextureD3D *sourceD3D = GetImplAs<TextureD3D>(source); 302 303 TextureStorage *sourceStorage = nullptr; 304 ANGLE_TRY(sourceD3D->getNativeTexture(context, &sourceStorage)); 305 306 TextureStorage9_2D *sourceStorage9 = GetAs<TextureStorage9_2D>(sourceStorage); 307 ASSERT(sourceStorage9); 308 309 TextureStorage9 *destStorage9 = GetAs<TextureStorage9>(storage); 310 ASSERT(destStorage9); 311 312 ASSERT(sourceLevel == 0); 313 IDirect3DBaseTexture9 *sourceTexture = nullptr; 314 ANGLE_TRY(sourceStorage9->getBaseTexture(context, &sourceTexture)); 315 316 angle::ComPtr<IDirect3DSurface9> sourceSurface = nullptr; 317 ANGLE_TRY(sourceStorage9->getSurfaceLevel(context, gl::TextureTarget::_2D, sourceLevel, true, 318 &sourceSurface)); 319 320 angle::ComPtr<IDirect3DSurface9> destSurface = nullptr; 321 ANGLE_TRY(destStorage9->getSurfaceLevel(context, destTarget, destLevel, true, &destSurface)); 322 323 return copy(context9, sourceSurface.Get(), sourceTexture, sourceRect, destFormat, destOffset, 324 destSurface.Get(), flipY, premultiplyAlpha, unmultiplyAlpha); 325 } 326 327 angle::Result Blit9::copy(Context9 *context9, 328 IDirect3DSurface9 *source, 329 IDirect3DBaseTexture9 *sourceTexture, 330 const RECT &sourceRect, 331 GLenum destFormat, 332 const gl::Offset &destOffset, 333 IDirect3DSurface9 *dest, 334 bool flipY, 335 bool premultiplyAlpha, 336 bool unmultiplyAlpha) 337 { 338 ASSERT(source != nullptr && dest != nullptr); 339 340 IDirect3DDevice9 *device = mRenderer->getDevice(); 341 342 D3DSURFACE_DESC sourceDesc; 343 D3DSURFACE_DESC destDesc; 344 source->GetDesc(&sourceDesc); 345 dest->GetDesc(&destDesc); 346 347 // Check if it's possible to use StetchRect 348 if (sourceDesc.Format == destDesc.Format && (destDesc.Usage & D3DUSAGE_RENDERTARGET) && 349 d3d9_gl::IsFormatChannelEquivalent(destDesc.Format, destFormat) && !flipY && 350 premultiplyAlpha == unmultiplyAlpha) 351 { 352 RECT destRect = {destOffset.x, destOffset.y, 353 destOffset.x + (sourceRect.right - sourceRect.left), 354 destOffset.y + (sourceRect.bottom - sourceRect.top)}; 355 HRESULT result = device->StretchRect(source, &sourceRect, dest, &destRect, D3DTEXF_POINT); 356 ANGLE_TRY_HR(context9, result, "StretchRect failed to blit between textures"); 357 return angle::Result::Continue; 358 } 359 360 angle::ComPtr<IDirect3DBaseTexture9> texture = sourceTexture; 361 RECT adjustedSourceRect = sourceRect; 362 gl::Extents sourceSize(sourceDesc.Width, sourceDesc.Height, 1); 363 364 if (texture == nullptr) 365 { 366 ANGLE_TRY(copySurfaceToTexture(context9, source, sourceRect, &texture)); 367 368 // copySurfaceToTexture only copies in the sourceRect area of the source surface. 369 // Adjust sourceRect so that it is now covering the entire source texture 370 adjustedSourceRect.left = 0; 371 adjustedSourceRect.right = sourceRect.right - sourceRect.left; 372 adjustedSourceRect.top = 0; 373 adjustedSourceRect.bottom = sourceRect.bottom - sourceRect.top; 374 375 sourceSize.width = sourceRect.right - sourceRect.left; 376 sourceSize.height = sourceRect.bottom - sourceRect.top; 377 } 378 379 ANGLE_TRY(formatConvert(context9, texture.Get(), adjustedSourceRect, sourceSize, destFormat, 380 destOffset, dest, flipY, premultiplyAlpha, unmultiplyAlpha)); 381 return angle::Result::Continue; 382 } 383 384 angle::Result Blit9::formatConvert(Context9 *context9, 385 IDirect3DBaseTexture9 *source, 386 const RECT &sourceRect, 387 const gl::Extents &sourceSize, 388 GLenum destFormat, 389 const gl::Offset &destOffset, 390 IDirect3DSurface9 *dest, 391 bool flipY, 392 bool premultiplyAlpha, 393 bool unmultiplyAlpha) 394 { 395 ANGLE_TRY(initialize(context9)); 396 397 IDirect3DDevice9 *device = mRenderer->getDevice(); 398 399 saveState(); 400 401 device->SetTexture(0, source); 402 device->SetRenderTarget(0, dest); 403 404 RECT destRect; 405 destRect.left = destOffset.x; 406 destRect.right = destOffset.x + (sourceRect.right - sourceRect.left); 407 destRect.top = destOffset.y; 408 destRect.bottom = destOffset.y + (sourceRect.bottom - sourceRect.top); 409 410 setViewportAndShaderConstants(sourceRect, sourceSize, destRect, flipY); 411 412 setCommonBlitState(); 413 414 angle::Result result = 415 setFormatConvertShaders(context9, destFormat, flipY, premultiplyAlpha, unmultiplyAlpha); 416 if (result == angle::Result::Continue) 417 { 418 render(); 419 } 420 421 restoreState(); 422 423 return result; 424 } 425 426 angle::Result Blit9::setFormatConvertShaders(Context9 *context9, 427 GLenum destFormat, 428 bool flipY, 429 bool premultiplyAlpha, 430 bool unmultiplyAlpha) 431 { 432 ANGLE_TRY(setVertexShader(context9, SHADER_VS_STANDARD)); 433 434 switch (destFormat) 435 { 436 case GL_RGBA: 437 case GL_BGRA_EXT: 438 case GL_RGB: 439 case GL_RG_EXT: 440 case GL_RED_EXT: 441 case GL_ALPHA: 442 if (premultiplyAlpha == unmultiplyAlpha) 443 { 444 ANGLE_TRY(setPixelShader(context9, SHADER_PS_COMPONENTMASK)); 445 } 446 else if (premultiplyAlpha) 447 { 448 ANGLE_TRY(setPixelShader(context9, SHADER_PS_COMPONENTMASK_PREMULTIPLY_ALPHA)); 449 } 450 else 451 { 452 ASSERT(unmultiplyAlpha); 453 ANGLE_TRY(setPixelShader(context9, SHADER_PS_COMPONENTMASK_UNMULTIPLY_ALPHA)); 454 } 455 break; 456 457 case GL_LUMINANCE: 458 case GL_LUMINANCE_ALPHA: 459 if (premultiplyAlpha == unmultiplyAlpha) 460 { 461 ANGLE_TRY(setPixelShader(context9, SHADER_PS_LUMINANCE)); 462 } 463 else if (premultiplyAlpha) 464 { 465 ANGLE_TRY(setPixelShader(context9, SHADER_PS_LUMINANCE_PREMULTIPLY_ALPHA)); 466 } 467 else 468 { 469 ASSERT(unmultiplyAlpha); 470 ANGLE_TRY(setPixelShader(context9, SHADER_PS_LUMINANCE_UNMULTIPLY_ALPHA)); 471 } 472 break; 473 474 default: 475 UNREACHABLE(); 476 } 477 478 enum 479 { 480 X = 0, 481 Y = 1, 482 Z = 2, 483 W = 3 484 }; 485 486 // The meaning of this constant depends on the shader that was selected. 487 // See the shader assembly code above for details. 488 // Allocate one array for both registers and split it into two float4's. 489 float psConst[8] = {0}; 490 float *multConst = &psConst[0]; 491 float *addConst = &psConst[4]; 492 493 switch (destFormat) 494 { 495 case GL_RGBA: 496 case GL_BGRA_EXT: 497 multConst[X] = 1; 498 multConst[Y] = 1; 499 multConst[Z] = 1; 500 multConst[W] = 1; 501 addConst[X] = 0; 502 addConst[Y] = 0; 503 addConst[Z] = 0; 504 addConst[W] = 0; 505 break; 506 507 case GL_RGB: 508 multConst[X] = 1; 509 multConst[Y] = 1; 510 multConst[Z] = 1; 511 multConst[W] = 0; 512 addConst[X] = 0; 513 addConst[Y] = 0; 514 addConst[Z] = 0; 515 addConst[W] = 1; 516 break; 517 518 case GL_RG_EXT: 519 multConst[X] = 1; 520 multConst[Y] = 1; 521 multConst[Z] = 0; 522 multConst[W] = 0; 523 addConst[X] = 0; 524 addConst[Y] = 0; 525 addConst[Z] = 0; 526 addConst[W] = 1; 527 break; 528 529 case GL_RED_EXT: 530 multConst[X] = 1; 531 multConst[Y] = 0; 532 multConst[Z] = 0; 533 multConst[W] = 0; 534 addConst[X] = 0; 535 addConst[Y] = 0; 536 addConst[Z] = 0; 537 addConst[W] = 1; 538 break; 539 540 case GL_ALPHA: 541 multConst[X] = 0; 542 multConst[Y] = 0; 543 multConst[Z] = 0; 544 multConst[W] = 1; 545 addConst[X] = 0; 546 addConst[Y] = 0; 547 addConst[Z] = 0; 548 addConst[W] = 0; 549 break; 550 551 case GL_LUMINANCE: 552 multConst[X] = 1; 553 multConst[Y] = 0; 554 multConst[Z] = 0; 555 multConst[W] = 0; 556 addConst[X] = 0; 557 addConst[Y] = 0; 558 addConst[Z] = 0; 559 addConst[W] = 1; 560 break; 561 562 case GL_LUMINANCE_ALPHA: 563 multConst[X] = 1; 564 multConst[Y] = 0; 565 multConst[Z] = 0; 566 multConst[W] = 1; 567 addConst[X] = 0; 568 addConst[Y] = 0; 569 addConst[Z] = 0; 570 addConst[W] = 0; 571 break; 572 573 default: 574 UNREACHABLE(); 575 } 576 577 mRenderer->getDevice()->SetPixelShaderConstantF(0, psConst, 2); 578 579 return angle::Result::Continue; 580 } 581 582 angle::Result Blit9::copySurfaceToTexture(Context9 *context9, 583 IDirect3DSurface9 *surface, 584 const RECT &sourceRect, 585 angle::ComPtr<IDirect3DBaseTexture9> *outTexture) 586 { 587 ASSERT(surface); 588 589 IDirect3DDevice9 *device = mRenderer->getDevice(); 590 591 D3DSURFACE_DESC sourceDesc; 592 surface->GetDesc(&sourceDesc); 593 594 // Copy the render target into a texture 595 angle::ComPtr<IDirect3DTexture9> texture; 596 HRESULT result = device->CreateTexture( 597 sourceRect.right - sourceRect.left, sourceRect.bottom - sourceRect.top, 1, 598 D3DUSAGE_RENDERTARGET, sourceDesc.Format, D3DPOOL_DEFAULT, &texture, nullptr); 599 ANGLE_TRY_HR(context9, result, "Failed to allocate internal texture for blit"); 600 601 angle::ComPtr<IDirect3DSurface9> textureSurface; 602 result = texture->GetSurfaceLevel(0, &textureSurface); 603 ANGLE_TRY_HR(context9, result, "Failed to query surface of internal blit texture"); 604 605 mRenderer->endScene(); 606 result = device->StretchRect(surface, &sourceRect, textureSurface.Get(), nullptr, D3DTEXF_NONE); 607 ANGLE_TRY_HR(context9, result, "Failed to copy between internal blit textures"); 608 *outTexture = texture; 609 610 return angle::Result::Continue; 611 } 612 613 void Blit9::setViewportAndShaderConstants(const RECT &sourceRect, 614 const gl::Extents &sourceSize, 615 const RECT &destRect, 616 bool flipY) 617 { 618 IDirect3DDevice9 *device = mRenderer->getDevice(); 619 620 D3DVIEWPORT9 vp; 621 vp.X = destRect.left; 622 vp.Y = destRect.top; 623 vp.Width = destRect.right - destRect.left; 624 vp.Height = destRect.bottom - destRect.top; 625 vp.MinZ = 0.0f; 626 vp.MaxZ = 1.0f; 627 device->SetViewport(&vp); 628 629 float vertexConstants[8] = { 630 // halfPixelAdjust 631 -1.0f / vp.Width, 632 1.0f / vp.Height, 633 0, 634 0, 635 // texcoordOffset 636 static_cast<float>(sourceRect.left) / sourceSize.width, 637 static_cast<float>(flipY ? sourceRect.bottom : sourceRect.top) / sourceSize.height, 638 static_cast<float>(sourceRect.right - sourceRect.left) / sourceSize.width, 639 static_cast<float>(flipY ? sourceRect.top - sourceRect.bottom 640 : sourceRect.bottom - sourceRect.top) / 641 sourceSize.height, 642 }; 643 644 device->SetVertexShaderConstantF(0, vertexConstants, 2); 645 } 646 647 void Blit9::setCommonBlitState() 648 { 649 IDirect3DDevice9 *device = mRenderer->getDevice(); 650 651 device->SetDepthStencilSurface(nullptr); 652 653 device->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID); 654 device->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE); 655 device->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE); 656 device->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE); 657 device->SetRenderState(D3DRS_CLIPPLANEENABLE, 0); 658 device->SetRenderState(D3DRS_COLORWRITEENABLE, 659 D3DCOLORWRITEENABLE_ALPHA | D3DCOLORWRITEENABLE_BLUE | 660 D3DCOLORWRITEENABLE_GREEN | D3DCOLORWRITEENABLE_RED); 661 device->SetRenderState(D3DRS_SRGBWRITEENABLE, FALSE); 662 device->SetRenderState(D3DRS_SCISSORTESTENABLE, FALSE); 663 664 device->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_POINT); 665 device->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_POINT); 666 device->SetSamplerState(0, D3DSAMP_SRGBTEXTURE, FALSE); 667 device->SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP); 668 device->SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP); 669 670 RECT scissorRect = {}; // Scissoring is disabled for flipping, but we need this to capture and 671 // restore the old rectangle 672 device->SetScissorRect(&scissorRect); 673 674 for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++) 675 { 676 device->SetStreamSourceFreq(i, 1); 677 } 678 } 679 680 void Blit9::render() 681 { 682 IDirect3DDevice9 *device = mRenderer->getDevice(); 683 684 device->SetStreamSource(0, mQuadVertexBuffer, 0, 2 * sizeof(float)); 685 device->SetVertexDeclaration(mQuadVertexDeclaration); 686 687 mRenderer->startScene(); 688 device->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2); 689 } 690 691 void Blit9::saveState() 692 { 693 IDirect3DDevice9 *device = mRenderer->getDevice(); 694 695 HRESULT hr; 696 697 device->GetDepthStencilSurface(&mSavedDepthStencil); 698 device->GetRenderTarget(0, &mSavedRenderTarget); 699 700 if (mSavedStateBlock == nullptr) 701 { 702 hr = device->BeginStateBlock(); 703 ASSERT(SUCCEEDED(hr) || hr == D3DERR_OUTOFVIDEOMEMORY || hr == E_OUTOFMEMORY); 704 705 setCommonBlitState(); 706 707 static const float mockConst[8] = {0}; 708 709 device->SetVertexShader(nullptr); 710 device->SetVertexShaderConstantF(0, mockConst, 2); 711 device->SetPixelShader(nullptr); 712 device->SetPixelShaderConstantF(0, mockConst, 2); 713 714 D3DVIEWPORT9 mockVp; 715 mockVp.X = 0; 716 mockVp.Y = 0; 717 mockVp.Width = 1; 718 mockVp.Height = 1; 719 mockVp.MinZ = 0; 720 mockVp.MaxZ = 1; 721 722 device->SetViewport(&mockVp); 723 724 device->SetTexture(0, nullptr); 725 726 device->SetStreamSource(0, mQuadVertexBuffer, 0, 0); 727 728 device->SetVertexDeclaration(mQuadVertexDeclaration); 729 730 hr = device->EndStateBlock(&mSavedStateBlock); 731 ASSERT(SUCCEEDED(hr) || hr == D3DERR_OUTOFVIDEOMEMORY || hr == E_OUTOFMEMORY); 732 } 733 734 ASSERT(mSavedStateBlock != nullptr); 735 736 if (mSavedStateBlock != nullptr) 737 { 738 hr = mSavedStateBlock->Capture(); 739 ASSERT(SUCCEEDED(hr)); 740 } 741 } 742 743 void Blit9::restoreState() 744 { 745 IDirect3DDevice9 *device = mRenderer->getDevice(); 746 747 device->SetDepthStencilSurface(mSavedDepthStencil); 748 SafeRelease(mSavedDepthStencil); 749 750 device->SetRenderTarget(0, mSavedRenderTarget); 751 SafeRelease(mSavedRenderTarget); 752 753 ASSERT(mSavedStateBlock != nullptr); 754 755 if (mSavedStateBlock != nullptr) 756 { 757 mSavedStateBlock->Apply(); 758 } 759 } 760 } // namespace rx