~ubuntu-branches/ubuntu/wily/qtbase-opensource-src/wily

« back to all changes in this revision

Viewing changes to src/3rdparty/angle/src/libGLESv2/Blit.cpp

  • Committer: Package Import Robot
  • Author(s): Timo Jyrinki
  • Date: 2013-02-05 12:46:17 UTC
  • Revision ID: package-import@ubuntu.com-20130205124617-c8jouts182j002fx
Tags: upstream-5.0.1+dfsg
ImportĀ upstreamĀ versionĀ 5.0.1+dfsg

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
//
 
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
 
 
9
#include "libGLESv2/Blit.h"
 
10
 
 
11
#include "common/debug.h"
 
12
 
 
13
#include "libGLESv2/main.h"
 
14
#include "libGLESv2/utilities.h"
 
15
 
 
16
namespace
 
17
{
 
18
#include "libGLESv2/shaders/standardvs.h"
 
19
#include "libGLESv2/shaders/flipyvs.h"
 
20
#include "libGLESv2/shaders/passthroughps.h"
 
21
#include "libGLESv2/shaders/luminanceps.h"
 
22
#include "libGLESv2/shaders/componentmaskps.h"
 
23
 
 
24
const BYTE* const g_shaderCode[] =
 
25
{
 
26
    g_vs20_standardvs,
 
27
    g_vs20_flipyvs,
 
28
    g_ps20_passthroughps,
 
29
    g_ps20_luminanceps,
 
30
    g_ps20_componentmaskps
 
31
};
 
32
 
 
33
const size_t g_shaderSize[] =
 
34
{
 
35
    sizeof(g_vs20_standardvs),
 
36
    sizeof(g_vs20_flipyvs),
 
37
    sizeof(g_ps20_passthroughps),
 
38
    sizeof(g_ps20_luminanceps),
 
39
    sizeof(g_ps20_componentmaskps)
 
40
};
 
41
}
 
42
 
 
43
namespace gl
 
