Commit 043fcf18 by Peng Huang Committed by Commit Bot

Support create ANGLE EGLContext from an external EGLContext

For Android WebView, Android creates an EGLContext, EGLSurface and FBO, and makeCurrent on them, and then calls WebView draw function to draw the WebView content on the current EGLSurface or binded FBO. So to use ANGLE in WebView, this CL adds a way to create ANGLE EGLContext from an external EGLContext, and save and restore GL state in eglMakeCurrent(). Bug: angleproject:5509 Change-Id: I874986813117f125e23e975ea1adc51ac5b3a631 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2615239 Commit-Queue: Peng Huang <penghuang@chromium.org> Reviewed-by: 's avatarGeoff Lang <geofflang@chromium.org> Reviewed-by: 's avatarJonah Ryan-Davis <jonahr@google.com>
parent 5635dbb9
...@@ -337,6 +337,13 @@ EGLAPI EGLBoolean EGLAPIENTRY eglSwapBuffersWithFrameTokenANGLE(EGLDisplay dpy, ...@@ -337,6 +337,13 @@ EGLAPI EGLBoolean EGLAPIENTRY eglSwapBuffersWithFrameTokenANGLE(EGLDisplay dpy,
#define EGL_DISPLAY_SEMAPHORE_SHARE_GROUP_ANGLE 0x348D #define EGL_DISPLAY_SEMAPHORE_SHARE_GROUP_ANGLE 0x348D
#endif /* EGL_ANGLE_display_semaphore_share_group */ #endif /* EGL_ANGLE_display_semaphore_share_group */
#ifndef EGL_ANGLE_external_context_and_surface
#define EGL_ANGLE_external_context_and_surface 1
#define EGL_EXTERNAL_CONTEXT_ANGLE 0x348E
#define EGL_EXTERNAL_SURFACE_ANGLE 0x348F
#define EGL_EXTERNAL_CONTEXT_SAVE_STATE_ANGLE 0x3490
#endif /* EGL_ANGLE_external_context_and_surface */
// clang-format on // clang-format on
#endif // INCLUDE_EGL_EGLEXT_ANGLE_ #endif // INCLUDE_EGL_EGLEXT_ANGLE_
...@@ -1438,6 +1438,7 @@ std::vector<std::string> DisplayExtensions::getStrings() const ...@@ -1438,6 +1438,7 @@ std::vector<std::string> DisplayExtensions::getStrings() const
InsertExtensionString("EGL_NOK_texture_from_pixmap", textureFromPixmapNOK, &extensionStrings); InsertExtensionString("EGL_NOK_texture_from_pixmap", textureFromPixmapNOK, &extensionStrings);
InsertExtensionString("EGL_NV_robustness_video_memory_purge", robustnessVideoMemoryPurgeNV, &extensionStrings); InsertExtensionString("EGL_NV_robustness_video_memory_purge", robustnessVideoMemoryPurgeNV, &extensionStrings);
InsertExtensionString("EGL_KHR_reusable_sync", reusableSyncKHR, &extensionStrings); InsertExtensionString("EGL_KHR_reusable_sync", reusableSyncKHR, &extensionStrings);
InsertExtensionString("EGL_ANGLE_external_context_and_surface", externalContextAndSurface, &extensionStrings);
// clang-format on // clang-format on
return extensionStrings; return extensionStrings;
......
...@@ -1193,6 +1193,9 @@ struct DisplayExtensions ...@@ -1193,6 +1193,9 @@ struct DisplayExtensions
// EGL_KHR_reusable_sync // EGL_KHR_reusable_sync
bool reusableSyncKHR = false; bool reusableSyncKHR = false;
// EGL_ANGLE_external_context_and_surface
bool externalContextAndSurface = false;
}; };
struct DeviceExtensions struct DeviceExtensions
......
...@@ -281,6 +281,17 @@ bool IsColorMaskedOut(const BlendStateExt &blendStateExt, const GLint drawbuffer ...@@ -281,6 +281,17 @@ bool IsColorMaskedOut(const BlendStateExt &blendStateExt, const GLint drawbuffer
ASSERT(static_cast<size_t>(drawbuffer) < blendStateExt.mMaxDrawBuffers); ASSERT(static_cast<size_t>(drawbuffer) < blendStateExt.mMaxDrawBuffers);
return blendStateExt.getColorMaskIndexed(static_cast<size_t>(drawbuffer)) == 0; return blendStateExt.getColorMaskIndexed(static_cast<size_t>(drawbuffer)) == 0;
} }
bool GetIsExternal(const egl::AttributeMap &attribs)
{
return (attribs.get(EGL_EXTERNAL_CONTEXT_ANGLE, EGL_FALSE) == EGL_TRUE);
}
bool GetSaveAndRestoreState(const egl::AttributeMap &attribs)
{
return (attribs.get(EGL_EXTERNAL_CONTEXT_SAVE_STATE_ANGLE, EGL_FALSE) == EGL_TRUE);
}
} // anonymous namespace } // anonymous namespace
thread_local Context *gCurrentValidContext = nullptr; thread_local Context *gCurrentValidContext = nullptr;
...@@ -339,7 +350,10 @@ Context::Context(egl::Display *display, ...@@ -339,7 +350,10 @@ Context::Context(egl::Display *display,
mThreadPool(nullptr), mThreadPool(nullptr),
mFrameCapture(new angle::FrameCapture), mFrameCapture(new angle::FrameCapture),
mRefCount(0), mRefCount(0),
mOverlay(mImplementation.get()) mOverlay(mImplementation.get()),
mIsExternal(GetIsExternal(attribs)),
mSaveAndRestoreState(GetSaveAndRestoreState(attribs)),
mIsCurrent(false)
{ {
for (angle::SubjectIndex uboIndex = kUniformBuffer0SubjectIndex; for (angle::SubjectIndex uboIndex = kUniformBuffer0SubjectIndex;
uboIndex < kUniformBufferMaxSubjectIndex; ++uboIndex) uboIndex < kUniformBufferMaxSubjectIndex; ++uboIndex)
...@@ -675,6 +689,8 @@ egl::Error Context::makeCurrent(egl::Display *display, ...@@ -675,6 +689,8 @@ egl::Error Context::makeCurrent(egl::Display *display,
if (!mHasBeenCurrent) if (!mHasBeenCurrent)
{ {
ASSERT(!mIsCurrent);
initialize(); initialize();
initRendererString(); initRendererString();
initVersionStrings(); initVersionStrings();
......
...@@ -406,6 +406,10 @@ class Context final : public egl::LabeledObject, angle::NonCopyable, public angl ...@@ -406,6 +406,10 @@ class Context final : public egl::LabeledObject, angle::NonCopyable, public angl
bool isVertexArrayGenerated(VertexArrayID vertexArray) const; bool isVertexArrayGenerated(VertexArrayID vertexArray) const;
bool isTransformFeedbackGenerated(TransformFeedbackID transformFeedback) const; bool isTransformFeedbackGenerated(TransformFeedbackID transformFeedback) const;
bool isExternal() const { return mIsExternal; }
bool saveAndRestoreState() const { return mSaveAndRestoreState; }
bool isCurrent() const { return mIsCurrent; }
void getBooleanvImpl(GLenum pname, GLboolean *params) const; void getBooleanvImpl(GLenum pname, GLboolean *params) const;
void getFloatvImpl(GLenum pname, GLfloat *params) const; void getFloatvImpl(GLenum pname, GLfloat *params) const;
void getIntegervImpl(GLenum pname, GLint *params) const; void getIntegervImpl(GLenum pname, GLint *params) const;
...@@ -772,7 +776,10 @@ class Context final : public egl::LabeledObject, angle::NonCopyable, public angl ...@@ -772,7 +776,10 @@ class Context final : public egl::LabeledObject, angle::NonCopyable, public angl
OverlayType mOverlay; OverlayType mOverlay;
bool mIsCurrent = false; const bool mIsExternal;
const bool mSaveAndRestoreState;
bool mIsCurrent;
}; };
// Thread-local current valid context bound to the thread. // Thread-local current valid context bound to the thread.
......
...@@ -381,6 +381,11 @@ void FramebufferManager::setDefaultFramebuffer(Framebuffer *framebuffer) ...@@ -381,6 +381,11 @@ void FramebufferManager::setDefaultFramebuffer(Framebuffer *framebuffer)
mObjectMap.assign(Framebuffer::kDefaultDrawFramebufferHandle, framebuffer); mObjectMap.assign(Framebuffer::kDefaultDrawFramebufferHandle, framebuffer);
} }
Framebuffer *FramebufferManager::getDefaultFramebuffer() const
{
return getFramebuffer(Framebuffer::kDefaultDrawFramebufferHandle);
}
void FramebufferManager::invalidateFramebufferCompletenessCache() const void FramebufferManager::invalidateFramebufferCompletenessCache() const
{ {
for (const auto &framebuffer : mObjectMap) for (const auto &framebuffer : mObjectMap)
......
...@@ -273,6 +273,7 @@ class FramebufferManager ...@@ -273,6 +273,7 @@ class FramebufferManager
FramebufferID createFramebuffer(); FramebufferID createFramebuffer();
Framebuffer *getFramebuffer(FramebufferID handle) const; Framebuffer *getFramebuffer(FramebufferID handle) const;
void setDefaultFramebuffer(Framebuffer *framebuffer); void setDefaultFramebuffer(Framebuffer *framebuffer);
Framebuffer *getDefaultFramebuffer() const;
void invalidateFramebufferCompletenessCache() const; void invalidateFramebufferCompletenessCache() const;
......
...@@ -1688,6 +1688,11 @@ Framebuffer *State::getTargetFramebuffer(GLenum target) const ...@@ -1688,6 +1688,11 @@ Framebuffer *State::getTargetFramebuffer(GLenum target) const
} }
} }
Framebuffer *State::getDefaultFramebuffer() const
{
return mFramebufferManager->getDefaultFramebuffer();
}
bool State::removeReadFramebufferBinding(FramebufferID framebuffer) bool State::removeReadFramebufferBinding(FramebufferID framebuffer)
{ {
if (mReadFramebuffer != nullptr && mReadFramebuffer->id() == framebuffer) if (mReadFramebuffer != nullptr && mReadFramebuffer->id() == framebuffer)
......
...@@ -333,6 +333,7 @@ class State : angle::NonCopyable ...@@ -333,6 +333,7 @@ class State : angle::NonCopyable
Framebuffer *getTargetFramebuffer(GLenum target) const; Framebuffer *getTargetFramebuffer(GLenum target) const;
Framebuffer *getReadFramebuffer() const { return mReadFramebuffer; } Framebuffer *getReadFramebuffer() const { return mReadFramebuffer; }
Framebuffer *getDrawFramebuffer() const { return mDrawFramebuffer; } Framebuffer *getDrawFramebuffer() const { return mDrawFramebuffer; }
Framebuffer *getDefaultFramebuffer() const;
bool removeReadFramebufferBinding(FramebufferID framebuffer); bool removeReadFramebufferBinding(FramebufferID framebuffer);
bool removeDrawFramebufferBinding(FramebufferID framebuffer); bool removeDrawFramebufferBinding(FramebufferID framebuffer);
......
...@@ -1317,6 +1317,14 @@ GLuint FramebufferGL::getFramebufferID() const ...@@ -1317,6 +1317,14 @@ GLuint FramebufferGL::getFramebufferID() const
return mFramebufferID; return mFramebufferID;
} }
void FramebufferGL::updateDefaultFramebufferID(GLuint framebufferID)
{
// We only update framebufferID for a default frambuffer, and the framebufferID is created
// externally. ANGLE doesn't owne it.
ASSERT(isDefault());
mFramebufferID = framebufferID;
}
bool FramebufferGL::isDefault() const bool FramebufferGL::isDefault() const
{ {
return mIsDefault; return mIsDefault;
......
...@@ -87,6 +87,7 @@ class FramebufferGL : public FramebufferImpl ...@@ -87,6 +87,7 @@ class FramebufferGL : public FramebufferImpl
gl::Command command) override; gl::Command command) override;
GLuint getFramebufferID() const; GLuint getFramebufferID() const;
void updateDefaultFramebufferID(GLuint framebufferID);
bool isDefault() const; bool isDefault() const;
bool hasEmulatedAlphaChannelTextureAttachment() const; bool hasEmulatedAlphaChannelTextureAttachment() const;
......
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
#include "libANGLE/renderer/gl/functionsgl_typedefs.h" #include "libANGLE/renderer/gl/functionsgl_typedefs.h"
#include "platform/FeaturesGL.h" #include "platform/FeaturesGL.h"
#include <array>
#include <map> #include <map>
namespace gl namespace gl
...@@ -34,6 +35,86 @@ class TransformFeedbackGL; ...@@ -34,6 +35,86 @@ class TransformFeedbackGL;
class VertexArrayGL; class VertexArrayGL;
class QueryGL; class QueryGL;
// TODO(penghuang): use gl::State?
struct ExternalContextState
{
GLint packAlignment;
GLint unpackAlignment;
GLenum vertexArrayBufferBinding;
GLenum elementArrayBufferBinding;
bool depthTest;
bool cullFace;
GLenum cullFaceMode;
std::array<bool, 4> colorMask;
gl::ColorF colorClear;
gl::ColorF blendColor;
GLfloat depthClear;
GLenum currentProgram;
GLenum depthFunc;
bool depthMask;
GLfloat depthRage[2];
GLenum frontFace;
GLfloat lineWidth;
GLfloat polygonOffsetFactor;
GLfloat polygonOffsetUnits;
GLfloat sampleCoverageValue;
bool sampleCoverageInvert;
GLenum blendEquationRgb;
GLenum blendEquationAlpha;
bool enableDither;
bool enablePolygonOffsetFill;
bool enableSampleAlphaToCoverage;
bool enableSampleCoverage;
bool multisampleEnabled;
bool blendEnabled;
GLenum blendSrcRgb;
GLenum blendSrcAlpha;
GLenum blendDestRgb;
GLenum blendDestAlpha;
GLenum activeTexture;
gl::Rectangle viewport;
bool scissorTest;
gl::Rectangle scissorBox;
struct StencilState
{
bool stencilTestEnabled;
GLenum stencilFrontFunc;
GLint stencilFrontRef;
GLenum stencilFrontMask;
GLenum stencilBackFunc;
GLint stencilBackRef;
GLenum stencilBackMask;
GLint stencilClear;
GLenum stencilFrontWritemask;
GLenum stencilBackWritemask;
GLenum stencilFrontFailOp;
GLenum stencilFrontZFailOp;
GLenum stencilFrontZPassOp;
GLenum stencilBackFailOp;
GLenum stencilBackZFailOp;
GLenum stencilBackZPassOp;
};
StencilState stencilState;
GLenum framebufferBinding;
struct TextureBindings
{
GLenum texture2d;
GLenum textureCubeMap;
GLenum textureExternalOES;
// TODO(boliu): TEXTURE_RECTANGLE_ARB
};
std::vector<TextureBindings> textureBindings;
GLenum vertexArrayBinding;
};
class StateManagerGL final : angle::NonCopyable class StateManagerGL final : angle::NonCopyable
{ {
public: public:
...@@ -181,6 +262,9 @@ class StateManagerGL final : angle::NonCopyable ...@@ -181,6 +262,9 @@ class StateManagerGL final : angle::NonCopyable
void validateState() const; void validateState() const;
void syncFromNativeContext(const gl::Extensions &extensions, ExternalContextState *state);
void restoreNativeContext(const gl::Extensions &extensions, const ExternalContextState *state);
private: private:
void setTextureCubemapSeamlessEnabled(bool enabled); void setTextureCubemapSeamlessEnabled(bool enabled);
...@@ -195,6 +279,12 @@ class StateManagerGL final : angle::NonCopyable ...@@ -195,6 +279,12 @@ class StateManagerGL final : angle::NonCopyable
void updateDispatchIndirectBufferBinding(const gl::Context *context); void updateDispatchIndirectBufferBinding(const gl::Context *context);
void updateDrawIndirectBufferBinding(const gl::Context *context); void updateDrawIndirectBufferBinding(const gl::Context *context);
template <typename T>
void get(GLenum name, T *value);
template <size_t n, typename T>
void get(GLenum name, std::array<T, n> *values);
void syncSamplersState(const gl::Context *context); void syncSamplersState(const gl::Context *context);
void syncTransformFeedbackState(const gl::Context *context); void syncTransformFeedbackState(const gl::Context *context);
...@@ -202,6 +292,40 @@ class StateManagerGL final : angle::NonCopyable ...@@ -202,6 +292,40 @@ class StateManagerGL final : angle::NonCopyable
const gl::Program *program, const gl::Program *program,
const gl::FramebufferState &drawFramebufferState) const; const gl::FramebufferState &drawFramebufferState) const;
void syncBlendFromNativeContext(const gl::Extensions &extensions, ExternalContextState *state);
void restoreBlendNativeContext(const gl::Extensions &extensions,
const ExternalContextState *state);
void syncFramebufferFromNativeContext(const gl::Extensions &extensions,
ExternalContextState *state);
void restoreFramebufferNativeContext(const gl::Extensions &extensions,
const ExternalContextState *state);
void syncPixelPackUnpackFromNativeContext(const gl::Extensions &extensions,
ExternalContextState *state);
void restorePixelPackUnpackNativeContext(const gl::Extensions &extensions,
const ExternalContextState *state);
void syncStencilFromNativeContext(const gl::Extensions &extensions,
ExternalContextState *state);
void restoreStencilNativeContext(const gl::Extensions &extensions,
const ExternalContextState *state);
void syncBufferBindingsFromNativeContext(const gl::Extensions &extensions,
ExternalContextState *state);
void restoreBufferBindingsNativeContext(const gl::Extensions &extensions,
const ExternalContextState *state);
void syncTextureUnitsFromNativeContext(const gl::Extensions &extensions,
ExternalContextState *state);
void restoreTextureUnitsNativeContext(const gl::Extensions &extensions,
const ExternalContextState *state);
void syncVertexArraysFromNativeContext(const gl::Extensions &extensions,
ExternalContextState *state);
void restoreVertexArraysNativeContext(const gl::Extensions &extensions,
const ExternalContextState *state);
const FunctionsGL *mFunctions; const FunctionsGL *mFunctions;
const angle::FeaturesGL &mFeatures; const angle::FeaturesGL &mFeatures;
...@@ -342,6 +466,7 @@ class StateManagerGL final : angle::NonCopyable ...@@ -342,6 +466,7 @@ class StateManagerGL final : angle::NonCopyable
gl::State::DirtyBits mLocalDirtyBits; gl::State::DirtyBits mLocalDirtyBits;
gl::AttributesMask mLocalDirtyCurrentValues; gl::AttributesMask mLocalDirtyCurrentValues;
}; };
} // namespace rx } // namespace rx
#endif // LIBANGLE_RENDERER_GL_STATEMANAGERGL_H_ #endif // LIBANGLE_RENDERER_GL_STATEMANAGERGL_H_
...@@ -6,8 +6,12 @@ ...@@ -6,8 +6,12 @@
#include "libANGLE/renderer/gl/egl/ContextEGL.h" #include "libANGLE/renderer/gl/egl/ContextEGL.h"
#include "libANGLE/renderer/gl/FramebufferGL.h"
#include "libANGLE/renderer/gl/StateManagerGL.h"
namespace rx namespace rx
{ {
ContextEGL::ContextEGL(const gl::State &state, ContextEGL::ContextEGL(const gl::State &state,
gl::ErrorSet *errorSet, gl::ErrorSet *errorSet,
const std::shared_ptr<RendererEGL> &renderer, const std::shared_ptr<RendererEGL> &renderer,
...@@ -17,8 +21,42 @@ ContextEGL::ContextEGL(const gl::State &state, ...@@ -17,8 +21,42 @@ ContextEGL::ContextEGL(const gl::State &state,
ContextEGL::~ContextEGL() {} ContextEGL::~ContextEGL() {}
angle::Result ContextEGL::onMakeCurrent(const gl::Context *context)
{
if (!context->isCurrent() && context->isExternal())
{
if (!mExtState)
{
mExtState = std::make_unique<ExternalContextState>();
const auto &caps = getNativeCaps();
mExtState->textureBindings.resize(
static_cast<size_t>(caps.maxCombinedTextureImageUnits));
}
getStateManager()->syncFromNativeContext(getNativeExtensions(), mExtState.get());
// Use current FBO as the default framebuffer when the external context is current.
gl::Framebuffer *framebuffer = mState.getDefaultFramebuffer();
GetImplAs<FramebufferGL>(framebuffer)
->updateDefaultFramebufferID(mExtState->framebufferBinding);
}
return ContextGL::onMakeCurrent(context);
}
angle::Result ContextEGL::onUnMakeCurrent(const gl::Context *context)
{
if (context->saveAndRestoreState())
{
ASSERT(context->isExternal());
ASSERT(mExtState);
getStateManager()->restoreNativeContext(getNativeExtensions(), mExtState.get());
}
return ContextGL::onUnMakeCurrent(context);
}
EGLContext ContextEGL::getContext() const EGLContext ContextEGL::getContext() const
{ {
return mRendererEGL->getContext(); return mRendererEGL->getContext();
} }
} // namespace rx } // namespace rx
...@@ -14,6 +14,9 @@ ...@@ -14,6 +14,9 @@
namespace rx namespace rx
{ {
struct ExternalContextState;
class ContextEGL : public ContextGL class ContextEGL : public ContextGL
{ {
public: public:
...@@ -23,10 +26,14 @@ class ContextEGL : public ContextGL ...@@ -23,10 +26,14 @@ class ContextEGL : public ContextGL
RobustnessVideoMemoryPurgeStatus robustnessVideoMemoryPurgeStatus); RobustnessVideoMemoryPurgeStatus robustnessVideoMemoryPurgeStatus);
~ContextEGL() override; ~ContextEGL() override;
angle::Result onMakeCurrent(const gl::Context *context) override;
angle::Result onUnMakeCurrent(const gl::Context *context) override;
EGLContext getContext() const; EGLContext getContext() const;
private: private:
std::shared_ptr<RendererEGL> mRendererEGL; std::shared_ptr<RendererEGL> mRendererEGL;
std::unique_ptr<ExternalContextState> mExtState;
}; };
} // namespace rx } // namespace rx
......
...@@ -280,7 +280,7 @@ egl::Error DisplayEGL::initialize(egl::Display *display) ...@@ -280,7 +280,7 @@ egl::Error DisplayEGL::initialize(egl::Display *display)
functionsGL->initialize(mDisplayAttributes); functionsGL->initialize(mDisplayAttributes);
mRenderer.reset( mRenderer.reset(
new RendererEGL(std::move(functionsGL), mDisplayAttributes, this, context, attribs)); new RendererEGL(std::move(functionsGL), mDisplayAttributes, this, context, attribs, false));
const gl::Version &maxVersion = mRenderer->getMaxSupportedESVersion(); const gl::Version &maxVersion = mRenderer->getMaxSupportedESVersion();
if (maxVersion < gl::Version(2, 0)) if (maxVersion < gl::Version(2, 0))
{ {
...@@ -751,7 +751,7 @@ egl::Error DisplayEGL::createRenderer(EGLContext shareContext, ...@@ -751,7 +751,7 @@ egl::Error DisplayEGL::createRenderer(EGLContext shareContext,
functionsGL->initialize(mDisplayAttributes); functionsGL->initialize(mDisplayAttributes);
outRenderer->reset( outRenderer->reset(
new RendererEGL(std::move(functionsGL), mDisplayAttributes, this, context, attribs)); new RendererEGL(std::move(functionsGL), mDisplayAttributes, this, context, attribs, false));
return egl::NoError(); return egl::NoError();
} }
......
...@@ -132,6 +132,9 @@ class DisplayEGL : public DisplayGL ...@@ -132,6 +132,9 @@ class DisplayEGL : public DisplayGL
{ {
EGLSurface surface = EGL_NO_SURFACE; EGLSurface surface = EGL_NO_SURFACE;
EGLContext context = EGL_NO_CONTEXT; EGLContext context = EGL_NO_CONTEXT;
// True if the current context is an external context. and both surface and context will be
// unset when an external context is current.
bool isExternalContext = false;
}; };
angle::HashMap<std::thread::id, CurrentNativeContext> mCurrentNativeContexts; angle::HashMap<std::thread::id, CurrentNativeContext> mCurrentNativeContexts;
......
...@@ -45,6 +45,7 @@ struct FunctionsEGL::EGLDispatchTable ...@@ -45,6 +45,7 @@ struct FunctionsEGL::EGLDispatchTable
destroyContextPtr(nullptr), destroyContextPtr(nullptr),
destroySurfacePtr(nullptr), destroySurfacePtr(nullptr),
getConfigAttribPtr(nullptr), getConfigAttribPtr(nullptr),
getCurrentSurfacePtr(nullptr),
getDisplayPtr(nullptr), getDisplayPtr(nullptr),
getErrorPtr(nullptr), getErrorPtr(nullptr),
initializePtr(nullptr), initializePtr(nullptr),
...@@ -59,6 +60,8 @@ struct FunctionsEGL::EGLDispatchTable ...@@ -59,6 +60,8 @@ struct FunctionsEGL::EGLDispatchTable
surfaceAttribPtr(nullptr), surfaceAttribPtr(nullptr),
swapIntervalPtr(nullptr), swapIntervalPtr(nullptr),
getCurrentContextPtr(nullptr),
createImageKHRPtr(nullptr), createImageKHRPtr(nullptr),
destroyImageKHRPtr(nullptr), destroyImageKHRPtr(nullptr),
...@@ -93,6 +96,7 @@ struct FunctionsEGL::EGLDispatchTable ...@@ -93,6 +96,7 @@ struct FunctionsEGL::EGLDispatchTable
PFNEGLDESTROYCONTEXTPROC destroyContextPtr; PFNEGLDESTROYCONTEXTPROC destroyContextPtr;
PFNEGLDESTROYSURFACEPROC destroySurfacePtr; PFNEGLDESTROYSURFACEPROC destroySurfacePtr;
PFNEGLGETCONFIGATTRIBPROC getConfigAttribPtr; PFNEGLGETCONFIGATTRIBPROC getConfigAttribPtr;
PFNEGLGETCURRENTSURFACEPROC getCurrentSurfacePtr;
PFNEGLGETDISPLAYPROC getDisplayPtr; PFNEGLGETDISPLAYPROC getDisplayPtr;
PFNEGLGETERRORPROC getErrorPtr; PFNEGLGETERRORPROC getErrorPtr;
PFNEGLINITIALIZEPROC initializePtr; PFNEGLINITIALIZEPROC initializePtr;
...@@ -108,6 +112,9 @@ struct FunctionsEGL::EGLDispatchTable ...@@ -108,6 +112,9 @@ struct FunctionsEGL::EGLDispatchTable
PFNEGLSURFACEATTRIBPROC surfaceAttribPtr; PFNEGLSURFACEATTRIBPROC surfaceAttribPtr;
PFNEGLSWAPINTERVALPROC swapIntervalPtr; PFNEGLSWAPINTERVALPROC swapIntervalPtr;
// 1.4
PFNEGLGETCURRENTCONTEXTPROC getCurrentContextPtr;
// EGL_KHR_image // EGL_KHR_image
PFNEGLCREATEIMAGEKHRPROC createImageKHRPtr; PFNEGLCREATEIMAGEKHRPROC createImageKHRPtr;
PFNEGLDESTROYIMAGEKHRPROC destroyImageKHRPtr; PFNEGLDESTROYIMAGEKHRPROC destroyImageKHRPtr;
...@@ -169,6 +176,7 @@ egl::Error FunctionsEGL::initialize(EGLNativeDisplayType nativeDisplay) ...@@ -169,6 +176,7 @@ egl::Error FunctionsEGL::initialize(EGLNativeDisplayType nativeDisplay)
ANGLE_GET_PROC_OR_ERROR(&mFnPtrs->destroyContextPtr, eglDestroyContext); ANGLE_GET_PROC_OR_ERROR(&mFnPtrs->destroyContextPtr, eglDestroyContext);
ANGLE_GET_PROC_OR_ERROR(&mFnPtrs->destroySurfacePtr, eglDestroySurface); ANGLE_GET_PROC_OR_ERROR(&mFnPtrs->destroySurfacePtr, eglDestroySurface);
ANGLE_GET_PROC_OR_ERROR(&mFnPtrs->getConfigAttribPtr, eglGetConfigAttrib); ANGLE_GET_PROC_OR_ERROR(&mFnPtrs->getConfigAttribPtr, eglGetConfigAttrib);
ANGLE_GET_PROC_OR_ERROR(&mFnPtrs->getCurrentSurfacePtr, eglGetCurrentSurface);
ANGLE_GET_PROC_OR_ERROR(&mFnPtrs->getDisplayPtr, eglGetDisplay); ANGLE_GET_PROC_OR_ERROR(&mFnPtrs->getDisplayPtr, eglGetDisplay);
ANGLE_GET_PROC_OR_ERROR(&mFnPtrs->getErrorPtr, eglGetError); ANGLE_GET_PROC_OR_ERROR(&mFnPtrs->getErrorPtr, eglGetError);
ANGLE_GET_PROC_OR_ERROR(&mFnPtrs->initializePtr, eglInitialize); ANGLE_GET_PROC_OR_ERROR(&mFnPtrs->initializePtr, eglInitialize);
...@@ -201,6 +209,8 @@ egl::Error FunctionsEGL::initialize(EGLNativeDisplayType nativeDisplay) ...@@ -201,6 +209,8 @@ egl::Error FunctionsEGL::initialize(EGLNativeDisplayType nativeDisplay)
return egl::Error(mFnPtrs->getErrorPtr(), "Failed to bind API in system egl"); return egl::Error(mFnPtrs->getErrorPtr(), "Failed to bind API in system egl");
} }
ANGLE_GET_PROC_OR_ERROR(&mFnPtrs->getCurrentContextPtr, eglGetCurrentContext);
const char *extensions = queryString(EGL_EXTENSIONS); const char *extensions = queryString(EGL_EXTENSIONS);
if (!extensions) if (!extensions)
{ {
...@@ -333,6 +343,11 @@ EGLBoolean FunctionsEGL::getConfigAttrib(EGLConfig config, EGLint attribute, EGL ...@@ -333,6 +343,11 @@ EGLBoolean FunctionsEGL::getConfigAttrib(EGLConfig config, EGLint attribute, EGL
return mFnPtrs->getConfigAttribPtr(mEGLDisplay, config, attribute, value); return mFnPtrs->getConfigAttribPtr(mEGLDisplay, config, attribute, value);
} }
EGLSurface FunctionsEGL::getCurrentSurface(EGLint readdraw) const
{
return mFnPtrs->getCurrentSurfacePtr(readdraw);
}
EGLContext FunctionsEGL::createContext(EGLConfig config, EGLContext FunctionsEGL::createContext(EGLConfig config,
EGLContext share_context, EGLContext share_context,
EGLint const *attrib_list) const EGLint const *attrib_list) const
...@@ -402,6 +417,11 @@ EGLBoolean FunctionsEGL::swapInterval(EGLint interval) const ...@@ -402,6 +417,11 @@ EGLBoolean FunctionsEGL::swapInterval(EGLint interval) const
return mFnPtrs->swapIntervalPtr(mEGLDisplay, interval); return mFnPtrs->swapIntervalPtr(mEGLDisplay, interval);
} }
EGLContext FunctionsEGL::getCurrentContext() const
{
return mFnPtrs->getCurrentContextPtr();
}
EGLImageKHR FunctionsEGL::createImageKHR(EGLContext context, EGLImageKHR FunctionsEGL::createImageKHR(EGLContext context,
EGLenum target, EGLenum target,
EGLClientBuffer buffer, EGLClientBuffer buffer,
......
...@@ -46,6 +46,7 @@ class FunctionsEGL ...@@ -46,6 +46,7 @@ class FunctionsEGL
EGLint config_size, EGLint config_size,
EGLint *num_config) const; EGLint *num_config) const;
EGLBoolean getConfigAttrib(EGLConfig config, EGLint attribute, EGLint *value) const; EGLBoolean getConfigAttrib(EGLConfig config, EGLint attribute, EGLint *value) const;
EGLSurface getCurrentSurface(EGLint readdraw) const;
EGLContext createContext(EGLConfig config, EGLContext createContext(EGLConfig config,
EGLContext share_context, EGLContext share_context,
EGLint const *attrib_list) const; EGLint const *attrib_list) const;
...@@ -65,6 +66,8 @@ class FunctionsEGL ...@@ -65,6 +66,8 @@ class FunctionsEGL
EGLBoolean surfaceAttrib(EGLSurface surface, EGLint attribute, EGLint value) const; EGLBoolean surfaceAttrib(EGLSurface surface, EGLint attribute, EGLint value) const;
EGLBoolean swapInterval(EGLint interval) const; EGLBoolean swapInterval(EGLint interval) const;
EGLContext getCurrentContext() const;
EGLImageKHR createImageKHR(EGLContext context, EGLImageKHR createImageKHR(EGLContext context,
EGLenum target, EGLenum target,
EGLClientBuffer buffer, EGLClientBuffer buffer,
......
...@@ -15,17 +15,22 @@ RendererEGL::RendererEGL(std::unique_ptr<FunctionsGL> functionsGL, ...@@ -15,17 +15,22 @@ RendererEGL::RendererEGL(std::unique_ptr<FunctionsGL> functionsGL,
const egl::AttributeMap &attribMap, const egl::AttributeMap &attribMap,
DisplayEGL *display, DisplayEGL *display,
EGLContext context, EGLContext context,
const native_egl::AttributeVector attribs) const native_egl::AttributeVector attribs,
bool isExternalContext)
: RendererGL(std::move(functionsGL), attribMap, display), : RendererGL(std::move(functionsGL), attribMap, display),
mDisplay(display), mDisplay(display),
mContext(context), mContext(context),
mAttribs(attribs) mAttribs(attribs),
mIsExternalContext(isExternalContext)
{} {}
RendererEGL::~RendererEGL() RendererEGL::~RendererEGL()
{ {
if (!mIsExternalContext)
{
mDisplay->destroyNativeContext(mContext); mDisplay->destroyNativeContext(mContext);
mContext = nullptr; mContext = nullptr;
}
} }
EGLContext RendererEGL::getContext() const EGLContext RendererEGL::getContext() const
......
...@@ -23,7 +23,8 @@ class RendererEGL : public RendererGL ...@@ -23,7 +23,8 @@ class RendererEGL : public RendererGL
const egl::AttributeMap &attribMap, const egl::AttributeMap &attribMap,
DisplayEGL *display, DisplayEGL *display,
EGLContext context, EGLContext context,
const native_egl::AttributeVector attribs); const native_egl::AttributeVector attribs,
bool isExternalContext);
~RendererEGL() override; ~RendererEGL() override;
EGLContext getContext() const; EGLContext getContext() const;
...@@ -34,6 +35,7 @@ class RendererEGL : public RendererGL ...@@ -34,6 +35,7 @@ class RendererEGL : public RendererGL
DisplayEGL *mDisplay; DisplayEGL *mDisplay;
EGLContext mContext; EGLContext mContext;
const native_egl::AttributeVector mAttribs; const native_egl::AttributeVector mAttribs;
const bool mIsExternalContext;
}; };
} // namespace rx } // namespace rx
......
...@@ -237,4 +237,9 @@ egl::Error SurfaceEGL::getFrameTimestamps(EGLuint64KHR frameId, ...@@ -237,4 +237,9 @@ egl::Error SurfaceEGL::getFrameTimestamps(EGLuint64KHR frameId,
return egl::NoError(); return egl::NoError();
} }
bool SurfaceEGL::isExternal() const
{
return false;
}
} // namespace rx } // namespace rx
...@@ -58,6 +58,7 @@ class SurfaceEGL : public SurfaceGL ...@@ -58,6 +58,7 @@ class SurfaceEGL : public SurfaceGL
EGLnsecsANDROID *values) const override; EGLnsecsANDROID *values) const override;
EGLSurface getSurface() const; EGLSurface getSurface() const;
virtual bool isExternal() const;
protected: protected:
const FunctionsEGL *mEGL; const FunctionsEGL *mEGL;
......
...@@ -152,7 +152,7 @@ egl::Error DisplayAndroid::initialize(egl::Display *display) ...@@ -152,7 +152,7 @@ egl::Error DisplayAndroid::initialize(egl::Display *display)
mConfig = configWithFormat; mConfig = configWithFormat;
} }
ANGLE_TRY(createRenderer(EGL_NO_CONTEXT, true, &mRenderer)); ANGLE_TRY(createRenderer(EGL_NO_CONTEXT, true, false, &mRenderer));
const gl::Version &maxVersion = mRenderer->getMaxSupportedESVersion(); const gl::Version &maxVersion = mRenderer->getMaxSupportedESVersion();
if (maxVersion < gl::Version(2, 0)) if (maxVersion < gl::Version(2, 0))
...@@ -205,14 +205,19 @@ ContextImpl *DisplayAndroid::createContext(const gl::State &state, ...@@ -205,14 +205,19 @@ ContextImpl *DisplayAndroid::createContext(const gl::State &state,
const egl::AttributeMap &attribs) const egl::AttributeMap &attribs)
{ {
std::shared_ptr<RendererEGL> renderer; std::shared_ptr<RendererEGL> renderer;
if (mVirtualizedContexts) bool usingExternalContext = attribs.get(EGL_EXTERNAL_CONTEXT_ANGLE, EGL_FALSE) == EGL_TRUE;
if (mVirtualizedContexts && !usingExternalContext)
{ {
renderer = mRenderer; renderer = mRenderer;
} }
else else
{ {
EGLContext nativeShareContext = EGL_NO_CONTEXT; EGLContext nativeShareContext = EGL_NO_CONTEXT;
if (shareContext) if (usingExternalContext)
{
ASSERT(!shareContext);
}
else if (shareContext)
{ {
ContextEGL *shareContextEGL = GetImplAs<ContextEGL>(shareContext); ContextEGL *shareContextEGL = GetImplAs<ContextEGL>(shareContext);
nativeShareContext = shareContextEGL->getContext(); nativeShareContext = shareContextEGL->getContext();
...@@ -221,7 +226,8 @@ ContextImpl *DisplayAndroid::createContext(const gl::State &state, ...@@ -221,7 +226,8 @@ ContextImpl *DisplayAndroid::createContext(const gl::State &state,
// Create a new renderer for this context. It only needs to share with the user's requested // Create a new renderer for this context. It only needs to share with the user's requested
// share context because there are no internal resources in DisplayAndroid that are shared // share context because there are no internal resources in DisplayAndroid that are shared
// at the GL level. // at the GL level.
egl::Error error = createRenderer(nativeShareContext, false, &renderer); egl::Error error =
createRenderer(nativeShareContext, false, usingExternalContext, &renderer);
if (error.isError()) if (error.isError())
{ {
ERR() << "Failed to create a shared renderer: " << error.getMessage(); ERR() << "Failed to create a shared renderer: " << error.getMessage();
...@@ -233,11 +239,67 @@ ContextImpl *DisplayAndroid::createContext(const gl::State &state, ...@@ -233,11 +239,67 @@ ContextImpl *DisplayAndroid::createContext(const gl::State &state,
RobustnessVideoMemoryPurgeStatus::NOT_REQUESTED); RobustnessVideoMemoryPurgeStatus::NOT_REQUESTED);
} }
class ExternalSurfaceEGL : public SurfaceEGL
{
public:
ExternalSurfaceEGL(const egl::SurfaceState &state,
const FunctionsEGL *egl,
EGLConfig config,
EGLint width,
EGLint height)
: SurfaceEGL(state, egl, config), mWidth(width), mHeight(height)
{}
~ExternalSurfaceEGL() override = default;
egl::Error initialize(const egl::Display *display) override { return egl::NoError(); }
EGLint getSwapBehavior() const override { return EGL_BUFFER_DESTROYED; }
EGLint getWidth() const override { return mWidth; }
EGLint getHeight() const override { return mHeight; }
bool isExternal() const override { return true; }
private:
const EGLint mWidth;
const EGLint mHeight;
};
SurfaceImpl *DisplayAndroid::createPbufferFromClientBuffer(const egl::SurfaceState &state,
EGLenum buftype,
EGLClientBuffer clientBuffer,
const egl::AttributeMap &attribs)
{
if (buftype == EGL_EXTERNAL_SURFACE_ANGLE)
{
ASSERT(clientBuffer == nullptr);
EGLint width = static_cast<EGLint>(attribs.get(EGL_WIDTH, 0));
EGLint height = static_cast<EGLint>(attribs.get(EGL_HEIGHT, 0));
// Use the ExternalSurfaceEGL, so ANGLE can know the framebuffer size.
return new ExternalSurfaceEGL(state, mEGL, EGL_NO_CONFIG_KHR, width, height);
}
return DisplayEGL::createPbufferFromClientBuffer(state, buftype, clientBuffer, attribs);
}
bool DisplayAndroid::isValidNativeWindow(EGLNativeWindowType window) const bool DisplayAndroid::isValidNativeWindow(EGLNativeWindowType window) const
{ {
return ANativeWindow_getFormat(window) >= 0; return ANativeWindow_getFormat(window) >= 0;
} }
egl::Error DisplayAndroid::validateClientBuffer(const egl::Config *configuration,
EGLenum buftype,
EGLClientBuffer clientBuffer,
const egl::AttributeMap &attribs) const
{
if (buftype == EGL_EXTERNAL_SURFACE_ANGLE)
{
ASSERT(clientBuffer == nullptr);
return egl::NoError();
}
return DisplayEGL::validateClientBuffer(configuration, buftype, clientBuffer, attribs);
}
egl::Error DisplayAndroid::validateImageClientBuffer(const gl::Context *context, egl::Error DisplayAndroid::validateImageClientBuffer(const gl::Context *context,
EGLenum target, EGLenum target,
EGLClientBuffer clientBuffer, EGLClientBuffer clientBuffer,
...@@ -290,6 +352,35 @@ egl::Error DisplayAndroid::makeCurrent(egl::Display *display, ...@@ -290,6 +352,35 @@ egl::Error DisplayAndroid::makeCurrent(egl::Display *display,
newContext = contextEGL->getContext(); newContext = contextEGL->getContext();
} }
if (currentContext.isExternalContext || (context && context->isExternal()))
{
ASSERT(currentContext.context == EGL_NO_CONTEXT);
ASSERT(currentContext.surface == EGL_NO_SURFACE);
if (!currentContext.isExternalContext)
{
// Switch to an ANGLE external context.
ASSERT(context);
currentContext.isExternalContext = true;
// We only support using external surface with external context.
ASSERT(GetImplAs<SurfaceEGL>(drawSurface)->isExternal());
}
else
{
// We don't support switching surfaces for external context.
ASSERT(!context);
// Release the ANGLE external context.
ASSERT(newSurface == EGL_NO_CONTEXT);
ASSERT(newContext == EGL_NO_SURFACE);
currentContext.isExternalContext = false;
}
// Do not need to call eglMakeCurrent(), since we don't support swtiching EGLSurface for
// external context.
return DisplayGL::makeCurrent(display, drawSurface, readSurface, context);
}
// The context should never change when context virtualization is being used, even when a null // The context should never change when context virtualization is being used, even when a null
// context is being bound. // context is being bound.
if (mVirtualizedContexts) if (mVirtualizedContexts)
...@@ -341,27 +432,46 @@ void DisplayAndroid::generateExtensions(egl::DisplayExtensions *outExtensions) c ...@@ -341,27 +432,46 @@ void DisplayAndroid::generateExtensions(egl::DisplayExtensions *outExtensions) c
// Surfaceless can be support if the native driver supports it or we know that we are running on // Surfaceless can be support if the native driver supports it or we know that we are running on
// a single thread (mVirtualizedContexts == true) // a single thread (mVirtualizedContexts == true)
outExtensions->surfacelessContext = mSupportsSurfaceless || mVirtualizedContexts; outExtensions->surfacelessContext = mSupportsSurfaceless || mVirtualizedContexts;
outExtensions->externalContextAndSurface = true;
} }
egl::Error DisplayAndroid::createRenderer(EGLContext shareContext, egl::Error DisplayAndroid::createRenderer(EGLContext shareContext,
bool makeNewContextCurrent, bool makeNewContextCurrent,
bool isExternalContext,
std::shared_ptr<RendererEGL> *outRenderer) std::shared_ptr<RendererEGL> *outRenderer)
{ {
EGLContext context = EGL_NO_CONTEXT; EGLContext context = EGL_NO_CONTEXT;
native_egl::AttributeVector attribs; native_egl::AttributeVector attribs;
ANGLE_TRY(initializeContext(shareContext, mDisplayAttributes, &context, &attribs));
// If isExternalContext is true, the external context is current, so we don't need to make the
// mMockPbuffer current.
if (isExternalContext)
{
ASSERT(shareContext == EGL_NO_CONTEXT);
ASSERT(!makeNewContextCurrent);
// Should we consider creating a share context to avoid querying and restoring GL context
// state?
context = mEGL->getCurrentContext();
ASSERT(context != EGL_NO_CONTEXT);
// TODO: get the version from the current context.
attribs = {EGL_CONTEXT_MAJOR_VERSION, 2, EGL_CONTEXT_MINOR_VERSION, 0, EGL_NONE};
}
else
{
ANGLE_TRY(initializeContext(shareContext, mDisplayAttributes, &context, &attribs));
if (mEGL->makeCurrent(mMockPbuffer, context) == EGL_FALSE) if (mEGL->makeCurrent(mMockPbuffer, context) == EGL_FALSE)
{ {
return egl::EglNotInitialized() return egl::EglNotInitialized()
<< "eglMakeCurrent failed with " << egl::Error(mEGL->getError()); << "eglMakeCurrent failed with " << egl::Error(mEGL->getError());
} }
}
std::unique_ptr<FunctionsGL> functionsGL(mEGL->makeFunctionsGL()); std::unique_ptr<FunctionsGL> functionsGL(mEGL->makeFunctionsGL());
functionsGL->initialize(mDisplayAttributes); functionsGL->initialize(mDisplayAttributes);
outRenderer->reset( outRenderer->reset(new RendererEGL(std::move(functionsGL), mDisplayAttributes, this, context,
new RendererEGL(std::move(functionsGL), mDisplayAttributes, this, context, attribs)); attribs, isExternalContext));
CurrentNativeContext &currentContext = mCurrentNativeContexts[std::this_thread::get_id()]; CurrentNativeContext &currentContext = mCurrentNativeContexts[std::this_thread::get_id()];
if (makeNewContextCurrent) if (makeNewContextCurrent)
...@@ -369,7 +479,7 @@ egl::Error DisplayAndroid::createRenderer(EGLContext shareContext, ...@@ -369,7 +479,7 @@ egl::Error DisplayAndroid::createRenderer(EGLContext shareContext,
currentContext.surface = mMockPbuffer; currentContext.surface = mMockPbuffer;
currentContext.context = context; currentContext.context = context;
} }
else else if (!isExternalContext)
{ {
// Reset the current context back to the previous state // Reset the current context back to the previous state
if (mEGL->makeCurrent(currentContext.surface, currentContext.context) == EGL_FALSE) if (mEGL->makeCurrent(currentContext.surface, currentContext.context) == EGL_FALSE)
......
...@@ -34,8 +34,15 @@ class DisplayAndroid : public DisplayEGL ...@@ -34,8 +34,15 @@ class DisplayAndroid : public DisplayEGL
const egl::Config *configuration, const egl::Config *configuration,
const gl::Context *shareContext, const gl::Context *shareContext,
const egl::AttributeMap &attribs) override; const egl::AttributeMap &attribs) override;
SurfaceImpl *createPbufferFromClientBuffer(const egl::SurfaceState &state,
EGLenum buftype,
EGLClientBuffer clientBuffer,
const egl::AttributeMap &attribs) override;
bool isValidNativeWindow(EGLNativeWindowType window) const override; bool isValidNativeWindow(EGLNativeWindowType window) const override;
egl::Error validateClientBuffer(const egl::Config *configuration,
EGLenum buftype,
EGLClientBuffer clientBuffer,
const egl::AttributeMap &attribs) const override;
egl::Error validateImageClientBuffer(const gl::Context *context, egl::Error validateImageClientBuffer(const gl::Context *context,
EGLenum target, EGLenum target,
EGLClientBuffer clientBuffer, EGLClientBuffer clientBuffer,
...@@ -62,6 +69,7 @@ class DisplayAndroid : public DisplayEGL ...@@ -62,6 +69,7 @@ class DisplayAndroid : public DisplayEGL
egl::Error createRenderer(EGLContext shareContext, egl::Error createRenderer(EGLContext shareContext,
bool makeNewContextCurrent, bool makeNewContextCurrent,
bool isExternalContext,
std::shared_ptr<RendererEGL> *outRenderer); std::shared_ptr<RendererEGL> *outRenderer);
bool mVirtualizedContexts; bool mVirtualizedContexts;
......
...@@ -530,7 +530,7 @@ egl::Error DisplayGbm::initialize(egl::Display *display) ...@@ -530,7 +530,7 @@ egl::Error DisplayGbm::initialize(egl::Display *display)
functionsGL->initialize(display->getAttributeMap()); functionsGL->initialize(display->getAttributeMap());
mRenderer.reset(new RendererEGL(std::move(functionsGL), display->getAttributeMap(), this, mRenderer.reset(new RendererEGL(std::move(functionsGL), display->getAttributeMap(), this,
context, attribs)); context, attribs, false));
const gl::Version &maxVersion = mRenderer->getMaxSupportedESVersion(); const gl::Version &maxVersion = mRenderer->getMaxSupportedESVersion();
if (maxVersion < gl::Version(2, 0)) if (maxVersion < gl::Version(2, 0))
{ {
......
...@@ -1948,6 +1948,47 @@ bool ValidateCreateContext(const ValidationContext *val, ...@@ -1948,6 +1948,47 @@ bool ValidateCreateContext(const ValidationContext *val,
} }
break; break;
case EGL_EXTERNAL_CONTEXT_ANGLE:
if (!display->getExtensions().externalContextAndSurface)
{
val->setError(EGL_BAD_ATTRIBUTE,
"Attribute "
"EGL_EXTERNAL_CONTEXT_ANGLE requires "
"EGL_ANGLE_external_context_and_surface.");
return false;
}
if (value != EGL_TRUE && value != EGL_FALSE)
{
val->setError(EGL_BAD_ATTRIBUTE,
"EGL_EXTERNAL_CONTEXT_ANGLE must "
"be either EGL_TRUE or EGL_FALSE.");
return false;
}
if (value == EGL_TRUE && shareContext)
{
val->setError(
EGL_BAD_ATTRIBUTE,
"EGL_EXTERNAL_CONTEXT_ANGLE doesn't allow creating with sharedContext.");
return false;
}
break;
case EGL_EXTERNAL_CONTEXT_SAVE_STATE_ANGLE:
if (!display->getExtensions().externalContextAndSurface)
{
val->setError(EGL_BAD_ATTRIBUTE,
"Attribute "
"EGL_EXTERNAL_CONTEXT_SAVE_STATE_ANGLE requires "
"EGL_ANGLE_external_context_and_surface.");
return false;
}
if (value != EGL_TRUE && value != EGL_FALSE)
{
val->setError(EGL_BAD_ATTRIBUTE,
"EGL_EXTERNAL_CONTEXT_SAVE_STATE_ANGLE must "
"be either EGL_TRUE or EGL_FALSE.");
return false;
}
break;
default: default:
val->setError(EGL_BAD_ATTRIBUTE, "Unknown attribute."); val->setError(EGL_BAD_ATTRIBUTE, "Unknown attribute.");
return false; return false;
...@@ -2380,6 +2421,21 @@ bool ValidateCreatePbufferFromClientBuffer(const ValidationContext *val, ...@@ -2380,6 +2421,21 @@ bool ValidateCreatePbufferFromClientBuffer(const ValidationContext *val,
return false; return false;
} }
break; break;
case EGL_EXTERNAL_SURFACE_ANGLE:
if (!display->getExtensions().externalContextAndSurface)
{
val->setError(EGL_BAD_ATTRIBUTE,
"Attribute "
"EGL_EXTERNAL_SURFACE_ANGLE requires "
"EGL_ANGLE_external_context_and_surface.");
return false;
}
if (buffer != nullptr)
{
val->setError(EGL_BAD_PARAMETER, "<buffer> must be null");
return false;
}
break;
default: default:
val->setError(EGL_BAD_PARAMETER); val->setError(EGL_BAD_PARAMETER);
...@@ -2397,10 +2453,11 @@ bool ValidateCreatePbufferFromClientBuffer(const ValidationContext *val, ...@@ -2397,10 +2453,11 @@ bool ValidateCreatePbufferFromClientBuffer(const ValidationContext *val,
case EGL_WIDTH: case EGL_WIDTH:
case EGL_HEIGHT: case EGL_HEIGHT:
if (buftype != EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE && if (buftype != EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE &&
buftype != EGL_D3D_TEXTURE_ANGLE && buftype != EGL_IOSURFACE_ANGLE) buftype != EGL_D3D_TEXTURE_ANGLE && buftype != EGL_IOSURFACE_ANGLE &&
buftype != EGL_EXTERNAL_SURFACE_ANGLE)
{ {
val->setError(EGL_BAD_PARAMETER, val->setError(EGL_BAD_PARAMETER,
"Width and Height are not supported for thie <buftype>"); "Width and Height are not supported for this <buftype>");
return false; return false;
} }
if (value < 0) if (value < 0)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment