blob: eaff32d3d73c0592f552519e4d863e599d489b2b [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.comd8e36562012-10-31 19:52:19 +000015#include "libGLESv2/renderer/renderer9_utils.h" // D3D9_REPLACE
daniel@transgaming.com3cef5392012-10-31 19:52:15 +000016#include "libGLESv2/Framebuffer.h"
daniel@transgaming.combbf56f72010-04-20 18:52:13 +000017
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +000018namespace
19{
apatrick@chromium.org99fbbe82012-07-19 19:11:24 +000020#include "libGLESv2/shaders/standardvs.h"
21#include "libGLESv2/shaders/flipyvs.h"
22#include "libGLESv2/shaders/passthroughps.h"
23#include "libGLESv2/shaders/luminanceps.h"
24#include "libGLESv2/shaders/componentmaskps.h"
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +000025
apatrick@chromium.org99fbbe82012-07-19 19:11:24 +000026const BYTE* const g_shaderCode[] =
27{
28 g_vs20_standardvs,
29 g_vs20_flipyvs,
30 g_ps20_passthroughps,
31 g_ps20_luminanceps,
32 g_ps20_componentmaskps
33};
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +000034
apatrick@chromium.org99fbbe82012-07-19 19:11:24 +000035const size_t g_shaderSize[] =
36{
37 sizeof(g_vs20_standardvs),
38 sizeof(g_vs20_flipyvs),
39 sizeof(g_ps20_passthroughps),
40 sizeof(g_ps20_luminanceps),
41 sizeof(g_ps20_componentmaskps)
42};
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +000043}
44
45namespace gl
46{
daniel@transgaming.com2507f412012-10-31 18:46:48 +000047Blit::Blit(renderer::Renderer9 *renderer)
daniel@transgaming.come4733d72012-10-31 18:07:01 +000048 : mRenderer(renderer), mQuadVertexBuffer(NULL), mQuadVertexDeclaration(NULL), mSavedRenderTarget(NULL), mSavedDepthStencil(NULL), mSavedStateBlock(NULL)
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +000049{
50 initGeometry();
51 memset(mCompiledShaders, 0, sizeof(mCompiledShaders));
52}
53
54Blit::~Blit()
55{
daniel@transgaming.com1ddd1dd2010-05-11 02:29:34 +000056 if (mSavedStateBlock) mSavedStateBlock->Release();
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +000057 if (mQuadVertexBuffer) mQuadVertexBuffer->Release();
58 if (mQuadVertexDeclaration) mQuadVertexDeclaration->Release();
59
60 for (int i = 0; i < SHADER_COUNT; i++)
61 {
62 if (mCompiledShaders[i])
63 {
64 mCompiledShaders[i]->Release();
65 }
66 }
67}
68
daniel@transgaming.com621ce052012-10-31 17:52:29 +000069// D3D9_REPLACE
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +000070void Blit::initGeometry()
71{
72 static const float quad[] =
73 {
74 -1, -1,
75 -1, 1,
76 1, -1,
77 1, 1
78 };
79
daniel@transgaming.come4733d72012-10-31 18:07:01 +000080 IDirect3DDevice9 *device = mRenderer->getDevice();
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +000081
daniel@transgaming.comaa614602011-04-28 16:20:58 +000082 HRESULT result = device->CreateVertexBuffer(sizeof(quad), D3DUSAGE_WRITEONLY, 0, D3DPOOL_DEFAULT, &mQuadVertexBuffer, NULL);
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +000083
daniel@transgaming.comaa614602011-04-28 16:20:58 +000084 if (FAILED(result))
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +000085 {
daniel@transgaming.comaa614602011-04-28 16:20:58 +000086 ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +000087 return error(GL_OUT_OF_MEMORY);
88 }
89
daniel@transgaming.comaa614602011-04-28 16:20:58 +000090 void *lockPtr = NULL;
91 result = mQuadVertexBuffer->Lock(0, 0, &lockPtr, 0);
92
93 if (FAILED(result) || lockPtr == NULL)
94 {
95 ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
96 return error(GL_OUT_OF_MEMORY);
97 }
98
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +000099 memcpy(lockPtr, quad, sizeof(quad));
100 mQuadVertexBuffer->Unlock();
101
102 static const D3DVERTEXELEMENT9 elements[] =
103 {
104 { 0, 0, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0 },
105 D3DDECL_END()
106 };
107
daniel@transgaming.comaa614602011-04-28 16:20:58 +0000108 result = device->CreateVertexDeclaration(elements, &mQuadVertexDeclaration);
109
110 if (FAILED(result))
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000111 {
daniel@transgaming.comaa614602011-04-28 16:20:58 +0000112 ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000113 return error(GL_OUT_OF_MEMORY);
114 }
115}
116
117template <class D3DShaderType>
118bool Blit::setShader(ShaderId source, const char *profile,
daniel@transgaming.com2507f412012-10-31 18:46:48 +0000119 D3DShaderType *(renderer::Renderer9::*createShader)(const DWORD *, size_t length),
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000120 HRESULT (WINAPI IDirect3DDevice9::*setShader)(D3DShaderType*))
121{
daniel@transgaming.come4733d72012-10-31 18:07:01 +0000122 IDirect3DDevice9 *device = mRenderer->getDevice(); // D3D9_REPLACE
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000123
124 D3DShaderType *shader;
125
126 if (mCompiledShaders[source] != NULL)
127 {
128 shader = static_cast<D3DShaderType*>(mCompiledShaders[source]);
129 }
130 else
131 {
apatrick@chromium.org99fbbe82012-07-19 19:11:24 +0000132 const BYTE* shaderCode = g_shaderCode[source];
133 size_t shaderSize = g_shaderSize[source];
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000134
daniel@transgaming.come4733d72012-10-31 18:07:01 +0000135 shader = (mRenderer->*createShader)(reinterpret_cast<const DWORD*>(shaderCode), shaderSize);
apatrick@chromium.org99fbbe82012-07-19 19:11:24 +0000136 if (!shader)
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000137 {
apatrick@chromium.org99fbbe82012-07-19 19:11:24 +0000138 ERR("Failed to create shader for blit operation");
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000139 return false;
140 }
141
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000142 mCompiledShaders[source] = shader;
143 }
144
145 HRESULT hr = (device->*setShader)(shader);
146
147 if (FAILED(hr))
148 {
apatrick@chromium.org99fbbe82012-07-19 19:11:24 +0000149 ERR("Failed to set shader for blit operation");
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000150 return false;
151 }
152
153 return true;
154}
155
156bool Blit::setVertexShader(ShaderId shader)
157{
daniel@transgaming.com2507f412012-10-31 18:46:48 +0000158 return setShader<IDirect3DVertexShader9>(shader, "vs_2_0", &renderer::Renderer9::createVertexShader, &IDirect3DDevice9::SetVertexShader);
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000159}
160
161bool Blit::setPixelShader(ShaderId shader)
162{
daniel@transgaming.com2507f412012-10-31 18:46:48 +0000163 return setShader<IDirect3DPixelShader9>(shader, "ps_2_0", &renderer::Renderer9::createPixelShader, &IDirect3DDevice9::SetPixelShader);
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000164}
165
daniel@transgaming.com8fd99e22010-04-20 18:52:00 +0000166RECT Blit::getSurfaceRect(IDirect3DSurface9 *surface) const
167{
168 D3DSURFACE_DESC desc;
169 surface->GetDesc(&desc);
170
171 RECT rect;
172 rect.left = 0;
173 rect.top = 0;
174 rect.right = desc.Width;
175 rect.bottom = desc.Height;
176
177 return rect;
178}
179
180bool Blit::boxFilter(IDirect3DSurface9 *source, IDirect3DSurface9 *dest)
181{
182 IDirect3DTexture9 *texture = copySurfaceToTexture(source, getSurfaceRect(source));
183 if (!texture)
184 {
185 return false;
186 }
187
daniel@transgaming.com621ce052012-10-31 17:52:29 +0000188 // D3D9_REPLACE
daniel@transgaming.come4733d72012-10-31 18:07:01 +0000189 IDirect3DDevice9 *device = mRenderer->getDevice();
daniel@transgaming.com1ddd1dd2010-05-11 02:29:34 +0000190
191 saveState();
192
daniel@transgaming.com8fd99e22010-04-20 18:52:00 +0000193 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
daniel@transgaming.com1ddd1dd2010-05-11 02:29:34 +0000209 restoreState();
210
daniel@transgaming.com8fd99e22010-04-20 18:52:00 +0000211 return true;
212}
213
daniel@transgaming.com3cef5392012-10-31 19:52:15 +0000214bool 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 +0000215{
daniel@transgaming.com621ce052012-10-31 17:52:29 +0000216 // D3D9_REPLACE
daniel@transgaming.com3cef5392012-10-31 19:52:15 +0000217 IDirect3DSurface9 *source = framebuffer->getRenderTarget();
218 if (!source)
219 {
220 ERR("Failed to retrieve the render target.");
221 return error(GL_OUT_OF_MEMORY, false);
222 }
223
224 IDirect3DSurface9 *destSurface = storage->getSurfaceLevel(level, true);
225 bool result = false;
226
227 if (destSurface)
228 {
229 result = copy(source, sourceRect, destFormat, xoffset, yoffset, destSurface);
230 destSurface->Release();
231 }
232
233 source->Release();
234 return result;
235}
236
237bool Blit::copy(Framebuffer *framebuffer, const RECT &sourceRect, GLenum destFormat, GLint xoffset, GLint yoffset, TextureStorageCubeMap *storage, GLenum target, GLint level)
238{
239 // D3D9_REPLACE
240 IDirect3DSurface9 *source = framebuffer->getRenderTarget();
241 if (!source)
242 {
243 ERR("Failed to retrieve the render target.");
244 return error(GL_OUT_OF_MEMORY, false);
245 }
246
247 IDirect3DSurface9 *destSurface = storage->getCubeMapSurface(target, level, true);
248 bool result = false;
249
250 if (destSurface)
251 {
252 result = copy(source, sourceRect, destFormat, xoffset, yoffset, destSurface);
253 destSurface->Release();
254 }
255
256 source->Release();
257 return result;
258}
259
260bool Blit::copy(IDirect3DSurface9 *source, const RECT &sourceRect, GLenum destFormat, GLint xoffset, GLint yoffset, IDirect3DSurface9 *dest)
261{
262 if (!dest)
263 {
264 return false;
265 }
266
daniel@transgaming.come4733d72012-10-31 18:07:01 +0000267 IDirect3DDevice9 *device = mRenderer->getDevice();
daniel@transgaming.comeef864a2011-04-22 11:33:27 +0000268
269 D3DSURFACE_DESC sourceDesc;
270 D3DSURFACE_DESC destDesc;
271 source->GetDesc(&sourceDesc);
272 dest->GetDesc(&destDesc);
273
daniel@transgaming.comad52cb12012-10-17 18:14:45 +0000274 if (sourceDesc.Format == destDesc.Format && destDesc.Usage & D3DUSAGE_RENDERTARGET &&
275 dx2es::IsFormatChannelEquivalent(destDesc.Format, destFormat)) // Can use StretchRect
daniel@transgaming.comeef864a2011-04-22 11:33:27 +0000276 {
277 RECT destRect = {xoffset, yoffset, xoffset + (sourceRect.right - sourceRect.left), yoffset + (sourceRect.bottom - sourceRect.top)};
278 HRESULT result = device->StretchRect(source, &sourceRect, dest, &destRect, D3DTEXF_POINT);
279
280 if (FAILED(result))
281 {
282 ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
283 return error(GL_OUT_OF_MEMORY, false);
284 }
285 }
286 else
287 {
288 return formatConvert(source, sourceRect, destFormat, xoffset, yoffset, dest);
289 }
daniel@transgaming.comeef864a2011-04-22 11:33:27 +0000290 return true;
291}
292
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000293bool Blit::formatConvert(IDirect3DSurface9 *source, const RECT &sourceRect, GLenum destFormat, GLint xoffset, GLint yoffset, IDirect3DSurface9 *dest)
294{
295 IDirect3DTexture9 *texture = copySurfaceToTexture(source, sourceRect);
296 if (!texture)
297 {
298 return false;
299 }
300
daniel@transgaming.com621ce052012-10-31 17:52:29 +0000301 // D3D9_REPLACE
daniel@transgaming.come4733d72012-10-31 18:07:01 +0000302 IDirect3DDevice9 *device = mRenderer->getDevice();
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000303
daniel@transgaming.com1ddd1dd2010-05-11 02:29:34 +0000304 saveState();
305
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000306 device->SetTexture(0, texture);
307 device->SetRenderTarget(0, dest);
308
daniel@transgaming.com8fd99e22010-04-20 18:52:00 +0000309 setViewport(sourceRect, xoffset, yoffset);
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000310
311 setCommonBlitState();
312 if (setFormatConvertShaders(destFormat))
313 {
314 render();
315 }
316
317 texture->Release();
318
daniel@transgaming.com1ddd1dd2010-05-11 02:29:34 +0000319 restoreState();
320
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000321 return true;
322}
323
324bool Blit::setFormatConvertShaders(GLenum destFormat)
325{
326 bool okay = setVertexShader(SHADER_VS_STANDARD);
327
328 switch (destFormat)
329 {
330 default: UNREACHABLE();
331 case GL_RGBA:
daniel@transgaming.coma9198d92010-08-08 04:49:56 +0000332 case GL_BGRA_EXT:
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000333 case GL_RGB:
334 case GL_ALPHA:
335 okay = okay && setPixelShader(SHADER_PS_COMPONENTMASK);
336 break;
337
338 case GL_LUMINANCE:
339 case GL_LUMINANCE_ALPHA:
340 okay = okay && setPixelShader(SHADER_PS_LUMINANCE);
341 break;
342 }
343
344 if (!okay)
345 {
346 return false;
347 }
348
349 enum { X = 0, Y = 1, Z = 2, W = 3 };
350
351 // The meaning of this constant depends on the shader that was selected.
352 // See the shader assembly code above for details.
353 float psConst0[4] = { 0, 0, 0, 0 };
354
355 switch (destFormat)
356 {
357 default: UNREACHABLE();
358 case GL_RGBA:
daniel@transgaming.coma9198d92010-08-08 04:49:56 +0000359 case GL_BGRA_EXT:
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000360 psConst0[X] = 1;
361 psConst0[Z] = 1;
362 break;
363
364 case GL_RGB:
365 psConst0[X] = 1;
366 psConst0[W] = 1;
367 break;
368
369 case GL_ALPHA:
370 psConst0[Z] = 1;
371 break;
372
373 case GL_LUMINANCE:
374 psConst0[Y] = 1;
375 break;
376
377 case GL_LUMINANCE_ALPHA:
378 psConst0[X] = 1;
379 break;
380 }
381
daniel@transgaming.come4733d72012-10-31 18:07:01 +0000382 mRenderer->getDevice()->SetPixelShaderConstantF(0, psConst0, 1); // D3D9_REPLACE
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000383
384 return true;
385}
386
daniel@transgaming.com621ce052012-10-31 17:52:29 +0000387// D3D9_REPLACE
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000388IDirect3DTexture9 *Blit::copySurfaceToTexture(IDirect3DSurface9 *surface, const RECT &sourceRect)
389{
daniel@transgaming.comd36c6a02010-08-31 12:15:09 +0000390 if (!surface)
391 {
392 return NULL;
393 }
394
daniel@transgaming.come4733d72012-10-31 18:07:01 +0000395 IDirect3DDevice9 *device = mRenderer->getDevice(); // D3D9_REPLACE
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000396
397 D3DSURFACE_DESC sourceDesc;
398 surface->GetDesc(&sourceDesc);
399
400 // Copy the render target into a texture
401 IDirect3DTexture9 *texture;
daniel@transgaming.com8fd99e22010-04-20 18:52:00 +0000402 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 +0000403
404 if (FAILED(result))
405 {
406 ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
407 return error(GL_OUT_OF_MEMORY, (IDirect3DTexture9*)NULL);
408 }
409
410 IDirect3DSurface9 *textureSurface;
411 result = texture->GetSurfaceLevel(0, &textureSurface);
412
413 if (FAILED(result))
414 {
415 ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
416 texture->Release();
417 return error(GL_OUT_OF_MEMORY, (IDirect3DTexture9*)NULL);
418 }
419
daniel@transgaming.come4733d72012-10-31 18:07:01 +0000420 mRenderer->endScene();
daniel@transgaming.com4c5142c2010-10-15 17:58:27 +0000421 result = device->StretchRect(surface, &sourceRect, textureSurface, NULL, D3DTEXF_NONE);
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000422
423 textureSurface->Release();
424
425 if (FAILED(result))
426 {
427 ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
428 texture->Release();
429 return error(GL_OUT_OF_MEMORY, (IDirect3DTexture9*)NULL);
430 }
431
432 return texture;
433}
434
daniel@transgaming.com8fd99e22010-04-20 18:52:00 +0000435void Blit::setViewport(const RECT &sourceRect, GLint xoffset, GLint yoffset)
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000436{
daniel@transgaming.come4733d72012-10-31 18:07:01 +0000437 IDirect3DDevice9 *device = mRenderer->getDevice(); // D3D9_REPLACE
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000438
439 D3DVIEWPORT9 vp;
440 vp.X = xoffset;
441 vp.Y = yoffset;
442 vp.Width = sourceRect.right - sourceRect.left;
daniel@transgaming.com8fd99e22010-04-20 18:52:00 +0000443 vp.Height = sourceRect.bottom - sourceRect.top;
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000444 vp.MinZ = 0.0f;
445 vp.MaxZ = 1.0f;
446 device->SetViewport(&vp);
447
448 float halfPixelAdjust[4] = { -1.0f/vp.Width, 1.0f/vp.Height, 0, 0 };
449 device->SetVertexShaderConstantF(0, halfPixelAdjust, 1);
450}
451
daniel@transgaming.com621ce052012-10-31 17:52:29 +0000452// D3D9_REPLACE
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000453void Blit::setCommonBlitState()
454{
daniel@transgaming.come4733d72012-10-31 18:07:01 +0000455 IDirect3DDevice9 *device = mRenderer->getDevice();
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000456
457 device->SetDepthStencilSurface(NULL);
458
459 device->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID);
460 device->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE);
461 device->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
462 device->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
463 device->SetRenderState(D3DRS_CLIPPLANEENABLE, 0);
464 device->SetRenderState(D3DRS_COLORWRITEENABLE, D3DCOLORWRITEENABLE_ALPHA | D3DCOLORWRITEENABLE_BLUE | D3DCOLORWRITEENABLE_GREEN | D3DCOLORWRITEENABLE_RED);
465 device->SetRenderState(D3DRS_SRGBWRITEENABLE, FALSE);
466 device->SetRenderState(D3DRS_SCISSORTESTENABLE, FALSE);
467
468 device->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_POINT);
469 device->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_POINT);
470 device->SetSamplerState(0, D3DSAMP_SRGBTEXTURE, FALSE);
daniel@transgaming.com8fd99e22010-04-20 18:52:00 +0000471 device->SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP);
472 device->SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP);
daniel@transgaming.com81655a72010-05-20 19:18:17 +0000473
daniel@transgaming.com74d760b2010-11-03 12:27:18 +0000474 RECT scissorRect = {0}; // Scissoring is disabled for flipping, but we need this to capture and restore the old rectangle
475 device->SetScissorRect(&scissorRect);
daniel@transgaming.com8ca9c6e2012-01-27 15:38:54 +0000476
477 for(int i = 0; i < MAX_VERTEX_ATTRIBS; i++)
478 {
479 device->SetStreamSourceFreq(i, 1);
480 }
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000481}
482
daniel@transgaming.com621ce052012-10-31 17:52:29 +0000483// D3D9_REPLACE
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000484void Blit::render()
485{
daniel@transgaming.come4733d72012-10-31 18:07:01 +0000486 IDirect3DDevice9 *device = mRenderer->getDevice();
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000487
488 HRESULT hr = device->SetStreamSource(0, mQuadVertexBuffer, 0, 2 * sizeof(float));
489 hr = device->SetVertexDeclaration(mQuadVertexDeclaration);
490
daniel@transgaming.come4733d72012-10-31 18:07:01 +0000491 mRenderer->startScene();
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000492 hr = device->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2);
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000493}
494
daniel@transgaming.com621ce052012-10-31 17:52:29 +0000495// D3D9_REPLACE
daniel@transgaming.com1ddd1dd2010-05-11 02:29:34 +0000496void Blit::saveState()
497{
daniel@transgaming.come4733d72012-10-31 18:07:01 +0000498 IDirect3DDevice9 *device = mRenderer->getDevice();
daniel@transgaming.com1ddd1dd2010-05-11 02:29:34 +0000499
500 HRESULT hr;
501
502 device->GetDepthStencilSurface(&mSavedDepthStencil);
503 device->GetRenderTarget(0, &mSavedRenderTarget);
504
505 if (mSavedStateBlock == NULL)
506 {
507 hr = device->BeginStateBlock();
508 ASSERT(SUCCEEDED(hr) || hr == D3DERR_OUTOFVIDEOMEMORY || hr == E_OUTOFMEMORY);
509
510 setCommonBlitState();
511
512 static const float dummyConst[4] = { 0, 0, 0, 0 };
513
514 device->SetVertexShader(NULL);
515 device->SetVertexShaderConstantF(0, dummyConst, 1);
516 device->SetPixelShader(NULL);
517 device->SetPixelShaderConstantF(0, dummyConst, 1);
518
519 D3DVIEWPORT9 dummyVp;
520 dummyVp.X = 0;
521 dummyVp.Y = 0;
522 dummyVp.Width = 1;
523 dummyVp.Height = 1;
524 dummyVp.MinZ = 0;
525 dummyVp.MaxZ = 1;
526
527 device->SetViewport(&dummyVp);
528
529 device->SetTexture(0, NULL);
530
531 device->SetStreamSource(0, mQuadVertexBuffer, 0, 0);
532
533 device->SetVertexDeclaration(mQuadVertexDeclaration);
534
535 hr = device->EndStateBlock(&mSavedStateBlock);
536 ASSERT(SUCCEEDED(hr) || hr == D3DERR_OUTOFVIDEOMEMORY || hr == E_OUTOFMEMORY);
537 }
538
539 ASSERT(mSavedStateBlock != NULL);
540
541 if (mSavedStateBlock != NULL)
542 {
543 hr = mSavedStateBlock->Capture();
544 ASSERT(SUCCEEDED(hr));
545 }
546}
547
daniel@transgaming.com621ce052012-10-31 17:52:29 +0000548// D3D9_REPLACE
daniel@transgaming.com1ddd1dd2010-05-11 02:29:34 +0000549void Blit::restoreState()
550{
daniel@transgaming.come4733d72012-10-31 18:07:01 +0000551 IDirect3DDevice9 *device = mRenderer->getDevice();
daniel@transgaming.com1ddd1dd2010-05-11 02:29:34 +0000552
553 device->SetDepthStencilSurface(mSavedDepthStencil);
554 if (mSavedDepthStencil != NULL)
555 {
556 mSavedDepthStencil->Release();
557 mSavedDepthStencil = NULL;
558 }
559
560 device->SetRenderTarget(0, mSavedRenderTarget);
561 if (mSavedRenderTarget != NULL)
562 {
563 mSavedRenderTarget->Release();
564 mSavedRenderTarget = NULL;
565 }
566
567 ASSERT(mSavedStateBlock != NULL);
568
569 if (mSavedStateBlock != NULL)
570 {
571 mSavedStateBlock->Apply();
572 }
573}
574
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000575}