~gabriel1984sibiu/minitube/qt5.6

« back to all changes in this revision

Viewing changes to src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/SwapChain9.cpp

  • Committer: Grevutiu Gabriel
  • Date: 2017-06-13 08:43:17 UTC
  • Revision ID: gabriel1984sibiu@gmail.com-20170613084317-ek0zqe0u9g3ocvi8
OriginalĀ upstreamĀ code

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
//
 
2
// Copyright (c) 2012-2014 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
// SwapChain9.cpp: Implements a back-end specific class for the D3D9 swap chain.
 
8
 
 
9
#include "libANGLE/renderer/d3d/d3d9/SwapChain9.h"
 
10
#include "libANGLE/renderer/d3d/d3d9/renderer9_utils.h"
 
11
#include "libANGLE/renderer/d3d/d3d9/formatutils9.h"
 
12
#include "libANGLE/renderer/d3d/d3d9/Renderer9.h"
 
13
#include "libANGLE/features.h"
 
14
 
 
15
namespace rx
 
16
{
 
17
 
 
18
SwapChain9::SwapChain9(Renderer9 *renderer,
 
19
                       NativeWindow nativeWindow,
 
20
                       HANDLE shareHandle,
 
21
                       GLenum backBufferFormat,
 
22
                       GLenum depthBufferFormat,
 
23
                       EGLint orientation)
 
24
    : SwapChainD3D(nativeWindow, shareHandle, backBufferFormat, depthBufferFormat),
 
25
      mRenderer(renderer),
 
26
      mWidth(-1),
 
27
      mHeight(-1),
 
28
      mSwapInterval(-1),
 
29
      mSwapChain(nullptr),
 
30
      mBackBuffer(nullptr),
 
31
      mRenderTarget(nullptr),
 
32
      mDepthStencil(nullptr),
 
33
      mOffscreenTexture(nullptr),
 
34
      mColorRenderTarget(this, false),
 
35
      mDepthStencilRenderTarget(this, true)
 
36
{
 
37
    ASSERT(orientation == 0);
 
38
}
 
39
 
 
40
SwapChain9::~SwapChain9()
 
41
{
 
42
    release();
 
43
}
 
44
 
 
45
void SwapChain9::release()
 
46
{
 
47
    SafeRelease(mSwapChain);
 
48
    SafeRelease(mBackBuffer);
 
49
    SafeRelease(mDepthStencil);
 
50
    SafeRelease(mRenderTarget);
 
51
    SafeRelease(mOffscreenTexture);
 
52
 
 
53
    if (mNativeWindow.getNativeWindow())
 
54
    {
 
55
        mShareHandle = NULL;
 
56
    }
 
57
}
 
58
 
 
59
static DWORD convertInterval(EGLint interval)
 
60
{
 
61
#if ANGLE_VSYNC == ANGLE_DISABLED
 
62
    return D3DPRESENT_INTERVAL_IMMEDIATE;
 
63
#else
 
64
    switch(interval)
 
65
    {
 
66
      case 0: return D3DPRESENT_INTERVAL_IMMEDIATE;
 
67
      case 1: return D3DPRESENT_INTERVAL_ONE;
 
68
      case 2: return D3DPRESENT_INTERVAL_TWO;
 
69
      case 3: return D3DPRESENT_INTERVAL_THREE;
 
70
      case 4: return D3DPRESENT_INTERVAL_FOUR;
 
71
      default: UNREACHABLE();
 
72
    }
 
73
 
 
74
    return D3DPRESENT_INTERVAL_DEFAULT;
 
75
#endif
 
76
}
 
77
 
 
78
EGLint SwapChain9::resize(int backbufferWidth, int backbufferHeight)
 
79
{
 
80
    // D3D9 does not support resizing swap chains without recreating them
 
81
    return reset(backbufferWidth, backbufferHeight, mSwapInterval);
 
82
}
 
83
 
 
84
EGLint SwapChain9::reset(int backbufferWidth, int backbufferHeight, EGLint swapInterval)
 
85
{
 
86
    IDirect3DDevice9 *device = mRenderer->getDevice();
 
87
 
 
88
    if (device == NULL)
 
89
    {
 
90
        return EGL_BAD_ACCESS;
 
91
    }
 
92
 
 
93
    // Evict all non-render target textures to system memory and release all resources
 
94
    // before reallocating them to free up as much video memory as possible.
 
95
    device->EvictManagedResources();
 
96
 
 
97
    HRESULT result;
 
98
 
 
99
    // Release specific resources to free up memory for the new render target, while the
 
100
    // old render target still exists for the purpose of preserving its contents.
 
101
    SafeRelease(mSwapChain);
 
102
    SafeRelease(mBackBuffer);
 
103
    SafeRelease(mOffscreenTexture);
 
104
    SafeRelease(mDepthStencil);
 
105
 
 
106
    HANDLE *pShareHandle = NULL;
 
107
    if (!mNativeWindow.getNativeWindow() && mRenderer->getShareHandleSupport())
 
108
    {
 
109
        pShareHandle = &mShareHandle;
 
110
    }
 
111
 
 
112
    const d3d9::TextureFormat &backBufferd3dFormatInfo = d3d9::GetTextureFormatInfo(mOffscreenRenderTargetFormat);
 
113
    result = device->CreateTexture(backbufferWidth, backbufferHeight, 1, D3DUSAGE_RENDERTARGET,
 
114
                                   backBufferd3dFormatInfo.texFormat, D3DPOOL_DEFAULT, &mOffscreenTexture,
 
115
                                   pShareHandle);
 
116
    if (FAILED(result))
 
117
    {
 
118
        ERR("Could not create offscreen texture: %08lX", result);
 
119
        release();
 
120
 
 
121
        if (d3d9::isDeviceLostError(result))
 
122
        {
 
123
            return EGL_CONTEXT_LOST;
 
124
        }
 
125
        else
 
126
        {
 
127
            return EGL_BAD_ALLOC;
 
128
        }
 
129
    }
 
130
 
 
131
    IDirect3DSurface9 *oldRenderTarget = mRenderTarget;
 
132
 
 
133
    result = mOffscreenTexture->GetSurfaceLevel(0, &mRenderTarget);
 
134
    ASSERT(SUCCEEDED(result));
 
135
 
 
136
    if (oldRenderTarget)
 
137
    {
 
138
        RECT rect =
 
139
        {
 
140
            0, 0,
 
141
            mWidth, mHeight
 
142
        };
 
143
 
 
144
        if (rect.right > static_cast<LONG>(backbufferWidth))
 
145
        {
 
146
            rect.right = backbufferWidth;
 
147
        }
 
148
 
 
149
        if (rect.bottom > static_cast<LONG>(backbufferHeight))
 
150
        {
 
151
            rect.bottom = backbufferHeight;
 
152
        }
 
153
 
 
154
        mRenderer->endScene();
 
155
 
 
156
        result = device->StretchRect(oldRenderTarget, &rect, mRenderTarget, &rect, D3DTEXF_NONE);
 
157
        ASSERT(SUCCEEDED(result));
 
158
 
 
159
        SafeRelease(oldRenderTarget);
 
160
    }
 
161
 
 
162
    const d3d9::TextureFormat &depthBufferd3dFormatInfo = d3d9::GetTextureFormatInfo(mDepthBufferFormat);
 
163
 
 
164
    // Don't create a swapchain for NULLREF devices
 
165
    D3DDEVTYPE deviceType = mRenderer->getD3D9DeviceType();
 
166
    EGLNativeWindowType window = mNativeWindow.getNativeWindow();
 
167
    if (window && deviceType != D3DDEVTYPE_NULLREF)
 
168
    {
 
169
        D3DPRESENT_PARAMETERS presentParameters = {0};
 
170
        presentParameters.AutoDepthStencilFormat = depthBufferd3dFormatInfo.renderFormat;
 
171
        presentParameters.BackBufferCount = 1;
 
172
        presentParameters.BackBufferFormat = backBufferd3dFormatInfo.renderFormat;
 
173
        presentParameters.EnableAutoDepthStencil = FALSE;
 
174
        presentParameters.Flags = 0;
 
175
        presentParameters.hDeviceWindow = window;
 
176
        presentParameters.MultiSampleQuality = 0;                  // FIXME: Unimplemented
 
177
        presentParameters.MultiSampleType = D3DMULTISAMPLE_NONE;   // FIXME: Unimplemented
 
178
        presentParameters.PresentationInterval = convertInterval(swapInterval);
 
179
        presentParameters.SwapEffect = D3DSWAPEFFECT_DISCARD;
 
180
        presentParameters.Windowed = TRUE;
 
181
        presentParameters.BackBufferWidth = backbufferWidth;
 
182
        presentParameters.BackBufferHeight = backbufferHeight;
 
183
 
 
184
        // http://crbug.com/140239
 
185
        // http://crbug.com/143434
 
186
        //
 
187
        // Some AMD/Intel switchable systems / drivers appear to round swap chain surfaces to a multiple of 64 pixels in width
 
188
        // when using the integrated Intel. This rounds the width up rather than down.
 
189
        //
 
190
        // Some non-switchable AMD GPUs / drivers do not respect the source rectangle to Present. Therefore, when the vendor ID
 
191
        // is not Intel, the back buffer width must be exactly the same width as the window or horizontal scaling will occur.
 
192
        if (mRenderer->getVendorId() == VENDOR_ID_INTEL)
 
193
        {
 
194
            presentParameters.BackBufferWidth = (presentParameters.BackBufferWidth + 63) / 64 * 64;
 
195
        }
 
196
 
 
197
        result = device->CreateAdditionalSwapChain(&presentParameters, &mSwapChain);
 
198
 
 
199
        if (FAILED(result))
 
200
        {
 
201
            ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY || result == D3DERR_INVALIDCALL || result == D3DERR_DEVICELOST);
 
202
 
 
203
            ERR("Could not create additional swap chains or offscreen surfaces: %08lX", result);
 
204
            release();
 
205
 
 
206
            if (d3d9::isDeviceLostError(result))
 
207
            {
 
208
                return EGL_CONTEXT_LOST;
 
209
            }
 
210
            else
 
211
            {
 
212
                return EGL_BAD_ALLOC;
 
213
            }
 
214
        }
 
215
 
 
216
        result = mSwapChain->GetBackBuffer(0, D3DBACKBUFFER_TYPE_MONO, &mBackBuffer);
 
217
        ASSERT(SUCCEEDED(result));
 
218
        InvalidateRect(window, NULL, FALSE);
 
219
    }
 
220
 
 
221
    if (mDepthBufferFormat != GL_NONE)
 
222
    {
 
223
        result = device->CreateDepthStencilSurface(backbufferWidth, backbufferHeight,
 
224
                                                   depthBufferd3dFormatInfo.renderFormat,
 
225
                                                   D3DMULTISAMPLE_NONE, 0, FALSE, &mDepthStencil, NULL);
 
226
 
 
227
        if (FAILED(result))
 
228
        {
 
229
            ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY || result == D3DERR_INVALIDCALL);
 
230
 
 
231
            ERR("Could not create depthstencil surface for new swap chain: 0x%08X", result);
 
232
            release();
 
233
 
 
234
            if (d3d9::isDeviceLostError(result))
 
235
            {
 
236
                return EGL_CONTEXT_LOST;
 
237
            }
 
238
            else
 
239
            {
 
240
                return EGL_BAD_ALLOC;
 
241
            }
 
242
        }
 
243
    }
 
