1a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block//
2a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
3a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block// Use of this source code is governed by a BSD-style license that can be
4a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block// found in the LICENSE file.
5a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block//
6a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
7a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block// Blit.cpp: Surface copy utility class.
8a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
9a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block#include "libGLESv2/Blit.h"
10a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
11a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block#include <d3dx9.h>
12a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
13a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block#include "common/debug.h"
14a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
15a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block#include "libGLESv2/main.h"
16a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
17a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Blocknamespace
18a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block{
19a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block// Standard Vertex Shader
20a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block// Input 0 is the homogenous position.
21a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block// Outputs the homogenous position as-is.
22a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block// Outputs a tex coord with (0,0) in the upper-left corner of the screen and (1,1) in the bottom right.
23a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block// C0.X must be negative half-pixel width, C0.Y must be half-pixel height. C0.ZW must be 0.
24a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Blockconst char standardvs[] =
25a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block"struct VS_OUTPUT\n"
26a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block"{\n"
27a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block"    float4 position : POSITION;\n"
28a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block"    float4 texcoord : TEXCOORD0;\n"
29a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block"};\n"
30a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block"\n"
31a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block"uniform float4 halfPixelSize : c0;\n"
32a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block"\n"
33a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block"VS_OUTPUT main(in float4 position : POSITION)\n"
34a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block"{\n"
35a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block"    VS_OUTPUT Out;\n"
36a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block"\n"
37a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block"    Out.position = position + halfPixelSize;\n"
38a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block"    Out.texcoord = position * float4(0.5, -0.5, 1.0, 1.0) + float4(0.5, 0.5, 0, 0);\n"
39a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block"\n"
40a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block"    return Out;\n"
41a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block"}\n";
42a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
43a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block// Flip Y Vertex Shader
44a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block// Input 0 is the homogenous position.
45a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block// Outputs the homogenous position as-is.
46a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block// Outputs a tex coord with (0,1) in the upper-left corner of the screen and (1,0) in the bottom right.
47a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block// C0.XY must be the half-pixel width and height. C0.ZW must be 0.
48a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Blockconst char flipyvs[] =
49a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block"struct VS_OUTPUT\n"
50a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block"{\n"
51a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block"    float4 position : POSITION;\n"
52a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block"    float4 texcoord : TEXCOORD0;\n"
53a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block"};\n"
54a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block"\n"
55a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block"uniform float4 halfPixelSize : c0;\n"
56a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block"\n"
57a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block"VS_OUTPUT main(in float4 position : POSITION)\n"
58a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block"{\n"
59a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block"    VS_OUTPUT Out;\n"
60a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block"\n"
61a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block"    Out.position = position + halfPixelSize;\n"
62a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block"    Out.texcoord = position * float4(0.5, 0.5, 1.0, 1.0) + float4(0.5, 0.5, 0, 0);\n"
63a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block"\n"
64a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block"    return Out;\n"
65a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block"}\n";
66a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
67a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block// Passthrough Pixel Shader
68a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block// Outputs texture 0 sampled at texcoord 0.
69a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Blockconst char passthroughps[] =
70a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block"sampler2D tex : s0;\n"
71a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block"\n"
72a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block"float4 main(float4 texcoord : TEXCOORD0) : COLOR\n"
73a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block"{\n"
74a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block"	return tex2D(tex, texcoord.xy);\n"
75a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block"}\n";
76a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
77a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block// Luminance Conversion Pixel Shader
78a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block// Outputs sample(tex0, tc0).rrra.
79a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block// For LA output (pass A) set C0.X = 1, C0.Y = 0.
80a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block// For L output (A = 1) set C0.X = 0, C0.Y = 1.
81a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Blockconst char luminanceps[] =
82a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block"sampler2D tex : s0;\n"
83a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block"\n"
84a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block"uniform float4 mode : c0;\n"
85a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block"\n"
86a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block"float4 main(float4 texcoord : TEXCOORD0) : COLOR\n"
87a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block"{\n"
88a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block"	float4 tmp = tex2D(tex, texcoord.xy);\n"
89a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block"	tmp.w = tmp.w * mode.x + mode.y;\n"
90a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block"	return tmp.xxxw;\n"
91a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block"}\n";
92a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
93a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block// RGB/A Component Mask Pixel Shader
94a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block// Outputs sample(tex0, tc0) with options to force RGB = 0 and/or A = 1.
95a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block// To force RGB = 0, set C0.X = 0, otherwise C0.X = 1.
96a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block// To force A = 1, set C0.Z = 0, C0.W = 1, otherwise C0.Z = 1, C0.W = 0.
97a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Blockconst char componentmaskps[] =
98a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block"sampler2D tex : s0;\n"
99a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block"\n"
100a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block"uniform float4 mode : c0;\n"
101a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block"\n"
102a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block"float4 main(float4 texcoord : TEXCOORD0) : COLOR\n"
103a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block"{\n"
104a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block"	float4 tmp = tex2D(tex, texcoord.xy);\n"
105a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block"	tmp.xyz = tmp.xyz * mode.x;\n"
106a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block"	tmp.w = tmp.w * mode.z + mode.w;\n"
107a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block"	return tmp;\n"
108a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block"}\n";
109a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
110a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block}
111a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
112a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Blocknamespace gl
113a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block{
114a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
115a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Blockconst char * const Blit::mShaderSource[] =
116a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block{
117a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    standardvs,
118a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    flipyvs,
119a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    passthroughps,
120a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    luminanceps,
121a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    componentmaskps
122a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block};
123a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
124a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve BlockBlit::Blit(Context *context)
125a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block  : mContext(context), mQuadVertexBuffer(NULL), mQuadVertexDeclaration(NULL), mSavedRenderTarget(NULL), mSavedDepthStencil(NULL), mSavedStateBlock(NULL)
126a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block{
127a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    initGeometry();
128a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    memset(mCompiledShaders, 0, sizeof(mCompiledShaders));
129a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block}
130a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
131a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve BlockBlit::~Blit()
132a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block{
133a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    if (mSavedStateBlock) mSavedStateBlock->Release();
134a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    if (mQuadVertexBuffer) mQuadVertexBuffer->Release();
135a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    if (mQuadVertexDeclaration) mQuadVertexDeclaration->Release();
136a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
137a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    for (int i = 0; i < SHADER_COUNT; i++)
138a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    {
139a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        if (mCompiledShaders[i])
140a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        {
141a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block            mCompiledShaders[i]->Release();
142a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        }
143a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    }
144a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block}
145a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
146a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Blockvoid Blit::initGeometry()
147a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block{
148a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    static const float quad[] =
149a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    {
150a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        -1, -1,
151a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        -1,  1,
152a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block         1, -1,
153a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block         1,  1
154a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    };
155a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
156a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    IDirect3DDevice9 *device = getDevice();
157a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
158a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    HRESULT hr = device->CreateVertexBuffer(sizeof(quad), D3DUSAGE_WRITEONLY, 0, D3DPOOL_DEFAULT, &mQuadVertexBuffer, NULL);
159a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
160a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    if (FAILED(hr))
161a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    {
162a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        ASSERT(hr == D3DERR_OUTOFVIDEOMEMORY || hr == E_OUTOFMEMORY);
163a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        return error(GL_OUT_OF_MEMORY);
164a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    }
165a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
166a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    void *lockPtr;
167a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    mQuadVertexBuffer->Lock(0, 0, &lockPtr, 0);
168a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    memcpy(lockPtr, quad, sizeof(quad));
169a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    mQuadVertexBuffer->Unlock();
170a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
171a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    static const D3DVERTEXELEMENT9 elements[] =
172a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    {
173a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        { 0, 0, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0 },
174a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        D3DDECL_END()
175a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    };
176a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
177a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    hr = device->CreateVertexDeclaration(elements, &mQuadVertexDeclaration);
178a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    if (FAILED(hr))
179a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    {
180a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        ASSERT(hr == D3DERR_OUTOFVIDEOMEMORY || hr == E_OUTOFMEMORY);
181a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        return error(GL_OUT_OF_MEMORY);
182a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    }
183a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block}
184a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
185a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Blocktemplate <class D3DShaderType>
186a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Blockbool Blit::setShader(ShaderId source, const char *profile,
187a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block                     HRESULT (WINAPI IDirect3DDevice9::*createShader)(const DWORD *, D3DShaderType**),
188a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block                     HRESULT (WINAPI IDirect3DDevice9::*setShader)(D3DShaderType*))
189a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block{
190a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    IDirect3DDevice9 *device = getDevice();
191a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
192a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    D3DShaderType *shader;
193a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
194a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    if (mCompiledShaders[source] != NULL)
195a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    {
196a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        shader = static_cast<D3DShaderType*>(mCompiledShaders[source]);
197a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    }
198a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    else
199a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    {
200a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        ID3DXBuffer *shaderCode;
201a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        HRESULT hr = D3DXCompileShader(mShaderSource[source], strlen(mShaderSource[source]), NULL, NULL, "main", profile, 0, &shaderCode, NULL, NULL);
202a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
203a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        if (FAILED(hr))
204a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        {
205a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block            ERR("Failed to compile %s shader for blit operation %d, error 0x%08X.", profile, (int)source, hr);
206a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block            return false;
207a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        }
208a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
209a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        hr = (device->*createShader)(static_cast<const DWORD*>(shaderCode->GetBufferPointer()), &shader);
210a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        if (FAILED(hr))
211a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        {
212a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block            shaderCode->Release();
213a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block            ERR("Failed to create %s shader for blit operation %d, error 0x%08X.", profile, (int)source, hr);
214a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block            return false;
215a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        }
216a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
217a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        shaderCode->Release();
218a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
219a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        mCompiledShaders[source] = shader;
220a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    }
221a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
222a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    HRESULT hr = (device->*setShader)(shader);
223a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
224a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    if (FAILED(hr))
225a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    {
226a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        ERR("Failed to set %s shader for blit operation %d, error 0x%08X.", profile, (int)source, hr);
227a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        return false;
228a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    }
229a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
230a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    return true;
231a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block}
232a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
233a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Blockbool Blit::setVertexShader(ShaderId shader)
234a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block{
2355abb8606fa57c3ebfc8b3c3dbc3fa4a25d2ae306Iain Merrick    return setShader<IDirect3DVertexShader9>(shader, mContext->supportsShaderModel3() ? "vs_3_0" : "vs_2_0", &IDirect3DDevice9::CreateVertexShader, &IDirect3DDevice9::SetVertexShader);
236a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block}
237a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
238a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Blockbool Blit::setPixelShader(ShaderId shader)
239a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block{
2405abb8606fa57c3ebfc8b3c3dbc3fa4a25d2ae306Iain Merrick    return setShader<IDirect3DPixelShader9>(shader, mContext->supportsShaderModel3() ? "ps_3_0" : "ps_2_0", &IDirect3DDevice9::CreatePixelShader, &IDirect3DDevice9::SetPixelShader);
241a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block}
242a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
243a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve BlockRECT Blit::getSurfaceRect(IDirect3DSurface9 *surface) const
244a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block{
245a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    D3DSURFACE_DESC desc;
246a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    surface->GetDesc(&desc);
247a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
248a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    RECT rect;
249a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    rect.left = 0;
250a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    rect.top = 0;
251a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    rect.right = desc.Width;
252a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    rect.bottom = desc.Height;
253a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
254a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    return rect;
255a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block}
256a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
257a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Blockbool Blit::boxFilter(IDirect3DSurface9 *source, IDirect3DSurface9 *dest)
258a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block{
259a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    IDirect3DTexture9 *texture = copySurfaceToTexture(source, getSurfaceRect(source));
260a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    if (!texture)
261a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    {
262a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        return false;
263a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    }
264a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
265a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    IDirect3DDevice9 *device = getDevice();
266a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
267a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    saveState();
268a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
269a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    device->SetTexture(0, texture);
270a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    device->SetRenderTarget(0, dest);
271a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
272a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    setVertexShader(SHADER_VS_STANDARD);
273a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    setPixelShader(SHADER_PS_PASSTHROUGH);
274a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
275a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    setCommonBlitState();
276a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    device->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
277a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    device->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
278a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
279a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    setViewport(getSurfaceRect(dest), 0, 0);
280a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
281a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    render();
282a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
283a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    texture->Release();
284a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
285a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    restoreState();
286a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
287a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    return true;
288a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block}
289a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
290a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Blockbool Blit::formatConvert(IDirect3DSurface9 *source, const RECT &sourceRect, GLenum destFormat, GLint xoffset, GLint yoffset, IDirect3DSurface9 *dest)
291a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block{
292a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    IDirect3DTexture9 *texture = copySurfaceToTexture(source, sourceRect);
293a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    if (!texture)
294a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    {
295a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        return false;
296a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    }
297a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
298a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    IDirect3DDevice9 *device = getDevice();
299a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
300a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    saveState();
301a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
302a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    device->SetTexture(0, texture);
303a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    device->SetRenderTarget(0, dest);
304a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
305a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    setViewport(sourceRect, xoffset, yoffset);
306a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
307a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    setCommonBlitState();
308a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    if (setFormatConvertShaders(destFormat))
309a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    {
310a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        render();
311a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    }
312a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
313a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    texture->Release();
314a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
315a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    restoreState();
316a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
317a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    return true;
318a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block}
319a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
320a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Blockbool Blit::setFormatConvertShaders(GLenum destFormat)
321a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block{
322a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    bool okay = setVertexShader(SHADER_VS_STANDARD);
323a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
324a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    switch (destFormat)
325a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    {
326a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block      default: UNREACHABLE();
327a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block      case GL_RGBA:
3285abb8606fa57c3ebfc8b3c3dbc3fa4a25d2ae306Iain Merrick      case GL_BGRA_EXT:
329a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block      case GL_RGB:
330a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block      case GL_ALPHA:
331a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        okay = okay && setPixelShader(SHADER_PS_COMPONENTMASK);
332a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        break;
333a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
334a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block      case GL_LUMINANCE:
335a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block      case GL_LUMINANCE_ALPHA:
336a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        okay = okay && setPixelShader(SHADER_PS_LUMINANCE);
337a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        break;
338a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    }
339a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
340a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    if (!okay)
341a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    {
342a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        return false;
343a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    }
344a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
345a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    enum { X = 0, Y = 1, Z = 2, W = 3 };
346a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
347a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    // The meaning of this constant depends on the shader that was selected.
348a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    // See the shader assembly code above for details.
349a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    float psConst0[4] = { 0, 0, 0, 0 };
350a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
351a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    switch (destFormat)
352a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    {
353a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block      default: UNREACHABLE();
354a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block      case GL_RGBA:
3555abb8606fa57c3ebfc8b3c3dbc3fa4a25d2ae306Iain Merrick      case GL_BGRA_EXT:
356a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        psConst0[X] = 1;
357a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        psConst0[Z] = 1;
358a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        break;
359a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
360a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block      case GL_RGB:
361a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        psConst0[X] = 1;
362a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        psConst0[W] = 1;
363a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        break;
364a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
365a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block      case GL_ALPHA:
366a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        psConst0[Z] = 1;
367a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        break;
368a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
369a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block      case GL_LUMINANCE:
370a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        psConst0[Y] = 1;
371a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        break;
372a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
373a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block      case GL_LUMINANCE_ALPHA:
374a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        psConst0[X] = 1;
375a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        break;
376a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    }
377a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
378a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    getDevice()->SetPixelShaderConstantF(0, psConst0, 1);
379a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
380a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    return true;
381a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block}
382a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
383a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve BlockIDirect3DTexture9 *Blit::copySurfaceToTexture(IDirect3DSurface9 *surface, const RECT &sourceRect)
384a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block{
385ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch    if (!surface)
386ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch    {
387ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch        return NULL;
388ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch    }
389ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch
390a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    egl::Display *display = getDisplay();
391a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    IDirect3DDevice9 *device = getDevice();
392a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
393a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    D3DSURFACE_DESC sourceDesc;
394a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    surface->GetDesc(&sourceDesc);
395a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
396a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    // Copy the render target into a texture
397a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    IDirect3DTexture9 *texture;
398a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    HRESULT result = device->CreateTexture(sourceRect.right - sourceRect.left, sourceRect.bottom - sourceRect.top, 1, D3DUSAGE_RENDERTARGET, sourceDesc.Format, D3DPOOL_DEFAULT, &texture, NULL);
399a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
400a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    if (FAILED(result))
401a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    {
402a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
403a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        return error(GL_OUT_OF_MEMORY, (IDirect3DTexture9*)NULL);
404a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    }
405a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
406a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    IDirect3DSurface9 *textureSurface;
407a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    result = texture->GetSurfaceLevel(0, &textureSurface);
408a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
409a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    if (FAILED(result))
410a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    {
411a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
412a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        texture->Release();
413a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        return error(GL_OUT_OF_MEMORY, (IDirect3DTexture9*)NULL);
414a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    }
415a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
416a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    display->endScene();
417ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch    result = device->StretchRect(surface, &sourceRect, textureSurface, NULL, D3DTEXF_NONE);
418a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
419a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    textureSurface->Release();
420a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
421a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    if (FAILED(result))
422a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    {
423a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
424a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        texture->Release();
425a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        return error(GL_OUT_OF_MEMORY, (IDirect3DTexture9*)NULL);
426a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    }
427a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
428a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    return texture;
429a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block}
430a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
431a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Blockvoid Blit::setViewport(const RECT &sourceRect, GLint xoffset, GLint yoffset)
432a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block{
433a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    IDirect3DDevice9 *device = getDevice();
434a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
435a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    D3DVIEWPORT9 vp;
436a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    vp.X      = xoffset;
437a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    vp.Y      = yoffset;
438a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    vp.Width  = sourceRect.right - sourceRect.left;
439a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    vp.Height = sourceRect.bottom - sourceRect.top;
440a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    vp.MinZ   = 0.0f;
441a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    vp.MaxZ   = 1.0f;
442a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    device->SetViewport(&vp);
443a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
444a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    float halfPixelAdjust[4] = { -1.0f/vp.Width, 1.0f/vp.Height, 0, 0 };
445a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    device->SetVertexShaderConstantF(0, halfPixelAdjust, 1);
446a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block}
447a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
448a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Blockvoid Blit::setCommonBlitState()
449a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block{
450a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    IDirect3DDevice9 *device = getDevice();
451a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
452a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    device->SetDepthStencilSurface(NULL);
453a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
454a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    device->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID);
455a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    device->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE);
456a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    device->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
457a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    device->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
458a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    device->SetRenderState(D3DRS_CLIPPLANEENABLE, 0);
459a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    device->SetRenderState(D3DRS_COLORWRITEENABLE, D3DCOLORWRITEENABLE_ALPHA | D3DCOLORWRITEENABLE_BLUE | D3DCOLORWRITEENABLE_GREEN | D3DCOLORWRITEENABLE_RED);
460a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    device->SetRenderState(D3DRS_SRGBWRITEENABLE, FALSE);
461a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    device->SetRenderState(D3DRS_SCISSORTESTENABLE, FALSE);
462a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
463a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    device->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_POINT);
464a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    device->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_POINT);
465a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    device->SetSamplerState(0, D3DSAMP_SRGBTEXTURE, FALSE);
466a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    device->SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP);
467a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    device->SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP);
468a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
469ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch    RECT scissorRect = {0};   // Scissoring is disabled for flipping, but we need this to capture and restore the old rectangle
470ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch    device->SetScissorRect(&scissorRect);
471a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block}
472a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
473a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Blockvoid Blit::render()
474a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block{
475a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    egl::Display *display = getDisplay();
476a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    IDirect3DDevice9 *device = getDevice();
477a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
478a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    HRESULT hr = device->SetStreamSource(0, mQuadVertexBuffer, 0, 2 * sizeof(float));
479a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    hr = device->SetVertexDeclaration(mQuadVertexDeclaration);
480a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
481a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    display->startScene();
482a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    hr = device->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2);
483a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block}
484a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
485a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Blockvoid Blit::saveState()
486a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block{
487a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    IDirect3DDevice9 *device = getDevice();
488a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
489a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    HRESULT hr;
490a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
491a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    device->GetDepthStencilSurface(&mSavedDepthStencil);
492a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    device->GetRenderTarget(0, &mSavedRenderTarget);
493a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
494a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    if (mSavedStateBlock == NULL)
495a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    {
496a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        hr = device->BeginStateBlock();
497a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        ASSERT(SUCCEEDED(hr) || hr == D3DERR_OUTOFVIDEOMEMORY || hr == E_OUTOFMEMORY);
498a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
499a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        setCommonBlitState();
500a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
501a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        static const float dummyConst[4] = { 0, 0, 0, 0 };
502a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
503a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        device->SetVertexShader(NULL);
504a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        device->SetVertexShaderConstantF(0, dummyConst, 1);
505a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        device->SetPixelShader(NULL);
506a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        device->SetPixelShaderConstantF(0, dummyConst, 1);
507a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
508a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        D3DVIEWPORT9 dummyVp;
509a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        dummyVp.X = 0;
510a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        dummyVp.Y = 0;
511a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        dummyVp.Width = 1;
512a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        dummyVp.Height = 1;
513a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        dummyVp.MinZ = 0;
514a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        dummyVp.MaxZ = 1;
515a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
516a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        device->SetViewport(&dummyVp);
517a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
518a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        device->SetTexture(0, NULL);
519a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
520a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        device->SetStreamSource(0, mQuadVertexBuffer, 0, 0);
521a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
522a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        device->SetVertexDeclaration(mQuadVertexDeclaration);
523a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
524a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        hr = device->EndStateBlock(&mSavedStateBlock);
525a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        ASSERT(SUCCEEDED(hr) || hr == D3DERR_OUTOFVIDEOMEMORY || hr == E_OUTOFMEMORY);
526a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    }
527a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
528a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    ASSERT(mSavedStateBlock != NULL);
529a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
530a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    if (mSavedStateBlock != NULL)
531a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    {
532a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        hr = mSavedStateBlock->Capture();
533a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        ASSERT(SUCCEEDED(hr));
534a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    }
535a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block}
536a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
537a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Blockvoid Blit::restoreState()
538a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block{
539a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    IDirect3DDevice9 *device = getDevice();
540a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
541a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    device->SetDepthStencilSurface(mSavedDepthStencil);
542a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    if (mSavedDepthStencil != NULL)
543a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    {
544a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        mSavedDepthStencil->Release();
545a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        mSavedDepthStencil = NULL;
546a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    }
547a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
548a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    device->SetRenderTarget(0, mSavedRenderTarget);
549a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    if (mSavedRenderTarget != NULL)
550a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    {
551a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        mSavedRenderTarget->Release();
552a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        mSavedRenderTarget = NULL;
553a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    }
554a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
555a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    ASSERT(mSavedStateBlock != NULL);
556a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
557a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    if (mSavedStateBlock != NULL)
558a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    {
559a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        mSavedStateBlock->Apply();
560a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    }
561a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block}
562a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
563a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block}
564