summaryrefslogtreecommitdiffstats
path: root/gfx/angle/src/libANGLE/renderer/gl/egl
diff options
context:
space:
mode:
Diffstat (limited to 'gfx/angle/src/libANGLE/renderer/gl/egl')
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/gl/egl/DisplayEGL.cpp116
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/gl/egl/DisplayEGL.h43
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/gl/egl/FunctionsEGL.cpp340
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/gl/egl/FunctionsEGL.h91
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/gl/egl/FunctionsEGLDL.cpp74
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/gl/egl/FunctionsEGLDL.h42
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/gl/egl/PbufferSurfaceEGL.cpp39
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/gl/egl/PbufferSurfaceEGL.h36
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/gl/egl/SurfaceEGL.cpp132
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/gl/egl/SurfaceEGL.h55
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/gl/egl/WindowSurfaceEGL.cpp40
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/gl/egl/WindowSurfaceEGL.h37
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/gl/egl/android/DisplayAndroid.cpp385
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/gl/egl/android/DisplayAndroid.h78
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/gl/egl/functionsegl_typedefs.h131
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/gl/egl/ozone/DisplayOzone.cpp945
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/gl/egl/ozone/DisplayOzone.h211
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/gl/egl/ozone/SurfaceOzone.cpp98
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/gl/egl/ozone/SurfaceOzone.h52
19 files changed, 2945 insertions, 0 deletions
diff --git a/gfx/angle/src/libANGLE/renderer/gl/egl/DisplayEGL.cpp b/gfx/angle/src/libANGLE/renderer/gl/egl/DisplayEGL.cpp
new file mode 100755
index 000000000..988b233b4
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/gl/egl/DisplayEGL.cpp
@@ -0,0 +1,116 @@
+//
+// Copyright (c) 2016 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.
+//
+
+// DisplayEGL.cpp: Common across EGL parts of platform specific egl::Display implementations
+
+#include "libANGLE/renderer/gl/egl/DisplayEGL.h"
+
+namespace rx
+{
+
+#define EGL_NO_CONFIG ((EGLConfig)0)
+
+DisplayEGL::DisplayEGL()
+ : DisplayGL(),
+ mEGL(nullptr),
+ mConfig(EGL_NO_CONFIG),
+ mContext(EGL_NO_CONTEXT),
+ mFunctionsGL(nullptr)
+{
+}
+
+DisplayEGL::~DisplayEGL()
+{
+}
+
+std::string DisplayEGL::getVendorString() const
+{
+ const char *vendor = mEGL->queryString(EGL_VENDOR);
+ ASSERT(vendor);
+ return vendor;
+}
+
+egl::Error DisplayEGL::initializeContext(const egl::AttributeMap &eglAttributes)
+{
+ gl::Version eglVersion(mEGL->majorVersion, mEGL->minorVersion);
+
+ EGLint requestedMajor =
+ eglAttributes.getAsInt(EGL_PLATFORM_ANGLE_MAX_VERSION_MAJOR_ANGLE, EGL_DONT_CARE);
+ EGLint requestedMinor =
+ eglAttributes.getAsInt(EGL_PLATFORM_ANGLE_MAX_VERSION_MINOR_ANGLE, EGL_DONT_CARE);
+ bool initializeRequested = requestedMajor != EGL_DONT_CARE && requestedMinor != EGL_DONT_CARE;
+
+ static_assert(EGL_CONTEXT_MAJOR_VERSION == EGL_CONTEXT_MAJOR_VERSION_KHR,
+ "Major Version define should match");
+ static_assert(EGL_CONTEXT_MINOR_VERSION == EGL_CONTEXT_MINOR_VERSION_KHR,
+ "Minor Version define should match");
+
+ std::vector<std::vector<EGLint>> contextAttribLists;
+ if (eglVersion >= gl::Version(1, 5) || mEGL->hasExtension("EGL_KHR_create_context"))
+ {
+ if (initializeRequested)
+ {
+ contextAttribLists.push_back({EGL_CONTEXT_MAJOR_VERSION, requestedMajor,
+ EGL_CONTEXT_MINOR_VERSION, requestedMinor, EGL_NONE});
+ }
+ else
+ {
+ // clang-format off
+ const gl::Version esVersionsFrom2_0[] = {
+ gl::Version(3, 2),
+ gl::Version(3, 1),
+ gl::Version(3, 0),
+ gl::Version(2, 0),
+ };
+ // clang-format on
+
+ for (const auto &version : esVersionsFrom2_0)
+ {
+ contextAttribLists.push_back(
+ {EGL_CONTEXT_MAJOR_VERSION, static_cast<EGLint>(version.major),
+ EGL_CONTEXT_MINOR_VERSION, static_cast<EGLint>(version.minor), EGL_NONE});
+ }
+ }
+ }
+ else
+ {
+ if (initializeRequested && (requestedMajor != 2 || requestedMinor != 0))
+ {
+ return egl::Error(EGL_BAD_ATTRIBUTE, "Unsupported requested context version");
+ }
+ contextAttribLists.push_back({EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE});
+ }
+
+ for (auto &attribList : contextAttribLists)
+ {
+ mContext = mEGL->createContext(mConfig, EGL_NO_CONTEXT, attribList.data());
+ if (mContext != EGL_NO_CONTEXT)
+ {
+ return egl::Error(EGL_SUCCESS);
+ }
+ }
+
+ return egl::Error(mEGL->getError(), "eglCreateContext failed");
+}
+
+void DisplayEGL::generateExtensions(egl::DisplayExtensions *outExtensions) const
+{
+ outExtensions->createContextRobustness =
+ mEGL->hasExtension("EGL_EXT_create_context_robustness");
+
+ outExtensions->postSubBuffer = false; // Since SurfaceEGL::postSubBuffer is not implemented
+}
+
+void DisplayEGL::generateCaps(egl::Caps *outCaps) const
+{
+ outCaps->textureNPOT = true; // Since we request GLES >= 2
+}
+
+const FunctionsGL *DisplayEGL::getFunctionsGL() const
+{
+ return mFunctionsGL;
+}
+} // namespace rx
diff --git a/gfx/angle/src/libANGLE/renderer/gl/egl/DisplayEGL.h b/gfx/angle/src/libANGLE/renderer/gl/egl/DisplayEGL.h
new file mode 100755
index 000000000..e498cd79a
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/gl/egl/DisplayEGL.h
@@ -0,0 +1,43 @@
+//
+// Copyright (c) 2016 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.
+//
+
+// DisplayEGL.h: Common across EGL parts of platform specific egl::Display implementations
+
+#ifndef LIBANGLE_RENDERER_GL_EGL_DISPLAYEGL_H_
+#define LIBANGLE_RENDERER_GL_EGL_DISPLAYEGL_H_
+
+#include "libANGLE/renderer/gl/DisplayGL.h"
+#include "libANGLE/renderer/gl/egl/FunctionsEGL.h"
+
+namespace rx
+{
+
+class DisplayEGL : public DisplayGL
+{
+ public:
+ DisplayEGL();
+ ~DisplayEGL() override;
+
+ std::string getVendorString() const override;
+
+ protected:
+ egl::Error initializeContext(const egl::AttributeMap &eglAttributes);
+
+ FunctionsEGL *mEGL;
+ EGLConfig mConfig;
+ EGLContext mContext;
+ FunctionsGL *mFunctionsGL;
+
+ private:
+ void generateExtensions(egl::DisplayExtensions *outExtensions) const override;
+ void generateCaps(egl::Caps *outCaps) const override;
+
+ const FunctionsGL *getFunctionsGL() const override;
+};
+
+} // namespace rx
+
+#endif /* LIBANGLE_RENDERER_GL_EGL_DISPLAYEGL_H_ */
diff --git a/gfx/angle/src/libANGLE/renderer/gl/egl/FunctionsEGL.cpp b/gfx/angle/src/libANGLE/renderer/gl/egl/FunctionsEGL.cpp
new file mode 100755
index 000000000..c0b0f846f
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/gl/egl/FunctionsEGL.cpp
@@ -0,0 +1,340 @@
+//
+// Copyright (c) 2016 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.
+//
+
+// FunctionsEGL.cpp: Implements the FunctionsEGL class.
+
+#include "libANGLE/renderer/gl/egl/FunctionsEGL.h"
+
+#include <algorithm>
+
+#include "libANGLE/renderer/gl/FunctionsGL.h"
+#include "libANGLE/renderer/gl/egl/functionsegl_typedefs.h"
+#include "common/string_utils.h"
+
+namespace
+{
+
+template <typename T>
+bool SetPtr(T *dst, void *src)
+{
+ if (src)
+ {
+ *dst = reinterpret_cast<T>(src);
+ return true;
+ }
+ return false;
+}
+} // namespace
+
+namespace rx
+{
+
+struct FunctionsEGL::EGLDispatchTable
+{
+ EGLDispatchTable()
+ : bindAPIPtr(nullptr),
+ chooseConfigPtr(nullptr),
+ createContextPtr(nullptr),
+ createPbufferSurfacePtr(nullptr),
+ createWindowSurfacePtr(nullptr),
+ destroyContextPtr(nullptr),
+ destroySurfacePtr(nullptr),
+ getConfigAttribPtr(nullptr),
+ getDisplayPtr(nullptr),
+ getErrorPtr(nullptr),
+ initializePtr(nullptr),
+ makeCurrentPtr(nullptr),
+ queryStringPtr(nullptr),
+ querySurfacePtr(nullptr),
+ swapBuffersPtr(nullptr),
+ terminatePtr(nullptr),
+
+ bindTexImagePtr(nullptr),
+ releaseTexImagePtr(nullptr),
+ swapIntervalPtr(nullptr),
+
+ createImageKHRPtr(nullptr),
+ destroyImageKHRPtr(nullptr),
+
+ clientWaitSyncKHRPtr(nullptr),
+ createSyncKHRPtr(nullptr),
+ destroySyncKHRPtr(nullptr),
+ getSyncAttribKHRPtr(nullptr)
+ {
+ }
+
+ // 1.0
+ PFNEGLBINDAPIPROC bindAPIPtr;
+ PFNEGLCHOOSECONFIGPROC chooseConfigPtr;
+ PFNEGLCREATECONTEXTPROC createContextPtr;
+ PFNEGLCREATEPBUFFERSURFACEPROC createPbufferSurfacePtr;
+ PFNEGLCREATEWINDOWSURFACEPROC createWindowSurfacePtr;
+ PFNEGLDESTROYCONTEXTPROC destroyContextPtr;
+ PFNEGLDESTROYSURFACEPROC destroySurfacePtr;
+ PFNEGLGETCONFIGATTRIBPROC getConfigAttribPtr;
+ PFNEGLGETDISPLAYPROC getDisplayPtr;
+ PFNEGLGETERRORPROC getErrorPtr;
+ PFNEGLINITIALIZEPROC initializePtr;
+ PFNEGLMAKECURRENTPROC makeCurrentPtr;
+ PFNEGLQUERYSTRINGPROC queryStringPtr;
+ PFNEGLQUERYSURFACEPROC querySurfacePtr;
+ PFNEGLSWAPBUFFERSPROC swapBuffersPtr;
+ PFNEGLTERMINATEPROC terminatePtr;
+
+ // 1.1
+ PFNEGLBINDTEXIMAGEPROC bindTexImagePtr;
+ PFNEGLRELEASETEXIMAGEPROC releaseTexImagePtr;
+ PFNEGLSWAPINTERVALPROC swapIntervalPtr;
+
+ // EGL_KHR_image
+ PFNEGLCREATEIMAGEKHRPROC createImageKHRPtr;
+ PFNEGLDESTROYIMAGEKHRPROC destroyImageKHRPtr;
+
+ // EGL_KHR_fence_sync
+ PFNEGLCLIENTWAITSYNCKHRPROC clientWaitSyncKHRPtr;
+ PFNEGLCREATESYNCKHRPROC createSyncKHRPtr;
+ PFNEGLDESTROYSYNCKHRPROC destroySyncKHRPtr;
+ PFNEGLGETSYNCATTRIBKHRPROC getSyncAttribKHRPtr;
+};
+
+FunctionsEGL::FunctionsEGL()
+ : majorVersion(0), minorVersion(0), mFnPtrs(new EGLDispatchTable()), mEGLDisplay(EGL_NO_DISPLAY)
+{
+}
+
+FunctionsEGL::~FunctionsEGL()
+{
+ SafeDelete(mFnPtrs);
+}
+
+egl::Error FunctionsEGL::initialize(EGLNativeDisplayType nativeDisplay)
+{
+#define ANGLE_GET_PROC_OR_ERROR(MEMBER, NAME) \
+ if (!SetPtr(MEMBER, getProcAddress(#NAME))) \
+ { \
+ return egl::Error(EGL_NOT_INITIALIZED, "Could not load EGL entry point " #NAME); \
+ }
+
+ ANGLE_GET_PROC_OR_ERROR(&mFnPtrs->bindAPIPtr, eglBindAPI);
+ ANGLE_GET_PROC_OR_ERROR(&mFnPtrs->chooseConfigPtr, eglChooseConfig);
+ ANGLE_GET_PROC_OR_ERROR(&mFnPtrs->createContextPtr, eglCreateContext);
+ ANGLE_GET_PROC_OR_ERROR(&mFnPtrs->createPbufferSurfacePtr, eglCreatePbufferSurface);
+ ANGLE_GET_PROC_OR_ERROR(&mFnPtrs->createWindowSurfacePtr, eglCreateWindowSurface);
+ ANGLE_GET_PROC_OR_ERROR(&mFnPtrs->destroyContextPtr, eglDestroyContext);
+ ANGLE_GET_PROC_OR_ERROR(&mFnPtrs->destroySurfacePtr, eglDestroySurface);
+ ANGLE_GET_PROC_OR_ERROR(&mFnPtrs->getConfigAttribPtr, eglGetConfigAttrib);
+ ANGLE_GET_PROC_OR_ERROR(&mFnPtrs->getDisplayPtr, eglGetDisplay);
+ ANGLE_GET_PROC_OR_ERROR(&mFnPtrs->getErrorPtr, eglGetError);
+ ANGLE_GET_PROC_OR_ERROR(&mFnPtrs->initializePtr, eglInitialize);
+ ANGLE_GET_PROC_OR_ERROR(&mFnPtrs->makeCurrentPtr, eglMakeCurrent);
+ ANGLE_GET_PROC_OR_ERROR(&mFnPtrs->queryStringPtr, eglQueryString);
+ ANGLE_GET_PROC_OR_ERROR(&mFnPtrs->querySurfacePtr, eglQuerySurface);
+ ANGLE_GET_PROC_OR_ERROR(&mFnPtrs->swapBuffersPtr, eglSwapBuffers);
+ ANGLE_GET_PROC_OR_ERROR(&mFnPtrs->terminatePtr, eglTerminate);
+
+ ANGLE_GET_PROC_OR_ERROR(&mFnPtrs->bindTexImagePtr, eglBindTexImage);
+ ANGLE_GET_PROC_OR_ERROR(&mFnPtrs->releaseTexImagePtr, eglReleaseTexImage);
+ ANGLE_GET_PROC_OR_ERROR(&mFnPtrs->swapIntervalPtr, eglSwapInterval);
+
+ mEGLDisplay = mFnPtrs->getDisplayPtr(nativeDisplay);
+ if (mEGLDisplay == EGL_NO_DISPLAY)
+ {
+ return egl::Error(EGL_NOT_INITIALIZED, "Failed to get system egl display");
+ }
+ if (mFnPtrs->initializePtr(mEGLDisplay, &majorVersion, &minorVersion) != EGL_TRUE)
+ {
+ return egl::Error(mFnPtrs->getErrorPtr(), "Failed to initialize system egl");
+ }
+ if (majorVersion < 1 || (majorVersion == 1 && minorVersion < 4))
+ {
+ return egl::Error(EGL_NOT_INITIALIZED, "Unsupported EGL version (require at least 1.4).");
+ }
+ if (mFnPtrs->bindAPIPtr(EGL_OPENGL_ES_API) != EGL_TRUE)
+ {
+ return egl::Error(mFnPtrs->getErrorPtr(), "Failed to bind API in system egl");
+ }
+
+ const char *extensions = queryString(EGL_EXTENSIONS);
+ if (!extensions)
+ {
+ return egl::Error(mFnPtrs->getErrorPtr(), "Faild to query extensions in system egl");
+ }
+ angle::SplitStringAlongWhitespace(extensions, &mExtensions);
+
+ if (hasExtension("EGL_KHR_image_base"))
+ {
+ ANGLE_GET_PROC_OR_ERROR(&mFnPtrs->createImageKHRPtr, eglCreateImageKHR);
+ ANGLE_GET_PROC_OR_ERROR(&mFnPtrs->destroyImageKHRPtr, eglDestroyImageKHR);
+ }
+ if (hasExtension("EGL_KHR_fence_sync"))
+ {
+ ANGLE_GET_PROC_OR_ERROR(&mFnPtrs->clientWaitSyncKHRPtr, eglClientWaitSyncKHR);
+ ANGLE_GET_PROC_OR_ERROR(&mFnPtrs->createSyncKHRPtr, eglCreateSyncKHR);
+ ANGLE_GET_PROC_OR_ERROR(&mFnPtrs->destroySyncKHRPtr, eglDestroySyncKHR);
+ ANGLE_GET_PROC_OR_ERROR(&mFnPtrs->getSyncAttribKHRPtr, eglGetSyncAttribKHR);
+ }
+
+#undef ANGLE_GET_PROC_OR_ERROR
+
+ return egl::Error(EGL_SUCCESS);
+}
+
+egl::Error FunctionsEGL::terminate()
+{
+ if (mFnPtrs->terminatePtr(mEGLDisplay) == EGL_TRUE)
+ {
+ mEGLDisplay = nullptr;
+ return egl::Error(EGL_SUCCESS);
+ }
+ return egl::Error(mFnPtrs->getErrorPtr());
+}
+
+class FunctionsGLEGL : public FunctionsGL
+{
+ public:
+ FunctionsGLEGL(const FunctionsEGL &egl) : mEGL(egl) {}
+
+ ~FunctionsGLEGL() override {}
+
+ private:
+ void *loadProcAddress(const std::string &function) override
+ {
+ return mEGL.getProcAddress(function.c_str());
+ }
+
+ const FunctionsEGL &mEGL;
+};
+
+FunctionsGL *FunctionsEGL::makeFunctionsGL(void) const
+{
+ return new FunctionsGLEGL(*this);
+}
+
+bool FunctionsEGL::hasExtension(const char *extension) const
+{
+ return std::find(mExtensions.begin(), mExtensions.end(), extension) != mExtensions.end();
+}
+
+EGLDisplay FunctionsEGL::getDisplay() const
+{
+ return mEGLDisplay;
+}
+
+EGLint FunctionsEGL::getError() const
+{
+ return mFnPtrs->getErrorPtr();
+}
+
+EGLBoolean FunctionsEGL::chooseConfig(EGLint const *attribList,
+ EGLConfig *configs,
+ EGLint configSize,
+ EGLint *numConfig) const
+{
+ return mFnPtrs->chooseConfigPtr(mEGLDisplay, attribList, configs, configSize, numConfig);
+}
+
+EGLBoolean FunctionsEGL::getConfigAttrib(EGLConfig config, EGLint attribute, EGLint *value) const
+{
+ return mFnPtrs->getConfigAttribPtr(mEGLDisplay, config, attribute, value);
+}
+
+EGLContext FunctionsEGL::createContext(EGLConfig config,
+ EGLContext share_context,
+ EGLint const *attrib_list) const
+{
+ return mFnPtrs->createContextPtr(mEGLDisplay, config, share_context, attrib_list);
+}
+
+EGLSurface FunctionsEGL::createPbufferSurface(EGLConfig config, const EGLint *attrib_list) const
+{
+ return mFnPtrs->createPbufferSurfacePtr(mEGLDisplay, config, attrib_list);
+}
+
+EGLSurface FunctionsEGL::createWindowSurface(EGLConfig config,
+ EGLNativeWindowType win,
+ const EGLint *attrib_list) const
+{
+ return mFnPtrs->createWindowSurfacePtr(mEGLDisplay, config, win, attrib_list);
+}
+
+EGLBoolean FunctionsEGL::destroyContext(EGLContext context) const
+{
+ return mFnPtrs->destroyContextPtr(mEGLDisplay, context);
+}
+
+EGLBoolean FunctionsEGL::destroySurface(EGLSurface surface) const
+{
+ return mFnPtrs->destroySurfacePtr(mEGLDisplay, surface);
+}
+
+EGLBoolean FunctionsEGL::makeCurrent(EGLSurface surface, EGLContext context) const
+{
+ return mFnPtrs->makeCurrentPtr(mEGLDisplay, surface, surface, context);
+}
+
+char const *FunctionsEGL::queryString(EGLint name) const
+{
+ return mFnPtrs->queryStringPtr(mEGLDisplay, name);
+}
+
+EGLBoolean FunctionsEGL::querySurface(EGLSurface surface, EGLint attribute, EGLint *value) const
+{
+ return mFnPtrs->querySurfacePtr(mEGLDisplay, surface, attribute, value);
+}
+
+EGLBoolean FunctionsEGL::swapBuffers(EGLSurface surface) const
+{
+ return mFnPtrs->swapBuffersPtr(mEGLDisplay, surface);
+}
+
+EGLBoolean FunctionsEGL::bindTexImage(EGLSurface surface, EGLint buffer) const
+{
+ return mFnPtrs->bindTexImagePtr(mEGLDisplay, surface, buffer);
+}
+
+EGLBoolean FunctionsEGL::releaseTexImage(EGLSurface surface, EGLint buffer) const
+{
+ return mFnPtrs->releaseTexImagePtr(mEGLDisplay, surface, buffer);
+}
+
+EGLBoolean FunctionsEGL::swapInterval(EGLint interval) const
+{
+ return mFnPtrs->swapIntervalPtr(mEGLDisplay, interval);
+}
+
+EGLImageKHR FunctionsEGL::createImageKHR(EGLContext context,
+ EGLenum target,
+ EGLClientBuffer buffer,
+ const EGLint *attrib_list) const
+{
+ return mFnPtrs->createImageKHRPtr(mEGLDisplay, context, target, buffer, attrib_list);
+}
+
+EGLBoolean FunctionsEGL::destroyImageKHR(EGLImageKHR image) const
+{
+ return mFnPtrs->destroyImageKHRPtr(mEGLDisplay, image);
+}
+
+EGLSyncKHR FunctionsEGL::createSyncKHR(EGLenum type, const EGLint *attrib_list)
+{
+ return mFnPtrs->createSyncKHRPtr(mEGLDisplay, type, attrib_list);
+}
+
+EGLBoolean FunctionsEGL::destroySyncKHR(EGLSyncKHR sync)
+{
+ return mFnPtrs->destroySyncKHRPtr(mEGLDisplay, sync);
+}
+
+EGLint FunctionsEGL::clientWaitSyncKHR(EGLSyncKHR sync, EGLint flags, EGLTimeKHR timeout)
+{
+ return mFnPtrs->clientWaitSyncKHRPtr(mEGLDisplay, sync, flags, timeout);
+}
+
+EGLBoolean FunctionsEGL::getSyncAttribKHR(EGLSyncKHR sync, EGLint attribute, EGLint *value)
+{
+ return mFnPtrs->getSyncAttribKHRPtr(mEGLDisplay, sync, attribute, value);
+}
+} // namespace rx
diff --git a/gfx/angle/src/libANGLE/renderer/gl/egl/FunctionsEGL.h b/gfx/angle/src/libANGLE/renderer/gl/egl/FunctionsEGL.h
new file mode 100755
index 000000000..43d5622e6
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/gl/egl/FunctionsEGL.h
@@ -0,0 +1,91 @@
+//
+// Copyright (c) 2016 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.
+//
+
+// FunctionsEGL.h: Defines the FunctionsEGL class to load functions and data from EGL
+
+#ifndef LIBANGLE_RENDERER_GL_CROS_FUNCTIONSEGL_H_
+#define LIBANGLE_RENDERER_GL_CROS_FUNCTIONSEGL_H_
+
+#include <EGL/egl.h>
+#include <EGL/eglext.h>
+
+#include <string>
+#include <vector>
+
+#include "libANGLE/Error.h"
+
+namespace rx
+{
+
+class FunctionsGL;
+
+class FunctionsEGL
+{
+ public:
+ FunctionsEGL();
+ virtual ~FunctionsEGL();
+
+ int majorVersion;
+ int minorVersion;
+
+ egl::Error initialize(EGLNativeDisplayType nativeDisplay);
+ egl::Error terminate();
+
+ virtual void *getProcAddress(const char *name) const = 0;
+
+ FunctionsGL *makeFunctionsGL() const;
+ bool hasExtension(const char *extension) const;
+ EGLDisplay getDisplay() const;
+ EGLint getError() const;
+
+ EGLBoolean chooseConfig(EGLint const *attrib_list,
+ EGLConfig *configs,
+ EGLint config_size,
+ EGLint *num_config) const;
+ EGLBoolean getConfigAttrib(EGLConfig config, EGLint attribute, EGLint *value) const;
+ EGLContext createContext(EGLConfig config,
+ EGLContext share_context,
+ EGLint const *attrib_list) const;
+ EGLSurface createPbufferSurface(EGLConfig config, const EGLint *attrib_list) const;
+ EGLSurface createWindowSurface(EGLConfig config,
+ EGLNativeWindowType win,
+ const EGLint *attrib_list) const;
+ EGLBoolean destroyContext(EGLContext context) const;
+ EGLBoolean destroySurface(EGLSurface surface) const;
+ EGLBoolean makeCurrent(EGLSurface surface, EGLContext context) const;
+ const char *queryString(EGLint name) const;
+ EGLBoolean querySurface(EGLSurface surface, EGLint attribute, EGLint *value) const;
+ EGLBoolean swapBuffers(EGLSurface surface) const;
+
+ EGLBoolean bindTexImage(EGLSurface surface, EGLint buffer) const;
+ EGLBoolean releaseTexImage(EGLSurface surface, EGLint buffer) const;
+ EGLBoolean swapInterval(EGLint interval) const;
+
+ EGLImageKHR createImageKHR(EGLContext context,
+ EGLenum target,
+ EGLClientBuffer buffer,
+ const EGLint *attrib_list) const;
+ EGLBoolean destroyImageKHR(EGLImageKHR image) const;
+
+ EGLSyncKHR createSyncKHR(EGLenum type, const EGLint *attrib_list);
+ EGLBoolean destroySyncKHR(EGLSyncKHR sync);
+ EGLint clientWaitSyncKHR(EGLSyncKHR sync, EGLint flags, EGLTimeKHR timeout);
+ EGLBoolean getSyncAttribKHR(EGLSyncKHR sync, EGLint attribute, EGLint *value);
+
+ private:
+ // So as to isolate from angle we do not include angleutils.h and cannot
+ // use angle::NonCopyable so we replicated it here instead.
+ FunctionsEGL(const FunctionsEGL &) = delete;
+ void operator=(const FunctionsEGL &) = delete;
+
+ struct EGLDispatchTable;
+ EGLDispatchTable *mFnPtrs;
+ EGLDisplay mEGLDisplay;
+ std::vector<std::string> mExtensions;
+};
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_GL_CROS_FUNCTIONSEGL_H_
diff --git a/gfx/angle/src/libANGLE/renderer/gl/egl/FunctionsEGLDL.cpp b/gfx/angle/src/libANGLE/renderer/gl/egl/FunctionsEGLDL.cpp
new file mode 100755
index 000000000..e6ef45d8d
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/gl/egl/FunctionsEGLDL.cpp
@@ -0,0 +1,74 @@
+//
+// Copyright (c) 2016 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.
+//
+
+// FunctionsEGLDL.cpp: Implements the FunctionsEGLDL class.
+
+#include "libANGLE/renderer/gl/egl/FunctionsEGLDL.h"
+
+#include <dlfcn.h>
+
+namespace rx
+{
+
+DynamicLib::DynamicLib() : handle(nullptr)
+{
+}
+
+DynamicLib::~DynamicLib()
+{
+ if (handle)
+ {
+ dlclose(handle);
+ handle = nullptr;
+ }
+}
+
+// Due to a bug in Mesa (or maybe libdl) it's not possible to close and re-open libEGL.so
+// an arbitrary number of times. End2end tests would die after a couple hundred tests.
+// So we use a static object with a destructor to close the library when the program exits.
+// TODO(fjhenigman) File a bug and put a link here.
+DynamicLib FunctionsEGLDL::sNativeLib;
+
+FunctionsEGLDL::FunctionsEGLDL() : mGetProcAddressPtr(nullptr)
+{
+}
+
+FunctionsEGLDL::~FunctionsEGLDL()
+{
+}
+
+egl::Error FunctionsEGLDL::initialize(EGLNativeDisplayType nativeDisplay, const char *libName)
+{
+ if (!sNativeLib.handle)
+ {
+ sNativeLib.handle = dlopen(libName, RTLD_NOW);
+ if (!sNativeLib.handle)
+ {
+ return egl::Error(EGL_NOT_INITIALIZED, "Could not dlopen native EGL: %s", dlerror());
+ }
+ }
+
+ mGetProcAddressPtr =
+ reinterpret_cast<PFNEGLGETPROCADDRESSPROC>(dlsym(sNativeLib.handle, "eglGetProcAddress"));
+ if (!mGetProcAddressPtr)
+ {
+ return egl::Error(EGL_NOT_INITIALIZED, "Could not find eglGetProcAddress");
+ }
+
+ return FunctionsEGL::initialize(nativeDisplay);
+}
+
+void *FunctionsEGLDL::getProcAddress(const char *name) const
+{
+ void *f = reinterpret_cast<void *>(mGetProcAddressPtr(name));
+ if (f)
+ {
+ return f;
+ }
+ return dlsym(sNativeLib.handle, name);
+}
+
+} // namespace rx
diff --git a/gfx/angle/src/libANGLE/renderer/gl/egl/FunctionsEGLDL.h b/gfx/angle/src/libANGLE/renderer/gl/egl/FunctionsEGLDL.h
new file mode 100755
index 000000000..d69df77ab
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/gl/egl/FunctionsEGLDL.h
@@ -0,0 +1,42 @@
+//
+// Copyright (c) 2016 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.
+//
+
+// FunctionsEGL.h: Implements FunctionsEGL with dlopen/dlsym/dlclose
+
+#ifndef LIBANGLE_RENDERER_GL_CROS_FUNCTIONSEGLDL_H_
+#define LIBANGLE_RENDERER_GL_CROS_FUNCTIONSEGLDL_H_
+
+#include "libANGLE/renderer/gl/egl/FunctionsEGL.h"
+#include "libANGLE/renderer/gl/egl/functionsegl_typedefs.h"
+
+namespace rx
+{
+
+class DynamicLib final
+{
+ public:
+ void *handle;
+
+ DynamicLib();
+ ~DynamicLib();
+};
+
+class FunctionsEGLDL : public FunctionsEGL
+{
+ public:
+ FunctionsEGLDL();
+ ~FunctionsEGLDL() override;
+
+ egl::Error initialize(EGLNativeDisplayType nativeDisplay, const char *libName);
+ void *getProcAddress(const char *name) const override;
+
+ private:
+ PFNEGLGETPROCADDRESSPROC mGetProcAddressPtr;
+ static DynamicLib sNativeLib;
+};
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_GL_CROS_FUNCTIONSEGLDL_H_
diff --git a/gfx/angle/src/libANGLE/renderer/gl/egl/PbufferSurfaceEGL.cpp b/gfx/angle/src/libANGLE/renderer/gl/egl/PbufferSurfaceEGL.cpp
new file mode 100755
index 000000000..68da9f2b8
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/gl/egl/PbufferSurfaceEGL.cpp
@@ -0,0 +1,39 @@
+//
+// Copyright (c) 2016 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.
+//
+
+// PbufferSurfaceEGL.h: EGL implementation of egl::Surface for pbuffers
+
+#include "libANGLE/renderer/gl/egl/PbufferSurfaceEGL.h"
+
+namespace rx
+{
+
+PbufferSurfaceEGL::PbufferSurfaceEGL(const egl::SurfaceState &state,
+ const FunctionsEGL *egl,
+ EGLConfig config,
+ const std::vector<EGLint> &attribList,
+ EGLContext context,
+ RendererGL *renderer)
+ : SurfaceEGL(state, egl, config, attribList, context, renderer)
+{
+}
+
+PbufferSurfaceEGL::~PbufferSurfaceEGL()
+{
+}
+
+egl::Error PbufferSurfaceEGL::initialize()
+{
+ mSurface = mEGL->createPbufferSurface(mConfig, mAttribList.data());
+ if (mSurface == EGL_NO_SURFACE)
+ {
+ return egl::Error(mEGL->getError(), "eglCreatePbufferSurface failed");
+ }
+
+ return egl::Error(EGL_SUCCESS);
+}
+
+} // namespace rx
diff --git a/gfx/angle/src/libANGLE/renderer/gl/egl/PbufferSurfaceEGL.h b/gfx/angle/src/libANGLE/renderer/gl/egl/PbufferSurfaceEGL.h
new file mode 100755
index 000000000..ff557f2ca
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/gl/egl/PbufferSurfaceEGL.h
@@ -0,0 +1,36 @@
+//
+// Copyright (c) 2016 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.
+//
+
+// PbufferSurfaceEGL.h: EGL implementation of egl::Surface for pbuffers
+
+#ifndef LIBANGLE_RENDERER_GL_EGL_PBUFFERSURFACEEGL_H_
+#define LIBANGLE_RENDERER_GL_EGL_PBUFFERSURFACEEGL_H_
+
+#include <vector>
+#include <EGL/egl.h>
+
+#include "libANGLE/renderer/gl/egl/SurfaceEGL.h"
+
+namespace rx
+{
+
+class PbufferSurfaceEGL : public SurfaceEGL
+{
+ public:
+ PbufferSurfaceEGL(const egl::SurfaceState &state,
+ const FunctionsEGL *egl,
+ EGLConfig config,
+ const std::vector<EGLint> &attribList,
+ EGLContext context,
+ RendererGL *renderer);
+ ~PbufferSurfaceEGL() override;
+
+ egl::Error initialize() override;
+};
+
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_GL_EGL_PBUFFERSURFACEEGL_H_
diff --git a/gfx/angle/src/libANGLE/renderer/gl/egl/SurfaceEGL.cpp b/gfx/angle/src/libANGLE/renderer/gl/egl/SurfaceEGL.cpp
new file mode 100755
index 000000000..693b61c9c
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/gl/egl/SurfaceEGL.cpp
@@ -0,0 +1,132 @@
+//
+// Copyright (c) 2016 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.
+//
+
+// SurfaceEGL.cpp: EGL implementation of egl::Surface
+
+#include "libANGLE/renderer/gl/egl/SurfaceEGL.h"
+
+#include "common/debug.h"
+
+namespace rx
+{
+
+SurfaceEGL::SurfaceEGL(const egl::SurfaceState &state,
+ const FunctionsEGL *egl,
+ EGLConfig config,
+ const std::vector<EGLint> &attribList,
+ EGLContext context,
+ RendererGL *renderer)
+ : SurfaceGL(state, renderer),
+ mEGL(egl),
+ mConfig(config),
+ mAttribList(attribList),
+ mSurface(EGL_NO_SURFACE),
+ mContext(context)
+{
+}
+
+SurfaceEGL::~SurfaceEGL()
+{
+ if (mSurface != EGL_NO_SURFACE)
+ {
+ EGLBoolean success = mEGL->destroySurface(mSurface);
+ ASSERT(success == EGL_TRUE);
+ }
+}
+
+egl::Error SurfaceEGL::makeCurrent()
+{
+ EGLBoolean success = mEGL->makeCurrent(mSurface, mContext);
+ if (success == EGL_FALSE)
+ {
+ return egl::Error(mEGL->getError(), "eglMakeCurrent failed");
+ }
+ return egl::Error(EGL_SUCCESS);
+}
+
+egl::Error SurfaceEGL::swap()
+{
+ EGLBoolean success = mEGL->swapBuffers(mSurface);
+ if (success == EGL_FALSE)
+ {
+ return egl::Error(mEGL->getError(), "eglSwapBuffers failed");
+ }
+ return egl::Error(EGL_SUCCESS);
+}
+
+egl::Error SurfaceEGL::postSubBuffer(EGLint x, EGLint y, EGLint width, EGLint height)
+{
+ UNIMPLEMENTED();
+ return egl::Error(EGL_BAD_SURFACE);
+}
+
+egl::Error SurfaceEGL::querySurfacePointerANGLE(EGLint attribute, void **value)
+{
+ UNIMPLEMENTED();
+ return egl::Error(EGL_BAD_SURFACE);
+}
+
+egl::Error SurfaceEGL::bindTexImage(gl::Texture *texture, EGLint buffer)
+{
+ EGLBoolean success = mEGL->bindTexImage(mSurface, buffer);
+ if (success == EGL_FALSE)
+ {
+ return egl::Error(mEGL->getError(), "eglBindTexImage failed");
+ }
+ return egl::Error(EGL_SUCCESS);
+}
+
+egl::Error SurfaceEGL::releaseTexImage(EGLint buffer)
+{
+ EGLBoolean success = mEGL->releaseTexImage(mSurface, buffer);
+ if (success == EGL_FALSE)
+ {
+ return egl::Error(mEGL->getError(), "eglReleaseTexImage failed");
+ }
+ return egl::Error(EGL_SUCCESS);
+}
+
+void SurfaceEGL::setSwapInterval(EGLint interval)
+{
+ EGLBoolean success = mEGL->swapInterval(interval);
+ if (success == EGL_FALSE)
+ {
+ ERR("eglSwapInterval error 0x%04x", mEGL->getError());
+ ASSERT(false);
+ }
+}
+
+EGLint SurfaceEGL::getWidth() const
+{
+ EGLint value;
+ EGLBoolean success = mEGL->querySurface(mSurface, EGL_WIDTH, &value);
+ ASSERT(success == EGL_TRUE);
+ return value;
+}
+
+EGLint SurfaceEGL::getHeight() const
+{
+ EGLint value;
+ EGLBoolean success = mEGL->querySurface(mSurface, EGL_HEIGHT, &value);
+ ASSERT(success == EGL_TRUE);
+ return value;
+}
+
+EGLint SurfaceEGL::isPostSubBufferSupported() const
+{
+ UNIMPLEMENTED();
+ return 0;
+}
+
+EGLint SurfaceEGL::getSwapBehavior() const
+{
+ EGLint value;
+ EGLBoolean success = mEGL->querySurface(mSurface, EGL_SWAP_BEHAVIOR, &value);
+ ASSERT(success == EGL_TRUE);
+ return value;
+}
+
+} // namespace rx
diff --git a/gfx/angle/src/libANGLE/renderer/gl/egl/SurfaceEGL.h b/gfx/angle/src/libANGLE/renderer/gl/egl/SurfaceEGL.h
new file mode 100755
index 000000000..ee1568c9e
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/gl/egl/SurfaceEGL.h
@@ -0,0 +1,55 @@
+//
+// Copyright (c) 2016 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.
+//
+
+// SurfaceEGL.h: common interface for EGL surfaces
+
+#ifndef LIBANGLE_RENDERER_GL_EGL_SURFACEEGL_H_
+#define LIBANGLE_RENDERER_GL_EGL_SURFACEEGL_H_
+
+#include <EGL/egl.h>
+
+#include "libANGLE/renderer/gl/SurfaceGL.h"
+#include "libANGLE/renderer/gl/egl/FunctionsEGL.h"
+
+namespace rx
+{
+
+class SurfaceEGL : public SurfaceGL
+{
+ public:
+ SurfaceEGL(const egl::SurfaceState &state,
+ const FunctionsEGL *egl,
+ EGLConfig config,
+ const std::vector<EGLint> &attribList,
+ EGLContext context,
+ RendererGL *renderer);
+ ~SurfaceEGL() override;
+
+ egl::Error makeCurrent() override;
+ egl::Error swap() override;
+ egl::Error postSubBuffer(EGLint x, EGLint y, EGLint width, EGLint height) override;
+ egl::Error querySurfacePointerANGLE(EGLint attribute, void **value) override;
+ egl::Error bindTexImage(gl::Texture *texture, EGLint buffer) override;
+ egl::Error releaseTexImage(EGLint buffer) override;
+ void setSwapInterval(EGLint interval) override;
+ EGLint getWidth() const override;
+ EGLint getHeight() const override;
+ EGLint isPostSubBufferSupported() const override;
+ EGLint getSwapBehavior() const override;
+
+ protected:
+ const FunctionsEGL *mEGL;
+ EGLConfig mConfig;
+ std::vector<EGLint> mAttribList;
+ EGLSurface mSurface;
+
+ private:
+ EGLContext mContext;
+};
+
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_GL_EGL_SURFACEEGL_H_
diff --git a/gfx/angle/src/libANGLE/renderer/gl/egl/WindowSurfaceEGL.cpp b/gfx/angle/src/libANGLE/renderer/gl/egl/WindowSurfaceEGL.cpp
new file mode 100755
index 000000000..db226ee18
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/gl/egl/WindowSurfaceEGL.cpp
@@ -0,0 +1,40 @@
+//
+// Copyright (c) 2016 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.
+//
+
+// WindowSurfaceEGL.h: EGL implementation of egl::Surface for windows
+
+#include "libANGLE/renderer/gl/egl/WindowSurfaceEGL.h"
+
+namespace rx
+{
+
+WindowSurfaceEGL::WindowSurfaceEGL(const egl::SurfaceState &state,
+ const FunctionsEGL *egl,
+ EGLConfig config,
+ EGLNativeWindowType window,
+ const std::vector<EGLint> &attribList,
+ EGLContext context,
+ RendererGL *renderer)
+ : SurfaceEGL(state, egl, config, attribList, context, renderer), mWindow(window)
+{
+}
+
+WindowSurfaceEGL::~WindowSurfaceEGL()
+{
+}
+
+egl::Error WindowSurfaceEGL::initialize()
+{
+ mSurface = mEGL->createWindowSurface(mConfig, mWindow, mAttribList.data());
+ if (mSurface == EGL_NO_SURFACE)
+ {
+ return egl::Error(mEGL->getError(), "eglCreateWindowSurface failed");
+ }
+
+ return egl::Error(EGL_SUCCESS);
+}
+
+} // namespace rx
diff --git a/gfx/angle/src/libANGLE/renderer/gl/egl/WindowSurfaceEGL.h b/gfx/angle/src/libANGLE/renderer/gl/egl/WindowSurfaceEGL.h
new file mode 100755
index 000000000..f9da4c27c
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/gl/egl/WindowSurfaceEGL.h
@@ -0,0 +1,37 @@
+//
+// Copyright (c) 2016 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.
+//
+
+// WindowSurfaceEGL.h: EGL implementation of egl::Surface for windows
+
+#ifndef LIBANGLE_RENDERER_GL_EGL_WINDOWSURFACEEGL_H_
+#define LIBANGLE_RENDERER_GL_EGL_WINDOWSURFACEEGL_H_
+
+#include "libANGLE/renderer/gl/egl/SurfaceEGL.h"
+
+namespace rx
+{
+
+class WindowSurfaceEGL : public SurfaceEGL
+{
+ public:
+ WindowSurfaceEGL(const egl::SurfaceState &state,
+ const FunctionsEGL *egl,
+ EGLConfig config,
+ EGLNativeWindowType window,
+ const std::vector<EGLint> &attribList,
+ EGLContext context,
+ RendererGL *renderer);
+ ~WindowSurfaceEGL() override;
+
+ egl::Error initialize() override;
+
+ private:
+ EGLNativeWindowType mWindow;
+};
+
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_GL_EGL_WINDOWSURFACEEGL_H_
diff --git a/gfx/angle/src/libANGLE/renderer/gl/egl/android/DisplayAndroid.cpp b/gfx/angle/src/libANGLE/renderer/gl/egl/android/DisplayAndroid.cpp
new file mode 100755
index 000000000..b689578c9
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/gl/egl/android/DisplayAndroid.cpp
@@ -0,0 +1,385 @@
+//
+// Copyright (c) 2016 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.
+//
+
+// DisplayAndroid.cpp: Android implementation of egl::Display
+
+#include <android/native_window.h>
+
+#include "common/debug.h"
+#include "libANGLE/Display.h"
+#include "libANGLE/renderer/gl/renderergl_utils.h"
+#include "libANGLE/renderer/gl/egl/android/DisplayAndroid.h"
+#include "libANGLE/renderer/gl/egl/FunctionsEGLDL.h"
+#include "libANGLE/renderer/gl/egl/PbufferSurfaceEGL.h"
+#include "libANGLE/renderer/gl/egl/WindowSurfaceEGL.h"
+
+namespace
+{
+const char *GetEGLPath()
+{
+#if defined(__LP64__)
+ return "/system/lib64/libEGL.so";
+#else
+ return "/system/lib/libEGL.so";
+#endif
+}
+} // namespace
+
+namespace rx
+{
+
+DisplayAndroid::DisplayAndroid() : DisplayEGL(), mDummyPbuffer(EGL_NO_SURFACE)
+{
+}
+
+DisplayAndroid::~DisplayAndroid()
+{
+}
+
+egl::Error DisplayAndroid::initialize(egl::Display *display)
+{
+ FunctionsEGLDL *egl = new FunctionsEGLDL();
+ mEGL = egl;
+ ANGLE_TRY(egl->initialize(display->getNativeDisplayId(), GetEGLPath()));
+
+ gl::Version eglVersion(mEGL->majorVersion, mEGL->minorVersion);
+ ASSERT(eglVersion >= gl::Version(1, 4));
+
+ static_assert(EGL_OPENGL_ES3_BIT == EGL_OPENGL_ES3_BIT_KHR, "Extension define must match core");
+ EGLint esBit = (eglVersion >= gl::Version(1, 5) || mEGL->hasExtension("EGL_KHR_create_context"))
+ ? EGL_OPENGL_ES3_BIT
+ : EGL_OPENGL_ES2_BIT;
+
+ // clang-format off
+ mConfigAttribList =
+ {
+ // Choose RGBA8888
+ EGL_COLOR_BUFFER_TYPE, EGL_RGB_BUFFER,
+ EGL_RED_SIZE, 8,
+ EGL_GREEN_SIZE, 8,
+ EGL_BLUE_SIZE, 8,
+ EGL_ALPHA_SIZE, 8,
+ // EGL1.5 spec Section 2.2 says that depth, multisample and stencil buffer depths
+ // must match for contexts to be compatible.
+ EGL_DEPTH_SIZE, 24,
+ EGL_STENCIL_SIZE, 8,
+ EGL_SAMPLE_BUFFERS, 0,
+ // Android doesn't support pixmaps
+ EGL_SURFACE_TYPE, EGL_WINDOW_BIT | EGL_PBUFFER_BIT,
+ EGL_CONFIG_CAVEAT, EGL_NONE,
+ EGL_CONFORMANT, esBit,
+ EGL_RENDERABLE_TYPE, esBit,
+ EGL_NONE
+ };
+ // clang-format on
+ EGLint numConfig;
+
+ EGLBoolean success = mEGL->chooseConfig(mConfigAttribList.data(), &mConfig, 1, &numConfig);
+ if (success == EGL_FALSE)
+ {
+ return egl::Error(mEGL->getError(), "eglChooseConfig failed");
+ }
+
+ ANGLE_TRY(initializeContext(display->getAttributeMap()));
+
+ int dummyPbufferAttribs[] = {
+ EGL_WIDTH, 1, EGL_HEIGHT, 1, EGL_NONE,
+ };
+ mDummyPbuffer = mEGL->createPbufferSurface(mConfig, dummyPbufferAttribs);
+ if (mDummyPbuffer == EGL_NO_SURFACE)
+ {
+ return egl::Error(mEGL->getError(), "eglCreatePbufferSurface failed");
+ }
+
+ success = mEGL->makeCurrent(mDummyPbuffer, mContext);
+ if (success == EGL_FALSE)
+ {
+ return egl::Error(mEGL->getError(), "eglMakeCurrent failed");
+ }
+
+ mFunctionsGL = mEGL->makeFunctionsGL();
+ mFunctionsGL->initialize();
+
+ return DisplayGL::initialize(display);
+}
+
+void DisplayAndroid::terminate()
+{
+ DisplayGL::terminate();
+
+ EGLBoolean success = mEGL->makeCurrent(EGL_NO_SURFACE, EGL_NO_CONTEXT);
+ if (success == EGL_FALSE)
+ {
+ ERR("eglMakeCurrent error 0x%04x", mEGL->getError());
+ }
+
+ if (mDummyPbuffer != EGL_NO_SURFACE)
+ {
+ success = mEGL->destroySurface(mDummyPbuffer);
+ mDummyPbuffer = EGL_NO_SURFACE;
+ if (success == EGL_FALSE)
+ {
+ ERR("eglDestroySurface error 0x%04x", mEGL->getError());
+ }
+ }
+
+ if (mContext != EGL_NO_CONTEXT)
+ {
+ success = mEGL->destroyContext(mContext);
+ mContext = EGL_NO_CONTEXT;
+ if (success == EGL_FALSE)
+ {
+ ERR("eglDestroyContext error 0x%04x", mEGL->getError());
+ }
+ }
+
+ egl::Error result = mEGL->terminate();
+ if (result.isError())
+ {
+ ERR("eglTerminate error 0x%04x", result.getCode());
+ }
+
+ SafeDelete(mEGL);
+ SafeDelete(mFunctionsGL);
+}
+
+SurfaceImpl *DisplayAndroid::createWindowSurface(const egl::SurfaceState &state,
+ const egl::Config *configuration,
+ EGLNativeWindowType window,
+ const egl::AttributeMap &attribs)
+{
+ EGLConfig config;
+ EGLint numConfig;
+ EGLBoolean success;
+
+ const EGLint configAttribList[] = {EGL_CONFIG_ID, mConfigIds[configuration->configID],
+ EGL_NONE};
+ success = mEGL->chooseConfig(configAttribList, &config, 1, &numConfig);
+ ASSERT(success && numConfig == 1);
+
+ return new WindowSurfaceEGL(state, mEGL, config, window, attribs.toIntVector(), mContext,
+ getRenderer());
+}
+
+SurfaceImpl *DisplayAndroid::createPbufferSurface(const egl::SurfaceState &state,
+ const egl::Config *configuration,
+ const egl::AttributeMap &attribs)
+{
+ EGLConfig config;
+ EGLint numConfig;
+ EGLBoolean success;
+
+ const EGLint configAttribList[] = {EGL_CONFIG_ID, mConfigIds[configuration->configID],
+ EGL_NONE};
+ success = mEGL->chooseConfig(configAttribList, &config, 1, &numConfig);
+ ASSERT(success && numConfig == 1);
+
+ return new PbufferSurfaceEGL(state, mEGL, config, attribs.toIntVector(), mContext,
+ getRenderer());
+}
+
+SurfaceImpl *DisplayAndroid::createPbufferFromClientBuffer(const egl::SurfaceState &state,
+ const egl::Config *configuration,
+ EGLenum buftype,
+ EGLClientBuffer clientBuffer,
+ const egl::AttributeMap &attribs)
+{
+ UNIMPLEMENTED();
+ return nullptr;
+}
+
+SurfaceImpl *DisplayAndroid::createPixmapSurface(const egl::SurfaceState &state,
+ const egl::Config *configuration,
+ NativePixmapType nativePixmap,
+ const egl::AttributeMap &attribs)
+{
+ UNIMPLEMENTED();
+ return nullptr;
+}
+
+ImageImpl *DisplayAndroid::createImage(EGLenum target,
+ egl::ImageSibling *buffer,
+ const egl::AttributeMap &attribs)
+{
+ UNIMPLEMENTED();
+ return DisplayGL::createImage(target, buffer, attribs);
+}
+
+template <typename T>
+void DisplayAndroid::getConfigAttrib(EGLConfig config, EGLint attribute, T *value) const
+{
+ EGLint tmp;
+ EGLBoolean success = mEGL->getConfigAttrib(config, attribute, &tmp);
+ ASSERT(success == EGL_TRUE);
+ *value = tmp;
+}
+
+egl::ConfigSet DisplayAndroid::generateConfigs()
+{
+ egl::ConfigSet configSet;
+ mConfigIds.clear();
+
+ EGLint numConfigs;
+ EGLBoolean success = mEGL->chooseConfig(mConfigAttribList.data(), nullptr, 0, &numConfigs);
+ ASSERT(success == EGL_TRUE && numConfigs > 0);
+
+ std::vector<EGLConfig> configs(numConfigs);
+ EGLint numConfigs2;
+ success =
+ mEGL->chooseConfig(mConfigAttribList.data(), configs.data(), numConfigs, &numConfigs2);
+ ASSERT(success == EGL_TRUE && numConfigs2 == numConfigs);
+
+ for (int i = 0; i < numConfigs; i++)
+ {
+ egl::Config config;
+
+ getConfigAttrib(configs[i], EGL_BUFFER_SIZE, &config.bufferSize);
+ getConfigAttrib(configs[i], EGL_RED_SIZE, &config.redSize);
+ getConfigAttrib(configs[i], EGL_GREEN_SIZE, &config.greenSize);
+ getConfigAttrib(configs[i], EGL_BLUE_SIZE, &config.blueSize);
+ getConfigAttrib(configs[i], EGL_LUMINANCE_SIZE, &config.luminanceSize);
+ getConfigAttrib(configs[i], EGL_ALPHA_SIZE, &config.alphaSize);
+ getConfigAttrib(configs[i], EGL_ALPHA_MASK_SIZE, &config.alphaMaskSize);
+ getConfigAttrib(configs[i], EGL_BIND_TO_TEXTURE_RGB, &config.bindToTextureRGB);
+ getConfigAttrib(configs[i], EGL_BIND_TO_TEXTURE_RGBA, &config.bindToTextureRGBA);
+ getConfigAttrib(configs[i], EGL_COLOR_BUFFER_TYPE, &config.colorBufferType);
+ getConfigAttrib(configs[i], EGL_CONFIG_CAVEAT, &config.configCaveat);
+ getConfigAttrib(configs[i], EGL_CONFIG_ID, &config.configID);
+ getConfigAttrib(configs[i], EGL_CONFORMANT, &config.conformant);
+ getConfigAttrib(configs[i], EGL_DEPTH_SIZE, &config.depthSize);
+ getConfigAttrib(configs[i], EGL_LEVEL, &config.level);
+ getConfigAttrib(configs[i], EGL_MAX_PBUFFER_WIDTH, &config.maxPBufferWidth);
+ getConfigAttrib(configs[i], EGL_MAX_PBUFFER_HEIGHT, &config.maxPBufferHeight);
+ getConfigAttrib(configs[i], EGL_MAX_PBUFFER_PIXELS, &config.maxPBufferPixels);
+ getConfigAttrib(configs[i], EGL_MAX_SWAP_INTERVAL, &config.maxSwapInterval);
+ getConfigAttrib(configs[i], EGL_MIN_SWAP_INTERVAL, &config.minSwapInterval);
+ getConfigAttrib(configs[i], EGL_NATIVE_RENDERABLE, &config.nativeRenderable);
+ getConfigAttrib(configs[i], EGL_NATIVE_VISUAL_ID, &config.nativeVisualID);
+ getConfigAttrib(configs[i], EGL_NATIVE_VISUAL_TYPE, &config.nativeVisualType);
+ getConfigAttrib(configs[i], EGL_RENDERABLE_TYPE, &config.renderableType);
+ getConfigAttrib(configs[i], EGL_SAMPLE_BUFFERS, &config.sampleBuffers);
+ getConfigAttrib(configs[i], EGL_SAMPLES, &config.samples);
+ getConfigAttrib(configs[i], EGL_STENCIL_SIZE, &config.stencilSize);
+ getConfigAttrib(configs[i], EGL_SURFACE_TYPE, &config.surfaceType);
+ getConfigAttrib(configs[i], EGL_TRANSPARENT_TYPE, &config.transparentType);
+ getConfigAttrib(configs[i], EGL_TRANSPARENT_RED_VALUE, &config.transparentRedValue);
+ getConfigAttrib(configs[i], EGL_TRANSPARENT_GREEN_VALUE, &config.transparentGreenValue);
+ getConfigAttrib(configs[i], EGL_TRANSPARENT_BLUE_VALUE, &config.transparentBlueValue);
+
+ if (config.colorBufferType == EGL_RGB_BUFFER)
+ {
+ if (config.redSize == 8 && config.greenSize == 8 && config.blueSize == 8 &&
+ config.alphaSize == 8)
+ {
+ config.renderTargetFormat = GL_RGBA8;
+ }
+ else if (config.redSize == 8 && config.greenSize == 8 && config.blueSize == 8 &&
+ config.alphaSize == 0)
+ {
+ config.renderTargetFormat = GL_RGB8;
+ }
+ else if (config.redSize == 5 && config.greenSize == 6 && config.blueSize == 5 &&
+ config.alphaSize == 0)
+ {
+ config.renderTargetFormat = GL_RGB565;
+ }
+ else
+ {
+ UNREACHABLE();
+ }
+ }
+ else
+ {
+ UNREACHABLE();
+ }
+
+ if (config.depthSize == 0 && config.stencilSize == 0)
+ {
+ config.depthStencilFormat = GL_ZERO;
+ }
+ else if (config.depthSize == 16 && config.stencilSize == 0)
+ {
+ config.depthStencilFormat = GL_DEPTH_COMPONENT16;
+ }
+ else if (config.depthSize == 24 && config.stencilSize == 0)
+ {
+ config.depthStencilFormat = GL_DEPTH_COMPONENT24;
+ }
+ else if (config.depthSize == 24 && config.stencilSize == 8)
+ {
+ config.depthStencilFormat = GL_DEPTH24_STENCIL8;
+ }
+ else if (config.depthSize == 0 && config.stencilSize == 8)
+ {
+ config.depthStencilFormat = GL_STENCIL_INDEX8;
+ }
+ else
+ {
+ UNREACHABLE();
+ }
+
+ config.matchNativePixmap = EGL_NONE;
+ config.optimalOrientation = 0;
+
+ int internalId = configSet.add(config);
+ mConfigIds[internalId] = config.configID;
+ }
+
+ return configSet;
+}
+
+bool DisplayAndroid::testDeviceLost()
+{
+ return false;
+}
+
+egl::Error DisplayAndroid::restoreLostDevice()
+{
+ UNIMPLEMENTED();
+ return egl::Error(EGL_SUCCESS);
+}
+
+bool DisplayAndroid::isValidNativeWindow(EGLNativeWindowType window) const
+{
+ return ANativeWindow_getFormat(window) >= 0;
+}
+
+egl::Error DisplayAndroid::getDevice(DeviceImpl **device)
+{
+ UNIMPLEMENTED();
+ return egl::Error(EGL_SUCCESS);
+}
+
+egl::Error DisplayAndroid::waitClient() const
+{
+ UNIMPLEMENTED();
+ return egl::Error(EGL_SUCCESS);
+}
+
+egl::Error DisplayAndroid::waitNative(EGLint engine,
+ egl::Surface *drawSurface,
+ egl::Surface *readSurface) const
+{
+ UNIMPLEMENTED();
+ return egl::Error(EGL_SUCCESS);
+}
+
+egl::Error DisplayAndroid::getDriverVersion(std::string *version) const
+{
+ VendorID vendor = GetVendorID(mFunctionsGL);
+
+ switch (vendor)
+ {
+ case VENDOR_ID_QUALCOMM:
+ *version = reinterpret_cast<const char *>(mFunctionsGL->getString(GL_VERSION));
+ return egl::Error(EGL_SUCCESS);
+ default:
+ *version = "";
+ return egl::Error(EGL_SUCCESS);
+ }
+}
+
+} // namespace rx
diff --git a/gfx/angle/src/libANGLE/renderer/gl/egl/android/DisplayAndroid.h b/gfx/angle/src/libANGLE/renderer/gl/egl/android/DisplayAndroid.h
new file mode 100755
index 000000000..0be9bb465
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/gl/egl/android/DisplayAndroid.h
@@ -0,0 +1,78 @@
+//
+// Copyright (c) 2016 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.
+//
+
+// DisplayAndroid.h: Android implementation of egl::Display
+
+#ifndef LIBANGLE_RENDERER_GL_EGL_ANDROID_DISPLAYANDROID_H_
+#define LIBANGLE_RENDERER_GL_EGL_ANDROID_DISPLAYANDROID_H_
+
+#include <map>
+#include <string>
+#include <vector>
+
+#include "libANGLE/renderer/gl/egl/DisplayEGL.h"
+
+namespace rx
+{
+
+class DisplayAndroid : public DisplayEGL
+{
+ public:
+ DisplayAndroid();
+ ~DisplayAndroid() override;
+
+ egl::Error initialize(egl::Display *display) override;
+ void terminate() override;
+
+ SurfaceImpl *createWindowSurface(const egl::SurfaceState &state,
+ const egl::Config *configuration,
+ EGLNativeWindowType window,
+ const egl::AttributeMap &attribs) override;
+ SurfaceImpl *createPbufferSurface(const egl::SurfaceState &state,
+ const egl::Config *configuration,
+ const egl::AttributeMap &attribs) override;
+ SurfaceImpl *createPbufferFromClientBuffer(const egl::SurfaceState &state,
+ const egl::Config *configuration,
+ EGLenum buftype,
+ EGLClientBuffer clientBuffer,
+ const egl::AttributeMap &attribs) override;
+ SurfaceImpl *createPixmapSurface(const egl::SurfaceState &state,
+ const egl::Config *configuration,
+ NativePixmapType nativePixmap,
+ const egl::AttributeMap &attribs) override;
+
+ ImageImpl *createImage(EGLenum target,
+ egl::ImageSibling *buffer,
+ const egl::AttributeMap &attribs) override;
+
+ egl::ConfigSet generateConfigs() override;
+
+ bool testDeviceLost() override;
+ egl::Error restoreLostDevice() override;
+
+ bool isValidNativeWindow(EGLNativeWindowType window) const override;
+
+ egl::Error getDevice(DeviceImpl **device) override;
+
+ egl::Error waitClient() const override;
+ egl::Error waitNative(EGLint engine,
+ egl::Surface *drawSurface,
+ egl::Surface *readSurface) const override;
+
+ egl::Error getDriverVersion(std::string *version) const override;
+
+ private:
+ template <typename T>
+ void getConfigAttrib(EGLConfig config, EGLint attribute, T *value) const;
+
+ std::vector<EGLint> mConfigAttribList;
+ std::map<EGLint, EGLint> mConfigIds;
+ EGLSurface mDummyPbuffer;
+};
+
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_GL_EGL_ANDROID_DISPLAYANDROID_H_
diff --git a/gfx/angle/src/libANGLE/renderer/gl/egl/functionsegl_typedefs.h b/gfx/angle/src/libANGLE/renderer/gl/egl/functionsegl_typedefs.h
new file mode 100755
index 000000000..78f9009bf
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/gl/egl/functionsegl_typedefs.h
@@ -0,0 +1,131 @@
+//
+// Copyright (c) 2016 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.
+//
+
+// functionsegl_typedefs.h: Typedefs of EGL functions.
+
+#ifndef LIBANGLE_RENDERER_GL_EGL_FUNCTIONSEGLTYPEDEFS_H_
+#define LIBANGLE_RENDERER_GL_EGL_FUNCTIONSEGLTYPEDEFS_H_
+
+#include <EGL/egl.h>
+
+namespace rx
+{
+// EGL 1.0
+typedef EGLBoolean (*PFNEGLCHOOSECONFIGPROC)(EGLDisplay dpy,
+ const EGLint *attrib_list,
+ EGLConfig *configs,
+ EGLint config_size,
+ EGLint *num_config);
+typedef EGLBoolean (*PFNEGLCOPYBUFFERSPROC)(EGLDisplay dpy,
+ EGLSurface surface,
+ EGLNativePixmapType target);
+typedef EGLContext (*PFNEGLCREATECONTEXTPROC)(EGLDisplay dpy,
+ EGLConfig config,
+ EGLContext share_context,
+ const EGLint *attrib_list);
+typedef EGLSurface (*PFNEGLCREATEPBUFFERSURFACEPROC)(EGLDisplay dpy,
+ EGLConfig config,
+ const EGLint *attrib_list);
+typedef EGLSurface (*PFNEGLCREATEPIXMAPSURFACEPROC)(EGLDisplay dpy,
+ EGLConfig config,
+ EGLNativePixmapType pixmap,
+ const EGLint *attrib_list);
+typedef EGLSurface (*PFNEGLCREATEWINDOWSURFACEPROC)(EGLDisplay dpy,
+ EGLConfig config,
+ EGLNativeWindowType win,
+ const EGLint *attrib_list);
+typedef EGLBoolean (*PFNEGLDESTROYCONTEXTPROC)(EGLDisplay dpy, EGLContext ctx);
+typedef EGLBoolean (*PFNEGLDESTROYSURFACEPROC)(EGLDisplay dpy, EGLSurface surface);
+typedef EGLBoolean (*PFNEGLGETCONFIGATTRIBPROC)(EGLDisplay dpy,
+ EGLConfig config,
+ EGLint attribute,
+ EGLint *value);
+typedef EGLBoolean (*PFNEGLGETCONFIGSPROC)(EGLDisplay dpy,
+ EGLConfig *configs,
+ EGLint config_size,
+ EGLint *num_config);
+typedef EGLDisplay (*PFNEGLGETCURRENTDISPLAYPROC)(void);
+typedef EGLSurface (*PFNEGLGETCURRENTSURFACEPROC)(EGLint readdraw);
+typedef EGLDisplay (*PFNEGLGETDISPLAYPROC)(EGLNativeDisplayType display_id);
+typedef EGLint (*PFNEGLGETERRORPROC)(void);
+typedef __eglMustCastToProperFunctionPointerType (*PFNEGLGETPROCADDRESSPROC)(const char *procname);
+typedef EGLBoolean (*PFNEGLINITIALIZEPROC)(EGLDisplay dpy, EGLint *major, EGLint *minor);
+typedef EGLBoolean (*PFNEGLMAKECURRENTPROC)(EGLDisplay dpy,
+ EGLSurface draw,
+ EGLSurface read,
+ EGLContext ctx);
+typedef EGLBoolean (*PFNEGLQUERYCONTEXTPROC)(EGLDisplay dpy,
+ EGLContext ctx,
+ EGLint attribute,
+ EGLint *value);
+typedef const char *(*PFNEGLQUERYSTRINGPROC)(EGLDisplay dpy, EGLint name);
+typedef EGLBoolean (*PFNEGLQUERYSURFACEPROC)(EGLDisplay dpy,
+ EGLSurface surface,
+ EGLint attribute,
+ EGLint *value);
+typedef EGLBoolean (*PFNEGLSWAPBUFFERSPROC)(EGLDisplay dpy, EGLSurface surface);
+typedef EGLBoolean (*PFNEGLTERMINATEPROC)(EGLDisplay dpy);
+typedef EGLBoolean (*PFNEGLWAITGLPROC)(void);
+typedef EGLBoolean (*PFNEGLWAITNATIVEPROC)(EGLint engine);
+
+// EGL 1.1
+typedef EGLBoolean (*PFNEGLBINDTEXIMAGEPROC)(EGLDisplay dpy, EGLSurface surface, EGLint buffer);
+typedef EGLBoolean (*PFNEGLRELEASETEXIMAGEPROC)(EGLDisplay dpy, EGLSurface surface, EGLint buffer);
+typedef EGLBoolean (*PFNEGLSURFACEATTRIBPROC)(EGLDisplay dpy,
+ EGLSurface surface,
+ EGLint attribute,
+ EGLint value);
+typedef EGLBoolean (*PFNEGLSWAPINTERVALPROC)(EGLDisplay dpy, EGLint interval);
+
+// EGL 1.2
+typedef EGLBoolean (*PFNEGLBINDAPIPROC)(EGLenum api);
+typedef EGLenum (*PFNEGLQUERYAPIPROC)(void);
+typedef EGLSurface (*PFNEGLCREATEPBUFFERFROMCLIENTBUFFERPROC)(EGLDisplay dpy,
+ EGLenum buftype,
+ EGLClientBuffer buffer,
+ EGLConfig config,
+ const EGLint *attrib_list);
+typedef EGLBoolean (*PFNEGLRELEASETHREADPROC)(void);
+typedef EGLBoolean (*PFNEGLWAITCLIENTPROC)(void);
+
+// EGL 1.3
+
+// EGL 1.4
+typedef EGLContext (*PFNEGLGETCURRENTCONTEXTPROC)(void);
+
+// EGL 1.5
+typedef EGLSync (*PFNEGLCREATESYNCPROC)(EGLDisplay dpy, EGLenum type, const EGLAttrib *attrib_list);
+typedef EGLBoolean (*PFNEGLDESTROYSYNCPROC)(EGLDisplay dpy, EGLSync sync);
+typedef EGLint (*PFNEGLCLIENTWAITSYNCPROC)(EGLDisplay dpy,
+ EGLSync sync,
+ EGLint flags,
+ EGLTime timeout);
+typedef EGLBoolean (*PFNEGLGETSYNCATTRIBPROC)(EGLDisplay dpy,
+ EGLSync sync,
+ EGLint attribute,
+ EGLAttrib *value);
+typedef EGLImage (*PFNEGLCREATEIMAGEPROC)(EGLDisplay dpy,
+ EGLContext ctx,
+ EGLenum target,
+ EGLClientBuffer buffer,
+ const EGLAttrib *attrib_list);
+typedef EGLBoolean (*PFNEGLDESTROYIMAGEPROC)(EGLDisplay dpy, EGLImage image);
+typedef EGLDisplay (*PFNEGLGETPLATFORMDISPLAYPROC)(EGLenum platform,
+ void *native_display,
+ const EGLAttrib *attrib_list);
+typedef EGLSurface (*PFNEGLCREATEPLATFORMWINDOWSURFACEPROC)(EGLDisplay dpy,
+ EGLConfig config,
+ void *native_window,
+ const EGLAttrib *attrib_list);
+typedef EGLSurface (*PFNEGLCREATEPLATFORMPIXMAPSURFACEPROC)(EGLDisplay dpy,
+ EGLConfig config,
+ void *native_pixmap,
+ const EGLAttrib *attrib_list);
+typedef EGLBoolean (*PFNEGLWAITSYNCPROC)(EGLDisplay dpy, EGLSync sync, EGLint flags);
+
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_GL_EGL_FUNCTIONSEGLTYPEDEFS_H_
diff --git a/gfx/angle/src/libANGLE/renderer/gl/egl/ozone/DisplayOzone.cpp b/gfx/angle/src/libANGLE/renderer/gl/egl/ozone/DisplayOzone.cpp
new file mode 100755
index 000000000..01549fcfa
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/gl/egl/ozone/DisplayOzone.cpp
@@ -0,0 +1,945 @@
+//
+// Copyright (c) 2016 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.
+//
+
+// DisplayOzone.cpp: Ozone implementation of egl::Display
+
+#include "libANGLE/renderer/gl/egl/ozone/DisplayOzone.h"
+
+#include <fcntl.h>
+#include <poll.h>
+#include <iostream>
+#include <unistd.h>
+#include <sys/time.h>
+
+#include <EGL/eglext.h>
+
+#include <gbm.h>
+#include <drm_fourcc.h>
+
+#include "common/debug.h"
+#include "libANGLE/Config.h"
+#include "libANGLE/Display.h"
+#include "libANGLE/Surface.h"
+#include "libANGLE/renderer/gl/FramebufferGL.h"
+#include "libANGLE/renderer/gl/RendererGL.h"
+#include "libANGLE/renderer/gl/StateManagerGL.h"
+#include "libANGLE/renderer/gl/egl/FunctionsEGLDL.h"
+#include "libANGLE/renderer/gl/egl/ozone/SurfaceOzone.h"
+#include "platform/Platform.h"
+
+// ARM-specific extension needed to make Mali GPU behave - not in any
+// published header file.
+#ifndef EGL_SYNC_PRIOR_COMMANDS_IMPLICIT_EXTERNAL_ARM
+#define EGL_SYNC_PRIOR_COMMANDS_IMPLICIT_EXTERNAL_ARM 0x328A
+#endif
+
+#ifndef EGL_NO_CONFIG_MESA
+#define EGL_NO_CONFIG_MESA ((EGLConfig)0)
+#endif
+
+namespace
+{
+
+EGLint UnsignedToSigned(uint32_t u)
+{
+ return *reinterpret_cast<const EGLint *>(&u);
+}
+
+drmModeModeInfoPtr ChooseMode(drmModeConnectorPtr conn)
+{
+ drmModeModeInfoPtr mode = nullptr;
+ ASSERT(conn);
+ ASSERT(conn->connection == DRM_MODE_CONNECTED);
+ // use first preferred mode if any, else end up with last mode in list
+ for (int i = 0; i < conn->count_modes; ++i)
+ {
+ mode = conn->modes + i;
+ if (mode->type & DRM_MODE_TYPE_PREFERRED)
+ {
+ break;
+ }
+ }
+ return mode;
+}
+
+int ChooseCRTC(int fd, drmModeConnectorPtr conn)
+{
+ for (int i = 0; i < conn->count_encoders; ++i)
+ {
+ drmModeEncoderPtr enc = drmModeGetEncoder(fd, conn->encoders[i]);
+ unsigned long crtcs = enc->possible_crtcs;
+ drmModeFreeEncoder(enc);
+ if (crtcs)
+ {
+ return __builtin_ctzl(crtcs);
+ }
+ }
+ return -1;
+}
+} // namespace
+
+namespace rx
+{
+
+// TODO(fjhenigman) Implement swap control. Until then this is unused.
+SwapControlData::SwapControlData()
+ : targetSwapInterval(0), maxSwapInterval(-1), currentSwapInterval(-1)
+{
+}
+
+DisplayOzone::Buffer::Buffer(DisplayOzone *display,
+ uint32_t useFlags,
+ uint32_t gbmFormat,
+ uint32_t drmFormat,
+ uint32_t drmFormatFB,
+ int depthBits,
+ int stencilBits)
+ : mDisplay(display),
+ mNative(nullptr),
+ mWidth(0),
+ mHeight(0),
+ mDepthBits(depthBits),
+ mStencilBits(stencilBits),
+ mUseFlags(useFlags),
+ mGBMFormat(gbmFormat),
+ mDRMFormat(drmFormat),
+ mDRMFormatFB(drmFormatFB),
+ mBO(nullptr),
+ mDMABuf(-1),
+ mHasDRMFB(false),
+ mDRMFB(0),
+ mImage(EGL_NO_IMAGE_KHR),
+ mColorBuffer(0),
+ mDSBuffer(0),
+ mGLFB(0),
+ mTexture(0)
+{
+}
+
+DisplayOzone::Buffer::~Buffer()
+{
+ mDisplay->mFunctionsGL->deleteFramebuffers(1, &mGLFB);
+ reset();
+}
+
+void DisplayOzone::Buffer::reset()
+{
+ if (mHasDRMFB)
+ {
+ int fd = gbm_device_get_fd(mDisplay->mGBM);
+ drmModeRmFB(fd, mDRMFB);
+ mHasDRMFB = false;
+ }
+
+ FunctionsGL *gl = mDisplay->mFunctionsGL;
+ gl->deleteRenderbuffers(1, &mColorBuffer);
+ mColorBuffer = 0;
+ gl->deleteRenderbuffers(1, &mDSBuffer);
+ mDSBuffer = 0;
+
+ // Here we might destroy the GL framebuffer (mGLFB) but unlike every other resource in Buffer,
+ // it does not get destroyed (and recreated) because when it is the default framebuffer for
+ // an ANGLE surface then ANGLE expects it to have the same lifetime as that surface.
+
+ if (mImage != EGL_NO_IMAGE_KHR)
+ {
+ mDisplay->mEGL->destroyImageKHR(mImage);
+ mImage = EGL_NO_IMAGE_KHR;
+ }
+
+ if (mTexture)
+ {
+ gl->deleteTextures(1, &mTexture);
+ mTexture = 0;
+ }
+
+ if (mDMABuf >= 0)
+ {
+ close(mDMABuf);
+ mDMABuf = -1;
+ }
+
+ if (mBO)
+ {
+ gbm_bo_destroy(mBO);
+ mBO = nullptr;
+ }
+}
+
+bool DisplayOzone::Buffer::resize(int32_t width, int32_t height)
+{
+ if (mWidth == width && mHeight == height)
+ {
+ return true;
+ }
+
+ reset();
+
+ if (width <= 0 || height <= 0)
+ {
+ return true;
+ }
+
+ mBO = gbm_bo_create(mDisplay->mGBM, width, height, mGBMFormat, mUseFlags);
+ if (!mBO)
+ {
+ return false;
+ }
+
+ mDMABuf = gbm_bo_get_fd(mBO);
+ if (mDMABuf < 0)
+ {
+ return false;
+ }
+
+ // clang-format off
+ const EGLint attr[] =
+ {
+ EGL_WIDTH, width,
+ EGL_HEIGHT, height,
+ EGL_LINUX_DRM_FOURCC_EXT, UnsignedToSigned(mDRMFormat),
+ EGL_DMA_BUF_PLANE0_FD_EXT, mDMABuf,
+ EGL_DMA_BUF_PLANE0_PITCH_EXT, UnsignedToSigned(gbm_bo_get_stride(mBO)),
+ EGL_DMA_BUF_PLANE0_OFFSET_EXT, 0,
+ EGL_NONE,
+ };
+ // clang-format on
+
+ mImage = mDisplay->mEGL->createImageKHR(EGL_NO_CONTEXT, EGL_LINUX_DMA_BUF_EXT, nullptr, attr);
+ if (mImage == EGL_NO_IMAGE_KHR)
+ {
+ return false;
+ }
+
+ FunctionsGL *gl = mDisplay->mFunctionsGL;
+ StateManagerGL *sm = mDisplay->getRenderer()->getStateManager();
+
+ gl->genRenderbuffers(1, &mColorBuffer);
+ sm->bindRenderbuffer(GL_RENDERBUFFER, mColorBuffer);
+ gl->eglImageTargetRenderbufferStorageOES(GL_RENDERBUFFER, mImage);
+
+ sm->bindFramebuffer(GL_FRAMEBUFFER, mGLFB);
+ gl->framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0_EXT, GL_RENDERBUFFER,
+ mColorBuffer);
+
+ if (mDepthBits || mStencilBits)
+ {
+ gl->genRenderbuffers(1, &mDSBuffer);
+ sm->bindRenderbuffer(GL_RENDERBUFFER, mDSBuffer);
+ gl->renderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8_OES, width, height);
+ }
+
+ if (mDepthBits)
+ {
+ gl->framebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER,
+ mDSBuffer);
+ }
+
+ if (mStencilBits)
+ {
+ gl->framebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER,
+ mDSBuffer);
+ }
+
+ mWidth = width;
+ mHeight = height;
+ return true;
+}
+
+bool DisplayOzone::Buffer::initialize(const NativeWindow *native)
+{
+ mNative = native;
+ mDisplay->mFunctionsGL->genFramebuffers(1, &mGLFB);
+ return resize(native->width, native->height);
+}
+
+bool DisplayOzone::Buffer::initialize(int width, int height)
+{
+ mDisplay->mFunctionsGL->genFramebuffers(1, &mGLFB);
+ return resize(width, height);
+}
+
+void DisplayOzone::Buffer::bindTexImage()
+{
+ mDisplay->mFunctionsGL->eglImageTargetTexture2DOES(GL_TEXTURE_2D, mImage);
+}
+
+GLuint DisplayOzone::Buffer::getTexture()
+{
+ // TODO(fjhenigman) Try not to create a new texture every time. That already works on Intel
+ // and should work on Mali with proper fences.
+ FunctionsGL *gl = mDisplay->mFunctionsGL;
+ StateManagerGL *sm = mDisplay->getRenderer()->getStateManager();
+
+ gl->genTextures(1, &mTexture);
+ sm->bindTexture(GL_TEXTURE_2D, mTexture);
+ gl->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ gl->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ gl->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ gl->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+ ASSERT(mImage != EGL_NO_IMAGE_KHR);
+ gl->eglImageTargetTexture2DOES(GL_TEXTURE_2D, mImage);
+ return mTexture;
+}
+
+uint32_t DisplayOzone::Buffer::getDRMFB()
+{
+ if (!mHasDRMFB)
+ {
+ int fd = gbm_device_get_fd(mDisplay->mGBM);
+ uint32_t handles[4] = {gbm_bo_get_handle(mBO).u32};
+ uint32_t pitches[4] = {gbm_bo_get_stride(mBO)};
+ uint32_t offsets[4] = {0};
+ if (drmModeAddFB2(fd, mWidth, mHeight, mDRMFormatFB, handles, pitches, offsets, &mDRMFB, 0))
+ {
+ std::cerr << "drmModeAddFB2 failed" << std::endl;
+ }
+ else
+ {
+ mHasDRMFB = true;
+ }
+ }
+
+ return mDRMFB;
+}
+
+FramebufferGL *DisplayOzone::Buffer::framebufferGL(const gl::FramebufferState &state)
+{
+ return new FramebufferGL(
+ mGLFB, state, mDisplay->mFunctionsGL, mDisplay->getRenderer()->getWorkarounds(),
+ mDisplay->getRenderer()->getBlitter(), mDisplay->getRenderer()->getStateManager());
+}
+
+void DisplayOzone::Buffer::present()
+{
+ if (mNative)
+ {
+ if (mNative->visible)
+ {
+ mDisplay->drawBuffer(this);
+ }
+ resize(mNative->width, mNative->height);
+ }
+}
+
+DisplayOzone::DisplayOzone()
+ : DisplayEGL(),
+ mSwapControl(SwapControl::ABSENT),
+ mMinSwapInterval(0),
+ mMaxSwapInterval(0),
+ mCurrentSwapInterval(-1),
+ mGBM(nullptr),
+ mConnector(nullptr),
+ mMode(nullptr),
+ mCRTC(nullptr),
+ mSetCRTC(true),
+ mWidth(0),
+ mHeight(0),
+ mScanning(nullptr),
+ mPending(nullptr),
+ mDrawing(nullptr),
+ mUnused(nullptr),
+ mProgram(0),
+ mVertexShader(0),
+ mFragmentShader(0),
+ mVertexBuffer(0),
+ mIndexBuffer(0),
+ mCenterUniform(0),
+ mWindowSizeUniform(0),
+ mBorderSizeUniform(0),
+ mDepthUniform(0)
+{
+}
+
+DisplayOzone::~DisplayOzone()
+{
+}
+
+egl::Error DisplayOzone::initialize(egl::Display *display)
+{
+ int fd;
+ char deviceName[30];
+ drmModeResPtr resources = nullptr;
+
+ for (int i = 0; i < 9; ++i)
+ {
+ snprintf(deviceName, sizeof(deviceName), "/dev/dri/card%d", i);
+ fd = open(deviceName, O_RDWR | O_CLOEXEC);
+ if (fd >= 0)
+ {
+ resources = drmModeGetResources(fd);
+ if (resources)
+ {
+ if (resources->count_connectors > 0)
+ {
+ break;
+ }
+ drmModeFreeResources(resources);
+ resources = nullptr;
+ }
+ close(fd);
+ }
+ }
+ if (!resources)
+ {
+ return egl::Error(EGL_NOT_INITIALIZED, "Could not open drm device.");
+ }
+
+ mGBM = gbm_create_device(fd);
+ if (!mGBM)
+ {
+ close(fd);
+ drmModeFreeResources(resources);
+ return egl::Error(EGL_NOT_INITIALIZED, "Could not create gbm device.");
+ }
+
+ mConnector = nullptr;
+ bool monitorConnected = false;
+ for (int i = 0; !mCRTC && i < resources->count_connectors; ++i)
+ {
+ drmModeFreeConnector(mConnector);
+ mConnector = drmModeGetConnector(fd, resources->connectors[i]);
+ if (!mConnector || mConnector->connection != DRM_MODE_CONNECTED)
+ {
+ continue;
+ }
+ monitorConnected = true;
+ mMode = ChooseMode(mConnector);
+ if (!mMode)
+ {
+ continue;
+ }
+ int n = ChooseCRTC(fd, mConnector);
+ if (n < 0)
+ {
+ continue;
+ }
+ mCRTC = drmModeGetCrtc(fd, resources->crtcs[n]);
+ }
+ drmModeFreeResources(resources);
+
+ if (mCRTC)
+ {
+ mWidth = mMode->hdisplay;
+ mHeight = mMode->vdisplay;
+ }
+ else if (!monitorConnected)
+ {
+ // Even though there is no monitor to show it, we still do
+ // everything the same as if there were one, so we need an
+ // arbitrary size for our buffers.
+ mWidth = 1280;
+ mHeight = 1024;
+ }
+ else
+ {
+ return egl::Error(EGL_NOT_INITIALIZED, "Failed to choose mode/crtc.");
+ }
+
+ // ANGLE builds its executables with an RPATH so they pull in ANGLE's libGL and libEGL.
+ // Here we need to open the native libEGL. An absolute path would work, but then we
+ // couldn't use LD_LIBRARY_PATH which is often useful during development. Instead we take
+ // advantage of the fact that the system lib is available under multiple names (for example
+ // with a .1 suffix) while Angle only installs libEGL.so.
+ FunctionsEGLDL *egl = new FunctionsEGLDL();
+ mEGL = egl;
+ ANGLE_TRY(egl->initialize(display->getNativeDisplayId(), "libEGL.so.1"));
+
+ const char *necessaryExtensions[] = {
+ "EGL_KHR_image_base", "EGL_EXT_image_dma_buf_import", "EGL_KHR_surfaceless_context",
+ };
+ for (auto &ext : necessaryExtensions)
+ {
+ if (!mEGL->hasExtension(ext))
+ {
+ return egl::Error(EGL_NOT_INITIALIZED, "need %s", ext);
+ }
+ }
+
+ if (mEGL->hasExtension("EGL_MESA_configless_context"))
+ {
+ mConfig = EGL_NO_CONFIG_MESA;
+ }
+ else
+ {
+ // clang-format off
+ const EGLint attrib[] =
+ {
+ // We want RGBA8 and DEPTH24_STENCIL8
+ EGL_RED_SIZE, 8,
+ EGL_GREEN_SIZE, 8,
+ EGL_BLUE_SIZE, 8,
+ EGL_ALPHA_SIZE, 8,
+ EGL_DEPTH_SIZE, 24,
+ EGL_STENCIL_SIZE, 8,
+ EGL_NONE,
+ };
+ // clang-format on
+ EGLint numConfig;
+ EGLConfig config[1];
+ if (!mEGL->chooseConfig(attrib, config, 1, &numConfig) || numConfig < 1)
+ {
+ return egl::Error(EGL_NOT_INITIALIZED, "Could not get EGL config.");
+ }
+ mConfig = config[0];
+ }
+
+ ANGLE_TRY(initializeContext(display->getAttributeMap()));
+
+ if (!mEGL->makeCurrent(EGL_NO_SURFACE, mContext))
+ {
+ return egl::Error(EGL_NOT_INITIALIZED, "Could not make context current.");
+ }
+
+ mFunctionsGL = mEGL->makeFunctionsGL();
+ mFunctionsGL->initialize();
+
+ return DisplayGL::initialize(display);
+}
+
+void DisplayOzone::pageFlipHandler(int fd,
+ unsigned int sequence,
+ unsigned int tv_sec,
+ unsigned int tv_usec,
+ void *data)
+{
+ DisplayOzone *display = reinterpret_cast<DisplayOzone *>(data);
+ uint64_t tv = tv_sec;
+ display->pageFlipHandler(sequence, tv * 1000000 + tv_usec);
+}
+
+void DisplayOzone::pageFlipHandler(unsigned int sequence, uint64_t tv)
+{
+ ASSERT(mPending);
+ mUnused = mScanning;
+ mScanning = mPending;
+ mPending = nullptr;
+}
+
+void DisplayOzone::presentScreen()
+{
+ if (!mCRTC)
+ {
+ // no monitor
+ return;
+ }
+
+ // see if pending flip has finished, without blocking
+ int fd = gbm_device_get_fd(mGBM);
+ if (mPending)
+ {
+ pollfd pfd;
+ pfd.fd = fd;
+ pfd.events = POLLIN;
+ if (poll(&pfd, 1, 0) < 0)
+ {
+ std::cerr << "poll failed: " << errno << " " << strerror(errno) << std::endl;
+ }
+ if (pfd.revents & POLLIN)
+ {
+ drmEventContext event;
+ event.version = DRM_EVENT_CONTEXT_VERSION;
+ event.page_flip_handler = pageFlipHandler;
+ drmHandleEvent(fd, &event);
+ }
+ }
+
+ // if pending flip has finished, schedule next one
+ if (!mPending && mDrawing)
+ {
+ flushGL();
+ if (mSetCRTC)
+ {
+ if (drmModeSetCrtc(fd, mCRTC->crtc_id, mDrawing->getDRMFB(), 0, 0,
+ &mConnector->connector_id, 1, mMode))
+ {
+ std::cerr << "set crtc failed: " << errno << " " << strerror(errno) << std::endl;
+ }
+ mSetCRTC = false;
+ }
+ if (drmModePageFlip(fd, mCRTC->crtc_id, mDrawing->getDRMFB(), DRM_MODE_PAGE_FLIP_EVENT,
+ this))
+ {
+ std::cerr << "page flip failed: " << errno << " " << strerror(errno) << std::endl;
+ }
+ mPending = mDrawing;
+ mDrawing = nullptr;
+ }
+}
+
+GLuint DisplayOzone::makeShader(GLuint type, const char *src)
+{
+ FunctionsGL *gl = mFunctionsGL;
+ GLuint shader = gl->createShader(type);
+ gl->shaderSource(shader, 1, &src, nullptr);
+ gl->compileShader(shader);
+
+ GLchar buf[999];
+ GLsizei len;
+ GLint compiled;
+ gl->getShaderInfoLog(shader, sizeof(buf), &len, buf);
+ gl->getShaderiv(shader, GL_COMPILE_STATUS, &compiled);
+ if (compiled != GL_TRUE)
+ {
+ ANGLEPlatformCurrent()->logError("DisplayOzone shader compilation error:");
+ ANGLEPlatformCurrent()->logError(buf);
+ }
+
+ return shader;
+}
+
+void DisplayOzone::drawWithTexture(Buffer *buffer)
+{
+ FunctionsGL *gl = mFunctionsGL;
+ StateManagerGL *sm = getRenderer()->getStateManager();
+
+ if (!mProgram)
+ {
+ const GLchar *vertexSource =
+ "#version 100\n"
+ "attribute vec3 vertex;\n"
+ "uniform vec2 center;\n"
+ "uniform vec2 windowSize;\n"
+ "uniform vec2 borderSize;\n"
+ "uniform float depth;\n"
+ "varying vec3 texCoord;\n"
+ "void main()\n"
+ "{\n"
+ " vec2 pos = vertex.xy * (windowSize + borderSize * vertex.z);\n"
+ " gl_Position = vec4(center + pos, depth, 1);\n"
+ " texCoord = vec3(pos / windowSize * vec2(.5, -.5) + vec2(.5, .5), vertex.z);\n"
+ "}\n";
+
+ const GLchar *fragmentSource =
+ "#version 100\n"
+ "precision mediump float;\n"
+ "uniform sampler2D tex;\n"
+ "varying vec3 texCoord;\n"
+ "void main()\n"
+ "{\n"
+ " if (texCoord.z > 0.)\n"
+ " {\n"
+ " float c = abs((texCoord.z * 2.) - 1.);\n"
+ " gl_FragColor = vec4(c, c, c, 1);\n"
+ " }\n"
+ " else\n"
+ " {\n"
+ " gl_FragColor = texture2D(tex, texCoord.xy);\n"
+ " }\n"
+ "}\n";
+
+ mVertexShader = makeShader(GL_VERTEX_SHADER, vertexSource);
+ mFragmentShader = makeShader(GL_FRAGMENT_SHADER, fragmentSource);
+ mProgram = gl->createProgram();
+ gl->attachShader(mProgram, mVertexShader);
+ gl->attachShader(mProgram, mFragmentShader);
+ gl->bindAttribLocation(mProgram, 0, "vertex");
+ gl->linkProgram(mProgram);
+ GLint linked;
+ gl->getProgramiv(mProgram, GL_LINK_STATUS, &linked);
+ ASSERT(linked);
+ mCenterUniform = gl->getUniformLocation(mProgram, "center");
+ mWindowSizeUniform = gl->getUniformLocation(mProgram, "windowSize");
+ mBorderSizeUniform = gl->getUniformLocation(mProgram, "borderSize");
+ mDepthUniform = gl->getUniformLocation(mProgram, "depth");
+ GLint texUniform = gl->getUniformLocation(mProgram, "tex");
+ sm->useProgram(mProgram);
+ gl->uniform1i(texUniform, 0);
+
+ // clang-format off
+ const GLfloat vertices[] =
+ {
+ // window corners, and window border inside corners
+ 1, -1, 0,
+ -1, -1, 0,
+ 1, 1, 0,
+ -1, 1, 0,
+ // window border outside corners
+ 1, -1, 1,
+ -1, -1, 1,
+ 1, 1, 1,
+ -1, 1, 1,
+ };
+ // clang-format on
+ gl->genBuffers(1, &mVertexBuffer);
+ sm->bindBuffer(GL_ARRAY_BUFFER, mVertexBuffer);
+ gl->bufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
+
+ // window border triangle strip
+ const GLuint borderStrip[] = {5, 0, 4, 2, 6, 3, 7, 1, 5, 0};
+
+ gl->genBuffers(1, &mIndexBuffer);
+ sm->bindBuffer(GL_ELEMENT_ARRAY_BUFFER, mIndexBuffer);
+ gl->bufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(borderStrip), borderStrip, GL_STATIC_DRAW);
+ }
+ else
+ {
+ sm->useProgram(mProgram);
+ sm->bindBuffer(GL_ARRAY_BUFFER, mVertexBuffer);
+ sm->bindBuffer(GL_ELEMENT_ARRAY_BUFFER, mIndexBuffer);
+ }
+
+ // convert from pixels to "-1 to 1" space
+ const NativeWindow *n = buffer->getNative();
+ double x = n->x * 2. / mWidth - 1;
+ double y = n->y * 2. / mHeight - 1;
+ double halfw = n->width * 1. / mWidth;
+ double halfh = n->height * 1. / mHeight;
+ double borderw = n->borderWidth * 2. / mWidth;
+ double borderh = n->borderHeight * 2. / mHeight;
+
+ gl->uniform2f(mCenterUniform, x + halfw, y + halfh);
+ gl->uniform2f(mWindowSizeUniform, halfw, halfh);
+ gl->uniform2f(mBorderSizeUniform, borderw, borderh);
+ gl->uniform1f(mDepthUniform, n->depth / 1e6);
+
+ sm->setBlendEnabled(false);
+ sm->setCullFaceEnabled(false);
+ sm->setStencilTestEnabled(false);
+ sm->setScissorTestEnabled(false);
+ sm->setDepthTestEnabled(true);
+ sm->setColorMask(true, true, true, true);
+ sm->setDepthMask(true);
+ sm->setDepthRange(0, 1);
+ sm->setDepthFunc(GL_LESS);
+ sm->setViewport(gl::Rectangle(0, 0, mWidth, mHeight));
+ sm->activeTexture(0);
+ GLuint tex = buffer->getTexture();
+ sm->bindTexture(GL_TEXTURE_2D, tex);
+ gl->vertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
+ gl->enableVertexAttribArray(0);
+ sm->bindFramebuffer(GL_DRAW_FRAMEBUFFER, mDrawing->getGLFB());
+ gl->drawArrays(GL_TRIANGLE_STRIP, 0, 4);
+ gl->drawElements(GL_TRIANGLE_STRIP, 10, GL_UNSIGNED_INT, 0);
+ sm->deleteTexture(tex);
+}
+
+void DisplayOzone::drawBuffer(Buffer *buffer)
+{
+ if (!mDrawing)
+ {
+ // get buffer on which to draw window
+ if (mUnused)
+ {
+ mDrawing = mUnused;
+ mUnused = nullptr;
+ }
+ else
+ {
+ mDrawing = new Buffer(this, GBM_BO_USE_RENDERING | GBM_BO_USE_SCANOUT,
+ GBM_FORMAT_ARGB8888, DRM_FORMAT_ARGB8888, DRM_FORMAT_XRGB8888,
+ true, true); // XXX shouldn't need stencil
+ if (!mDrawing || !mDrawing->initialize(mWidth, mHeight))
+ {
+ return;
+ }
+ }
+
+ StateManagerGL *sm = getRenderer()->getStateManager();
+ sm->bindFramebuffer(GL_DRAW_FRAMEBUFFER, mDrawing->getGLFB());
+ sm->setClearColor(gl::ColorF(0, 0, 0, 1));
+ sm->setClearDepth(1);
+ sm->setScissorTestEnabled(false);
+ sm->setColorMask(true, true, true, true);
+ sm->setDepthMask(true);
+ mFunctionsGL->clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+ }
+
+ drawWithTexture(buffer);
+ presentScreen();
+}
+
+void DisplayOzone::flushGL()
+{
+ mFunctionsGL->flush();
+ if (mEGL->hasExtension("EGL_KHR_fence_sync"))
+ {
+ const EGLint attrib[] = {EGL_SYNC_CONDITION_KHR,
+ EGL_SYNC_PRIOR_COMMANDS_IMPLICIT_EXTERNAL_ARM, EGL_NONE};
+ EGLSyncKHR fence = mEGL->createSyncKHR(EGL_SYNC_FENCE_KHR, attrib);
+ if (fence)
+ {
+ // TODO(fjhenigman) Figure out the right way to use fences on Mali GPU
+ // to maximize throughput and avoid hangs when a program is interrupted.
+ // This busy wait was an attempt to reduce hangs when interrupted by SIGINT,
+ // but we still get some.
+ for (;;)
+ {
+ EGLint r = mEGL->clientWaitSyncKHR(fence, EGL_SYNC_FLUSH_COMMANDS_BIT_KHR, 0);
+ if (r != EGL_TIMEOUT_EXPIRED_KHR)
+ {
+ break;
+ }
+ usleep(99);
+ }
+ mEGL->destroySyncKHR(fence);
+ return;
+ }
+ }
+}
+
+void DisplayOzone::terminate()
+{
+ SafeDelete(mScanning);
+ SafeDelete(mPending);
+ SafeDelete(mDrawing);
+ SafeDelete(mUnused);
+
+ if (mProgram)
+ {
+ mFunctionsGL->deleteProgram(mProgram);
+ mFunctionsGL->deleteShader(mVertexShader);
+ mFunctionsGL->deleteShader(mFragmentShader);
+ mFunctionsGL->deleteBuffers(1, &mVertexBuffer);
+ mFunctionsGL->deleteBuffers(1, &mIndexBuffer);
+ mProgram = 0;
+ }
+
+ DisplayGL::terminate();
+
+ if (mContext)
+ {
+ // Mesa might crash if you terminate EGL with a context current
+ // then re-initialize EGL, so make our context not current.
+ mEGL->makeCurrent(EGL_NO_SURFACE, EGL_NO_CONTEXT);
+ mEGL->destroyContext(mContext);
+ mContext = nullptr;
+ }
+
+ SafeDelete(mFunctionsGL);
+
+ if (mEGL)
+ {
+ mEGL->terminate();
+ SafeDelete(mEGL);
+ }
+
+ drmModeFreeCrtc(mCRTC);
+
+ if (mGBM)
+ {
+ int fd = gbm_device_get_fd(mGBM);
+ gbm_device_destroy(mGBM);
+ mGBM = nullptr;
+ close(fd);
+ }
+}
+
+SurfaceImpl *DisplayOzone::createWindowSurface(const egl::SurfaceState &state,
+ const egl::Config *configuration,
+ EGLNativeWindowType window,
+ const egl::AttributeMap &attribs)
+{
+ Buffer *buffer = new Buffer(this, GBM_BO_USE_RENDERING, GBM_FORMAT_ARGB8888,
+ DRM_FORMAT_ARGB8888, DRM_FORMAT_XRGB8888, true, true);
+ if (!buffer || !buffer->initialize(reinterpret_cast<const NativeWindow *>(window)))
+ {
+ return nullptr;
+ }
+ return new SurfaceOzone(state, getRenderer(), buffer);
+}
+
+SurfaceImpl *DisplayOzone::createPbufferSurface(const egl::SurfaceState &state,
+ const egl::Config *configuration,
+ const egl::AttributeMap &attribs)
+{
+ EGLAttrib width = attribs.get(EGL_WIDTH, 0);
+ EGLAttrib height = attribs.get(EGL_HEIGHT, 0);
+ Buffer *buffer = new Buffer(this, GBM_BO_USE_RENDERING, GBM_FORMAT_ARGB8888,
+ DRM_FORMAT_ARGB8888, DRM_FORMAT_XRGB8888, true, true);
+ if (!buffer || !buffer->initialize(width, height))
+ {
+ return nullptr;
+ }
+ return new SurfaceOzone(state, getRenderer(), buffer);
+}
+
+SurfaceImpl *DisplayOzone::createPbufferFromClientBuffer(const egl::SurfaceState &state,
+ const egl::Config *configuration,
+ EGLenum buftype,
+ EGLClientBuffer clientBuffer,
+ const egl::AttributeMap &attribs)
+{
+ UNIMPLEMENTED();
+ return nullptr;
+}
+
+SurfaceImpl *DisplayOzone::createPixmapSurface(const egl::SurfaceState &state,
+ const egl::Config *configuration,
+ NativePixmapType nativePixmap,
+ const egl::AttributeMap &attribs)
+{
+ UNIMPLEMENTED();
+ return nullptr;
+}
+
+egl::Error DisplayOzone::getDevice(DeviceImpl **device)
+{
+ UNIMPLEMENTED();
+ return egl::Error(EGL_BAD_DISPLAY);
+}
+
+egl::ConfigSet DisplayOzone::generateConfigs()
+{
+ egl::ConfigSet configs;
+
+ egl::Config config;
+ config.redSize = 8;
+ config.greenSize = 8;
+ config.blueSize = 8;
+ config.alphaSize = 8;
+ config.depthSize = 24;
+ config.stencilSize = 8;
+ config.bindToTextureRGBA = EGL_TRUE;
+ config.renderableType = EGL_OPENGL_ES2_BIT;
+ config.surfaceType = EGL_WINDOW_BIT | EGL_PBUFFER_BIT;
+
+ configs.add(config);
+ return configs;
+}
+
+bool DisplayOzone::testDeviceLost()
+{
+ return false;
+}
+
+egl::Error DisplayOzone::restoreLostDevice()
+{
+ UNIMPLEMENTED();
+ return egl::Error(EGL_BAD_DISPLAY);
+}
+
+bool DisplayOzone::isValidNativeWindow(EGLNativeWindowType window) const
+{
+ return true;
+}
+
+egl::Error DisplayOzone::getDriverVersion(std::string *version) const
+{
+ *version = "";
+ return egl::Error(EGL_SUCCESS);
+}
+
+egl::Error DisplayOzone::waitClient() const
+{
+ // TODO(fjhenigman) Implement this.
+ return egl::Error(EGL_SUCCESS);
+}
+
+egl::Error DisplayOzone::waitNative(EGLint engine,
+ egl::Surface *drawSurface,
+ egl::Surface *readSurface) const
+{
+ // TODO(fjhenigman) Implement this.
+ return egl::Error(EGL_SUCCESS);
+}
+
+void DisplayOzone::setSwapInterval(EGLSurface drawable, SwapControlData *data)
+{
+ ASSERT(data != nullptr);
+}
+
+} // namespace rx
diff --git a/gfx/angle/src/libANGLE/renderer/gl/egl/ozone/DisplayOzone.h b/gfx/angle/src/libANGLE/renderer/gl/egl/ozone/DisplayOzone.h
new file mode 100755
index 000000000..77c669314
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/gl/egl/ozone/DisplayOzone.h
@@ -0,0 +1,211 @@
+//
+// Copyright (c) 2016 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.
+//
+
+// DisplayOzone.h: Ozone implementation of egl::Display
+
+#ifndef LIBANGLE_RENDERER_GL_EGL_OZONE_DISPLAYOZONE_H_
+#define LIBANGLE_RENDERER_GL_EGL_OZONE_DISPLAYOZONE_H_
+
+#include <xf86drm.h>
+#include <xf86drmMode.h>
+
+#include <string>
+
+#include "libANGLE/renderer/gl/egl/DisplayEGL.h"
+
+struct gbm_device;
+struct gbm_bo;
+
+namespace gl
+{
+class FramebufferState;
+}
+
+namespace rx
+{
+
+class FramebufferGL;
+
+// TODO(fjhenigman) Implement swap control. The following struct will be used for that.
+// State-tracking data for the swap control to allow DisplayOzone to remember per
+// drawable information for swap control.
+struct SwapControlData final
+{
+ SwapControlData();
+
+ // Set by the drawable
+ int targetSwapInterval;
+
+ // DisplayOzone-side state-tracking
+ int maxSwapInterval;
+ int currentSwapInterval;
+};
+
+class DisplayOzone final : public DisplayEGL
+{
+ public:
+ struct NativeWindow
+ {
+ int32_t x;
+ int32_t y;
+ int32_t width;
+ int32_t height;
+ int32_t borderWidth;
+ int32_t borderHeight;
+ int32_t visible;
+ int32_t depth;
+ };
+
+ class Buffer final : angle::NonCopyable
+ {
+ public:
+ Buffer(DisplayOzone *display,
+ uint32_t useFlags,
+ uint32_t gbmFormat,
+ uint32_t drmFormat,
+ uint32_t drmFormatFB,
+ int depthBits,
+ int stencilBits);
+
+ ~Buffer();
+ bool initialize(const NativeWindow *window);
+ bool initialize(int32_t width, int32_t height);
+ void reset();
+ bool resize(int32_t width, int32_t height);
+ FramebufferGL *framebufferGL(const gl::FramebufferState &state);
+ void present();
+ uint32_t getDRMFB();
+ void bindTexImage();
+ GLuint getTexture();
+ int32_t getWidth() const { return mWidth; }
+ int32_t getHeight() const { return mHeight; }
+ GLuint getGLFB() const { return mGLFB; }
+ const NativeWindow *getNative() const { return mNative; }
+
+ private:
+ DisplayOzone *mDisplay;
+ const NativeWindow *mNative;
+ int mWidth;
+ int mHeight;
+ const int mDepthBits;
+ const int mStencilBits;
+ const uint32_t mUseFlags;
+ const uint32_t mGBMFormat;
+ const uint32_t mDRMFormat;
+ const uint32_t mDRMFormatFB;
+ gbm_bo *mBO;
+ int mDMABuf;
+ bool mHasDRMFB;
+ uint32_t mDRMFB;
+ EGLImageKHR mImage;
+ GLuint mColorBuffer;
+ GLuint mDSBuffer;
+ GLuint mGLFB;
+ GLuint mTexture;
+ };
+
+ DisplayOzone();
+ ~DisplayOzone() override;
+
+ egl::Error initialize(egl::Display *display) override;
+ void terminate() override;
+
+ SurfaceImpl *createWindowSurface(const egl::SurfaceState &state,
+ const egl::Config *configuration,
+ EGLNativeWindowType window,
+ const egl::AttributeMap &attribs) override;
+ SurfaceImpl *createPbufferSurface(const egl::SurfaceState &state,
+ const egl::Config *configuration,
+ const egl::AttributeMap &attribs) override;
+ SurfaceImpl *createPbufferFromClientBuffer(const egl::SurfaceState &state,
+ const egl::Config *configuration,
+ EGLenum buftype,
+ EGLClientBuffer clientBuffer,
+ const egl::AttributeMap &attribs) override;
+ SurfaceImpl *createPixmapSurface(const egl::SurfaceState &state,
+ const egl::Config *configuration,
+ NativePixmapType nativePixmap,
+ const egl::AttributeMap &attribs) override;
+
+ egl::ConfigSet generateConfigs() override;
+
+ bool testDeviceLost() override;
+ egl::Error restoreLostDevice() override;
+
+ bool isValidNativeWindow(EGLNativeWindowType window) const override;
+
+ egl::Error getDevice(DeviceImpl **device) override;
+
+ egl::Error waitClient() const override;
+ egl::Error waitNative(EGLint engine,
+ egl::Surface *drawSurface,
+ egl::Surface *readSurface) const override;
+
+ // TODO(fjhenigman) Implement this.
+ // Swap interval can be set globally or per drawable.
+ // This function will make sure the drawable's swap interval is the
+ // one required so that the subsequent swapBuffers acts as expected.
+ void setSwapInterval(EGLSurface drawable, SwapControlData *data);
+
+ egl::Error getDriverVersion(std::string *version) const override;
+
+ private:
+ GLuint makeShader(GLuint type, const char *src);
+ void drawBuffer(Buffer *buffer);
+ void drawWithBlit(Buffer *buffer);
+ void drawWithTexture(Buffer *buffer);
+ void flushGL();
+ void presentScreen();
+ static void pageFlipHandler(int fd,
+ unsigned int sequence,
+ unsigned int tv_sec,
+ unsigned int tv_usec,
+ void *data);
+ void pageFlipHandler(unsigned int sequence, uint64_t tv);
+
+ // TODO(fjhenigman) Implement swap control. The following stuff will be used for that.
+ enum class SwapControl
+ {
+ ABSENT,
+ EXT,
+ MESA,
+ SGI,
+ };
+ SwapControl mSwapControl;
+ int mMinSwapInterval;
+ int mMaxSwapInterval;
+ int mCurrentSwapInterval;
+
+ gbm_device *mGBM;
+ drmModeConnectorPtr mConnector;
+ drmModeModeInfoPtr mMode;
+ drmModeCrtcPtr mCRTC;
+ bool mSetCRTC;
+
+ int32_t mWidth;
+ int32_t mHeight;
+
+ // Three scanout buffers cycle through four states. The state of a buffer
+ // is indicated by which of these pointers points to it.
+ // TODO(fjhenigman) It might be simpler/clearer to use a ring buffer.
+ Buffer *mScanning;
+ Buffer *mPending;
+ Buffer *mDrawing;
+ Buffer *mUnused;
+
+ GLuint mProgram;
+ GLuint mVertexShader;
+ GLuint mFragmentShader;
+ GLuint mVertexBuffer;
+ GLuint mIndexBuffer;
+ GLint mCenterUniform;
+ GLint mWindowSizeUniform;
+ GLint mBorderSizeUniform;
+ GLint mDepthUniform;
+};
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_GL_EGL_OZONE_DISPLAYOZONE_H_
diff --git a/gfx/angle/src/libANGLE/renderer/gl/egl/ozone/SurfaceOzone.cpp b/gfx/angle/src/libANGLE/renderer/gl/egl/ozone/SurfaceOzone.cpp
new file mode 100755
index 000000000..614fed0fd
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/gl/egl/ozone/SurfaceOzone.cpp
@@ -0,0 +1,98 @@
+//
+// Copyright (c) 2016 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.
+//
+
+// SurfaceOzone.cpp: Ozone implementation of egl::SurfaceGL
+
+#include "libANGLE/renderer/gl/egl/ozone/SurfaceOzone.h"
+
+#include "libANGLE/renderer/gl/FramebufferGL.h"
+#include "libANGLE/renderer/gl/egl/ozone/DisplayOzone.h"
+
+namespace rx
+{
+
+SurfaceOzone::SurfaceOzone(const egl::SurfaceState &state,
+ RendererGL *renderer,
+ DisplayOzone::Buffer *buffer)
+ : SurfaceGL(state, renderer), mBuffer(buffer)
+{
+}
+
+SurfaceOzone::~SurfaceOzone()
+{
+ delete mBuffer;
+}
+
+egl::Error SurfaceOzone::initialize()
+{
+ return egl::Error(EGL_SUCCESS);
+}
+
+FramebufferImpl *SurfaceOzone::createDefaultFramebuffer(const gl::FramebufferState &state)
+{
+ return mBuffer->framebufferGL(state);
+}
+
+egl::Error SurfaceOzone::makeCurrent()
+{
+ return egl::Error(EGL_SUCCESS);
+}
+
+egl::Error SurfaceOzone::swap()
+{
+ mBuffer->present();
+ return egl::Error(EGL_SUCCESS);
+}
+
+egl::Error SurfaceOzone::postSubBuffer(EGLint x, EGLint y, EGLint width, EGLint height)
+{
+ UNIMPLEMENTED();
+ return egl::Error(EGL_SUCCESS);
+}
+
+egl::Error SurfaceOzone::querySurfacePointerANGLE(EGLint attribute, void **value)
+{
+ UNIMPLEMENTED();
+ return egl::Error(EGL_SUCCESS);
+}
+
+egl::Error SurfaceOzone::bindTexImage(gl::Texture *texture, EGLint buffer)
+{
+ mBuffer->bindTexImage();
+ return egl::Error(EGL_SUCCESS);
+}
+
+egl::Error SurfaceOzone::releaseTexImage(EGLint buffer)
+{
+ return egl::Error(EGL_SUCCESS);
+}
+
+void SurfaceOzone::setSwapInterval(EGLint interval)
+{
+ mSwapControl.targetSwapInterval = interval;
+}
+
+EGLint SurfaceOzone::getWidth() const
+{
+ return mBuffer->getWidth();
+}
+
+EGLint SurfaceOzone::getHeight() const
+{
+ return mBuffer->getHeight();
+}
+
+EGLint SurfaceOzone::isPostSubBufferSupported() const
+{
+ UNIMPLEMENTED();
+ return EGL_FALSE;
+}
+
+EGLint SurfaceOzone::getSwapBehavior() const
+{
+ return EGL_BUFFER_PRESERVED;
+}
+} // namespace rx
diff --git a/gfx/angle/src/libANGLE/renderer/gl/egl/ozone/SurfaceOzone.h b/gfx/angle/src/libANGLE/renderer/gl/egl/ozone/SurfaceOzone.h
new file mode 100755
index 000000000..24b8ec8c9
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/gl/egl/ozone/SurfaceOzone.h
@@ -0,0 +1,52 @@
+//
+// Copyright (c) 2016 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.
+//
+
+// SurfaceOzone.h: Ozone implementation of egl::SurfaceGL
+
+#ifndef LIBANGLE_RENDERER_GL_EGL_OZONE_SURFACEOZONE_H_
+#define LIBANGLE_RENDERER_GL_EGL_OZONE_SURFACEOZONE_H_
+
+#include "libANGLE/renderer/gl/SurfaceGL.h"
+#include "libANGLE/renderer/gl/egl/ozone/DisplayOzone.h"
+
+namespace rx
+{
+
+class SurfaceOzone : public SurfaceGL
+{
+ public:
+ SurfaceOzone(const egl::SurfaceState &state,
+ RendererGL *renderer,
+ DisplayOzone::Buffer *buffer);
+ ~SurfaceOzone() override;
+
+ FramebufferImpl *createDefaultFramebuffer(const gl::FramebufferState &state) override;
+
+ egl::Error initialize() override;
+ egl::Error makeCurrent() override;
+
+ egl::Error swap() override;
+ egl::Error postSubBuffer(EGLint x, EGLint y, EGLint width, EGLint height) override;
+ egl::Error querySurfacePointerANGLE(EGLint attribute, void **value) override;
+ egl::Error bindTexImage(gl::Texture *texture, EGLint buffer) override;
+ egl::Error releaseTexImage(EGLint buffer) override;
+ void setSwapInterval(EGLint interval) override;
+
+ EGLint getWidth() const override;
+ EGLint getHeight() const override;
+
+ EGLint isPostSubBufferSupported() const override;
+ EGLint getSwapBehavior() const override;
+
+ private:
+ DisplayOzone::Buffer *mBuffer;
+
+ // TODO(fjhenigman) Implement swap control. This will be used for that.
+ SwapControlData mSwapControl;
+};
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_GL_EGL_OZONE_SURFACEOZONE_H_