b=618892; [webgl] implement pbuffers in ANGLE for faster interop; r=upstream

This commit is contained in:
Vladimir Vukicevic 2011-01-06 14:07:12 -08:00
parent 0e6fa3a53a
commit e24c8b11dd
10 changed files with 206 additions and 33 deletions

View File

@ -9,6 +9,8 @@ Local patches:
angle-nspr-misc.patch - don't bother with ANGLE_OS detection with NSPR
angle-pbuffers.patch - add pbuffer support to ANGLE, and d3d texture handle query (angle issue 91)
== Visual Studio Solution Files ==
The VS solution/project files that are used to build ANGLE are built

View File

@ -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 1
#define EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE 0x3200
#endif
#ifdef __cplusplus
}
#endif

View File

@ -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: /* ignore */ break;
case EGL_MAX_PBUFFER_HEIGHT: /* ignore */ break;
case EGL_MAX_PBUFFER_PIXELS: /* ignore */ break;
default:
return false;
}

View File

@ -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);

View File

@ -189,7 +189,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);
}
}
}
@ -332,6 +333,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;
}
@ -403,6 +407,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)
@ -639,4 +653,4 @@ D3DPRESENT_PARAMETERS Display::getDefaultPresentParameters()
return presentParameters;
}
}
}

View File

@ -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);
@ -67,6 +68,8 @@ class Display
virtual bool getLuminanceTextureSupport();
virtual bool getLuminanceAlphaTextureSupport();
bool isD3d9exDevice() { return mD3d9ex != NULL; }
private:
DISALLOW_COPY_AND_ASSIGN(Display);

View File

@ -24,6 +24,7 @@ Surface::Surface(Display *display, const Config *config, HWND window)
mDepthStencil = NULL;
mBackBuffer = NULL;
mFlipTexture = NULL;
mShareHandle = NULL;
mFlipState = NULL;
mPreFlipState = NULL;
@ -37,6 +38,27 @@ Surface::Surface(Display *display, const Config *config, HWND window)
resetSwapChain();
}
Surface::Surface(Display *display, const Config *config, EGLint width, EGLint height)
: mDisplay(display), mConfig(config), mWindow(NULL), mWindowSubclassed(false),
mWidth(width), mHeight(height)
{
mSwapChain = NULL;
mDepthStencil = NULL;
mBackBuffer = NULL;
mFlipTexture = NULL;
mShareHandle = NULL;
mFlipState = NULL;
mPreFlipState = NULL;
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();
@ -84,6 +106,11 @@ void Surface::release()
void Surface::resetSwapChain()
{
if (!mWindow) {
resetSwapChain(mWidth, mHeight);
return;
}
RECT windowRect;
if (!GetClientRect(getWindowHandle(), &windowRect))
{
@ -109,8 +136,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;
@ -126,14 +154,16 @@ 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);
if (FAILED(result))
{
ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
if (FAILED(result))
{
ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
ERR("Could not create additional swap chains: %08lX", result);
return error(EGL_BAD_ALLOC);
ERR("Could not create additional swap chains: %08lX", result);
return error(EGL_BAD_ALLOC);
}
}
result = device->CreateDepthStencilSurface(presentParameters.BackBufferWidth, presentParameters.BackBufferHeight,
@ -144,7 +174,8 @@ void Surface::resetSwapChain(int backbufferWidth, int backbufferHeight)
{
ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
mSwapChain->Release();
if (mSwapChain)
mSwapChain->Release();
ERR("Could not create depthstencil surface for new swap chain: %08lX", result);
return error(EGL_BAD_ALLOC);
@ -152,27 +183,39 @@ void Surface::resetSwapChain(int backbufferWidth, int backbufferHeight)
ASSERT(SUCCEEDED(result));
HANDLE *pShareHandle = NULL;
if (mDisplay->isD3d9exDevice()) {
pShareHandle = &mShareHandle;
}
result = device->CreateTexture(presentParameters.BackBufferWidth, presentParameters.BackBufferHeight, 1, D3DUSAGE_RENDERTARGET,
presentParameters.BackBufferFormat, D3DPOOL_DEFAULT, &mFlipTexture, NULL);
presentParameters.BackBufferFormat, D3DPOOL_DEFAULT, &mFlipTexture, pShareHandle);
if (FAILED(result))
{
ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
mSwapChain->Release();
if (mSwapChain)
mSwapChain->Release();
mDepthStencil->Release();
ERR("Could not create flip texture for new swap chain: %08lX", result);
return error(EGL_BAD_ALLOC);
}
mSwapChain->GetBackBuffer(0, D3DBACKBUFFER_TYPE_MONO, &mBackBuffer);
if (mSwapChain) {
mSwapChain->GetBackBuffer(0, D3DBACKBUFFER_TYPE_MONO, &mBackBuffer);
} else {
mFlipTexture->GetSurfaceLevel(0, &mBackBuffer);
}
mWidth = presentParameters.BackBufferWidth;
mHeight = presentParameters.BackBufferHeight;
mPresentIntervalDirty = false;
InvalidateRect(mWindow, NULL, FALSE);
if (mWindow)
InvalidateRect(mWindow, NULL, FALSE);
// The flip state block recorded mFlipTexture so it is now invalid.
releaseRecordedState(device);
@ -327,6 +370,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) {

View File

@ -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
@ -52,6 +55,7 @@ private:
IDirect3DSurface9 *mBackBuffer;
IDirect3DSurface9 *mDepthStencil;
IDirect3DTexture9 *mFlipTexture;
HANDLE mShareHandle;
void subclassWindow();
void unsubclassWindow();

View File

@ -193,7 +193,7 @@ const char *__stdcall eglQueryString(EGLDisplay dpy, EGLint name)
case EGL_CLIENT_APIS:
return success("OpenGL_ES");
case EGL_EXTENSIONS:
return success("");
return success("EGL_ANGLE_query_surface_pointer EGL_ANGLE_surface_d3d_texture_2d_share_handle");
case EGL_VENDOR:
return success("TransGaming Inc.");
case EGL_VERSION:
@ -390,15 +390,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);
}
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&)
{
@ -424,7 +470,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&)
{
@ -549,6 +595,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)
{
TRACE("(EGLenum api = 0x%X)", api);
@ -698,9 +784,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&)
{
@ -723,9 +809,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&)
{
@ -1092,6 +1178,7 @@ __eglMustCastToProperFunctionPointerType __stdcall eglGetProcAddress(const char
static const Extension eglExtensions[] =
{
{"eglQuerySurfacePointerANGLE", (__eglMustCastToProperFunctionPointerType)eglQuerySurfacePointerANGLE},
{"", NULL},
};

View File

@ -11,6 +11,7 @@
#define EGLAPI
#include <EGL/egl.h>
#include <EGL/eglext.h>
namespace egl
{