diff options
Diffstat (limited to 'src/3rdparty/angle/src/libEGL/Surface.cpp')
-rw-r--r-- | src/3rdparty/angle/src/libEGL/Surface.cpp | 432 |
1 files changed, 85 insertions, 347 deletions
diff --git a/src/3rdparty/angle/src/libEGL/Surface.cpp b/src/3rdparty/angle/src/libEGL/Surface.cpp index d9e1887e85..5a62142b45 100644 --- a/src/3rdparty/angle/src/libEGL/Surface.cpp +++ b/src/3rdparty/angle/src/libEGL/Surface.cpp @@ -1,5 +1,5 @@ // -// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved. +// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // @@ -14,6 +14,8 @@ #include "common/debug.h" #include "libGLESv2/Texture.h" +#include "libGLESv2/renderer/SwapChain.h" +#include "libGLESv2/main.h" #include "libEGL/main.h" #include "libEGL/Display.h" @@ -23,14 +25,11 @@ namespace egl { -Surface::Surface(Display *display, const Config *config, HWND window, EGLint postSubBufferSupported) +Surface::Surface(Display *display, const Config *config, HWND window, EGLint postSubBufferSupported) : mDisplay(display), mConfig(config), mWindow(window), mPostSubBufferSupported(postSubBufferSupported) { + mRenderer = mDisplay->getRenderer(); mSwapChain = NULL; - mBackBuffer = NULL; - mDepthStencil = NULL; - mRenderTarget = NULL; - mOffscreenTexture = NULL; mShareHandle = NULL; mTexture = NULL; mTextureFormat = EGL_NO_TEXTURE; @@ -40,6 +39,8 @@ Surface::Surface(Display *display, const Config *config, HWND window, EGLint pos mRenderBuffer = EGL_BACK_BUFFER; mSwapBehavior = EGL_BUFFER_PRESERVED; mSwapInterval = -1; + mWidth = -1; + mHeight = -1; setSwapInterval(1); subclassWindow(); @@ -48,11 +49,8 @@ Surface::Surface(Display *display, const Config *config, HWND window, EGLint pos Surface::Surface(Display *display, const Config *config, HANDLE shareHandle, EGLint width, EGLint height, EGLenum textureFormat, EGLenum textureType) : mDisplay(display), mWindow(NULL), mConfig(config), mShareHandle(shareHandle), mWidth(width), mHeight(height), mPostSubBufferSupported(EGL_FALSE) { + mRenderer = mDisplay->getRenderer(); mSwapChain = NULL; - mBackBuffer = NULL; - mDepthStencil = NULL; - mRenderTarget = NULL; - mOffscreenTexture = NULL; mWindowSubclassed = false; mTexture = NULL; mTextureFormat = textureFormat; @@ -76,8 +74,6 @@ bool Surface::initialize() typedef HRESULT (STDAPICALLTYPE *PtrDwmIsCompositionEnabled)(BOOL*); typedef HRESULT (STDAPICALLTYPE *PtrDwmSetPresentParameters)(HWND, DWM_PRESENT_PARAMETERS *); - ASSERT(!mSwapChain && !mOffscreenTexture && !mDepthStencil); - if (!resetSwapChain()) return false; @@ -118,260 +114,106 @@ bool Surface::initialize() void Surface::release() { - if (mSwapChain) - { - mSwapChain->Release(); - mSwapChain = NULL; - } - - if (mBackBuffer) - { - mBackBuffer->Release(); - mBackBuffer = NULL; - } - - if (mDepthStencil) - { - mDepthStencil->Release(); - mDepthStencil = NULL; - } - - if (mRenderTarget) - { - mRenderTarget->Release(); - mRenderTarget = NULL; - } - - if (mOffscreenTexture) - { - mOffscreenTexture->Release(); - mOffscreenTexture = NULL; - } + delete mSwapChain; + mSwapChain = NULL; if (mTexture) { mTexture->releaseTexImage(); mTexture = NULL; } - - mShareHandle = NULL; } bool Surface::resetSwapChain() { - if (!mWindow) - { - return resetSwapChain(mWidth, mHeight); - } - - RECT windowRect; - if (!GetClientRect(getWindowHandle(), &windowRect)) - { - ASSERT(false); + ASSERT(!mSwapChain); - ERR("Could not retrieve the window dimensions"); - return false; - } - - return resetSwapChain(windowRect.right - windowRect.left, windowRect.bottom - windowRect.top); -} + int width; + int height; -bool Surface::resetSwapChain(int backbufferWidth, int backbufferHeight) -{ - IDirect3DDevice9 *device = mDisplay->getDevice(); - - if (device == NULL) + if (mWindow) { - return false; - } - - // Evict all non-render target textures to system memory and release all resources - // before reallocating them to free up as much video memory as possible. - device->EvictManagedResources(); - - HRESULT result; + RECT windowRect; + if (!GetClientRect(getWindowHandle(), &windowRect)) + { + ASSERT(false); - // Release specific resources to free up memory for the new render target, while the - // old render target still exists for the purpose of preserving its contents. - if (mSwapChain) - { - mSwapChain->Release(); - mSwapChain = NULL; - } + ERR("Could not retrieve the window dimensions"); + return error(EGL_BAD_SURFACE, false); + } - if (mBackBuffer) - { - mBackBuffer->Release(); - mBackBuffer = NULL; + width = windowRect.right - windowRect.left; + height = windowRect.bottom - windowRect.top; } - - if (mOffscreenTexture) + else { - mOffscreenTexture->Release(); - mOffscreenTexture = NULL; + // non-window surface - size is determined at creation + width = mWidth; + height = mHeight; } - if (mDepthStencil) + mSwapChain = mRenderer->createSwapChain(mWindow, mShareHandle, + mConfig->mRenderTargetFormat, + mConfig->mDepthStencilFormat); + if (!mSwapChain) { - mDepthStencil->Release(); - mDepthStencil = NULL; + return error(EGL_BAD_ALLOC, false); } - HANDLE *pShareHandle = NULL; - if (!mWindow && mDisplay->shareHandleSupported()) + if (!resetSwapChain(width, height)) { - pShareHandle = &mShareHandle; + delete mSwapChain; + mSwapChain = NULL; + return false; } - // CreateTexture will fail on zero dimensions, so just release old target - if (!backbufferWidth || !backbufferHeight) - { - if (mRenderTarget) - { - mRenderTarget->Release(); - mRenderTarget = NULL; - } + return true; +} - mWidth = backbufferWidth; - mHeight = backbufferHeight; - mPresentIntervalDirty = false; +bool Surface::resizeSwapChain(int backbufferWidth, int backbufferHeight) +{ + ASSERT(backbufferWidth >= 0 && backbufferHeight >= 0); + ASSERT(mSwapChain); - return true; - } + EGLint status = mSwapChain->resize(backbufferWidth, backbufferHeight); - result = device->CreateTexture(backbufferWidth, backbufferHeight, 1, D3DUSAGE_RENDERTARGET, - mConfig->mRenderTargetFormat, D3DPOOL_DEFAULT, &mOffscreenTexture, pShareHandle); - if (FAILED(result)) + if (status == EGL_CONTEXT_LOST) { - ERR("Could not create offscreen texture: %08lX", result); - release(); - - if(isDeviceLostError(result)) - { - mDisplay->notifyDeviceLost(); - return false; - } - else - { - return error(EGL_BAD_ALLOC, false); - } + mDisplay->notifyDeviceLost(); + return false; } - - IDirect3DSurface9 *oldRenderTarget = mRenderTarget; - - result = mOffscreenTexture->GetSurfaceLevel(0, &mRenderTarget); - ASSERT(SUCCEEDED(result)); - - if (oldRenderTarget) + else if (status != EGL_SUCCESS) { - RECT rect = - { - 0, 0, - mWidth, mHeight - }; - - if (rect.right > static_cast<LONG>(backbufferWidth)) - { - rect.right = backbufferWidth; - } + return error(status, false); + } - if (rect.bottom > static_cast<LONG>(backbufferHeight)) - { - rect.bottom = backbufferHeight; - } + mWidth = backbufferWidth; + mHeight = backbufferHeight; - mDisplay->endScene(); + return true; +} - result = device->StretchRect(oldRenderTarget, &rect, mRenderTarget, &rect, D3DTEXF_NONE); - ASSERT(SUCCEEDED(result)); +bool Surface::resetSwapChain(int backbufferWidth, int backbufferHeight) +{ + ASSERT(backbufferWidth >= 0 && backbufferHeight >= 0); + ASSERT(mSwapChain); - oldRenderTarget->Release(); - } + EGLint status = mSwapChain->reset(backbufferWidth, backbufferHeight, mSwapInterval); - if (mWindow) + if (status == EGL_CONTEXT_LOST) { - D3DPRESENT_PARAMETERS presentParameters = {0}; - presentParameters.AutoDepthStencilFormat = mConfig->mDepthStencilFormat; - presentParameters.BackBufferCount = 1; - presentParameters.BackBufferFormat = mConfig->mRenderTargetFormat; - presentParameters.EnableAutoDepthStencil = FALSE; - presentParameters.Flags = 0; - presentParameters.hDeviceWindow = getWindowHandle(); - presentParameters.MultiSampleQuality = 0; // FIXME: Unimplemented - presentParameters.MultiSampleType = D3DMULTISAMPLE_NONE; // FIXME: Unimplemented - presentParameters.PresentationInterval = mPresentInterval; - presentParameters.SwapEffect = D3DSWAPEFFECT_DISCARD; - presentParameters.Windowed = TRUE; - presentParameters.BackBufferWidth = backbufferWidth; - presentParameters.BackBufferHeight = backbufferHeight; - - // http://crbug.com/140239 - // http://crbug.com/143434 - // - // Some AMD/Intel switchable systems / drivers appear to round swap chain surfaces to a multiple of 64 pixels in width - // when using the integrated Intel. This rounds the width up rather than down. - // - // Some non-switchable AMD GPUs / drivers do not respect the source rectangle to Present. Therefore, when the vendor ID - // is not Intel, the back buffer width must be exactly the same width as the window or horizontal scaling will occur. - D3DADAPTER_IDENTIFIER9* adapterIdentifier = mDisplay->getAdapterIdentifier(); - if (adapterIdentifier->VendorId == VENDOR_ID_INTEL) - { - presentParameters.BackBufferWidth = (presentParameters.BackBufferWidth + 63) / 64 * 64; - } - - result = device->CreateAdditionalSwapChain(&presentParameters, &mSwapChain); - - if (FAILED(result)) - { - ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY || result == D3DERR_INVALIDCALL || result == D3DERR_DEVICELOST); - - ERR("Could not create additional swap chains or offscreen surfaces: %08lX", result); - release(); - - if(isDeviceLostError(result)) - { - mDisplay->notifyDeviceLost(); - return false; - } - else - { - return error(EGL_BAD_ALLOC, false); - } - } - - result = mSwapChain->GetBackBuffer(0, D3DBACKBUFFER_TYPE_MONO, &mBackBuffer); - ASSERT(SUCCEEDED(result)); - InvalidateRect(mWindow, NULL, FALSE); + mRenderer->notifyDeviceLost(); + return false; } - - if (mConfig->mDepthStencilFormat != D3DFMT_UNKNOWN) + else if (status != EGL_SUCCESS) { - result = device->CreateDepthStencilSurface(backbufferWidth, backbufferHeight, mConfig->mDepthStencilFormat, D3DMULTISAMPLE_NONE, - 0, FALSE, &mDepthStencil, NULL); - - if (FAILED(result)) - { - ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY || result == D3DERR_INVALIDCALL); - - ERR("Could not create depthstencil surface for new swap chain: 0x%08X", result); - release(); - - if(isDeviceLostError(result)) - { - mDisplay->notifyDeviceLost(); - return false; - } - else - { - return error(EGL_BAD_ALLOC, false); - } - } + return error(status, false); } mWidth = backbufferWidth; mHeight = backbufferHeight; + mSwapIntervalDirty = false; - mPresentIntervalDirty = false; return true; } @@ -397,86 +239,18 @@ bool Surface::swapRect(EGLint x, EGLint y, EGLint width, EGLint height) return true; } - IDirect3DDevice9 *device = mDisplay->getDevice(); - - // Disable all pipeline operations - device->SetRenderState(D3DRS_ZENABLE, D3DZB_FALSE); - device->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID); - device->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE); - device->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE); - device->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE); - device->SetRenderState(D3DRS_STENCILENABLE, FALSE); - device->SetRenderState(D3DRS_CLIPPLANEENABLE, 0); - device->SetRenderState(D3DRS_COLORWRITEENABLE, D3DCOLORWRITEENABLE_ALPHA | D3DCOLORWRITEENABLE_BLUE | D3DCOLORWRITEENABLE_GREEN | D3DCOLORWRITEENABLE_RED); - device->SetRenderState(D3DRS_SRGBWRITEENABLE, FALSE); - device->SetRenderState(D3DRS_SCISSORTESTENABLE, FALSE); - device->SetPixelShader(NULL); - device->SetVertexShader(NULL); - - device->SetRenderTarget(0, mBackBuffer); - device->SetDepthStencilSurface(NULL); - - device->SetTexture(0, mOffscreenTexture); - device->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1); - device->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE); - device->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE); - device->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_POINT); - device->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_POINT); - device->SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP); - device->SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP); - device->SetFVF(D3DFVF_XYZRHW | D3DFVF_TEX1); - - D3DVIEWPORT9 viewport = {0, 0, mWidth, mHeight, 0.0f, 1.0f}; - device->SetViewport(&viewport); - - float x1 = x - 0.5f; - float y1 = (mHeight - y - height) - 0.5f; - float x2 = (x + width) - 0.5f; - float y2 = (mHeight - y) - 0.5f; - - float u1 = x / float(mWidth); - float v1 = y / float(mHeight); - float u2 = (x + width) / float(mWidth); - float v2 = (y + height) / float(mHeight); - - float quad[4][6] = {{x1, y1, 0.0f, 1.0f, u1, v2}, - {x2, y1, 0.0f, 1.0f, u2, v2}, - {x2, y2, 0.0f, 1.0f, u2, v1}, - {x1, y2, 0.0f, 1.0f, u1, v1}}; // x, y, z, rhw, u, v - - mDisplay->startScene(); - device->DrawPrimitiveUP(D3DPT_TRIANGLEFAN, 2, quad, 6 * sizeof(float)); - mDisplay->endScene(); - - device->SetTexture(0, NULL); - - RECT rect = - { - x, mHeight - y - height, - x + width, mHeight - y - }; - - HRESULT result = mSwapChain->Present(&rect, &rect, NULL, NULL, 0); - - gl::Context *context = static_cast<gl::Context*>(glGetCurrentContext()); - if (context) - { - context->markAllStateDirty(); - } + EGLint status = mSwapChain->swapRect(x, y, width, height); - if (isDeviceLostError(result)) + if (status == EGL_CONTEXT_LOST) { - mDisplay->notifyDeviceLost(); + mRenderer->notifyDeviceLost(); return false; } - - if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY || result == D3DERR_DRIVERINTERNALERROR) + else if (status != EGL_SUCCESS) { - return error(EGL_BAD_ALLOC, false); + return error(status, false); } - ASSERT(SUCCEEDED(result)); - checkForOutOfDateSwapChain(); return true; @@ -572,9 +346,17 @@ bool Surface::checkForOutOfDateSwapChain() int clientHeight = client.bottom - client.top; bool sizeDirty = clientWidth != getWidth() || clientHeight != getHeight(); - if (sizeDirty || mPresentIntervalDirty) + if (mSwapIntervalDirty) { resetSwapChain(clientWidth, clientHeight); + } + else if (sizeDirty) + { + resizeSwapChain(clientWidth, clientHeight); + } + + if (mSwapIntervalDirty || sizeDirty) + { if (static_cast<egl::Surface*>(getCurrentDrawSurface()) == this) { glMakeCurrent(glGetCurrentContext(), static_cast<egl::Display*>(getCurrentDisplay()), this); @@ -582,22 +364,8 @@ bool Surface::checkForOutOfDateSwapChain() return true; } - return false; -} - -DWORD Surface::convertInterval(EGLint interval) -{ - switch(interval) - { - case 0: return D3DPRESENT_INTERVAL_IMMEDIATE; - case 1: return D3DPRESENT_INTERVAL_ONE; - case 2: return D3DPRESENT_INTERVAL_TWO; - case 3: return D3DPRESENT_INTERVAL_THREE; - case 4: return D3DPRESENT_INTERVAL_FOUR; - default: UNREACHABLE(); - } - return D3DPRESENT_INTERVAL_DEFAULT; + return false; } bool Surface::swap() @@ -631,38 +399,9 @@ EGLint Surface::isPostSubBufferSupported() const return mPostSubBufferSupported; } -// Increments refcount on surface. -// caller must Release() the returned surface -IDirect3DSurface9 *Surface::getRenderTarget() -{ - if (mRenderTarget) - { - mRenderTarget->AddRef(); - } - - return mRenderTarget; -} - -// Increments refcount on surface. -// caller must Release() the returned surface -IDirect3DSurface9 *Surface::getDepthStencil() -{ - if (mDepthStencil) - { - mDepthStencil->AddRef(); - } - - return mDepthStencil; -} - -IDirect3DTexture9 *Surface::getOffscreenTexture() +rx::SwapChain *Surface::getSwapChain() const { - if (mOffscreenTexture) - { - mOffscreenTexture->AddRef(); - } - - return mOffscreenTexture; + return mSwapChain; } void Surface::setSwapInterval(EGLint interval) @@ -673,11 +412,10 @@ void Surface::setSwapInterval(EGLint interval) } mSwapInterval = interval; - mSwapInterval = std::max(mSwapInterval, mDisplay->getMinSwapInterval()); - mSwapInterval = std::min(mSwapInterval, mDisplay->getMaxSwapInterval()); + mSwapInterval = std::max(mSwapInterval, mRenderer->getMinSwapInterval()); + mSwapInterval = std::min(mSwapInterval, mRenderer->getMaxSwapInterval()); - mPresentInterval = convertInterval(mSwapInterval); - mPresentIntervalDirty = true; + mSwapIntervalDirty = true; } EGLenum Surface::getTextureFormat() const @@ -700,7 +438,7 @@ gl::Texture2D *Surface::getBoundTexture() const return mTexture; } -D3DFORMAT Surface::getFormat() const +EGLenum Surface::getFormat() const { return mConfig->mRenderTargetFormat; } |