Commit 46e6c7a5 by Jamie Madill

Add stubs for no_error extension.

In some cases ANGLE flushes state for FBOs during validation. For testing of the state synching code for FBOs, this makes end-to-end testing impossible. Solve this by partially implementing a hidden no_error extension, hidden to the user by not exposing the extension string, but allowing us to skip validation of some of the FBO methods that require checking for complete FBOs. BUG=angleproject:1280 BUG=angleproject:1260 Change-Id: I708f348ccec6697b974c48cd890ec75a703abe21 Reviewed-on: https://chromium-review.googlesource.com/322210 Tryjob-Request: Jamie Madill <jmadill@chromium.org> Reviewed-by: 's avatarGeoff Lang <geofflang@chromium.org> Reviewed-by: 's avatarCorentin Wallez <cwallez@chromium.org> Tested-by: 's avatarJamie Madill <jmadill@chromium.org>
parent e5df3066
......@@ -152,6 +152,7 @@ Extensions::Extensions()
maxDebugLoggedMessages(0),
maxDebugGroupStackDepth(0),
maxLabelLength(0),
noError(false),
colorBufferFloat(false)
{
}
......@@ -218,6 +219,8 @@ std::vector<std::string> Extensions::getStrings() const
InsertExtensionString("GL_EXT_color_buffer_float", colorBufferFloat, &extensionStrings);
InsertExtensionString("GL_OES_vertex_array_object", vertexArrayObject, &extensionStrings);
InsertExtensionString("GL_KHR_debug", debug, &extensionStrings);
// TODO(jmadill): Enable this when complete.
//InsertExtensionString("GL_KHR_no_error", noError, &extensionStrings);
// clang-format on
return extensionStrings;
......@@ -622,7 +625,8 @@ DisplayExtensions::DisplayExtensions()
glRenderbufferImage(false),
getAllProcAddresses(false),
flexibleSurfaceCompatibility(false),
directComposition(false)
directComposition(false),
createContextNoError(false)
{
}
......@@ -652,6 +656,8 @@ std::vector<std::string> DisplayExtensions::getStrings() const
InsertExtensionString("EGL_KHR_gl_renderbuffer_image", glRenderbufferImage, &extensionStrings);
InsertExtensionString("EGL_KHR_get_all_proc_addresses", getAllProcAddresses, &extensionStrings);
InsertExtensionString("EGL_ANGLE_flexible_surface_compatibility", flexibleSurfaceCompatibility, &extensionStrings);
// TODO(jmadill): Enable this when complete.
//InsertExtensionString("KHR_create_context_no_error", createContextNoError, &extensionStrings);
// clang-format on
return extensionStrings;
......
......@@ -267,6 +267,9 @@ struct Extensions
GLuint maxDebugGroupStackDepth;
GLuint maxLabelLength;
// KHR_no_error
bool noError;
// ES3 Extension support
// GL_EXT_color_buffer_float
......@@ -468,6 +471,9 @@ struct DisplayExtensions
// EGL_ANGLE_direct_composition
bool directComposition;
// KHR_create_context_no_error
bool createContextNoError;
};
struct DeviceExtensions
......
......@@ -52,37 +52,79 @@ void MarkTransformFeedbackBufferUsage(gl::TransformFeedback *transformFeedback)
}
}
}
// Attribute map queries.
EGLint GetClientVersion(const egl::AttributeMap &attribs)
{
return attribs.get(EGL_CONTEXT_CLIENT_VERSION, 1);
}
GLenum GetResetStrategy(const egl::AttributeMap &attribs)
{
EGLenum attrib = attribs.get(EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_EXT,
EGL_NO_RESET_NOTIFICATION_EXT);
switch (attrib)
{
case EGL_NO_RESET_NOTIFICATION:
return GL_NO_RESET_NOTIFICATION_EXT;
case EGL_LOSE_CONTEXT_ON_RESET:
return GL_LOSE_CONTEXT_ON_RESET_EXT;
default:
UNREACHABLE();
return GL_NONE;
}
}
bool GetRobustAccess(const egl::AttributeMap &attribs)
{
return (attribs.get(EGL_CONTEXT_OPENGL_ROBUST_ACCESS_EXT, EGL_FALSE) == EGL_TRUE);
}
bool GetDebug(const egl::AttributeMap &attribs)
{
return (attribs.get(EGL_CONTEXT_OPENGL_DEBUG, EGL_FALSE) == EGL_TRUE);
}
bool GetNoError(const egl::AttributeMap &attribs)
{
return (attribs.get(EGL_CONTEXT_OPENGL_NO_ERROR_KHR, EGL_FALSE) == EGL_TRUE);
}
} // anonymous namespace
namespace gl
{
Context::Context(const egl::Config *config,
int clientVersion,
const Context *shareContext,
rx::Renderer *renderer,
bool notifyResets,
bool robustAccess,
bool debug)
: ValidationContext(clientVersion,
const egl::AttributeMap &attribs)
: ValidationContext(GetClientVersion(attribs),
mState,
mCaps,
mTextureCaps,
mExtensions,
nullptr,
mLimitations),
mLimitations,
GetNoError(attribs)),
mCompiler(nullptr),
mRenderer(renderer),
mClientVersion(GetClientVersion(attribs)),
mConfig(config),
mCurrentSurface(nullptr)
mClientType(EGL_OPENGL_ES_API),
mHasBeenCurrent(false),
mContextLost(false),
mResetStatus(GL_NO_ERROR),
mResetStrategy(GetResetStrategy(attribs)),
mRobustAccess(GetRobustAccess(attribs)),
mCurrentSurface(nullptr),
mResourceManager(nullptr)
{
ASSERT(robustAccess == false); // Unimplemented
ASSERT(!mRobustAccess); // Unimplemented
initCaps(clientVersion);
mState.initialize(mCaps, mExtensions, clientVersion, debug);
initCaps(mClientVersion);
mClientVersion = clientVersion;
mClientType = EGL_OPENGL_ES_API;
mState.initialize(mCaps, mExtensions, mClientVersion, GetDebug(attribs));
mFenceNVHandleAllocator.setBaseHandle(0);
......@@ -148,12 +190,6 @@ Context::Context(const egl::Config *config,
bindTransformFeedback(0);
}
mHasBeenCurrent = false;
mContextLost = false;
mResetStatus = GL_NO_ERROR;
mResetStrategy = (notifyResets ? GL_LOSE_CONTEXT_ON_RESET_EXT : GL_NO_RESET_NOTIFICATION_EXT);
mRobustAccess = robustAccess;
mCompiler = new Compiler(mRenderer, getData());
}
......
......@@ -33,6 +33,7 @@ class Renderer;
namespace egl
{
class AttributeMap;
class Surface;
struct Config;
}
......@@ -59,12 +60,9 @@ class Context final : public ValidationContext
{
public:
Context(const egl::Config *config,
int clientVersion,
const Context *shareContext,
rx::Renderer *renderer,
bool notifyResets,
bool robustAccess,
bool debug);
const egl::AttributeMap &attribs);
virtual ~Context();
......
......@@ -40,7 +40,8 @@ ValidationContext::ValidationContext(GLint clientVersion,
const TextureCapsMap &textureCaps,
const Extensions &extensions,
const ResourceManager *resourceManager,
const Limitations &limitations)
const Limitations &limitations,
bool skipValidation)
: mData(reinterpret_cast<uintptr_t>(this),
clientVersion,
state,
......@@ -48,7 +49,8 @@ ValidationContext::ValidationContext(GLint clientVersion,
textureCaps,
extensions,
resourceManager,
limitations)
limitations),
mSkipValidation(skipValidation)
{
}
}
} // namespace gl
......@@ -47,7 +47,8 @@ class ValidationContext : angle::NonCopyable
const TextureCapsMap &textureCaps,
const Extensions &extensions,
const ResourceManager *resourceManager,
const Limitations &limitations);
const Limitations &limitations,
bool skipValidation);
virtual ~ValidationContext() {}
virtual void recordError(const Error &error) = 0;
......@@ -59,9 +60,11 @@ class ValidationContext : angle::NonCopyable
const TextureCapsMap &getTextureCaps() const { return *mData.textureCaps; }
const Extensions &getExtensions() const { return *mData.extensions; }
const Limitations &getLimitations() const { return *mData.limitations; }
bool skipValidation() const { return mSkipValidation; }
protected:
Data mData;
bool mSkipValidation;
};
}
......
......@@ -695,12 +695,8 @@ Error Display::createContext(const Config *configuration, gl::Context *shareCont
}
}
gl::Context *context = nullptr;
Error error = mImplementation->createContext(configuration, shareContext, attribs, &context);
if (error.isError())
{
return error;
}
gl::Context *context = *outContext =
mImplementation->createContext(configuration, shareContext, attribs);
ASSERT(context != nullptr);
mContextSet.insert(context);
......
......@@ -64,8 +64,9 @@ class DisplayImpl : angle::NonCopyable
egl::ImageSibling *buffer,
const egl::AttributeMap &attribs) = 0;
virtual egl::Error createContext(const egl::Config *config, const gl::Context *shareContext, const egl::AttributeMap &attribs,
gl::Context **outContext) = 0;
virtual gl::Context *createContext(const egl::Config *config,
const gl::Context *shareContext,
const egl::AttributeMap &attribs) = 0;
virtual egl::Error makeCurrent(egl::Surface *drawSurface, egl::Surface *readSurface, gl::Context *context) = 0;
......
......@@ -229,19 +229,12 @@ egl::Error DisplayD3D::getDevice(DeviceImpl **device)
return mRenderer->getEGLDevice(device);
}
egl::Error DisplayD3D::createContext(const egl::Config *config, const gl::Context *shareContext, const egl::AttributeMap &attribs,
gl::Context **outContext)
gl::Context *DisplayD3D::createContext(const egl::Config *config,
const gl::Context *shareContext,
const egl::AttributeMap &attribs)
{
ASSERT(mRenderer != nullptr);
EGLint clientVersion = attribs.get(EGL_CONTEXT_CLIENT_VERSION, 1);
bool notifyResets = (attribs.get(EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_EXT, EGL_NO_RESET_NOTIFICATION_EXT) == EGL_LOSE_CONTEXT_ON_RESET_EXT);
bool robustAccess = (attribs.get(EGL_CONTEXT_OPENGL_ROBUST_ACCESS_EXT, EGL_FALSE) == EGL_TRUE);
bool debug = (attribs.get(EGL_CONTEXT_OPENGL_DEBUG, EGL_FALSE) == EGL_TRUE);
*outContext = new gl::Context(config, clientVersion, shareContext, mRenderer, notifyResets,
robustAccess, debug);
return egl::Error(EGL_SUCCESS);
return new gl::Context(config, shareContext, mRenderer, attribs);
}
egl::Error DisplayD3D::makeCurrent(egl::Surface *drawSurface, egl::Surface *readSurface, gl::Context *context)
......
......@@ -41,8 +41,9 @@ class DisplayD3D : public DisplayImpl
egl::ImageSibling *buffer,
const egl::AttributeMap &attribs) override;
egl::Error createContext(const egl::Config *config, const gl::Context *shareContext, const egl::AttributeMap &attribs,
gl::Context **outContext) override;
gl::Context *createContext(const egl::Config *config,
const gl::Context *shareContext,
const egl::AttributeMap &attribs) override;
egl::Error makeCurrent(egl::Surface *drawSurface, egl::Surface *readSurface, gl::Context *context) override;
......
......@@ -1084,6 +1084,8 @@ void Renderer11::generateDisplayExtensions(egl::DisplayExtensions *outExtensions
outExtensions->deviceQuery = true;
outExtensions->createContextNoError = true;
outExtensions->image = true;
outExtensions->imageBase = true;
outExtensions->glTexture2DImage = true;
......
......@@ -1217,6 +1217,7 @@ void GenerateCaps(ID3D11Device *device, ID3D11DeviceContext *deviceContext, cons
extensions->unpackSubimage = true;
extensions->packSubimage = true;
extensions->vertexArrayObject = true;
extensions->noError = true;
// D3D11 Feature Level 10_0+ uses SV_IsFrontFace in HLSL to emulate gl_FrontFacing.
// D3D11 Feature Level 9_3 doesn't support SV_IsFrontFace, and has no equivalent, so can't support gl_FrontFacing.
......
......@@ -524,6 +524,7 @@ void Renderer9::generateDisplayExtensions(egl::DisplayExtensions *outExtensions)
outExtensions->postSubBuffer = true;
outExtensions->createContext = true;
outExtensions->deviceQuery = true;
outExtensions->createContextNoError = true;
outExtensions->image = true;
outExtensions->imageBase = true;
......
......@@ -577,6 +577,7 @@ void GenerateCaps(IDirect3D9 *d3d9,
extensions->unpackSubimage = true;
extensions->packSubimage = true;
extensions->vertexArrayObject = true;
extensions->noError = true;
// D3D9 has no concept of separate masks and refs for front and back faces in the depth stencil
// state.
......
......@@ -55,18 +55,12 @@ ImageImpl *DisplayGL::createImage(EGLenum target,
return nullptr;
}
egl::Error DisplayGL::createContext(const egl::Config *config, const gl::Context *shareContext, const egl::AttributeMap &attribs, gl::Context **outContext)
gl::Context *DisplayGL::createContext(const egl::Config *config,
const gl::Context *shareContext,
const egl::AttributeMap &attribs)
{
ASSERT(mRenderer != nullptr);
EGLint clientVersion = attribs.get(EGL_CONTEXT_CLIENT_VERSION, 1);
bool notifyResets = (attribs.get(EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_EXT, EGL_NO_RESET_NOTIFICATION_EXT) == EGL_LOSE_CONTEXT_ON_RESET_EXT);
bool robustAccess = (attribs.get(EGL_CONTEXT_OPENGL_ROBUST_ACCESS_EXT, EGL_FALSE) == EGL_TRUE);
bool debug = (attribs.get(EGL_CONTEXT_OPENGL_DEBUG, EGL_FALSE) == EGL_TRUE);
*outContext = new gl::Context(config, clientVersion, shareContext, mRenderer, notifyResets,
robustAccess, debug);
return egl::Error(EGL_SUCCESS);
return new gl::Context(config, shareContext, mRenderer, attribs);
}
egl::Error DisplayGL::makeCurrent(egl::Surface *drawSurface, egl::Surface *readSurface, gl::Context *context)
......
......@@ -30,8 +30,9 @@ class DisplayGL : public DisplayImpl
egl::ImageSibling *buffer,
const egl::AttributeMap &attribs) override;
egl::Error createContext(const egl::Config *config, const gl::Context *shareContext, const egl::AttributeMap &attribs,
gl::Context **outContext) override;
gl::Context *createContext(const egl::Config *config,
const gl::Context *shareContext,
const egl::AttributeMap &attribs) override;
egl::Error makeCurrent(egl::Surface *drawSurface, egl::Surface *readSurface, gl::Context *context) override;
......
......@@ -248,6 +248,7 @@ const FunctionsGL *DisplayCGL::getFunctionsGL() const
void DisplayCGL::generateExtensions(egl::DisplayExtensions *outExtensions) const
{
outExtensions->createContext = true;
outExtensions->createContextNoError = true;
}
void DisplayCGL::generateCaps(egl::Caps *outCaps) const
......
......@@ -703,6 +703,7 @@ const FunctionsGL *DisplayGLX::getFunctionsGL() const
void DisplayGLX::generateExtensions(egl::DisplayExtensions *outExtensions) const
{
outExtensions->createContext = true;
outExtensions->createContextNoError = true;
}
void DisplayGLX::generateCaps(egl::Caps *outCaps) const
......
......@@ -611,6 +611,8 @@ void GenerateCaps(const FunctionsGL *functions, gl::Caps *caps, gl::TextureCapsM
// ANGLE emulates vertex array objects in its GL layer
extensions->vertexArrayObject = true;
extensions->noError = true;
}
void GenerateWorkarounds(const FunctionsGL *functions, WorkaroundsGL *workarounds)
......
......@@ -467,6 +467,7 @@ const FunctionsGL *DisplayWGL::getFunctionsGL() const
void DisplayWGL::generateExtensions(egl::DisplayExtensions *outExtensions) const
{
outExtensions->createContext = true;
outExtensions->createContextNoError = true;
}
void DisplayWGL::generateCaps(egl::Caps *outCaps) const
......
......@@ -248,6 +248,17 @@ Error ValidateCreateContext(Display *display, Config *configuration, gl::Context
}
break;
case EGL_CONTEXT_OPENGL_NO_ERROR_KHR:
if (!display->getExtensions().createContextNoError)
{
return Error(EGL_BAD_ATTRIBUTE, "Invalid Context attribute.");
}
if (value != EGL_TRUE && value != EGL_FALSE)
{
return Error(EGL_BAD_ATTRIBUTE, "Attribute must be EGL_TRUE or EGL_FALSE.");
}
break;
default:
return Error(EGL_BAD_ATTRIBUTE);
}
......
......@@ -42,7 +42,8 @@ class MockValidationContext : public ValidationContext
const TextureCapsMap &textureCaps,
const Extensions &extensions,
const ResourceManager *resourceManager,
const Limitations &limitations);
const Limitations &limitations,
bool skipValidation);
MOCK_METHOD1(recordError, void(const Error &));
};
......@@ -53,14 +54,16 @@ MockValidationContext::MockValidationContext(GLint clientVersion,
const TextureCapsMap &textureCaps,
const Extensions &extensions,
const ResourceManager *resourceManager,
const Limitations &limitations)
const Limitations &limitations,
bool skipValidation)
: ValidationContext(clientVersion,
state,
caps,
textureCaps,
extensions,
resourceManager,
limitations)
limitations,
skipValidation)
{
}
......@@ -115,8 +118,8 @@ TEST(ValidationESTest, DrawElementsWithMaxIndexGivesError)
state.setDrawFramebufferBinding(framebuffer);
state.setProgram(program);
MockValidationContext testContext(3, state, caps, textureCaps, extensions, nullptr,
limitations);
MockValidationContext testContext(3, state, caps, textureCaps, extensions, nullptr, limitations,
false);
// Set the expectation for the validation error here.
Error expectedError(GL_INVALID_OPERATION, g_ExceedsMaxElementErrorMessage);
......
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