244
 
 
245
    mWidth = backbufferWidth;
 
246
    mHeight = backbufferHeight;
 
247
    mSwapInterval = swapInterval;
 
248
 
 
249
    return EGL_SUCCESS;
 
250
}
 
251
 
 
252
// parameters should be validated/clamped by caller
 
253
EGLint SwapChain9::swapRect(EGLint x, EGLint y, EGLint width, EGLint height)
 
254
{
 
255
    if (!mSwapChain)
 
256
    {
 
257
        return EGL_SUCCESS;
 
258
    }
 
259
 
 
260
    IDirect3DDevice9 *device = mRenderer->getDevice();
 
261
 
 
262
    // Disable all pipeline operations
 
263
    device->SetRenderState(D3DRS_ZENABLE, D3DZB_FALSE);
 
264
    device->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID);
 
265
    device->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE);
 
266
    device->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
 
267
    device->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
 
268
    device->SetRenderState(D3DRS_STENCILENABLE, FALSE);
 
269
    device->SetRenderState(D3DRS_CLIPPLANEENABLE, 0);
 
270
    device->SetRenderState(D3DRS_COLORWRITEENABLE, D3DCOLORWRITEENABLE_ALPHA | D3DCOLORWRITEENABLE_BLUE | D3DCOLORWRITEENABLE_GREEN | D3DCOLORWRITEENABLE_RED);
 
