blob: ec23121354f62087a98c3d2add358288971253ac [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.com204677a2013-01-11 21:16:09 +000015#include "libGLESv2/renderer/renderer9_utils.h"
16#include "libGLESv2/renderer/TextureStorage9.h"
17#include "libGLESv2/renderer/RenderTarget9.h"
daniel@transgaming.com3cef5392012-10-31 19:52:15 +000018#include "libGLESv2/Framebuffer.h"
daniel@transgaming.combbf56f72010-04-20 18:52:13 +000019
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +000020namespace
21{
daniel@transgaming.com8dc8e272013-01-11 04:10:45 +000022#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"
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +000027
apatrick@chromium.org99fbbe82012-07-19 19:11:24 +000028const 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};
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +000036
apatrick@chromium.org99fbbe82012-07-19 19:11:24 +000037const 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};
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +000045}
46
daniel@transgaming.comde8a7ff2012-11-28 19:34:13 +000047namespace rx
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +000048{
daniel@transgaming.com76d3e6e2012-10-31 19:55:33 +000049Blit::Blit(rx::Renderer9 *renderer)
daniel@transgaming.come3e826d2012-11-28 19:42:35 +000050 : mRenderer(renderer), mQuadVertexBuffer(NULL), mQuadVertexDeclaration(NULL), mSavedStateBlock(NULL), mSavedRenderTarget(NULL), mSavedDepthStencil(NULL)
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +000051{
52 initGeometry();
53 memset(mCompiledShaders, 0, sizeof(mCompiledShaders));
54}
55
56Blit::~Blit()
57{
daniel@transgaming.com1ddd1dd2010-05-11 02:29:34 +000058 if (mSavedStateBlock) mSavedStateBlock->Release();
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +000059 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
71void 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.com204677a2013-01-11 21:16:09 +0000123 IDirect3DDevice9 *device = mRenderer->getDevice();
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.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.com87705f82012-12-20 21:10:45 +0000214bool Blit::copy(gl::Framebuffer *framebuffer, const RECT &sourceRect, GLenum destFormat, GLint xoffset, GLint yoffset, TextureStorageInterface2D *storage, GLint level)
daniel@transgaming.comeef864a2011-04-22 11:33:27 +0000215{
daniel@transgaming.comd186dc72012-11-28 19:40:16 +0000216 RenderTarget9 *renderTarget = NULL;
217 IDirect3DSurface9 *source = NULL;
218 gl::Renderbuffer *colorbuffer = framebuffer->getColorbuffer();
219
220 if (colorbuffer)
221 {
222 renderTarget = RenderTarget9::makeRenderTarget9(colorbuffer->getRenderTarget());
223 }
224
225 if (renderTarget)
226 {
227 source = renderTarget->getSurface();
228 }
229
daniel@transgaming.com3cef5392012-10-31 19:52:15 +0000230 if (!source)
231 {
232 ERR("Failed to retrieve the render target.");
233 return error(GL_OUT_OF_MEMORY, false);
234 }
235
daniel@transgaming.com87705f82012-12-20 21:10:45 +0000236 TextureStorage9_2D *storage9 = TextureStorage9_2D::makeTextureStorage9_2D(storage->getStorageInstance());
daniel@transgaming.com34da3972012-12-20 21:10:29 +0000237 IDirect3DSurface9 *destSurface = storage9->getSurfaceLevel(level, true);
daniel@transgaming.com3cef5392012-10-31 19:52:15 +0000238 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
daniel@transgaming.com87705f82012-12-20 21:10:45 +0000250bool Blit::copy(gl::Framebuffer *framebuffer, const RECT &sourceRect, GLenum destFormat, GLint xoffset, GLint yoffset, TextureStorageInterfaceCube *storage, GLenum target, GLint level)
daniel@transgaming.com3cef5392012-10-31 19:52:15 +0000251{
daniel@transgaming.comd186dc72012-11-28 19:40:16 +0000252 RenderTarget9 *renderTarget = NULL;
253 IDirect3DSurface9 *source = NULL;
254 gl::Renderbuffer *colorbuffer = framebuffer->getColorbuffer();
255
256 if (colorbuffer)
257 {
258 renderTarget = RenderTarget9::makeRenderTarget9(colorbuffer->getRenderTarget());
259 }
260
261 if (renderTarget)
262 {
263 source = renderTarget->getSurface();
264 }
265
daniel@transgaming.com3cef5392012-10-31 19:52:15 +0000266 if (!source)
267 {
268 ERR("Failed to retrieve the render target.");
269 return error(GL_OUT_OF_MEMORY, false);
270 }
271
daniel@transgaming.com87705f82012-12-20 21:10:45 +0000272 TextureStorage9_Cube *storage9 = TextureStorage9_Cube::makeTextureStorage9_Cube(storage->getStorageInstance());
daniel@transgaming.com34da3972012-12-20 21:10:29 +0000273 IDirect3DSurface9 *destSurface = storage9->getCubeMapSurface(target, level, true);
daniel@transgaming.com3cef5392012-10-31 19:52:15 +0000274 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
286bool 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
daniel@transgaming.come4733d72012-10-31 18:07:01 +0000293 IDirect3DDevice9 *device = mRenderer->getDevice();
daniel@transgaming.comeef864a2011-04-22 11:33:27 +0000294
295 D3DSURFACE_DESC sourceDesc;
296 D3DSURFACE_DESC destDesc;
297 source->GetDesc(&sourceDesc);
298 dest->GetDesc(&destDesc);
299
daniel@transgaming.comad52cb12012-10-17 18:14:45 +0000300 if (sourceDesc.Format == destDesc.Format && destDesc.Usage & D3DUSAGE_RENDERTARGET &&
daniel@transgaming.com682a37c2012-11-28 19:34:44 +0000301 d3d9_gl::IsFormatChannelEquivalent(destDesc.Format, destFormat)) // Can use StretchRect
daniel@transgaming.comeef864a2011-04-22 11:33:27 +0000302 {
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 error(GL_OUT_OF_MEMORY, false);
310 }
311 }
312 else
313 {
314 return formatConvert(source, sourceRect, destFormat, xoffset, yoffset, dest);
315 }
daniel@transgaming.comeef864a2011-04-22 11:33:27 +0000316 return true;
317}
318
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000319bool 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
daniel@transgaming.come4733d72012-10-31 18:07:01 +0000327 IDirect3DDevice9 *device = mRenderer->getDevice();
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000328
daniel@transgaming.com1ddd1dd2010-05-11 02:29:34 +0000329 saveState();
330
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000331 device->SetTexture(0, texture);
332 device->SetRenderTarget(0, dest);
333
daniel@transgaming.com8fd99e22010-04-20 18:52:00 +0000334 setViewport(sourceRect, xoffset, yoffset);
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000335
336 setCommonBlitState();
337 if (setFormatConvertShaders(destFormat))
338 {
339 render();
340 }
341
342 texture->Release();
343
daniel@transgaming.com1ddd1dd2010-05-11 02:29:34 +0000344 restoreState();
345
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000346 return true;
347}
348
349bool Blit::setFormatConvertShaders(GLenum destFormat)
350{
351 bool okay = setVertexShader(SHADER_VS_STANDARD);
352
353 switch (destFormat)
354 {
355 default: UNREACHABLE();
356 case GL_RGBA:
daniel@transgaming.coma9198d92010-08-08 04:49:56 +0000357 case GL_BGRA_EXT:
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000358 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:
daniel@transgaming.coma9198d92010-08-08 04:49:56 +0000384 case GL_BGRA_EXT:
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000385 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
daniel@transgaming.com204677a2013-01-11 21:16:09 +0000407 mRenderer->getDevice()->SetPixelShaderConstantF(0, psConst0, 1);
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000408
409 return true;
410}
411
412IDirect3DTexture9 *Blit::copySurfaceToTexture(IDirect3DSurface9 *surface, const RECT &sourceRect)
413{
daniel@transgaming.comd36c6a02010-08-31 12:15:09 +0000414 if (!surface)
415 {
416 return NULL;
417 }
418
daniel@transgaming.com204677a2013-01-11 21:16:09 +0000419 IDirect3DDevice9 *device = mRenderer->getDevice();
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000420
421 D3DSURFACE_DESC sourceDesc;
422 surface->GetDesc(&sourceDesc);
423
424 // Copy the render target into a texture
425 IDirect3DTexture9 *texture;
daniel@transgaming.com8fd99e22010-04-20 18:52:00 +0000426 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 +0000427
428 if (FAILED(result))
429 {
430 ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
431 return 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 error(GL_OUT_OF_MEMORY, (IDirect3DTexture9*)NULL);
442 }
443
daniel@transgaming.come4733d72012-10-31 18:07:01 +0000444 mRenderer->endScene();
daniel@transgaming.com4c5142c2010-10-15 17:58:27 +0000445 result = device->StretchRect(surface, &sourceRect, textureSurface, NULL, D3DTEXF_NONE);
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000446
447 textureSurface->Release();
448
449 if (FAILED(result))
450 {
451 ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
452 texture->Release();
453 return error(GL_OUT_OF_MEMORY, (IDirect3DTexture9*)NULL);
454 }
455
456 return texture;
457}
458
daniel@transgaming.com8fd99e22010-04-20 18:52:00 +0000459void Blit::setViewport(const RECT &sourceRect, GLint xoffset, GLint yoffset)
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000460{
daniel@transgaming.com204677a2013-01-11 21:16:09 +0000461 IDirect3DDevice9 *device = mRenderer->getDevice();
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000462
463 D3DVIEWPORT9 vp;
464 vp.X = xoffset;
465 vp.Y = yoffset;
466 vp.Width = sourceRect.right - sourceRect.left;
daniel@transgaming.com8fd99e22010-04-20 18:52:00 +0000467 vp.Height = sourceRect.bottom - sourceRect.top;
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000468 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
476void Blit::setCommonBlitState()
477{
daniel@transgaming.come4733d72012-10-31 18:07:01 +0000478 IDirect3DDevice9 *device = mRenderer->getDevice();
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000479
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);
daniel@transgaming.com8fd99e22010-04-20 18:52:00 +0000494 device->SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP);
495 device->SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP);
daniel@transgaming.com81655a72010-05-20 19:18:17 +0000496
daniel@transgaming.com74d760b2010-11-03 12:27:18 +0000497 RECT scissorRect = {0}; // Scissoring is disabled for flipping, but we need this to capture and restore the old rectangle
498 device->SetScissorRect(&scissorRect);
daniel@transgaming.com8ca9c6e2012-01-27 15:38:54 +0000499
daniel@transgaming.comde8a7ff2012-11-28 19:34:13 +0000500 for(int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++)
daniel@transgaming.com8ca9c6e2012-01-27 15:38:54 +0000501 {
502 device->SetStreamSourceFreq(i, 1);
503 }
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000504}
505
506void Blit::render()
507{
daniel@transgaming.come4733d72012-10-31 18:07:01 +0000508 IDirect3DDevice9 *device = mRenderer->getDevice();
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000509
510 HRESULT hr = device->SetStreamSource(0, mQuadVertexBuffer, 0, 2 * sizeof(float));
511 hr = device->SetVertexDeclaration(mQuadVertexDeclaration);
512
daniel@transgaming.come4733d72012-10-31 18:07:01 +0000513 mRenderer->startScene();
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000514 hr = device->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2);
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000515}
516
daniel@transgaming.com1ddd1dd2010-05-11 02:29:34 +0000517void Blit::saveState()
518{
daniel@transgaming.come4733d72012-10-31 18:07:01 +0000519 IDirect3DDevice9 *device = mRenderer->getDevice();
daniel@transgaming.com1ddd1dd2010-05-11 02:29:34 +0000520
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
569void Blit::restoreState()
570{
daniel@transgaming.come4733d72012-10-31 18:07:01 +0000571 IDirect3DDevice9 *device = mRenderer->getDevice();
daniel@transgaming.com1ddd1dd2010-05-11 02:29:34 +0000572
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
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000595}