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