Add an extension to disable resource generation on bind.

BUG=angleproject:1518

Change-Id: I662f7b07da5c97831496f2617b0adadf9858bdc9
Reviewed-on: https://chromium-review.googlesource.com/386799
Reviewed-by: Antoine Labour <piman@chromium.org>
Commit-Queue: Geoff Lang <geofflang@chromium.org>
This commit is contained in:
Geoff Lang 2016-09-19 15:11:17 -04:00 коммит произвёл Commit Bot
Родитель 44ebf6b41f
Коммит f41a7151a5
27 изменённых файлов: 631 добавлений и 78 удалений

Просмотреть файл

@ -0,0 +1,118 @@
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

Просмотреть файл

@ -0,0 +1,87 @@
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
#define EGL_CONTEXT_WEBGL_COMPATIBILITY_ANGLE 0x3AAC
#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
#define EGL_ARM_pixmap_multisample_discard 1
#define EGL_DISCARD_SAMPLES_ARM 0x3286

Просмотреть файл

@ -838,6 +838,11 @@ GL_APICALL void GL_APIENTRY glCoverageModulationCHROMIUM(GLenum components);
#endif
#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)
// but CHROMIUM_path_rendering only needs MatrixLoadfEXT, MatrixLoadIdentityEXT
#ifndef GL_EXT_direct_state_access

Просмотреть файл

