Commit 721b7f26 by vladimirv@gmail.com

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
parent 9e83b593
......@@ -215,6 +215,19 @@ typedef EGLBoolean (EGLAPIENTRYP PFNEGLSIGNALSYNCNVPROC) (EGLSyncNV sync, EGLenu
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
......
......@@ -19,10 +19,10 @@ using namespace std;
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 @@ void Config::setDefaults()
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 @@ void Config::set(D3DDISPLAYMODE displayMode, EGLint minInterval, EGLint maxInter
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 @@ ConfigSet::ConfigSet()
{
}
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 @@ bool ConfigSet::getConfigs(EGLConfig *configs, const EGLint *attribList, EGLint
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;
}
......
......@@ -26,10 +26,10 @@ class Display;
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 @@ class ConfigSet
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);
......
......@@ -181,7 +181,8 @@ bool Display::initialize()
{
// 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 @@ bool Display::initialize()
return false;
}
initExtensionString();
static const TCHAR windowName[] = TEXT("AngleHiddenWindow");
static const TCHAR className[] = TEXT("STATIC");
......@@ -329,6 +332,9 @@ bool Display::getConfigAttrib(EGLConfig config, EGLint attribute, EGLint *value)
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 @@ Surface *Display::createWindowSurface(HWND window, EGLConfig config)
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 @@ D3DPRESENT_PARAMETERS Display::getDefaultPresentParameters()
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();
}
}
......@@ -43,6 +43,7 @@ class Display
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 @@ class Display
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 @@ class Display
bool createDevice();
bool resetDevice();
void initExtensionString();
std::string mExtensionString;
};
}
......
......@@ -25,6 +25,8 @@ Surface::Surface(Display *display, const Config *config, HWND window)
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 @@ Surface::Surface(Display *display, const Config *config, HWND window)
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 @@ void Surface::release()
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 @@ void Surface::resetSwapChain(int backbufferWidth, int backbufferHeight)
// 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 @@ void Surface::resetSwapChain(int backbufferWidth, int backbufferHeight)
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 @@ void Surface::resetSwapChain(int backbufferWidth, int backbufferHeight)
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 @@ static LRESULT CALLBACK SurfaceWindowProc(HWND hwnd, UINT message, WPARAM wparam
void Surface::subclassWindow()
{
if (!mWindow)
return;
SetLastError(0);
LONG oldWndProc = SetWindowLong(mWindow, GWL_WNDPROC, reinterpret_cast<LONG>(SurfaceWindowProc));
if(oldWndProc == 0 && GetLastError() != ERROR_SUCCESS) {
......
......@@ -26,6 +26,7 @@ class Surface
{
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 @@ class Surface
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 @@ private:
IDirect3DSwapChain9 *mSwapChain;
IDirect3DSurface9 *mDepthStencil;
IDirect3DSurface9* mRenderTarget;
IDirect3DTexture9* mOffscreenTexture;
HANDLE mShareHandle;
void subclassWindow();
void unsubclassWindow();
......
......@@ -194,7 +194,7 @@ const char *__stdcall eglQueryString(EGLDisplay dpy, EGLint name)
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 @@ EGLSurface __stdcall eglCreatePbufferSurface(EGLDisplay dpy, EGLConfig config, c
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);
}
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(EGL_NO_DISPLAY);
return success(surface);
}
catch(std::bad_alloc&)
{
......@@ -425,7 +471,7 @@ EGLSurface __stdcall eglCreatePixmapSurface(EGLDisplay dpy, EGLConfig config, EG
UNIMPLEMENTED(); // FIXME
return success(EGL_NO_DISPLAY);
return success(EGL_NO_SURFACE);
}
catch(std::bad_alloc&)
{
......@@ -550,6 +596,46 @@ EGLBoolean __stdcall eglQuerySurface(EGLDisplay dpy, EGLSurface surface, EGLint
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 @@ EGLBoolean __stdcall eglBindTexImage(EGLDisplay dpy, EGLSurface surface, EGLint
return EGL_FALSE;
}
UNIMPLEMENTED(); // FIXME
// FIXME - need implementation
return success(EGL_TRUE);
return success(EGL_FALSE);
}
catch(std::bad_alloc&)
{
......@@ -724,9 +810,9 @@ EGLBoolean __stdcall eglReleaseTexImage(EGLDisplay dpy, EGLSurface surface, EGLi
return EGL_FALSE;
}
UNIMPLEMENTED(); // FIXME
// FIXME - need implementation
return success(EGL_TRUE);
return success(EGL_FALSE);
}
catch(std::bad_alloc&)
{
......@@ -1093,6 +1179,7 @@ __eglMustCastToProperFunctionPointerType __stdcall eglGetProcAddress(const char
static const Extension eglExtensions[] =
{
{"eglQuerySurfacePointerANGLE", (__eglMustCastToProperFunctionPointerType)eglQuerySurfacePointerANGLE},
{"", NULL},
};
......
......@@ -11,6 +11,7 @@
#define EGLAPI
#include <EGL/egl.h>
#include <EGL/eglext.h>
namespace egl
{
......
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