Commit f41a7151 by Geoff Lang Committed by Commit Bot

Add an extension to disable resource generation on bind.

BUG=angleproject:1518 Change-Id: I662f7b07da5c97831496f2617b0adadf9858bdc9 Reviewed-on: https://chromium-review.googlesource.com/386799Reviewed-by: 's avatarAntoine Labour <piman@chromium.org> Commit-Queue: Geoff Lang <geofflang@chromium.org>
parent 44ebf6b4
Name
CHROMIUM_bind_generates_resource
Name Strings
GL_CHROMIUM_bind_generates_resource
Contributors
Geoff Lang
Contact
Geoff Lang (geofflang 'at' google.com)
Notice
Copyright (c) 2016 The Khronos Group Inc. Copyright terms at
http://www.khronos.org/registry/speccopyright.html
Status
Draft
Version
Version 1, September 19, 2016
Number
OpenGL ES Extension #??
Dependencies
Requires OpenGL ES 2.0
Written against the OpenGL ES 2.0 specification.
Overview
This extension allows the user to control the behaviour when binding an
object that has not been generated. This functionality is useful to
notify the user of potential use-after-free errors or support other APIs
such as WebGL on top of an OpenGL ES context.
New Procedures and Functions
None
New Tokens
Accepted by the <cap> parameter to IsEnabled and the <pname> parameter to
GetBooleanv, GetIntegerv, GetFloatv, and GetInteger64v:
BIND_GENERATES_RESOURCE_CHROMIUM 0x9244
Additions to the OpenGL ES Specification
Add to the end of Section 2.9 "Buffer Objects":
If BIND_GENERATES_RESOURCE_CHROMIUM is false, BindBuffer fails and an
INVALID_OPERATION error is generated if buffer is not zero or a name
returned from a previous call to GenBuffers, or if such a name has since
been deleted with DeleteBuffers.
Add to the end of Section 3.7.13 "Texture Objects":
If BIND_GENERATES_RESOURCE_CHROMIUM is false, BindTexture fails and an
INVALID_OPERATION error is generated if texture is not zero or a name
returned from a previous call to GenTextures, or if such a name has since
been deleted with DeleteTextures.
Add to the end of Section 4.4.1 "Binding and Managing Framebuffer Objects":
If BIND_GENERATES_RESOURCE_CHROMIUM is false, BindFramebuffer fails and an
INVALID_OPERATION error is generated if framebuffer is not zero or a name
returned from a previous call to GenFramebuffers, or if such a name has
since been deleted with DeleteFramebuffers.
Add to the end of Section 4.4.3 "Renderbuffer Objects":
If BIND_GENERATES_RESOURCE_CHROMIUM is false, BindRenderbuffer fails and an
INVALID_OPERATION error is generated if renderbuffer is not zero or a name
returned from a previous call to GenRenderbuffers, or if such a name has
since been deleted with DeleteRenderbuffers.
New State
Modify Table 6.22, Miscellaneous
Add:
Initial
Get Value Type Get Command Value Description
----------------------- ---- ----------- ------- --------------
BIND_GENERATES_RESOURCE_CHROMIUM B IsEnabled TRUE Bind generates
new resources
Conformance Tests
TBD
Issues
(1) Should the BIND_GENERATES_RESOURCE_CHROMIUM state be enabled at context
creation time or dynamically through the Enable and Disable functions?
RESOLOVED: BIND_GENERATES_RESOURCE_CHROMIUM is initialized by a context
creation attribute and cannot be modified. One of the major use cases of
this extension is to back WebGL contexts and the end user should not be
allowed to modify this state.
Revision History
Rev. Date Author Changes
---- ------------- --------- ----------------------------------------
1 Sept 19, 2016 geofflang Initial version
Name
CHROMIUM_create_context_bind_generates_resource
Name Strings
EGL_CHROMIUM_create_context_bind_generates_resource
Contributors
Geoff Lang
Contacts
Geoff Lang (geofflang 'at' google.com)
Status
Draft
Version
Version 1, September 21, 2016
Number
EGL Extension #??
Dependencies
Requires EGL 1.4.
Written against the EGL 1.4 specification.
This spec interacts with GL_CHROMIUM_bind_generates_resource (or
equivalent) extension.
Overview
This extension allows the creation of an OpenGL or OpenGL ES context that
allows or disallows implicit creation of OpenGL resources on bind.
New Types
None
New Procedures and Functions
None
New Tokens
Accepted as an attribute name in the <*attrib_list> argument to
eglCreateContext:
EGL_CONTEXT_BIND_GENERATES_RESOURCE_CHROMIUM 0x3AAD
Additions to the EGL 1.4 Specification
Add the following to section 3.7.1 "Creating Rendering Contexts":
EGL_CONTEXT_BIND_GENERATES_RESOURCE_CHROMIUM indicates whether the context
should be created with the GL_BIND_GENERATES_RESOURCE_CHROMIUM state
initialized to GL_TRUE or GL_FALSE. The default value of
EGL_CONTEXT_BIND_GENERATES_RESOURCE_CHROMIUM is EGL_TRUE.
Errors
None
New State
None
Conformance Tests
TBD
Issues
None
Revision History
Rev. Date Author Changes
---- ------------- --------- ----------------------------------------
1 Sept 21, 2016 geofflang Initial version
...@@ -572,6 +572,11 @@ EGLAPI EGLBoolean EGLAPIENTRY eglStreamPostD3DTextureNV12ANGLE(EGLDisplay dpy, E ...@@ -572,6 +572,11 @@ EGLAPI EGLBoolean EGLAPIENTRY eglStreamPostD3DTextureNV12ANGLE(EGLDisplay dpy, E
#define EGL_CONTEXT_WEBGL_COMPATIBILITY_ANGLE 0x3AAC #define EGL_CONTEXT_WEBGL_COMPATIBILITY_ANGLE 0x3AAC
#endif /* EGL_ANGLE_create_context_webgl_compatibility */ #endif /* EGL_ANGLE_create_context_webgl_compatibility */
#ifndef EGL_CHROMIUM_create_context_bind_generates_resource
#define EGL_CHROMIUM_create_context_bind_generates_resource 1
#define EGL_CONTEXT_BIND_GENERATES_RESOURCE_CHROMIUM 0x3AAD
#endif /* EGL_CHROMIUM_create_context_bind_generates_resource */
#ifndef EGL_ARM_pixmap_multisample_discard #ifndef EGL_ARM_pixmap_multisample_discard
#define EGL_ARM_pixmap_multisample_discard 1 #define EGL_ARM_pixmap_multisample_discard 1
#define EGL_DISCARD_SAMPLES_ARM 0x3286 #define EGL_DISCARD_SAMPLES_ARM 0x3286
......
...@@ -838,6 +838,11 @@ GL_APICALL void GL_APIENTRY glCoverageModulationCHROMIUM(GLenum components); ...@@ -838,6 +838,11 @@ GL_APICALL void GL_APIENTRY glCoverageModulationCHROMIUM(GLenum components);
#endif #endif
#endif /* GL_CHROMIUM_framebuffer_mixed_samples */ #endif /* GL_CHROMIUM_framebuffer_mixed_samples */
#ifndef GL_CHROMIUM_bind_generates_resource
#define GL_CHROMIUM_bind_generates_resource 1
#define GL_BIND_GENERATES_RESOURCE_CHROMIUM 0x9244
#endif /* GL_CHROMIUM_bind_generates_resource */
// needed by NV_path_rendering (and thus CHROMIUM_path_rendering) // needed by NV_path_rendering (and thus CHROMIUM_path_rendering)
// but CHROMIUM_path_rendering only needs MatrixLoadfEXT, MatrixLoadIdentityEXT // but CHROMIUM_path_rendering only needs MatrixLoadfEXT, MatrixLoadIdentityEXT
#ifndef GL_EXT_direct_state_access #ifndef GL_EXT_direct_state_access
......
...@@ -167,6 +167,7 @@ Extensions::Extensions() ...@@ -167,6 +167,7 @@ Extensions::Extensions()
syncQuery(false), syncQuery(false),
copyTexture(false), copyTexture(false),
webglCompatibility(false), webglCompatibility(false),
bindGeneratesResource(false),
colorBufferFloat(false), colorBufferFloat(false),
multisampleCompatibility(false), multisampleCompatibility(false),
framebufferMixedSamples(false), framebufferMixedSamples(false),
...@@ -579,6 +580,7 @@ const ExtensionInfoMap &GetExtensionInfoMap() ...@@ -579,6 +580,7 @@ const ExtensionInfoMap &GetExtensionInfoMap()
map["GL_CHROMIUM_sync_query"] = esOnlyExtension(&Extensions::syncQuery); map["GL_CHROMIUM_sync_query"] = esOnlyExtension(&Extensions::syncQuery);
map["GL_CHROMIUM_copy_texture"] = esOnlyExtension(&Extensions::copyTexture); map["GL_CHROMIUM_copy_texture"] = esOnlyExtension(&Extensions::copyTexture);
map["GL_ANGLE_webgl_compatibility"] = esOnlyExtension(&Extensions::webglCompatibility); map["GL_ANGLE_webgl_compatibility"] = esOnlyExtension(&Extensions::webglCompatibility);
map["GL_CHROMIUM_bind_generates_resource"] = esOnlyExtension(&Extensions::bindGeneratesResource);
map["GL_EXT_multisample_compatibility"] = esOnlyExtension(&Extensions::multisampleCompatibility); map["GL_EXT_multisample_compatibility"] = esOnlyExtension(&Extensions::multisampleCompatibility);
map["GL_CHROMIUM_framebuffer_mixed_samples"] = esOnlyExtension(&Extensions::framebufferMixedSamples); map["GL_CHROMIUM_framebuffer_mixed_samples"] = esOnlyExtension(&Extensions::framebufferMixedSamples);
map["GL_EXT_texture_norm16"] = esOnlyExtension(&Extensions::textureNorm16); map["GL_EXT_texture_norm16"] = esOnlyExtension(&Extensions::textureNorm16);
...@@ -777,7 +779,8 @@ DisplayExtensions::DisplayExtensions() ...@@ -777,7 +779,8 @@ DisplayExtensions::DisplayExtensions()
streamConsumerGLTexture(false), streamConsumerGLTexture(false),
streamConsumerGLTextureYUV(false), streamConsumerGLTextureYUV(false),
streamProducerD3DTextureNV12(false), streamProducerD3DTextureNV12(false),
createContextWebGLCompatibility(false) createContextWebGLCompatibility(false),
createContextBindGeneratesResource(false)
{ {
} }
...@@ -786,34 +789,35 @@ std::vector<std::string> DisplayExtensions::getStrings() const ...@@ -786,34 +789,35 @@ std::vector<std::string> DisplayExtensions::getStrings() const
std::vector<std::string> extensionStrings; std::vector<std::string> extensionStrings;
// clang-format off // clang-format off
// | Extension name | Supported flag | Output vector | // | Extension name | Supported flag | Output vector |
InsertExtensionString("EGL_EXT_create_context_robustness", createContextRobustness, &extensionStrings); InsertExtensionString("EGL_EXT_create_context_robustness", createContextRobustness, &extensionStrings);
InsertExtensionString("EGL_ANGLE_d3d_share_handle_client_buffer", d3dShareHandleClientBuffer, &extensionStrings); InsertExtensionString("EGL_ANGLE_d3d_share_handle_client_buffer", d3dShareHandleClientBuffer, &extensionStrings);
InsertExtensionString("EGL_ANGLE_surface_d3d_texture_2d_share_handle", surfaceD3DTexture2DShareHandle, &extensionStrings); InsertExtensionString("EGL_ANGLE_surface_d3d_texture_2d_share_handle", surfaceD3DTexture2DShareHandle, &extensionStrings);
InsertExtensionString("EGL_ANGLE_query_surface_pointer", querySurfacePointer, &extensionStrings); InsertExtensionString("EGL_ANGLE_query_surface_pointer", querySurfacePointer, &extensionStrings);
InsertExtensionString("EGL_ANGLE_window_fixed_size", windowFixedSize, &extensionStrings); InsertExtensionString("EGL_ANGLE_window_fixed_size", windowFixedSize, &extensionStrings);
InsertExtensionString("EGL_ANGLE_keyed_mutex", keyedMutex, &extensionStrings); InsertExtensionString("EGL_ANGLE_keyed_mutex", keyedMutex, &extensionStrings);
InsertExtensionString("EGL_ANGLE_surface_orientation", surfaceOrientation, &extensionStrings); InsertExtensionString("EGL_ANGLE_surface_orientation", surfaceOrientation, &extensionStrings);
InsertExtensionString("EGL_ANGLE_direct_composition", directComposition, &extensionStrings); InsertExtensionString("EGL_ANGLE_direct_composition", directComposition, &extensionStrings);
InsertExtensionString("EGL_NV_post_sub_buffer", postSubBuffer, &extensionStrings); InsertExtensionString("EGL_NV_post_sub_buffer", postSubBuffer, &extensionStrings);
InsertExtensionString("EGL_KHR_create_context", createContext, &extensionStrings); InsertExtensionString("EGL_KHR_create_context", createContext, &extensionStrings);
InsertExtensionString("EGL_EXT_device_query", deviceQuery, &extensionStrings); InsertExtensionString("EGL_EXT_device_query", deviceQuery, &extensionStrings);
InsertExtensionString("EGL_KHR_image", image, &extensionStrings); InsertExtensionString("EGL_KHR_image", image, &extensionStrings);
InsertExtensionString("EGL_KHR_image_base", imageBase, &extensionStrings); InsertExtensionString("EGL_KHR_image_base", imageBase, &extensionStrings);
InsertExtensionString("EGL_KHR_image_pixmap", imagePixmap, &extensionStrings); InsertExtensionString("EGL_KHR_image_pixmap", imagePixmap, &extensionStrings);
InsertExtensionString("EGL_KHR_gl_texture_2D_image", glTexture2DImage, &extensionStrings); InsertExtensionString("EGL_KHR_gl_texture_2D_image", glTexture2DImage, &extensionStrings);
InsertExtensionString("EGL_KHR_gl_texture_cubemap_image", glTextureCubemapImage, &extensionStrings); InsertExtensionString("EGL_KHR_gl_texture_cubemap_image", glTextureCubemapImage, &extensionStrings);
InsertExtensionString("EGL_KHR_gl_texture_3D_image", glTexture3DImage, &extensionStrings); InsertExtensionString("EGL_KHR_gl_texture_3D_image", glTexture3DImage, &extensionStrings);
InsertExtensionString("EGL_KHR_gl_renderbuffer_image", glRenderbufferImage, &extensionStrings); InsertExtensionString("EGL_KHR_gl_renderbuffer_image", glRenderbufferImage, &extensionStrings);
InsertExtensionString("EGL_KHR_get_all_proc_addresses", getAllProcAddresses, &extensionStrings); InsertExtensionString("EGL_KHR_get_all_proc_addresses", getAllProcAddresses, &extensionStrings);
InsertExtensionString("EGL_KHR_stream", stream, &extensionStrings); InsertExtensionString("EGL_KHR_stream", stream, &extensionStrings);
InsertExtensionString("EGL_KHR_stream_consumer_gltexture", streamConsumerGLTexture, &extensionStrings); InsertExtensionString("EGL_KHR_stream_consumer_gltexture", streamConsumerGLTexture, &extensionStrings);
InsertExtensionString("EGL_NV_stream_consumer_gltexture_yuv", streamConsumerGLTextureYUV, &extensionStrings); InsertExtensionString("EGL_NV_stream_consumer_gltexture_yuv", streamConsumerGLTextureYUV, &extensionStrings);
InsertExtensionString("EGL_ANGLE_flexible_surface_compatibility", flexibleSurfaceCompatibility, &extensionStrings); InsertExtensionString("EGL_ANGLE_flexible_surface_compatibility", flexibleSurfaceCompatibility, &extensionStrings);
InsertExtensionString("EGL_ANGLE_stream_producer_d3d_texture_nv12", streamProducerD3DTextureNV12, &extensionStrings); InsertExtensionString("EGL_ANGLE_stream_producer_d3d_texture_nv12", streamProducerD3DTextureNV12, &extensionStrings);
InsertExtensionString("EGL_ANGLE_create_context_webgl_compatibility", createContextWebGLCompatibility,&extensionStrings); InsertExtensionString("EGL_ANGLE_create_context_webgl_compatibility", createContextWebGLCompatibility, &extensionStrings);
InsertExtensionString("EGL_CHROMIUM_create_context_bind_generates_resource", createContextBindGeneratesResource, &extensionStrings);
// TODO(jmadill): Enable this when complete. // TODO(jmadill): Enable this when complete.
//InsertExtensionString("KHR_create_context_no_error", createContextNoError, &extensionStrings); //InsertExtensionString("KHR_create_context_no_error", createContextNoError, &extensionStrings);
// clang-format on // clang-format on
return extensionStrings; return extensionStrings;
......
...@@ -296,6 +296,9 @@ struct Extensions ...@@ -296,6 +296,9 @@ struct Extensions
// GL_ANGLE_webgl_compatibility // GL_ANGLE_webgl_compatibility
bool webglCompatibility; bool webglCompatibility;
// GL_CHROMIUM_bind_generates_resource
bool bindGeneratesResource;
// ES3 Extension support // ES3 Extension support
// GL_EXT_color_buffer_float // GL_EXT_color_buffer_float
...@@ -592,6 +595,9 @@ struct DisplayExtensions ...@@ -592,6 +595,9 @@ struct DisplayExtensions
// EGL_ANGLE_create_context_webgl_compatibility // EGL_ANGLE_create_context_webgl_compatibility
bool createContextWebGLCompatibility; bool createContextWebGLCompatibility;
// EGL_CHROMIUM_create_context_bind_generates_resource
bool createContextBindGeneratesResource;
}; };
struct DeviceExtensions struct DeviceExtensions
......
...@@ -184,6 +184,11 @@ bool GetWebGLContext(const egl::AttributeMap &attribs) ...@@ -184,6 +184,11 @@ bool GetWebGLContext(const egl::AttributeMap &attribs)
return (attribs.get(EGL_CONTEXT_WEBGL_COMPATIBILITY_ANGLE, EGL_FALSE) == EGL_TRUE); return (attribs.get(EGL_CONTEXT_WEBGL_COMPATIBILITY_ANGLE, EGL_FALSE) == EGL_TRUE);
} }
bool GetBindGeneratesResource(const egl::AttributeMap &attribs)
{
return (attribs.get(EGL_CONTEXT_BIND_GENERATES_RESOURCE_CHROMIUM, EGL_TRUE) == EGL_TRUE);
}
std::string GetObjectLabelFromPointer(GLsizei length, const GLchar *label) std::string GetObjectLabelFromPointer(GLsizei length, const GLchar *label)
{ {
std::string labelName; std::string labelName;
...@@ -251,7 +256,8 @@ Context::Context(rx::EGLImplFactory *implFactory, ...@@ -251,7 +256,8 @@ Context::Context(rx::EGLImplFactory *implFactory,
initCaps(GetWebGLContext(attribs)); initCaps(GetWebGLContext(attribs));
mGLState.initialize(mCaps, mExtensions, mClientMajorVersion, GetDebug(attribs)); mGLState.initialize(mCaps, mExtensions, mClientMajorVersion, GetDebug(attribs),
GetBindGeneratesResource(attribs));
mFenceNVHandleAllocator.setBaseHandle(0); mFenceNVHandleAllocator.setBaseHandle(0);
...@@ -2080,13 +2086,36 @@ Framebuffer *Context::checkFramebufferAllocation(GLuint framebuffer) ...@@ -2080,13 +2086,36 @@ Framebuffer *Context::checkFramebufferAllocation(GLuint framebuffer)
return framebufferIt->second; return framebufferIt->second;
} }
bool Context::isTextureGenerated(GLuint texture) const
{
return mResourceManager->isTextureGenerated(texture);
}
bool Context::isBufferGenerated(GLuint buffer) const
{
return mResourceManager->isBufferGenerated(buffer);
}
bool Context::isRenderbufferGenerated(GLuint renderbuffer) const
{
return mResourceManager->isRenderbufferGenerated(renderbuffer);
}
bool Context::isFramebufferGenerated(GLuint framebuffer) const
{
ASSERT(mFramebufferMap.find(0) != mFramebufferMap.end());
return mFramebufferMap.find(framebuffer) != mFramebufferMap.end();
}
bool Context::isVertexArrayGenerated(GLuint vertexArray) bool Context::isVertexArrayGenerated(GLuint vertexArray)
{ {
ASSERT(mVertexArrayMap.find(0) != mVertexArrayMap.end());
return mVertexArrayMap.find(vertexArray) != mVertexArrayMap.end(); return mVertexArrayMap.find(vertexArray) != mVertexArrayMap.end();
} }
bool Context::isTransformFeedbackGenerated(GLuint transformFeedback) bool Context::isTransformFeedbackGenerated(GLuint transformFeedback)
{ {
ASSERT(mTransformFeedbackMap.find(0) != mTransformFeedbackMap.end());
return mTransformFeedbackMap.find(transformFeedback) != mTransformFeedbackMap.end(); return mTransformFeedbackMap.find(transformFeedback) != mTransformFeedbackMap.end();
} }
...@@ -2376,6 +2405,7 @@ void Context::initCaps(bool webGLContext) ...@@ -2376,6 +2405,7 @@ void Context::initCaps(bool webGLContext)
// Some extensions are always available because they are implemented in the GL layer. // Some extensions are always available because they are implemented in the GL layer.
mExtensions.bindUniformLocation = true; mExtensions.bindUniformLocation = true;
mExtensions.vertexArrayObject = true; mExtensions.vertexArrayObject = true;
mExtensions.bindGeneratesResource = true;
// Enable the no error extension if the context was created with the flag. // Enable the no error extension if the context was created with the flag.
mExtensions.noError = mSkipValidation; mExtensions.noError = mSkipValidation;
......
...@@ -191,6 +191,10 @@ class Context final : public ValidationContext ...@@ -191,6 +191,10 @@ class Context final : public ValidationContext
bool isSampler(GLuint samplerName) const; bool isSampler(GLuint samplerName) const;
bool isTextureGenerated(GLuint texture) const;
bool isBufferGenerated(GLuint buffer) const;
bool isRenderbufferGenerated(GLuint renderbuffer) const;
bool isFramebufferGenerated(GLuint framebuffer) const;
bool isVertexArrayGenerated(GLuint vertexArray); bool isVertexArrayGenerated(GLuint vertexArray);
bool isTransformFeedbackGenerated(GLuint vertexArray); bool isTransformFeedbackGenerated(GLuint vertexArray);
......
...@@ -327,6 +327,17 @@ bool ValidationContext::getQueryParameterInfo(GLenum pname, GLenum *type, unsign ...@@ -327,6 +327,17 @@ bool ValidationContext::getQueryParameterInfo(GLenum pname, GLenum *type, unsign
} }
} }
if (getExtensions().bindGeneratesResource)
{
switch (pname)
{
case GL_BIND_GENERATES_RESOURCE_CHROMIUM:
*type = GL_BOOL;
*numParams = 1;
return true;
}
}
// Check for ES3.0+ parameter names which are also exposed as ES2 extensions // Check for ES3.0+ parameter names which are also exposed as ES2 extensions
switch (pname) switch (pname)
{ {
......
...@@ -919,6 +919,7 @@ void Display::initDisplayExtensions() ...@@ -919,6 +919,7 @@ void Display::initDisplayExtensions()
mDisplayExtensions.createContext = true; mDisplayExtensions.createContext = true;
mDisplayExtensions.createContextNoError = true; mDisplayExtensions.createContextNoError = true;
mDisplayExtensions.createContextWebGLCompatibility = true; mDisplayExtensions.createContextWebGLCompatibility = true;
mDisplayExtensions.createContextBindGeneratesResource = true;
// Force EGL_KHR_get_all_proc_addresses on. // Force EGL_KHR_get_all_proc_addresses on.
mDisplayExtensions.getAllProcAddresses = true; mDisplayExtensions.getAllProcAddresses = true;
......
...@@ -544,4 +544,19 @@ bool ResourceManager::isSampler(GLuint sampler) ...@@ -544,4 +544,19 @@ bool ResourceManager::isSampler(GLuint sampler)
return mSamplerMap.find(sampler) != mSamplerMap.end(); return mSamplerMap.find(sampler) != mSamplerMap.end();
} }
bool ResourceManager::isTextureGenerated(GLuint texture) const
{
return texture == 0 || mTextureMap.find(texture) != mTextureMap.end();
}
bool ResourceManager::isBufferGenerated(GLuint buffer) const
{
return buffer == 0 || mBufferMap.find(buffer) != mBufferMap.end();
}
bool ResourceManager::isRenderbufferGenerated(GLuint renderbuffer) const
{
return renderbuffer == 0 || mRenderbufferMap.find(renderbuffer) != mRenderbufferMap.end();
}
} // namespace gl } // namespace gl
...@@ -85,6 +85,11 @@ class ResourceManager : angle::NonCopyable ...@@ -85,6 +85,11 @@ class ResourceManager : angle::NonCopyable
bool isSampler(GLuint sampler); bool isSampler(GLuint sampler);
// GL_CHROMIUM_bind_generates_resource
bool isTextureGenerated(GLuint texture) const;
bool isBufferGenerated(GLuint buffer) const;
bool isRenderbufferGenerated(GLuint renderbuffer) const;
private: private:
void createTextureInternal(GLuint handle); void createTextureInternal(GLuint handle);
......
...@@ -50,6 +50,7 @@ State::State() ...@@ -50,6 +50,7 @@ State::State()
mLineWidth(0), mLineWidth(0),
mGenerateMipmapHint(GL_NONE), mGenerateMipmapHint(GL_NONE),
mFragmentShaderDerivativeHint(GL_NONE), mFragmentShaderDerivativeHint(GL_NONE),
mBindGeneratesResource(true),
mNearZ(0), mNearZ(0),
mFarZ(0), mFarZ(0),
mReadFramebuffer(nullptr), mReadFramebuffer(nullptr),
...@@ -71,7 +72,8 @@ State::~State() ...@@ -71,7 +72,8 @@ State::~State()
void State::initialize(const Caps &caps, void State::initialize(const Caps &caps,
const Extensions &extensions, const Extensions &extensions,
GLuint clientVersion, GLuint clientVersion,
bool debug) bool debug,
bool bindGeneratesResource)
{ {
mMaxDrawBuffers = caps.maxDrawBuffers; mMaxDrawBuffers = caps.maxDrawBuffers;
mMaxCombinedTextureImageUnits = caps.maxCombinedTextureImageUnits; mMaxCombinedTextureImageUnits = caps.maxCombinedTextureImageUnits;
...@@ -137,6 +139,8 @@ void State::initialize(const Caps &caps, ...@@ -137,6 +139,8 @@ void State::initialize(const Caps &caps,
mGenerateMipmapHint = GL_DONT_CARE; mGenerateMipmapHint = GL_DONT_CARE;
mFragmentShaderDerivativeHint = GL_DONT_CARE; mFragmentShaderDerivativeHint = GL_DONT_CARE;
mBindGeneratesResource = bindGeneratesResource;
mLineWidth = 1.0f; mLineWidth = 1.0f;
mViewport.x = 0; mViewport.x = 0;
...@@ -658,6 +662,8 @@ bool State::getEnableFeature(GLenum feature) const ...@@ -658,6 +662,8 @@ bool State::getEnableFeature(GLenum feature) const
return mDebug.isOutputSynchronous(); return mDebug.isOutputSynchronous();
case GL_DEBUG_OUTPUT: case GL_DEBUG_OUTPUT:
return mDebug.isOutputEnabled(); return mDebug.isOutputEnabled();
case GL_BIND_GENERATES_RESOURCE_CHROMIUM:
return isBindGeneratesResourceEnabled();
default: UNREACHABLE(); return false; default: UNREACHABLE(); return false;
} }
} }
...@@ -688,6 +694,11 @@ void State::setFragmentShaderDerivativeHint(GLenum hint) ...@@ -688,6 +694,11 @@ void State::setFragmentShaderDerivativeHint(GLenum hint)
// Ignore for now. It is valid for implementations to ignore hint. // Ignore for now. It is valid for implementations to ignore hint.
} }
bool State::isBindGeneratesResourceEnabled() const
{
return mBindGeneratesResource;
}
void State::setViewportParams(GLint x, GLint y, GLsizei width, GLsizei height) void State::setViewportParams(GLint x, GLint y, GLsizei width, GLsizei height)
{ {
mViewport.x = x; mViewport.x = x;
...@@ -1486,6 +1497,9 @@ void State::getBooleanv(GLenum pname, GLboolean *params) ...@@ -1486,6 +1497,9 @@ void State::getBooleanv(GLenum pname, GLboolean *params)
case GL_SAMPLE_ALPHA_TO_ONE_EXT: case GL_SAMPLE_ALPHA_TO_ONE_EXT:
*params = mSampleAlphaToOne; *params = mSampleAlphaToOne;
break; break;
case GL_BIND_GENERATES_RESOURCE_CHROMIUM:
*params = isBindGeneratesResourceEnabled() ? GL_TRUE : GL_FALSE;
break;
default: default:
UNREACHABLE(); UNREACHABLE();
break; break;
......
...@@ -42,7 +42,8 @@ class State : angle::NonCopyable ...@@ -42,7 +42,8 @@ class State : angle::NonCopyable
void initialize(const Caps &caps, void initialize(const Caps &caps,
const Extensions &extensions, const Extensions &extensions,
GLuint clientVersion, GLuint clientVersion,
bool debug); bool debug,
bool bindGeneratesResource);
void reset(); void reset();
// State chunk getters // State chunk getters
...@@ -147,6 +148,9 @@ class State : angle::NonCopyable ...@@ -147,6 +148,9 @@ class State : angle::NonCopyable
void setGenerateMipmapHint(GLenum hint); void setGenerateMipmapHint(GLenum hint);
void setFragmentShaderDerivativeHint(GLenum hint); void setFragmentShaderDerivativeHint(GLenum hint);
// GL_CHROMIUM_bind_generates_resource
bool isBindGeneratesResourceEnabled() const;
// Viewport state setter/getter // Viewport state setter/getter
void setViewportParams(GLint x, GLint y, GLsizei width, GLsizei height); void setViewportParams(GLint x, GLint y, GLsizei width, GLsizei height);
const Rectangle &getViewport() const; const Rectangle &getViewport() const;
...@@ -418,6 +422,8 @@ class State : angle::NonCopyable ...@@ -418,6 +422,8 @@ class State : angle::NonCopyable
GLenum mGenerateMipmapHint; GLenum mGenerateMipmapHint;
GLenum mFragmentShaderDerivativeHint; GLenum mFragmentShaderDerivativeHint;
bool mBindGeneratesResource;
Rectangle mViewport; Rectangle mViewport;
float mNearZ; float mNearZ;
float mFarZ; float mFarZ;
......
...@@ -342,6 +342,21 @@ Error ValidateCreateContext(Display *display, Config *configuration, gl::Context ...@@ -342,6 +342,21 @@ Error ValidateCreateContext(Display *display, Config *configuration, gl::Context
} }
break; break;
case EGL_CONTEXT_BIND_GENERATES_RESOURCE_CHROMIUM:
if (!display->getExtensions().createContextBindGeneratesResource)
{
return Error(EGL_BAD_ATTRIBUTE,
"Attribute EGL_CONTEXT_BIND_GENERATES_RESOURCE_CHROMIUM requires "
"EGL_CHROMIUM_create_context_bind_generates_resource.");
}
if (value != EGL_TRUE && value != EGL_FALSE)
{
return Error(EGL_BAD_ATTRIBUTE,
"EGL_CONTEXT_BIND_GENERATES_RESOURCE_CHROMIUM must be EGL_TRUE or "
"EGL_FALSE.");
}
break;
default: default:
return Error(EGL_BAD_ATTRIBUTE); return Error(EGL_BAD_ATTRIBUTE);
} }
......
...@@ -131,41 +131,44 @@ bool ValidReadPixelsFormatType(ValidationContext *context, ...@@ -131,41 +131,44 @@ bool ValidReadPixelsFormatType(ValidationContext *context,
} }
} }
} // anonymous namespace bool ValidCap(const Context *context, GLenum cap, bool queryOnly)
bool ValidCap(const Context *context, GLenum cap)
{ {
switch (cap) switch (cap)
{ {
// EXT_multisample_compatibility // EXT_multisample_compatibility
case GL_MULTISAMPLE_EXT: case GL_MULTISAMPLE_EXT:
case GL_SAMPLE_ALPHA_TO_ONE_EXT: case GL_SAMPLE_ALPHA_TO_ONE_EXT:
return context->getExtensions().multisampleCompatibility; return context->getExtensions().multisampleCompatibility;
case GL_CULL_FACE: case GL_CULL_FACE:
case GL_POLYGON_OFFSET_FILL: case GL_POLYGON_OFFSET_FILL:
case GL_SAMPLE_ALPHA_TO_COVERAGE: case GL_SAMPLE_ALPHA_TO_COVERAGE:
case GL_SAMPLE_COVERAGE: case GL_SAMPLE_COVERAGE:
case GL_SCISSOR_TEST: case GL_SCISSOR_TEST:
case GL_STENCIL_TEST: case GL_STENCIL_TEST:
case GL_DEPTH_TEST: case GL_DEPTH_TEST:
case GL_BLEND: case GL_BLEND:
case GL_DITHER: case GL_DITHER:
return true; return true;
case GL_PRIMITIVE_RESTART_FIXED_INDEX: case GL_PRIMITIVE_RESTART_FIXED_INDEX:
case GL_RASTERIZER_DISCARD: case GL_RASTERIZER_DISCARD:
return (context->getClientMajorVersion() >= 3); return (context->getClientMajorVersion() >= 3);
case GL_DEBUG_OUTPUT_SYNCHRONOUS: case GL_DEBUG_OUTPUT_SYNCHRONOUS:
case GL_DEBUG_OUTPUT: case GL_DEBUG_OUTPUT:
return context->getExtensions().debug; return context->getExtensions().debug;
default: case GL_BIND_GENERATES_RESOURCE_CHROMIUM:
return false; return queryOnly && context->getExtensions().bindGeneratesResource;
default:
return false;
} }
} }
} // anonymous namespace
bool ValidTextureTarget(const ValidationContext *context, GLenum target) bool ValidTextureTarget(const ValidationContext *context, GLenum target)
{ {
switch (target) switch (target)
...@@ -3133,4 +3136,50 @@ bool ValidateGenOrDelete(Context *context, GLint n) ...@@ -3133,4 +3136,50 @@ bool ValidateGenOrDelete(Context *context, GLint n)
return true; return true;
} }
bool ValidateEnable(Context *context, GLenum cap)
{
if (!ValidCap(context, cap, false))
{
context->handleError(Error(GL_INVALID_ENUM, "Invalid cap."));
return false;
}
if (context->getLimitations().noSampleAlphaToCoverageSupport &&
cap == GL_SAMPLE_ALPHA_TO_COVERAGE)
{
const char *errorMessage = "Current renderer doesn't support alpha-to-coverage";
context->handleError(Error(GL_INVALID_OPERATION, errorMessage));
// We also output an error message to the debugger window if tracing is active, so that
// developers can see the error message.
ERR("%s", errorMessage);
return false;
}
return true;
}
bool ValidateDisable(Context *context, GLenum cap)
{
if (!ValidCap(context, cap, false))
{
context->handleError(Error(GL_INVALID_ENUM, "Invalid cap."));
return false;
}
return true;
}
bool ValidateIsEnabled(Context *context, GLenum cap)
{
if (!ValidCap(context, cap, true))
{
context->handleError(Error(GL_INVALID_ENUM, "Invalid cap."));
return false;
}
return true;
}
} // namespace gl } // namespace gl
...@@ -29,7 +29,6 @@ class Program; ...@@ -29,7 +29,6 @@ class Program;
class Shader; class Shader;
class ValidationContext; class ValidationContext;
bool ValidCap(const Context *context, GLenum cap);
bool ValidTextureTarget(const ValidationContext *context, GLenum target); bool ValidTextureTarget(const ValidationContext *context, GLenum target);
bool ValidTexture2DTarget(const ValidationContext *context, GLenum target); bool ValidTexture2DTarget(const ValidationContext *context, GLenum target);
bool ValidTexture3DTarget(const ValidationContext *context, GLenum target); bool ValidTexture3DTarget(const ValidationContext *context, GLenum target);
...@@ -270,6 +269,10 @@ bool ValidateDeleteTextures(Context *context, GLint n, const GLuint *textures); ...@@ -270,6 +269,10 @@ bool ValidateDeleteTextures(Context *context, GLint n, const GLuint *textures);
bool ValidateGenOrDelete(Context *context, GLint n); bool ValidateGenOrDelete(Context *context, GLint n);
bool ValidateEnable(Context *context, GLenum cap);
bool ValidateDisable(Context *context, GLenum cap);
bool ValidateIsEnabled(Context *context, GLenum cap);
// Error messages shared here for use in testing. // Error messages shared here for use in testing.
extern const char *g_ExceedsMaxElementErrorMessage; extern const char *g_ExceedsMaxElementErrorMessage;
} // namespace gl } // namespace gl
......
...@@ -2187,6 +2187,13 @@ bool ValidateBindTexture(Context *context, GLenum target, GLuint texture) ...@@ -2187,6 +2187,13 @@ bool ValidateBindTexture(Context *context, GLenum target, GLuint texture)
return false; return false;
} }
if (!context->getGLState().isBindGeneratesResourceEnabled() &&
!context->isTextureGenerated(texture))
{
context->handleError(Error(GL_INVALID_OPERATION, "Texture was not generated"));
return false;
}
switch (target) switch (target)
{ {
case GL_TEXTURE_2D: case GL_TEXTURE_2D:
......
...@@ -87,7 +87,7 @@ TEST(ValidationESTest, DrawElementsWithMaxIndexGivesError) ...@@ -87,7 +87,7 @@ TEST(ValidationESTest, DrawElementsWithMaxIndexGivesError)
caps.maxElementIndex = 100; caps.maxElementIndex = 100;
caps.maxDrawBuffers = 1; caps.maxDrawBuffers = 1;
caps.maxColorAttachments = 1; caps.maxColorAttachments = 1;
state.initialize(caps, extensions, 3, false); state.initialize(caps, extensions, 3, false, true);
NiceMock<MockTextureImpl> *textureImpl = new NiceMock<MockTextureImpl>(); NiceMock<MockTextureImpl> *textureImpl = new NiceMock<MockTextureImpl>();
EXPECT_CALL(mockFactory, createTexture(_)).WillOnce(Return(textureImpl)); EXPECT_CALL(mockFactory, createTexture(_)).WillOnce(Return(textureImpl));
......
...@@ -123,6 +123,13 @@ void GL_APIENTRY BindBuffer(GLenum target, GLuint buffer) ...@@ -123,6 +123,13 @@ void GL_APIENTRY BindBuffer(GLenum target, GLuint buffer)
return; return;
} }
if (!context->getGLState().isBindGeneratesResourceEnabled() &&
!context->isBufferGenerated(buffer))
{
context->handleError(Error(GL_INVALID_OPERATION, "Buffer was not generated"));
return;
}
switch (target) switch (target)
{ {
case GL_ARRAY_BUFFER: case GL_ARRAY_BUFFER:
...@@ -170,6 +177,13 @@ void GL_APIENTRY BindFramebuffer(GLenum target, GLuint framebuffer) ...@@ -170,6 +177,13 @@ void GL_APIENTRY BindFramebuffer(GLenum target, GLuint framebuffer)
return; return;
} }
if (!context->getGLState().isBindGeneratesResourceEnabled() &&
!context->isFramebufferGenerated(framebuffer))
{
context->handleError(Error(GL_INVALID_OPERATION, "Framebuffer was not generated"));
return;
}
if (target == GL_READ_FRAMEBUFFER_ANGLE || target == GL_FRAMEBUFFER) if (target == GL_READ_FRAMEBUFFER_ANGLE || target == GL_FRAMEBUFFER)
{ {
context->bindReadFramebuffer(framebuffer); context->bindReadFramebuffer(framebuffer);
...@@ -195,6 +209,13 @@ void GL_APIENTRY BindRenderbuffer(GLenum target, GLuint renderbuffer) ...@@ -195,6 +209,13 @@ void GL_APIENTRY BindRenderbuffer(GLenum target, GLuint renderbuffer)
return; return;
} }
if (!context->getGLState().isBindGeneratesResourceEnabled() &&
!context->isRenderbufferGenerated(renderbuffer))
{
context->handleError(Error(GL_INVALID_OPERATION, "Renderbuffer was not generated"));
return;
}
context->bindRenderbuffer(renderbuffer); context->bindRenderbuffer(renderbuffer);
} }
} }
...@@ -917,9 +938,8 @@ void GL_APIENTRY Disable(GLenum cap) ...@@ -917,9 +938,8 @@ void GL_APIENTRY Disable(GLenum cap)
Context *context = GetValidGlobalContext(); Context *context = GetValidGlobalContext();
if (context) if (context)
{ {
if (!ValidCap(context, cap)) if (!context->skipValidation() && !ValidateDisable(context, cap))
{ {
context->handleError(Error(GL_INVALID_ENUM));
return; return;
} }
...@@ -995,26 +1015,11 @@ void GL_APIENTRY Enable(GLenum cap) ...@@ -995,26 +1015,11 @@ void GL_APIENTRY Enable(GLenum cap)
Context *context = GetValidGlobalContext(); Context *context = GetValidGlobalContext();
if (context) if (context)
{ {
if (!ValidCap(context, cap)) if (!context->skipValidation() && !ValidateEnable(context, cap))
{ {
context->handleError(Error(GL_INVALID_ENUM));
return; return;
} }
if (context->getLimitations().noSampleAlphaToCoverageSupport)
{
if (cap == GL_SAMPLE_ALPHA_TO_COVERAGE)
{
const char *errorMessage = "Current renderer doesn't support alpha-to-coverage";
context->handleError(Error(GL_INVALID_OPERATION, errorMessage));
// We also output an error message to the debugger window if tracing is active, so that developers can see the error message.
ERR("%s", errorMessage);
return;
}
}
context->enable(cap); context->enable(cap);
} }
} }
...@@ -2677,9 +2682,8 @@ GLboolean GL_APIENTRY IsEnabled(GLenum cap) ...@@ -2677,9 +2682,8 @@ GLboolean GL_APIENTRY IsEnabled(GLenum cap)
Context *context = GetValidGlobalContext(); Context *context = GetValidGlobalContext();
if (context) if (context)
{ {
if (!ValidCap(context, cap)) if (!context->skipValidation() && !ValidateIsEnabled(context, cap))
{ {
context->handleError(Error(GL_INVALID_ENUM));
return GL_FALSE; return GL_FALSE;
} }
......
...@@ -759,6 +759,13 @@ void GL_APIENTRY BindBufferRange(GLenum target, GLuint index, GLuint buffer, GLi ...@@ -759,6 +759,13 @@ void GL_APIENTRY BindBufferRange(GLenum target, GLuint index, GLuint buffer, GLi
return; return;
} }
if (!context->getGLState().isBindGeneratesResourceEnabled() &&
!context->isBufferGenerated(buffer))
{
context->handleError(Error(GL_INVALID_OPERATION, "Buffer was not generated"));
return;
}
switch (target) switch (target)
{ {
case GL_TRANSFORM_FEEDBACK_BUFFER: case GL_TRANSFORM_FEEDBACK_BUFFER:
...@@ -841,6 +848,13 @@ void GL_APIENTRY BindBufferBase(GLenum target, GLuint index, GLuint buffer) ...@@ -841,6 +848,13 @@ void GL_APIENTRY BindBufferBase(GLenum target, GLuint index, GLuint buffer)
return; return;
} }
if (!context->getGLState().isBindGeneratesResourceEnabled() &&
!context->isBufferGenerated(buffer))
{
context->handleError(Error(GL_INVALID_OPERATION, "Buffer was not generated"));
return;
}
switch (target) switch (target)
{ {
case GL_TRANSFORM_FEEDBACK_BUFFER: case GL_TRANSFORM_FEEDBACK_BUFFER:
......
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
{ {
'angle_end2end_tests_sources': 'angle_end2end_tests_sources':
[ [
'<(angle_path)/src/tests/gl_tests/BindGeneratesResourceTest.cpp',
'<(angle_path)/src/tests/gl_tests/BindUniformLocationTest.cpp', '<(angle_path)/src/tests/gl_tests/BindUniformLocationTest.cpp',
'<(angle_path)/src/tests/gl_tests/BlendMinMaxTest.cpp', '<(angle_path)/src/tests/gl_tests/BlendMinMaxTest.cpp',
'<(angle_path)/src/tests/gl_tests/BlitFramebufferANGLETest.cpp', '<(angle_path)/src/tests/gl_tests/BlitFramebufferANGLETest.cpp',
......
//
// Copyright 2015 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.
//
// BindGeneratesResourceTest.cpp : Tests of the GL_CHROMIUM_bind_generates_resource extension.
#include "test_utils/ANGLETest.h"
namespace angle
{
class BindGeneratesResourceTest : public ANGLETest
{
protected:
BindGeneratesResourceTest() { setBindGeneratesResource(false); }
};
// Context creation would fail if EGL_CHROMIUM_create_context_bind_generates_resource was not
// available so the GL extension should always be present
TEST_P(BindGeneratesResourceTest, ExtensionStringExposed)
{
EXPECT_TRUE(extensionEnabled("GL_CHROMIUM_bind_generates_resource"));
}
// Verify that GL_BIND_GENERATES_RESOURCE_CHROMIUM can be queried but not changed
TEST_P(BindGeneratesResourceTest, QueryValidation)
{
GLint intValue = 2;
glGetIntegerv(GL_BIND_GENERATES_RESOURCE_CHROMIUM, &intValue);
EXPECT_GL_NO_ERROR();
EXPECT_EQ(intValue, GL_FALSE);
float floatValue = 2.0f;
glGetFloatv(GL_BIND_GENERATES_RESOURCE_CHROMIUM, &floatValue);
EXPECT_GL_NO_ERROR();
EXPECT_EQ(floatValue, 0.0f);
GLboolean boolValue = GL_TRUE;
glGetBooleanv(GL_BIND_GENERATES_RESOURCE_CHROMIUM, &boolValue);
EXPECT_GL_NO_ERROR();
EXPECT_EQ(boolValue, GL_FALSE);
boolValue = glIsEnabled(GL_BIND_GENERATES_RESOURCE_CHROMIUM);
EXPECT_GL_NO_ERROR();
EXPECT_EQ(boolValue, GL_FALSE);
glEnable(GL_BIND_GENERATES_RESOURCE_CHROMIUM);
EXPECT_GL_ERROR(GL_INVALID_ENUM);
glDisable(GL_BIND_GENERATES_RESOURCE_CHROMIUM);
EXPECT_GL_ERROR(GL_INVALID_ENUM);
}
// Test that buffers cannot be generated on bind
TEST_P(BindGeneratesResourceTest, Buffers)
{
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 2);
EXPECT_GL_ERROR(GL_INVALID_OPERATION);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
EXPECT_GL_NO_ERROR();
if (getClientMajorVersion() >= 3)
{
glBindBufferBase(GL_UNIFORM_BUFFER, 0, 3);
EXPECT_GL_ERROR(GL_INVALID_OPERATION);
glBindBufferBase(GL_UNIFORM_BUFFER, 0, 0);
EXPECT_GL_NO_ERROR();
glBindBufferRange(GL_UNIFORM_BUFFER, 0, 4, 1, 2);
EXPECT_GL_ERROR(GL_INVALID_OPERATION);
glBindBufferRange(GL_UNIFORM_BUFFER, 0, 0, 1, 2);
EXPECT_GL_NO_ERROR();
}
}
// Test that textures cannot be generated on bind
TEST_P(BindGeneratesResourceTest, Textures)
{
glBindTexture(GL_TEXTURE_2D, 2);
EXPECT_GL_ERROR(GL_INVALID_OPERATION);
glBindTexture(GL_TEXTURE_2D, 0);
EXPECT_GL_NO_ERROR();
}
// Test that framebuffers cannot be generated on bind
TEST_P(BindGeneratesResourceTest, Framebuffers)
{
glBindFramebuffer(GL_FRAMEBUFFER, 2);
EXPECT_GL_ERROR(GL_INVALID_OPERATION);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
EXPECT_GL_NO_ERROR();
}
// Test that renderbuffer cannot be generated on bind
TEST_P(BindGeneratesResourceTest, Renderbuffers)
{
glBindRenderbuffer(GL_RENDERBUFFER, 2);
EXPECT_GL_ERROR(GL_INVALID_OPERATION);
glBindRenderbuffer(GL_RENDERBUFFER, 0);
EXPECT_GL_NO_ERROR();
}
// Use this to select which configurations (e.g. which renderer, which GLES major version) these
// tests should be run against.
ANGLE_INSTANTIATE_TEST(BindGeneratesResourceTest,
ES2_D3D9(),
ES2_D3D11(),
ES3_D3D11(),
ES2_D3D11_FL9_3(),
ES2_OPENGL(),
ES3_OPENGL(),
ES2_OPENGLES(),
ES3_OPENGLES());
} // namespace
...@@ -609,6 +609,11 @@ void ANGLETest::setWebGLCompatibilityEnabled(bool webglCompatibility) ...@@ -609,6 +609,11 @@ void ANGLETest::setWebGLCompatibilityEnabled(bool webglCompatibility)
mEGLWindow->setWebGLCompatibilityEnabled(webglCompatibility); mEGLWindow->setWebGLCompatibilityEnabled(webglCompatibility);
} }
void ANGLETest::setBindGeneratesResource(bool bindGeneratesResource)
{
mEGLWindow->setBindGeneratesResource(bindGeneratesResource);
}
int ANGLETest::getClientMajorVersion() const int ANGLETest::getClientMajorVersion() const
{ {
return mEGLWindow->getClientMajorVersion(); return mEGLWindow->getClientMajorVersion();
......
...@@ -185,6 +185,7 @@ class ANGLETest : public ::testing::TestWithParam<angle::PlatformParameters> ...@@ -185,6 +185,7 @@ class ANGLETest : public ::testing::TestWithParam<angle::PlatformParameters>
void setDebugEnabled(bool enabled); void setDebugEnabled(bool enabled);
void setNoErrorEnabled(bool enabled); void setNoErrorEnabled(bool enabled);
void setWebGLCompatibilityEnabled(bool webglCompatibility); void setWebGLCompatibilityEnabled(bool webglCompatibility);
void setBindGeneratesResource(bool bindGeneratesResource);
int getClientMajorVersion() const; int getClientMajorVersion() const;
int getClientMinorVersion() const; int getClientMinorVersion() const;
......
...@@ -111,6 +111,7 @@ EGLWindow::EGLWindow(EGLint glesMajorVersion, ...@@ -111,6 +111,7 @@ EGLWindow::EGLWindow(EGLint glesMajorVersion,
mDebug(false), mDebug(false),
mNoError(false), mNoError(false),
mWebGLCompatibility(false), mWebGLCompatibility(false),
mBindGeneratesResource(true),
mSwapInterval(-1) mSwapInterval(-1)
{ {
} }
...@@ -216,6 +217,14 @@ bool EGLWindow::initializeGL(OSWindow *osWindow) ...@@ -216,6 +217,14 @@ bool EGLWindow::initializeGL(OSWindow *osWindow)
return false; return false;
} }
bool hasBindGeneratesResource =
strstr(displayExtensions, "EGL_CHROMIUM_create_context_bind_generates_resource") != nullptr;
if (!mBindGeneratesResource && !hasBindGeneratesResource)
{
destroyGL();
return false;
}
eglBindAPI(EGL_OPENGL_ES_API); eglBindAPI(EGL_OPENGL_ES_API);
if (eglGetError() != EGL_SUCCESS) if (eglGetError() != EGL_SUCCESS)
{ {
...@@ -290,6 +299,12 @@ bool EGLWindow::initializeGL(OSWindow *osWindow) ...@@ -290,6 +299,12 @@ bool EGLWindow::initializeGL(OSWindow *osWindow)
contextAttributes.push_back(EGL_CONTEXT_WEBGL_COMPATIBILITY_ANGLE); contextAttributes.push_back(EGL_CONTEXT_WEBGL_COMPATIBILITY_ANGLE);
contextAttributes.push_back(mWebGLCompatibility ? EGL_TRUE : EGL_FALSE); contextAttributes.push_back(mWebGLCompatibility ? EGL_TRUE : EGL_FALSE);
} }
if (hasBindGeneratesResource)
{
contextAttributes.push_back(EGL_CONTEXT_BIND_GENERATES_RESOURCE_CHROMIUM);
contextAttributes.push_back(mBindGeneratesResource ? EGL_TRUE : EGL_FALSE);
}
} }
contextAttributes.push_back(EGL_NONE); contextAttributes.push_back(EGL_NONE);
......
...@@ -72,6 +72,10 @@ class ANGLE_EXPORT EGLWindow : angle::NonCopyable ...@@ -72,6 +72,10 @@ class ANGLE_EXPORT EGLWindow : angle::NonCopyable
{ {
mWebGLCompatibility = webglCompatibility; mWebGLCompatibility = webglCompatibility;
} }
void setBindGeneratesResource(bool bindGeneratesResource)
{
mBindGeneratesResource = bindGeneratesResource;
}
void setSwapInterval(EGLint swapInterval) { mSwapInterval = swapInterval; } void setSwapInterval(EGLint swapInterval) { mSwapInterval = swapInterval; }
static EGLBoolean FindEGLConfig(EGLDisplay dpy, const EGLint *attrib_list, EGLConfig *config); static EGLBoolean FindEGLConfig(EGLDisplay dpy, const EGLint *attrib_list, EGLConfig *config);
...@@ -118,6 +122,7 @@ class ANGLE_EXPORT EGLWindow : angle::NonCopyable ...@@ -118,6 +122,7 @@ class ANGLE_EXPORT EGLWindow : angle::NonCopyable
bool mDebug; bool mDebug;
bool mNoError; bool mNoError;
bool mWebGLCompatibility; bool mWebGLCompatibility;
bool mBindGeneratesResource;
EGLint mSwapInterval; EGLint mSwapInterval;
}; };
......
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