Add renderer::SwapChain class and move functionality from egl::Surface

Trac #21810 Signed-off-by: Nicolas Capens git-svn-id: https://angleproject.googlecode.com/svn/branches/dx11proto@1351 736b8ea6-26fd-11df-bfd4-992fa37f6226
parent 3281f97d
......@@ -255,6 +255,8 @@
'libGLESv2/renderer/Renderer.cpp',
'libGLESv2/renderer/Renderer.h',
'libGLESv2/renderer/ShaderCache.h',
'libGLESv2/renderer/SwapChain.cpp',
'libGLESv2/renderer/SwapChain.h',
'libGLESv2/ResourceManager.cpp',
'libGLESv2/ResourceManager.h',
'libGLESv2/Shader.cpp',
......
//
// 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,7 @@
#include "common/debug.h"
#include "libGLESv2/Texture.h"
#include "libGLESv2/renderer/SwapChain.h"
#include "libEGL/main.h"
#include "libEGL/Display.h"
......@@ -23,32 +24,10 @@
namespace egl
{
// D3D9_REMOVE - Temporary duplication of this conversion function until remainder of d3d types are stripped
D3DFORMAT ConvertRenderbufferFormat(GLenum format)
{
switch (format)
{
case GL_NONE: return D3DFMT_NULL;
case GL_RGBA4:
case GL_RGB5_A1:
case GL_RGBA8_OES: return D3DFMT_A8R8G8B8;
case GL_RGB565: return D3DFMT_R5G6B5;
case GL_RGB8_OES: return D3DFMT_X8R8G8B8;
case GL_DEPTH_COMPONENT16:
case GL_STENCIL_INDEX8:
case GL_DEPTH24_STENCIL8_OES: return D3DFMT_D24S8;
default: UNREACHABLE(); return D3DFMT_A8R8G8B8;
}
}
Surface::Surface(Display *display, const Config *config, HWND window, EGLint postSubBufferSupported)
: mDisplay(display), mConfig(config), mWindow(window), mPostSubBufferSupported(postSubBufferSupported)
{
mSwapChain = NULL;
mBackBuffer = NULL;
mDepthStencil = NULL;
mRenderTarget = NULL;
mOffscreenTexture = NULL;
mShareHandle = NULL;
mTexture = NULL;
mTextureFormat = EGL_NO_TEXTURE;
......@@ -58,6 +37,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();
......@@ -67,10 +48,6 @@ Surface::Surface(Display *display, const Config *config, HANDLE shareHandle, EGL
: mDisplay(display), mWindow(NULL), mConfig(config), mShareHandle(shareHandle), mWidth(width), mHeight(height), mPostSubBufferSupported(EGL_FALSE)
{
mSwapChain = NULL;
mBackBuffer = NULL;
mDepthStencil = NULL;
mRenderTarget = NULL;
mOffscreenTexture = NULL;
mWindowSubclassed = false;
mTexture = NULL;
mTextureFormat = textureFormat;
......@@ -91,8 +68,6 @@ Surface::~Surface()
bool Surface::initialize()
{
ASSERT(!mSwapChain && !mOffscreenTexture && !mDepthStencil);
if (!resetSwapChain())
return false;
......@@ -119,248 +94,81 @@ 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;
}
glDestroySwapChain(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);
ERR("Could not retrieve the window dimensions");
return false;
}
return resetSwapChain(windowRect.right - windowRect.left, windowRect.bottom - windowRect.top);
}
// D3D9_REPLACE
bool Surface::resetSwapChain(int backbufferWidth, int backbufferHeight)
{
renderer::Renderer *renderer = mDisplay->getRenderer();
IDirect3DDevice9 *device = renderer->getDevice();
if (device == NULL)
{
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();
ASSERT(!mSwapChain);
HRESULT result;
int width;
int height;
// 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)
if (mWindow)
{
mSwapChain->Release();
mSwapChain = NULL;
}
RECT windowRect;
if (!GetClientRect(getWindowHandle(), &windowRect))
{
ASSERT(false);
if (mBackBuffer)
{
mBackBuffer->Release();
mBackBuffer = NULL;
}
ERR("Could not retrieve the window dimensions");
return error(EGL_BAD_SURFACE, false);
}
if (mOffscreenTexture)
{
mOffscreenTexture->Release();
mOffscreenTexture = NULL;
width = windowRect.right - windowRect.left;
height = windowRect.bottom - windowRect.top;
}
if (mDepthStencil)
else
{
mDepthStencil->Release();
mDepthStencil = NULL;
// non-window surface - size is determined at creation
width = mWidth;
height = mHeight;
}
mShareHandle = NULL;
HANDLE *pShareHandle = NULL;
if (!mWindow && renderer->getShareHandleSupport())
mSwapChain = glCreateSwapChain(mDisplay->getRenderer(), mWindow, mShareHandle,
mConfig->mRenderTargetFormat, mConfig->mDepthStencilFormat);
if (!mSwapChain)
{
pShareHandle = &mShareHandle;
return error(EGL_BAD_ALLOC, false);
}
result = device->CreateTexture(backbufferWidth, backbufferHeight, 1, D3DUSAGE_RENDERTARGET,
ConvertRenderbufferFormat(mConfig->mRenderTargetFormat), D3DPOOL_DEFAULT, &mOffscreenTexture, pShareHandle);
if (FAILED(result))
if (!resetSwapChain(width, height))
{
ERR("Could not create offscreen texture: %08lX", result);
release();
if(isDeviceLostError(result))
{
mDisplay->notifyDeviceLost();
return false;
}
else
{
return error(EGL_BAD_ALLOC, false);
}
glDestroySwapChain(mSwapChain);
mSwapChain = NULL;
}
IDirect3DSurface9 *oldRenderTarget = mRenderTarget;
result = mOffscreenTexture->GetSurfaceLevel(0, &mRenderTarget);
ASSERT(SUCCEEDED(result));
if (oldRenderTarget)
{
RECT rect =
{
0, 0,
mWidth, mHeight
};
if (rect.right > static_cast<LONG>(backbufferWidth))
{
rect.right = backbufferWidth;
}
if (rect.bottom > static_cast<LONG>(backbufferHeight))
{
rect.bottom = backbufferHeight;
}
renderer->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 = ConvertRenderbufferFormat(mConfig->mDepthStencilFormat);
presentParameters.BackBufferCount = 1;
presentParameters.BackBufferFormat = ConvertRenderbufferFormat(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 = renderer->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));
mDisplay->notifyDeviceLost();
return false;
}
if (mConfig->mDepthStencilFormat != D3DFMT_UNKNOWN)
else if (status != EGL_SUCCESS)
{
result = device->CreateDepthStencilSurface(backbufferWidth, backbufferHeight,
ConvertRenderbufferFormat(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;
}
......@@ -386,87 +194,18 @@ bool Surface::swapRect(EGLint x, EGLint y, EGLint width, EGLint height)
return true;
}
renderer::Renderer *renderer = mDisplay->getRenderer();
IDirect3DDevice9 *device = renderer->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
renderer->startScene();
device->DrawPrimitiveUP(D3DPT_TRIANGLEFAN, 2, quad, 6 * sizeof(float));
renderer->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();
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;
......@@ -562,7 +301,7 @@ bool Surface::checkForOutOfDateSwapChain()
int clientHeight = client.bottom - client.top;
bool sizeDirty = clientWidth != getWidth() || clientHeight != getHeight();
if (sizeDirty || mPresentIntervalDirty)
if (sizeDirty || mSwapIntervalDirty)
{
resetSwapChain(clientWidth, clientHeight);
if (static_cast<egl::Surface*>(getCurrentDrawSurface()) == this)
......@@ -575,21 +314,6 @@ bool Surface::checkForOutOfDateSwapChain()
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;
}
bool Surface::swap()
{
return swapRect(0, 0, mWidth, mHeight);
......@@ -621,38 +345,9 @@ EGLint Surface::isPostSubBufferSupported() const
return mPostSubBufferSupported;
}
// Increments refcount on surface.
// caller must Release() the returned surface
IDirect3DSurface9 *Surface::getRenderTarget()
renderer::SwapChain *Surface::getSwapChain() const
{
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()
{
if (mOffscreenTexture)
{
mOffscreenTexture->AddRef();
}
return mOffscreenTexture;
return mSwapChain;
}
void Surface::setSwapInterval(EGLint interval)
......@@ -666,8 +361,7 @@ void Surface::setSwapInterval(EGLint interval)
mSwapInterval = std::max(mSwapInterval, mDisplay->getMinSwapInterval());
mSwapInterval = std::min(mSwapInterval, mDisplay->getMaxSwapInterval());
mPresentInterval = convertInterval(mSwapInterval);
mPresentIntervalDirty = true;
mSwapIntervalDirty = true;
}
EGLenum Surface::getTextureFormat() const
......
//
// 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.
//
......@@ -8,12 +8,11 @@
// such as the client area of a window, including any back buffers.
// Implements EGLSurface and related functionality. [EGL 1.4] section 2.2 page 3.
#ifndef INCLUDE_SURFACE_H_
#define INCLUDE_SURFACE_H_
#ifndef LIBEGL_SURFACE_H_
#define LIBEGL_SURFACE_H_
#define EGLAPI
#include <EGL/egl.h>
#include <d3d9.h>
#include "common/angleutils.h"
......@@ -21,6 +20,10 @@ namespace gl
{
class Texture2D;
}
namespace renderer
{
class SwapChain;
}
namespace egl
{
......@@ -48,11 +51,7 @@ class Surface
virtual EGLint isPostSubBufferSupported() const;
virtual IDirect3DSurface9 *getRenderTarget();
virtual IDirect3DSurface9 *getDepthStencil();
virtual IDirect3DTexture9 *getOffscreenTexture();
HANDLE getShareHandle() { return mShareHandle; }
virtual renderer::SwapChain *getSwapChain() const;
void setSwapInterval(EGLint interval);
bool checkForOutOfDateSwapChain(); // Returns true if swapchain changed due to resize or interval update
......@@ -68,19 +67,14 @@ private:
DISALLOW_COPY_AND_ASSIGN(Surface);
Display *const mDisplay;
IDirect3DSwapChain9 *mSwapChain;
IDirect3DSurface9 *mBackBuffer;
IDirect3DSurface9 *mDepthStencil;
IDirect3DSurface9* mRenderTarget;
IDirect3DTexture9* mOffscreenTexture;
HANDLE mShareHandle;
renderer::SwapChain *mSwapChain;
void subclassWindow();
void unsubclassWindow();
bool resetSwapChain(int backbufferWidth, int backbufferHeight);
bool swapRect(EGLint x, EGLint y, EGLint width, EGLint height);
static DWORD convertInterval(EGLint interval);
const HWND mWindow; // Window that the surface is created for.
bool mWindowSubclassed; // Indicates whether we successfully subclassed mWindow for WM_RESIZE hooking
......@@ -103,10 +97,9 @@ private:
EGLint mSwapInterval;
EGLint mPostSubBufferSupported;
DWORD mPresentInterval;
bool mPresentIntervalDirty;
bool mSwapIntervalDirty;
gl::Texture2D *mTexture;
};
}
#endif // INCLUDE_SURFACE_H_
#endif // LIBEGL_SURFACE_H_
......@@ -504,7 +504,10 @@ EGLBoolean __stdcall eglQuerySurfacePointerANGLE(EGLDisplay dpy, EGLSurface surf
switch (attribute)
{
case EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE:
*value = (void*) eglSurface->getShareHandle();
{
renderer::SwapChain *swapchain = eglSurface->getSwapChain();
*value = (void*) (swapchain ? swapchain->getShareHandle() : NULL);
}
break;
default:
return error(EGL_BAD_ATTRIBUTE, EGL_FALSE);
......
......@@ -317,8 +317,10 @@ void Context::makeCurrent(egl::Display *display, egl::Surface *surface)
}
// Wrap the existing Direct3D 9 resources into GL objects and assign them to the '0' names
IDirect3DSurface9 *defaultRenderTarget = surface->getRenderTarget();
IDirect3DSurface9 *depthStencil = surface->getDepthStencil();
// D3D9_REPLACE
renderer::SwapChain *swapchain = surface->getSwapChain();
IDirect3DSurface9 *defaultRenderTarget = swapchain->getRenderTarget();
IDirect3DSurface9 *depthStencil = swapchain->getDepthStencil();
Colorbuffer *colorbufferZero = new Colorbuffer(defaultRenderTarget);
DepthStencilbuffer *depthStencilbufferZero = new DepthStencilbuffer(depthStencil);
......@@ -4429,4 +4431,16 @@ void glDestroyRenderer(renderer::Renderer *renderer)
delete renderer;
}
renderer::SwapChain *glCreateSwapChain(renderer::Renderer *renderer, HWND window, HANDLE shareHandle,
GLenum backBufferFormat, GLenum depthBufferFormat)
{
return new renderer::SwapChain(renderer, window, shareHandle, backBufferFormat, depthBufferFormat);
}
void glDestroySwapChain(renderer::SwapChain *swapChain)
{
delete swapChain;
}
}
......@@ -30,6 +30,7 @@
#include "libGLESv2/ResourceManager.h"
#include "libGLESv2/HandleAllocator.h"
#include "libGLESv2/renderer/Renderer.h"
#include "libGLESv2/renderer/SwapChain.h"
namespace egl
{
......@@ -670,6 +671,9 @@ void glMakeCurrent(gl::Context *context, egl::Display *display, egl::Surface *su
gl::Context *glGetCurrentContext();
renderer::Renderer *glCreateRenderer(egl::Display *display, HMODULE hModule, HDC hDc);
void glDestroyRenderer(renderer::Renderer *renderer);
renderer::SwapChain *glCreateSwapChain(renderer::Renderer *renderer, HWND window, HANDLE shareHandle,
GLenum backBufferFormat, GLenum depthBufferFormat);
void glDestroySwapChain(renderer::SwapChain *swapChain);
__eglMustCastToProperFunctionPointerType __stdcall glGetProcAddress(const char *procname);
bool __stdcall glBindTexImage(egl::Surface *surface);
......
......@@ -1840,7 +1840,8 @@ void Texture2D::bindTexImage(egl::Surface *surface)
mImageArray[0].redefine(internalformat, surface->getWidth(), surface->getHeight(), true);
delete mTexStorage;
mTexStorage = new TextureStorage2D(surface->getOffscreenTexture());
renderer::SwapChain *swapchain = surface->getSwapChain(); // D3D9_REPLACE
mTexStorage = new TextureStorage2D(swapchain->getOffscreenTexture());
mDirtyImages = true;
mSurface = surface;
......
......@@ -182,3 +182,5 @@ EXPORTS
glBindTexImage @158 NONAME
glCreateRenderer @177 NONAME
glDestroyRenderer @178 NONAME
glCreateSwapChain @179 NONAME
glDestroySwapChain @180 NONAME
......@@ -246,6 +246,7 @@ copy "$(OutDir)libGLESv2.lib" "$(ProjectDir)..\..\lib\$(Configuration)\"
<ClCompile Include="..\common\RefCountObject.cpp" />
<ClCompile Include="Renderbuffer.cpp" />
<ClCompile Include="renderer\Renderer.cpp" />
<ClCompile Include="renderer\SwapChain.cpp" />
<ClCompile Include="ResourceManager.cpp" />
<ClCompile Include="Shader.cpp" />
<ClCompile Include="Texture.cpp" />
......@@ -276,6 +277,7 @@ copy "$(OutDir)libGLESv2.lib" "$(ProjectDir)..\..\lib\$(Configuration)\"
<ClInclude Include="Renderbuffer.h" />
<ClInclude Include="renderer\Renderer.h" />
<ClInclude Include="renderer\ShaderCache.h" />
<ClInclude Include="renderer\SwapChain.h" />
<ClInclude Include="resource.h" />
<ClInclude Include="ResourceManager.h" />
<ClInclude Include="Shader.h" />
......
......@@ -9,6 +9,9 @@
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
</Filter>
<Filter Include="Renderer">
<UniqueIdentifier>{93a76964-77a3-4b20-a6f5-e14e762d4e14}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="Blit.cpp">
......@@ -81,7 +84,10 @@
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="renderer\Renderer.cpp">
<Filter>Source Files</Filter>
<Filter>Renderer</Filter>
</ClCompile>
<ClCompile Include="renderer\SwapChain.cpp">
<Filter>Renderer</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
......@@ -166,11 +172,17 @@
<ClInclude Include="VertexDataManager.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="renderer\Renderer.h">
<ClInclude Include="EnumTypes.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="renderer\ShaderCache.h">
<Filter>Header Files</Filter>
<Filter>Renderer</Filter>
</ClInclude>
<ClInclude Include="renderer\Renderer.h">
<Filter>Renderer</Filter>
</ClInclude>
<ClInclude Include="renderer\SwapChain.h">
<Filter>Renderer</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
......
//
// Copyright (c) 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.
//
// SwapChain.cpp: Implements a back-end specific class that hides the details of the
// implementation-specific swapchain.
#include "libGLESv2/renderer/SwapChain.h"
#include "common/debug.h"
#include "libGLESv2/utilities.h"
#include "libGLESv2/renderer/Renderer.h"
#include "libGLESv2/Context.h"
namespace renderer
{
SwapChain::SwapChain(Renderer *renderer, HWND window, HANDLE shareHandle,
GLenum backBufferFormat, GLenum depthBufferFormat)
: mRenderer(renderer), mWindow(window), mShareHandle(shareHandle),
mBackBufferFormat(backBufferFormat), mDepthBufferFormat(depthBufferFormat)
{
mSwapChain = NULL;
mBackBuffer = NULL;
mDepthStencil = NULL;
mRenderTarget = NULL;
mOffscreenTexture = NULL;
mWidth = -1;
mHeight = -1;
}
SwapChain::~SwapChain()
{
release();
}
void SwapChain::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;
}
mShareHandle = NULL;
}
static DWORD 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;
}
// D3D9_REPLACE
EGLint SwapChain::reset(int backbufferWidth, int backbufferHeight, EGLint swapInterval)
{
IDirect3DDevice9 *device = mRenderer->getDevice();
if (device == NULL)
{
return EGL_BAD_ACCESS;
}
// 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;
// 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;
}
if (mBackBuffer)
{
mBackBuffer->Release();
mBackBuffer = NULL;
}
if (mOffscreenTexture)
{
mOffscreenTexture->Release();
mOffscreenTexture = NULL;
}
if (mDepthStencil)
{
mDepthStencil->Release();
mDepthStencil = NULL;
}
mShareHandle = NULL;
HANDLE *pShareHandle = NULL;
if (!mWindow && mRenderer->getShareHandleSupport())
{
pShareHandle = &mShareHandle;
}
result = device->CreateTexture(backbufferWidth, backbufferHeight, 1, D3DUSAGE_RENDERTARGET,
es2dx::ConvertRenderbufferFormat(mBackBufferFormat), D3DPOOL_DEFAULT,
&mOffscreenTexture, pShareHandle);
if (FAILED(result))
{
ERR("Could not create offscreen texture: %08lX", result);
release();
if(isDeviceLostError(result))
{
return EGL_CONTEXT_LOST;
}
else
{
return EGL_BAD_ALLOC;
}
}
IDirect3DSurface9 *oldRenderTarget = mRenderTarget;
result = mOffscreenTexture->GetSurfaceLevel(0, &mRenderTarget);
ASSERT(SUCCEEDED(result));
if (oldRenderTarget)
{
RECT rect =
{
0, 0,
mWidth, mHeight
};
if (rect.right > static_cast<LONG>(backbufferWidth))
{
rect.right = backbufferWidth;
}
if (rect.bottom > static_cast<LONG>(backbufferHeight))
{
rect.bottom = backbufferHeight;
}
mRenderer->endScene();
result = device->StretchRect(oldRenderTarget, &rect, mRenderTarget, &rect, D3DTEXF_NONE);
ASSERT(SUCCEEDED(result));
oldRenderTarget->Release();
}
if (mWindow)
{
D3DPRESENT_PARAMETERS presentParameters = {0};
presentParameters.AutoDepthStencilFormat = es2dx::ConvertRenderbufferFormat(mDepthBufferFormat);
presentParameters.BackBufferCount = 1;
presentParameters.BackBufferFormat = es2dx::ConvertRenderbufferFormat(mBackBufferFormat);
presentParameters.EnableAutoDepthStencil = FALSE;
presentParameters.Flags = 0;
presentParameters.hDeviceWindow = mWindow;
presentParameters.MultiSampleQuality = 0; // FIXME: Unimplemented
presentParameters.MultiSampleType = D3DMULTISAMPLE_NONE; // FIXME: Unimplemented
presentParameters.PresentationInterval = convertInterval(swapInterval);
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 = mRenderer->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))
{
return EGL_CONTEXT_LOST;
}
else
{
return EGL_BAD_ALLOC;
}
}
result = mSwapChain->GetBackBuffer(0, D3DBACKBUFFER_TYPE_MONO, &mBackBuffer);
ASSERT(SUCCEEDED(result));
}
if (mDepthBufferFormat != D3DFMT_UNKNOWN)
{
result = device->CreateDepthStencilSurface(backbufferWidth, backbufferHeight,
es2dx::ConvertRenderbufferFormat(mDepthBufferFormat),
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))
{
return EGL_CONTEXT_LOST;
}
else
{
return EGL_BAD_ALLOC;
}
}
}
mWidth = backbufferWidth;
mHeight = backbufferHeight;
return EGL_SUCCESS;
}
// parameters should be validated/clamped by caller
EGLint SwapChain::swapRect(EGLint x, EGLint y, EGLint width, EGLint height)
{
if (!mSwapChain)
{
return EGL_SUCCESS;
}
IDirect3DDevice9 *device = mRenderer->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
mRenderer->startScene();
device->DrawPrimitiveUP(D3DPT_TRIANGLEFAN, 2, quad, 6 * sizeof(float));
mRenderer->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();
}
if (isDeviceLostError(result))
{
return EGL_CONTEXT_LOST;
}
if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY || result == D3DERR_DRIVERINTERNALERROR)
{
return EGL_BAD_ALLOC;
}
ASSERT(SUCCEEDED(result));
return EGL_SUCCESS;
}
// Increments refcount on surface.
// caller must Release() the returned surface
IDirect3DSurface9 *SwapChain::getRenderTarget()
{
if (mRenderTarget)
{
mRenderTarget->AddRef();
}
return mRenderTarget;
}
// Increments refcount on surface.
// caller must Release() the returned surface
IDirect3DSurface9 *SwapChain::getDepthStencil()
{
if (mDepthStencil)
{
mDepthStencil->AddRef();
}
return mDepthStencil;
}
// Increments refcount on texture.
// caller must Release() the returned texture
IDirect3DTexture9 *SwapChain::getOffscreenTexture()
{
if (mOffscreenTexture)
{
mOffscreenTexture->AddRef();
}
return mOffscreenTexture;
}
}
//
// Copyright (c) 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.
//
// SwapChain.h: Defines a back-end specific class that hides the details of the
// implementation-specific swapchain.
#ifndef LIBGLESV2_RENDERER_SWAPCHAIN_H_
#define LIBGLESV2_RENDERER_SWAPCHAIN_H_
#define GL_APICALL
#include <GLES2/gl2.h>
#include <GLES2/gl2ext.h>
#define EGLAPI
#include <EGL/egl.h>
#include "common/angleutils.h"
#include <d3d9.h> // D3D9_REPLACE
namespace renderer
{
class Renderer;
class SwapChain
{
public:
SwapChain(Renderer *renderer, HWND window, HANDLE shareHandle,
GLenum backBufferFormat, GLenum depthBufferFormat);
virtual ~SwapChain();
virtual EGLint reset(EGLint backbufferWidth, EGLint backbufferHeight, EGLint swapInterval);
virtual EGLint swapRect(EGLint x, EGLint y, EGLint width, EGLint height);
virtual IDirect3DSurface9 *getRenderTarget();
virtual IDirect3DSurface9 *getDepthStencil();
virtual IDirect3DTexture9 *getOffscreenTexture();
HANDLE getShareHandle() { return mShareHandle; }
private:
DISALLOW_COPY_AND_ASSIGN(SwapChain);
void release();
Renderer *mRenderer;
EGLint mHeight;
EGLint mWidth;
const HWND mWindow; // Window that the surface is created for.
const GLenum mBackBufferFormat;
const GLenum mDepthBufferFormat;
IDirect3DSwapChain9 *mSwapChain;
IDirect3DSurface9 *mBackBuffer;
IDirect3DSurface9 *mDepthStencil;
IDirect3DSurface9* mRenderTarget;
IDirect3DTexture9* mOffscreenTexture;
HANDLE mShareHandle;
};
}
#endif // LIBGLESV2_RENDERER_SWAPCHAIN_H_
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment