blob: 2d125946f7c2fc92711f212b39e804a7648ca189 [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.comde8a7ff2012-11-28 19:34:13 +00009#include "libGLESv2/renderer/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.comde8a7ff2012-11-28 19:34:13 +000016#include "libGLESv2/renderer/TextureStorage.h"
daniel@transgaming.com3cef5392012-10-31 19:52:15 +000017#include "libGLESv2/Framebuffer.h"
daniel@transgaming.combbf56f72010-04-20 18:52:13 +000018
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +000019namespace
20{
apatrick@chromium.org99fbbe82012-07-19 19:11:24 +000021#include "libGLESv2/shaders/standardvs.h"
22#include "libGLESv2/shaders/flipyvs.h"
23#include "libGLESv2/shaders/passthroughps.h"
24#include "libGLESv2/shaders/luminanceps.h"
25#include "libGLESv2/shaders/componentmaskps.h"
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +000026
apatrick@chromium.org99fbbe82012-07-19 19:11:24 +000027const BYTE* const g_shaderCode[] =
28{
29 g_vs20_standardvs,
30 g_vs20_flipyvs,
31 g_ps20_passthroughps,
32 g_ps20_luminanceps,
33 g_ps20_componentmaskps
34};
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +000035
apatrick@chromium.org99fbbe82012-07-19 19:11:24 +000036const size_t g_shaderSize[] =
37{
38 sizeof(g_vs20_standardvs),
39 sizeof(g_vs20_flipyvs),
40 sizeof(g_ps20_passthroughps),
41 sizeof(g_ps20_luminanceps),
42 sizeof(g_ps20_componentmaskps)
43};
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +000044}
45
daniel@transgaming.comde8a7ff2012-11-28 19:34:13 +000046namespace rx
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +000047{
daniel@transgaming.com76d3e6e2012-10-31 19:55:33 +000048Blit::Blit(rx::Renderer9 *renderer)
daniel@transgaming.come4733d72012-10-31 18:07:01 +000049 : mRenderer(renderer), mQuadVertexBuffer(NULL), mQuadVertexDeclaration(NULL), mSavedRenderTarget(NULL), mSavedDepthStencil(NULL), mSavedStateBlock(NULL)
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +000050{
51 initGeometry();
52 memset(mCompiledShaders, 0, sizeof(mCompiledShaders));
53}
54
55Blit::~Blit()
56{
daniel@transgaming.com1ddd1dd2010-05-11 02:29:34 +000057 if (mSavedStateBlock) mSavedStateBlock->Release();
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +000058 if (mQuadVertexBuffer) mQuadVertexBuffer->Release();
59 if (mQuadVertexDeclaration) mQuadVertexDeclaration->Release();
60
61 for (int i = 0; i < SHADER_COUNT; i++)
62 {
63 if (mCompiledShaders[i])
64 {
65 mCompiledShaders[i]->Release();
66 }
67 }
68}
69
daniel@transgaming.com621ce052012-10-31 17:52:29 +000070// D3D9_REPLACE
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +000071void Blit::initGeometry()
72{
73 static const float quad[] =
74 {
75 -1, -1,
76 -1, 1,
77 1, -1,
78 1, 1
79 };
80
daniel@transgaming.come4733d72012-10-31 18:07:01 +000081 IDirect3DDevice9 *device = mRenderer->getDevice();
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +000082
daniel@transgaming.comaa614602011-04-28 16:20:58 +000083 HRESULT result = device->CreateVertexBuffer(sizeof(quad), D3DUSAGE_WRITEONLY, 0, D3DPOOL_DEFAULT, &mQuadVertexBuffer, NULL);
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +000084
daniel@transgaming.comaa614602011-04-28 16:20:58 +000085 if (FAILED(result))
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +000086 {
daniel@transgaming.comaa614602011-04-28 16:20:58 +000087 ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +000088 return error(GL_OUT_OF_MEMORY);
89 }
90
daniel@transgaming.comaa614602011-04-28 16:20:58 +000091 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 error(GL_OUT_OF_MEMORY);
98 }
99
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000100 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
daniel@transgaming.comaa614602011-04-28 16:20:58 +0000109 result = device->CreateVertexDeclaration(elements, &mQuadVertexDeclaration);
110
111 if (FAILED(result))
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000112 {
daniel@transgaming.comaa614602011-04-28 16:20:58 +0000113 ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000114 return error(GL_OUT_OF_MEMORY);
115 }
116}
117
118template <class D3DShaderType>
119bool Blit::setShader(ShaderId source, const char *profile,
daniel@transgaming.com76d3e6e2012-10-31 19:55:33 +0000120 D3DShaderType *(rx::Renderer9::*createShader)(const DWORD *, size_t length),
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000121 HRESULT (WINAPI IDirect3DDevice9::*setShader)(D3DShaderType*))
122{
daniel@transgaming.come4733d72012-10-31 18:07:01 +0000123 IDirect3DDevice9 *device = mRenderer->getDevice(); // D3D9_REPLACE
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000124
125 D3DShaderType *shader;
126
127 if (mCompiledShaders[source] != NULL)
128 {
129 shader = static_cast<D3DShaderType*>(mCompiledShaders[source]);
130 }
131 else
132 {
apatrick@chromium.org99fbbe82012-07-19 19:11:24 +0000133 const BYTE* shaderCode = g_shaderCode[source];
134 size_t shaderSize = g_shaderSize[source];
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000135
daniel@transgaming.come4733d72012-10-31 18:07:01 +0000136 shader = (mRenderer->*createShader)(reinterpret_cast<const DWORD*>(shaderCode), shaderSize);
apatrick@chromium.org99fbbe82012-07-19 19:11:24 +0000137 if (!shader)
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000138 {
apatrick@chromium.org99fbbe82012-07-19 19:11:24 +0000139 ERR("Failed to create shader for blit operation");
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000140 return false;
141 }
142
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000143 mCompiledShaders[source] = shader;
144 }
145
146 HRESULT hr = (device->*setShader)(shader);
147
148 if (FAILED(hr))
149 {
apatrick@chromium.org99fbbe82012-07-19 19:11:24 +0000150 ERR("Failed to set shader for blit operation");
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000151 return false;
152 }
153
154 return true;
155}
156
157bool Blit::setVertexShader(ShaderId shader)
158{
daniel@transgaming.com76d3e6e2012-10-31 19:55:33 +0000159 return setShader<IDirect3DVertexShader9>(shader, "vs_2_0", &rx::Renderer9::createVertexShader, &IDirect3DDevice9::SetVertexShader);
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000160}
161
162bool Blit::setPixelShader(ShaderId shader)
163{
daniel@transgaming.com76d3e6e2012-10-31 19:55:33 +0000164 return setShader<IDirect3DPixelShader9>(shader, "ps_2_0", &rx::Renderer9::createPixelShader, &IDirect3DDevice9::SetPixelShader);
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000165}
166
daniel@transgaming.com8fd99e22010-04-20 18:52:00 +0000167RECT 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
181bool Blit::boxFilter(IDirect3DSurface9 *source, IDirect3DSurface9 *dest)
182{
183 IDirect3DTexture9 *texture = copySurfaceToTexture(source, getSurfaceRect(source));
184 if (!texture)
185 {
186 return false;
187 }
188
daniel@transgaming.com621ce052012-10-31 17:52:29 +0000189 // D3D9_REPLACE
daniel@transgaming.come4733d72012-10-31 18:07:01 +0000190 IDirect3DDevice9 *device = mRenderer->getDevice();
daniel@transgaming.com1ddd1dd2010-05-11 02:29:34 +0000191
192 saveState();
193
daniel@transgaming.com8fd99e22010-04-20 18:52:00 +0000194 device->SetTexture(0, texture);
195 device->SetRenderTarget(0, dest);
196
197 setVertexShader(SHADER_VS_STANDARD);
198 setPixelShader(SHADER_PS_PASSTHROUGH);
199
200 setCommonBlitState();
201 device->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
202 device->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
203
204 setViewport(getSurfaceRect(dest), 0, 0);
205
206 render();
207
208 texture->Release();
209
daniel@transgaming.com1ddd1dd2010-05-11 02:29:34 +0000210 restoreState();
211
daniel@transgaming.com8fd99e22010-04-20 18:52:00 +0000212 return true;
213}
214
daniel@transgaming.com31b13e12012-11-28 19:34:30 +0000215bool Blit::copy(gl::Framebuffer *framebuffer, const RECT &sourceRect, GLenum destFormat, GLint xoffset, GLint yoffset, TextureStorage2D *storage, GLint level)
daniel@transgaming.comeef864a2011-04-22 11:33:27 +0000216{
daniel@transgaming.com621ce052012-10-31 17:52:29 +0000217 // D3D9_REPLACE
daniel@transgaming.com3cef5392012-10-31 19:52:15 +0000218 IDirect3DSurface9 *source = framebuffer->getRenderTarget();
219 if (!source)
220 {
221 ERR("Failed to retrieve the render target.");
222 return error(GL_OUT_OF_MEMORY, false);
223 }
224
225 IDirect3DSurface9 *destSurface = storage->getSurfaceLevel(level, true);
226 bool result = false;
227
228 if (destSurface)
229 {
230 result = copy(source, sourceRect, destFormat, xoffset, yoffset, destSurface);
231 destSurface->Release();
232 }
233
234 source->Release();
235 return result;
236}
237
daniel@transgaming.com31b13e12012-11-28 19:34:30 +0000238bool Blit::copy(gl::Framebuffer *framebuffer, const RECT &sourceRect, GLenum destFormat, GLint xoffset, GLint yoffset, TextureStorageCubeMap *storage, GLenum target, GLint level)
daniel@transgaming.com3cef5392012-10-31 19:52:15 +0000239{
240 // D3D9_REPLACE
241 IDirect3DSurface9 *source = framebuffer->getRenderTarget();
242 if (!source)
243 {
244 ERR("Failed to retrieve the render target.");
245 return error(GL_OUT_OF_MEMORY, false);
246 }
247
248 IDirect3DSurface9 *destSurface = storage->getCubeMapSurface(target, level, true);
249 bool result = false;
250
251 if (destSurface)
252 {
253 result = copy(source, sourceRect, destFormat, xoffset, yoffset, destSurface);
254 destSurface->Release();
255 }
256
257 source->Release();
258 return result;
259}
260
261bool Blit::copy(IDirect3DSurface9 *source, const RECT &sourceRect, GLenum destFormat, GLint xoffset, GLint yoffset, IDirect3DSurface9 *dest)
262{
263 if (!dest)
264 {
265 return false;
266 }
267
daniel@transgaming.come4733d72012-10-31 18:07:01 +0000268 IDirect3DDevice9 *device = mRenderer->getDevice();
daniel@transgaming.comeef864a2011-04-22 11:33:27 +0000269
270 D3DSURFACE_DESC sourceDesc;
271 D3DSURFACE_DESC destDesc;
272 source->GetDesc(&sourceDesc);
273 dest->GetDesc(&destDesc);
274
daniel@transgaming.comad52cb12012-10-17 18:14:45 +0000275 if (sourceDesc.Format == destDesc.Format && destDesc.Usage & D3DUSAGE_RENDERTARGET &&
daniel@transgaming.com682a37c2012-11-28 19:34:44 +0000276 d3d9_gl::IsFormatChannelEquivalent(destDesc.Format, destFormat)) // Can use StretchRect
daniel@transgaming.comeef864a2011-04-22 11:33:27 +0000277 {
278 RECT destRect = {xoffset, yoffset, xoffset + (sourceRect.right - sourceRect.left), yoffset + (sourceRect.bottom - sourceRect.top)};
279 HRESULT result = device->StretchRect(source, &sourceRect, dest, &destRect, D3DTEXF_POINT);
280
281 if (FAILED(result))
282 {
283 ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
284 return error(GL_OUT_OF_MEMORY, false);
285 }
286 }
287 else
288 {
289 return formatConvert(source, sourceRect, destFormat, xoffset, yoffset, dest);
290 }
daniel@transgaming.comeef864a2011-04-22 11:33:27 +0000291 return true;
292}
293
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000294bool Blit::formatConvert(IDirect3DSurface9 *source, const RECT &sourceRect, GLenum destFormat, GLint xoffset, GLint yoffset, IDirect3DSurface9 *dest)
295{
296 IDirect3DTexture9 *texture = copySurfaceToTexture(source, sourceRect);
297 if (!texture)
298 {
299 return false;
300 }
301
daniel@transgaming.com621ce052012-10-31 17:52:29 +0000302 // D3D9_REPLACE
daniel@transgaming.come4733d72012-10-31 18:07:01 +0000303 IDirect3DDevice9 *device = mRenderer->getDevice();
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000304
daniel@transgaming.com1ddd1dd2010-05-11 02:29:34 +0000305 saveState();
306
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000307 device->SetTexture(0, texture);
308 device->SetRenderTarget(0, dest);
309
daniel@transgaming.com8fd99e22010-04-20 18:52:00 +0000310 setViewport(sourceRect, xoffset, yoffset);
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000311
312 setCommonBlitState();
313 if (setFormatConvertShaders(destFormat))
314 {
315 render();
316 }
317
318 texture->Release();
319
daniel@transgaming.com1ddd1dd2010-05-11 02:29:34 +0000320 restoreState();
321
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000322 return true;
323}
324
325bool Blit::setFormatConvertShaders(GLenum destFormat)
326{
327 bool okay = setVertexShader(SHADER_VS_STANDARD);
328
329 switch (destFormat)
330 {
331 default: UNREACHABLE();
332 case GL_RGBA:
daniel@transgaming.coma9198d92010-08-08 04:49:56 +0000333 case GL_BGRA_EXT:
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000334 case GL_RGB:
335 case GL_ALPHA:
336 okay = okay && setPixelShader(SHADER_PS_COMPONENTMASK);
337 break;
338
339 case GL_LUMINANCE:
340 case GL_LUMINANCE_ALPHA:
341 okay = okay && setPixelShader(SHADER_PS_LUMINANCE);
342 break;
343 }
344
345 if (!okay)
346 {
347 return false;
348 }
349
350 enum { X = 0, Y = 1, Z = 2, W = 3 };
351
352 // The meaning of this constant depends on the shader that was selected.
353 // See the shader assembly code above for details.
354 float psConst0[4] = { 0, 0, 0, 0 };
355
356 switch (destFormat)
357 {
358 default: UNREACHABLE();
359 case GL_RGBA:
daniel@transgaming.coma9198d92010-08-08 04:49:56 +0000360 case GL_BGRA_EXT:
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000361 psConst0[X] = 1;
362 psConst0[Z] = 1;
363 break;
364
365 case GL_RGB:
366 psConst0[X] = 1;
367 psConst0[W] = 1;
368 break;
369
370 case GL_ALPHA:
371 psConst0[Z] = 1;
372 break;
373
374 case GL_LUMINANCE:
375 psConst0[Y] = 1;
376 break;
377
378 case GL_LUMINANCE_ALPHA:
379 psConst0[X] = 1;
380 break;
381 }
382
daniel@transgaming.come4733d72012-10-31 18:07:01 +0000383 mRenderer->getDevice()->SetPixelShaderConstantF(0, psConst0, 1); // D3D9_REPLACE
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000384
385 return true;
386}
387
daniel@transgaming.com621ce052012-10-31 17:52:29 +0000388// D3D9_REPLACE
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000389IDirect3DTexture9 *Blit::copySurfaceToTexture(IDirect3DSurface9 *surface, const RECT &sourceRect)
390{
daniel@transgaming.comd36c6a02010-08-31 12:15:09 +0000391 if (!surface)
392 {
393 return NULL;
394 }
395
daniel@transgaming.come4733d72012-10-31 18:07:01 +0000396 IDirect3DDevice9 *device = mRenderer->getDevice(); // D3D9_REPLACE
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000397
398 D3DSURFACE_DESC sourceDesc;
399 surface->GetDesc(&sourceDesc);
400
401 // Copy the render target into a texture
402 IDirect3DTexture9 *texture;
daniel@transgaming.com8fd99e22010-04-20 18:52:00 +0000403 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 +0000404
405 if (FAILED(result))
406 {
407 ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
408 return error(GL_OUT_OF_MEMORY, (IDirect3DTexture9*)NULL);
409 }
410
411 IDirect3DSurface9 *textureSurface;
412 result = texture->GetSurfaceLevel(0, &textureSurface);
413
414 if (FAILED(result))
415 {
416 ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
417 texture->Release();
418 return error(GL_OUT_OF_MEMORY, (IDirect3DTexture9*)NULL);
419 }
420
daniel@transgaming.come4733d72012-10-31 18:07:01 +0000421 mRenderer->endScene();
daniel@transgaming.com4c5142c2010-10-15 17:58:27 +0000422 result = device->StretchRect(surface, &sourceRect, textureSurface, NULL, D3DTEXF_NONE);
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000423
424 textureSurface->Release();
425
426 if (FAILED(result))
427 {
428 ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
429 texture->Release();
430 return error(GL_OUT_OF_MEMORY, (IDirect3DTexture9*)NULL);
431 }
432
433 return texture;
434}
435
daniel@transgaming.com8fd99e22010-04-20 18:52:00 +0000436void Blit::setViewport(const RECT &sourceRect, GLint xoffset, GLint yoffset)
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000437{
daniel@transgaming.come4733d72012-10-31 18:07:01 +0000438 IDirect3DDevice9 *device = mRenderer->getDevice(); // D3D9_REPLACE
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000439
440 D3DVIEWPORT9 vp;
441 vp.X = xoffset;
442 vp.Y = yoffset;
443 vp.Width = sourceRect.right - sourceRect.left;
daniel@transgaming.com8fd99e22010-04-20 18:52:00 +0000444 vp.Height = sourceRect.bottom - sourceRect.top;
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000445 vp.MinZ = 0.0f;
446 vp.MaxZ = 1.0f;
447 device->SetViewport(&vp);
448
449 float halfPixelAdjust[4] = { -1.0f/vp.Width, 1.0f/vp.Height, 0, 0 };
450 device->SetVertexShaderConstantF(0, halfPixelAdjust, 1);
451}
452
daniel@transgaming.com621ce052012-10-31 17:52:29 +0000453// D3D9_REPLACE
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000454void Blit::setCommonBlitState()
455{
daniel@transgaming.come4733d72012-10-31 18:07:01 +0000456 IDirect3DDevice9 *device = mRenderer->getDevice();
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000457
458 device->SetDepthStencilSurface(NULL);
459
460 device->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID);
461 device->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE);
462 device->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
463 device->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
464 device->SetRenderState(D3DRS_CLIPPLANEENABLE, 0);
465 device->SetRenderState(D3DRS_COLORWRITEENABLE, D3DCOLORWRITEENABLE_ALPHA | D3DCOLORWRITEENABLE_BLUE | D3DCOLORWRITEENABLE_GREEN | D3DCOLORWRITEENABLE_RED);
466 device->SetRenderState(D3DRS_SRGBWRITEENABLE, FALSE);
467 device->SetRenderState(D3DRS_SCISSORTESTENABLE, FALSE);
468
469 device->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_POINT);
470 device->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_POINT);
471 device->SetSamplerState(0, D3DSAMP_SRGBTEXTURE, FALSE);
daniel@transgaming.com8fd99e22010-04-20 18:52:00 +0000472 device->SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP);
473 device->SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP);
daniel@transgaming.com81655a72010-05-20 19:18:17 +0000474
daniel@transgaming.com74d760b2010-11-03 12:27:18 +0000475 RECT scissorRect = {0}; // Scissoring is disabled for flipping, but we need this to capture and restore the old rectangle
476 device->SetScissorRect(&scissorRect);
daniel@transgaming.com8ca9c6e2012-01-27 15:38:54 +0000477
daniel@transgaming.comde8a7ff2012-11-28 19:34:13 +0000478 for(int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++)
daniel@transgaming.com8ca9c6e2012-01-27 15:38:54 +0000479 {
480 device->SetStreamSourceFreq(i, 1);
481 }
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000482}
483
daniel@transgaming.com621ce052012-10-31 17:52:29 +0000484// D3D9_REPLACE
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000485void Blit::render()
486{
daniel@transgaming.come4733d72012-10-31 18:07:01 +0000487 IDirect3DDevice9 *device = mRenderer->getDevice();
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000488
489 HRESULT hr = device->SetStreamSource(0, mQuadVertexBuffer, 0, 2 * sizeof(float));
490 hr = device->SetVertexDeclaration(mQuadVertexDeclaration);
491
daniel@transgaming.come4733d72012-10-31 18:07:01 +0000492 mRenderer->startScene();
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000493 hr = device->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2);
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000494}
495
daniel@transgaming.com621ce052012-10-31 17:52:29 +0000496// D3D9_REPLACE
daniel@transgaming.com1ddd1dd2010-05-11 02:29:34 +0000497void Blit::saveState()
498{
daniel@transgaming.come4733d72012-10-31 18:07:01 +0000499 IDirect3DDevice9 *device = mRenderer->getDevice();
daniel@transgaming.com1ddd1dd2010-05-11 02:29:34 +0000500
501 HRESULT hr;
502
503 device->GetDepthStencilSurface(&mSavedDepthStencil);
504 device->GetRenderTarget(0, &mSavedRenderTarget);
505
506 if (mSavedStateBlock == NULL)
507 {
508 hr = device->BeginStateBlock();
509 ASSERT(SUCCEEDED(hr) || hr == D3DERR_OUTOFVIDEOMEMORY || hr == E_OUTOFMEMORY);
510
511 setCommonBlitState();
512
513 static const float dummyConst[4] = { 0, 0, 0, 0 };
514
515 device->SetVertexShader(NULL);
516 device->SetVertexShaderConstantF(0, dummyConst, 1);
517 device->SetPixelShader(NULL);
518 device->SetPixelShaderConstantF(0, dummyConst, 1);
519
520 D3DVIEWPORT9 dummyVp;
521 dummyVp.X = 0;
522 dummyVp.Y = 0;
523 dummyVp.Width = 1;
524 dummyVp.Height = 1;
525 dummyVp.MinZ = 0;
526 dummyVp.MaxZ = 1;
527
528 device->SetViewport(&dummyVp);
529
530 device->SetTexture(0, NULL);
531
532 device->SetStreamSource(0, mQuadVertexBuffer, 0, 0);
533
534 device->SetVertexDeclaration(mQuadVertexDeclaration);
535
536 hr = device->EndStateBlock(&mSavedStateBlock);
537 ASSERT(SUCCEEDED(hr) || hr == D3DERR_OUTOFVIDEOMEMORY || hr == E_OUTOFMEMORY);
538 }
539
540 ASSERT(mSavedStateBlock != NULL);
541
542 if (mSavedStateBlock != NULL)
543 {
544 hr = mSavedStateBlock->Capture();
545 ASSERT(SUCCEEDED(hr));
546 }
547}
548
daniel@transgaming.com621ce052012-10-31 17:52:29 +0000549// D3D9_REPLACE
daniel@transgaming.com1ddd1dd2010-05-11 02:29:34 +0000550void Blit::restoreState()
551{
daniel@transgaming.come4733d72012-10-31 18:07:01 +0000552 IDirect3DDevice9 *device = mRenderer->getDevice();
daniel@transgaming.com1ddd1dd2010-05-11 02:29:34 +0000553
554 device->SetDepthStencilSurface(mSavedDepthStencil);
555 if (mSavedDepthStencil != NULL)
556 {
557 mSavedDepthStencil->Release();
558 mSavedDepthStencil = NULL;
559 }
560
561 device->SetRenderTarget(0, mSavedRenderTarget);
562 if (mSavedRenderTarget != NULL)
563 {
564 mSavedRenderTarget->Release();
565 mSavedRenderTarget = NULL;
566 }
567
568 ASSERT(mSavedStateBlock != NULL);
569
570 if (mSavedStateBlock != NULL)
571 {
572 mSavedStateBlock->Apply();
573 }
574}
575
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000576}