gfx/angle/angle-pbuffers.patch
author Bas Schouten <bas.schouten@live.nl>
Tue, 08 Feb 2011 18:44:14 -0600
changeset 62211 fa1a4b6abff0d357235b6e293dcba6aa1e592262
parent 61660 55196a9321b13b64f181aadb226f297f424a865c
permissions -rw-r--r--
Bug 612103 - Followup: Only report a failure when the call actually fails. r=jrmuizel a=blocking-final

# HG changeset patch
# Parent f0b9a118e816430191f013f327a19aff57cfb136
try: -b do -p win32 -u all -t none
repair ANGLE

diff --git a/gfx/angle/include/EGL/eglext.h b/gfx/angle/include/EGL/eglext.h
--- a/gfx/angle/include/EGL/eglext.h
+++ b/gfx/angle/include/EGL/eglext.h
@@ -210,13 +210,26 @@ EGLBoolean eglGetSyncAttribNV (EGLSyncNV
 typedef EGLSyncNV (EGLAPIENTRYP PFNEGLCREATEFENCESYNCNVPROC) (EGLDisplay dpy, EGLenum condition, const EGLint *attrib_list);
 typedef EGLBoolean (EGLAPIENTRYP PFNEGLDESTROYSYNCNVPROC) (EGLSyncNV sync);
 typedef EGLBoolean (EGLAPIENTRYP PFNEGLFENCENVPROC) (EGLSyncNV sync);
 typedef EGLint (EGLAPIENTRYP PFNEGLCLIENTWAITSYNCNVPROC) (EGLSyncNV sync, EGLint flags, EGLTimeNV timeout);
 typedef EGLBoolean (EGLAPIENTRYP PFNEGLSIGNALSYNCNVPROC) (EGLSyncNV sync, EGLenum mode);
 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_share_handle
+#define EGL_ANGLE_surface_d3d_share_handle
+#define EGL_D3D_TEXTURE_SHARE_HANDLE_ANGLE 0x3200
+#endif
+
 #ifdef __cplusplus
 }
 #endif
 
 #endif
diff --git a/gfx/angle/src/libEGL/Config.cpp b/gfx/angle/src/libEGL/Config.cpp
--- a/gfx/angle/src/libEGL/Config.cpp
+++ b/gfx/angle/src/libEGL/Config.cpp
@@ -14,20 +14,20 @@
 #include <vector>
 
 #include "common/debug.h"
 
 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()
 {
     mBufferSize = 0;
     mRedSize = 0;
     mGreenSize = 0;
     mBlueSize = 0;
@@ -57,17 +57,17 @@ void Config::setDefaults()
     mStencilSize = 0;
     mSurfaceType = EGL_WINDOW_BIT;
     mTransparentType = EGL_NONE;
     mTransparentRedValue = EGL_DONT_CARE;
     mTransparentGreenValue = EGL_DONT_CARE;
     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)
     {
       case D3DFMT_A1R5G5B5:
         mBufferSize = 16;
         mRedSize = 5;
         mGreenSize = 5;
         mBlueSize = 5;
@@ -153,19 +153,19 @@ void Config::set(D3DDISPLAYMODE displayM
 //      mStencilSize = 8;
 //      break;
       default:
         UNREACHABLE();
     }
 
     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;
     mNativeVisualID = 0;
     mNativeVisualType = 0;
     mRenderableType = EGL_OPENGL_ES2_BIT;
     mSampleBuffers = multiSample ? 1 : 0;
     mSamples = multiSample;
@@ -277,19 +277,19 @@ const EGLint ConfigSet::mSortAttribs[] =
     EGL_NONE
 };
 
 ConfigSet::ConfigSet()
     : mSet(SortConfig(mSortAttribs))
 {
 }
 
-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);
 }
 
 size_t ConfigSet::size() const
 {
     return mSet.size();
 }
@@ -332,16 +332,19 @@ bool ConfigSet::getConfigs(EGLConfig *co
               case EGL_MIN_SWAP_INTERVAL:         match = config->mMinSwapInterval == attribute[1];                 break;
               case EGL_MAX_SWAP_INTERVAL:         match = config->mMaxSwapInterval == attribute[1];                 break;
               case EGL_LUMINANCE_SIZE:            match = config->mLuminanceSize >= attribute[1];                   break;
               case EGL_ALPHA_MASK_SIZE:           match = config->mAlphaMaskSize >= attribute[1];                   break;
               case EGL_COLOR_BUFFER_TYPE:         match = config->mColorBufferType == attribute[1];                 break;
               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;
             }
 
             if (!match)
             {
                 break;
             }
