diff options
Diffstat (limited to 'Source/ThirdParty/ANGLE/src/libEGL/Surface.cpp')
-rw-r--r-- | Source/ThirdParty/ANGLE/src/libEGL/Surface.cpp | 596 |
1 files changed, 368 insertions, 228 deletions
diff --git a/Source/ThirdParty/ANGLE/src/libEGL/Surface.cpp b/Source/ThirdParty/ANGLE/src/libEGL/Surface.cpp index 2736a7f..07ad3cf 100644 --- a/Source/ThirdParty/ANGLE/src/libEGL/Surface.cpp +++ b/Source/ThirdParty/ANGLE/src/libEGL/Surface.cpp @@ -13,21 +13,43 @@ #include "libEGL/Surface.h" #include "common/debug.h" +#include "libGLESv2/Texture.h" #include "libEGL/main.h" #include "libEGL/Display.h" +#include <dwmapi.h> + namespace egl { -Surface::Surface(Display *display, const Config *config, HWND window) - : mDisplay(display), mConfig(config), mWindow(window) + +namespace +{ +const int versionWindowsVista = MAKEWORD(0x00, 0x06); +const int versionWindows7 = MAKEWORD(0x01, 0x06); + +// Return the version of the operating system in a format suitable for ordering +// comparison. +int getComparableOSVersion() +{ + DWORD version = GetVersion(); + int majorVersion = LOBYTE(LOWORD(version)); + int minorVersion = HIBYTE(LOWORD(version)); + return MAKEWORD(minorVersion, majorVersion); +} +} + +Surface::Surface(Display *display, const Config *config, HWND window, EGLint postSubBufferSupported) + : mDisplay(display), mConfig(config), mWindow(window), mPostSubBufferSupported(postSubBufferSupported) { mSwapChain = NULL; mDepthStencil = NULL; - mBackBuffer = NULL; - mFlipTexture = NULL; - mFlipState = NULL; - mPreFlipState = NULL; + mRenderTarget = NULL; + mOffscreenTexture = NULL; + mShareHandle = NULL; + mTexture = NULL; + mTextureFormat = EGL_NO_TEXTURE; + mTextureTarget = EGL_NO_TEXTURE; mPixelAspectRatio = (EGLint)(1.0 * EGL_DISPLAY_SCALING); // FIXME: Determine actual pixel aspect ratio mRenderBuffer = EGL_BACK_BUFFER; @@ -36,7 +58,25 @@ Surface::Surface(Display *display, const Config *config, HWND window) setSwapInterval(1); subclassWindow(); - resetSwapChain(); +} + +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) +{ + mSwapChain = NULL; + mDepthStencil = NULL; + mRenderTarget = NULL; + mOffscreenTexture = NULL; + mWindowSubclassed = false; + mTexture = NULL; + mTextureFormat = textureFormat; + mTextureTarget = textureType; + + mPixelAspectRatio = (EGLint)(1.0 * EGL_DISPLAY_SCALING); // FIXME: Determine actual pixel aspect ratio + mRenderBuffer = EGL_BACK_BUFFER; + mSwapBehavior = EGL_BUFFER_PRESERVED; + mSwapInterval = -1; + setSwapInterval(1); } Surface::~Surface() @@ -45,6 +85,34 @@ Surface::~Surface() release(); } +bool Surface::initialize() +{ + ASSERT(!mSwapChain && !mOffscreenTexture && !mDepthStencil); + + if (!resetSwapChain()) + return false; + + // Modify present parameters for this window, if we are composited, + // to minimize the amount of queuing done by DWM between our calls to + // present and the actual screen. + if (mWindow && (getComparableOSVersion() >= versionWindowsVista)) { + BOOL isComposited; + HRESULT result = DwmIsCompositionEnabled(&isComposited); + if (SUCCEEDED(result) && isComposited) { + DWM_PRESENT_PARAMETERS presentParams; + memset(&presentParams, 0, sizeof(presentParams)); + presentParams.cbSize = sizeof(DWM_PRESENT_PARAMETERS); + presentParams.cBuffer = 2; + + result = DwmSetPresentParameters(mWindow, &presentParams); + if (FAILED(result)) + ERR("Unable to set present parameters: 0x%08X", result); + } + } + + return true; +} + void Surface::release() { if (mSwapChain) @@ -53,68 +121,116 @@ void Surface::release() mSwapChain = NULL; } - if (mBackBuffer) - { - mBackBuffer->Release(); - mBackBuffer = NULL; - } - if (mDepthStencil) { mDepthStencil->Release(); mDepthStencil = NULL; } - if (mFlipTexture) + if (mRenderTarget) { - mFlipTexture->Release(); - mFlipTexture = NULL; + mRenderTarget->Release(); + mRenderTarget = NULL; } - if (mFlipState) + if (mOffscreenTexture) { - mFlipState->Release(); - mFlipState = NULL; + mOffscreenTexture->Release(); + mOffscreenTexture = NULL; } - if (mPreFlipState) + if (mTexture) { - mPreFlipState->Release(); - mPreFlipState = NULL; + mTexture->releaseTexImage(); + mTexture = NULL; } } -void Surface::resetSwapChain() +bool Surface::resetSwapChain() { + if (!mWindow) + { + return resetSwapChain(mWidth, mHeight); + } + RECT windowRect; if (!GetClientRect(getWindowHandle(), &windowRect)) { ASSERT(false); ERR("Could not retrieve the window dimensions"); - return; + return false; } - resetSwapChain(windowRect.right - windowRect.left, windowRect.bottom - windowRect.top); + return resetSwapChain(windowRect.right - windowRect.left, windowRect.bottom - windowRect.top); } -void Surface::resetSwapChain(int backbufferWidth, int backbufferHeight) +bool Surface::resetSwapChain(int backbufferWidth, int backbufferHeight) { IDirect3DDevice9 *device = mDisplay->getDevice(); if (device == NULL) { - return; + return false; + } + + IDirect3DSurface9* preservedRenderTarget = NULL; + if (mPostSubBufferSupported && mRenderTarget) + { + preservedRenderTarget = mRenderTarget; + preservedRenderTarget->AddRef(); } // 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(); release(); - + D3DPRESENT_PARAMETERS presentParameters = {0}; + HRESULT result; + + bool useFlipEx = (getComparableOSVersion() >= versionWindows7) && mDisplay->isD3d9ExDevice(); + + // FlipEx causes unseemly stretching when resizing windows AND when one + // draws outside of the WM_PAINT callback. While this is seldom a problem in + // single process applications, it is particuarly noticeable in multiprocess + // applications. Therefore, if the creator process of our window is not in + // the current process, disable use of FlipEx. + DWORD windowPID; + GetWindowThreadProcessId(mWindow, &windowPID); + if (windowPID != GetCurrentProcessId()) + { + useFlipEx = false; + } + + // Various hardware does not support D3DSWAPEFFECT_FLIPEX when either the + // device format or back buffer format is not 32-bit. + HDC deviceContext = GetDC(0); + int deviceFormatBits = GetDeviceCaps(deviceContext, BITSPIXEL); + ReleaseDC(0, deviceContext); + if (mConfig->mBufferSize != 32 || deviceFormatBits != 32) + { + useFlipEx = false; + } + + // D3DSWAPEFFECT_FLIPEX is always VSYNCed + if (mSwapInterval == 0) + { + useFlipEx = false; + } + + // D3DSWAPEFFECT_FLIPEX does not preserve the back buffer. + if (mPostSubBufferSupported) + { + useFlipEx = false; + } presentParameters.AutoDepthStencilFormat = mConfig->mDepthStencilFormat; + // We set BackBufferCount = 1 even when we use D3DSWAPEFFECT_FLIPEX. + // We do this because DirectX docs are a bit vague whether to set this to 1 + // or 2. The runtime seems to accept 1, so we speculate that either it is + // forcing it to 2 without telling us, or better, doing something smart + // behind the scenes knowing that we don't need more. presentParameters.BackBufferCount = 1; presentParameters.BackBufferFormat = mConfig->mRenderTargetFormat; presentParameters.EnableAutoDepthStencil = FALSE; @@ -123,200 +239,131 @@ void Surface::resetSwapChain(int backbufferWidth, int backbufferHeight) presentParameters.MultiSampleQuality = 0; // FIXME: Unimplemented presentParameters.MultiSampleType = D3DMULTISAMPLE_NONE; // FIXME: Unimplemented presentParameters.PresentationInterval = mPresentInterval; - presentParameters.SwapEffect = D3DSWAPEFFECT_DISCARD; + // Use flipEx on Win7 or greater. + if(useFlipEx) + presentParameters.SwapEffect = D3DSWAPEFFECT_FLIPEX; + else + presentParameters.SwapEffect = mPostSubBufferSupported ? D3DSWAPEFFECT_COPY : D3DSWAPEFFECT_DISCARD; presentParameters.Windowed = TRUE; presentParameters.BackBufferWidth = backbufferWidth; presentParameters.BackBufferHeight = backbufferHeight; - HRESULT result = device->CreateAdditionalSwapChain(&presentParameters, &mSwapChain); - - if (FAILED(result)) + if (mWindow) { - ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY); + result = device->CreateAdditionalSwapChain(&presentParameters, &mSwapChain); + } else { + HANDLE *pShareHandle = NULL; + if (mDisplay->shareHandleSupported()) { + pShareHandle = &mShareHandle; + } - ERR("Could not create additional swap chains: %08lX", result); - release(); - return error(EGL_BAD_ALLOC); + result = device->CreateTexture(presentParameters.BackBufferWidth, presentParameters.BackBufferHeight, 1, D3DUSAGE_RENDERTARGET, + presentParameters.BackBufferFormat, D3DPOOL_DEFAULT, &mOffscreenTexture, pShareHandle); } - result = device->CreateDepthStencilSurface(presentParameters.BackBufferWidth, presentParameters.BackBufferHeight, - presentParameters.AutoDepthStencilFormat, presentParameters.MultiSampleType, - presentParameters.MultiSampleQuality, FALSE, &mDepthStencil, NULL); - if (FAILED(result)) { - ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY); + ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY || result == D3DERR_INVALIDCALL || result == D3DERR_DEVICELOST); - ERR("Could not create depthstencil surface for new swap chain: %08lX", result); + ERR("Could not create additional swap chains or offscreen surfaces: %08lX", result); release(); - return error(EGL_BAD_ALLOC); - } - ASSERT(SUCCEEDED(result)); - - result = device->CreateTexture(presentParameters.BackBufferWidth, presentParameters.BackBufferHeight, 1, D3DUSAGE_RENDERTARGET, - presentParameters.BackBufferFormat, D3DPOOL_DEFAULT, &mFlipTexture, NULL); - - if (FAILED(result)) - { - ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY); - - ERR("Could not create flip texture for new swap chain: %08lX", result); - release(); - return error(EGL_BAD_ALLOC); - } - - mSwapChain->GetBackBuffer(0, D3DBACKBUFFER_TYPE_MONO, &mBackBuffer); - mWidth = presentParameters.BackBufferWidth; - mHeight = presentParameters.BackBufferHeight; - - mPresentIntervalDirty = false; - - InvalidateRect(mWindow, NULL, FALSE); - - // The flip state block recorded mFlipTexture so it is now invalid. - releaseRecordedState(device); -} - -HWND Surface::getWindowHandle() -{ - return mWindow; -} - -void Surface::writeRecordableFlipState(IDirect3DDevice9 *device) -{ - // 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); - - // Just sample the texture - device->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1); - device->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE); - device->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE); - device->SetTexture(0, NULL); // The actual texture will change after resizing. But the pre-flip state block must save/restore the texture. - device->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_POINT); - device->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_POINT); - device->SetSamplerState(0, D3DSAMP_SRGBTEXTURE, FALSE); - device->SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP); - device->SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP); - device->SetFVF(D3DFVF_XYZRHW | D3DFVF_TEX1); - - RECT scissorRect = {0}; // Scissoring is disabled for flipping, but we need this to capture and restore the old rectangle - device->SetScissorRect(&scissorRect); - D3DVIEWPORT9 viewport = {0, 0, mWidth, mHeight, 0.0f, 1.0f}; - device->SetViewport(&viewport); -} - -void Surface::applyFlipState(IDirect3DDevice9 *device) -{ - HRESULT hr; - - if (mFlipState == NULL) - { - // Create two state blocks both recording the states that are changed when swapping. - - // mPreFlipState will record the original state each entry. - hr = device->BeginStateBlock(); - ASSERT(SUCCEEDED(hr)); - writeRecordableFlipState(device); - hr = device->EndStateBlock(&mPreFlipState); - ASSERT(SUCCEEDED(hr) || hr == D3DERR_OUTOFVIDEOMEMORY || hr == E_OUTOFMEMORY); - - if (SUCCEEDED(hr)) + + if (preservedRenderTarget) { - mPreFlipState->Capture(); + preservedRenderTarget->Release(); + preservedRenderTarget = NULL; } - // mFlipState will record the state for the swap operation. - hr = device->BeginStateBlock(); - ASSERT(SUCCEEDED(hr)); - - writeRecordableFlipState(device); - - hr = device->EndStateBlock(&mFlipState); - ASSERT(SUCCEEDED(hr) || hr == D3DERR_OUTOFVIDEOMEMORY || hr == E_OUTOFMEMORY); - - if (FAILED(hr)) + if(isDeviceLostError(result)) { - mFlipState = NULL; - mPreFlipState->Release(); - mPreFlipState = NULL; + mDisplay->notifyDeviceLost(); + return false; } else { - hr = mFlipState->Apply(); - ASSERT(SUCCEEDED(hr)); + return error(EGL_BAD_ALLOC, false); + } + } + + if (mWindow) + { + mSwapChain->GetBackBuffer(0, D3DBACKBUFFER_TYPE_MONO, &mRenderTarget); + if (!preservedRenderTarget) + { + InvalidateRect(mWindow, NULL, FALSE); } } else { - hr = mPreFlipState->Capture(); - ASSERT(SUCCEEDED(hr)); - hr = mFlipState->Apply(); - ASSERT(SUCCEEDED(hr)); + mOffscreenTexture->GetSurfaceLevel(0, &mRenderTarget); } - device->GetRenderTarget(0, &mPreFlipBackBuffer); - device->GetDepthStencilSurface(&mPreFlipDepthStencil); + if (preservedRenderTarget) + { + RECT rect = + { + 0, 0, + mWidth, mHeight + }; - device->SetRenderTarget(0, mBackBuffer); - device->SetDepthStencilSurface(NULL); -} + if (rect.right > static_cast<LONG>(presentParameters.BackBufferWidth)) + { + rect.right = presentParameters.BackBufferWidth; + } -void Surface::restoreState(IDirect3DDevice9 *device) -{ - device->SetRenderTarget(0, mPreFlipBackBuffer); - device->SetDepthStencilSurface(mPreFlipDepthStencil); + if (rect.bottom > static_cast<LONG>(presentParameters.BackBufferHeight)) + { + rect.bottom = presentParameters.BackBufferHeight; + } - if (mPreFlipBackBuffer) + mDisplay->endScene(); + device->StretchRect(preservedRenderTarget, &rect, mRenderTarget, &rect, D3DTEXF_NONE); + + preservedRenderTarget->Release(); + preservedRenderTarget = NULL; + } + + if (mConfig->mDepthStencilFormat != D3DFMT_UNKNOWN) { - mPreFlipBackBuffer->Release(); - mPreFlipBackBuffer = NULL; + result = device->CreateDepthStencilSurface(presentParameters.BackBufferWidth, presentParameters.BackBufferHeight, + presentParameters.AutoDepthStencilFormat, presentParameters.MultiSampleType, + presentParameters.MultiSampleQuality, FALSE, &mDepthStencil, NULL); } - if (mPreFlipDepthStencil) + if (FAILED(result)) { - mPreFlipDepthStencil->Release(); - mPreFlipDepthStencil = NULL; + ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY || result == D3DERR_INVALIDCALL); + + ERR("Could not create depthstencil surface for new swap chain: 0x%08X", result); + release(); + return error(EGL_BAD_ALLOC, false); } - mPreFlipState->Apply(); + mWidth = presentParameters.BackBufferWidth; + mHeight = presentParameters.BackBufferHeight; + + mPresentIntervalDirty = false; + return true; } -// On the next flip, this will cause the state to be recorded from scratch. -// In particular we need to do this if the flip texture changes. -void Surface::releaseRecordedState(IDirect3DDevice9 *device) +HWND Surface::getWindowHandle() { - if (mFlipState) - { - mFlipState->Release(); - mFlipState = NULL; - } - - if (mPreFlipState) - { - mPreFlipState->Release(); - mPreFlipState = NULL; - } + return mWindow; } + + #define kSurfaceProperty _TEXT("Egl::SurfaceOwner") #define kParentWndProc _TEXT("Egl::SurfaceParentWndProc") -static LRESULT CALLBACK SurfaceWindowProc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam) { - if (message == WM_SIZE) { +static LRESULT CALLBACK SurfaceWindowProc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam) +{ + if (message == WM_SIZE) + { Surface* surf = reinterpret_cast<Surface*>(GetProp(hwnd, kSurfaceProperty)); - if(surf) { - surf->checkForOutOfDateSwapChain(); + if(surf) + { + surf->checkForOutOfDateSwapChain(); } } WNDPROC prevWndFunc = reinterpret_cast<WNDPROC >(GetProp(hwnd, kParentWndProc)); @@ -325,39 +372,55 @@ static LRESULT CALLBACK SurfaceWindowProc(HWND hwnd, UINT message, WPARAM wparam void Surface::subclassWindow() { - SetLastError(0); - LONG oldWndProc = SetWindowLong(mWindow, GWL_WNDPROC, reinterpret_cast<LONG>(SurfaceWindowProc)); - if(oldWndProc == 0 && GetLastError() != ERROR_SUCCESS) { - mWindowSubclassed = false; - return; - } + if (!mWindow) + { + return; + } - SetProp(mWindow, kSurfaceProperty, reinterpret_cast<HANDLE>(this)); - SetProp(mWindow, kParentWndProc, reinterpret_cast<HANDLE>(oldWndProc)); - mWindowSubclassed = true; + DWORD processId; + DWORD threadId = GetWindowThreadProcessId(mWindow, &processId); + if (processId != GetCurrentProcessId() || threadId != GetCurrentThreadId()) + { + return; + } + + SetLastError(0); + LONG_PTR oldWndProc = SetWindowLongPtr(mWindow, GWLP_WNDPROC, reinterpret_cast<LONG_PTR>(SurfaceWindowProc)); + if(oldWndProc == 0 && GetLastError() != ERROR_SUCCESS) + { + mWindowSubclassed = false; + return; + } + + SetProp(mWindow, kSurfaceProperty, reinterpret_cast<HANDLE>(this)); + SetProp(mWindow, kParentWndProc, reinterpret_cast<HANDLE>(oldWndProc)); + mWindowSubclassed = true; } void Surface::unsubclassWindow() { - if(!mWindowSubclassed) - return; - - // un-subclass - LONG parentWndFunc = reinterpret_cast<LONG>(GetProp(mWindow, kParentWndProc)); - - // Check the windowproc is still SurfaceWindowProc. - // If this assert fails, then it is likely the application has subclassed the - // hwnd as well and did not unsubclass before destroying its EGL context. The - // application should be modified to either subclass before initializing the - // EGL context, or to unsubclass before destroying the EGL context. - if(parentWndFunc) { - LONG prevWndFunc = SetWindowLong(mWindow, GWL_WNDPROC, parentWndFunc); - ASSERT(prevWndFunc == reinterpret_cast<LONG>(SurfaceWindowProc)); - } + if(!mWindowSubclassed) + { + return; + } + + // un-subclass + LONG_PTR parentWndFunc = reinterpret_cast<LONG_PTR>(GetProp(mWindow, kParentWndProc)); - RemoveProp(mWindow, kSurfaceProperty); - RemoveProp(mWindow, kParentWndProc); - mWindowSubclassed = false; + // Check the windowproc is still SurfaceWindowProc. + // If this assert fails, then it is likely the application has subclassed the + // hwnd as well and did not unsubclass before destroying its EGL context. The + // application should be modified to either subclass before initializing the + // EGL context, or to unsubclass before destroying the EGL context. + if(parentWndFunc) + { + LONG_PTR prevWndFunc = SetWindowLongPtr(mWindow, GWLP_WNDPROC, parentWndFunc); + ASSERT(prevWndFunc == reinterpret_cast<LONG_PTR>(SurfaceWindowProc)); + } + + RemoveProp(mWindow, kSurfaceProperty); + RemoveProp(mWindow, kParentWndProc); + mWindowSubclassed = false; } bool Surface::checkForOutOfDateSwapChain() @@ -402,40 +465,79 @@ DWORD Surface::convertInterval(EGLint interval) return D3DPRESENT_INTERVAL_DEFAULT; } - bool Surface::swap() { if (mSwapChain) { - IDirect3DDevice9 *device = mDisplay->getDevice(); + mDisplay->endScene(); + + HRESULT result = mSwapChain->Present(NULL, NULL, NULL, NULL, 0); + + if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY) + { + return error(EGL_BAD_ALLOC, false); + } + + if (isDeviceLostError(result)) + { + mDisplay->notifyDeviceLost(); + return false; + } - applyFlipState(device); - device->SetTexture(0, mFlipTexture); + ASSERT(SUCCEEDED(result)); - // Render the texture upside down into the back buffer - // Texcoords are chosen to flip the renderTarget about its Y axis. - float w = static_cast<float>(getWidth()); - float h = static_cast<float>(getHeight()); - float quad[4][6] = {{0 - 0.5f, 0 - 0.5f, 0.0f, 1.0f, 0.0f, 1.0f}, - {w - 0.5f, 0 - 0.5f, 0.0f, 1.0f, 1.0f, 1.0f}, - {w - 0.5f, h - 0.5f, 0.0f, 1.0f, 1.0f, 0.0f}, - {0 - 0.5f, h - 0.5f, 0.0f, 1.0f, 0.0f, 0.0f}}; // x, y, z, rhw, u, v + checkForOutOfDateSwapChain(); + } + + return true; +} - mDisplay->startScene(); - device->DrawPrimitiveUP(D3DPT_TRIANGLEFAN, 2, quad, 6 * sizeof(float)); +bool Surface::postSubBuffer(EGLint x, EGLint y, EGLint width, EGLint height) +{ + if (x < 0 || y < 0 || width < 0 || height < 0) + { + return error(EGL_BAD_PARAMETER, false); + } - restoreState(device); + if (!mPostSubBufferSupported) + { + // Spec is not clear about how this should be handled. + return true; + } + if (mSwapChain) + { mDisplay->endScene(); - HRESULT result = mSwapChain->Present(NULL, NULL, NULL, NULL, 0); + RECT rect = + { + x, mHeight - y - height, + x + width, mHeight - y + }; + + if (rect.right > mWidth) + { + rect.right = mWidth; + } + + if (rect.bottom > mHeight) + { + rect.bottom = mHeight; + } + + if (rect.left == rect.right || rect.top == rect.bottom) + { + return true; + } + + HRESULT result = mSwapChain->Present(&rect, &rect, NULL, NULL, 0); if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY || result == D3DERR_DRIVERINTERNALERROR) { return error(EGL_BAD_ALLOC, false); } - if (result == D3DERR_DEVICELOST) + if (result == D3DERR_DEVICELOST || result == D3DERR_DEVICEHUNG || result == D3DERR_DEVICEREMOVED) { return error(EGL_CONTEXT_LOST, false); } @@ -458,16 +560,19 @@ EGLint Surface::getHeight() const return mHeight; } -IDirect3DSurface9 *Surface::getRenderTarget() +EGLint Surface::isPostSubBufferSupported() const { - IDirect3DSurface9 *textureSurface = NULL; + return mPostSubBufferSupported; +} - if (mFlipTexture) +IDirect3DSurface9 *Surface::getRenderTarget() +{ + if (mRenderTarget) { - mFlipTexture->GetSurfaceLevel(0, &textureSurface); + mRenderTarget->AddRef(); } - return textureSurface; + return mRenderTarget; } IDirect3DSurface9 *Surface::getDepthStencil() @@ -480,6 +585,16 @@ IDirect3DSurface9 *Surface::getDepthStencil() return mDepthStencil; } +IDirect3DTexture9 *Surface::getOffscreenTexture() +{ + if (mOffscreenTexture) + { + mOffscreenTexture->AddRef(); + } + + return mOffscreenTexture; +} + void Surface::setSwapInterval(EGLint interval) { if (mSwapInterval == interval) @@ -494,4 +609,29 @@ void Surface::setSwapInterval(EGLint interval) mPresentInterval = convertInterval(mSwapInterval); mPresentIntervalDirty = true; } + +EGLenum Surface::getTextureFormat() const +{ + return mTextureFormat; +} + +EGLenum Surface::getTextureTarget() const +{ + return mTextureTarget; +} + +void Surface::setBoundTexture(gl::Texture2D *texture) +{ + mTexture = texture; +} + +gl::Texture2D *Surface::getBoundTexture() const +{ + return mTexture; +} + +D3DFORMAT Surface::getFormat() const +{ + return mConfig->mRenderTargetFormat; +} } |