271
    device->SetRenderState(D3DRS_SRGBWRITEENABLE, FALSE);
 
272
    device->SetRenderState(D3DRS_SCISSORTESTENABLE, FALSE);
 
273
    device->SetPixelShader(NULL);
 
274
    device->SetVertexShader(NULL);
 
275
 
 
276
    device->SetRenderTarget(0, mBackBuffer);
 
277
    device->SetDepthStencilSurface(NULL);
 
278
 
 
279
    device->SetTexture(0, mOffscreenTexture);
 
280
    device->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
 
281
    device->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
 
282
    device->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE);
 
283
    device->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_POINT);
 
284
    device->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_POINT);
 
285
    device->SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP);
 
286
    device->SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP);
 
287
    device->SetFVF(D3DFVF_XYZRHW | D3DFVF_TEX1);
 
288
 
 
289
    for (UINT streamIndex = 0; streamIndex < gl::MAX_VERTEX_ATTRIBS; streamIndex++)
 
290
    {
 
291
        device->SetStreamSourceFreq(streamIndex, 1);
 
292
    }
 
293
 
 
294
    D3DVIEWPORT9 viewport = {0, 0, static_cast<DWORD>(mWidth), static_cast<DWORD>(mHeight), 0.0f, 1.0f};
 
295
    device->SetViewport(&viewport);
 