diff --git a/gfx/angle/src/libEGL/Config.h b/gfx/angle/src/libEGL/Config.h
--- a/gfx/angle/src/libEGL/Config.h
+++ b/gfx/angle/src/libEGL/Config.h
@@ -21,20 +21,20 @@
 
 namespace egl
 {
 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;
     const D3DFORMAT mRenderTargetFormat;
     const D3DFORMAT mDepthStencilFormat;
     const EGLint mMultiSample;
 
     EGLint mBufferSize;              // Depth of the color buffer
@@ -94,17 +94,17 @@ class SortConfig
 
 class ConfigSet
 {
     friend Display;
 
   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);
 
   private:
     DISALLOW_COPY_AND_ASSIGN(ConfigSet);
 
     typedef std::set<Config, SortConfig> Set;
diff --git a/gfx/angle/src/libEGL/Display.cpp b/gfx/angle/src/libEGL/Display.cpp
--- a/gfx/angle/src/libEGL/Display.cpp
+++ b/gfx/angle/src/libEGL/Display.cpp
@@ -175,17 +175,18 @@ bool Display::initialize()
                     if (SUCCEEDED(result))
                     {
                         HRESULT result = mD3d9->CheckDepthStencilMatch(mAdapter, mDeviceType, currentDisplayMode.Format, renderTargetFormat, depthStencilFormat);
 
                         if (SUCCEEDED(result))
                         {
                             // FIXME: enumerate multi-sampling
 
-                            configSet.add(currentDisplayMode, mMinSwapInterval, mMaxSwapInterval, renderTargetFormat, depthStencilFormat, 0);
+                            configSet.add(currentDisplayMode, mMinSwapInterval, mMaxSwapInterval, renderTargetFormat, depthStencilFormat, 0,
+                                          mDeviceCaps.MaxTextureWidth, mDeviceCaps.MaxTextureHeight);
                         }
                     }
                 }
             }
         }
 
         // Give the sorted configs a unique ID and store them internally
         EGLint index = 1;
@@ -317,16 +318,19 @@ bool Display::getConfigAttrib(EGLConfig 
       case EGL_MIN_SWAP_INTERVAL:         *value = configuration->mMinSwapInterval;        break;
       case EGL_MAX_SWAP_INTERVAL:         *value = configuration->mMaxSwapInterval;        break;
       case EGL_LUMINANCE_SIZE:            *value = configuration->mLuminanceSize;          break;
       case EGL_ALPHA_MASK_SIZE:           *value = configuration->mAlphaMaskSize;          break;
       case EGL_COLOR_BUFFER_TYPE:         *value = configuration->mColorBufferType;        break;
       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;
     }
 
     return true;
 }
 
 bool Display::createDevice()
@@ -388,16 +392,26 @@ Surface *Display::createWindowSurface(HW
     const Config *configuration = mConfigSet.get(config);
 
     Surface *surface = new Surface(this, configuration, window);
     mSurfaceSet.insert(surface);
 
     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)
     {
         if (!createDevice())
         {
             return NULL;
         }
@@ -641,9 +655,9 @@ D3DPRESENT_PARAMETERS Display::getDefaul
     presentParameters.MultiSampleQuality = 0;
     presentParameters.MultiSampleType = D3DMULTISAMPLE_NONE;
     presentParameters.PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT;
     presentParameters.SwapEffect = D3DSWAPEFFECT_DISCARD;
     presentParameters.Windowed = TRUE;
 
     return presentParameters;
 }
-}
\ No newline at end of file
+}
diff --git a/gfx/angle/src/libEGL/Display.h b/gfx/angle/src/libEGL/Display.h
--- a/gfx/angle/src/libEGL/Display.h
+++ b/gfx/angle/src/libEGL/Display.h
@@ -38,16 +38,17 @@ class Display
 
     virtual void startScene();
     virtual void endScene();
 
     bool getConfigs(EGLConfig *configs, const EGLint *attribList, EGLint configSize, EGLint *numConfig);
     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);
     void destroyContext(gl::Context *context);
 
     bool isInitialized();
     bool isValidConfig(EGLConfig config);
     bool isValidContext(gl::Context *context);
