blob: c7def67eed3de28383543e7512e8169051e908d2 [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.com34da3972012-12-20 21:10:29 +000016#include "libGLESv2/renderer/TextureStorage9.h" // D3D9_REPLACE
17#include "libGLESv2/renderer/RenderTarget9.h" // D3D9_REPLACE
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
daniel@transgaming.com621ce052012-10-31 17:52:29 +000071// D3D9_REPLACE
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +000072void Blit::initGeometry()
73{
74 static const float quad[] =
75 {
76 -1, -1,
77 -1, 1,
78 1, -1,
79 1, 1
80 };
81
daniel@transgaming.come4733d72012-10-31 18:07:01 +000082 IDirect3DDevice9 *device = mRenderer->getDevice();
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +000083
daniel@transgaming.comaa614602011-04-28 16:20:58 +000084 HRESULT result = device->CreateVertexBuffer(sizeof(quad), D3DUSAGE_WRITEONLY, 0, D3DPOOL_DEFAULT, &mQuadVertexBuffer, NULL);
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +000085
daniel@transgaming.comaa614602011-04-28 16:20:58 +000086 if (FAILED(result))
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +000087 {
daniel@transgaming.comaa614602011-04-28 16:20:58 +000088 ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +000089 return error(GL_OUT_OF_MEMORY);
90 }
91
daniel@transgaming.comaa614602011-04-28 16:20:58 +000092 void *lockPtr = NULL;
93 result = mQuadVertexBuffer->Lock(0, 0, &lockPtr, 0);
94
95 if (FAILED(result) || lockPtr == NULL)
96 {
97 ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
98 return error(GL_OUT_OF_MEMORY);
99 }
100
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000101 memcpy(lockPtr, quad, sizeof(quad));
102 mQuadVertexBuffer->Unlock();
103
104 static const D3DVERTEXELEMENT9 elements[] =
105 {
106 { 0, 0, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0 },
107 D3DDECL_END()
108 };
109
daniel@transgaming.comaa614602011-04-28 16:20:58 +0000110 result = device->CreateVertexDeclaration(elements, &mQuadVertexDeclaration);
111
112 if (FAILED(result))
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000113 {
daniel@transgaming.comaa614602011-04-28 16:20:58 +0000114 ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000115 return error(GL_OUT_OF_MEMORY);
116 }
117}
118
119template <class D3DShaderType>
120bool Blit::setShader(ShaderId source, const char *profile,
daniel@transgaming.com76d3e6e2012-10-31 19:55:33 +0000121 D3DShaderType *(rx::Renderer9::*createShader)(const DWORD *, size_t length),
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000122 HRESULT (WINAPI IDirect3DDevice9::*setShader)(D3DShaderType*))
123{
daniel@transgaming.come4733d72012-10-31 18:07:01 +0000124 IDirect3DDevice9 *device = mRenderer->getDevice(); // D3D9_REPLACE
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000125
126 D3DShaderType *shader;
127
128 if (mCompiledShaders[source] != NULL)
129 {
130 shader = static_cast<D3DShaderType*>(mCompiledShaders[source]);
131 }
132 else
133 {
apatrick@chromium.org99fbbe82012-07-19 19:11:24 +0000134 const BYTE* shaderCode = g_shaderCode[source];
135 size_t shaderSize = g_shaderSize[source];
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000136
daniel@transgaming.come4733d72012-10-31 18:07:01 +0000137 shader = (mRenderer->*createShader)(reinterpret_cast<const DWORD*>(shaderCode), shaderSize);
apatrick@chromium.org99fbbe82012-07-19 19:11:24 +0000138 if (!shader)
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000139 {
apatrick@chromium.org99fbbe82012-07-19 19:11:24 +0000140 ERR("Failed to create shader for blit operation");
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000141 return false;
142 }
143
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000144 mCompiledShaders[source] = shader;
145 }
146
147 HRESULT hr = (device->*setShader)(shader);
148
149 if (FAILED(hr))
150 {
apatrick@chromium.org99fbbe82012-07-19 19:11:24 +0000151 ERR("Failed to set shader for blit operation");
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000152 return false;
153 }
154
155 return true;
156}
157
158bool Blit::setVertexShader(ShaderId shader)
159{
daniel@transgaming.com76d3e6e2012-10-31 19:55:33 +0000160 return setShader<IDirect3DVertexShader9>(shader, "vs_2_0", &rx::Renderer9::createVertexShader, &IDirect3DDevice9::SetVertexShader);
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000161}
162
163bool Blit::setPixelShader(ShaderId shader)
164{
daniel@transgaming.com76d3e6e2012-10-31 19:55:33 +0000165 return setShader<IDirect3DPixelShader9>(shader, "ps_2_0", &rx::Renderer9::createPixelShader, &IDirect3DDevice9::SetPixelShader);
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000166}
167
daniel@transgaming.com8fd99e22010-04-20 18:52:00 +0000168RECT Blit::getSurfaceRect(IDirect3DSurface9 *surface) const
169{
170 D3DSURFACE_DESC desc;
171 surface->GetDesc(&desc);
172
173 RECT rect;
174 rect.left = 0;
175 rect.top = 0;
176 rect.right = desc.Width;
177 rect.bottom = desc.Height;
178
179 return rect;
180}
181
182bool Blit::boxFilter(IDirect3DSurface9 *source, IDirect3DSurface9 *dest)
183{
184 IDirect3DTexture9 *texture = copySurfaceToTexture(source, getSurfaceRect(source));
185 if (!texture)
186 {
187 return false;
188 }
189
daniel@transgaming.com621ce052012-10-31 17:52:29 +0000190 // D3D9_REPLACE
daniel@transgaming.come4733d72012-10-31 18:07:01 +0000191 IDirect3DDevice9 *device = mRenderer->getDevice();
daniel@transgaming.com1ddd1dd2010-05-11 02:29:34 +0000192
193 saveState();
194
daniel@transgaming.com8fd99e22010-04-20 18:52:00 +0000195 device->SetTexture(0, texture);
196 device->SetRenderTarget(0, dest);
197
198 setVertexShader(SHADER_VS_STANDARD);
199 setPixelShader(SHADER_PS_PASSTHROUGH);
200
201 setCommonBlitState();
202 device->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
203 device->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
204
205 setViewport(getSurfaceRect(dest), 0, 0);
206
207 render();
208
209 texture->Release();
210
daniel@transgaming.com1ddd1dd2010-05-11 02:29:34 +0000211 restoreState();
212
daniel@transgaming.com8fd99e22010-04-20 18:52:00 +0000213 return true;
214}
215
daniel@transgaming.com87705f82012-12-20 21:10:45 +0000216bool 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 +0000217{
daniel@transgaming.com621ce052012-10-31 17:52:29 +0000218 // D3D9_REPLACE
daniel@transgaming.comd186dc72012-11-28 19:40:16 +0000219 RenderTarget9 *renderTarget = NULL;
220 IDirect3DSurface9 *source = NULL;
221 gl::Renderbuffer *colorbuffer = framebuffer->getColorbuffer();
222
223 if (colorbuffer)
224 {
225 renderTarget = RenderTarget9::makeRenderTarget9(colorbuffer->getRenderTarget());
226 }
227
228 if (renderTarget)
229 {
230 source = renderTarget->getSurface();
231 }
232
daniel@transgaming.com3cef5392012-10-31 19:52:15 +0000233 if (!source)
234 {
235 ERR("Failed to retrieve the render target.");
236 return error(GL_OUT_OF_MEMORY, false);
237 }
238
daniel@transgaming.com87705f82012-12-20 21:10:45 +0000239 TextureStorage9_2D *storage9 = TextureStorage9_2D::makeTextureStorage9_2D(storage->getStorageInstance());
daniel@transgaming.com34da3972012-12-20 21:10:29 +0000240 IDirect3DSurface9 *destSurface = storage9->getSurfaceLevel(level, true);
daniel@transgaming.com3cef5392012-10-31 19:52:15 +0000241 bool result = false;
242
243 if (destSurface)
244 {
245 result = copy(source, sourceRect, destFormat, xoffset, yoffset, destSurface);
246 destSurface->Release();
247 }
248
249 source->Release();
250 return result;
251}
252
daniel@transgaming.com87705f82012-12-20 21:10:45 +0000253bool 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 +0000254{
255 // D3D9_REPLACE
daniel@transgaming.comd186dc72012-11-28 19:40:16 +0000256 RenderTarget9 *renderTarget = NULL;
257 IDirect3DSurface9 *source = NULL;
258 gl::Renderbuffer *colorbuffer = framebuffer->getColorbuffer();
259
260 if (colorbuffer)
261 {
262 renderTarget = RenderTarget9::makeRenderTarget9(colorbuffer->getRenderTarget());
263 }
264
265 if (renderTarget)
266 {
267 source = renderTarget->getSurface();
268 }
269
daniel@transgaming.com3cef5392012-10-31 19:52:15 +0000270 if (!source)
271 {
272 ERR("Failed to retrieve the render target.");
273 return error(GL_OUT_OF_MEMORY, false);
274 }
275
daniel@transgaming.com87705f82012-12-20 21:10:45 +0000276 TextureStorage9_Cube *storage9 = TextureStorage9_Cube::makeTextureStorage9_Cube(storage->getStorageInstance());
daniel@transgaming.com34da3972012-12-20 21:10:29 +0000277 IDirect3DSurface9 *destSurface = storage9->getCubeMapSurface(target, level, true);
daniel@transgaming.com3cef5392012-10-31 19:52:15 +0000278 bool result = false;
279
280 if (destSurface)
281 {
282 result = copy(source, sourceRect, destFormat, xoffset, yoffset, destSurface);
283 destSurface->Release();
284 }
285
286 source->Release();
287 return result;
288}
289
290bool Blit::copy(IDirect3DSurface9 *source, const RECT &sourceRect, GLenum destFormat, GLint xoffset, GLint yoffset, IDirect3DSurface9 *dest)
291{
292 if (!dest)
293 {
294 return false;
295 }
296
daniel@transgaming.come4733d72012-10-31 18:07:01 +0000297 IDirect3DDevice9 *device = mRenderer->getDevice();
daniel@transgaming.comeef864a2011-04-22 11:33:27 +0000298
299 D3DSURFACE_DESC sourceDesc;
300 D3DSURFACE_DESC destDesc;
301 source->GetDesc(&sourceDesc);
302 dest->GetDesc(&destDesc);
303
daniel@transgaming.comad52cb12012-10-17 18:14:45 +0000304 if (sourceDesc.Format == destDesc.Format && destDesc.Usage & D3DUSAGE_RENDERTARGET &&
daniel@transgaming.com682a37c2012-11-28 19:34:44 +0000305 d3d9_gl::IsFormatChannelEquivalent(destDesc.Format, destFormat)) // Can use StretchRect
daniel@transgaming.comeef864a2011-04-22 11:33:27 +0000306 {
307 RECT destRect = {xoffset, yoffset, xoffset + (sourceRect.right - sourceRect.left), yoffset + (sourceRect.bottom - sourceRect.top)};
308 HRESULT result = device->StretchRect(source, &sourceRect, dest, &destRect, D3DTEXF_POINT);
309
310 if (FAILED(result))
311 {
312 ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
313 return error(GL_OUT_OF_MEMORY, false);
314 }
315 }
316 else
317 {
318 return formatConvert(source, sourceRect, destFormat, xoffset, yoffset, dest);
319 }
daniel@transgaming.comeef864a2011-04-22 11:33:27 +0000320 return true;
321}
322
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000323bool Blit::formatConvert(IDirect3DSurface9 *source, const RECT &sourceRect, GLenum destFormat, GLint xoffset, GLint yoffset, IDirect3DSurface9 *dest)
324{
325 IDirect3DTexture9 *texture = copySurfaceToTexture(source, sourceRect);
326 if (!texture)
327 {
328 return false;
329 }
330
daniel@transgaming.com621ce052012-10-31 17:52:29 +0000331 // D3D9_REPLACE
daniel@transgaming.come4733d72012-10-31 18:07:01 +0000332 IDirect3DDevice9 *device = mRenderer->getDevice();
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000333
daniel@transgaming.com1ddd1dd2010-05-11 02:29:34 +0000334 saveState();
335
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000336 device->SetTexture(0, texture);
337 device->SetRenderTarget(0, dest);
338
daniel@transgaming.com8fd99e22010-04-20 18:52:00 +0000339 setViewport(sourceRect, xoffset, yoffset);
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000340
341 setCommonBlitState();
342 if (setFormatConvertShaders(destFormat))
343 {
344 render();
345 }
346
347 texture->Release();
348
daniel@transgaming.com1ddd1dd2010-05-11 02:29:34 +0000349 restoreState();
350
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000351 return true;
352}
353
354bool Blit::setFormatConvertShaders(GLenum destFormat)
355{
356 bool okay = setVertexShader(SHADER_VS_STANDARD);
357
358 switch (destFormat)
359 {
360 default: UNREACHABLE();
361 case GL_RGBA:
daniel@transgaming.coma9198d92010-08-08 04:49:56 +0000362 case GL_BGRA_EXT:
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000363 case GL_RGB:
364 case GL_ALPHA:
365 okay = okay && setPixelShader(SHADER_PS_COMPONENTMASK);
366 break;
367
368 case GL_LUMINANCE:
369 case GL_LUMINANCE_ALPHA:
370 okay = okay && setPixelShader(SHADER_PS_LUMINANCE);
371 break;
372 }
373
374 if (!okay)
375 {
376 return false;
377 }
378
379 enum { X = 0, Y = 1, Z = 2, W = 3 };
380
381 // The meaning of this constant depends on the shader that was selected.
382 // See the shader assembly code above for details.
383 float psConst0[4] = { 0, 0, 0, 0 };
384
385 switch (destFormat)
386 {
387 default: UNREACHABLE();
388 case GL_RGBA:
daniel@transgaming.coma9198d92010-08-08 04:49:56 +0000389 case GL_BGRA_EXT:
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000390 psConst0[X] = 1;
391 psConst0[Z] = 1;
392 break;
393
394 case GL_RGB:
395 psConst0[X] = 1;
396 psConst0[W] = 1;
397 break;
398
399 case GL_ALPHA:
400 psConst0[Z] = 1;
401 break;
402
403 case GL_LUMINANCE:
404 psConst0[Y] = 1;
405 break;
406
407 case GL_LUMINANCE_ALPHA:
408 psConst0[X] = 1;
409 break;
410 }
411
daniel@transgaming.come4733d72012-10-31 18:07:01 +0000412 mRenderer->getDevice()->SetPixelShaderConstantF(0, psConst0, 1); // D3D9_REPLACE
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000413
414 return true;
415}
416
daniel@transgaming.com621ce052012-10-31 17:52:29 +0000417// D3D9_REPLACE
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000418IDirect3DTexture9 *Blit::copySurfaceToTexture(IDirect3DSurface9 *surface, const RECT &sourceRect)
419{
daniel@transgaming.comd36c6a02010-08-31 12:15:09 +0000420 if (!surface)
421 {
422 return NULL;
423 }
424
daniel@transgaming.come4733d72012-10-31 18:07:01 +0000425 IDirect3DDevice9 *device = mRenderer->getDevice(); // D3D9_REPLACE
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000426
427 D3DSURFACE_DESC sourceDesc;
428 surface->GetDesc(&sourceDesc);
429
430 // Copy the render target into a texture
431 IDirect3DTexture9 *texture;
daniel@transgaming.com8fd99e22010-04-20 18:52:00 +0000432 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 +0000433
434 if (FAILED(result))
435 {
436 ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
437 return error(GL_OUT_OF_MEMORY, (IDirect3DTexture9*)NULL);
438 }
439
440 IDirect3DSurface9 *textureSurface;
441 result = texture->GetSurfaceLevel(0, &textureSurface);
442
443 if (FAILED(result))
444 {
445 ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
446 texture->Release();
447 return error(GL_OUT_OF_MEMORY, (IDirect3DTexture9*)NULL);
448 }
449
daniel@transgaming.come4733d72012-10-31 18:07:01 +0000450 mRenderer->endScene();
daniel@transgaming.com4c5142c2010-10-15 17:58:27 +0000451 result = device->StretchRect(surface, &sourceRect, textureSurface, NULL, D3DTEXF_NONE);
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000452
453 textureSurface->Release();
454
455 if (FAILED(result))
456 {
457 ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
458 texture->Release();
459 return error(GL_OUT_OF_MEMORY, (IDirect3DTexture9*)NULL);
460 }
461
462 return texture;
463}
464
daniel@transgaming.com8fd99e22010-04-20 18:52:00 +0000465void Blit::setViewport(const RECT &sourceRect, GLint xoffset, GLint yoffset)
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000466{
daniel@transgaming.come4733d72012-10-31 18:07:01 +0000467 IDirect3DDevice9 *device = mRenderer->getDevice(); // D3D9_REPLACE
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000468
469 D3DVIEWPORT9 vp;
470 vp.X = xoffset;
471 vp.Y = yoffset;
472 vp.Width = sourceRect.right - sourceRect.left;
daniel@transgaming.com8fd99e22010-04-20 18:52:00 +0000473 vp.Height = sourceRect.bottom - sourceRect.top;
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000474 vp.MinZ = 0.0f;
475 vp.MaxZ = 1.0f;
476 device->SetViewport(&vp);
477
478 float halfPixelAdjust[4] = { -1.0f/vp.Width, 1.0f/vp.Height, 0, 0 };
479 device->SetVertexShaderConstantF(0, halfPixelAdjust, 1);
480}
481
daniel@transgaming.com621ce052012-10-31 17:52:29 +0000482// D3D9_REPLACE
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000483void Blit::setCommonBlitState()
484{
daniel@transgaming.come4733d72012-10-31 18:07:01 +0000485 IDirect3DDevice9 *device = mRenderer->getDevice();
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000486
487 device->SetDepthStencilSurface(NULL);
488
489 device->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID);
490 device->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE);
491 device->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
492 device->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
493 device->SetRenderState(D3DRS_CLIPPLANEENABLE, 0);
494 device->SetRenderState(D3DRS_COLORWRITEENABLE, D3DCOLORWRITEENABLE_ALPHA | D3DCOLORWRITEENABLE_BLUE | D3DCOLORWRITEENABLE_GREEN | D3DCOLORWRITEENABLE_RED);
495 device->SetRenderState(D3DRS_SRGBWRITEENABLE, FALSE);
496 device->SetRenderState(D3DRS_SCISSORTESTENABLE, FALSE);
497
498 device->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_POINT);
499 device->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_POINT);
500 device->SetSamplerState(0, D3DSAMP_SRGBTEXTURE, FALSE);
daniel@transgaming.com8fd99e22010-04-20 18:52:00 +0000501 device->SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP);
502 device->SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP);
daniel@transgaming.com81655a72010-05-20 19:18:17 +0000503
daniel@transgaming.com74d760b2010-11-03 12:27:18 +0000504 RECT scissorRect = {0}; // Scissoring is disabled for flipping, but we need this to capture and restore the old rectangle
505 device->SetScissorRect(&scissorRect);
daniel@transgaming.com8ca9c6e2012-01-27 15:38:54 +0000506
daniel@transgaming.comde8a7ff2012-11-28 19:34:13 +0000507 for(int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++)
daniel@transgaming.com8ca9c6e2012-01-27 15:38:54 +0000508 {
509 device->SetStreamSourceFreq(i, 1);
510 }
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000511}
512
daniel@transgaming.com621ce052012-10-31 17:52:29 +0000513// D3D9_REPLACE
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000514void Blit::render()
515{
daniel@transgaming.come4733d72012-10-31 18:07:01 +0000516 IDirect3DDevice9 *device = mRenderer->getDevice();
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000517
518 HRESULT hr = device->SetStreamSource(0, mQuadVertexBuffer, 0, 2 * sizeof(float));
519 hr = device->SetVertexDeclaration(mQuadVertexDeclaration);
520
daniel@transgaming.come4733d72012-10-31 18:07:01 +0000521 mRenderer->startScene();
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000522 hr = device->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2);
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000523}
524
daniel@transgaming.com621ce052012-10-31 17:52:29 +0000525// D3D9_REPLACE
daniel@transgaming.com1ddd1dd2010-05-11 02:29:34 +0000526void Blit::saveState()
527{
daniel@transgaming.come4733d72012-10-31 18:07:01 +0000528 IDirect3DDevice9 *device = mRenderer->getDevice();
daniel@transgaming.com1ddd1dd2010-05-11 02:29:34 +0000529
530 HRESULT hr;
531
532 device->GetDepthStencilSurface(&mSavedDepthStencil);
533 device->GetRenderTarget(0, &mSavedRenderTarget);
534
535 if (mSavedStateBlock == NULL)
536 {
537 hr = device->BeginStateBlock();
538 ASSERT(SUCCEEDED(hr) || hr == D3DERR_OUTOFVIDEOMEMORY || hr == E_OUTOFMEMORY);
539
540 setCommonBlitState();
541
542 static const float dummyConst[4] = { 0, 0, 0, 0 };
543
544 device->SetVertexShader(NULL);
545 device->SetVertexShaderConstantF(0, dummyConst, 1);
546 device->SetPixelShader(NULL);
547 device->SetPixelShaderConstantF(0, dummyConst, 1);
548
549 D3DVIEWPORT9 dummyVp;
550 dummyVp.X = 0;
551 dummyVp.Y = 0;
552 dummyVp.Width = 1;
553 dummyVp.Height = 1;
554 dummyVp.MinZ = 0;
555 dummyVp.MaxZ = 1;
556
557 device->SetViewport(&dummyVp);
558
559 device->SetTexture(0, NULL);
560
561 device->SetStreamSource(0, mQuadVertexBuffer, 0, 0);
562
563 device->SetVertexDeclaration(mQuadVertexDeclaration);
564
565 hr = device->EndStateBlock(&mSavedStateBlock);
566 ASSERT(SUCCEEDED(hr) || hr == D3DERR_OUTOFVIDEOMEMORY || hr == E_OUTOFMEMORY);
567 }
568
569 ASSERT(mSavedStateBlock != NULL);
570
571 if (mSavedStateBlock != NULL)
572 {
573 hr = mSavedStateBlock->Capture();
574 ASSERT(SUCCEEDED(hr));
575 }
576}
577
daniel@transgaming.com621ce052012-10-31 17:52:29 +0000578// D3D9_REPLACE
daniel@transgaming.com1ddd1dd2010-05-11 02:29:34 +0000579void Blit::restoreState()
580{
daniel@transgaming.come4733d72012-10-31 18:07:01 +0000581 IDirect3DDevice9 *device = mRenderer->getDevice();
daniel@transgaming.com1ddd1dd2010-05-11 02:29:34 +0000582
583 device->SetDepthStencilSurface(mSavedDepthStencil);
584 if (mSavedDepthStencil != NULL)
585 {
586 mSavedDepthStencil->Release();
587 mSavedDepthStencil = NULL;
588 }
589
590 device->SetRenderTarget(0, mSavedRenderTarget);
591 if (mSavedRenderTarget != NULL)
592 {
593 mSavedRenderTarget->Release();
594 mSavedRenderTarget = NULL;
595 }
596
597 ASSERT(mSavedStateBlock != NULL);
598
599 if (mSavedStateBlock != NULL)
600 {
601 mSavedStateBlock->Apply();
602 }
603}
604
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000605}