296
 
 
297
    float x1 = x - 0.5f;
 
298
    float y1 = (mHeight - y - height) - 0.5f;
 
299
    float x2 = (x + width) - 0.5f;
 
300
    float y2 = (mHeight - y) - 0.5f;
 
301
 
 
302
    float u1 = x / float(mWidth);
 
303
    float v1 = y / float(mHeight);
 
304
    float u2 = (x + width) / float(mWidth);
 
305
    float v2 = (y + height) / float(mHeight);
 
306
 
 
307
    float quad[4][6] = {{x1, y1, 0.0f, 1.0f, u1, v2},
 
308
                        {x2, y1, 0.0f, 1.0f, u2, v2},
 
309
                        {x2, y2, 0.0f, 1.0f, u2, v1},
 
310
                        {x1, y2, 0.0f, 1.0f, u1, v1}};   // x, y, z, rhw, u, v
 
311
 
 
312
    mRenderer->startScene();
 
313
    device->DrawPrimitiveUP(D3DPT_TRIANGLEFAN, 2, quad, 6 * sizeof(float));
 
314
    mRenderer->endScene();
 
315
 
 
316
    device->SetTexture(0, NULL);
 
317
 
 
318
    RECT rect =
 
319
    {
 
320
        static_cast<LONG>(x), static_cast<LONG>(mHeight - y - height),
 
321
        static_cast<LONG>(x + width), static_cast<LONG>(mHeight - y)
 
322
    };
 
323
 
 
324
    HRESULT result = mSwapChain->Present(&rect, &rect, NULL, NULL, 0);
 