@@ -63,16 +64,18 @@ class Display
     virtual bool getCompressedTextureSupport();
     virtual bool getEventQuerySupport();
     virtual bool getFloatTextureSupport(bool *filtering, bool *renderable);
     virtual bool getHalfFloatTextureSupport(bool *filtering, bool *renderable);
     virtual bool getLuminanceTextureSupport();
     virtual bool getLuminanceAlphaTextureSupport();
     virtual D3DPOOL getBufferPool(DWORD usage) const;
 
+    bool isD3d9exDevice() { return mD3d9ex != NULL; }
+
   private:
     DISALLOW_COPY_AND_ASSIGN(Display);
 
     D3DPRESENT_PARAMETERS getDefaultPresentParameters();
 
     const HDC mDc;
 
     HMODULE mD3d9Module;
diff --git a/gfx/angle/src/libEGL/Surface.cpp b/gfx/angle/src/libEGL/Surface.cpp
--- a/gfx/angle/src/libEGL/Surface.cpp
+++ b/gfx/angle/src/libEGL/Surface.cpp
@@ -20,27 +20,48 @@
 namespace egl
 {
 Surface::Surface(Display *display, const Config *config, HWND window) 
     : mDisplay(display), mConfig(config), mWindow(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;
     mSwapBehavior = EGL_BUFFER_PRESERVED;
     mSwapInterval = -1;
     setSwapInterval(1);
 
     subclassWindow();
     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();
     release();
 }
 
 void Surface::release()
 {
@@ -56,20 +77,31 @@ void Surface::release()
         mDepthStencil = NULL;
     }
 
     if (mRenderTarget)
     {
         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))
     {
         ASSERT(false);
 
         ERR("Could not retrieve the window dimensions");
         return;
     }
@@ -85,40 +117,52 @@ void Surface::resetSwapChain(int backbuf
     {
         return;
     }
 
     // Evict all non-render target textures to system memory and release all resources
     // before reallocating them to free up as much video memory as possible.
     device->EvictManagedResources();
     release();
-    
+
     D3DPRESENT_PARAMETERS presentParameters = {0};
+    HRESULT result;
 
     presentParameters.AutoDepthStencilFormat = mConfig->mDepthStencilFormat;
     presentParameters.BackBufferCount = 1;
     presentParameters.BackBufferFormat = mConfig->mRenderTargetFormat;
     presentParameters.EnableAutoDepthStencil = FALSE;
     presentParameters.Flags = 0;
     presentParameters.hDeviceWindow = getWindowHandle();
     presentParameters.MultiSampleQuality = 0;                  // FIXME: Unimplemented
     presentParameters.MultiSampleType = D3DMULTISAMPLE_NONE;   // FIXME: Unimplemented
     presentParameters.PresentationInterval = mPresentInterval;
     presentParameters.SwapEffect = D3DSWAPEFFECT_DISCARD;
     presentParameters.Windowed = TRUE;
     presentParameters.BackBufferWidth = backbufferWidth;
     presentParameters.BackBufferHeight = backbufferHeight;
 
-    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);
     }
 
     result = device->CreateDepthStencilSurface(presentParameters.BackBufferWidth, presentParameters.BackBufferHeight,
                                                presentParameters.AutoDepthStencilFormat, presentParameters.MultiSampleType,
                                                presentParameters.MultiSampleQuality, FALSE, &mDepthStencil, NULL);
 
