Commit fb0580a6 by Jamie Madill

MANGLE egl::Surface.

This class has its fingers in a lot of other classes. In particular, we will likely need to revisit the context lost handling methods when we implement the robustness extensions on top of desktop GL. For now, we can leave them tied pretty tightly to the D3D implementation. BUG=angle:795 Change-Id: I9b3ac90dfd393f52c5b49bc2bd6b97fb5536ed91 Reviewed-on: https://chromium-review.googlesource.com/228916Tested-by: 's avatarJamie Madill <jmadill@chromium.org> Reviewed-by: 's avatarGeoff Lang <geofflang@chromium.org>
parent 533f0a1d
...@@ -19,10 +19,11 @@ ...@@ -19,10 +19,11 @@
#include "common/debug.h" #include "common/debug.h"
#include "common/mathutil.h" #include "common/mathutil.h"
#include "libANGLE/Context.h" #include "libANGLE/Context.h"
#include "libANGLE/renderer/SwapChain.h"
#include "libANGLE/Surface.h" #include "libANGLE/Surface.h"
#include "libANGLE/renderer/Renderer.h"
//TODO(jmadill): remove these
#include "libANGLE/renderer/SwapChain.h"
#include "libANGLE/renderer/d3d/SurfaceD3D.h"
#include <EGL/eglext.h> #include <EGL/eglext.h>
...@@ -372,7 +373,11 @@ Error Display::createWindowSurface(EGLNativeWindowType window, EGLConfig config, ...@@ -372,7 +373,11 @@ Error Display::createWindowSurface(EGLNativeWindowType window, EGLConfig config,
} }
} }
Surface *surface = new Surface(this, configuration, window, fixedSize, width, height, postSubBufferSupported); //TODO(jmadill): MANGLE refactor
rx::SurfaceD3D *surfaceD3D = rx::SurfaceD3D::createFromWindow(this, configuration, window, fixedSize,
width, height, postSubBufferSupported);
Surface *surface = new Surface(surfaceD3D);
Error error = surface->initialize(); Error error = surface->initialize();
if (error.isError()) if (error.isError())
{ {
...@@ -386,7 +391,8 @@ Error Display::createWindowSurface(EGLNativeWindowType window, EGLConfig config, ...@@ -386,7 +391,8 @@ Error Display::createWindowSurface(EGLNativeWindowType window, EGLConfig config,
return Error(EGL_SUCCESS); return Error(EGL_SUCCESS);
} }
Error Display::createOffscreenSurface(EGLConfig config, EGLClientBuffer shareHandle, const EGLint *attribList, EGLSurface *outSurface) Error Display::createOffscreenSurface(EGLConfig config, EGLClientBuffer shareHandle,
const EGLint *attribList, EGLSurface *outSurface)
{ {
EGLint width = 0, height = 0; EGLint width = 0, height = 0;
EGLenum textureFormat = EGL_NO_TEXTURE; EGLenum textureFormat = EGL_NO_TEXTURE;
...@@ -489,7 +495,11 @@ Error Display::createOffscreenSurface(EGLConfig config, EGLClientBuffer shareHan ...@@ -489,7 +495,11 @@ Error Display::createOffscreenSurface(EGLConfig config, EGLClientBuffer shareHan
} }
} }
Surface *surface = new Surface(this, configuration, shareHandle, width, height, textureFormat, textureTarget); //TODO(jmadill): MANGLE refactor
rx::SurfaceD3D *surfaceD3D = rx::SurfaceD3D::createOffscreen(this, configuration, shareHandle,
width, height, textureFormat, textureTarget);
Surface *surface = new Surface(surfaceD3D);
Error error = surface->initialize(); Error error = surface->initialize();
if (error.isError()) if (error.isError())
{ {
...@@ -546,9 +556,16 @@ Error Display::restoreLostDevice() ...@@ -546,9 +556,16 @@ Error Display::restoreLostDevice()
} }
// Release surface resources to make the Reset() succeed // Release surface resources to make the Reset() succeed
for (SurfaceSet::iterator surface = mSurfaceSet.begin(); surface != mSurfaceSet.end(); surface++) for (const auto &surface : mSurfaceSet)
{ {
(*surface)->release(); //TODO(jmadill): MANGLE refactor
rx::SurfaceD3D *surfaceD3D = rx::SurfaceD3D::makeSurfaceD3D(surface);
if (surface->getBoundTexture())
{
surface->releaseTexImage(EGL_BACK_BUFFER);
}
surfaceD3D->releaseSwapChain();
} }
if (!mRenderer->resetDevice()) if (!mRenderer->resetDevice())
...@@ -557,9 +574,12 @@ Error Display::restoreLostDevice() ...@@ -557,9 +574,12 @@ Error Display::restoreLostDevice()
} }
// Restore any surfaces that may have been lost // Restore any surfaces that may have been lost
for (SurfaceSet::iterator surface = mSurfaceSet.begin(); surface != mSurfaceSet.end(); surface++) for (const auto &surface : mSurfaceSet)
{ {
Error error = (*surface)->resetSwapChain(); //TODO(jmadill): MANGLE refactor
rx::SurfaceD3D *surfaceD3D = rx::SurfaceD3D::makeSurfaceD3D(surface);
Error error = surfaceD3D->resetSwapChain();
if (error.isError()) if (error.isError())
{ {
return error; return error;
...@@ -592,9 +612,11 @@ void Display::notifyDeviceLost() ...@@ -592,9 +612,11 @@ void Display::notifyDeviceLost()
void Display::recreateSwapChains() void Display::recreateSwapChains()
{ {
for (SurfaceSet::iterator surface = mSurfaceSet.begin(); surface != mSurfaceSet.end(); surface++) for (const auto &surface : mSurfaceSet)
{ {
(*surface)->getSwapChain()->recreate(); //TODO(jmadill): MANGLE refactor
rx::SurfaceD3D *surfaceD3D = rx::SurfaceD3D::makeSurfaceD3D(surface);
surfaceD3D->getSwapChain()->recreate();
} }
} }
......
...@@ -10,422 +10,83 @@ ...@@ -10,422 +10,83 @@
#include "libANGLE/Surface.h" #include "libANGLE/Surface.h"
#include "common/debug.h" #include "libANGLE/Config.h"
#include "libANGLE/Display.h"
#include "libANGLE/Texture.h" #include "libANGLE/Texture.h"
#include "libANGLE/renderer/SwapChain.h" #include "libANGLE/renderer/SurfaceImpl.h"
#include <algorithm>
#include <tchar.h>
#include <EGL/eglext.h>
//TODO(jmadill): phase this out
#include "libANGLE/renderer/d3d/RendererD3D.h"
namespace egl namespace egl
{ {
Surface::Surface(Display *display, const Config *config, EGLNativeWindowType window, EGLint fixedSize, EGLint width, EGLint height, EGLint postSubBufferSupported) Surface::Surface(rx::SurfaceImpl *impl)
: mDisplay(display), mConfig(config), mNativeWindow(window), mPostSubBufferSupported(postSubBufferSupported) : mImplementation(impl),
// FIXME: Determine actual pixel aspect ratio
mPixelAspectRatio(static_cast<EGLint>(1.0 * EGL_DISPLAY_SCALING)),
mRenderBuffer(EGL_BACK_BUFFER),
mSwapBehavior(EGL_BUFFER_PRESERVED),
mTexture(NULL)
{ {
//TODO(jmadill): MANGLE refactor. (note, can't call makeRendererD3D because of dll export issues)
mRenderer = static_cast<rx::RendererD3D*>(mDisplay->getRenderer());
mSwapChain = 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;
mSwapBehavior = EGL_BUFFER_PRESERVED;
mSwapInterval = -1;
mWidth = width;
mHeight = height;
setSwapInterval(1);
mFixedSize = fixedSize;
subclassWindow();
}
Surface::Surface(Display *display, const Config *config, EGLClientBuffer shareHandle, EGLint width, EGLint height, EGLenum textureFormat, EGLenum textureType)
: mDisplay(display), mNativeWindow(NULL), mConfig(config), mShareHandle(shareHandle), mWidth(width), mHeight(height), mPostSubBufferSupported(EGL_FALSE)
{
//TODO(jmadill): MANGLE refactor. (note, can't call makeRendererD3D because of dll export issues)
mRenderer = static_cast<rx::RendererD3D*>(mDisplay->getRenderer());
mSwapChain = 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); setSwapInterval(1);
// This constructor is for offscreen surfaces, which are always fixed-size.
mFixedSize = EGL_TRUE;
} }
Surface::~Surface() Surface::~Surface()
{ {
unsubclassWindow(); if (mTexture)
release();
}
Error Surface::initialize()
{
if (mNativeWindow.getNativeWindow())
{ {
if (!mNativeWindow.initialize()) if (mImplementation)
{ {
return Error(EGL_BAD_SURFACE); mImplementation->releaseTexImage(mTexture->id());
} }
}
Error error = resetSwapChain();
if (error.isError())
{
return error;
}
return Error(EGL_SUCCESS);
}
void Surface::release()
{
delete mSwapChain;
mSwapChain = NULL;
if (mTexture)
{
mTexture->releaseTexImage(); mTexture->releaseTexImage();
mTexture = NULL; mTexture = NULL;
} }
}
Error Surface::resetSwapChain()
{
ASSERT(!mSwapChain);
int width;
int height;
if (!mFixedSize)
{
RECT windowRect;
if (!mNativeWindow.getClientRect(&windowRect))
{
ASSERT(false);
return Error(EGL_BAD_SURFACE, "Could not retrieve the window dimensions");
}
width = windowRect.right - windowRect.left;
height = windowRect.bottom - windowRect.top;
}
else
{
// non-window surface - size is determined at creation
width = mWidth;
height = mHeight;
}
mSwapChain = mRenderer->createSwapChain(mNativeWindow, static_cast<HANDLE>(mShareHandle),
mConfig->mRenderTargetFormat,
mConfig->mDepthStencilFormat);
if (!mSwapChain)
{
return Error(EGL_BAD_ALLOC);
}
Error error = resetSwapChain(width, height);
if (error.isError())
{
SafeDelete(mSwapChain);
return error;
}
return Error(EGL_SUCCESS);
}
Error Surface::resizeSwapChain(int backbufferWidth, int backbufferHeight)
{
ASSERT(backbufferWidth >= 0 && backbufferHeight >= 0);
ASSERT(mSwapChain);
EGLint status = mSwapChain->resize(std::max(1, backbufferWidth), std::max(1, backbufferHeight));
if (status == EGL_CONTEXT_LOST)
{
mDisplay->notifyDeviceLost();
return Error(status);
}
else if (status != EGL_SUCCESS)
{
return Error(status);
}
mWidth = backbufferWidth;
mHeight = backbufferHeight;
return Error(EGL_SUCCESS);
}
Error Surface::resetSwapChain(int backbufferWidth, int backbufferHeight)
{
ASSERT(backbufferWidth >= 0 && backbufferHeight >= 0);
ASSERT(mSwapChain);
EGLint status = mSwapChain->reset(std::max(1, backbufferWidth), std::max(1, backbufferHeight), mSwapInterval);
if (status == EGL_CONTEXT_LOST)
{
//TODO(jmadill): MANGLE refactor
rx::RendererD3D *rendererD3D = static_cast<rx::RendererD3D*>(mRenderer);
rendererD3D->notifyDeviceLost();
return Error(status);
}
else if (status != EGL_SUCCESS)
{
return Error(status);
}
mWidth = backbufferWidth;
mHeight = backbufferHeight;
mSwapIntervalDirty = false;
return Error(EGL_SUCCESS); SafeDelete(mImplementation);
} }
Error Surface::swapRect(EGLint x, EGLint y, EGLint width, EGLint height) Error Surface::initialize()
{
if (!mSwapChain)
{
return Error(EGL_SUCCESS);
}
if (x + width > mWidth)
{
width = mWidth - x;
}
if (y + height > mHeight)
{
height = mHeight - y;
}
if (width == 0 || height == 0)
{
return Error(EGL_SUCCESS);
}
EGLint status = mSwapChain->swapRect(x, y, width, height);
if (status == EGL_CONTEXT_LOST)
{
//TODO(jmadill): MANGLE refactor
rx::RendererD3D *rendererD3D = static_cast<rx::RendererD3D*>(mRenderer);
rendererD3D->notifyDeviceLost();
return Error(status);
}
else if (status != EGL_SUCCESS)
{
return Error(status);
}
checkForOutOfDateSwapChain();
return Error(EGL_SUCCESS);
}
EGLNativeWindowType Surface::getWindowHandle()
{
return mNativeWindow.getNativeWindow();
}
#if !defined(ANGLE_ENABLE_WINDOWS_STORE)
#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)
{
Surface* surf = reinterpret_cast<Surface*>(GetProp(hwnd, kSurfaceProperty));
if(surf)
{
surf->checkForOutOfDateSwapChain();
}
}
WNDPROC prevWndFunc = reinterpret_cast<WNDPROC >(GetProp(hwnd, kParentWndProc));
return CallWindowProc(prevWndFunc, hwnd, message, wparam, lparam);
}
#endif
void Surface::subclassWindow()
{ {
#if !defined(ANGLE_ENABLE_WINDOWS_STORE) return mImplementation->initialize();
HWND window = mNativeWindow.getNativeWindow();
if (!window)
{
return;
}
DWORD processId;
DWORD threadId = GetWindowThreadProcessId(window, &processId);
if (processId != GetCurrentProcessId() || threadId != GetCurrentThreadId())
{
return;
}
SetLastError(0);
LONG_PTR oldWndProc = SetWindowLongPtr(window, GWLP_WNDPROC, reinterpret_cast<LONG_PTR>(SurfaceWindowProc));
if(oldWndProc == 0 && GetLastError() != ERROR_SUCCESS)
{
mWindowSubclassed = false;
return;
}
SetProp(window, kSurfaceProperty, reinterpret_cast<HANDLE>(this));
SetProp(window, kParentWndProc, reinterpret_cast<HANDLE>(oldWndProc));
mWindowSubclassed = true;
#endif
} }
void Surface::unsubclassWindow() EGLNativeWindowType Surface::getWindowHandle() const
{ {
if(!mWindowSubclassed) return mImplementation->getWindowHandle();
{
return;
}
#if !defined(ANGLE_ENABLE_WINDOWS_STORE)
HWND window = mNativeWindow.getNativeWindow();
if (!window)
{
return;
}
// un-subclass
LONG_PTR parentWndFunc = reinterpret_cast<LONG_PTR>(GetProp(window, 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_PTR prevWndFunc = SetWindowLongPtr(window, GWLP_WNDPROC, parentWndFunc);
UNUSED_ASSERTION_VARIABLE(prevWndFunc);
ASSERT(prevWndFunc == reinterpret_cast<LONG_PTR>(SurfaceWindowProc));
}
RemoveProp(window, kSurfaceProperty);
RemoveProp(window, kParentWndProc);
#endif
mWindowSubclassed = false;
}
bool Surface::checkForOutOfDateSwapChain()
{
RECT client;
int clientWidth = getWidth();
int clientHeight = getHeight();
bool sizeDirty = false;
if (!mFixedSize && !mNativeWindow.isIconic())
{
// The window is automatically resized to 150x22 when it's minimized, but the swapchain shouldn't be resized
// because that's not a useful size to render to.
if (!mNativeWindow.getClientRect(&client))
{
ASSERT(false);
return false;
}
// Grow the buffer now, if the window has grown. We need to grow now to avoid losing information.
clientWidth = client.right - client.left;
clientHeight = client.bottom - client.top;
sizeDirty = clientWidth != getWidth() || clientHeight != getHeight();
}
bool wasDirty = (mSwapIntervalDirty || sizeDirty);
if (mSwapIntervalDirty)
{
resetSwapChain(clientWidth, clientHeight);
}
else if (sizeDirty)
{
resizeSwapChain(clientWidth, clientHeight);
}
return wasDirty;
} }
Error Surface::swap() Error Surface::swap()
{ {
return swapRect(0, 0, mWidth, mHeight); return mImplementation->swap();
} }
Error Surface::postSubBuffer(EGLint x, EGLint y, EGLint width, EGLint height) Error Surface::postSubBuffer(EGLint x, EGLint y, EGLint width, EGLint height)
{ {
if (!mPostSubBufferSupported) if (!isPostSubBufferSupported())
{ {
// Spec is not clear about how this should be handled. // Spec is not clear about how this should be handled.
return Error(EGL_SUCCESS); return Error(EGL_SUCCESS);
} }
return swapRect(x, y, width, height); return mImplementation->postSubBuffer(x, y, width, height);
} }
Error Surface::querySurfacePointerANGLE(EGLint attribute, void **value) Error Surface::querySurfacePointerANGLE(EGLint attribute, void **value)
{ {
// TODO(jmadill): MANGLE refactor return mImplementation->querySurfacePointerANGLE(attribute, value);
ASSERT(attribute == EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE);
*value = mSwapChain->getShareHandle();
return Error(EGL_SUCCESS);
} }
EGLint Surface::isPostSubBufferSupported() const EGLint Surface::isPostSubBufferSupported() const
{ {
return mPostSubBufferSupported; return mImplementation->isPostSubBufferSupported();
}
rx::SwapChain *Surface::getSwapChain() const
{
return mSwapChain;
} }
void Surface::setSwapInterval(EGLint interval) void Surface::setSwapInterval(EGLint interval)
{ {
if (mSwapInterval == interval) mImplementation->setSwapInterval(interval);
{
return;
}
mSwapInterval = interval;
mSwapInterval = std::max(mSwapInterval, mRenderer->getMinSwapInterval());
mSwapInterval = std::min(mSwapInterval, mRenderer->getMaxSwapInterval());
mSwapIntervalDirty = true;
} }
EGLint Surface::getConfigID() const EGLint Surface::getConfigID() const
{ {
return mConfig->mConfigID; return mImplementation->getConfig()->mConfigID;
}
EGLint Surface::getWidth() const
{
return mWidth;
}
EGLint Surface::getHeight() const
{
return mHeight;
} }
EGLint Surface::getPixelAspectRatio() const EGLint Surface::getPixelAspectRatio() const
...@@ -445,31 +106,51 @@ EGLenum Surface::getSwapBehavior() const ...@@ -445,31 +106,51 @@ EGLenum Surface::getSwapBehavior() const
EGLenum Surface::getTextureFormat() const EGLenum Surface::getTextureFormat() const
{ {
return mTextureFormat; return mImplementation->getTextureFormat();
} }
EGLenum Surface::getTextureTarget() const EGLenum Surface::getTextureTarget() const
{ {
return mTextureTarget; return mImplementation->getTextureTarget();
} }
void Surface::setBoundTexture(gl::Texture2D *texture) EGLint Surface::isFixedSize() const
{ {
mTexture = texture; return mImplementation->isFixedSize();
} }
gl::Texture2D *Surface::getBoundTexture() const EGLenum Surface::getFormat() const
{ {
return mTexture; return mImplementation->getFormat();
} }
EGLint Surface::isFixedSize() const EGLint Surface::getWidth() const
{ {
return mFixedSize; return mImplementation->getWidth();
} }
EGLenum Surface::getFormat() const EGLint Surface::getHeight() const
{
return mImplementation->getHeight();
}
Error Surface::bindTexImage(gl::Texture2D *texture, EGLint buffer)
{
ASSERT(!mTexture);
texture->bindTexImage(this);
mTexture = texture;
return mImplementation->bindTexImage(buffer);
}
Error Surface::releaseTexImage(EGLint buffer)
{ {
return mConfig->mRenderTargetFormat; ASSERT(mTexture);
gl::Texture2D *boundTexture = mTexture;
mTexture = NULL;
boundTexture->releaseTexImage();
return mImplementation->releaseTexImage(buffer);
} }
} }
...@@ -11,23 +11,19 @@ ...@@ -11,23 +11,19 @@
#ifndef LIBANGLE_SURFACE_H_ #ifndef LIBANGLE_SURFACE_H_
#define LIBANGLE_SURFACE_H_ #define LIBANGLE_SURFACE_H_
#include "common/angleutils.h"
#include "libANGLE/Error.h" #include "libANGLE/Error.h"
// TODO: don't expose this to egl::Surface
#include "libANGLE/renderer/d3d/d3d11/NativeWindow.h"
#include <EGL/egl.h> #include <EGL/egl.h>
#include "common/angleutils.h"
namespace gl namespace gl
{ {
class Texture2D; class Texture2D;
} }
namespace rx namespace rx
{ {
class SwapChain; class SurfaceImpl;
class RendererD3D; //TODO(jmadill): remove this
} }
namespace egl namespace egl
...@@ -35,85 +31,55 @@ namespace egl ...@@ -35,85 +31,55 @@ namespace egl
class Display; class Display;
class Config; class Config;
class Surface class Surface final
{ {
public: public:
Surface(Display *display, const egl::Config *config, EGLNativeWindowType window, EGLint fixedSize, EGLint width, EGLint height, EGLint postSubBufferSupported); Surface(rx::SurfaceImpl *impl);
Surface(Display *display, const egl::Config *config, EGLClientBuffer shareHandle, EGLint width, EGLint height, EGLenum textureFormat, EGLenum textureTarget); ~Surface();
virtual ~Surface(); rx::SurfaceImpl *getImplementation() const { return mImplementation; }
Error initialize(); Error initialize();
void release();
Error resetSwapChain();
EGLNativeWindowType getWindowHandle();
Error swap(); Error swap();
Error postSubBuffer(EGLint x, EGLint y, EGLint width, EGLint height); Error postSubBuffer(EGLint x, EGLint y, EGLint width, EGLint height);
Error querySurfacePointerANGLE(EGLint attribute, void **value); Error querySurfacePointerANGLE(EGLint attribute, void **value);
Error bindTexImage(gl::Texture2D *texture, EGLint buffer);
Error releaseTexImage(EGLint buffer);
virtual EGLint isPostSubBufferSupported() const; EGLNativeWindowType getWindowHandle() const;
virtual rx::SwapChain *getSwapChain() const; EGLint isPostSubBufferSupported() const;
void setSwapInterval(EGLint interval); void setSwapInterval(EGLint interval);
bool checkForOutOfDateSwapChain(); // Returns true if swapchain changed due to resize or interval update
virtual EGLint getConfigID() const; EGLint getConfigID() const;
virtual EGLint getWidth() const;
virtual EGLint getHeight() const; // width and height can change with client window resizing
virtual EGLint getPixelAspectRatio() const; EGLint getWidth() const;
virtual EGLenum getRenderBuffer() const; EGLint getHeight() const;
virtual EGLenum getSwapBehavior() const; EGLint getPixelAspectRatio() const;
virtual EGLenum getTextureFormat() const; EGLenum getRenderBuffer() const;
virtual EGLenum getTextureTarget() const; EGLenum getSwapBehavior() const;
virtual EGLenum getFormat() const; EGLenum getTextureFormat() const;
EGLenum getTextureTarget() const;
EGLenum getFormat() const;
virtual void setBoundTexture(gl::Texture2D *texture); gl::Texture2D *getBoundTexture() const { return mTexture; }
virtual gl::Texture2D *getBoundTexture() const;
EGLint isFixedSize() const; EGLint isFixedSize() const;
private: private:
DISALLOW_COPY_AND_ASSIGN(Surface); DISALLOW_COPY_AND_ASSIGN(Surface);
Display *const mDisplay; rx::SurfaceImpl *mImplementation;
rx::RendererD3D *mRenderer;
EGLClientBuffer mShareHandle;
rx::SwapChain *mSwapChain;
void subclassWindow();
void unsubclassWindow();
Error resizeSwapChain(int backbufferWidth, int backbufferHeight);
Error resetSwapChain(int backbufferWidth, int backbufferHeight);
Error swapRect(EGLint x, EGLint y, EGLint width, EGLint height);
rx::NativeWindow mNativeWindow; // Handler for the Window that the surface is created for.
bool mWindowSubclassed; // Indicates whether we successfully subclassed mWindow for WM_RESIZE hooking
const egl::Config *mConfig; // EGL config surface was created with
EGLint mHeight; // Height of surface
EGLint mWidth; // Width of surface
// EGLint horizontalResolution; // Horizontal dot pitch
// EGLint verticalResolution; // Vertical dot pitch
// EGLBoolean largestPBuffer; // If true, create largest pbuffer possible
// EGLBoolean mipmapTexture; // True if texture has mipmaps
// EGLint mipmapLevel; // Mipmap level to render to
// EGLenum multisampleResolve; // Multisample resolve behavior
EGLint mPixelAspectRatio; // Display aspect ratio EGLint mPixelAspectRatio; // Display aspect ratio
EGLenum mRenderBuffer; // Render buffer EGLenum mRenderBuffer; // Render buffer
EGLenum mSwapBehavior; // Buffer swap behavior EGLenum mSwapBehavior; // Buffer swap behavior
EGLenum mTextureFormat; // Format of texture: RGB, RGBA, or no texture
EGLenum mTextureTarget; // Type of texture: 2D or no texture
// EGLenum vgAlphaFormat; // Alpha format for OpenVG
// EGLenum vgColorSpace; // Color space for OpenVG
EGLint mSwapInterval;
EGLint mPostSubBufferSupported;
EGLint mFixedSize;
bool mSwapIntervalDirty;
gl::Texture2D *mTexture; gl::Texture2D *mTexture;
}; };
} }
#endif // LIBANGLE_SURFACE_H_ #endif // LIBANGLE_SURFACE_H_
...@@ -181,7 +181,7 @@ Texture2D::~Texture2D() ...@@ -181,7 +181,7 @@ Texture2D::~Texture2D()
{ {
if (mSurface) if (mSurface)
{ {
mSurface->setBoundTexture(NULL); mSurface->releaseTexImage(EGL_BACK_BUFFER);
mSurface = NULL; mSurface = NULL;
} }
} }
...@@ -228,20 +228,15 @@ Error Texture2D::setImage(GLint level, GLsizei width, GLsizei height, GLenum int ...@@ -228,20 +228,15 @@ Error Texture2D::setImage(GLint level, GLsizei width, GLsizei height, GLenum int
void Texture2D::bindTexImage(egl::Surface *surface) void Texture2D::bindTexImage(egl::Surface *surface)
{ {
releaseTexImage(); releaseTexImage();
mTexture->bindTexImage(surface); mTexture->bindTexImage(surface);
mSurface = surface; mSurface = surface;
mSurface->setBoundTexture(this);
} }
void Texture2D::releaseTexImage() void Texture2D::releaseTexImage()
{ {
if (mSurface) if (mSurface)
{ {
mSurface->setBoundTexture(NULL);
mSurface = NULL; mSurface = NULL;
mTexture->releaseTexImage(); mTexture->releaseTexImage();
} }
} }
......
//
// Copyright (c) 2002-2014 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.
//
// SurfaceImpl.cpp: Implementation of Surface stub method class
#include "libANGLE/renderer/SurfaceImpl.h"
#include "libANGLE/Config.h"
namespace rx
{
SurfaceImpl::SurfaceImpl(egl::Display *display, const egl::Config *config, EGLint width, EGLint height,
EGLint fixedSize, EGLint postSubBufferSupported, EGLenum textureFormat,
EGLenum textureType, EGLClientBuffer shareHandle)
: mDisplay(display),
mConfig(config),
mWidth(width),
mHeight(height),
mFixedSize(fixedSize),
mSwapInterval(-1),
mPostSubBufferSupported(postSubBufferSupported),
mTextureFormat(textureFormat),
mTextureTarget(textureType),
mShareHandle(shareHandle)
{
}
SurfaceImpl::~SurfaceImpl()
{
}
EGLenum SurfaceImpl::getFormat() const
{
return mConfig->mRenderTargetFormat;
}
}
//
// Copyright (c) 2014 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.
//
// SurfaceImpl.h: Implementation methods of egl::Surface
#ifndef LIBANGLE_RENDERER_SURFACEIMPL_H_
#define LIBANGLE_RENDERER_SURFACEIMPL_H_
#include "common/angleutils.h"
#include "libANGLE/Error.h"
namespace egl
{
class Display;
class Config;
}
namespace gl
{
class Texture2D;
}
namespace rx
{
class SurfaceImpl
{
public:
SurfaceImpl(egl::Display *display, const egl::Config *config, EGLint width, EGLint height,
EGLint fixedSize, EGLint postSubBufferSupported, EGLenum textureFormat,
EGLenum textureType, EGLClientBuffer shareHandle);
virtual ~SurfaceImpl();
virtual egl::Error initialize() = 0;
virtual egl::Error swap() = 0;
virtual egl::Error postSubBuffer(EGLint x, EGLint y, EGLint width, EGLint height) = 0;
virtual egl::Error querySurfacePointerANGLE(EGLint attribute, void **value) = 0;
virtual egl::Error bindTexImage(EGLint buffer) = 0;
virtual egl::Error releaseTexImage(EGLint buffer) = 0;
virtual void setSwapInterval(EGLint interval) = 0;
// width and height can change with client window resizing
EGLint getWidth() const { return mWidth; }
EGLint getHeight() const { return mHeight; }
//TODO(jmadill): Possibly should be redesigned
virtual EGLNativeWindowType getWindowHandle() const = 0;
const egl::Config *getConfig() const { return mConfig; }
EGLint isFixedSize() const { return mFixedSize; }
EGLenum getFormat() const;
EGLint isPostSubBufferSupported() const { return mPostSubBufferSupported; }
EGLenum getTextureFormat() const { return mTextureFormat; }
EGLenum getTextureTarget() const { return mTextureTarget; }
protected:
// Useful for mocking
SurfaceImpl()
: mDisplay(nullptr),
mConfig(nullptr),
mWidth(0),
mHeight(0),
mFixedSize(0),
mPostSubBufferSupported(0),
mTextureFormat(EGL_NONE),
mTextureTarget(EGL_NONE),
mShareHandle(static_cast<EGLClientBuffer>(0))
{}
egl::Display *const mDisplay;
const egl::Config *mConfig; // EGL config surface was created with
EGLint mWidth;
EGLint mHeight;
EGLint mFixedSize;
EGLint mSwapInterval;
EGLint mPostSubBufferSupported;
// EGLint horizontalResolution; // Horizontal dot pitch
// EGLint verticalResolution; // Vertical dot pitch
// EGLBoolean largestPBuffer; // If true, create largest pbuffer possible
// EGLBoolean mipmapTexture; // True if texture has mipmaps
// EGLint mipmapLevel; // Mipmap level to render to
// EGLenum multisampleResolve; // Multisample resolve behavior
EGLenum mTextureFormat; // Format of texture: RGB, RGBA, or no texture
EGLenum mTextureTarget; // Type of texture: 2D or no texture
// EGLenum vgAlphaFormat; // Alpha format for OpenVG
// EGLenum vgColorSpace; // Color space for OpenVG
EGLClientBuffer mShareHandle;
private:
DISALLOW_COPY_AND_ASSIGN(SurfaceImpl);
};
}
#endif // LIBANGLE_RENDERER_SURFACEIMPL_H_
//
// Copyright (c) 2014 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.
//
// SurfaceD3D.cpp: D3D implementation of an EGL surface
#include "libANGLE/renderer/d3d/SurfaceD3D.h"
#include "libANGLE/Display.h"
#include "libANGLE/Surface.h"
#include "libANGLE/renderer/SwapChain.h"
#include "libANGLE/renderer/d3d/RendererD3D.h"
#include <tchar.h>
#include <EGL/eglext.h>
#include <algorithm>
namespace rx
{
//static
SurfaceD3D *SurfaceD3D::makeSurfaceD3D(SurfaceImpl *impl)
{
ASSERT(HAS_DYNAMIC_TYPE(SurfaceD3D*, impl));
return static_cast<SurfaceD3D*>(impl);
}
//static
SurfaceD3D *SurfaceD3D::makeSurfaceD3D(egl::Surface *surface)
{
return makeSurfaceD3D(surface->getImplementation());
}
SurfaceD3D *SurfaceD3D::createOffscreen(egl::Display *display, const egl::Config *config, EGLClientBuffer shareHandle,
EGLint width, EGLint height, EGLenum textureFormat, EGLenum textureType)
{
return new SurfaceD3D(display, config, width, height, EGL_TRUE, EGL_FALSE,
textureFormat, textureType, shareHandle, NULL);
}
SurfaceD3D *SurfaceD3D::createFromWindow(egl::Display *display, const egl::Config *config, EGLNativeWindowType window,
EGLint fixedSize, EGLint width, EGLint height, EGLint postSubBufferSupported)
{
return new SurfaceD3D(display, config, width, height, fixedSize, postSubBufferSupported,
EGL_NO_TEXTURE, EGL_NO_TEXTURE, static_cast<EGLClientBuffer>(0), window);
}
SurfaceD3D::SurfaceD3D(egl::Display *display, const egl::Config *config, EGLint width, EGLint height,
EGLint fixedSize, EGLint postSubBufferSupported, EGLenum textureFormat,
EGLenum textureType, EGLClientBuffer shareHandle, EGLNativeWindowType window)
: SurfaceImpl(display, config, width, height, fixedSize, postSubBufferSupported, textureFormat, textureType, shareHandle),
mRenderer(static_cast<rx::RendererD3D*>(mDisplay->getRenderer())),
mSwapChain(NULL),
mWindowSubclassed(false),
mNativeWindow(window)
{
subclassWindow();
}
SurfaceD3D::~SurfaceD3D()
{
unsubclassWindow();
releaseSwapChain();
}
void SurfaceD3D::releaseSwapChain()
{
SafeDelete(mSwapChain);
}
egl::Error SurfaceD3D::initialize()
{
if (mNativeWindow.getNativeWindow())
{
if (!mNativeWindow.initialize())
{
return egl::Error(EGL_BAD_SURFACE);
}
}
egl::Error error = resetSwapChain();
if (error.isError())
{
return error;
}
return egl::Error(EGL_SUCCESS);
}
egl::Error SurfaceD3D::bindTexImage(EGLint)
{
return egl::Error(EGL_SUCCESS);
}
egl::Error SurfaceD3D::releaseTexImage(EGLint)
{
return egl::Error(EGL_SUCCESS);
}
egl::Error SurfaceD3D::resetSwapChain()
{
ASSERT(!mSwapChain);
int width;
int height;
if (!mFixedSize)
{
RECT windowRect;
if (!mNativeWindow.getClientRect(&windowRect))
{
ASSERT(false);
return egl::Error(EGL_BAD_SURFACE, "Could not retrieve the window dimensions");
}
width = windowRect.right - windowRect.left;
height = windowRect.bottom - windowRect.top;
}
else
{
// non-window surface - size is determined at creation
width = mWidth;
height = mHeight;
}
mSwapChain = mRenderer->createSwapChain(mNativeWindow, static_cast<HANDLE>(mShareHandle),
mConfig->mRenderTargetFormat,
mConfig->mDepthStencilFormat);
if (!mSwapChain)
{
return egl::Error(EGL_BAD_ALLOC);
}
egl::Error error = resetSwapChain(width, height);
if (error.isError())
{
SafeDelete(mSwapChain);
return error;
}
return egl::Error(EGL_SUCCESS);
}
egl::Error SurfaceD3D::resizeSwapChain(int backbufferWidth, int backbufferHeight)
{
ASSERT(backbufferWidth >= 0 && backbufferHeight >= 0);
ASSERT(mSwapChain);
EGLint status = mSwapChain->resize(std::max(1, backbufferWidth), std::max(1, backbufferHeight));
if (status == EGL_CONTEXT_LOST)
{
mDisplay->notifyDeviceLost();
return egl::Error(status);
}
else if (status != EGL_SUCCESS)
{
return egl::Error(status);
}
mWidth = backbufferWidth;
mHeight = backbufferHeight;
return egl::Error(EGL_SUCCESS);
}
egl::Error SurfaceD3D::resetSwapChain(int backbufferWidth, int backbufferHeight)
{
ASSERT(backbufferWidth >= 0 && backbufferHeight >= 0);
ASSERT(mSwapChain);
EGLint status = mSwapChain->reset(std::max(1, backbufferWidth), std::max(1, backbufferHeight), mSwapInterval);
if (status == EGL_CONTEXT_LOST)
{
mRenderer->notifyDeviceLost();
return egl::Error(status);
}
else if (status != EGL_SUCCESS)
{
return egl::Error(status);
}
mWidth = backbufferWidth;
mHeight = backbufferHeight;
mSwapIntervalDirty = false;
return egl::Error(EGL_SUCCESS);
}
egl::Error SurfaceD3D::swapRect(EGLint x, EGLint y, EGLint width, EGLint height)
{
if (!mSwapChain)
{
return egl::Error(EGL_SUCCESS);
}
if (x + width > mWidth)
{
width = mWidth - x;
}
if (y + height > mHeight)
{
height = mHeight - y;
}
if (width == 0 || height == 0)
{
return egl::Error(EGL_SUCCESS);
}
EGLint status = mSwapChain->swapRect(x, y, width, height);
if (status == EGL_CONTEXT_LOST)
{
mRenderer->notifyDeviceLost();
return egl::Error(status);
}
else if (status != EGL_SUCCESS)
{
return egl::Error(status);
}
checkForOutOfDateSwapChain();
return egl::Error(EGL_SUCCESS);
}
EGLNativeWindowType SurfaceD3D::getWindowHandle() const
{
return mNativeWindow.getNativeWindow();
}
#if !defined(ANGLE_ENABLE_WINDOWS_STORE)
#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)
{
SurfaceD3D* surf = reinterpret_cast<SurfaceD3D*>(GetProp(hwnd, kSurfaceProperty));
if(surf)
{
surf->checkForOutOfDateSwapChain();
}
}
WNDPROC prevWndFunc = reinterpret_cast<WNDPROC >(GetProp(hwnd, kParentWndProc));
return CallWindowProc(prevWndFunc, hwnd, message, wparam, lparam);
}
#endif
void SurfaceD3D::subclassWindow()
{
#if !defined(ANGLE_ENABLE_WINDOWS_STORE)
HWND window = mNativeWindow.getNativeWindow();
if (!window)
{
return;
}
DWORD processId;
DWORD threadId = GetWindowThreadProcessId(window, &processId);
if (processId != GetCurrentProcessId() || threadId != GetCurrentThreadId())
{
return;
}
SetLastError(0);
LONG_PTR oldWndProc = SetWindowLongPtr(window, GWLP_WNDPROC, reinterpret_cast<LONG_PTR>(SurfaceWindowProc));
if(oldWndProc == 0 && GetLastError() != ERROR_SUCCESS)
{
mWindowSubclassed = false;
return;
}
SetProp(window, kSurfaceProperty, reinterpret_cast<HANDLE>(this));
SetProp(window, kParentWndProc, reinterpret_cast<HANDLE>(oldWndProc));
mWindowSubclassed = true;
#endif
}
void SurfaceD3D::unsubclassWindow()
{
if (!mWindowSubclassed)
{
return;
}
#if !defined(ANGLE_ENABLE_WINDOWS_STORE)
HWND window = mNativeWindow.getNativeWindow();
if (!window)
{
return;
}
// un-subclass
LONG_PTR parentWndFunc = reinterpret_cast<LONG_PTR>(GetProp(window, 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_PTR prevWndFunc = SetWindowLongPtr(window, GWLP_WNDPROC, parentWndFunc);
UNUSED_ASSERTION_VARIABLE(prevWndFunc);
ASSERT(prevWndFunc == reinterpret_cast<LONG_PTR>(SurfaceWindowProc));
}
RemoveProp(window, kSurfaceProperty);
RemoveProp(window, kParentWndProc);
#endif
mWindowSubclassed = false;
}
bool SurfaceD3D::checkForOutOfDateSwapChain()
{
RECT client;
int clientWidth = getWidth();
int clientHeight = getHeight();
bool sizeDirty = false;
if (!mFixedSize && !mNativeWindow.isIconic())
{
// The window is automatically resized to 150x22 when it's minimized, but the swapchain shouldn't be resized
// because that's not a useful size to render to.
if (!mNativeWindow.getClientRect(&client))
{
ASSERT(false);
return false;
}
// Grow the buffer now, if the window has grown. We need to grow now to avoid losing information.
clientWidth = client.right - client.left;
clientHeight = client.bottom - client.top;
sizeDirty = clientWidth != getWidth() || clientHeight != getHeight();
}
bool wasDirty = (mSwapIntervalDirty || sizeDirty);
if (mSwapIntervalDirty)
{
resetSwapChain(clientWidth, clientHeight);
}
else if (sizeDirty)
{
resizeSwapChain(clientWidth, clientHeight);
}
return wasDirty;
}
egl::Error SurfaceD3D::swap()
{
return swapRect(0, 0, mWidth, mHeight);
}
egl::Error SurfaceD3D::postSubBuffer(EGLint x, EGLint y, EGLint width, EGLint height)
{
return swapRect(x, y, width, height);
}
rx::SwapChain *SurfaceD3D::getSwapChain() const
{
return mSwapChain;
}
void SurfaceD3D::setSwapInterval(EGLint interval)
{
if (mSwapInterval == interval)
{
return;
}
mSwapInterval = interval;
mSwapInterval = std::max(mSwapInterval, mRenderer->getMinSwapInterval());
mSwapInterval = std::min(mSwapInterval, mRenderer->getMaxSwapInterval());
mSwapIntervalDirty = true;
}
egl::Error SurfaceD3D::querySurfacePointerANGLE(EGLint attribute, void **value)
{
ASSERT(attribute == EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE);
*value = mSwapChain->getShareHandle();
return egl::Error(EGL_SUCCESS);
}
}
//
// Copyright (c) 2014 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.
//
// SurfaceD3D.h: D3D implementation of an EGL surface
#ifndef LIBANGLE_RENDERER_D3D_SURFACED3D_H_
#define LIBANGLE_RENDERER_D3D_SURFACED3D_H_
#include "libANGLE/renderer/SurfaceImpl.h"
#include "libANGLE/renderer/d3d/d3d11/NativeWindow.h"
namespace egl
{
class Surface;
}
namespace rx
{
class SwapChain;
class RendererD3D;
class SurfaceD3D : public SurfaceImpl
{
public:
static SurfaceD3D *createFromWindow(egl::Display *display, const egl::Config *config,
EGLNativeWindowType window, EGLint fixedSize,
EGLint width, EGLint height, EGLint postSubBufferSupported);
static SurfaceD3D *createOffscreen(egl::Display *display, const egl::Config *config,
EGLClientBuffer shareHandle, EGLint width, EGLint height,
EGLenum textureFormat, EGLenum textureTarget);
~SurfaceD3D() override;
void releaseSwapChain();
static SurfaceD3D *makeSurfaceD3D(SurfaceImpl *impl);
static SurfaceD3D *makeSurfaceD3D(egl::Surface *surface);
egl::Error initialize() override;
egl::Error swap() override;
egl::Error postSubBuffer(EGLint x, EGLint y, EGLint width, EGLint height) override;
egl::Error querySurfacePointerANGLE(EGLint attribute, void **value) override;
egl::Error bindTexImage(EGLint buffer) override;
egl::Error releaseTexImage(EGLint buffer) override;
void setSwapInterval(EGLint interval) override;
// D3D implementations (some virtual to hack across DLL boundaries)
virtual SwapChain *getSwapChain() const;
egl::Error resetSwapChain();
// Returns true if swapchain changed due to resize or interval update
bool checkForOutOfDateSwapChain();
EGLNativeWindowType getWindowHandle() const override;
private:
DISALLOW_COPY_AND_ASSIGN(SurfaceD3D);
SurfaceD3D(egl::Display *display, const egl::Config *config, EGLint width, EGLint height,
EGLint fixedSize, EGLint postSubBufferSupported, EGLenum textureFormat,
EGLenum textureType, EGLClientBuffer shareHandle, EGLNativeWindowType window);
egl::Error swapRect(EGLint x, EGLint y, EGLint width, EGLint height);
egl::Error resetSwapChain(int backbufferWidth, int backbufferHeight);
egl::Error resizeSwapChain(int backbufferWidth, int backbufferHeight);
void subclassWindow();
void unsubclassWindow();
RendererD3D *mRenderer;
SwapChain *mSwapChain;
bool mSwapIntervalDirty;
bool mWindowSubclassed; // Indicates whether we successfully subclassed mWindow for WM_RESIZE hooking
NativeWindow mNativeWindow; // Handler for the Window that the surface is created for.
};
}
#endif // LIBANGLE_RENDERER_D3D_SURFACED3D_H_
...@@ -6,22 +6,22 @@ ...@@ -6,22 +6,22 @@
// TextureD3D.cpp: Implementations of the Texture interfaces shared betweeen the D3D backends. // TextureD3D.cpp: Implementations of the Texture interfaces shared betweeen the D3D backends.
#include "libANGLE/renderer/d3d/TextureD3D.h"
#include "common/mathutil.h"
#include "common/utilities.h"
#include "libANGLE/Buffer.h" #include "libANGLE/Buffer.h"
#include "libANGLE/Framebuffer.h" #include "libANGLE/Framebuffer.h"
#include "libANGLE/Surface.h"
#include "libANGLE/Texture.h" #include "libANGLE/Texture.h"
#include "libANGLE/formatutils.h" #include "libANGLE/formatutils.h"
#include "libANGLE/renderer/BufferImpl.h" #include "libANGLE/renderer/BufferImpl.h"
#include "libANGLE/renderer/RenderTarget.h" #include "libANGLE/renderer/RenderTarget.h"
#include "libANGLE/renderer/d3d/BufferD3D.h" #include "libANGLE/renderer/d3d/BufferD3D.h"
#include "libANGLE/renderer/d3d/TextureD3D.h"
#include "libANGLE/renderer/d3d/TextureStorage.h"
#include "libANGLE/renderer/d3d/ImageD3D.h" #include "libANGLE/renderer/d3d/ImageD3D.h"
#include "libANGLE/renderer/d3d/RendererD3D.h" #include "libANGLE/renderer/d3d/RendererD3D.h"
#include "libANGLE/renderer/d3d/SurfaceD3D.h"
#include "libANGLE/Surface.h" #include "libANGLE/renderer/d3d/TextureStorage.h"
#include "common/mathutil.h"
#include "common/utilities.h"
namespace rx namespace rx
{ {
...@@ -847,7 +847,10 @@ void TextureD3D_2D::bindTexImage(egl::Surface *surface) ...@@ -847,7 +847,10 @@ void TextureD3D_2D::bindTexImage(egl::Surface *surface)
SafeDelete(mTexStorage); SafeDelete(mTexStorage);
} }
mTexStorage = mRenderer->createTextureStorage2D(surface->getSwapChain()); SurfaceD3D *surfaceD3D = SurfaceD3D::makeSurfaceD3D(surface);
ASSERT(surfaceD3D);
mTexStorage = mRenderer->createTextureStorage2D(surfaceD3D->getSwapChain());
mDirtyImages = true; mDirtyImages = true;
} }
......
...@@ -6,48 +6,46 @@ ...@@ -6,48 +6,46 @@
// Renderer11.cpp: Implements a back-end specific class for the D3D11 renderer. // Renderer11.cpp: Implements a back-end specific class for the D3D11 renderer.
#include "libANGLE/renderer/d3d/d3d11/Renderer11.h"
#include "common/utilities.h"
#include "common/tls.h"
#include "libANGLE/Buffer.h" #include "libANGLE/Buffer.h"
#include "libANGLE/Display.h"
#include "libANGLE/Framebuffer.h"
#include "libANGLE/FramebufferAttachment.h" #include "libANGLE/FramebufferAttachment.h"
#include "libANGLE/ProgramBinary.h" #include "libANGLE/ProgramBinary.h"
#include "libANGLE/Framebuffer.h"
#include "libANGLE/State.h" #include "libANGLE/State.h"
#include "libANGLE/Surface.h"
#include "libANGLE/renderer/d3d/FramebufferD3D.h"
#include "libANGLE/renderer/d3d/IndexDataManager.h"
#include "libANGLE/renderer/d3d/ProgramD3D.h" #include "libANGLE/renderer/d3d/ProgramD3D.h"
#include "libANGLE/renderer/d3d/RenderbufferD3D.h"
#include "libANGLE/renderer/d3d/ShaderD3D.h" #include "libANGLE/renderer/d3d/ShaderD3D.h"
#include "libANGLE/renderer/d3d/SurfaceD3D.h"
#include "libANGLE/renderer/d3d/TextureD3D.h" #include "libANGLE/renderer/d3d/TextureD3D.h"
#include "libANGLE/renderer/d3d/TransformFeedbackD3D.h" #include "libANGLE/renderer/d3d/TransformFeedbackD3D.h"
#include "libANGLE/renderer/d3d/FramebufferD3D.h" #include "libANGLE/renderer/d3d/VertexDataManager.h"
#include "libANGLE/renderer/d3d/d3d11/Renderer11.h" #include "libANGLE/renderer/d3d/d3d11/Blit11.h"
#include "libANGLE/renderer/d3d/d3d11/Buffer11.h"
#include "libANGLE/renderer/d3d/d3d11/Clear11.h"
#include "libANGLE/renderer/d3d/d3d11/Fence11.h"
#include "libANGLE/renderer/d3d/d3d11/Image11.h"
#include "libANGLE/renderer/d3d/d3d11/IndexBuffer11.h"
#include "libANGLE/renderer/d3d/d3d11/PixelTransfer11.h"
#include "libANGLE/renderer/d3d/d3d11/Query11.h"
#include "libANGLE/renderer/d3d/d3d11/RenderTarget11.h" #include "libANGLE/renderer/d3d/d3d11/RenderTarget11.h"
#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h"
#include "libANGLE/renderer/d3d/d3d11/formatutils11.h"
#include "libANGLE/renderer/d3d/d3d11/ShaderExecutable11.h" #include "libANGLE/renderer/d3d/d3d11/ShaderExecutable11.h"
#include "libANGLE/renderer/d3d/d3d11/SwapChain11.h" #include "libANGLE/renderer/d3d/d3d11/SwapChain11.h"
#include "libANGLE/renderer/d3d/d3d11/Image11.h"
#include "libANGLE/renderer/d3d/d3d11/VertexBuffer11.h"
#include "libANGLE/renderer/d3d/d3d11/IndexBuffer11.h"
#include "libANGLE/renderer/d3d/d3d11/Buffer11.h"
#include "libANGLE/renderer/d3d/VertexDataManager.h"
#include "libANGLE/renderer/d3d/IndexDataManager.h"
#include "libANGLE/renderer/d3d/d3d11/TextureStorage11.h" #include "libANGLE/renderer/d3d/d3d11/TextureStorage11.h"
#include "libANGLE/renderer/d3d/d3d11/Query11.h"
#include "libANGLE/renderer/d3d/d3d11/Fence11.h"
#include "libANGLE/renderer/d3d/d3d11/Blit11.h"
#include "libANGLE/renderer/d3d/d3d11/Clear11.h"
#include "libANGLE/renderer/d3d/d3d11/Trim11.h" #include "libANGLE/renderer/d3d/d3d11/Trim11.h"
#include "libANGLE/renderer/d3d/d3d11/PixelTransfer11.h"
#include "libANGLE/renderer/d3d/d3d11/VertexArray11.h" #include "libANGLE/renderer/d3d/d3d11/VertexArray11.h"
#include "libANGLE/renderer/d3d/d3d11/Buffer11.h" #include "libANGLE/renderer/d3d/d3d11/VertexBuffer11.h"
#include "libANGLE/renderer/d3d/RenderbufferD3D.h" #include "libANGLE/renderer/d3d/d3d11/formatutils11.h"
#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h"
#include "libANGLE/Display.h"
#include "libANGLE/Surface.h"
#include "common/utilities.h"
#include "common/tls.h"
#include <EGL/eglext.h>
#include <sstream> #include <sstream>
#include <EGL/eglext.h>
// Enable ANGLE_SKIP_DXGI_1_2_CHECK if there is not a possibility of using cross-process // Enable ANGLE_SKIP_DXGI_1_2_CHECK if there is not a possibility of using cross-process
// HWNDs or the Windows 7 Platform Update (KB2670838) is expected to be installed. // HWNDs or the Windows 7 Platform Update (KB2670838) is expected to be installed.
...@@ -2392,7 +2390,9 @@ gl::Error Renderer11::createRenderTarget(int width, int height, GLenum format, G ...@@ -2392,7 +2390,9 @@ gl::Error Renderer11::createRenderTarget(int width, int height, GLenum format, G
DefaultAttachmentImpl *Renderer11::createDefaultAttachment(GLenum type, egl::Surface *surface) DefaultAttachmentImpl *Renderer11::createDefaultAttachment(GLenum type, egl::Surface *surface)
{ {
SwapChain11 *swapChain = SwapChain11::makeSwapChain11(surface->getSwapChain()); SurfaceD3D *surfaceD3D = SurfaceD3D::makeSurfaceD3D(surface);
SwapChain11 *swapChain = SwapChain11::makeSwapChain11(surfaceD3D->getSwapChain());
switch (type) switch (type)
{ {
case GL_BACK: case GL_BACK:
......
...@@ -7,40 +7,41 @@ ...@@ -7,40 +7,41 @@
// Renderer9.cpp: Implements a back-end specific class for the D3D9 renderer. // Renderer9.cpp: Implements a back-end specific class for the D3D9 renderer.
#include "libANGLE/renderer/d3d/d3d9/Renderer9.h" #include "libANGLE/renderer/d3d/d3d9/Renderer9.h"
#include "libANGLE/renderer/d3d/d3d9/renderer9_utils.h"
#include "libANGLE/renderer/d3d/d3d9/formatutils9.h" #include "common/utilities.h"
#include "libANGLE/renderer/d3d/d3d9/ShaderExecutable9.h"
#include "libANGLE/renderer/d3d/d3d9/SwapChain9.h"
#include "libANGLE/renderer/d3d/d3d9/TextureStorage9.h"
#include "libANGLE/renderer/d3d/d3d9/Image9.h"
#include "libANGLE/renderer/d3d/d3d9/Blit9.h"
#include "libANGLE/renderer/d3d/d3d9/RenderTarget9.h"
#include "libANGLE/renderer/d3d/d3d9/VertexBuffer9.h"
#include "libANGLE/renderer/d3d/d3d9/IndexBuffer9.h"
#include "libANGLE/renderer/d3d/d3d9/Buffer9.h"
#include "libANGLE/renderer/d3d/d3d9/Query9.h"
#include "libANGLE/renderer/d3d/d3d9/Fence9.h"
#include "libANGLE/renderer/d3d/d3d9/VertexArray9.h"
#include "libANGLE/renderer/d3d/IndexDataManager.h"
#include "libANGLE/renderer/d3d/ProgramD3D.h"
#include "libANGLE/renderer/d3d/ShaderD3D.h"
#include "libANGLE/renderer/d3d/TextureD3D.h"
#include "libANGLE/renderer/d3d/TransformFeedbackD3D.h"
#include "libANGLE/renderer/d3d/RenderbufferD3D.h"
#include "libANGLE/renderer/d3d/FramebufferD3D.h"
#include "libANGLE/Buffer.h" #include "libANGLE/Buffer.h"
#include "libANGLE/Texture.h" #include "libANGLE/Display.h"
#include "libANGLE/Framebuffer.h" #include "libANGLE/Framebuffer.h"
#include "libANGLE/FramebufferAttachment.h" #include "libANGLE/FramebufferAttachment.h"
#include "libANGLE/Renderbuffer.h"
#include "libANGLE/ProgramBinary.h" #include "libANGLE/ProgramBinary.h"
#include "libANGLE/Renderbuffer.h"
#include "libANGLE/State.h" #include "libANGLE/State.h"
#include "libANGLE/angletypes.h"
#include "libANGLE/Display.h"
#include "libANGLE/Surface.h" #include "libANGLE/Surface.h"
#include "libANGLE/Texture.h"
#include "libANGLE/angletypes.h"
#include "libANGLE/features.h" #include "libANGLE/features.h"
#include "libANGLE/renderer/d3d/FramebufferD3D.h"
#include "common/utilities.h" #include "libANGLE/renderer/d3d/IndexDataManager.h"
#include "libANGLE/renderer/d3d/ProgramD3D.h"
#include "libANGLE/renderer/d3d/RenderbufferD3D.h"
#include "libANGLE/renderer/d3d/ShaderD3D.h"
#include "libANGLE/renderer/d3d/SurfaceD3D.h"
#include "libANGLE/renderer/d3d/TextureD3D.h"
#include "libANGLE/renderer/d3d/TransformFeedbackD3D.h"
#include "libANGLE/renderer/d3d/d3d9/Blit9.h"
#include "libANGLE/renderer/d3d/d3d9/Buffer9.h"
#include "libANGLE/renderer/d3d/d3d9/Fence9.h"
#include "libANGLE/renderer/d3d/d3d9/Image9.h"
#include "libANGLE/renderer/d3d/d3d9/IndexBuffer9.h"
#include "libANGLE/renderer/d3d/d3d9/Query9.h"
#include "libANGLE/renderer/d3d/d3d9/RenderTarget9.h"
#include "libANGLE/renderer/d3d/d3d9/ShaderExecutable9.h"
#include "libANGLE/renderer/d3d/d3d9/SwapChain9.h"
#include "libANGLE/renderer/d3d/d3d9/TextureStorage9.h"
#include "libANGLE/renderer/d3d/d3d9/VertexArray9.h"
#include "libANGLE/renderer/d3d/d3d9/VertexBuffer9.h"
#include "libANGLE/renderer/d3d/d3d9/renderer9_utils.h"
#include "libANGLE/renderer/d3d/d3d9/formatutils9.h"
#include "third_party/trace_event/trace_event.h" #include "third_party/trace_event/trace_event.h"
...@@ -2849,7 +2850,9 @@ gl::Error Renderer9::createRenderTarget(int width, int height, GLenum format, GL ...@@ -2849,7 +2850,9 @@ gl::Error Renderer9::createRenderTarget(int width, int height, GLenum format, GL
DefaultAttachmentImpl *Renderer9::createDefaultAttachment(GLenum type, egl::Surface *surface) DefaultAttachmentImpl *Renderer9::createDefaultAttachment(GLenum type, egl::Surface *surface)
{ {
SwapChain9 *swapChain = SwapChain9::makeSwapChain9(surface->getSwapChain()); SurfaceD3D *surfaceD3D = SurfaceD3D::makeSurfaceD3D(surface);
SwapChain9 *swapChain = SwapChain9::makeSwapChain9(surfaceD3D->getSwapChain());
switch (type) switch (type)
{ {
case GL_BACK: case GL_BACK:
......
...@@ -18,9 +18,6 @@ ...@@ -18,9 +18,6 @@
#include "libANGLE/Surface.h" #include "libANGLE/Surface.h"
#include "libANGLE/renderer/SwapChain.h" #include "libANGLE/renderer/SwapChain.h"
// TODO: don't reference this from here, use a method on DisplayImpl to validate windows
#include "libANGLE/renderer/d3d/d3d11/NativeWindow.h"
#include "common/debug.h" #include "common/debug.h"
#include "common/version.h" #include "common/version.h"
...@@ -763,7 +760,7 @@ EGLBoolean __stdcall eglBindTexImage(EGLDisplay dpy, EGLSurface surface, EGLint ...@@ -763,7 +760,7 @@ EGLBoolean __stdcall eglBindTexImage(EGLDisplay dpy, EGLSurface surface, EGLint
return EGL_FALSE; return EGL_FALSE;
} }
textureObject->bindTexImage(eglSurface); eglSurface->bindTexImage(textureObject, buffer);
} }
recordError(egl::Error(EGL_SUCCESS)); recordError(egl::Error(EGL_SUCCESS));
...@@ -804,7 +801,7 @@ EGLBoolean __stdcall eglReleaseTexImage(EGLDisplay dpy, EGLSurface surface, EGLi ...@@ -804,7 +801,7 @@ EGLBoolean __stdcall eglReleaseTexImage(EGLDisplay dpy, EGLSurface surface, EGLi
if (texture) if (texture)
{ {
texture->releaseTexImage(); eglSurface->releaseTexImage(buffer);
} }
recordError(egl::Error(EGL_SUCCESS)); recordError(egl::Error(EGL_SUCCESS));
......
...@@ -127,6 +127,8 @@ ...@@ -127,6 +127,8 @@
'libANGLE/renderer/RenderTarget.cpp', 'libANGLE/renderer/RenderTarget.cpp',
'libANGLE/renderer/ShaderExecutable.h', 'libANGLE/renderer/ShaderExecutable.h',
'libANGLE/renderer/ShaderImpl.h', 'libANGLE/renderer/ShaderImpl.h',
'libANGLE/renderer/SurfaceImpl.cpp',
'libANGLE/renderer/SurfaceImpl.h',
'libANGLE/renderer/SwapChain.h', 'libANGLE/renderer/SwapChain.h',
'libANGLE/renderer/TextureImpl.h', 'libANGLE/renderer/TextureImpl.h',
'libANGLE/renderer/TransformFeedbackImpl.h', 'libANGLE/renderer/TransformFeedbackImpl.h',
...@@ -182,6 +184,8 @@ ...@@ -182,6 +184,8 @@
'libANGLE/renderer/d3d/RendererD3D.h', 'libANGLE/renderer/d3d/RendererD3D.h',
'libANGLE/renderer/d3d/ShaderD3D.cpp', 'libANGLE/renderer/d3d/ShaderD3D.cpp',
'libANGLE/renderer/d3d/ShaderD3D.h', 'libANGLE/renderer/d3d/ShaderD3D.h',
'libANGLE/renderer/d3d/SurfaceD3D.cpp',
'libANGLE/renderer/d3d/SurfaceD3D.h',
'libANGLE/renderer/d3d/TextureD3D.cpp', 'libANGLE/renderer/d3d/TextureD3D.cpp',
'libANGLE/renderer/d3d/TextureD3D.h', 'libANGLE/renderer/d3d/TextureD3D.h',
'libANGLE/renderer/d3d/TextureStorage.cpp', 'libANGLE/renderer/d3d/TextureStorage.cpp',
......
//
// Copyright (c) 2014 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.
//
#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include "libANGLE/Surface.h"
#include "libANGLE/renderer/SurfaceImpl.h"
namespace
{
class MockSurfaceImpl : public rx::SurfaceImpl
{
public:
virtual ~MockSurfaceImpl() { destroy(); }
MOCK_METHOD0(initialize, egl::Error());
MOCK_METHOD0(swap, egl::Error());
MOCK_METHOD4(postSubBuffer, egl::Error(EGLint, EGLint, EGLint, EGLint));
MOCK_METHOD2(querySurfacePointerANGLE, egl::Error(EGLint, void**));
MOCK_METHOD1(bindTexImage, egl::Error(EGLint));
MOCK_METHOD1(releaseTexImage, egl::Error(EGLint));
MOCK_METHOD1(setSwapInterval, void(EGLint));
MOCK_CONST_METHOD0(getWindowHandle, EGLNativeWindowType());
MOCK_METHOD0(destroy, void());
};
class SurfaceTest : public testing::Test
{
protected:
virtual void SetUp()
{
mImpl = new MockSurfaceImpl;
EXPECT_CALL(*mImpl, setSwapInterval(1));
EXPECT_CALL(*mImpl, destroy());
mSurface = new egl::Surface(mImpl);
}
virtual void TearDown()
{
delete mSurface;
}
MockSurfaceImpl *mImpl;
egl::Surface *mSurface;
};
TEST_F(SurfaceTest, DestructionDeletesImpl)
{
MockSurfaceImpl *impl = new MockSurfaceImpl;
EXPECT_CALL(*impl, setSwapInterval(1)).Times(1).RetiresOnSaturation();
EXPECT_CALL(*impl, destroy()).Times(1).RetiresOnSaturation();
egl::Surface *surface = new egl::Surface(impl);
delete surface;
// Only needed because the mock is leaked if bugs are present,
// which logs an error, but does not cause the test to fail.
// Ordinarily mocks are verified when destroyed.
testing::Mock::VerifyAndClear(impl);
}
} // namespace
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
[ [
'Fence_unittest.cpp', 'Fence_unittest.cpp',
'ImageIndexIterator_unittest.cpp', 'ImageIndexIterator_unittest.cpp',
'Surface_unittest.cpp',
'TransformFeedback_unittest.cpp' 'TransformFeedback_unittest.cpp'
], ],
} }
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