Issue=91 -- implement pbuffers in ANGLE; add D3D share handle support
git-svn-id: https://angleproject.googlecode.com/svn/trunk@558 736b8ea6-26fd-11df-bfd4-992fa37f6226
diff --git a/include/EGL/eglext.h b/include/EGL/eglext.h
index 638e336..b650a50 100644
--- a/include/EGL/eglext.h
+++ b/include/EGL/eglext.h
@@ -215,6 +215,19 @@
typedef EGLBoolean (EGLAPIENTRYP PFNEGLGETSYNCATTRIBNVPROC) (EGLSyncNV sync, EGLint attribute, EGLint *value);
#endif
+#ifndef EGL_ANGLE_query_surface_pointer
+#define EGL_ANGLE_query_surface_pointer 1
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLBoolean eglQuerySurfacePointerANGLE(EGLDisplay dpy, EGLSurface surface, EGLint attribute, void **value);
+#endif
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYSURFACEPOINTERANGLEPROC) (EGLDisplay dpy, EGLSurface surface, EGLint attribute, void **value);
+#endif
+
+#ifndef EGL_ANGLE_surface_d3d_texture_2d_share_handle
+#define EGL_ANGLE_surface_d3d_texture_2d_share_handle
+#define EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE 0x3200
+#endif
+
#ifdef __cplusplus
}
#endif
diff --git a/src/libEGL/Config.cpp b/src/libEGL/Config.cpp
index 284f61d..511b8ae 100644
--- a/src/libEGL/Config.cpp
+++ b/src/libEGL/Config.cpp
@@ -19,10 +19,10 @@
namespace egl
{
-Config::Config(D3DDISPLAYMODE displayMode, EGLint minInterval, EGLint maxInterval, D3DFORMAT renderTargetFormat, D3DFORMAT depthStencilFormat, EGLint multiSample)
+Config::Config(D3DDISPLAYMODE displayMode, EGLint minInterval, EGLint maxInterval, D3DFORMAT renderTargetFormat, D3DFORMAT depthStencilFormat, EGLint multiSample, EGLint texWidth, EGLint texHeight)
: mDisplayMode(displayMode), mRenderTargetFormat(renderTargetFormat), mDepthStencilFormat(depthStencilFormat), mMultiSample(multiSample)
{
- set(displayMode, minInterval, maxInterval, renderTargetFormat, depthStencilFormat, multiSample);
+ set(displayMode, minInterval, maxInterval, renderTargetFormat, depthStencilFormat, multiSample, texWidth, texHeight);
}
void Config::setDefaults()
@@ -62,7 +62,7 @@
mTransparentBlueValue = EGL_DONT_CARE;
}
-void Config::set(D3DDISPLAYMODE displayMode, EGLint minInterval, EGLint maxInterval, D3DFORMAT renderTargetFormat, D3DFORMAT depthStencilFormat, EGLint multiSample)
+void Config::set(D3DDISPLAYMODE displayMode, EGLint minInterval, EGLint maxInterval, D3DFORMAT renderTargetFormat, D3DFORMAT depthStencilFormat, EGLint multiSample, EGLint texWidth, EGLint texHeight)
{
switch (renderTargetFormat)
{
@@ -158,9 +158,9 @@
mLevel = 0;
mMatchNativePixmap = EGL_NONE;
- mMaxPBufferWidth = 0;
- mMaxPBufferHeight = 0;
- mMaxPBufferPixels = 0;
+ mMaxPBufferWidth = texWidth;
+ mMaxPBufferHeight = texHeight;
+ mMaxPBufferPixels = texWidth*texHeight;
mMaxSwapInterval = maxInterval;
mMinSwapInterval = minInterval;
mNativeRenderable = EGL_FALSE;
@@ -282,9 +282,9 @@
{
}
-void ConfigSet::add(D3DDISPLAYMODE displayMode, EGLint minSwapInterval, EGLint maxSwapInterval, D3DFORMAT renderTargetFormat, D3DFORMAT depthStencilFormat, EGLint multiSample)
+void ConfigSet::add(D3DDISPLAYMODE displayMode, EGLint minSwapInterval, EGLint maxSwapInterval, D3DFORMAT renderTargetFormat, D3DFORMAT depthStencilFormat, EGLint multiSample, EGLint texWidth, EGLint texHeight)
{
- Config config(displayMode, minSwapInterval, maxSwapInterval, renderTargetFormat, depthStencilFormat, multiSample);
+ Config config(displayMode, minSwapInterval, maxSwapInterval, renderTargetFormat, depthStencilFormat, multiSample, texWidth, texHeight);
mSet.insert(config);
}
@@ -337,6 +337,9 @@
case EGL_RENDERABLE_TYPE: match = (config->mRenderableType & attribute[1]) == attribute[1]; break;
case EGL_MATCH_NATIVE_PIXMAP: match = false; UNIMPLEMENTED(); break;
case EGL_CONFORMANT: match = (config->mConformant & attribute[1]) == attribute[1]; break;
+ case EGL_MAX_PBUFFER_WIDTH: match = config->mMaxPBufferWidth >= attribute[1]; break;
+ case EGL_MAX_PBUFFER_HEIGHT: match = config->mMaxPBufferHeight >= attribute[1]; break;
+ case EGL_MAX_PBUFFER_PIXELS: match = config->mMaxPBufferPixels >= attribute[1]; break;
default:
return false;
}
diff --git a/src/libEGL/Config.h b/src/libEGL/Config.h
index b340f56..95626ed 100644
--- a/src/libEGL/Config.h
+++ b/src/libEGL/Config.h
@@ -26,10 +26,10 @@
class Config
{
public:
- Config(D3DDISPLAYMODE displayMode, EGLint minSwapInterval, EGLint maxSwapInterval, D3DFORMAT renderTargetFormat, D3DFORMAT depthStencilFormat, EGLint multiSample);
+ Config(D3DDISPLAYMODE displayMode, EGLint minSwapInterval, EGLint maxSwapInterval, D3DFORMAT renderTargetFormat, D3DFORMAT depthStencilFormat, EGLint multiSample, EGLint texWidth, EGLint texHeight);
void setDefaults();
- void set(D3DDISPLAYMODE displayMode, EGLint minSwapInterval, EGLint maxSwapInterval, D3DFORMAT renderTargetFormat, D3DFORMAT depthStencilFormat, EGLint multiSample);
+ void set(D3DDISPLAYMODE displayMode, EGLint minSwapInterval, EGLint maxSwapInterval, D3DFORMAT renderTargetFormat, D3DFORMAT depthStencilFormat, EGLint multiSample, EGLint texWidth, EGLint texHeight);
EGLConfig getHandle() const;
const D3DDISPLAYMODE mDisplayMode;
@@ -99,7 +99,7 @@
public:
ConfigSet();
- void add(D3DDISPLAYMODE displayMode, EGLint minSwapInterval, EGLint maxSwapInterval, D3DFORMAT renderTargetFormat, D3DFORMAT depthStencilFormat, EGLint multiSample);
+ void add(D3DDISPLAYMODE displayMode, EGLint minSwapInterval, EGLint maxSwapInterval, D3DFORMAT renderTargetFormat, D3DFORMAT depthStencilFormat, EGLint multiSample, EGLint texWidth, EGLint texHeight);
size_t size() const;
bool getConfigs(EGLConfig *configs, const EGLint *attribList, EGLint configSize, EGLint *numConfig);
const egl::Config *get(EGLConfig configHandle);
diff --git a/src/libEGL/Display.cpp b/src/libEGL/Display.cpp
index 4673e73..15901ae 100644
--- a/src/libEGL/Display.cpp
+++ b/src/libEGL/Display.cpp
@@ -181,7 +181,8 @@
{
// FIXME: enumerate multi-sampling
- configSet.add(currentDisplayMode, mMinSwapInterval, mMaxSwapInterval, renderTargetFormat, depthStencilFormat, 0);
+ configSet.add(currentDisplayMode, mMinSwapInterval, mMaxSwapInterval, renderTargetFormat, depthStencilFormat, 0,
+ mDeviceCaps.MaxTextureWidth, mDeviceCaps.MaxTextureHeight);
}
}
}
@@ -207,6 +208,8 @@
return false;
}
+ initExtensionString();
+
static const TCHAR windowName[] = TEXT("AngleHiddenWindow");
static const TCHAR className[] = TEXT("STATIC");
@@ -329,6 +332,9 @@
case EGL_RENDERABLE_TYPE: *value = configuration->mRenderableType; break;
case EGL_MATCH_NATIVE_PIXMAP: *value = false; UNIMPLEMENTED(); break;
case EGL_CONFORMANT: *value = configuration->mConformant; break;
+ case EGL_MAX_PBUFFER_WIDTH: *value = configuration->mMaxPBufferWidth; break;
+ case EGL_MAX_PBUFFER_HEIGHT: *value = configuration->mMaxPBufferHeight; break;
+ case EGL_MAX_PBUFFER_PIXELS: *value = configuration->mMaxPBufferPixels; break;
default:
return false;
}
@@ -406,6 +412,16 @@
return surface;
}
+Surface *Display::createOffscreenSurface(int width, int height, EGLConfig config)
+{
+ const Config *configuration = mConfigSet.get(config);
+
+ Surface *surface = new Surface(this, configuration, width, height);
+ mSurfaceSet.insert(surface);
+
+ return surface;
+}
+
EGLContext Display::createContext(EGLConfig configHandle, const gl::Context *shareContext)
{
if (!mDevice)
@@ -671,4 +687,25 @@
return presentParameters;
}
-}
\ No newline at end of file
+
+void Display::initExtensionString()
+{
+ mExtensionString += "EGL_ANGLE_query_surface_pointer ";
+
+ if (isD3d9ExDevice()) {
+ mExtensionString += "EGL_ANGLE_surface_d3d_texture_2d_share_handle ";
+ }
+
+ std::string::size_type end = mExtensionString.find_last_not_of(' ');
+ if (end != std::string::npos)
+ {
+ mExtensionString.resize(end+1);
+ }
+}
+
+const char *Display::getExtensionString() const
+{
+ return mExtensionString.c_str();
+}
+
+}
diff --git a/src/libEGL/Display.h b/src/libEGL/Display.h
index c87d5ec..8434973 100644
--- a/src/libEGL/Display.h
+++ b/src/libEGL/Display.h
@@ -43,6 +43,7 @@
bool getConfigAttrib(EGLConfig config, EGLint attribute, EGLint *value);
egl::Surface *createWindowSurface(HWND window, EGLConfig config);
+ egl::Surface *createOffscreenSurface(int width, int height, EGLConfig config);
EGLContext createContext(EGLConfig configHandle, const gl::Context *shareContext);
void destroySurface(egl::Surface *surface);
@@ -69,6 +70,9 @@
virtual bool getLuminanceAlphaTextureSupport();
virtual D3DPOOL getBufferPool(DWORD usage) const;
+ bool isD3d9ExDevice() { return mD3d9Ex != NULL; }
+ const char *getExtensionString() const;
+
private:
DISALLOW_COPY_AND_ASSIGN(Display);
@@ -101,6 +105,9 @@
bool createDevice();
bool resetDevice();
+
+ void initExtensionString();
+ std::string mExtensionString;
};
}
diff --git a/src/libEGL/Surface.cpp b/src/libEGL/Surface.cpp
index 5e7f97a..6c55e88 100644
--- a/src/libEGL/Surface.cpp
+++ b/src/libEGL/Surface.cpp
@@ -25,6 +25,8 @@
mSwapChain = NULL;
mDepthStencil = NULL;
mRenderTarget = NULL;
+ mOffscreenTexture = NULL;
+ mShareHandle = NULL;
mPixelAspectRatio = (EGLint)(1.0 * EGL_DISPLAY_SCALING); // FIXME: Determine actual pixel aspect ratio
mRenderBuffer = EGL_BACK_BUFFER;
@@ -36,6 +38,25 @@
resetSwapChain();
}
+Surface::Surface(Display *display, const Config *config, EGLint width, EGLint height)
+ : mDisplay(display), mWindow(NULL), mConfig(config), mWidth(width), mHeight(height)
+{
+ mSwapChain = NULL;
+ mDepthStencil = NULL;
+ mRenderTarget = NULL;
+ mOffscreenTexture = NULL;
+ mShareHandle = NULL;
+ mWindowSubclassed = false;
+
+ 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);
+
+ resetSwapChain(width, height);
+}
+
Surface::~Surface()
{
unsubclassWindow();
@@ -61,10 +82,21 @@
mRenderTarget->Release();
mRenderTarget = NULL;
}
+
+ if (mOffscreenTexture)
+ {
+ mOffscreenTexture->Release();
+ mOffscreenTexture = NULL;
+ }
}
void Surface::resetSwapChain()
{
+ if (!mWindow) {
+ resetSwapChain(mWidth, mHeight);
+ return;
+ }
+
RECT windowRect;
if (!GetClientRect(getWindowHandle(), &windowRect))
{
@@ -90,8 +122,9 @@
// before reallocating them to free up as much video memory as possible.
device->EvictManagedResources();
release();
-
+
D3DPRESENT_PARAMETERS presentParameters = {0};
+ HRESULT result;
presentParameters.AutoDepthStencilFormat = mConfig->mDepthStencilFormat;
presentParameters.BackBufferCount = 1;
@@ -107,13 +140,24 @@
presentParameters.BackBufferWidth = backbufferWidth;
presentParameters.BackBufferHeight = backbufferHeight;
- HRESULT result = device->CreateAdditionalSwapChain(&presentParameters, &mSwapChain);
+ if (mWindow)
+ {
+ result = device->CreateAdditionalSwapChain(&presentParameters, &mSwapChain);
+ } else {
+ HANDLE *pShareHandle = NULL;
+ if (mDisplay->isD3d9ExDevice()) {
+ pShareHandle = &mShareHandle;
+ }
+
+ result = device->CreateTexture(presentParameters.BackBufferWidth, presentParameters.BackBufferHeight, 1, D3DUSAGE_RENDERTARGET,
+ presentParameters.BackBufferFormat, D3DPOOL_DEFAULT, &mOffscreenTexture, pShareHandle);
+ }
if (FAILED(result))
{
ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
- ERR("Could not create additional swap chains: %08lX", result);
+ ERR("Could not create additional swap chains or offscreen surfaces: %08lX", result);
release();
return error(EGL_BAD_ALLOC);
}
@@ -131,13 +175,17 @@
return error(EGL_BAD_ALLOC);
}
- mSwapChain->GetBackBuffer(0, D3DBACKBUFFER_TYPE_MONO, &mRenderTarget);
+ if (mWindow) {
+ mSwapChain->GetBackBuffer(0, D3DBACKBUFFER_TYPE_MONO, &mRenderTarget);
+ InvalidateRect(mWindow, NULL, FALSE);
+ } else {
+ mOffscreenTexture->GetSurfaceLevel(0, &mRenderTarget);
+ }
+
mWidth = presentParameters.BackBufferWidth;
mHeight = presentParameters.BackBufferHeight;
mPresentIntervalDirty = false;
-
- InvalidateRect(mWindow, NULL, FALSE);
}
HWND Surface::getWindowHandle()
@@ -162,6 +210,9 @@
void Surface::subclassWindow()
{
+ if (!mWindow)
+ return;
+
SetLastError(0);
LONG oldWndProc = SetWindowLong(mWindow, GWL_WNDPROC, reinterpret_cast<LONG>(SurfaceWindowProc));
if(oldWndProc == 0 && GetLastError() != ERROR_SUCCESS) {
diff --git a/src/libEGL/Surface.h b/src/libEGL/Surface.h
index 180b8a8..87a19f3 100644
--- a/src/libEGL/Surface.h
+++ b/src/libEGL/Surface.h
@@ -26,6 +26,7 @@
{
public:
Surface(Display *display, const egl::Config *config, HWND window);
+ Surface(Display *display, const egl::Config *config, EGLint width, EGLint height);
~Surface();
@@ -41,6 +42,8 @@
virtual IDirect3DSurface9 *getRenderTarget();
virtual IDirect3DSurface9 *getDepthStencil();
+ HANDLE getShareHandle() { return mShareHandle; }
+
void setSwapInterval(EGLint interval);
bool checkForOutOfDateSwapChain(); // Returns true if swapchain changed due to resize or interval update
@@ -51,6 +54,9 @@
IDirect3DSwapChain9 *mSwapChain;
IDirect3DSurface9 *mDepthStencil;
IDirect3DSurface9* mRenderTarget;
+ IDirect3DTexture9* mOffscreenTexture;
+
+ HANDLE mShareHandle;
void subclassWindow();
void unsubclassWindow();
diff --git a/src/libEGL/libEGL.cpp b/src/libEGL/libEGL.cpp
index 4f97fd5..bc40763 100644
--- a/src/libEGL/libEGL.cpp
+++ b/src/libEGL/libEGL.cpp
@@ -194,7 +194,7 @@
case EGL_CLIENT_APIS:
return success("OpenGL_ES");
case EGL_EXTENSIONS:
- return success("");
+ return display->getExtensionString();
case EGL_VENDOR:
return success("Google Inc.");
case EGL_VERSION:
@@ -391,15 +391,61 @@
try
{
egl::Display *display = static_cast<egl::Display*>(dpy);
+ EGLint width = 0, height = 0;
if (!validate(display, config))
{
return EGL_NO_SURFACE;
}
- UNIMPLEMENTED(); // FIXME
+ if (attrib_list)
+ {
+ while (*attrib_list != EGL_NONE)
+ {
+ switch (attrib_list[0])
+ {
+ case EGL_WIDTH:
+ width = attrib_list[1];
+ break;
+ case EGL_HEIGHT:
+ height = attrib_list[1];
+ break;
+ case EGL_LARGEST_PBUFFER:
+ if (attrib_list[1] != EGL_FALSE)
+ UNIMPLEMENTED(); // FIXME
+ break;
+ case EGL_TEXTURE_FORMAT:
+ case EGL_TEXTURE_TARGET:
+ switch (attrib_list[1])
+ {
+ case EGL_NO_TEXTURE:
+ break;
+ default:
+ return error(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE);
+ }
+ break;
+ case EGL_MIPMAP_TEXTURE:
+ if (attrib_list[1] != EGL_FALSE)
+ return error(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE);
+ break;
+ case EGL_VG_COLORSPACE:
+ return error(EGL_BAD_MATCH, EGL_NO_SURFACE);
+ case EGL_VG_ALPHA_FORMAT:
+ return error(EGL_BAD_MATCH, EGL_NO_SURFACE);
+ default:
+ return error(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE);
+ }
- return success(EGL_NO_DISPLAY);
+ attrib_list += 2;
+ }
+ }
+
+ if (width == 0 || height == 0)
+ return error(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE);
+
+ EGLSurface surface = (EGLSurface)display->createOffscreenSurface(width, height, config);
+
+ return success(surface);
}
catch(std::bad_alloc&)
{
@@ -425,7 +471,7 @@
UNIMPLEMENTED(); // FIXME
- return success(EGL_NO_DISPLAY);
+ return success(EGL_NO_SURFACE);
}
catch(std::bad_alloc&)
{
@@ -550,6 +596,46 @@
return EGL_FALSE;
}
+EGLBoolean __stdcall eglQuerySurfacePointerANGLE(EGLDisplay dpy, EGLSurface surface, EGLint attribute, void **value)
+{
+ TRACE("(EGLDisplay dpy = 0x%0.8p, EGLSurface surface = 0x%0.8p, EGLint attribute = %d, void **value = 0x%0.8p)",
+ dpy, surface, attribute, value);
+
+ try
+ {
+ egl::Display *display = static_cast<egl::Display*>(dpy);
+
+ if (!validate(display))
+ {
+ return EGL_FALSE;
+ }
+
+ if (surface == EGL_NO_SURFACE)
+ {
+ return error(EGL_BAD_SURFACE, EGL_FALSE);
+ }
+
+ egl::Surface *eglSurface = (egl::Surface*)surface;
+
+ switch (attribute)
+ {
+ case EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE:
+ *value = (void*) eglSurface->getShareHandle();
+ break;
+ default:
+ return error(EGL_BAD_ATTRIBUTE, EGL_FALSE);
+ }
+
+ return success(EGL_TRUE);
+ }
+ catch(std::bad_alloc&)
+ {
+ return error(EGL_BAD_ALLOC, EGL_FALSE);
+ }
+
+ return EGL_FALSE;
+}
+
EGLBoolean __stdcall eglBindAPI(EGLenum api)
{
EVENT("(EGLenum api = 0x%X)", api);
@@ -699,9 +785,9 @@
return EGL_FALSE;
}
- UNIMPLEMENTED(); // FIXME
+ // FIXME - need implementation
- return success(EGL_TRUE);
+ return success(EGL_FALSE);
}
catch(std::bad_alloc&)
{
@@ -724,9 +810,9 @@
return EGL_FALSE;
}
- UNIMPLEMENTED(); // FIXME
+ // FIXME - need implementation
- return success(EGL_TRUE);
+ return success(EGL_FALSE);
}
catch(std::bad_alloc&)
{
@@ -1093,6 +1179,7 @@
static const Extension eglExtensions[] =
{
+ {"eglQuerySurfacePointerANGLE", (__eglMustCastToProperFunctionPointerType)eglQuerySurfacePointerANGLE},
{"", NULL},
};
diff --git a/src/libEGL/main.h b/src/libEGL/main.h
index d6dc759..d09d9e6 100644
--- a/src/libEGL/main.h
+++ b/src/libEGL/main.h
@@ -11,6 +11,7 @@
#define EGLAPI
#include <EGL/egl.h>
+#include <EGL/eglext.h>
namespace egl
{