blob: a53e6cfba7bd58006f88ee7526104196452faf29 [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
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +000011#include "common/debug.h"
12
daniel@transgaming.combbf56f72010-04-20 18:52:13 +000013#include "libGLESv2/main.h"
daniel@transgaming.comad52cb12012-10-17 18:14:45 +000014#include "libGLESv2/utilities.h"
daniel@transgaming.com3cef5392012-10-31 19:52:15 +000015#include "libGLESv2/Framebuffer.h"
daniel@transgaming.combbf56f72010-04-20 18:52:13 +000016
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +000017namespace
18{
apatrick@chromium.org99fbbe82012-07-19 19:11:24 +000019#include "libGLESv2/shaders/standardvs.h"
20#include "libGLESv2/shaders/flipyvs.h"
21#include "libGLESv2/shaders/passthroughps.h"
22#include "libGLESv2/shaders/luminanceps.h"
23#include "libGLESv2/shaders/componentmaskps.h"
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +000024
apatrick@chromium.org99fbbe82012-07-19 19:11:24 +000025const BYTE* const g_shaderCode[] =
26{
27 g_vs20_standardvs,
28 g_vs20_flipyvs,
29 g_ps20_passthroughps,
30 g_ps20_luminanceps,
31 g_ps20_componentmaskps
32};
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +000033
apatrick@chromium.org99fbbe82012-07-19 19:11:24 +000034const size_t g_shaderSize[] =
35{
36 sizeof(g_vs20_standardvs),
37 sizeof(g_vs20_flipyvs),
38 sizeof(g_ps20_passthroughps),
39 sizeof(g_ps20_luminanceps),
40 sizeof(g_ps20_componentmaskps)
41};
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +000042}
43
44namespace gl
45{
daniel@transgaming.com2507f412012-10-31 18:46:48 +000046Blit::Blit(renderer::Renderer9 *renderer)
daniel@transgaming.come4733d72012-10-31 18:07:01 +000047 : mRenderer(renderer), mQuadVertexBuffer(NULL), mQuadVertexDeclaration(NULL), mSavedRenderTarget(NULL), mSavedDepthStencil(NULL), mSavedStateBlock(NULL)
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +000048{
49 initGeometry();
50 memset(mCompiledShaders, 0, sizeof(mCompiledShaders));
51}
52
53Blit::~Blit()
54{
daniel@transgaming.com1ddd1dd2010-05-11 02:29:34 +000055 if (mSavedStateBlock) mSavedStateBlock->Release();
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +000056 if (mQuadVertexBuffer) mQuadVertexBuffer->Release();
57 if (mQuadVertexDeclaration) mQuadVertexDeclaration->Release();
58
59 for (int i = 0; i < SHADER_COUNT; i++)
60 {
61 if (mCompiledShaders[i])
62 {
63 mCompiledShaders[i]->Release();
64 }
65 }
66}
67
daniel@transgaming.com621ce052012-10-31 17:52:29 +000068// D3D9_REPLACE
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +000069void Blit::initGeometry()
70{
71 static const float quad[] =
72 {
73 -1, -1,
74 -1, 1,
75 1, -1,
76 1, 1
77 };
78
daniel@transgaming.come4733d72012-10-31 18:07:01 +000079 IDirect3DDevice9 *device = mRenderer->getDevice();
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +000080
daniel@transgaming.comaa614602011-04-28 16:20:58 +000081 HRESULT result = device->CreateVertexBuffer(sizeof(quad), D3DUSAGE_WRITEONLY, 0, D3DPOOL_DEFAULT, &mQuadVertexBuffer, NULL);
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +000082
daniel@transgaming.comaa614602011-04-28 16:20:58 +000083 if (FAILED(result))
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +000084 {
daniel@transgaming.comaa614602011-04-28 16:20:58 +000085 ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +000086 return error(GL_OUT_OF_MEMORY);
87 }
88
daniel@transgaming.comaa614602011-04-28 16:20:58 +000089 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 error(GL_OUT_OF_MEMORY);
96 }
97
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +000098 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
daniel@transgaming.comaa614602011-04-28 16:20:58 +0000107 result = device->CreateVertexDeclaration(elements, &mQuadVertexDeclaration);
108
109 if (FAILED(result))
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000110 {
daniel@transgaming.comaa614602011-04-28 16:20:58 +0000111 ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000112 return error(GL_OUT_OF_MEMORY);
113 }
114}
115
116template <class D3DShaderType>
117bool Blit::setShader(ShaderId source, const char *profile,
daniel@transgaming.com2507f412012-10-31 18:46:48 +0000118 D3DShaderType *(renderer::Renderer9::*createShader)(const DWORD *, size_t length),
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000119 HRESULT (WINAPI IDirect3DDevice9::*setShader)(D3DShaderType*))
120{
daniel@transgaming.come4733d72012-10-31 18:07:01 +0000121 IDirect3DDevice9 *device = mRenderer->getDevice(); // D3D9_REPLACE
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000122
123 D3DShaderType *shader;
124
125 if (mCompiledShaders[source] != NULL)
126 {
127 shader = static_cast<D3DShaderType*>(mCompiledShaders[source]);
128 }
129 else
130 {
apatrick@chromium.org99fbbe82012-07-19 19:11:24 +0000131 const BYTE* shaderCode = g_shaderCode[source];
132 size_t shaderSize = g_shaderSize[source];
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000133
daniel@transgaming.come4733d72012-10-31 18:07:01 +0000134 shader = (mRenderer->*createShader)(reinterpret_cast<const DWORD*>(shaderCode), shaderSize);
apatrick@chromium.org99fbbe82012-07-19 19:11:24 +0000135 if (!shader)
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000136 {
apatrick@chromium.org99fbbe82012-07-19 19:11:24 +0000137 ERR("Failed to create shader for blit operation");
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000138 return false;
139 }
140
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000141 mCompiledShaders[source] = shader;
142 }
143
144 HRESULT hr = (device->*setShader)(shader);
145
146 if (FAILED(hr))
147 {
apatrick@chromium.org99fbbe82012-07-19 19:11:24 +0000148 ERR("Failed to set shader for blit operation");
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000149 return false;
150 }
151
152 return true;
153}
154
155bool Blit::setVertexShader(ShaderId shader)
156{
daniel@transgaming.com2507f412012-10-31 18:46:48 +0000157 return setShader<IDirect3DVertexShader9>(shader, "vs_2_0", &renderer::Renderer9::createVertexShader, &IDirect3DDevice9::SetVertexShader);
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000158}
159
160bool Blit::setPixelShader(ShaderId shader)
161{
daniel@transgaming.com2507f412012-10-31 18:46:48 +0000162 return setShader<IDirect3DPixelShader9>(shader, "ps_2_0", &renderer::Renderer9::createPixelShader, &IDirect3DDevice9::SetPixelShader);
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000163}
164
daniel@transgaming.com8fd99e22010-04-20 18:52:00 +0000165RECT Blit::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
179bool Blit::boxFilter(IDirect3DSurface9 *source, IDirect3DSurface9 *dest)
180{
181 IDirect3DTexture9 *texture = copySurfaceToTexture(source, getSurfaceRect(source));
182 if (!texture)
183 {
184 return false;
185 }
186
daniel@transgaming.com621ce052012-10-31 17:52:29 +0000187 // D3D9_REPLACE
daniel@transgaming.come4733d72012-10-31 18:07:01 +0000188 IDirect3DDevice9 *device = mRenderer->getDevice();
daniel@transgaming.com1ddd1dd2010-05-11 02:29:34 +0000189
190 saveState();
191
daniel@transgaming.com8fd99e22010-04-20 18:52:00 +0000192 device->SetTexture(0, texture);
193 device->SetRenderTarget(0, dest);
194
195 setVertexShader(SHADER_VS_STANDARD);
196 setPixelShader(SHADER_PS_PASSTHROUGH);
197
198 setCommonBlitState();
199 device->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
200 device->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
201
202 setViewport(getSurfaceRect(dest), 0, 0);
203
204 render();
205
206 texture->Release();
207
daniel@transgaming.com1ddd1dd2010-05-11 02:29:34 +0000208 restoreState();
209
daniel@transgaming.com8fd99e22010-04-20 18:52:00 +0000210 return true;
211}
212
daniel@transgaming.com3cef5392012-10-31 19:52:15 +0000213bool Blit::copy(Framebuffer *framebuffer, const RECT &sourceRect, GLenum destFormat, GLint xoffset, GLint yoffset, TextureStorage2D *storage, GLint level)
daniel@transgaming.comeef864a2011-04-22 11:33:27 +0000214{
daniel@transgaming.com621ce052012-10-31 17:52:29 +0000215 // D3D9_REPLACE
daniel@transgaming.com3cef5392012-10-31 19:52:15 +0000216 IDirect3DSurface9 *source = framebuffer->getRenderTarget();
217 if (!source)
218 {
219 ERR("Failed to retrieve the render target.");
220 return error(GL_OUT_OF_MEMORY, false);
221 }
222
223 IDirect3DSurface9 *destSurface = storage->getSurfaceLevel(level, true);
224 bool result = false;
225
226 if (destSurface)
227 {
228 result = copy(source, sourceRect, destFormat, xoffset, yoffset, destSurface);
229 destSurface->Release();
230 }
231
232 source->Release();
233 return result;
234}
235
236bool Blit::copy(Framebuffer *framebuffer, const RECT &sourceRect, GLenum destFormat, GLint xoffset, GLint yoffset, TextureStorageCubeMap *storage, GLenum target, GLint level)
237{
238 // D3D9_REPLACE
239 IDirect3DSurface9 *source = framebuffer->getRenderTarget();
240 if (!source)
241 {
242 ERR("Failed to retrieve the render target.");
243 return error(GL_OUT_OF_MEMORY, false);
244 }
245
246 IDirect3DSurface9 *destSurface = storage->getCubeMapSurface(target, level, true);
247 bool result = false;
248
249 if (destSurface)
250 {
251 result = copy(source, sourceRect, destFormat, xoffset, yoffset, destSurface);
252 destSurface->Release();
253 }
254
255 source->Release();
256 return result;
257}
258
259bool Blit::copy(IDirect3DSurface9 *source, const RECT &sourceRect, GLenum destFormat, GLint xoffset, GLint yoffset, IDirect3DSurface9 *dest)
260{
261 if (!dest)
262 {
263 return false;
264 }
265
daniel@transgaming.come4733d72012-10-31 18:07:01 +0000266 IDirect3DDevice9 *device = mRenderer->getDevice();
daniel@transgaming.comeef864a2011-04-22 11:33:27 +0000267
268 D3DSURFACE_DESC sourceDesc;
269 D3DSURFACE_DESC destDesc;
270 source->GetDesc(&sourceDesc);
271 dest->GetDesc(&destDesc);
272
daniel@transgaming.comad52cb12012-10-17 18:14:45 +0000273 if (sourceDesc.Format == destDesc.Format && destDesc.Usage & D3DUSAGE_RENDERTARGET &&
274 dx2es::IsFormatChannelEquivalent(destDesc.Format, destFormat)) // Can use StretchRect
daniel@transgaming.comeef864a2011-04-22 11:33:27 +0000275 {
276 RECT destRect = {xoffset, yoffset, xoffset + (sourceRect.right - sourceRect.left), yoffset + (sourceRect.bottom - sourceRect.top)};
277 HRESULT result = device->StretchRect(source, &sourceRect, dest, &destRect, D3DTEXF_POINT);
278
279 if (FAILED(result))
280 {
281 ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
282 return error(GL_OUT_OF_MEMORY, false);
283 }
284 }
285 else
286 {
287 return formatConvert(source, sourceRect, destFormat, xoffset, yoffset, dest);
288 }
daniel@transgaming.comeef864a2011-04-22 11:33:27 +0000289 return true;
290}
291
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000292bool Blit::formatConvert(IDirect3DSurface9 *source, const RECT &sourceRect, GLenum destFormat, GLint xoffset, GLint yoffset, IDirect3DSurface9 *dest)
293{
294 IDirect3DTexture9 *texture = copySurfaceToTexture(source, sourceRect);
295 if (!texture)
296 {
297 return false;
298 }
299
daniel@transgaming.com621ce052012-10-31 17:52:29 +0000300 // D3D9_REPLACE
daniel@transgaming.come4733d72012-10-31 18:07:01 +0000301 IDirect3DDevice9 *device = mRenderer->getDevice();
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000302
daniel@transgaming.com1ddd1dd2010-05-11 02:29:34 +0000303 saveState();
304
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000305 device->SetTexture(0, texture);
306 device->SetRenderTarget(0, dest);
307
daniel@transgaming.com8fd99e22010-04-20 18:52:00 +0000308 setViewport(sourceRect, xoffset, yoffset);
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000309
310 setCommonBlitState();
311 if (setFormatConvertShaders(destFormat))
312 {
313 render();
314 }
315
316 texture->Release();
317
daniel@transgaming.com1ddd1dd2010-05-11 02:29:34 +0000318 restoreState();
319
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000320 return true;
321}
322
323bool Blit::setFormatConvertShaders(GLenum destFormat)
324{
325 bool okay = setVertexShader(SHADER_VS_STANDARD);
326
327 switch (destFormat)
328 {
329 default: UNREACHABLE();
330 case GL_RGBA:
daniel@transgaming.coma9198d92010-08-08 04:49:56 +0000331 case GL_BGRA_EXT:
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000332 case GL_RGB:
333 case GL_ALPHA:
334 okay = okay && setPixelShader(SHADER_PS_COMPONENTMASK);
335 break;
336
337 case GL_LUMINANCE:
338 case GL_LUMINANCE_ALPHA:
339 okay = okay && setPixelShader(SHADER_PS_LUMINANCE);
340 break;
341 }
342
343 if (!okay)
344 {
345 return false;
346 }
347
348 enum { X = 0, Y = 1, Z = 2, W = 3 };
349
350 // The meaning of this constant depends on the shader that was selected.
351 // See the shader assembly code above for details.
352 float psConst0[4] = { 0, 0, 0, 0 };
353
354 switch (destFormat)
355 {
356 default: UNREACHABLE();
357 case GL_RGBA:
daniel@transgaming.coma9198d92010-08-08 04:49:56 +0000358 case GL_BGRA_EXT:
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000359 psConst0[X] = 1;
360 psConst0[Z] = 1;
361 break;
362
363 case GL_RGB:
364 psConst0[X] = 1;
365 psConst0[W] = 1;
366 break;
367
368 case GL_ALPHA:
369 psConst0[Z] = 1;
370 break;
371
372 case GL_LUMINANCE:
373 psConst0[Y] = 1;
374 break;
375
376 case GL_LUMINANCE_ALPHA:
377 psConst0[X] = 1;
378 break;
379 }
380
daniel@transgaming.come4733d72012-10-31 18:07:01 +0000381 mRenderer->getDevice()->SetPixelShaderConstantF(0, psConst0, 1); // D3D9_REPLACE
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000382
383 return true;
384}
385
daniel@transgaming.com621ce052012-10-31 17:52:29 +0000386// D3D9_REPLACE
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000387IDirect3DTexture9 *Blit::copySurfaceToTexture(IDirect3DSurface9 *surface, const RECT &sourceRect)
388{
daniel@transgaming.comd36c6a02010-08-31 12:15:09 +0000389 if (!surface)
390 {
391 return NULL;
392 }
393
daniel@transgaming.come4733d72012-10-31 18:07:01 +0000394 IDirect3DDevice9 *device = mRenderer->getDevice(); // D3D9_REPLACE
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000395
396 D3DSURFACE_DESC sourceDesc;
397 surface->GetDesc(&sourceDesc);
398
399 // Copy the render target into a texture
400 IDirect3DTexture9 *texture;
daniel@transgaming.com8fd99e22010-04-20 18:52:00 +0000401 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 +0000402
403 if (FAILED(result))
404 {
405 ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
406 return error(GL_OUT_OF_MEMORY, (IDirect3DTexture9*)NULL);
407 }
408
409 IDirect3DSurface9 *textureSurface;
410 result = texture->GetSurfaceLevel(0, &textureSurface);
411
412 if (FAILED(result))
413 {
414 ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
415 texture->Release();
416 return error(GL_OUT_OF_MEMORY, (IDirect3DTexture9*)NULL);
417 }
418
daniel@transgaming.come4733d72012-10-31 18:07:01 +0000419 mRenderer->endScene();
daniel@transgaming.com4c5142c2010-10-15 17:58:27 +0000420 result = device->StretchRect(surface, &sourceRect, textureSurface, NULL, D3DTEXF_NONE);
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000421
422 textureSurface->Release();
423
424 if (FAILED(result))
425 {
426 ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
427 texture->Release();
428 return error(GL_OUT_OF_MEMORY, (IDirect3DTexture9*)NULL);
429 }
430
431 return texture;
432}
433
daniel@transgaming.com8fd99e22010-04-20 18:52:00 +0000434void Blit::setViewport(const RECT &sourceRect, GLint xoffset, GLint yoffset)
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000435{
daniel@transgaming.come4733d72012-10-31 18:07:01 +0000436 IDirect3DDevice9 *device = mRenderer->getDevice(); // D3D9_REPLACE
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000437
438 D3DVIEWPORT9 vp;
439 vp.X = xoffset;
440 vp.Y = yoffset;
441 vp.Width = sourceRect.right - sourceRect.left;
daniel@transgaming.com8fd99e22010-04-20 18:52:00 +0000442 vp.Height = sourceRect.bottom - sourceRect.top;
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000443 vp.MinZ = 0.0f;
444 vp.MaxZ = 1.0f;
445 device->SetViewport(&vp);
446
447 float halfPixelAdjust[4] = { -1.0f/vp.Width, 1.0f/vp.Height, 0, 0 };
448 device->SetVertexShaderConstantF(0, halfPixelAdjust, 1);
449}
450
daniel@transgaming.com621ce052012-10-31 17:52:29 +0000451// D3D9_REPLACE
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000452void Blit::setCommonBlitState()
453{
daniel@transgaming.come4733d72012-10-31 18:07:01 +0000454 IDirect3DDevice9 *device = mRenderer->getDevice();
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000455
456 device->SetDepthStencilSurface(NULL);
457
458 device->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID);
459 device->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE);
460 device->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
461 device->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
462 device->SetRenderState(D3DRS_CLIPPLANEENABLE, 0);
463 device->SetRenderState(D3DRS_COLORWRITEENABLE, D3DCOLORWRITEENABLE_ALPHA | D3DCOLORWRITEENABLE_BLUE | D3DCOLORWRITEENABLE_GREEN | D3DCOLORWRITEENABLE_RED);
464 device->SetRenderState(D3DRS_SRGBWRITEENABLE, FALSE);
465 device->SetRenderState(D3DRS_SCISSORTESTENABLE, FALSE);
466
467 device->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_POINT);
468 device->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_POINT);
469 device->SetSamplerState(0, D3DSAMP_SRGBTEXTURE, FALSE);
daniel@transgaming.com8fd99e22010-04-20 18:52:00 +0000470 device->SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP);
471 device->SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP);
daniel@transgaming.com81655a72010-05-20 19:18:17 +0000472
daniel@transgaming.com74d760b2010-11-03 12:27:18 +0000473 RECT scissorRect = {0}; // Scissoring is disabled for flipping, but we need this to capture and restore the old rectangle
474 device->SetScissorRect(&scissorRect);
daniel@transgaming.com8ca9c6e2012-01-27 15:38:54 +0000475
476 for(int i = 0; i < MAX_VERTEX_ATTRIBS; i++)
477 {
478 device->SetStreamSourceFreq(i, 1);
479 }
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000480}
481
daniel@transgaming.com621ce052012-10-31 17:52:29 +0000482// D3D9_REPLACE
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000483void Blit::render()
484{
daniel@transgaming.come4733d72012-10-31 18:07:01 +0000485 IDirect3DDevice9 *device = mRenderer->getDevice();
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000486
487 HRESULT hr = device->SetStreamSource(0, mQuadVertexBuffer, 0, 2 * sizeof(float));
488 hr = device->SetVertexDeclaration(mQuadVertexDeclaration);
489
daniel@transgaming.come4733d72012-10-31 18:07:01 +0000490 mRenderer->startScene();
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000491 hr = device->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2);
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000492}
493
daniel@transgaming.com621ce052012-10-31 17:52:29 +0000494// D3D9_REPLACE
daniel@transgaming.com1ddd1dd2010-05-11 02:29:34 +0000495void Blit::saveState()
496{
daniel@transgaming.come4733d72012-10-31 18:07:01 +0000497 IDirect3DDevice9 *device = mRenderer->getDevice();
daniel@transgaming.com1ddd1dd2010-05-11 02:29:34 +0000498
499 HRESULT hr;
500
501 device->GetDepthStencilSurface(&mSavedDepthStencil);
502 device->GetRenderTarget(0, &mSavedRenderTarget);
503
504 if (mSavedStateBlock == NULL)
505 {
506 hr = device->BeginStateBlock();
507 ASSERT(SUCCEEDED(hr) || hr == D3DERR_OUTOFVIDEOMEMORY || hr == E_OUTOFMEMORY);
508
509 setCommonBlitState();
510
511 static const float dummyConst[4] = { 0, 0, 0, 0 };
512
513 device->SetVertexShader(NULL);
514 device->SetVertexShaderConstantF(0, dummyConst, 1);
515 device->SetPixelShader(NULL);
516 device->SetPixelShaderConstantF(0, dummyConst, 1);
517
518 D3DVIEWPORT9 dummyVp;
519 dummyVp.X = 0;
520 dummyVp.Y = 0;
521 dummyVp.Width = 1;
522 dummyVp.Height = 1;
523 dummyVp.MinZ = 0;
524 dummyVp.MaxZ = 1;
525
526 device->SetViewport(&dummyVp);
527
528 device->SetTexture(0, NULL);
529
530 device->SetStreamSource(0, mQuadVertexBuffer, 0, 0);
531
532 device->SetVertexDeclaration(mQuadVertexDeclaration);
533
534 hr = device->EndStateBlock(&mSavedStateBlock);
535 ASSERT(SUCCEEDED(hr) || hr == D3DERR_OUTOFVIDEOMEMORY || hr == E_OUTOFMEMORY);
536 }
537
538 ASSERT(mSavedStateBlock != NULL);
539
540 if (mSavedStateBlock != NULL)
541 {
542 hr = mSavedStateBlock->Capture();
543 ASSERT(SUCCEEDED(hr));
544 }
545}
546
daniel@transgaming.com621ce052012-10-31 17:52:29 +0000547// D3D9_REPLACE
daniel@transgaming.com1ddd1dd2010-05-11 02:29:34 +0000548void Blit::restoreState()
549{
daniel@transgaming.come4733d72012-10-31 18:07:01 +0000550 IDirect3DDevice9 *device = mRenderer->getDevice();
daniel@transgaming.com1ddd1dd2010-05-11 02:29:34 +0000551
552 device->SetDepthStencilSurface(mSavedDepthStencil);
553 if (mSavedDepthStencil != NULL)
554 {
555 mSavedDepthStencil->Release();
556 mSavedDepthStencil = NULL;
557 }
558
559 device->SetRenderTarget(0, mSavedRenderTarget);
560 if (mSavedRenderTarget != NULL)
561 {
562 mSavedRenderTarget->Release();
563 mSavedRenderTarget = NULL;
564 }
565
566 ASSERT(mSavedStateBlock != NULL);
567
568 if (mSavedStateBlock != NULL)
569 {
570 mSavedStateBlock->Apply();
571 }
572}
573
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000574}