blob: e48430040e24c72a41beccd17371b7882c7d0485 [file] [log] [blame]
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +00001//
2// Copyright (c) 2002-2010 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// Blit.cpp: Surface copy utility class.
8
daniel@transgaming.combbf56f72010-04-20 18:52:13 +00009#include "libGLESv2/Blit.h"
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +000010
11#include <d3dx9.h>
12
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +000013#include "common/debug.h"
14
daniel@transgaming.combbf56f72010-04-20 18:52:13 +000015#include "libGLESv2/main.h"
16
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +000017namespace
18{
19// Standard Vertex Shader
20// Input 0 is the homogenous position.
21// Outputs the homogenous position as-is.
22// Outputs a tex coord with (0,0) in the upper-left corner of the screen and (1,1) in the bottom right.
23// C0.X must be negative half-pixel width, C0.Y must be half-pixel height. C0.ZW must be 0.
24const char standardvs[] =
25"struct VS_OUTPUT\n"
26"{\n"
27" float4 position : POSITION;\n"
28" float4 texcoord : TEXCOORD0;\n"
29"};\n"
30"\n"
31"uniform float4 halfPixelSize : c0;\n"
32"\n"
33"VS_OUTPUT main(in float4 position : POSITION)\n"
34"{\n"
35" VS_OUTPUT Out;\n"
36"\n"
37" Out.position = position + halfPixelSize;\n"
38" Out.texcoord = position * float4(0.5, -0.5, 1.0, 1.0) + float4(0.5, 0.5, 0, 0);\n"
39"\n"
40" return Out;\n"
41"}\n";
42
43// Flip Y Vertex Shader
44// Input 0 is the homogenous position.
45// Outputs the homogenous position as-is.
46// Outputs a tex coord with (0,1) in the upper-left corner of the screen and (1,0) in the bottom right.
47// C0.XY must be the half-pixel width and height. C0.ZW must be 0.
48const char flipyvs[] =
49"struct VS_OUTPUT\n"
50"{\n"
51" float4 position : POSITION;\n"
52" float4 texcoord : TEXCOORD0;\n"
53"};\n"
54"\n"
55"uniform float4 halfPixelSize : c0;\n"
56"\n"
57"VS_OUTPUT main(in float4 position : POSITION)\n"
58"{\n"
59" VS_OUTPUT Out;\n"
60"\n"
61" Out.position = position + halfPixelSize;\n"
62" Out.texcoord = position * float4(0.5, 0.5, 1.0, 1.0) + float4(0.5, 0.5, 0, 0);\n"
63"\n"
64" return Out;\n"
65"}\n";
66
67// Passthrough Pixel Shader
68// Outputs texture 0 sampled at texcoord 0.
69const char passthroughps[] =
70"sampler2D tex : s0;\n"
71"\n"
72"float4 main(float4 texcoord : TEXCOORD0) : COLOR\n"
73"{\n"
74" return tex2D(tex, texcoord.xy);\n"
75"}\n";
76
77// Luminance Conversion Pixel Shader
78// Outputs sample(tex0, tc0).rrra.
79// For LA output (pass A) set C0.X = 1, C0.Y = 0.
80// For L output (A = 1) set C0.X = 0, C0.Y = 1.
81const char luminanceps[] =
82"sampler2D tex : s0;\n"
83"\n"
84"uniform float4 mode : c0;\n"
85"\n"
86"float4 main(float4 texcoord : TEXCOORD0) : COLOR\n"
87"{\n"
88" float4 tmp = tex2D(tex, texcoord.xy);\n"
89" tmp.w = tmp.w * mode.x + mode.y;\n"
90" return tmp.xxxw;\n"
91"}\n";
92
93// RGB/A Component Mask Pixel Shader
94// Outputs sample(tex0, tc0) with options to force RGB = 0 and/or A = 1.
95// To force RGB = 0, set C0.X = 0, otherwise C0.X = 1.
96// To force A = 1, set C0.Z = 0, C0.W = 1, otherwise C0.Z = 1, C0.W = 0.
97const char componentmaskps[] =
98"sampler2D tex : s0;\n"
99"\n"
100"uniform float4 mode : c0;\n"
101"\n"
102"float4 main(float4 texcoord : TEXCOORD0) : COLOR\n"
103"{\n"
104" float4 tmp = tex2D(tex, texcoord.xy);\n"
105" tmp.xyz = tmp.xyz * mode.x;\n"
106" tmp.w = tmp.w * mode.z + mode.w;\n"
107" return tmp;\n"
108"}\n";
109
110}
111
112namespace gl
113{
114
115const char * const Blit::mShaderSource[] =
116{
117 standardvs,
118 flipyvs,
119 passthroughps,
120 luminanceps,
121 componentmaskps
122};
123
124Blit::Blit(Context *context)
daniel@transgaming.com1ddd1dd2010-05-11 02:29:34 +0000125 : mContext(context), mQuadVertexBuffer(NULL), mQuadVertexDeclaration(NULL), mSavedRenderTarget(NULL), mSavedDepthStencil(NULL), mSavedStateBlock(NULL)
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000126{
127 initGeometry();
128 memset(mCompiledShaders, 0, sizeof(mCompiledShaders));
129}
130
131Blit::~Blit()
132{
daniel@transgaming.com1ddd1dd2010-05-11 02:29:34 +0000133 if (mSavedStateBlock) mSavedStateBlock->Release();
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000134 if (mQuadVertexBuffer) mQuadVertexBuffer->Release();
135 if (mQuadVertexDeclaration) mQuadVertexDeclaration->Release();
136
137 for (int i = 0; i < SHADER_COUNT; i++)
138 {
139 if (mCompiledShaders[i])
140 {
141 mCompiledShaders[i]->Release();
142 }
143 }
144}
145
146void Blit::initGeometry()
147{
148 static const float quad[] =
149 {
150 -1, -1,
151 -1, 1,
152 1, -1,
153 1, 1
154 };
155
156 IDirect3DDevice9 *device = getDevice();
157
daniel@transgaming.comaa614602011-04-28 16:20:58 +0000158 HRESULT result = device->CreateVertexBuffer(sizeof(quad), D3DUSAGE_WRITEONLY, 0, D3DPOOL_DEFAULT, &mQuadVertexBuffer, NULL);
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000159
daniel@transgaming.comaa614602011-04-28 16:20:58 +0000160 if (FAILED(result))
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000161 {
daniel@transgaming.comaa614602011-04-28 16:20:58 +0000162 ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000163 return error(GL_OUT_OF_MEMORY);
164 }
165
daniel@transgaming.comaa614602011-04-28 16:20:58 +0000166 void *lockPtr = NULL;
167 result = mQuadVertexBuffer->Lock(0, 0, &lockPtr, 0);
168
169 if (FAILED(result) || lockPtr == NULL)
170 {
171 ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
172 return error(GL_OUT_OF_MEMORY);
173 }
174
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000175 memcpy(lockPtr, quad, sizeof(quad));
176 mQuadVertexBuffer->Unlock();
177
178 static const D3DVERTEXELEMENT9 elements[] =
179 {
180 { 0, 0, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0 },
181 D3DDECL_END()
182 };
183
daniel@transgaming.comaa614602011-04-28 16:20:58 +0000184 result = device->CreateVertexDeclaration(elements, &mQuadVertexDeclaration);
185
186 if (FAILED(result))
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000187 {
daniel@transgaming.comaa614602011-04-28 16:20:58 +0000188 ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000189 return error(GL_OUT_OF_MEMORY);
190 }
191}
192
193template <class D3DShaderType>
194bool Blit::setShader(ShaderId source, const char *profile,
apatrick@chromium.org3cfd7222012-07-13 22:36:58 +0000195 D3DShaderType *(egl::Display::*createShader)(const DWORD *, size_t length),
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000196 HRESULT (WINAPI IDirect3DDevice9::*setShader)(D3DShaderType*))
197{
apatrick@chromium.org3cfd7222012-07-13 22:36:58 +0000198 egl::Display *display = getDisplay();
199 IDirect3DDevice9 *device = display->getDevice();
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000200
201 D3DShaderType *shader;
202
203 if (mCompiledShaders[source] != NULL)
204 {
205 shader = static_cast<D3DShaderType*>(mCompiledShaders[source]);
206 }
207 else
208 {
apatrick@chromium.org3cfd7222012-07-13 22:36:58 +0000209 // FIXME: Complile these shaders offline and embed the byte code in the module.
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000210 ID3DXBuffer *shaderCode;
211 HRESULT hr = D3DXCompileShader(mShaderSource[source], strlen(mShaderSource[source]), NULL, NULL, "main", profile, 0, &shaderCode, NULL, NULL);
212
213 if (FAILED(hr))
214 {
215 ERR("Failed to compile %s shader for blit operation %d, error 0x%08X.", profile, (int)source, hr);
216 return false;
217 }
218
apatrick@chromium.org3cfd7222012-07-13 22:36:58 +0000219 shader = (display->*createShader)(static_cast<const DWORD*>(shaderCode->GetBufferPointer()), shaderCode->GetBufferSize());
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000220 if (FAILED(hr))
221 {
222 shaderCode->Release();
223 ERR("Failed to create %s shader for blit operation %d, error 0x%08X.", profile, (int)source, hr);
224 return false;
225 }
226
227 shaderCode->Release();
228
229 mCompiledShaders[source] = shader;
230 }
231
232 HRESULT hr = (device->*setShader)(shader);
233
234 if (FAILED(hr))
235 {
236 ERR("Failed to set %s shader for blit operation %d, error 0x%08X.", profile, (int)source, hr);
237 return false;
238 }
239
240 return true;
241}
242
243bool Blit::setVertexShader(ShaderId shader)
244{
apatrick@chromium.org3cfd7222012-07-13 22:36:58 +0000245 return setShader<IDirect3DVertexShader9>(shader, mContext->supportsShaderModel3() ? "vs_3_0" : "vs_2_0", &egl::Display::createVertexShader, &IDirect3DDevice9::SetVertexShader);
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000246}
247
248bool Blit::setPixelShader(ShaderId shader)
249{
apatrick@chromium.org3cfd7222012-07-13 22:36:58 +0000250 return setShader<IDirect3DPixelShader9>(shader, mContext->supportsShaderModel3() ? "ps_3_0" : "ps_2_0", &egl::Display::createPixelShader, &IDirect3DDevice9::SetPixelShader);
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000251}
252
daniel@transgaming.com8fd99e22010-04-20 18:52:00 +0000253RECT Blit::getSurfaceRect(IDirect3DSurface9 *surface) const
254{
255 D3DSURFACE_DESC desc;
256 surface->GetDesc(&desc);
257
258 RECT rect;
259 rect.left = 0;
260 rect.top = 0;
261 rect.right = desc.Width;
262 rect.bottom = desc.Height;
263
264 return rect;
265}
266
267bool Blit::boxFilter(IDirect3DSurface9 *source, IDirect3DSurface9 *dest)
268{
269 IDirect3DTexture9 *texture = copySurfaceToTexture(source, getSurfaceRect(source));
270 if (!texture)
271 {
272 return false;
273 }
274
275 IDirect3DDevice9 *device = getDevice();
daniel@transgaming.com1ddd1dd2010-05-11 02:29:34 +0000276
277 saveState();
278
daniel@transgaming.com8fd99e22010-04-20 18:52:00 +0000279 device->SetTexture(0, texture);
280 device->SetRenderTarget(0, dest);
281
282 setVertexShader(SHADER_VS_STANDARD);
283 setPixelShader(SHADER_PS_PASSTHROUGH);
284
285 setCommonBlitState();
286 device->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
287 device->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
288
289 setViewport(getSurfaceRect(dest), 0, 0);
290
291 render();
292
293 texture->Release();
294
daniel@transgaming.com1ddd1dd2010-05-11 02:29:34 +0000295 restoreState();
296
daniel@transgaming.com8fd99e22010-04-20 18:52:00 +0000297 return true;
298}
299
daniel@transgaming.comeef864a2011-04-22 11:33:27 +0000300bool Blit::copy(IDirect3DSurface9 *source, const RECT &sourceRect, GLenum destFormat, GLint xoffset, GLint yoffset, IDirect3DSurface9 *dest)
301{
302 IDirect3DDevice9 *device = getDevice();
303
304 D3DSURFACE_DESC sourceDesc;
305 D3DSURFACE_DESC destDesc;
306 source->GetDesc(&sourceDesc);
307 dest->GetDesc(&destDesc);
308
309 if (sourceDesc.Format == destDesc.Format && destDesc.Usage & D3DUSAGE_RENDERTARGET) // Can use StretchRect
310 {
311 RECT destRect = {xoffset, yoffset, xoffset + (sourceRect.right - sourceRect.left), yoffset + (sourceRect.bottom - sourceRect.top)};
312 HRESULT result = device->StretchRect(source, &sourceRect, dest, &destRect, D3DTEXF_POINT);
313
314 if (FAILED(result))
315 {
316 ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
317 return error(GL_OUT_OF_MEMORY, false);
318 }
319 }
320 else
321 {
322 return formatConvert(source, sourceRect, destFormat, xoffset, yoffset, dest);
323 }
324
325 return true;
326}
327
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000328bool Blit::formatConvert(IDirect3DSurface9 *source, const RECT &sourceRect, GLenum destFormat, GLint xoffset, GLint yoffset, IDirect3DSurface9 *dest)
329{
330 IDirect3DTexture9 *texture = copySurfaceToTexture(source, sourceRect);
331 if (!texture)
332 {
333 return false;
334 }
335
336 IDirect3DDevice9 *device = getDevice();
337
daniel@transgaming.com1ddd1dd2010-05-11 02:29:34 +0000338 saveState();
339
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000340 device->SetTexture(0, texture);
341 device->SetRenderTarget(0, dest);
342
daniel@transgaming.com8fd99e22010-04-20 18:52:00 +0000343 setViewport(sourceRect, xoffset, yoffset);
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000344
345 setCommonBlitState();
346 if (setFormatConvertShaders(destFormat))
347 {
348 render();
349 }
350
351 texture->Release();
352
daniel@transgaming.com1ddd1dd2010-05-11 02:29:34 +0000353 restoreState();
354
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000355 return true;
356}
357
358bool Blit::setFormatConvertShaders(GLenum destFormat)
359{
360 bool okay = setVertexShader(SHADER_VS_STANDARD);
361
362 switch (destFormat)
363 {
364 default: UNREACHABLE();
365 case GL_RGBA:
daniel@transgaming.coma9198d92010-08-08 04:49:56 +0000366 case GL_BGRA_EXT:
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000367 case GL_RGB:
368 case GL_ALPHA:
369 okay = okay && setPixelShader(SHADER_PS_COMPONENTMASK);
370 break;
371
372 case GL_LUMINANCE:
373 case GL_LUMINANCE_ALPHA:
374 okay = okay && setPixelShader(SHADER_PS_LUMINANCE);
375 break;
376 }
377
378 if (!okay)
379 {
380 return false;
381 }
382
383 enum { X = 0, Y = 1, Z = 2, W = 3 };
384
385 // The meaning of this constant depends on the shader that was selected.
386 // See the shader assembly code above for details.
387 float psConst0[4] = { 0, 0, 0, 0 };
388
389 switch (destFormat)
390 {
391 default: UNREACHABLE();
392 case GL_RGBA:
daniel@transgaming.coma9198d92010-08-08 04:49:56 +0000393 case GL_BGRA_EXT:
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000394 psConst0[X] = 1;
395 psConst0[Z] = 1;
396 break;
397
398 case GL_RGB:
399 psConst0[X] = 1;
400 psConst0[W] = 1;
401 break;
402
403 case GL_ALPHA:
404 psConst0[Z] = 1;
405 break;
406
407 case GL_LUMINANCE:
408 psConst0[Y] = 1;
409 break;
410
411 case GL_LUMINANCE_ALPHA:
412 psConst0[X] = 1;
413 break;
414 }
415
416 getDevice()->SetPixelShaderConstantF(0, psConst0, 1);
417
418 return true;
419}
420
421IDirect3DTexture9 *Blit::copySurfaceToTexture(IDirect3DSurface9 *surface, const RECT &sourceRect)
422{
daniel@transgaming.comd36c6a02010-08-31 12:15:09 +0000423 if (!surface)
424 {
425 return NULL;
426 }
427
daniel@transgaming.comae072af2010-05-05 18:47:28 +0000428 egl::Display *display = getDisplay();
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000429 IDirect3DDevice9 *device = getDevice();
430
431 D3DSURFACE_DESC sourceDesc;
432 surface->GetDesc(&sourceDesc);
433
434 // Copy the render target into a texture
435 IDirect3DTexture9 *texture;
daniel@transgaming.com8fd99e22010-04-20 18:52:00 +0000436 HRESULT result = device->CreateTexture(sourceRect.right - sourceRect.left, sourceRect.bottom - sourceRect.top, 1, D3DUSAGE_RENDERTARGET, sourceDesc.Format, D3DPOOL_DEFAULT, &texture, NULL);
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000437
438 if (FAILED(result))
439 {
440 ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
441 return error(GL_OUT_OF_MEMORY, (IDirect3DTexture9*)NULL);
442 }
443
444 IDirect3DSurface9 *textureSurface;
445 result = texture->GetSurfaceLevel(0, &textureSurface);
446
447 if (FAILED(result))
448 {
449 ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
450 texture->Release();
451 return error(GL_OUT_OF_MEMORY, (IDirect3DTexture9*)NULL);
452 }
453
daniel@transgaming.comae072af2010-05-05 18:47:28 +0000454 display->endScene();
daniel@transgaming.com4c5142c2010-10-15 17:58:27 +0000455 result = device->StretchRect(surface, &sourceRect, textureSurface, NULL, D3DTEXF_NONE);
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000456
457 textureSurface->Release();
458
459 if (FAILED(result))
460 {
461 ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
462 texture->Release();
463 return error(GL_OUT_OF_MEMORY, (IDirect3DTexture9*)NULL);
464 }
465
466 return texture;
467}
468
daniel@transgaming.com8fd99e22010-04-20 18:52:00 +0000469void Blit::setViewport(const RECT &sourceRect, GLint xoffset, GLint yoffset)
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000470{
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000471 IDirect3DDevice9 *device = getDevice();
472
473 D3DVIEWPORT9 vp;
474 vp.X = xoffset;
475 vp.Y = yoffset;
476 vp.Width = sourceRect.right - sourceRect.left;
daniel@transgaming.com8fd99e22010-04-20 18:52:00 +0000477 vp.Height = sourceRect.bottom - sourceRect.top;
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000478 vp.MinZ = 0.0f;
479 vp.MaxZ = 1.0f;
480 device->SetViewport(&vp);
481
482 float halfPixelAdjust[4] = { -1.0f/vp.Width, 1.0f/vp.Height, 0, 0 };
483 device->SetVertexShaderConstantF(0, halfPixelAdjust, 1);
484}
485
486void Blit::setCommonBlitState()
487{
488 IDirect3DDevice9 *device = getDevice();
489
490 device->SetDepthStencilSurface(NULL);
491
492 device->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID);
493 device->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE);
494 device->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
495 device->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
496 device->SetRenderState(D3DRS_CLIPPLANEENABLE, 0);
497 device->SetRenderState(D3DRS_COLORWRITEENABLE, D3DCOLORWRITEENABLE_ALPHA | D3DCOLORWRITEENABLE_BLUE | D3DCOLORWRITEENABLE_GREEN | D3DCOLORWRITEENABLE_RED);
498 device->SetRenderState(D3DRS_SRGBWRITEENABLE, FALSE);
499 device->SetRenderState(D3DRS_SCISSORTESTENABLE, FALSE);
500
501 device->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_POINT);
502 device->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_POINT);
503 device->SetSamplerState(0, D3DSAMP_SRGBTEXTURE, FALSE);
daniel@transgaming.com8fd99e22010-04-20 18:52:00 +0000504 device->SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP);
505 device->SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP);
daniel@transgaming.com81655a72010-05-20 19:18:17 +0000506
daniel@transgaming.com74d760b2010-11-03 12:27:18 +0000507 RECT scissorRect = {0}; // Scissoring is disabled for flipping, but we need this to capture and restore the old rectangle
508 device->SetScissorRect(&scissorRect);
daniel@transgaming.com8ca9c6e2012-01-27 15:38:54 +0000509
510 for(int i = 0; i < MAX_VERTEX_ATTRIBS; i++)
511 {
512 device->SetStreamSourceFreq(i, 1);
513 }
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000514}
515
516void Blit::render()
517{
daniel@transgaming.comae072af2010-05-05 18:47:28 +0000518 egl::Display *display = getDisplay();
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000519 IDirect3DDevice9 *device = getDevice();
520
521 HRESULT hr = device->SetStreamSource(0, mQuadVertexBuffer, 0, 2 * sizeof(float));
522 hr = device->SetVertexDeclaration(mQuadVertexDeclaration);
523
daniel@transgaming.comae072af2010-05-05 18:47:28 +0000524 display->startScene();
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000525 hr = device->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2);
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000526}
527
daniel@transgaming.com1ddd1dd2010-05-11 02:29:34 +0000528void Blit::saveState()
529{
530 IDirect3DDevice9 *device = getDevice();
531
532 HRESULT hr;
533
534 device->GetDepthStencilSurface(&mSavedDepthStencil);
535 device->GetRenderTarget(0, &mSavedRenderTarget);
536
537 if (mSavedStateBlock == NULL)
538 {
539 hr = device->BeginStateBlock();
540 ASSERT(SUCCEEDED(hr) || hr == D3DERR_OUTOFVIDEOMEMORY || hr == E_OUTOFMEMORY);
541
542 setCommonBlitState();
543
544 static const float dummyConst[4] = { 0, 0, 0, 0 };
545
546 device->SetVertexShader(NULL);
547 device->SetVertexShaderConstantF(0, dummyConst, 1);
548 device->SetPixelShader(NULL);
549 device->SetPixelShaderConstantF(0, dummyConst, 1);
550
551 D3DVIEWPORT9 dummyVp;
552 dummyVp.X = 0;
553 dummyVp.Y = 0;
554 dummyVp.Width = 1;
555 dummyVp.Height = 1;
556 dummyVp.MinZ = 0;
557 dummyVp.MaxZ = 1;
558
559 device->SetViewport(&dummyVp);
560
561 device->SetTexture(0, NULL);
562
563 device->SetStreamSource(0, mQuadVertexBuffer, 0, 0);
564
565 device->SetVertexDeclaration(mQuadVertexDeclaration);
566
567 hr = device->EndStateBlock(&mSavedStateBlock);
568 ASSERT(SUCCEEDED(hr) || hr == D3DERR_OUTOFVIDEOMEMORY || hr == E_OUTOFMEMORY);
569 }
570
571 ASSERT(mSavedStateBlock != NULL);
572
573 if (mSavedStateBlock != NULL)
574 {
575 hr = mSavedStateBlock->Capture();
576 ASSERT(SUCCEEDED(hr));
577 }
578}
579
580void Blit::restoreState()
581{
582 IDirect3DDevice9 *device = getDevice();
583
584 device->SetDepthStencilSurface(mSavedDepthStencil);
585 if (mSavedDepthStencil != NULL)
586 {
587 mSavedDepthStencil->Release();
588 mSavedDepthStencil = NULL;
589 }
590
591 device->SetRenderTarget(0, mSavedRenderTarget);
592 if (mSavedRenderTarget != NULL)
593 {
594 mSavedRenderTarget->Release();
595 mSavedRenderTarget = NULL;
596 }
597
598 ASSERT(mSavedStateBlock != NULL);
599
600 if (mSavedStateBlock != NULL)
601 {
602 mSavedStateBlock->Apply();
603 }
604}
605
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000606}