Home | History | Annotate | Download | only in d3d9
      1 #include "precompiled.h"
      2 //
      3 // Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
      4 // Use of this source code is governed by a BSD-style license that can be
      5 // found in the LICENSE file.
      6 //
      7 
      8 // Blit9.cpp: Surface copy utility class.
      9 
     10 #include "libGLESv2/renderer/d3d9/Blit9.h"
     11 
     12 #include "libGLESv2/main.h"
     13 #include "libGLESv2/renderer/d3d9/renderer9_utils.h"
     14 #include "libGLESv2/renderer/d3d9/formatutils9.h"
     15 #include "libGLESv2/renderer/d3d9/TextureStorage9.h"
     16 #include "libGLESv2/renderer/d3d9/RenderTarget9.h"
     17 #include "libGLESv2/renderer/d3d9/Renderer9.h"
     18 #include "libGLESv2/Framebuffer.h"
     19 #include "libGLESv2/Renderbuffer.h"
     20 
     21 namespace
     22 {
     23 #include "libGLESv2/renderer/d3d9/shaders/compiled/standardvs.h"
     24 #include "libGLESv2/renderer/d3d9/shaders/compiled/flipyvs.h"
     25 #include "libGLESv2/renderer/d3d9/shaders/compiled/passthroughps.h"
     26 #include "libGLESv2/renderer/d3d9/shaders/compiled/luminanceps.h"
     27 #include "libGLESv2/renderer/d3d9/shaders/compiled/componentmaskps.h"
     28 
     29 const BYTE* const g_shaderCode[] =
     30 {
     31     g_vs20_standardvs,
     32     g_vs20_flipyvs,
     33     g_ps20_passthroughps,
     34     g_ps20_luminanceps,
     35     g_ps20_componentmaskps
     36 };
     37 
     38 const size_t g_shaderSize[] =
     39 {
     40     sizeof(g_vs20_standardvs),
     41     sizeof(g_vs20_flipyvs),
     42     sizeof(g_ps20_passthroughps),
     43     sizeof(g_ps20_luminanceps),
     44     sizeof(g_ps20_componentmaskps)
     45 };
     46 }
     47 
     48 namespace rx
     49 {
     50 Blit9::Blit9(rx::Renderer9 *renderer)
     51   : mRenderer(renderer), mQuadVertexBuffer(NULL), mQuadVertexDeclaration(NULL), mSavedStateBlock(NULL), mSavedRenderTarget(NULL), mSavedDepthStencil(NULL)
     52 {
     53     initGeometry();
     54     memset(mCompiledShaders, 0, sizeof(mCompiledShaders));
     55 }
     56 
     57 Blit9::~Blit9()
     58 {
     59     SafeRelease(mSavedStateBlock);
     60     SafeRelease(mQuadVertexBuffer);
     61     SafeRelease(mQuadVertexDeclaration);
     62 
     63     for (int i = 0; i < SHADER_COUNT; i++)
     64     {
     65         SafeRelease(mCompiledShaders[i]);
     66     }
     67 }
     68 
     69 void Blit9::initGeometry()
     70 {
     71     static const float quad[] =
     72     {
     73         -1, -1,
     74         -1,  1,
     75          1, -1,
     76          1,  1
     77     };
     78 
     79     IDirect3DDevice9 *device = mRenderer->getDevice();
     80 
     81     HRESULT result = device->CreateVertexBuffer(sizeof(quad), D3DUSAGE_WRITEONLY, 0, D3DPOOL_DEFAULT, &mQuadVertexBuffer, NULL);
     82 
     83     if (FAILED(result))
     84     {
     85         ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
     86         return gl::error(GL_OUT_OF_MEMORY);
     87     }
     88 
     89     void *lockPtr = NULL;
     90     result = mQuadVertexBuffer->Lock(0, 0, &lockPtr, 0);
     91 
     92     if (FAILED(result) || lockPtr == NULL)
     93     {
     94         ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
     95         return gl::error(GL_OUT_OF_MEMORY);
     96     }
     97 
     98     memcpy(lockPtr, quad, sizeof(quad));
     99     mQuadVertexBuffer->Unlock();
    100 
    101     static const D3DVERTEXELEMENT9 elements[] =
    102     {
    103         { 0, 0, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0 },
    104         D3DDECL_END()
    105     };
    106 
    107     result = device->CreateVertexDeclaration(elements, &mQuadVertexDeclaration);
    108 
    109     if (FAILED(result))
    110     {
    111         ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
    112         return gl::error(GL_OUT_OF_MEMORY);
    113     }
    114 }
    115 
    116 template <class D3DShaderType>
    117 bool Blit9::setShader(ShaderId source, const char *profile,
    118                      D3DShaderType *(rx::Renderer9::*createShader)(const DWORD *, size_t length),
    119                      HRESULT (WINAPI IDirect3DDevice9::*setShader)(D3DShaderType*))
    120 {
    121     IDirect3DDevice9 *device = mRenderer->getDevice();
    122 
    123     D3DShaderType *shader;
    124 
    125     if (mCompiledShaders[source] != NULL)
    126     {
    127         shader = static_cast<D3DShaderType*>(mCompiledShaders[source]);
    128     }
    129     else
    130     {
    131         const BYTE* shaderCode = g_shaderCode[source];
    132         size_t shaderSize = g_shaderSize[source];
    133 
    134         shader = (mRenderer->*createShader)(reinterpret_cast<const DWORD*>(shaderCode), shaderSize);
    135         if (!shader)
    136         {
    137             ERR("Failed to create shader for blit operation");
    138             return false;
    139         }
    140 
    141         mCompiledShaders[source] = shader;
    142     }
    143 
    144     HRESULT hr = (device->*setShader)(shader);
    145 
    146     if (FAILED(hr))
    147     {
    148         ERR("Failed to set shader for blit operation");
    149         return false;
    150     }
    151 
    152     return true;
    153 }
    154 
    155 bool Blit9::setVertexShader(ShaderId shader)
    156 {
    157     return setShader<IDirect3DVertexShader9>(shader, "vs_2_0", &rx::Renderer9::createVertexShader, &IDirect3DDevice9::SetVertexShader);
    158 }
    159 
    160 bool Blit9::setPixelShader(ShaderId shader)
    161 {
    162     return setShader<IDirect3DPixelShader9>(shader, "ps_2_0", &rx::Renderer9::createPixelShader, &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 bool Blit9::boxFilter(IDirect3DSurface9 *source, IDirect3DSurface9 *dest)
    180 {
    181     IDirect3DTexture9 *texture = copySurfaceToTexture(source, getSurfaceRect(source));
    182     if (!texture)
    183     {
    184         return false;
    185     }
    186 
    187     IDirect3DDevice9 *device = mRenderer->getDevice();
    188 
    189     saveState();
    190 
    191     device->SetTexture(0, texture);
    192     device->SetRenderTarget(0, dest);
    193 
    194     setVertexShader(SHADER_VS_STANDARD);
    195     setPixelShader(SHADER_PS_PASSTHROUGH);
    196 
    197     setCommonBlitState();
    198     device->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
    199     device->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
    200 
    201     setViewport(getSurfaceRect(dest), 0, 0);
    202 
    203     render();
    204 
    205     SafeRelease(texture);
    206 
    207     restoreState();
    208 
    209     return true;
    210 }
    211 
    212 bool Blit9::copy(gl::Framebuffer *framebuffer, const RECT &sourceRect, GLenum destFormat, GLint xoffset, GLint yoffset, TextureStorageInterface2D *storage, GLint level)
    213 {
    214     RenderTarget9 *renderTarget = NULL;
    215     IDirect3DSurface9 *source = NULL;
    216     gl::FramebufferAttachment *colorbuffer = framebuffer->getColorbuffer(0);
    217 
    218     if (colorbuffer)
    219     {
    220         renderTarget = RenderTarget9::makeRenderTarget9(colorbuffer->getRenderTarget());
    221     }
    222 
    223     if (renderTarget)
    224     {
    225         source = renderTarget->getSurface();
    226     }
    227 
    228     if (!source)
    229     {
    230         ERR("Failed to retrieve the render target.");
    231         return gl::error(GL_OUT_OF_MEMORY, false);
    232     }
    233 
    234     TextureStorage9_2D *storage9 = TextureStorage9_2D::makeTextureStorage9_2D(storage->getStorageInstance());
    235     IDirect3DSurface9 *destSurface = storage9->getSurfaceLevel(level, true);
    236     bool result = false;
    237 
    238     if (destSurface)
    239     {
    240         result = copy(source, sourceRect, destFormat, xoffset, yoffset, destSurface);
    241         SafeRelease(destSurface);
    242     }
    243 
    244     SafeRelease(source);
    245     return result;
    246 }
    247 
    248 bool Blit9::copy(gl::Framebuffer *framebuffer, const RECT &sourceRect, GLenum destFormat, GLint xoffset, GLint yoffset, TextureStorageInterfaceCube *storage, GLenum target, GLint level)
    249 {
    250     RenderTarget9 *renderTarget = NULL;
    251     IDirect3DSurface9 *source = NULL;
    252     gl::FramebufferAttachment *colorbuffer = framebuffer->getColorbuffer(0);
    253 
    254     if (colorbuffer)
    255     {
    256         renderTarget = RenderTarget9::makeRenderTarget9(colorbuffer->getRenderTarget());
    257     }
    258 
    259     if (renderTarget)
    260     {
    261         source = renderTarget->getSurface();
    262     }
    263 
    264     if (!source)
    265     {
    266         ERR("Failed to retrieve the render target.");
    267         return gl::error(GL_OUT_OF_MEMORY, false);
    268     }
    269 
    270     TextureStorage9_Cube *storage9 = TextureStorage9_Cube::makeTextureStorage9_Cube(storage->getStorageInstance());
    271     IDirect3DSurface9 *destSurface = storage9->getCubeMapSurface(target, level, true);
    272     bool result = false;
    273 
    274     if (destSurface)
    275     {
    276         result = copy(source, sourceRect, destFormat, xoffset, yoffset, destSurface);
    277         SafeRelease(destSurface);
    278     }
    279 
    280     SafeRelease(source);
    281     return result;
    282 }
    283 
    284 bool Blit9::copy(IDirect3DSurface9 *source, const RECT &sourceRect, GLenum destFormat, GLint xoffset, GLint yoffset, IDirect3DSurface9 *dest)
    285 {
    286     if (!dest)
    287     {
    288         return false;
    289     }
    290 
    291     IDirect3DDevice9 *device = mRenderer->getDevice();
    292 
    293     D3DSURFACE_DESC sourceDesc;
    294     D3DSURFACE_DESC destDesc;
    295     source->GetDesc(&sourceDesc);
    296     dest->GetDesc(&destDesc);
    297 
    298     if (sourceDesc.Format == destDesc.Format && destDesc.Usage & D3DUSAGE_RENDERTARGET &&
    299         d3d9_gl::IsFormatChannelEquivalent(destDesc.Format, destFormat, mRenderer->getCurrentClientVersion()))   // Can use StretchRect
    300     {
    301         RECT destRect = {xoffset, yoffset, xoffset + (sourceRect.right - sourceRect.left), yoffset + (sourceRect.bottom - sourceRect.top)};
    302         HRESULT result = device->StretchRect(source, &sourceRect, dest, &destRect, D3DTEXF_POINT);
    303 
    304         if (FAILED(result))
    305         {
    306             ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
    307             return gl::error(GL_OUT_OF_MEMORY, false);
    308         }
    309     }
    310     else
    311     {
    312         return formatConvert(source, sourceRect, destFormat, xoffset, yoffset, dest);
    313     }
    314     return true;
    315 }
    316 
    317 bool Blit9::formatConvert(IDirect3DSurface9 *source, const RECT &sourceRect, GLenum destFormat, GLint xoffset, GLint yoffset, IDirect3DSurface9 *dest)
    318 {
    319     IDirect3DTexture9 *texture = copySurfaceToTexture(source, sourceRect);
    320     if (!texture)
    321     {
    322         return false;
    323     }
    324 
    325     IDirect3DDevice9 *device = mRenderer->getDevice();
    326 
    327     saveState();
    328 
    329     device->SetTexture(0, texture);
    330     device->SetRenderTarget(0, dest);
    331 
    332     setViewport(sourceRect, xoffset, yoffset);
    333 
    334     setCommonBlitState();
    335     if (setFormatConvertShaders(destFormat))
    336     {
    337         render();
    338     }
    339 
    340     SafeRelease(texture);
    341 
    342     restoreState();
    343 
    344     return true;
    345 }
    346 
    347 bool Blit9::setFormatConvertShaders(GLenum destFormat)
    348 {
    349     bool okay = setVertexShader(SHADER_VS_STANDARD);
    350 
    351     switch (destFormat)
    352     {
    353       default: UNREACHABLE();
    354       case GL_RGBA:
    355       case GL_BGRA_EXT:
    356       case GL_RGB:
    357       case GL_RG_EXT:
    358       case GL_RED_EXT:
    359       case GL_ALPHA:
    360         okay = okay && setPixelShader(SHADER_PS_COMPONENTMASK);
    361         break;
    362 
    363       case GL_LUMINANCE:
    364       case GL_LUMINANCE_ALPHA:
    365         okay = okay && setPixelShader(SHADER_PS_LUMINANCE);
    366         break;
    367     }
    368 
    369     if (!okay)
    370     {
    371         return false;
    372     }
    373 
    374     enum { X = 0, Y = 1, Z = 2, W = 3 };
    375 
    376     // The meaning of this constant depends on the shader that was selected.
    377     // See the shader assembly code above for details.
    378     // Allocate one array for both registers and split it into two float4's.
    379     float psConst[8] = { 0 };
    380     float *multConst = &psConst[0];
    381     float *addConst = &psConst[4];
    382 
    383     switch (destFormat)
    384     {
    385       default: UNREACHABLE();
    386       case GL_RGBA:
    387       case GL_BGRA_EXT:
    388         multConst[X] = 1;
    389         multConst[Y] = 1;
    390         multConst[Z] = 1;
    391         multConst[W] = 1;
    392         addConst[X] = 0;
    393         addConst[Y] = 0;
    394         addConst[Z] = 0;
    395         addConst[W] = 0;
    396         break;
    397 
    398       case GL_RGB:
    399         multConst[X] = 1;
    400         multConst[Y] = 1;
    401         multConst[Z] = 1;
    402         multConst[W] = 0;
    403         addConst[X] = 0;
    404         addConst[Y] = 0;
    405         addConst[Z] = 0;
    406         addConst[W] = 1;
    407         break;
    408 
    409       case GL_RG_EXT:
    410         multConst[X] = 1;
    411         multConst[Y] = 1;
    412         multConst[Z] = 0;
    413         multConst[W] = 0;
    414         addConst[X] = 0;
    415         addConst[Y] = 0;
    416         addConst[Z] = 0;
    417         addConst[W] = 1;
    418         break;
    419 
    420       case GL_RED_EXT:
    421         multConst[X] = 1;
    422         multConst[Y] = 0;
    423         multConst[Z] = 0;
    424         multConst[W] = 0;
    425         addConst[X] = 0;
    426         addConst[Y] = 0;
    427         addConst[Z] = 0;
    428         addConst[W] = 1;
    429         break;
    430 
    431       case GL_ALPHA:
    432         multConst[X] = 0;
    433         multConst[Y] = 0;
    434         multConst[Z] = 0;
    435         multConst[W] = 1;
    436         addConst[X] = 0;
    437         addConst[Y] = 0;
    438         addConst[Z] = 0;
    439         addConst[W] = 0;
    440         break;
    441 
    442       case GL_LUMINANCE:
    443         multConst[X] = 1;
    444         multConst[Y] = 0;
    445         multConst[Z] = 0;
    446         multConst[W] = 0;
    447         addConst[X] = 0;
    448         addConst[Y] = 0;
    449         addConst[Z] = 0;
    450         addConst[W] = 1;
    451         break;
    452 
    453       case GL_LUMINANCE_ALPHA:
    454         multConst[X] = 1;
    455         multConst[Y] = 0;
    456         multConst[Z] = 0;
    457         multConst[W] = 1;
    458         addConst[X] = 0;
    459         addConst[Y] = 0;
    460         addConst[Z] = 0;
    461         addConst[W] = 0;
    462         break;
    463     }
    464 
    465     mRenderer->getDevice()->SetPixelShaderConstantF(0, psConst, 2);
    466 
    467     return true;
    468 }
    469 
    470 IDirect3DTexture9 *Blit9::copySurfaceToTexture(IDirect3DSurface9 *surface, const RECT &sourceRect)
    471 {
    472     if (!surface)
    473     {
    474         return NULL;
    475     }
    476 
    477     IDirect3DDevice9 *device = mRenderer->getDevice();
    478 
    479     D3DSURFACE_DESC sourceDesc;
    480     surface->GetDesc(&sourceDesc);
    481 
    482     // Copy the render target into a texture
    483     IDirect3DTexture9 *texture;
    484     HRESULT result = device->CreateTexture(sourceRect.right - sourceRect.left, sourceRect.bottom - sourceRect.top, 1, D3DUSAGE_RENDERTARGET, sourceDesc.Format, D3DPOOL_DEFAULT, &texture, NULL);
    485 
    486     if (FAILED(result))
    487     {
    488         ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
    489         return gl::error(GL_OUT_OF_MEMORY, (IDirect3DTexture9*)NULL);
    490     }
    491 
    492     IDirect3DSurface9 *textureSurface;
    493     result = texture->GetSurfaceLevel(0, &textureSurface);
    494 
    495     if (FAILED(result))
    496     {
    497         ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
    498         SafeRelease(texture);
    499         return gl::error(GL_OUT_OF_MEMORY, (IDirect3DTexture9*)NULL);
    500     }
    501 
    502     mRenderer->endScene();
    503     result = device->StretchRect(surface, &sourceRect, textureSurface, NULL, D3DTEXF_NONE);
    504 
    505     SafeRelease(textureSurface);
    506 
    507     if (FAILED(result))
    508     {
    509         ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
    510         SafeRelease(texture);
    511         return gl::error(GL_OUT_OF_MEMORY, (IDirect3DTexture9*)NULL);
    512     }
    513 
    514     return texture;
    515 }
    516 
    517 void Blit9::setViewport(const RECT &sourceRect, GLint xoffset, GLint yoffset)
    518 {
    519     IDirect3DDevice9 *device = mRenderer->getDevice();
    520 
    521     D3DVIEWPORT9 vp;
    522     vp.X      = xoffset;
    523     vp.Y      = yoffset;
    524     vp.Width  = sourceRect.right - sourceRect.left;
    525     vp.Height = sourceRect.bottom - sourceRect.top;
    526     vp.MinZ   = 0.0f;
    527     vp.MaxZ   = 1.0f;
    528     device->SetViewport(&vp);
    529 
    530     float halfPixelAdjust[4] = { -1.0f/vp.Width, 1.0f/vp.Height, 0, 0 };
    531     device->SetVertexShaderConstantF(0, halfPixelAdjust, 1);
    532 }
    533 
    534 void Blit9::setCommonBlitState()
    535 {
    536     IDirect3DDevice9 *device = mRenderer->getDevice();
    537 
    538     device->SetDepthStencilSurface(NULL);
    539 
    540     device->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID);
    541     device->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE);
    542     device->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
    543     device->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
    544     device->SetRenderState(D3DRS_CLIPPLANEENABLE, 0);
    545     device->SetRenderState(D3DRS_COLORWRITEENABLE, D3DCOLORWRITEENABLE_ALPHA | D3DCOLORWRITEENABLE_BLUE | D3DCOLORWRITEENABLE_GREEN | D3DCOLORWRITEENABLE_RED);
    546     device->SetRenderState(D3DRS_SRGBWRITEENABLE, FALSE);
    547     device->SetRenderState(D3DRS_SCISSORTESTENABLE, FALSE);
    548 
    549     device->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_POINT);
    550     device->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_POINT);
    551     device->SetSamplerState(0, D3DSAMP_SRGBTEXTURE, FALSE);
    552     device->SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP);
    553     device->SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP);
    554 
    555     RECT scissorRect = {0};   // Scissoring is disabled for flipping, but we need this to capture and restore the old rectangle
    556     device->SetScissorRect(&scissorRect);
    557 
    558     for(int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++)
    559     {
    560         device->SetStreamSourceFreq(i, 1);
    561     }
    562 }
    563 
    564 void Blit9::render()
    565 {
    566     IDirect3DDevice9 *device = mRenderer->getDevice();
    567 
    568     HRESULT hr = device->SetStreamSource(0, mQuadVertexBuffer, 0, 2 * sizeof(float));
    569     hr = device->SetVertexDeclaration(mQuadVertexDeclaration);
    570 
    571     mRenderer->startScene();
    572     hr = device->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2);
    573 }
    574 
    575 void Blit9::saveState()
    576 {
    577     IDirect3DDevice9 *device = mRenderer->getDevice();
    578 
    579     HRESULT hr;
    580 
    581     device->GetDepthStencilSurface(&mSavedDepthStencil);
    582     device->GetRenderTarget(0, &mSavedRenderTarget);
    583 
    584     if (mSavedStateBlock == NULL)
    585     {
    586         hr = device->BeginStateBlock();
    587         ASSERT(SUCCEEDED(hr) || hr == D3DERR_OUTOFVIDEOMEMORY || hr == E_OUTOFMEMORY);
    588 
    589         setCommonBlitState();
    590 
    591         static const float dummyConst[8] = { 0 };
    592 
    593         device->SetVertexShader(NULL);
    594         device->SetVertexShaderConstantF(0, dummyConst, 2);
    595         device->SetPixelShader(NULL);
    596         device->SetPixelShaderConstantF(0, dummyConst, 2);
    597 
    598         D3DVIEWPORT9 dummyVp;
    599         dummyVp.X = 0;
    600         dummyVp.Y = 0;
    601         dummyVp.Width = 1;
    602         dummyVp.Height = 1;
    603         dummyVp.MinZ = 0;
    604         dummyVp.MaxZ = 1;
    605 
    606         device->SetViewport(&dummyVp);
    607 
    608         device->SetTexture(0, NULL);
    609 
    610         device->SetStreamSource(0, mQuadVertexBuffer, 0, 0);
    611 
    612         device->SetVertexDeclaration(mQuadVertexDeclaration);
    613 
    614         hr = device->EndStateBlock(&mSavedStateBlock);
    615         ASSERT(SUCCEEDED(hr) || hr == D3DERR_OUTOFVIDEOMEMORY || hr == E_OUTOFMEMORY);
    616     }
    617 
    618     ASSERT(mSavedStateBlock != NULL);
    619 
    620     if (mSavedStateBlock != NULL)
    621     {
    622         hr = mSavedStateBlock->Capture();
    623         ASSERT(SUCCEEDED(hr));
    624     }
    625 }
    626 
    627 void Blit9::restoreState()
    628 {
    629     IDirect3DDevice9 *device = mRenderer->getDevice();
    630 
    631     device->SetDepthStencilSurface(mSavedDepthStencil);
    632     SafeRelease(mSavedDepthStencil);
    633 
    634     device->SetRenderTarget(0, mSavedRenderTarget);
    635     SafeRelease(mSavedRenderTarget);
    636 
    637     ASSERT(mSavedStateBlock != NULL);
    638 
    639     if (mSavedStateBlock != NULL)
    640     {
    641         mSavedStateBlock->Apply();
    642     }
    643 }
    644 
    645 }
    646