44
{
 
45
Blit::Blit(Context *context)
 
46
  : mContext(context), mQuadVertexBuffer(NULL), mQuadVertexDeclaration(NULL), mSavedRenderTarget(NULL), mSavedDepthStencil(NULL), mSavedStateBlock(NULL)
 
47
{
 
48
    initGeometry();
 
49
    memset(mCompiledShaders, 0, sizeof(mCompiledShaders));
 
50
}
 
51
 
 
52
Blit::~Blit()
 
53
{
 
54
    if (mSavedStateBlock) mSavedStateBlock->Release();
 
55
    if (mQuadVertexBuffer) mQuadVertexBuffer->Release();
 
56
    if (mQuadVertexDeclaration) mQuadVertexDeclaration->Release();
 
57
 
 
58
    for (int i = 0; i < SHADER_COUNT; i++)
 
59
    {
 
60
        if (mCompiledShaders[i])
 
61
        {
 
62
            mCompiledShaders[i]->Release();
 
63
        }
 
64
    }
 
65
}
 
66
 
 
67
void Blit::initGeometry()
 
68
{
 
69
    static const float quad[] =
 
70
    {
 
71
        -1, -1,
 
72
        -1,  1,
 
73
         1, -1,
 
74
         1,  1
 
75
    };
 
76
 
 
77
    IDirect3DDevice9 *device = getDevice();
 
78
 
 
79
    HRESULT result = device->CreateVertexBuffer(sizeof(quad), D3DUSAGE_WRITEONLY, 0, D3DPOOL_DEFAULT, &mQuadVertexBuffer, NULL);
 
80
 
 
81
    if (FAILED(result))
 
82
    {
 
83
        ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
 
84
        return error(GL_OUT_OF_MEMORY);
 
85
    }
 
86
 
 
87
    void *lockPtr = NULL;
 
88
    result = mQuadVertexBuffer->Lock(0, 0, &lockPtr, 0);
 
89
 
 
90
    if (FAILED(result) || lockPtr == NULL)
 
91
    {
 
92
        ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
 
93
        return error(GL_OUT_OF_MEMORY);
 
94
    }
 
95
 
 
96
    memcpy(lockPtr, quad, sizeof(quad));
 
97
    mQuadVertexBuffer->Unlock();
 
98
 
 
99
    static const D3DVERTEXELEMENT9 elements[] =
 
100
    {
 
101
        { 0, 0, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0 },
 
102
        D3DDECL_END()
 
103
    };
 
104
 
 
105
    result = device->CreateVertexDeclaration(elements, &mQuadVertexDeclaration);
 
106
 
 
107
    if (FAILED(result))
 
108
    {
 
109
        ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
 
110
        return error(GL_OUT_OF_MEMORY);
 
111
    }
 
112
}
 
113
 
 
114
template <class D3DShaderType>
 
115
bool Blit::setShader(ShaderId source, const char *profile,
 
116
                     D3DShaderType *(egl::Display::*createShader)(const DWORD *, size_t length),
 
117
                     HRESULT (WINAPI IDirect3DDevice9::*setShader)(D3DShaderType*))
 
118
{
 
119
    egl::Display *display = getDisplay();
 
120
    IDirect3DDevice9 *device = display->getDevice();
 
121
 
 
122
    D3DShaderType *shader;
 
123
 
 
124
    if (mCompiledShaders[source] != NULL)
 
125
    {
 
126
        shader = static_cast<D3DShaderType*>(mCompiledShaders[source]);
 
127
    }
 
128
    else
 
129
    {
 
130
        const BYTE* shaderCode = g_shaderCode[source];
 
131
        size_t shaderSize = g_shaderSize[source];
 
132
 
 
133
        shader = (display->*createShader)(reinterpret_cast<const DWORD*>(shaderCode), shaderSize);
 
134
        if (!shader)
 
135
        {
 
136
            ERR("Failed to create shader for blit operation");
 
137
            return false;
 
138
        }
 
139
 
 
140
        mCompiledShaders[source] = shader;
 
141
    }
 
142
 
 
143
    HRESULT hr = (device->*setShader)(shader);
 
144
 
 
145
    if (FAILED(hr))
 
146
    {
 
147
        ERR("Failed to set shader for blit operation");
 
148
        return false;
 
149
    }
 
150
 
 
151
    return true;
 
152
}
 
153
 
 
154
bool Blit::setVertexShader(ShaderId shader)
 
155
{
 
156
    return setShader<IDirect3DVertexShader9>(shader, "vs_2_0", &egl::Display::createVertexShader, &IDirect3DDevice9::SetVertexShader);
 
157
}
 
158
 
 
159
bool Blit::setPixelShader(ShaderId shader)
 
160
{
 
161
    return setShader<IDirect3DPixelShader9>(shader, "ps_2_0", &egl::Display::createPixelShader, &IDirect3DDevice9::SetPixelShader);
 
162
}
 
163
 
 
164
RECT Blit::getSurfaceRect(IDirect3DSurface9 *surface) const
 
165
{
 
166
    D3DSURFACE_DESC desc;
 
167
    surface->GetDesc(&desc);
 
168
 
 
169
    RECT rect;
 
170
    rect.left = 0;
 
171
    rect.top = 0;
 
172
    rect.right = desc.Width;
 
173
    rect.bottom = desc.Height;
 
174
 
 
175
    return rect;
 
176
}
 
177
 
 
178
bool Blit::boxFilter(IDirect3DSurface9 *source, IDirect3DSurface9 *dest)
 
179
{
 
180
    IDirect3DTexture9 *texture = copySurfaceToTexture(source, getSurfaceRect(source));
 
181
    if (!texture)
 
182
    {
 
183
        return false;
 
184
    }
 
185
 
 
186
    IDirect3DDevice9 *device = getDevice();
 
187
 
 
188
    saveState();
 
189
 
 
190
    device->SetTexture(0, texture);
 
191
    device->SetRenderTarget(0, dest);
 
192
 
 
193
    setVertexShader(SHADER_VS_STANDARD);
 
194
    setPixelShader(SHADER_PS_PASSTHROUGH);
 
195
 
 
196
    setCommonBlitState();
 
197
    device->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
 
198
    device->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
 
199
 
 
200
    setViewport(getSurfaceRect(dest), 0, 0);
 
201
 
 
202
    render();
 
203
 
 
204
    texture->Release();
 
205
 
 
206
    restoreState();
 
207
 
 
208
    return true;
 
209
}
 
210
 
 
211
bool Blit::copy(IDirect3DSurface9 *source, const RECT &sourceRect, GLenum destFormat, GLint xoffset, GLint yoffset, IDirect3DSurface9 *dest)
 
212
{
 
213
    IDirect3DDevice9 *device = getDevice();
 
214
 
 
215
    D3DSURFACE_DESC sourceDesc;
 
216
    D3DSURFACE_DESC destDesc;
 
217
    source->GetDesc(&sourceDesc);
 
218
    dest->GetDesc(&destDesc);
 
219
 
 
220
    if (sourceDesc.Format == destDesc.Format && destDesc.Usage & D3DUSAGE_RENDERTARGET &&
 
221
        dx2es::IsFormatChannelEquivalent(destDesc.Format, destFormat))   // Can use StretchRect
 
222
    {
 
223
        RECT destRect = {xoffset, yoffset, xoffset + (sourceRect.right - sourceRect.left), yoffset + (sourceRect.bottom - sourceRect.top)};
 
224
        HRESULT result = device->StretchRect(source, &sourceRect, dest, &destRect, D3DTEXF_POINT);
 
225
 
 
226
        if (FAILED(result))
 
227
        {
 
228
            ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
 
229
            return error(GL_OUT_OF_MEMORY, false);
 
230
        }
 
231
    }
 
232
    else
 
233
    {
 
234
        return formatConvert(source, sourceRect, destFormat, xoffset, yoffset, dest);
 
235
    }
 
236
 
 
237
    return true;
 
238
}
 
239
 
 
240
bool Blit::formatConvert(IDirect3DSurface9 *source, const RECT &sourceRect, GLenum destFormat, GLint xoffset, GLint yoffset, IDirect3DSurface9 *dest)
 
241
{
 
242
    IDirect3DTexture9 *texture = copySurfaceToTexture(source, sourceRect);
 
243
    if (!texture)
 
244
    {
 
245
        return false;
 
246
    }
 
247
 
 
248
    IDirect3DDevice9 *device = getDevice();
 
249
 
 
250
    saveState();
 
251
 
 
252
    device->SetTexture(0, texture);
 
253
    device->SetRenderTarget(0, dest);
 
254
 
 
255
    setViewport(sourceRect, xoffset, yoffset);
 
256
 
 
257
    setCommonBlitState();
 
258
    if (setFormatConvertShaders(destFormat))
 
259
    {
 
260
        render();
 
261
    }
 
262
 
 
263
    texture->Release();
 
264
 
 
265
    restoreState();
 
266
 
 
267
    return true;
 
268
}
 
269
 
 
270
bool Blit::setFormatConvertShaders(GLenum destFormat)
 
271
{
 
272
    bool okay = setVertexShader(SHADER_VS_STANDARD);
 
273
 
 
274
    switch (destFormat)
 
275
    {
 
276
      default: UNREACHABLE();
 
277
      case GL_RGBA:
 
278
      case GL_BGRA_EXT:
 
279
      case GL_RGB:
 
280
      case GL_ALPHA:
 
281
        okay = okay && setPixelShader(SHADER_PS_COMPONENTMASK);
 
282
        break;
 
283
 
 
284
      case GL_LUMINANCE:
 
285
      case GL_LUMINANCE_ALPHA:
 
286
        okay = okay && setPixelShader(SHADER_PS_LUMINANCE);
 
287
        break;
 
288
    }
 
289
 
 
290
    if (!okay)
 
291
    {
 
292
        return false;
 
293
    }
 
294
 
 
295
    enum { X = 0, Y = 1, Z = 2, W = 3 };
 
296
 
 
297
    // The meaning of this constant depends on the shader that was selected.
 
298
    // See the shader assembly code above for details.
 
299
    float psConst0[4] = { 0, 0, 0, 0 };
 
300
 
 
301
    switch (destFormat)
 
302
    {
 
303
      default: UNREACHABLE();
 
304
      case GL_RGBA:
 
305
      case GL_BGRA_EXT:
 
306
        psConst0[X] = 1;
 
307
        psConst0[Z] = 1;
 
308
        break;
 
309
 
 
310
      case GL_RGB:
 
311
        psConst0[X] = 1;
 
312
        psConst0[W] = 1;
 
313
        break;
 
314
 
 
315
      case GL_ALPHA:
 
316
        psConst0[Z] = 1;
 
317
        break;
 
318
 
 
319
      case GL_LUMINANCE:
 
320
        psConst0[Y] = 1;
 
321
        break;
 
322
 
 
323
      case GL_LUMINANCE_ALPHA:
 
324
        psConst0[X] = 1;
 
325
        break;
 
326
    }
 
327
 
 
328
    getDevice()->SetPixelShaderConstantF(0, psConst0, 1);
 
329
 
 
330
    return true;
 
331
}
 
332
 
 
333
IDirect3DTexture9 *Blit::copySurfaceToTexture(IDirect3DSurface9 *surface, const RECT &sourceRect)
 
334
{
 
335
    if (!surface)
 
336
    {
 
337
        return NULL;
 
338
    }
 
339
 
 
340
    egl::Display *display = getDisplay();
 
341
    IDirect3DDevice9 *device = getDevice();
 
342
 
 
343
    D3DSURFACE_DESC sourceDesc;
 
344
    surface->GetDesc(&sourceDesc);
 
345
 
 
346
    // Copy the render target into a texture
 
347
    IDirect3DTexture9 *texture;
 
348
    HRESULT result = device->CreateTexture(sourceRect.right - sourceRect.left, sourceRect.bottom - sourceRect.top, 1, D3DUSAGE_RENDERTARGET, sourceDesc.Format, D3DPOOL_DEFAULT, &texture, NULL);
 
349
 
 
350
    if (FAILED(result))
 
351
    {
 
352
        ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
 
353
        return error(GL_OUT_OF_MEMORY, (IDirect3DTexture9*)NULL);
 
354
    }
 
355
 
 
356
    IDirect3DSurface9 *textureSurface;
 
357
    result = texture->GetSurfaceLevel(0, &textureSurface);
 
358
 
 
359
    if (FAILED(result))
 
360
    {
 
361
        ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
 
362
        texture->Release();
 
363
        return error(GL_OUT_OF_MEMORY, (IDirect3DTexture9*)NULL);
 
364
    }
 
365
 
 
366
    display->endScene();
 
367
    result = device->StretchRect(surface, &sourceRect, textureSurface, NULL, D3DTEXF_NONE);
 
368
 
 
369
    textureSurface->Release();
 
370
 
 
371
    if (FAILED(result))
 
372
    {
 
373
        ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
 
374
        texture->Release();
 
375
        return error(GL_OUT_OF_MEMORY, (IDirect3DTexture9*)NULL);
 
376
    }
 
377
 
 
378
    return texture;
 
379
}
 
380
 
 
381
void Blit::setViewport(const RECT &sourceRect, GLint xoffset, GLint yoffset)
 
382
{
 
383
    IDirect3DDevice9 *device = getDevice();
 
384
 
 
385
    D3DVIEWPORT9 vp;
 
386
    vp.X      = xoffset;
 
387
    vp.Y      = yoffset;
 
388
    vp.Width  = sourceRect.right - sourceRect.left;
 
389
    vp.Height = sourceRect.bottom - sourceRect.top;
 
390
    vp.MinZ   = 0.0f;
 
391
    vp.MaxZ   = 1.0f;
 
392
    device->SetViewport(&vp);
 
393
 
 
394
    float halfPixelAdjust[4] = { -1.0f/vp.Width, 1.0f/vp.Height, 0, 0 };
 
395
    device->SetVertexShaderConstantF(0, halfPixelAdjust, 1);
 
396
}
 
397
 
 
398
void Blit::setCommonBlitState()
 
399
{
 
400
    IDirect3DDevice9 *device = getDevice();
 
401
 
 
402
    device->SetDepthStencilSurface(NULL);
 
403
 
 
404
    device->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID);
 
405
    device->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE);
 