@ -167,6 +167,7 @@ Extensions::Extensions()
syncQuery(false),
copyTexture(false),
webglCompatibility(false),
bindGeneratesResource(false),
colorBufferFloat(false),
multisampleCompatibility(false),
framebufferMixedSamples(false),
@ -579,6 +580,7 @@ const ExtensionInfoMap &GetExtensionInfoMap()
map["GL_CHROMIUM_sync_query"] = esOnlyExtension(&Extensions::syncQuery);
map["GL_CHROMIUM_copy_texture"] = esOnlyExtension(&Extensions::copyTexture);
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_CHROMIUM_framebuffer_mixed_samples"] = esOnlyExtension(&Extensions::framebufferMixedSamples);
map["GL_EXT_texture_norm16"] = esOnlyExtension(&Extensions::textureNorm16);
@ -777,7 +779,8 @@ DisplayExtensions::DisplayExtensions()
streamConsumerGLTexture(false),
streamConsumerGLTextureYUV(false),
streamProducerD3DTextureNV12(false),
createContextWebGLCompatibility(false)
createContextWebGLCompatibility(false),
createContextBindGeneratesResource(false)
{
}
@ -786,34 +789,35 @@ std::vector<std::string> DisplayExtensions::getStrings() const
std::vector<std::string> extensionStrings;
// clang-format off
// | Extension name | Supported flag | Output vector |
InsertExtensionString("EGL_EXT_create_context_robustness", createContextRobustness, &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_query_surface_pointer", querySurfacePointer, &extensionStrings);
InsertExtensionString("EGL_ANGLE_window_fixed_size", windowFixedSize, &extensionStrings);
InsertExtensionString("EGL_ANGLE_keyed_mutex", keyedMutex, &extensionStrings);
InsertExtensionString("EGL_ANGLE_surface_orientation", surfaceOrientation, &extensionStrings);
InsertExtensionString("EGL_ANGLE_direct_composition", directComposition, &extensionStrings);
InsertExtensionString("EGL_NV_post_sub_buffer", postSubBuffer, &extensionStrings);
InsertExtensionString("EGL_KHR_create_context", createContext, &extensionStrings);
InsertExtensionString("EGL_EXT_device_query", deviceQuery, &extensionStrings);
InsertExtensionString("EGL_KHR_image", image, &extensionStrings);
InsertExtensionString("EGL_KHR_image_base", imageBase, &extensionStrings);
InsertExtensionString("EGL_KHR_image_pixmap", imagePixmap, &extensionStrings);
InsertExtensionString("EGL_KHR_gl_texture_2D_image", glTexture2DImage, &extensionStrings);
InsertExtensionString("EGL_KHR_gl_texture_cubemap_image", glTextureCubemapImage, &extensionStrings);
InsertExtensionString("EGL_KHR_gl_texture_3D_image", glTexture3DImage, &extensionStrings);
InsertExtensionString("EGL_KHR_gl_renderbuffer_image", glRenderbufferImage, &extensionStrings);
InsertExtensionString("EGL_KHR_get_all_proc_addresses", getAllProcAddresses, &extensionStrings);
InsertExtensionString("EGL_KHR_stream", stream, &extensionStrings);
InsertExtensionString("EGL_KHR_stream_consumer_gltexture", streamConsumerGLTexture, &extensionStrings);
InsertExtensionString("EGL_NV_stream_consumer_gltexture_yuv", streamConsumerGLTextureYUV, &extensionStrings);
InsertExtensionString("EGL_ANGLE_flexible_surface_compatibility", flexibleSurfaceCompatibility, &extensionStrings);
InsertExtensionString("EGL_ANGLE_stream_producer_d3d_texture_nv12", streamProducerD3DTextureNV12, &extensionStrings);
InsertExtensionString("EGL_ANGLE_create_context_webgl_compatibility", createContextWebGLCompatibility,&extensionStrings);
// | Extension name | Supported flag | Output vector |
InsertExtensionString("EGL_EXT_create_context_robustness", createContextRobustness, &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_query_surface_pointer", querySurfacePointer, &extensionStrings);
InsertExtensionString("EGL_ANGLE_window_fixed_size", windowFixedSize, &extensionStrings);
InsertExtensionString("EGL_ANGLE_keyed_mutex", keyedMutex, &extensionStrings);
InsertExtensionString("EGL_ANGLE_surface_orientation", surfaceOrientation, &extensionStrings);
InsertExtensionString("EGL_ANGLE_direct_composition", directComposition, &extensionStrings);
InsertExtensionString("EGL_NV_post_sub_buffer", postSubBuffer, &extensionStrings);
InsertExtensionString("EGL_KHR_create_context", createContext, &extensionStrings);
InsertExtensionString("EGL_EXT_device_query", deviceQuery, &extensionStrings);
InsertExtensionString("EGL_KHR_image", image, &extensionStrings);
InsertExtensionString("EGL_KHR_image_base", imageBase, &extensionStrings);
InsertExtensionString("EGL_KHR_image_pixmap", imagePixmap, &extensionStrings);
InsertExtensionString("EGL_KHR_gl_texture_2D_image", glTexture2DImage, &extensionStrings);
InsertExtensionString("EGL_KHR_gl_texture_cubemap_image", glTextureCubemapImage, &extensionStrings);
InsertExtensionString("EGL_KHR_gl_texture_3D_image", glTexture3DImage, &extensionStrings);
InsertExtensionString("EGL_KHR_gl_renderbuffer_image", glRenderbufferImage, &extensionStrings);
InsertExtensionString("EGL_KHR_get_all_proc_addresses", getAllProcAddresses, &extensionStrings);
InsertExtensionString("EGL_KHR_stream", stream, &extensionStrings);
InsertExtensionString("EGL_KHR_stream_consumer_gltexture", streamConsumerGLTexture, &extensionStrings);
InsertExtensionString("EGL_NV_stream_consumer_gltexture_yuv", streamConsumerGLTextureYUV, &extensionStrings);
InsertExtensionString("EGL_ANGLE_flexible_surface_compatibility", flexibleSurfaceCompatibility, &extensionStrings);
InsertExtensionString("EGL_ANGLE_stream_producer_d3d_texture_nv12", streamProducerD3DTextureNV12, &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.
//InsertExtensionString("KHR_create_context_no_error", createContextNoError, &extensionStrings);
//InsertExtensionString("KHR_create_context_no_error", createContextNoError, &extensionStrings);
// clang-format on
return extensionStrings;

Просмотреть файл

@ -296,6 +296,9 @@ struct Extensions
// GL_ANGLE_webgl_compatibility
bool webglCompatibility;
// GL_CHROMIUM_bind_generates_resource
bool bindGeneratesResource;
// ES3 Extension support
// GL_EXT_color_buffer_float
@ -592,6 +595,9 @@ struct DisplayExtensions
// EGL_ANGLE_create_context_webgl_compatibility
bool createContextWebGLCompatibility;
// EGL_CHROMIUM_create_context_bind_generates_resource
bool createContextBindGeneratesResource;
};
struct DeviceExtensions

Просмотреть файл

@ -184,6 +184,11 @@ bool GetWebGLContext(const egl::AttributeMap &attribs)
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 labelName;
@ -251,7 +256,8 @@ Context::Context(rx::EGLImplFactory *implFactory,
initCaps(GetWebGLContext(attribs));
mGLState.initialize(mCaps, mExtensions, mClientMajorVersion, GetDebug(attribs));
mGLState.initialize(mCaps, mExtensions, mClientMajorVersion, GetDebug(attribs),
GetBindGeneratesResource(attribs));
mFenceNVHandleAllocator.setBaseHandle(0);
@ -2080,13 +2086,36 @@ Framebuffer *Context::checkFramebufferAllocation(GLuint framebuffer)
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)
{
ASSERT(mVertexArrayMap.find(0) != mVertexArrayMap.end());
return mVertexArrayMap.find(vertexArray) != mVertexArrayMap.end();
}
bool Context::isTransformFeedbackGenerated(GLuint transformFeedback)
{
ASSERT(mTransformFeedbackMap.find(0) != mTransformFeedbackMap.end());
return mTransformFeedbackMap.find(transformFeedback) != mTransformFeedbackMap.end();
}
@ -2376,6 +2405,7 @@ void Context::initCaps(bool webGLContext)
// Some extensions are always available because they are implemented in the GL layer.
mExtensions.bindUniformLocation = true;
mExtensions.vertexArrayObject = true;
mExtensions.bindGeneratesResource = true;
// Enable the no error extension if the context was created with the flag.
mExtensions.noError = mSkipValidation;

Просмотреть файл

@ -191,6 +191,10 @@ class Context final : public ValidationContext
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 isTransformFeedbackGenerated(GLuint vertexArray);

Просмотреть файл

@ -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
switch (pname)
{

Просмотреть файл

@ -919,6 +919,7 @@ void Display::initDisplayExtensions()
mDisplayExtensions.createContext = true;
mDisplayExtensions.createContextNoError = true;
mDisplayExtensions.createContextWebGLCompatibility = true;
mDisplayExtensions.createContextBindGeneratesResource = true;
// Force EGL_KHR_get_all_proc_addresses on.
mDisplayExtensions.getAllProcAddresses = true;

Просмотреть файл

@ -544,4 +544,19 @@ bool ResourceManager::isSampler(GLuint sampler)
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

Просмотреть файл

@ -85,6 +85,11 @@ class ResourceManager : angle::NonCopyable
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:
void createTextureInternal(GLuint handle);

Просмотреть файл

@ -50,6 +50,7 @@ State::State()
mLineWidth(0),
mGenerateMipmapHint(GL_NONE),
mFragmentShaderDerivativeHint(GL_NONE),
mBindGeneratesResource(true),
mNearZ(0),
mFarZ(0),
mReadFramebuffer(nullptr),
@ -71,7 +72,8 @@ State::~State()
void State::initialize(const Caps &caps,
const Extensions &extensions,
GLuint clientVersion,
bool debug)
bool debug,
bool bindGeneratesResource)
{
mMaxDrawBuffers = caps.maxDrawBuffers;
mMaxCombinedTextureImageUnits = caps.maxCombinedTextureImageUnits;
@ -137,6 +139,8 @@ void State::initialize(const Caps &caps,
mGenerateMipmapHint = GL_DONT_CARE;
mFragmentShaderDerivativeHint = GL_DONT_CARE;
mBindGeneratesResource = bindGeneratesResource;
mLineWidth = 1.0f;
mViewport.x = 0;
@ -658,6 +662,8 @@ bool State::getEnableFeature(GLenum feature) const
return mDebug.isOutputSynchronous();
case GL_DEBUG_OUTPUT:
return mDebug.isOutputEnabled();
case GL_BIND_GENERATES_RESOURCE_CHROMIUM:
return isBindGeneratesResourceEnabled();
default: UNREACHABLE(); return false;
}
}
@ -688,6 +694,11 @@ void State::setFragmentShaderDerivativeHint(GLenum 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)
{
mViewport.x = x;
@ -1486,6 +1497,9 @@ void State::getBooleanv(GLenum pname, GLboolean *params)
case GL_SAMPLE_ALPHA_TO_ONE_EXT:
*params = mSampleAlphaToOne;
break;
case GL_BIND_GENERATES_RESOURCE_CHROMIUM:
*params = isBindGeneratesResourceEnabled() ? GL_TRUE : GL_FALSE;
break;
default:
UNREACHABLE();
break;

Просмотреть файл

@ -42,7 +42,8 @@ class State : angle::NonCopyable
void initialize(const Caps &caps,
const Extensions &extensions,
GLuint clientVersion,
bool debug);
bool debug,
bool bindGeneratesResource);
void reset();
// State chunk getters
@ -147,6 +148,9 @@ class State : angle::NonCopyable
void setGenerateMipmapHint(GLenum hint);
void setFragmentShaderDerivativeHint(GLenum hint);
// GL_CHROMIUM_bind_generates_resource
bool isBindGeneratesResourceEnabled() const;
// Viewport state setter/getter
void setViewportParams(GLint x, GLint y, GLsizei width, GLsizei height);
const Rectangle &getViewport() const;
@ -418,6 +422,8 @@ class State : angle::NonCopyable
GLenum mGenerateMipmapHint;
GLenum mFragmentShaderDerivativeHint;
bool mBindGeneratesResource;
Rectangle mViewport;
float mNearZ;
float mFarZ;

Просмотреть файл

@ -342,6 +342,21 @@ Error ValidateCreateContext(Display *display, Config *configuration, gl::Context
}
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:
return Error(EGL_BAD_ATTRIBUTE);
}

Просмотреть файл

@ -131,41 +131,44 @@ bool ValidReadPixelsFormatType(ValidationContext *context,
}
}
} // anonymous namespace
bool ValidCap(const Context *context, GLenum cap)
bool ValidCap(const Context *context, GLenum cap, bool queryOnly)
{
switch (cap)
{
// EXT_multisample_compatibility
case GL_MULTISAMPLE_EXT:
case GL_SAMPLE_ALPHA_TO_ONE_EXT:
return context->getExtensions().multisampleCompatibility;
// EXT_multisample_compatibility
case GL_MULTISAMPLE_EXT:
case GL_SAMPLE_ALPHA_TO_ONE_EXT:
return context->getExtensions().multisampleCompatibility;
case GL_CULL_FACE:
case GL_POLYGON_OFFSET_FILL:
case GL_SAMPLE_ALPHA_TO_COVERAGE:
case GL_SAMPLE_COVERAGE:
case GL_SCISSOR_TEST:
case GL_STENCIL_TEST:
case GL_DEPTH_TEST:
case GL_BLEND:
case GL_DITHER:
return true;
case GL_CULL_FACE:
case GL_POLYGON_OFFSET_FILL:
case GL_SAMPLE_ALPHA_TO_COVERAGE:
case GL_SAMPLE_COVERAGE:
case GL_SCISSOR_TEST:
case GL_STENCIL_TEST:
case GL_DEPTH_TEST:
case GL_BLEND:
case GL_DITHER:
return true;
case GL_PRIMITIVE_RESTART_FIXED_INDEX:
case GL_RASTERIZER_DISCARD:
return (context->getClientMajorVersion() >= 3);
case GL_PRIMITIVE_RESTART_FIXED_INDEX:
case GL_RASTERIZER_DISCARD:
return (context->getClientMajorVersion() >= 3);
case GL_DEBUG_OUTPUT_SYNCHRONOUS:
case GL_DEBUG_OUTPUT:
return context->getExtensions().debug;
case GL_DEBUG_OUTPUT_SYNCHRONOUS:
case GL_DEBUG_OUTPUT:
return context->getExtensions().debug;
default:
return false;
case GL_BIND_GENERATES_RESOURCE_CHROMIUM:
return queryOnly && context->getExtensions().bindGeneratesResource;
default:
return false;
}
}
} // anonymous namespace
bool ValidTextureTarget(const ValidationContext *context, GLenum target)
{
switch (target)
@ -3133,4 +3136,50 @@ bool ValidateGenOrDelete(Context *context, GLint n)
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

Просмотреть файл

@ -29,7 +29,6 @@ class Program;
class Shader;
class ValidationContext;
bool ValidCap(const Context *context, GLenum cap);
bool ValidTextureTarget(const ValidationContext *context, GLenum target);
bool ValidTexture2DTarget(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);
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.
extern const char *g_ExceedsMaxElementErrorMessage;
} // namespace gl

