Commit 6b873dd7 by Jamie Madill Committed by Commit Bot

Add gl::ErrorSet and angle::Result.

gl::ErrorSet can handle errors and is accessible from ContextImpl. It allows the implementation to mutate the error set without using the gl::Context directly. angle::Result is the faster POD return value class. It should generate optimal code. It can also be used seamlessly with the ANGLE_TRY macro. Also introduces an internal enum as a workaround for generating and consuming errors in the back-end. When the internal enum is used as an error return value the error is not consumed in the front-end. This is a temporary workaround only. Bug: angleproject:2491 Bug: angleproject:2713 Change-Id: I6cbdaadd075ccbdf241844cbcbc4ed5c3be40a8b Reviewed-on: https://chromium-review.googlesource.com/1133200 Commit-Queue: Jamie Madill <jmadill@chromium.org> Reviewed-by: 's avatarFrank Henigman <fjhenigman@chromium.org>
parent 0cc29136
...@@ -253,6 +253,10 @@ std::string ToString(const T &value) ...@@ -253,6 +253,10 @@ std::string ToString(const T &value)
// TODO(jmadill): Clean this up at some point. // TODO(jmadill): Clean this up at some point.
#define EGL_PLATFORM_ANGLE_PLATFORM_METHODS_ANGLEX 0x9999 #define EGL_PLATFORM_ANGLE_PLATFORM_METHODS_ANGLEX 0x9999
// This internal enum is used to filter internal errors that are already handled.
// TODO(jmadill): Remove this when refactor is done. http://anglebug.com/2491
#define GL_INTERNAL_ERROR_ANGLEX 0x6AEE
#define ANGLE_TRY_CHECKED_MATH(result) \ #define ANGLE_TRY_CHECKED_MATH(result) \
if (!result) \ if (!result) \
{ \ { \
......
...@@ -330,6 +330,7 @@ Context::Context(rx::EGLImplFactory *implFactory, ...@@ -330,6 +330,7 @@ Context::Context(rx::EGLImplFactory *implFactory,
memoryProgramCache != nullptr), memoryProgramCache != nullptr),
mConfig(config), mConfig(config),
mClientType(EGL_OPENGL_ES_API), mClientType(EGL_OPENGL_ES_API),
mErrors(this),
mHasBeenCurrent(false), mHasBeenCurrent(false),
mContextLost(false), mContextLost(false),
mResetStatus(GL_NO_ERROR), mResetStatus(GL_NO_ERROR),
...@@ -2541,21 +2542,9 @@ void Context::getProgramInterfaceivRobust(GLuint program, ...@@ -2541,21 +2542,9 @@ void Context::getProgramInterfaceivRobust(GLuint program,
UNIMPLEMENTED(); UNIMPLEMENTED();
} }
void Context::handleError(const Error &error) const void Context::handleError(const Error &error)
{ {
if (ANGLE_UNLIKELY(error.isError())) mErrors.handleError(error);
{
GLenum code = error.getCode();
mErrors.insert(code);
if (code == GL_OUT_OF_MEMORY && getWorkarounds().loseContextOnOutOfMemory)
{
markContextLost();
}
ASSERT(!error.getMessage().empty());
mGLState.getDebug().insertMessage(GL_DEBUG_SOURCE_API, GL_DEBUG_TYPE_ERROR, error.getID(),
GL_DEBUG_SEVERITY_HIGH, error.getMessage());
}
} }
// Get one of the recorded errors and clear its flag, if any. // Get one of the recorded errors and clear its flag, if any.
...@@ -2568,14 +2557,12 @@ GLenum Context::getError() ...@@ -2568,14 +2557,12 @@ GLenum Context::getError()
} }
else else
{ {
GLenum error = *mErrors.begin(); return mErrors.popError();
mErrors.erase(mErrors.begin());
return error;
} }
} }
// NOTE: this function should not assume that this context is current! // NOTE: this function should not assume that this context is current!
void Context::markContextLost() const void Context::markContextLost()
{ {
if (mResetStrategy == GL_LOSE_CONTEXT_ON_RESET_EXT) if (mResetStrategy == GL_LOSE_CONTEXT_ON_RESET_EXT)
{ {
...@@ -7542,4 +7529,48 @@ void Context::maxShaderCompilerThreads(GLuint count) ...@@ -7542,4 +7529,48 @@ void Context::maxShaderCompilerThreads(GLuint count)
mGLState.setMaxShaderCompilerThreads(count); mGLState.setMaxShaderCompilerThreads(count);
} }
// ErrorSet implementation.
ErrorSet::ErrorSet(Context *context) : mContext(context)
{
}
ErrorSet::~ErrorSet() = default;
void ErrorSet::handleError(const Error &error)
{
// This internal enum is used to filter internal errors that are already handled.
// TODO(jmadill): Remove this when refactor is done. http://anglebug.com/2491
if (error.getCode() == GL_INTERNAL_ERROR_ANGLEX)
{
return;
}
if (ANGLE_UNLIKELY(error.isError()))
{
GLenum code = error.getCode();
mErrors.insert(code);
if (code == GL_OUT_OF_MEMORY && mContext->getWorkarounds().loseContextOnOutOfMemory)
{
mContext->markContextLost();
}
ASSERT(!error.getMessage().empty());
mContext->getGLState().getDebug().insertMessage(GL_DEBUG_SOURCE_API, GL_DEBUG_TYPE_ERROR,
error.getID(), GL_DEBUG_SEVERITY_HIGH,
error.getMessage());
}
}
bool ErrorSet::empty() const
{
return mErrors.empty();
}
GLenum ErrorSet::popError()
{
ASSERT(!empty());
GLenum error = *mErrors.begin();
mErrors.erase(mErrors.begin());
return error;
}
} // namespace gl } // namespace gl
...@@ -63,6 +63,21 @@ class TransformFeedback; ...@@ -63,6 +63,21 @@ class TransformFeedback;
class VertexArray; class VertexArray;
struct VertexAttribute; struct VertexAttribute;
class ErrorSet : angle::NonCopyable
{
public:
explicit ErrorSet(Context *context);
~ErrorSet();
void handleError(const Error &error);
bool empty() const;
GLenum popError();
private:
Context *mContext;
std::set<GLenum> mErrors;
};
class Context final : public egl::LabeledObject, angle::NonCopyable class Context final : public egl::LabeledObject, angle::NonCopyable
{ {
public: public:
...@@ -1380,10 +1395,10 @@ class Context final : public egl::LabeledObject, angle::NonCopyable ...@@ -1380,10 +1395,10 @@ class Context final : public egl::LabeledObject, angle::NonCopyable
void framebufferTexture(GLenum target, GLenum attachment, GLuint texture, GLint level); void framebufferTexture(GLenum target, GLenum attachment, GLuint texture, GLint level);
// Consumes the error. // Consumes the error.
void handleError(const Error &error) const; void handleError(const Error &error);
GLenum getError(); GLenum getError();
void markContextLost() const; void markContextLost();
bool isContextLost() const; bool isContextLost() const;
GLenum getGraphicsResetStatus(); GLenum getGraphicsResetStatus();
bool isResetNotificationEnabled(); bool isResetNotificationEnabled();
...@@ -1574,17 +1589,16 @@ class Context final : public egl::LabeledObject, angle::NonCopyable ...@@ -1574,17 +1589,16 @@ class Context final : public egl::LabeledObject, angle::NonCopyable
std::vector<const char *> mRequestableExtensionStrings; std::vector<const char *> mRequestableExtensionStrings;
// Recorded errors // Recorded errors
typedef std::set<GLenum> ErrorSet; ErrorSet mErrors;
mutable ErrorSet mErrors;
// GLES1 renderer state // GLES1 renderer state
std::unique_ptr<GLES1Renderer> mGLES1Renderer; std::unique_ptr<GLES1Renderer> mGLES1Renderer;
// Current/lost context flags // Current/lost context flags
bool mHasBeenCurrent; bool mHasBeenCurrent;
mutable bool mContextLost; bool mContextLost;
mutable GLenum mResetStatus; GLenum mResetStatus;
mutable bool mContextLostForced; bool mContextLostForced;
GLenum mResetStrategy; GLenum mResetStrategy;
const bool mRobustAccess; const bool mRobustAccess;
const bool mSurfacelessSupported; const bool mSurfacelessSupported;
......
...@@ -26,7 +26,6 @@ std::unique_ptr<std::string> EmplaceErrorString(std::string &&message) ...@@ -26,7 +26,6 @@ std::unique_ptr<std::string> EmplaceErrorString(std::string &&message)
namespace gl namespace gl
{ {
Error::Error(GLenum errorCode, std::string &&message) Error::Error(GLenum errorCode, std::string &&message)
: mCode(errorCode), mID(errorCode), mMessage(EmplaceErrorString(std::move(message))) : mCode(errorCode), mID(errorCode), mMessage(EmplaceErrorString(std::move(message)))
{ {
...@@ -108,3 +107,19 @@ std::ostream &operator<<(std::ostream &os, const Error &err) ...@@ -108,3 +107,19 @@ std::ostream &operator<<(std::ostream &os, const Error &err)
} }
} // namespace egl } // namespace egl
// angle::Result Implementation.
namespace angle
{
Result::operator gl::Error() const
{
if (mStop)
{
return gl::Error(GL_INTERNAL_ERROR_ANGLEX);
}
else
{
return gl::NoError();
}
}
} // namespace angle
...@@ -262,6 +262,35 @@ inline Error NoError() ...@@ -262,6 +262,35 @@ inline Error NoError()
#undef ANGLE_CONCAT2 #undef ANGLE_CONCAT2
#undef ANGLE_CONCAT1 #undef ANGLE_CONCAT1
namespace angle
{
// Result signals if calling code should continue running or early exit. A value of Stop() can
// either indicate and Error or a non-Error early exit condition such as a detected no-op.
class ANGLE_NO_DISCARD Result
{
public:
// TODO(jmadill): Rename when refactor is complete. http://anglebug.com/2491
bool isError() const { return mStop; }
static Result Stop() { return Result(true); }
static Result Continue() { return Result(false); }
// TODO(jmadill): Remove when refactor is complete. http://anglebug.com/2491
operator gl::Error() const;
// TODO(jmadill): Remove when refactor is complete. http://anglebug.com/2491
template <typename T>
operator gl::ErrorOrResult<T>() const
{
return operator gl::Error();
}
private:
Result(bool stop) : mStop(stop) {}
bool mStop;
};
} // namespace angle
#include "Error.inl" #include "Error.inl"
#endif // LIBANGLE_ERROR_H_ #endif // LIBANGLE_ERROR_H_
...@@ -1024,7 +1024,8 @@ GLenum Framebuffer::checkStatus(const Context *context) ...@@ -1024,7 +1024,8 @@ GLenum Framebuffer::checkStatus(const Context *context)
Error err = syncState(context); Error err = syncState(context);
if (err.isError()) if (err.isError())
{ {
context->handleError(err); // TODO(jmadill): Remove when refactor complete. http://anglebug.com/2491
const_cast<Context *>(context)->handleError(err);
return GetDefaultReturnValue<EntryPoint::CheckFramebufferStatus, GLenum>(); return GetDefaultReturnValue<EntryPoint::CheckFramebufferStatus, GLenum>();
} }
if (!mImpl->checkStatus(context)) if (!mImpl->checkStatus(context))
......
...@@ -9,11 +9,13 @@ ...@@ -9,11 +9,13 @@
#include "libANGLE/renderer/ContextImpl.h" #include "libANGLE/renderer/ContextImpl.h"
#include "libANGLE/Context.h"
namespace rx namespace rx
{ {
ContextImpl::ContextImpl(const gl::ContextState &state) ContextImpl::ContextImpl(const gl::ContextState &state)
: mState(state), mMemoryProgramCache(nullptr) : mState(state), mMemoryProgramCache(nullptr), mErrors(nullptr)
{ {
} }
...@@ -116,4 +118,13 @@ void ContextImpl::setMemoryProgramCache(gl::MemoryProgramCache *memoryProgramCac ...@@ -116,4 +118,13 @@ void ContextImpl::setMemoryProgramCache(gl::MemoryProgramCache *memoryProgramCac
mMemoryProgramCache = memoryProgramCache; mMemoryProgramCache = memoryProgramCache;
} }
void ContextImpl::setErrorSet(gl::ErrorSet *errorSet)
{
mErrors = errorSet;
}
void ContextImpl::handleError(const gl::Error &error)
{
mErrors->handleError(error);
}
} // namespace rx } // namespace rx
...@@ -18,6 +18,7 @@ ...@@ -18,6 +18,7 @@
namespace gl namespace gl
{ {
class ErrorSet;
class MemoryProgramCache; class MemoryProgramCache;
class Path; class Path;
struct Workarounds; struct Workarounds;
...@@ -181,9 +182,15 @@ class ContextImpl : public GLImplFactory ...@@ -181,9 +182,15 @@ class ContextImpl : public GLImplFactory
// on draw calls we can store the refreshed shaders in the cache. // on draw calls we can store the refreshed shaders in the cache.
void setMemoryProgramCache(gl::MemoryProgramCache *memoryProgramCache); void setMemoryProgramCache(gl::MemoryProgramCache *memoryProgramCache);
// TODO(jmadill): Move init into the constructor. http://anglebug.com/2491
void setErrorSet(gl::ErrorSet *errorSet);
void handleError(const gl::Error &error);
protected: protected:
const gl::ContextState &mState; const gl::ContextState &mState;
gl::MemoryProgramCache *mMemoryProgramCache; gl::MemoryProgramCache *mMemoryProgramCache;
gl::ErrorSet *mErrors;
}; };
} // namespace rx } // namespace rx
......
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