MANGLE egl::Display.

BUG=angle:794

Change-Id: Id131f3119100030d6ee630e357a8d28396a6a813
Reviewed-on: https://chromium-review.googlesource.com/231852
Tested-by: Jamie Madill <jmadill@chromium.org>
Reviewed-by: Geoff Lang <geofflang@chromium.org>
diff --git a/src/libANGLE/renderer/DisplayImpl.cpp b/src/libANGLE/renderer/DisplayImpl.cpp
new file mode 100644
index 0000000..8da133c
--- /dev/null
+++ b/src/libANGLE/renderer/DisplayImpl.cpp
@@ -0,0 +1,30 @@
+//
+// 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.
+//
+
+// DisplayImpl.cpp: Implementation methods of egl::Display
+
+#include "libANGLE/renderer/DisplayImpl.h"
+
+#include "libANGLE/Surface.h"
+
+namespace rx
+{
+
+DisplayImpl::~DisplayImpl()
+{
+    while (!mSurfaceSet.empty())
+    {
+        destroySurface(*mSurfaceSet.begin());
+    }
+}
+
+void DisplayImpl::destroySurface(egl::Surface *surface)
+{
+    mSurfaceSet.erase(surface);
+    SafeDelete(surface);
+}
+
+}
diff --git a/src/libANGLE/renderer/DisplayImpl.h b/src/libANGLE/renderer/DisplayImpl.h
new file mode 100644
index 0000000..34f6e50
--- /dev/null
+++ b/src/libANGLE/renderer/DisplayImpl.h
@@ -0,0 +1,59 @@
+//
+// 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.
+//
+
+// DisplayImpl.h: Implementation methods of egl::Display
+
+#ifndef LIBANGLE_RENDERER_DISPLAYIMPL_H_
+#define LIBANGLE_RENDERER_DISPLAYIMPL_H_
+
+#include "common/angleutils.h"
+#include "libANGLE/Error.h"
+
+#include <set>
+
+namespace egl
+{
+class Display;
+class Config;
+class Surface;
+}
+
+namespace rx
+{
+class SurfaceImpl;
+
+class DisplayImpl
+{
+  public:
+    DisplayImpl() {}
+    virtual ~DisplayImpl();
+
+    virtual SurfaceImpl *createWindowSurface(egl::Display *display, const egl::Config *config,
+                                             EGLNativeWindowType window, EGLint fixedSize,
+                                             EGLint width, EGLint height, EGLint postSubBufferSupported) = 0;
+    virtual SurfaceImpl *createOffscreenSurface(egl::Display *display, const egl::Config *config,
+                                                EGLClientBuffer shareHandle, EGLint width, EGLint height,
+                                                EGLenum textureFormat, EGLenum textureTarget) = 0;
+    virtual egl::Error restoreLostDevice() = 0;
+
+    typedef std::set<egl::Surface*> SurfaceSet;
+    const SurfaceSet &getSurfaceSet() const { return mSurfaceSet; }
+    SurfaceSet &getSurfaceSet() { return mSurfaceSet; }
+
+    void destroySurface(egl::Surface *surface);
+
+  protected:
+    // Place the surface set here so it can be accessible for handling
+    // context loss events. (It is shared between the Display and Impl.)
+    SurfaceSet mSurfaceSet;
+
+  private:
+    DISALLOW_COPY_AND_ASSIGN(DisplayImpl);
+};
+
+}
+
+#endif // LIBANGLE_RENDERER_DISPLAYIMPL_H_
diff --git a/src/libANGLE/renderer/Renderer.h b/src/libANGLE/renderer/Renderer.h
index 9d91914..ac16544 100644
--- a/src/libANGLE/renderer/Renderer.h
+++ b/src/libANGLE/renderer/Renderer.h
@@ -58,6 +58,7 @@
 struct TranslatedIndexData;
 struct Workarounds;
 class SwapChain;