406
    device->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
 
407
    device->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
 
408
    device->SetRenderState(D3DRS_CLIPPLANEENABLE, 0);
 
409
    device->SetRenderState(D3DRS_COLORWRITEENABLE, D3DCOLORWRITEENABLE_ALPHA | D3DCOLORWRITEENABLE_BLUE | D3DCOLORWRITEENABLE_GREEN | D3DCOLORWRITEENABLE_RED);
 
410
    device->SetRenderState(D3DRS_SRGBWRITEENABLE, FALSE);
 
411
    device->SetRenderState(D3DRS_SCISSORTESTENABLE, FALSE);
 
412
 
 
413
    device->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_POINT);
 
414
    device->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_POINT);
 
415
    device->SetSamplerState(0, D3DSAMP_SRGBTEXTURE, FALSE);
 
416
    device->SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP);
 
417
    device->SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP);
 
418
 
 
419
    RECT scissorRect = {0};   // Scissoring is disabled for flipping, but we need this to capture and restore the old rectangle
 
420
    device->SetScissorRect(&scissorRect);
 
421
 
 
422
    for(int i = 0; i < MAX_VERTEX_ATTRIBS; i++)
 
423
    {
 
424
        device->SetStreamSourceFreq(i, 1);
 
425
    }
 
426
}
 