@@ -126,23 +170,27 @@ void Surface::resetSwapChain(int backbuf
     {
         ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
 
         ERR("Could not create depthstencil surface for new swap chain: %08lX", result);
         release();
         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()
 {
     return mWindow;
 }
 
 
@@ -157,16 +205,19 @@ static LRESULT CALLBACK SurfaceWindowPro
       }
   }
   WNDPROC prevWndFunc = reinterpret_cast<WNDPROC >(GetProp(hwnd, kParentWndProc));
   return CallWindowProc(prevWndFunc, hwnd, message, wparam, lparam);
 }
 
 void Surface::subclassWindow()
 {
+  if (!mWindow)
+    return;
+
   SetLastError(0);
   LONG oldWndProc = SetWindowLong(mWindow, GWL_WNDPROC, reinterpret_cast<LONG>(SurfaceWindowProc));
   if(oldWndProc == 0 && GetLastError() != ERROR_SUCCESS) {
     mWindowSubclassed = false;
     return;
   }
 
   SetProp(mWindow, kSurfaceProperty, reinterpret_cast<HANDLE>(this));
diff --git a/gfx/angle/src/libEGL/Surface.h b/gfx/angle/src/libEGL/Surface.h
--- a/gfx/angle/src/libEGL/Surface.h
+++ b/gfx/angle/src/libEGL/Surface.h
@@ -21,41 +21,47 @@ namespace egl
 {
 class Display;
 class Config;
 
 class Surface
 {
   public:
     Surface(Display *display, const egl::Config *config, HWND window);
+    Surface(Display *display, const egl::Config *config, EGLint width, EGLint height);
 
     ~Surface();
 
     void release();
     void resetSwapChain();
 
     HWND getWindowHandle();
     bool swap();
 
     virtual EGLint getWidth() const;
     virtual EGLint getHeight() const;
 
     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
 
 private:
     DISALLOW_COPY_AND_ASSIGN(Surface);
 
     Display *const mDisplay;
     IDirect3DSwapChain9 *mSwapChain;
     IDirect3DSurface9 *mDepthStencil;
     IDirect3DSurface9* mRenderTarget;
+    IDirect3DTexture9* mOffscreenTexture;
+
+    HANDLE mShareHandle;
 
     void subclassWindow();
     void unsubclassWindow();
     void resetSwapChain(int backbufferWidth, int backbufferHeight);
     static DWORD convertInterval(EGLint interval);
 
     const HWND mWindow;            // Window that the surface is created for.
     bool mWindowSubclassed;        // Indicates whether we successfully subclassed mWindow for WM_RESIZE hooking
diff --git a/gfx/angle/src/libEGL/libEGL.cpp b/gfx/angle/src/libEGL/libEGL.cpp
--- a/gfx/angle/src/libEGL/libEGL.cpp
+++ b/gfx/angle/src/libEGL/libEGL.cpp
@@ -189,17 +189,17 @@ const char *__stdcall eglQueryString(EGL
             return NULL;
         }
 
         switch (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_share_handle");
           case EGL_VENDOR:
             return success("Google Inc.");
           case EGL_VERSION:
             return success("1.4 (ANGLE "VERSION_STRING")");
         }
 
         return error(EGL_BAD_PARAMETER, (const char*)NULL);
     }
@@ -386,25 +386,71 @@ EGLSurface __stdcall eglCreateWindowSurf
 EGLSurface __stdcall eglCreatePbufferSurface(EGLDisplay dpy, EGLConfig config, const EGLint *attrib_list)
 {
     EVENT("(EGLDisplay dpy = 0x%0.8p, EGLConfig config = 0x%0.8p, const EGLint *attrib_list = 0x%0.8p)",
           dpy, config, attrib_list);
 
     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&)
     {
         return error(EGL_BAD_ALLOC, EGL_NO_SURFACE);
     }
 
     return EGL_NO_SURFACE;
 }
@@ -420,17 +466,17 @@ EGLSurface __stdcall eglCreatePixmapSurf
 
         if (!validate(display, config))
         {
             return EGL_NO_SURFACE;
         }
 
         UNIMPLEMENTED();   // FIXME
 
-        return success(EGL_NO_DISPLAY);
+        return success(EGL_NO_SURFACE);
     }
     catch(std::bad_alloc&)
     {
         return error(EGL_BAD_ALLOC, EGL_NO_SURFACE);
     }
 
     return EGL_NO_SURFACE;
 }