+class DisplayImpl;
 
 struct ConfigDesc
 {
@@ -76,7 +77,6 @@
     virtual ~Renderer();
 
     virtual EGLint initialize() = 0;
-    virtual bool resetDevice() = 0;
 
     virtual int generateConfigs(ConfigDesc **configDescList) = 0;
     virtual void deleteConfigs(ConfigDesc *configDescList) = 0;
@@ -161,6 +161,8 @@
     virtual int getMinSwapInterval() const = 0;
     virtual int getMaxSwapInterval() const = 0;
 
+    virtual DisplayImpl *createDisplay() = 0;
+
   private:
     DISALLOW_COPY_AND_ASSIGN(Renderer);
 
diff --git a/src/libANGLE/renderer/d3d/DisplayD3D.cpp b/src/libANGLE/renderer/d3d/DisplayD3D.cpp
new file mode 100644
index 0000000..2c9866d
--- /dev/null
+++ b/src/libANGLE/renderer/d3d/DisplayD3D.cpp
@@ -0,0 +1,68 @@
+//
+// 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.
+//
+
+// DisplayD3D.cpp: D3D implementation of egl::Display
+
+#include "libANGLE/renderer/d3d/DisplayD3D.h"
+
+#include "libANGLE/Surface.h"
+#include "libANGLE/renderer/SwapChain.h"
+#include "libANGLE/renderer/d3d/RendererD3D.h"
+#include "libANGLE/renderer/d3d/SurfaceD3D.h"
+
+namespace rx
+{
+
+SurfaceImpl *DisplayD3D::createWindowSurface(egl::Display *display, const egl::Config *config,
+                                             EGLNativeWindowType window, EGLint fixedSize,
+                                             EGLint width, EGLint height, EGLint postSubBufferSupported)
+{
+    return SurfaceD3D::createFromWindow(display, config, window, fixedSize,
+                                        width, height, postSubBufferSupported);
+}
+
+SurfaceImpl *DisplayD3D::createOffscreenSurface(egl::Display *display, const egl::Config *config,
+                                                EGLClientBuffer shareHandle, EGLint width, EGLint height,
+                                                EGLenum textureFormat, EGLenum textureTarget)
+{
+    return SurfaceD3D::createOffscreen(display, config, shareHandle,
+                                       width, height, textureFormat, textureTarget);
+}
+
+egl::Error DisplayD3D::restoreLostDevice()
+{
+    // Release surface resources to make the Reset() succeed
+    for (auto &surface : mSurfaceSet)
+    {
+        if (surface->getBoundTexture())
+        {
+            surface->releaseTexImage(EGL_BACK_BUFFER);
+        }
+        SurfaceD3D *surfaceD3D = SurfaceD3D::makeSurfaceD3D(surface);
+        surfaceD3D->releaseSwapChain();
+    }
+
+    if (!mRenderer->resetDevice())
+    {
+        return egl::Error(EGL_BAD_ALLOC);
+    }
+
+    // Restore any surfaces that may have been lost
+    for (const auto &surface : mSurfaceSet)
+    {
+        SurfaceD3D *surfaceD3D = SurfaceD3D::makeSurfaceD3D(surface);
+
+        egl::Error error = surfaceD3D->resetSwapChain();
+        if (error.isError())
+        {
+            return error;
+        }
+    }
+
+    return egl::Error(EGL_SUCCESS);
+}
+
+}
diff --git a/src/libANGLE/renderer/d3d/DisplayD3D.h b/src/libANGLE/renderer/d3d/DisplayD3D.h
new file mode 100644
index 0000000..7716d56
--- /dev/null
+++ b/src/libANGLE/renderer/d3d/DisplayD3D.h
@@ -0,0 +1,38 @@
+//
+// 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.
+//
+
+// DisplayD3D.h: D3D implementation of egl::Display
+
+#ifndef LIBANGLE_RENDERER_D3D_DISPLAYD3D_H_
+#define LIBANGLE_RENDERER_D3D_DISPLAYD3D_H_
+
+#include "libANGLE/renderer/DisplayImpl.h"
+
+namespace rx
+{
+class RendererD3D;
+
+class DisplayD3D : public DisplayImpl
+{
+  public:
+    DisplayD3D(rx::RendererD3D *renderer) {}
+    SurfaceImpl *createWindowSurface(egl::Display *display, const egl::Config *config,
+                                     EGLNativeWindowType window, EGLint fixedSize,
+                                     EGLint width, EGLint height, EGLint postSubBufferSupported) override;
+    SurfaceImpl *createOffscreenSurface(egl::Display *display, const egl::Config *config,
+                                        EGLClientBuffer shareHandle, EGLint width, EGLint height,
+                                        EGLenum textureFormat, EGLenum textureTarget) override;
+    egl::Error restoreLostDevice() override;
+
+  private:
+    DISALLOW_COPY_AND_ASSIGN(DisplayD3D);
+
+    rx::RendererD3D *mRenderer;
+};
+
+}
+
+#endif // LIBANGLE_RENDERER_D3D_DISPLAYD3D_H_
diff --git a/src/libANGLE/renderer/d3d/RendererD3D.cpp b/src/libANGLE/renderer/d3d/RendererD3D.cpp
index 8312b8a..d5d729b 100644
--- a/src/libANGLE/renderer/d3d/RendererD3D.cpp
+++ b/src/libANGLE/renderer/d3d/RendererD3D.cpp
@@ -16,6 +16,7 @@
 #include "libANGLE/State.h"
 #include "libANGLE/VertexArray.h"
 #include "libANGLE/formatutils.h"
+#include "libANGLE/renderer/d3d/DisplayD3D.h"
 #include "libANGLE/renderer/d3d/IndexDataManager.h"
 
 namespace rx
@@ -824,4 +825,9 @@
     return std::string("");
 }
 
+DisplayImpl *RendererD3D::createDisplay()
+{
+    return new DisplayD3D(this);
+}
+
 }
diff --git a/src/libANGLE/renderer/d3d/RendererD3D.h b/src/libANGLE/renderer/d3d/RendererD3D.h
index 6df0487..d0b6ba9 100644
--- a/src/libANGLE/renderer/d3d/RendererD3D.h
+++ b/src/libANGLE/renderer/d3d/RendererD3D.h
@@ -69,6 +69,8 @@
     bool isDeviceLost() const override;
     std::string getVendorString() const override;
 
+    DisplayImpl *createDisplay() override;
+
     // Direct3D Specific methods
     virtual GUID getAdapterIdentifier() const = 0;
 
@@ -155,7 +157,9 @@
     virtual VertexBuffer *createVertexBuffer() = 0;
     virtual IndexBuffer *createIndexBuffer() = 0;
 
+    // Device lost
     void notifyDeviceLost() override;
+    virtual bool resetDevice() = 0;
 
   protected:
     virtual gl::Error drawArrays(GLenum mode, GLsizei count, GLsizei instances, bool transformFeedbackActive) = 0;