427
 
 
428
void Blit::render()
 
429
{
 
430
    egl::Display *display = getDisplay();
 
431
    IDirect3DDevice9 *device = getDevice();
 
432
 
 
433
    HRESULT hr = device->SetStreamSource(0, mQuadVertexBuffer, 0, 2 * sizeof(float));
 
434
    hr = device->SetVertexDeclaration(mQuadVertexDeclaration);
 
435
 
 
436
    display->startScene();
 
437
    hr = device->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2);
 
438
}
 
439
 
 
440
void Blit::saveState()
 
441
{
 
442
    IDirect3DDevice9 *device = getDevice();
 
443
 
 
444
    HRESULT hr;
 
445
 
 
446
    device->GetDepthStencilSurface(&mSavedDepthStencil);
 
447
    device->GetRenderTarget(0, &mSavedRenderTarget);
 
448
 
 
449
    if (mSavedStateBlock == NULL)
 
450
    {
 
451
        hr = device->BeginStateBlock();
 
452
        ASSERT(SUCCEEDED(hr) || hr == D3DERR_OUTOFVIDEOMEMORY || hr == E_OUTOFMEMORY);
 
453
 
 
454
        setCommonBlitState();
 
455
 
 
456
        static const float dummyConst[4] = { 0, 0, 0, 0 };
 
457
 
 
458
        device->SetVertexShader(NULL);
 
459
        device->SetVertexShaderConstantF(0, dummyConst, 1);
 
460
        device->SetPixelShader(NULL);
 
461
        device->SetPixelShaderConstantF(0, dummyConst, 1);
 
462
 
 
463
        D3DVIEWPORT9 dummyVp;
 
464
        dummyVp.X = 0;
 
465
        dummyVp.Y = 0;
 
466
        dummyVp.Width = 1;
 
467
        dummyVp.Height = 1;
 
468
        dummyVp.MinZ = 0;
 
469
        dummyVp.MaxZ = 1;
 
470
 
 
471
        device->SetViewport(&dummyVp);
 
472
 
 
473
        device->SetTexture(0, NULL);
 
474
 
 
475
        device->SetStreamSource(0, mQuadVertexBuffer, 0, 0);
 
476
 
 
477
        device->SetVertexDeclaration(mQuadVertexDeclaration);
 
478
 
 
479
        hr = device->EndStateBlock(&mSavedStateBlock);
 
480
        ASSERT(SUCCEEDED(hr) || hr == D3DERR_OUTOFVIDEOMEMORY || hr == E_OUTOFMEMORY);
 
481
    }
 
482
 
 
483
    ASSERT(mSavedStateBlock != NULL);
 
484
 
 
485
    if (mSavedStateBlock != NULL)
 
486
    {
 
487
        hr = mSavedStateBlock->Capture();
 
488
        ASSERT(SUCCEEDED(hr));
 
489
    }
 
490
}
 
491
 
 
492
void Blit::restoreState()
 
493
{
 
494
    IDirect3DDevice9 *device = getDevice();
 
495
 
 
496
    device->SetDepthStencilSurface(mSavedDepthStencil);
 
497
    if (mSavedDepthStencil != NULL)
 
498
    {
 
499
        mSavedDepthStencil->Release();
 
500
        mSavedDepthStencil = NULL;
 
501
    }
 
502
 
 
503
    device->SetRenderTarget(0, mSavedRenderTarget);
 
504
    if (mSavedRenderTarget != NULL)
 
505
    {
 
506
        mSavedRenderTarget->Release();
 
507
        mSavedRenderTarget = NULL;
 
508
    }
 
509
 
 
510
    ASSERT(mSavedStateBlock != NULL);
 
511
 
 
512
    if (mSavedStateBlock != NULL)
 
513
    {
 
514
        mSavedStateBlock->Apply();
 
515
    }
 
516
}
 
517
 
 
518
}