325
 
 
326
    mRenderer->markAllStateDirty();
 
327
 
 
328
    if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY || result == D3DERR_DRIVERINTERNALERROR)
 
329
    {
 
330
        return EGL_BAD_ALLOC;
 
331
    }
 
332
 
 
333
    // On Windows 8 systems, IDirect3DSwapChain9::Present sometimes returns 0x88760873 when the windows is
 
334
    // in the process of entering/exiting fullscreen. This code doesn't seem to have any documentation.  The
 
335
    // device appears to be ok after emitting this error so simply return a failure to swap.
 
336
    if (result == 0x88760873)
 
337
    {
 
338
        return EGL_BAD_MATCH;
 
339
    }
 
340
 
 
341
    // http://crbug.com/313210
 
342
    // If our swap failed, trigger a device lost event. Resetting will work around an AMD-specific
 
343
    // device removed bug with lost contexts when reinstalling drivers.
 
344
    if (FAILED(result))
 
345
    {
 
346
        mRenderer->notifyDeviceLost();
 
347
        return EGL_CONTEXT_LOST;
 
348
    }
 
349
 
 
350
    return EGL_SUCCESS;
 
351
}
 
352
 
 
353
// Increments refcount on surface.
 
354
// caller must Release() the returned surface
 
355
// TODO: remove the AddRef to match SwapChain11
 
356
IDirect3DSurface9 *SwapChain9::getRenderTarget()
 
357
{
 
358
    if (mRenderTarget)
 
359
    {
 
360
        mRenderTarget->AddRef();
 
361
    }
 
362
 
 
363
    return mRenderTarget;
 
364
}
 
365
 
 
366
// Increments refcount on surface.
 
367
// caller must Release() the returned surface
 
368
// TODO: remove the AddRef to match SwapChain11
 
369
IDirect3DSurface9 *SwapChain9::getDepthStencil()
 
370
{
 
371
    if (mDepthStencil)
 
372
    {
 
373
        mDepthStencil->AddRef();
 
374
    }
 
375
 
 
376
    return mDepthStencil;
 
377
}
 
378
 
 
379
// Increments refcount on texture.
 
380
// caller must Release() the returned texture
 
381
// TODO: remove the AddRef to match SwapChain11
 
382
IDirect3DTexture9 *SwapChain9::getOffscreenTexture()
 
383
{
 
384
    if (mOffscreenTexture)
 
385
    {
 
386
        mOffscreenTexture->AddRef();
 
387
    }
 
388
 
 
389
    return mOffscreenTexture;
 
390
}
 
391
 
 
392
void *SwapChain9::getKeyedMutex()
 
393
{
 
394
    UNREACHABLE();
 
395
    return nullptr;
 
396
}
 
397
 
 
398
void SwapChain9::recreate()
 
399
{
 
400
    if (!mSwapChain)
 
401
    {
 
402
        return;
 
403
    }
 
404
 
 
405
    IDirect3DDevice9 *device = mRenderer->getDevice();
 
406
    if (device == NULL)
 
407
    {
 
408
        return;
 
409
    }
 
410
 
 
411
    D3DPRESENT_PARAMETERS presentParameters;
 
412
    HRESULT result = mSwapChain->GetPresentParameters(&presentParameters);
 
413
    ASSERT(SUCCEEDED(result));
 
414
 
 
415
    IDirect3DSwapChain9* newSwapChain = NULL;
 
416
    result = device->CreateAdditionalSwapChain(&presentParameters, &newSwapChain);
 
417
    if (FAILED(result))
 
418
    {
 
419
        return;
 
420
    }
 
421
 
 
422
    SafeRelease(mSwapChain);
 
423
    mSwapChain = newSwapChain;
 
424
 
 
425
    SafeRelease(mBackBuffer);
 
426
    result = mSwapChain->GetBackBuffer(0, D3DBACKBUFFER_TYPE_MONO, &mBackBuffer);
 
427
    ASSERT(SUCCEEDED(result));
 
428
}
 
429
 
 
430
}