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 @@ ...@@ -255,6 +255,8 @@
'libGLESv2/renderer/Renderer.cpp', 'libGLESv2/renderer/Renderer.cpp',
'libGLESv2/renderer/Renderer.h', 'libGLESv2/renderer/Renderer.h',
'libGLESv2/renderer/ShaderCache.h', 'libGLESv2/renderer/ShaderCache.h',
'libGLESv2/renderer/SwapChain.cpp',
'libGLESv2/renderer/SwapChain.h',
'libGLESv2/ResourceManager.cpp', 'libGLESv2/ResourceManager.cpp',
'libGLESv2/ResourceManager.h', 'libGLESv2/ResourceManager.h',
'libGLESv2/Shader.cpp', '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 // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
// //
...@@ -14,6 +14,7 @@ ...@@ -14,6 +14,7 @@
#include "common/debug.h" #include "common/debug.h"
#include "libGLESv2/Texture.h" #include "libGLESv2/Texture.h"
#include "libGLESv2/renderer/SwapChain.h"
#include "libEGL/main.h" #include "libEGL/main.h"
#include "libEGL/Display.h" #include "libEGL/Display.h"
...@@ -23,32 +24,10 @@ ...@@ -23,32 +24,10 @@
namespace egl 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) Surface::Surface(Display *display, const Config *config, HWND window, EGLint postSubBufferSupported)
: mDisplay(display), mConfig(config), mWindow(window), mPostSubBufferSupported(postSubBufferSupported) : mDisplay(display), mConfig(config), mWindow(window), mPostSubBufferSupported(postSubBufferSupported)
{ {
mSwapChain = NULL; mSwapChain = NULL;
mBackBuffer = NULL;
mDepthStencil = NULL;
mRenderTarget = NULL;
mOffscreenTexture = NULL;
mShareHandle = NULL; mShareHandle = NULL;
mTexture = NULL; mTexture = NULL;
mTextureFormat = EGL_NO_TEXTURE; mTextureFormat = EGL_NO_TEXTURE;
...@@ -58,6 +37,8 @@ Surface::Surface(Display *display, const Config *config, HWND window, EGLint pos ...@@ -58,6 +37,8 @@ Surface::Surface(Display *display, const Config *config, HWND window, EGLint pos
mRenderBuffer = EGL_BACK_BUFFER; mRenderBuffer = EGL_BACK_BUFFER;
mSwapBehavior = EGL_BUFFER_PRESERVED; mSwapBehavior = EGL_BUFFER_PRESERVED;
mSwapInterval = -1; mSwapInterval = -1;
mWidth = -1;
mHeight = -1;
setSwapInterval(1); setSwapInterval(1);
subclassWindow(); subclassWindow();
...@@ -67,10 +48,6 @@ Surface::Surface(Display *display, const Config *config, HANDLE shareHandle, EGL ...@@ -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) : mDisplay(display), mWindow(NULL), mConfig(config), mShareHandle(shareHandle), mWidth(width), mHeight(height), mPostSubBufferSupported(EGL_FALSE)
{ {
mSwapChain = NULL; mSwapChain = NULL;
mBackBuffer = NULL;
mDepthStencil = NULL;
mRenderTarget = NULL;
mOffscreenTexture = NULL;
mWindowSubclassed = false; mWindowSubclassed = false;
mTexture = NULL; mTexture = NULL;
mTextureFormat = textureFormat; mTextureFormat = textureFormat;
...@@ -91,8 +68,6 @@ Surface::~Surface() ...@@ -91,8 +68,6 @@ Surface::~Surface()
bool Surface::initialize() bool Surface::initialize()
{ {
ASSERT(!mSwapChain && !mOffscreenTexture && !mDepthStencil);
if (!resetSwapChain()) if (!resetSwapChain())
return false; return false;
...@@ -119,248 +94,81 @@ bool Surface::initialize() ...@@ -119,248 +94,81 @@ bool Surface::initialize()
void Surface::release() void Surface::release()
{ {
if (mSwapChain) glDestroySwapChain(mSwapChain);
{
mSwapChain->Release();
mSwapChain = NULL; 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;
}
if (mTexture) if (mTexture)
{ {
mTexture->releaseTexImage(); mTexture->releaseTexImage();
mTexture = NULL; mTexture = NULL;
} }
mShareHandle = NULL;
} }
bool Surface::resetSwapChain() bool Surface::resetSwapChain()
{ {
if (!mWindow) ASSERT(!mSwapChain);
{
return resetSwapChain(mWidth, mHeight);
}
int width;
int height;
if (mWindow)
{
RECT windowRect; RECT windowRect;
if (!GetClientRect(getWindowHandle(), &windowRect)) if (!GetClientRect(getWindowHandle(), &windowRect))
{ {
ASSERT(false); ASSERT(false);
ERR("Could not retrieve the window dimensions"); ERR("Could not retrieve the window dimensions");
return false; return error(EGL_BAD_SURFACE, 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();
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 && renderer->getShareHandleSupport())
{
pShareHandle = &mShareHandle;
} }
result = device->CreateTexture(backbufferWidth, backbufferHeight, 1, D3DUSAGE_RENDERTARGET, width = windowRect.right - windowRect.left;
ConvertRenderbufferFormat(mConfig->mRenderTargetFormat), D3DPOOL_DEFAULT, &mOffscreenTexture, pShareHandle); height = windowRect.bottom - windowRect.top;
if (FAILED(result))
{
ERR("Could not create offscreen texture: %08lX", result);
release();
if(isDeviceLostError(result))
{
mDisplay->notifyDeviceLost();
return false;
} }
else else
{ {
return error(EGL_BAD_ALLOC, false); // non-window surface - size is determined at creation
width = mWidth;
height = mHeight;
} }
}
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)) mSwapChain = glCreateSwapChain(mDisplay->getRenderer(), mWindow, mShareHandle,
{ mConfig->mRenderTargetFormat, mConfig->mDepthStencilFormat);
rect.right = backbufferWidth; if (!mSwapChain)
}
if (rect.bottom > static_cast<LONG>(backbufferHeight))
{
rect.bottom = backbufferHeight;
}
renderer->endScene();
result = device->StretchRect(oldRenderTarget, &rect, mRenderTarget, &rect, D3DTEXF_NONE);
ASSERT(SUCCEEDED(result));
oldRenderTarget->Release();
}
if (mWindow)
{
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); return error(EGL_BAD_ALLOC, false);
} }
}
result = mSwapChain->GetBackBuffer(0, D3DBACKBUFFER_TYPE_MONO, &mBackBuffer); if (!resetSwapChain(width, height))
ASSERT(SUCCEEDED(result)); {
glDestroySwapChain(mSwapChain);
mSwapChain = NULL;
} }
if (mConfig->mDepthStencilFormat != D3DFMT_UNKNOWN) return true;
{ }
result = device->CreateDepthStencilSurface(backbufferWidth, backbufferHeight,
ConvertRenderbufferFormat(mConfig->mDepthStencilFormat), D3DMULTISAMPLE_NONE,
0, FALSE, &mDepthStencil, NULL);
if (FAILED(result)) bool Surface::resetSwapChain(int backbufferWidth, int backbufferHeight)
{ {
ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY || result == D3DERR_INVALIDCALL); ASSERT(backbufferWidth >= 0 && backbufferHeight >= 0);
ASSERT(mSwapChain);
ERR("Could not create depthstencil surface for new swap chain: 0x%08X", result); EGLint status = mSwapChain->reset(backbufferWidth, backbufferHeight, mSwapInterval);
release();
if(isDeviceLostError(result)) if (status == EGL_CONTEXT_LOST)
{ {
mDisplay->notifyDeviceLost(); mDisplay->notifyDeviceLost();
return false; return false;
} }
else else if (status != EGL_SUCCESS)
{ {
return error(EGL_BAD_ALLOC, false); return error(status, false);
}
}
} }
mWidth = backbufferWidth; mWidth = backbufferWidth;
mHeight = backbufferHeight; mHeight = backbufferHeight;
mSwapIntervalDirty = false;
mPresentIntervalDirty = false;
return true; return true;
} }
...@@ -386,87 +194,18 @@ bool Surface::swapRect(EGLint x, EGLint y, EGLint width, EGLint height) ...@@ -386,87 +194,18 @@ bool Surface::swapRect(EGLint x, EGLint y, EGLint width, EGLint height)
return true; return true;
} }
renderer::Renderer *renderer = mDisplay->getRenderer(); EGLint status = mSwapChain->swapRect(x, y, width, height);
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();
}
if (isDeviceLostError(result)) if (status == EGL_CONTEXT_LOST)
{ {
mDisplay->notifyDeviceLost(); mDisplay->notifyDeviceLost();
return false; return false;
} }
else if (status != EGL_SUCCESS)
if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY || result == D3DERR_DRIVERINTERNALERROR)
{ {
return error(EGL_BAD_ALLOC, false); return error(status, false);
} }
ASSERT(SUCCEEDED(result));
checkForOutOfDateSwapChain(); checkForOutOfDateSwapChain();
return true; return true;
...@@ -562,7 +301,7 @@ bool Surface::checkForOutOfDateSwapChain() ...@@ -562,7 +301,7 @@ bool Surface::checkForOutOfDateSwapChain()
int clientHeight = client.bottom - client.top; int clientHeight = client.bottom - client.top;
bool sizeDirty = clientWidth != getWidth() || clientHeight != getHeight(); bool sizeDirty = clientWidth != getWidth() || clientHeight != getHeight();
if (sizeDirty || mPresentIntervalDirty) if (sizeDirty || mSwapIntervalDirty)
{ {
resetSwapChain(clientWidth, clientHeight); resetSwapChain(clientWidth, clientHeight);
if (static_cast<egl::Surface*>(getCurrentDrawSurface()) == this) if (static_cast<egl::Surface*>(getCurrentDrawSurface()) == this)
...@@ -575,21 +314,6 @@ bool Surface::checkForOutOfDateSwapChain() ...@@ -575,21 +314,6 @@ bool Surface::checkForOutOfDateSwapChain()
return false; 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() bool Surface::swap()
{ {
return swapRect(0, 0, mWidth, mHeight); return swapRect(0, 0, mWidth, mHeight);
...@@ -621,38 +345,9 @@ EGLint Surface::isPostSubBufferSupported() const ...@@ -621,38 +345,9 @@ EGLint Surface::isPostSubBufferSupported() const
return mPostSubBufferSupported; return mPostSubBufferSupported;
} }
// Increments refcount on surface. renderer::SwapChain *Surface::getSwapChain() const
// caller must Release() the returned surface
IDirect3DSurface9 *Surface::getRenderTarget()
{ {
if (mRenderTarget) return mSwapChain;
{
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;
} }
void Surface::setSwapInterval(EGLint interval) void Surface::setSwapInterval(EGLint interval)
...@@ -666,8 +361,7 @@ void Surface::setSwapInterval(EGLint interval) ...@@ -666,8 +361,7 @@ void Surface::setSwapInterval(EGLint interval)
mSwapInterval = std::max(mSwapInterval, mDisplay->getMinSwapInterval()); mSwapInterval = std::max(mSwapInterval, mDisplay->getMinSwapInterval());
mSwapInterval = std::min(mSwapInterval, mDisplay->getMaxSwapInterval()); mSwapInterval = std::min(mSwapInterval, mDisplay->getMaxSwapInterval());
mPresentInterval = convertInterval(mSwapInterval); mSwapIntervalDirty = true;
mPresentIntervalDirty = true;
} }
EGLenum Surface::getTextureFormat() const 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 // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
// //
...@@ -8,12 +8,11 @@ ...@@ -8,12 +8,11 @@
// such as the client area of a window, including any back buffers. // 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. // Implements EGLSurface and related functionality. [EGL 1.4] section 2.2 page 3.
#ifndef INCLUDE_SURFACE_H_ #ifndef LIBEGL_SURFACE_H_
#define INCLUDE_SURFACE_H_ #define LIBEGL_SURFACE_H_
#define EGLAPI #define EGLAPI
#include <EGL/egl.h> #include <EGL/egl.h>
#include <d3d9.h>
#include "common/angleutils.h" #include "common/angleutils.h"
...@@ -21,6 +20,10 @@ namespace gl ...@@ -21,6 +20,10 @@ namespace gl
{ {
class Texture2D; class Texture2D;
} }
namespace renderer
{
class SwapChain;
}
namespace egl namespace egl
{ {
...@@ -48,11 +51,7 @@ class Surface ...@@ -48,11 +51,7 @@ class Surface
virtual EGLint isPostSubBufferSupported() const; virtual EGLint isPostSubBufferSupported() const;
virtual IDirect3DSurface9 *getRenderTarget(); virtual renderer::SwapChain *getSwapChain() const;
virtual IDirect3DSurface9 *getDepthStencil();
virtual IDirect3DTexture9 *getOffscreenTexture();
HANDLE getShareHandle() { return mShareHandle; }
void setSwapInterval(EGLint interval); void setSwapInterval(EGLint interval);
bool checkForOutOfDateSwapChain(); // Returns true if swapchain changed due to resize or interval update bool checkForOutOfDateSwapChain(); // Returns true if swapchain changed due to resize or interval update
...@@ -68,19 +67,14 @@ private: ...@@ -68,19 +67,14 @@ private:
DISALLOW_COPY_AND_ASSIGN(Surface); DISALLOW_COPY_AND_ASSIGN(Surface);
Display *const mDisplay; Display *const mDisplay;
IDirect3DSwapChain9 *mSwapChain;
IDirect3DSurface9 *mBackBuffer;
IDirect3DSurface9 *mDepthStencil;
IDirect3DSurface9* mRenderTarget;
IDirect3DTexture9* mOffscreenTexture;
HANDLE mShareHandle; HANDLE mShareHandle;
renderer::SwapChain *mSwapChain;
void subclassWindow(); void subclassWindow();
void unsubclassWindow(); void unsubclassWindow();
bool resetSwapChain(int backbufferWidth, int backbufferHeight); bool resetSwapChain(int backbufferWidth, int backbufferHeight);
bool swapRect(EGLint x, EGLint y, EGLint width, EGLint height); 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. const HWND mWindow; // Window that the surface is created for.
bool mWindowSubclassed; // Indicates whether we successfully subclassed mWindow for WM_RESIZE hooking bool mWindowSubclassed; // Indicates whether we successfully subclassed mWindow for WM_RESIZE hooking
...@@ -103,10 +97,9 @@ private: ...@@ -103,10 +97,9 @@ private:
EGLint mSwapInterval; EGLint mSwapInterval;
EGLint mPostSubBufferSupported; EGLint mPostSubBufferSupported;
DWORD mPresentInterval; bool mSwapIntervalDirty;
bool mPresentIntervalDirty;
gl::Texture2D *mTexture; gl::Texture2D *mTexture;
}; };
} }
#endif // INCLUDE_SURFACE_H_ #endif // LIBEGL_SURFACE_H_
...@@ -504,7 +504,10 @@ EGLBoolean __stdcall eglQuerySurfacePointerANGLE(EGLDisplay dpy, EGLSurface surf ...@@ -504,7 +504,10 @@ EGLBoolean __stdcall eglQuerySurfacePointerANGLE(EGLDisplay dpy, EGLSurface surf
switch (attribute) switch (attribute)
{ {
case EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE: case EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE:
*value = (void*) eglSurface->getShareHandle(); {
renderer::SwapChain *swapchain = eglSurface->getSwapChain();
*value = (void*) (swapchain ? swapchain->getShareHandle() : NULL);
}
break; break;
default: default:
return error(EGL_BAD_ATTRIBUTE, EGL_FALSE); return error(EGL_BAD_ATTRIBUTE, EGL_FALSE);
......
...@@ -317,8 +317,10 @@ void Context::makeCurrent(egl::Display *display, egl::Surface *surface) ...@@ -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 // Wrap the existing Direct3D 9 resources into GL objects and assign them to the '0' names
IDirect3DSurface9 *defaultRenderTarget = surface->getRenderTarget(); // D3D9_REPLACE
IDirect3DSurface9 *depthStencil = surface->getDepthStencil(); renderer::SwapChain *swapchain = surface->getSwapChain();
IDirect3DSurface9 *defaultRenderTarget = swapchain->getRenderTarget();
IDirect3DSurface9 *depthStencil = swapchain->getDepthStencil();
Colorbuffer *colorbufferZero = new Colorbuffer(defaultRenderTarget); Colorbuffer *colorbufferZero = new Colorbuffer(defaultRenderTarget);
DepthStencilbuffer *depthStencilbufferZero = new DepthStencilbuffer(depthStencil); DepthStencilbuffer *depthStencilbufferZero = new DepthStencilbuffer(depthStencil);
...@@ -4429,4 +4431,16 @@ void glDestroyRenderer(renderer::Renderer *renderer) ...@@ -4429,4 +4431,16 @@ void glDestroyRenderer(renderer::Renderer *renderer)
delete 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 @@ ...@@ -30,6 +30,7 @@
#include "libGLESv2/ResourceManager.h" #include "libGLESv2/ResourceManager.h"
#include "libGLESv2/HandleAllocator.h" #include "libGLESv2/HandleAllocator.h"
#include "libGLESv2/renderer/Renderer.h" #include "libGLESv2/renderer/Renderer.h"
#include "libGLESv2/renderer/SwapChain.h"
namespace egl namespace egl
{ {
...@@ -670,6 +671,9 @@ void glMakeCurrent(gl::Context *context, egl::Display *display, egl::Surface *su ...@@ -670,6 +671,9 @@ void glMakeCurrent(gl::Context *context, egl::Display *display, egl::Surface *su
gl::Context *glGetCurrentContext(); gl::Context *glGetCurrentContext();
renderer::Renderer *glCreateRenderer(egl::Display *display, HMODULE hModule, HDC hDc); renderer::Renderer *glCreateRenderer(egl::Display *display, HMODULE hModule, HDC hDc);
void glDestroyRenderer(renderer::Renderer *renderer); 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); __eglMustCastToProperFunctionPointerType __stdcall glGetProcAddress(const char *procname);
bool __stdcall glBindTexImage(egl::Surface *surface); bool __stdcall glBindTexImage(egl::Surface *surface);
......
...@@ -1840,7 +1840,8 @@ void Texture2D::bindTexImage(egl::Surface *surface) ...@@ -1840,7 +1840,8 @@ void Texture2D::bindTexImage(egl::Surface *surface)
mImageArray[0].redefine(internalformat, surface->getWidth(), surface->getHeight(), true); mImageArray[0].redefine(internalformat, surface->getWidth(), surface->getHeight(), true);
delete mTexStorage; delete mTexStorage;
mTexStorage = new TextureStorage2D(surface->getOffscreenTexture()); renderer::SwapChain *swapchain = surface->getSwapChain(); // D3D9_REPLACE
mTexStorage = new TextureStorage2D(swapchain->getOffscreenTexture());
mDirtyImages = true; mDirtyImages = true;
mSurface = surface; mSurface = surface;
......
...@@ -182,3 +182,5 @@ EXPORTS ...@@ -182,3 +182,5 @@ EXPORTS
glBindTexImage @158 NONAME glBindTexImage @158 NONAME
glCreateRenderer @177 NONAME glCreateRenderer @177 NONAME
glDestroyRenderer @178 NONAME glDestroyRenderer @178 NONAME
glCreateSwapChain @179 NONAME
glDestroySwapChain @180 NONAME
...@@ -246,6 +246,7 @@ copy "$(OutDir)libGLESv2.lib" "$(ProjectDir)..\..\lib\$(Configuration)\" ...@@ -246,6 +246,7 @@ copy "$(OutDir)libGLESv2.lib" "$(ProjectDir)..\..\lib\$(Configuration)\"
<ClCompile Include="..\common\RefCountObject.cpp" /> <ClCompile Include="..\common\RefCountObject.cpp" />
<ClCompile Include="Renderbuffer.cpp" /> <ClCompile Include="Renderbuffer.cpp" />
<ClCompile Include="renderer\Renderer.cpp" /> <ClCompile Include="renderer\Renderer.cpp" />
<ClCompile Include="renderer\SwapChain.cpp" />
<ClCompile Include="ResourceManager.cpp" /> <ClCompile Include="ResourceManager.cpp" />
<ClCompile Include="Shader.cpp" /> <ClCompile Include="Shader.cpp" />
<ClCompile Include="Texture.cpp" /> <ClCompile Include="Texture.cpp" />
...@@ -276,6 +277,7 @@ copy "$(OutDir)libGLESv2.lib" "$(ProjectDir)..\..\lib\$(Configuration)\" ...@@ -276,6 +277,7 @@ copy "$(OutDir)libGLESv2.lib" "$(ProjectDir)..\..\lib\$(Configuration)\"
<ClInclude Include="Renderbuffer.h" /> <ClInclude Include="Renderbuffer.h" />
<ClInclude Include="renderer\Renderer.h" /> <ClInclude Include="renderer\Renderer.h" />
<ClInclude Include="renderer\ShaderCache.h" /> <ClInclude Include="renderer\ShaderCache.h" />
<ClInclude Include="renderer\SwapChain.h" />
<ClInclude Include="resource.h" /> <ClInclude Include="resource.h" />
<ClInclude Include="ResourceManager.h" /> <ClInclude Include="ResourceManager.h" />
<ClInclude Include="Shader.h" /> <ClInclude Include="Shader.h" />
......
...@@ -9,6 +9,9 @@ ...@@ -9,6 +9,9 @@
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier> <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions> <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
</Filter> </Filter>
<Filter Include="Renderer">
<UniqueIdentifier>{93a76964-77a3-4b20-a6f5-e14e762d4e14}</UniqueIdentifier>
</Filter>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClCompile Include="Blit.cpp"> <ClCompile Include="Blit.cpp">
...@@ -81,7 +84,10 @@ ...@@ -81,7 +84,10 @@
<Filter>Source Files</Filter> <Filter>Source Files</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="renderer\Renderer.cpp"> <ClCompile Include="renderer\Renderer.cpp">
<Filter>Source Files</Filter> <Filter>Renderer</Filter>
</ClCompile>
<ClCompile Include="renderer\SwapChain.cpp">
<Filter>Renderer</Filter>
</ClCompile> </ClCompile>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
...@@ -166,11 +172,17 @@ ...@@ -166,11 +172,17 @@
<ClInclude Include="VertexDataManager.h"> <ClInclude Include="VertexDataManager.h">
<Filter>Header Files</Filter> <Filter>Header Files</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="renderer\Renderer.h"> <ClInclude Include="EnumTypes.h">
<Filter>Header Files</Filter> <Filter>Header Files</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="renderer\ShaderCache.h"> <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> </ClInclude>
</ItemGroup> </ItemGroup>
<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