mirror of
https://github.com/godotengine/godot-angle-static.git
synced 2026-01-06 02:09:55 +03:00
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: Geoff Lang <geofflang@chromium.org> Reviewed-by: Corentin Wallez <cwallez@chromium.org> Tested-by: Jamie Madill <jmadill@chromium.org>
This commit is contained in:
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user