Просмотреть файл

@ -2187,6 +2187,13 @@ bool ValidateBindTexture(Context *context, GLenum target, GLuint texture)
return false;
}
if (!context->getGLState().isBindGeneratesResourceEnabled() &&
!context->isTextureGenerated(texture))
{
context->handleError(Error(GL_INVALID_OPERATION, "Texture was not generated"));
return false;
}
switch (target)
{
case GL_TEXTURE_2D:

Просмотреть файл

@ -87,7 +87,7 @@ TEST(ValidationESTest, DrawElementsWithMaxIndexGivesError)
caps.maxElementIndex = 100;
caps.maxDrawBuffers = 1;
caps.maxColorAttachments = 1;
state.initialize(caps, extensions, 3, false);
state.initialize(caps, extensions, 3, false, true);
NiceMock<MockTextureImpl> *textureImpl = new NiceMock<MockTextureImpl>();
EXPECT_CALL(mockFactory, createTexture(_)).WillOnce(Return(textureImpl));

Просмотреть файл

@ -123,6 +123,13 @@ void GL_APIENTRY BindBuffer(GLenum target, GLuint buffer)
return;
}
if (!context->getGLState().isBindGeneratesResourceEnabled() &&
!context->isBufferGenerated(buffer))
{
context->handleError(Error(GL_INVALID_OPERATION, "Buffer was not generated"));
return;
}
switch (target)
{
case GL_ARRAY_BUFFER:
@ -170,6 +177,13 @@ void GL_APIENTRY BindFramebuffer(GLenum target, GLuint framebuffer)
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)
{
context->bindReadFramebuffer(framebuffer);
@ -195,6 +209,13 @@ void GL_APIENTRY BindRenderbuffer(GLenum target, GLuint renderbuffer)
return;
}
if (!context->getGLState().isBindGeneratesResourceEnabled() &&
!context->isRenderbufferGenerated(renderbuffer))
{
context->handleError(Error(GL_INVALID_OPERATION, "Renderbuffer was not generated"));
return;
}
context->bindRenderbuffer(renderbuffer);
}
}
@ -917,9 +938,8 @@ void GL_APIENTRY Disable(GLenum cap)
Context *context = GetValidGlobalContext();
if (context)
{
if (!ValidCap(context, cap))
if (!context->skipValidation() && !ValidateDisable(context, cap))
{
context->handleError(Error(GL_INVALID_ENUM));
return;
}
@ -995,26 +1015,11 @@ void GL_APIENTRY Enable(GLenum cap)
Context *context = GetValidGlobalContext();
if (context)
{
if (!ValidCap(context, cap))
if (!context->skipValidation() && !ValidateEnable(context, cap))
{
context->handleError(Error(GL_INVALID_ENUM));
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);
}
}
@ -2677,9 +2682,8 @@ GLboolean GL_APIENTRY IsEnabled(GLenum cap)
Context *context = GetValidGlobalContext();
if (context)
{
if (!ValidCap(context, cap))
if (!context->skipValidation() && !ValidateIsEnabled(context, cap))
{
context->handleError(Error(GL_INVALID_ENUM));
return GL_FALSE;
}

Просмотреть файл

@ -759,6 +759,13 @@ void GL_APIENTRY BindBufferRange(GLenum target, GLuint index, GLuint buffer, GLi
return;
}
if (!context->getGLState().isBindGeneratesResourceEnabled() &&
!context->isBufferGenerated(buffer))
{
context->handleError(Error(GL_INVALID_OPERATION, "Buffer was not generated"));
return;
}
switch (target)
{
case GL_TRANSFORM_FEEDBACK_BUFFER:
@ -841,6 +848,13 @@ void GL_APIENTRY BindBufferBase(GLenum target, GLuint index, GLuint buffer)
return;
}
if (!context->getGLState().isBindGeneratesResourceEnabled() &&
!context->isBufferGenerated(buffer))
{
context->handleError(Error(GL_INVALID_OPERATION, "Buffer was not generated"));
return;
}
switch (target)
{
case GL_TRANSFORM_FEEDBACK_BUFFER:

Просмотреть файл

@ -15,6 +15,7 @@
{
'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/BlendMinMaxTest.cpp',
'<(angle_path)/src/tests/gl_tests/BlitFramebufferANGLETest.cpp',

Просмотреть файл

@ -0,0 +1,123 @@
//
// 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)
mEGLWindow->setWebGLCompatibilityEnabled(webglCompatibility);
}
void ANGLETest::setBindGeneratesResource(bool bindGeneratesResource)
{
mEGLWindow->setBindGeneratesResource(bindGeneratesResource);
}
int ANGLETest::getClientMajorVersion() const
{
return mEGLWindow->getClientMajorVersion();

Просмотреть файл

@ -185,6 +185,7 @@ class ANGLETest : public ::testing::TestWithParam<angle::PlatformParameters>
void setDebugEnabled(bool enabled);
void setNoErrorEnabled(bool enabled);
void setWebGLCompatibilityEnabled(bool webglCompatibility);
void setBindGeneratesResource(bool bindGeneratesResource);
int getClientMajorVersion() const;
int getClientMinorVersion() const;

Просмотреть файл

@ -111,6 +111,7 @@ EGLWindow::EGLWindow(EGLint glesMajorVersion,
mDebug(false),
mNoError(false),
mWebGLCompatibility(false),
mBindGeneratesResource(true),
mSwapInterval(-1)
{
}
@ -216,6 +217,14 @@ bool EGLWindow::initializeGL(OSWindow *osWindow)
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);
if (eglGetError() != EGL_SUCCESS)
{
@ -290,6 +299,12 @@ bool EGLWindow::initializeGL(OSWindow *osWindow)
contextAttributes.push_back(EGL_CONTEXT_WEBGL_COMPATIBILITY_ANGLE);
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);

Просмотреть файл

@ -72,6 +72,10 @@ class ANGLE_EXPORT EGLWindow : angle::NonCopyable
{
mWebGLCompatibility = webglCompatibility;
}
void setBindGeneratesResource(bool bindGeneratesResource)
{
mBindGeneratesResource = bindGeneratesResource;
}
void setSwapInterval(EGLint swapInterval) { mSwapInterval = swapInterval; }
static EGLBoolean FindEGLConfig(EGLDisplay dpy, const EGLint *attrib_list, EGLConfig *config);
@ -118,6 +122,7 @@ class ANGLE_EXPORT EGLWindow : angle::NonCopyable
bool mDebug;
bool mNoError;
bool mWebGLCompatibility;
bool mBindGeneratesResource;
EGLint mSwapInterval;
};