@@ -545,16 +591,56 @@ EGLBoolean __stdcall eglQuerySurface(EGL
     catch(std::bad_alloc&)
     {
         return error(EGL_BAD_ALLOC, EGL_FALSE);
     }
 
     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_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);
 
     try
     {
         switch (api)
         {
@@ -694,19 +780,19 @@ EGLBoolean __stdcall eglBindTexImage(EGL
     {
         egl::Display *display = static_cast<egl::Display*>(dpy);
 
         if (!validate(display))
         {
             return EGL_FALSE;
         }
 
-        UNIMPLEMENTED();   // FIXME
+        // FIXME - need implementation
 
-        return success(EGL_TRUE);
+        return success(EGL_FALSE);
     }
     catch(std::bad_alloc&)
     {
         return error(EGL_BAD_ALLOC, EGL_FALSE);
     }
 
     return EGL_FALSE;
 }
@@ -719,19 +805,19 @@ EGLBoolean __stdcall eglReleaseTexImage(
     {
         egl::Display *display = static_cast<egl::Display*>(dpy);
 
         if (!validate(display))
         {
             return EGL_FALSE;
         }
 
-        UNIMPLEMENTED();   // FIXME
+        // FIXME - need implementation
 
-        return success(EGL_TRUE);
+        return success(EGL_FALSE);
     }
     catch(std::bad_alloc&)
     {
         return error(EGL_BAD_ALLOC, EGL_FALSE);
     }
 
     return EGL_FALSE;
 }
@@ -1088,16 +1174,17 @@ __eglMustCastToProperFunctionPointerType
         struct Extension
         {
             const char *name;
             __eglMustCastToProperFunctionPointerType address;
         };
 
         static const Extension eglExtensions[] =
         {
+            {"eglQuerySurfacePointerANGLE", (__eglMustCastToProperFunctionPointerType)eglQuerySurfacePointerANGLE},
             {"", NULL},
         };
 
         for (int ext = 0; ext < sizeof(eglExtensions) / sizeof(Extension); ext++)
         {
             if (strcmp(procname, eglExtensions[ext].name) == 0)
             {
                 return (__eglMustCastToProperFunctionPointerType)eglExtensions[ext].address;
diff --git a/gfx/angle/src/libEGL/main.h b/gfx/angle/src/libEGL/main.h
--- a/gfx/angle/src/libEGL/main.h
+++ b/gfx/angle/src/libEGL/main.h
@@ -6,16 +6,17 @@
 
 // main.h: Management of thread-local data.
 
 #ifndef LIBEGL_MAIN_H_
 #define LIBEGL_MAIN_H_
 
 #define EGLAPI
 #include <EGL/egl.h>
+#include <EGL/eglext.h>
 
 namespace egl
 {
 struct Current
 {
     EGLint error;
     EGLenum API;
     EGLDisplay display;
diff --git a/gfx/layers/d3d10/CanvasLayerD3D10.cpp b/gfx/layers/d3d10/CanvasLayerD3D10.cpp
--- a/gfx/layers/d3d10/CanvasLayerD3D10.cpp
+++ b/gfx/layers/d3d10/CanvasLayerD3D10.cpp
@@ -83,18 +83,22 @@ CanvasLayerD3D10::Initialize(const Data&
   }
 
   mIsD2DTexture = PR_FALSE;
   mUsingSharedTexture = PR_FALSE;
 
   HANDLE shareHandle = mGLContext ? mGLContext->GetD3DShareHandle() : nsnull;
   if (shareHandle) {
     HRESULT hr = device()->OpenSharedResource(shareHandle, __uuidof(ID3D10Texture2D), getter_AddRefs(mTexture));
-    if (SUCCEEDED(hr))
+    if (SUCCEEDED(hr)) {
       mUsingSharedTexture = PR_TRUE;
+      // XXX for ANGLE, it's already the right-way up.  If we start using NV GL-D3D interop
+      // however, we'll need to do the right thing.
+      mNeedsYFlip = PR_FALSE;
+    }
   }
 
   if (!mUsingSharedTexture) {
     CD3D10_TEXTURE2D_DESC desc(DXGI_FORMAT_B8G8R8A8_UNORM, mBounds.width, mBounds.height, 1, 1);
     desc.Usage = D3D10_USAGE_DYNAMIC;
     desc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE;
 
     HRESULT hr = device()->CreateTexture2D(&desc, NULL, getter_AddRefs(mTexture));
diff --git a/gfx/thebes/GLContextProviderEGL.cpp b/gfx/thebes/GLContextProviderEGL.cpp
--- a/gfx/thebes/GLContextProviderEGL.cpp
+++ b/gfx/thebes/GLContextProviderEGL.cpp
@@ -391,18 +391,18 @@ public:
             NS_WARNING("Couldn't find required entry points in EGL library (early init)");
             return PR_FALSE;
         }
 
         mEGLDisplay = fGetDisplay(EGL_DEFAULT_DISPLAY);
         if (!fInitialize(mEGLDisplay, NULL, NULL))
             return PR_FALSE;
 
-        const char *vendor = (const char*) fQueryString(mEGLDisplay, LOCAL_EGL_VENDOR);
-        if (vendor && strstr(vendor, "TransGaming") != 0) {
+        const char *version = (const char*) fQueryString(mEGLDisplay, LOCAL_EGL_VERSION);
+        if (version && strstr(version, "ANGLE") != 0) {
             mIsANGLE = PR_TRUE;
         }
         
         const char *extensions = (const char*) fQueryString(mEGLDisplay, LOCAL_EGL_EXTENSIONS);
         if (!extensions)
             extensions = "";
 
         printf_stderr("Extensions: %s 0x%02x\n", extensions, extensions[0]);