зеркало из https://github.com/AvaloniaUI/angle.git
Reland 'Remove IndexRange retrieving in validation'
This change adds GL_KHR_robust_buffer_access_behavior support. The old change is in https://chromium-review.googlesource.com/c/angle/angle/+/607413 BUG=755897, angleproject:1393, angleproject:1463 Change-Id: I04a1132c3ae8d3a766194df61c4ff7bf0b084f03 Reviewed-on: https://chromium-review.googlesource.com/640750 Commit-Queue: Geoff Lang <geofflang@chromium.org> Reviewed-by: Geoff Lang <geofflang@chromium.org>
This commit is contained in:
Родитель
72b4e1e5bb
Коммит
8a7b3a0ced
|
@ -177,6 +177,7 @@ Extensions::Extensions()
|
||||||
queryCounterBitsTimeElapsed(0),
|
queryCounterBitsTimeElapsed(0),
|
||||||
queryCounterBitsTimestamp(0),
|
queryCounterBitsTimestamp(0),
|
||||||
robustness(false),
|
robustness(false),
|
||||||
|
robustBufferAccessBehavior(false),
|
||||||
blendMinMax(false),
|
blendMinMax(false),
|
||||||
framebufferBlit(false),
|
framebufferBlit(false),
|
||||||
framebufferMultisample(false),
|
framebufferMultisample(false),
|
||||||
|
@ -651,6 +652,7 @@ const ExtensionInfoMap &GetExtensionInfoMap()
|
||||||
map["GL_ANGLE_timer_query"] = esOnlyExtension(&Extensions::timerQuery);
|
map["GL_ANGLE_timer_query"] = esOnlyExtension(&Extensions::timerQuery);
|
||||||
map["GL_EXT_disjoint_timer_query"] = esOnlyExtension(&Extensions::disjointTimerQuery);
|
map["GL_EXT_disjoint_timer_query"] = esOnlyExtension(&Extensions::disjointTimerQuery);
|
||||||
map["GL_EXT_robustness"] = esOnlyExtension(&Extensions::robustness);
|
map["GL_EXT_robustness"] = esOnlyExtension(&Extensions::robustness);
|
||||||
|
map["GL_KHR_robust_buffer_access_behavior"] = esOnlyExtension(&Extensions::robustBufferAccessBehavior);
|
||||||
map["GL_EXT_blend_minmax"] = esOnlyExtension(&Extensions::blendMinMax);
|
map["GL_EXT_blend_minmax"] = esOnlyExtension(&Extensions::blendMinMax);
|
||||||
map["GL_ANGLE_framebuffer_blit"] = esOnlyExtension(&Extensions::framebufferBlit);
|
map["GL_ANGLE_framebuffer_blit"] = esOnlyExtension(&Extensions::framebufferBlit);
|
||||||
map["GL_ANGLE_framebuffer_multisample"] = esOnlyExtension(&Extensions::framebufferMultisample);
|
map["GL_ANGLE_framebuffer_multisample"] = esOnlyExtension(&Extensions::framebufferMultisample);
|
||||||
|
|
|
@ -218,6 +218,9 @@ struct Extensions
|
||||||
// GL_EXT_robustness
|
// GL_EXT_robustness
|
||||||
bool robustness;
|
bool robustness;
|
||||||
|
|
||||||
|
// GL_KHR_robust_buffer_access_behavior
|
||||||
|
bool robustBufferAccessBehavior;
|
||||||
|
|
||||||
// GL_EXT_blend_minmax
|
// GL_EXT_blend_minmax
|
||||||
bool blendMinMax;
|
bool blendMinMax;
|
||||||
|
|
||||||
|
|
|
@ -280,11 +280,6 @@ Context::Context(rx::EGLImplFactory *implFactory,
|
||||||
mScratchBuffer(1000u),
|
mScratchBuffer(1000u),
|
||||||
mZeroFilledBuffer(1000u)
|
mZeroFilledBuffer(1000u)
|
||||||
{
|
{
|
||||||
if (mRobustAccess)
|
|
||||||
{
|
|
||||||
UNIMPLEMENTED();
|
|
||||||
}
|
|
||||||
|
|
||||||
initCaps(displayExtensions);
|
initCaps(displayExtensions);
|
||||||
initWorkarounds();
|
initWorkarounds();
|
||||||
|
|
||||||
|
@ -2610,6 +2605,11 @@ void Context::initCaps(const egl::DisplayExtensions &displayExtensions)
|
||||||
mExtensions.robustResourceInitialization =
|
mExtensions.robustResourceInitialization =
|
||||||
egl::Display::GetClientExtensions().displayRobustResourceInitialization;
|
egl::Display::GetClientExtensions().displayRobustResourceInitialization;
|
||||||
|
|
||||||
|
// mExtensions.robustBufferAccessBehavior is true only if robust access is true and the backend
|
||||||
|
// supports it.
|
||||||
|
mExtensions.robustBufferAccessBehavior =
|
||||||
|
mRobustAccess && mExtensions.robustBufferAccessBehavior;
|
||||||
|
|
||||||
// Enable the cache control query unconditionally.
|
// Enable the cache control query unconditionally.
|
||||||
mExtensions.programCacheControl = true;
|
mExtensions.programCacheControl = true;
|
||||||
|
|
||||||
|
|
|
@ -410,7 +410,7 @@ gl::Error VertexDataManager::storeDynamicAttribs(
|
||||||
for (auto attribIndex : dynamicAttribsMask)
|
for (auto attribIndex : dynamicAttribsMask)
|
||||||
{
|
{
|
||||||
const auto &dynamicAttrib = (*translatedAttribs)[attribIndex];
|
const auto &dynamicAttrib = (*translatedAttribs)[attribIndex];
|
||||||
ANGLE_TRY(reserveSpaceForAttrib(dynamicAttrib, count, instances));
|
ANGLE_TRY(reserveSpaceForAttrib(dynamicAttrib, start, count, instances));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Store dynamic attributes
|
// Store dynamic attributes
|
||||||
|
@ -445,6 +445,7 @@ void VertexDataManager::PromoteDynamicAttribs(
|
||||||
}
|
}
|
||||||
|
|
||||||
gl::Error VertexDataManager::reserveSpaceForAttrib(const TranslatedAttribute &translatedAttrib,
|
gl::Error VertexDataManager::reserveSpaceForAttrib(const TranslatedAttribute &translatedAttrib,
|
||||||
|
GLint start,
|
||||||
GLsizei count,
|
GLsizei count,
|
||||||
GLsizei instances) const
|
GLsizei instances) const
|
||||||
{
|
{
|
||||||
|
@ -460,10 +461,23 @@ gl::Error VertexDataManager::reserveSpaceForAttrib(const TranslatedAttribute &tr
|
||||||
|
|
||||||
size_t totalCount = gl::ComputeVertexBindingElementCount(
|
size_t totalCount = gl::ComputeVertexBindingElementCount(
|
||||||
binding.getDivisor(), static_cast<size_t>(count), static_cast<size_t>(instances));
|
binding.getDivisor(), static_cast<size_t>(count), static_cast<size_t>(instances));
|
||||||
ASSERT(!bufferD3D ||
|
// TODO(jiajia.qin@intel.com): force the index buffer to clamp any out of range indices instead
|
||||||
ElementsInBuffer(attrib, binding, static_cast<unsigned int>(bufferD3D->getSize())) >=
|
// of invalid operation here.
|
||||||
static_cast<int>(totalCount));
|
if (bufferD3D)
|
||||||
|
{
|
||||||
|
// Vertices do not apply the 'start' offset when the divisor is non-zero even when doing
|
||||||
|
// a non-instanced draw call
|
||||||
|
GLint firstVertexIndex = binding.getDivisor() > 0 ? 0 : start;
|
||||||
|
int64_t maxVertexCount =
|
||||||
|
static_cast<int64_t>(firstVertexIndex) + static_cast<int64_t>(totalCount);
|
||||||
|
int elementsInBuffer =
|
||||||
|
ElementsInBuffer(attrib, binding, static_cast<unsigned int>(bufferD3D->getSize()));
|
||||||
|
|
||||||
|
if (maxVertexCount > elementsInBuffer)
|
||||||
|
{
|
||||||
|
return gl::InvalidOperation() << "Vertex buffer is not big enough for the draw call.";
|
||||||
|
}
|
||||||
|
}
|
||||||
return mStreamingBuffer->reserveVertexSpace(attrib, binding, static_cast<GLsizei>(totalCount),
|
return mStreamingBuffer->reserveVertexSpace(attrib, binding, static_cast<GLsizei>(totalCount),
|
||||||
instances);
|
instances);
|
||||||
}
|
}
|
||||||
|
|
|
@ -128,6 +128,7 @@ class VertexDataManager : angle::NonCopyable
|
||||||
|
|
||||||
gl::Error reserveSpaceForAttrib(const TranslatedAttribute &translatedAttrib,
|
gl::Error reserveSpaceForAttrib(const TranslatedAttribute &translatedAttrib,
|
||||||
GLsizei count,
|
GLsizei count,
|
||||||
|
GLint start,
|
||||||
GLsizei instances) const;
|
GLsizei instances) const;
|
||||||
|
|
||||||
gl::Error storeDynamicAttrib(TranslatedAttribute *translated,
|
gl::Error storeDynamicAttrib(TranslatedAttribute *translated,
|
||||||
|
|
|
@ -1381,6 +1381,9 @@ void GenerateCaps(ID3D11Device *device, ID3D11DeviceContext *deviceContext, cons
|
||||||
extensions->queryCounterBitsTimestamp =
|
extensions->queryCounterBitsTimestamp =
|
||||||
0; // Timestamps cannot be supported due to D3D11 limitations
|
0; // Timestamps cannot be supported due to D3D11 limitations
|
||||||
extensions->robustness = true;
|
extensions->robustness = true;
|
||||||
|
// Direct3D guarantees to return zero for any resource that is accessed out of bounds.
|
||||||
|
// See https://msdn.microsoft.com/en-us/library/windows/desktop/ff476332(v=vs.85).aspx
|
||||||
|
extensions->robustBufferAccessBehavior = true;
|
||||||
extensions->blendMinMax = true;
|
extensions->blendMinMax = true;
|
||||||
extensions->framebufferBlit = GetFramebufferBlitSupport(featureLevel);
|
extensions->framebufferBlit = GetFramebufferBlitSupport(featureLevel);
|
||||||
extensions->framebufferMultisample = GetFramebufferMultisampleSupport(featureLevel);
|
extensions->framebufferMultisample = GetFramebufferMultisampleSupport(featureLevel);
|
||||||
|
|
|
@ -579,6 +579,9 @@ void GenerateCaps(IDirect3D9 *d3d9,
|
||||||
extensions->timerQuery = false; // Unimplemented
|
extensions->timerQuery = false; // Unimplemented
|
||||||
extensions->disjointTimerQuery = false;
|
extensions->disjointTimerQuery = false;
|
||||||
extensions->robustness = true;
|
extensions->robustness = true;
|
||||||
|
// Direct3D guarantees to return zero for any resource that is accessed out of bounds.
|
||||||
|
// See https://msdn.microsoft.com/en-us/library/windows/desktop/ff476332(v=vs.85).aspx
|
||||||
|
extensions->robustBufferAccessBehavior = true;
|
||||||
extensions->blendMinMax = true;
|
extensions->blendMinMax = true;
|
||||||
extensions->framebufferBlit = true;
|
extensions->framebufferBlit = true;
|
||||||
extensions->framebufferMultisample = true;
|
extensions->framebufferMultisample = true;
|
||||||
|
|
|
@ -821,6 +821,8 @@ egl::Error DisplayGLX::createContextAttribs(glx::FBConfig,
|
||||||
|
|
||||||
if (mHasARBCreateContextRobustness)
|
if (mHasARBCreateContextRobustness)
|
||||||
{
|
{
|
||||||
|
attribs.push_back(GLX_CONTEXT_FLAGS_ARB);
|
||||||
|
attribs.push_back(GLX_CONTEXT_ROBUST_ACCESS_BIT_ARB);
|
||||||
attribs.push_back(GLX_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB);
|
attribs.push_back(GLX_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB);
|
||||||
attribs.push_back(GLX_LOSE_CONTEXT_ON_RESET_ARB);
|
attribs.push_back(GLX_LOSE_CONTEXT_ON_RESET_ARB);
|
||||||
}
|
}
|
||||||
|
|
|
@ -953,6 +953,11 @@ void GenerateCaps(const FunctionsGL *functions,
|
||||||
functions->hasGLESExtension("GL_KHR_robustness") ||
|
functions->hasGLESExtension("GL_KHR_robustness") ||
|
||||||
functions->hasGLESExtension("GL_EXT_robustness");
|
functions->hasGLESExtension("GL_EXT_robustness");
|
||||||
|
|
||||||
|
extensions->robustBufferAccessBehavior =
|
||||||
|
extensions->robustness &&
|
||||||
|
(functions->hasGLExtension("GL_ARB_robust_buffer_access_behavior") ||
|
||||||
|
functions->hasGLESExtension("GL_KHR_robust_buffer_access_behavior"));
|
||||||
|
|
||||||
extensions->copyTexture = true;
|
extensions->copyTexture = true;
|
||||||
extensions->syncQuery = SyncQueryGL::IsSupported(functions);
|
extensions->syncQuery = SyncQueryGL::IsSupported(functions);
|
||||||
|
|
||||||
|
|
|
@ -773,6 +773,8 @@ HGLRC DisplayWGL::createContextAttribs(const gl::Version &version, int profileMa
|
||||||
|
|
||||||
if (mHasWGLCreateContextRobustness)
|
if (mHasWGLCreateContextRobustness)
|
||||||
{
|
{
|
||||||
|
attribs.push_back(WGL_CONTEXT_FLAGS_ARB);
|
||||||
|
attribs.push_back(WGL_CONTEXT_ROBUST_ACCESS_BIT_ARB);
|
||||||
attribs.push_back(WGL_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB);
|
attribs.push_back(WGL_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB);
|
||||||
attribs.push_back(WGL_LOSE_CONTEXT_ON_RESET_ARB);
|
attribs.push_back(WGL_LOSE_CONTEXT_ON_RESET_ARB);
|
||||||
}
|
}
|
||||||
|
|
|
@ -2887,34 +2887,46 @@ bool ValidateDrawElementsCommon(ValidationContext *context,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Use the parameter buffer to retrieve and cache the index range.
|
if (context->getExtensions().robustBufferAccessBehavior)
|
||||||
// TODO: offer fast path, with disabled index validation.
|
|
||||||
// TODO: also disable index checking on back-ends that are robust to out-of-range accesses.
|
|
||||||
const auto ¶ms = context->getParams<HasIndexRange>();
|
|
||||||
const auto &indexRangeOpt = params.getIndexRange();
|
|
||||||
if (!indexRangeOpt.valid())
|
|
||||||
{
|
{
|
||||||
// Unexpected error.
|
// Here we use maxVertex = 0 and vertexCount = 1 to avoid retrieving IndexRange when robust
|
||||||
return false;
|
// access is enabled.
|
||||||
|
if (!ValidateDrawAttribs(context, primcount, 0, 1))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Use the parameter buffer to retrieve and cache the index range.
|
||||||
|
const auto ¶ms = context->getParams<HasIndexRange>();
|
||||||
|
const auto &indexRangeOpt = params.getIndexRange();
|
||||||
|
if (!indexRangeOpt.valid())
|
||||||
|
{
|
||||||
|
// Unexpected error.
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we use an index greater than our maximum supported index range, return an error.
|
||||||
|
// The ES3 spec does not specify behaviour here, it is undefined, but ANGLE should always
|
||||||
|
// return an error if possible here.
|
||||||
|
if (static_cast<GLuint64>(indexRangeOpt.value().end) >= context->getCaps().maxElementIndex)
|
||||||
|
{
|
||||||
|
ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExceedsMaxElement);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(indexRangeOpt.value().end),
|
||||||
|
static_cast<GLint>(indexRangeOpt.value().vertexCount())))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// No op if there are no real indices in the index data (all are primitive restart).
|
||||||
|
return (indexRangeOpt.value().vertexIndexCount > 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we use an index greater than our maximum supported index range, return an error.
|
return true;
|
||||||
// The ES3 spec does not specify behaviour here, it is undefined, but ANGLE should always
|
|
||||||
// return an error if possible here.
|
|
||||||
if (static_cast<GLuint64>(indexRangeOpt.value().end) >= context->getCaps().maxElementIndex)
|
|
||||||
{
|
|
||||||
ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExceedsMaxElement);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(indexRangeOpt.value().end),
|
|
||||||
static_cast<GLint>(indexRangeOpt.value().vertexCount())))
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// No op if there are no real indices in the index data (all are primitive restart).
|
|
||||||
return (indexRangeOpt.value().vertexIndexCount > 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ValidateDrawElementsInstancedCommon(ValidationContext *context,
|
bool ValidateDrawElementsInstancedCommon(ValidationContext *context,
|
||||||
|
|
|
@ -56,10 +56,10 @@ class MockValidationContext : public ValidationContext
|
||||||
};
|
};
|
||||||
|
|
||||||
// Test that ANGLE generates an INVALID_OPERATION when validating index data that uses a value
|
// Test that ANGLE generates an INVALID_OPERATION when validating index data that uses a value
|
||||||
// larger than MAX_ELEMENT_INDEX. Not specified in the GLES 3 spec, it's undefined behaviour,
|
// larger than MAX_ELEMENT_INDEX and robust access is not enabled. Not specified in the GLES 3 spec,
|
||||||
// but we want a test to ensure we maintain this behaviour.
|
// it's undefined behaviour, but we want a test to ensure we maintain this behaviour. TODO(jmadill):
|
||||||
// TODO(jmadill): Re-enable when framebuffer sync state doesn't happen in validation.
|
// Re-enable when framebuffer sync state doesn't happen in validation. Also broken because of change
|
||||||
// Also broken because of change of api of the state initialize method.
|
// of api of the state initialize method.
|
||||||
TEST(ValidationESTest, DISABLED_DrawElementsWithMaxIndexGivesError)
|
TEST(ValidationESTest, DISABLED_DrawElementsWithMaxIndexGivesError)
|
||||||
{
|
{
|
||||||
auto framebufferImpl = MakeFramebufferMock();
|
auto framebufferImpl = MakeFramebufferMock();
|
||||||
|
@ -116,8 +116,11 @@ TEST(ValidationESTest, DISABLED_DrawElementsWithMaxIndexGivesError)
|
||||||
3, 4, static_cast<GLuint>(caps.maxElementIndex)};
|
3, 4, static_cast<GLuint>(caps.maxElementIndex)};
|
||||||
EXPECT_TRUE(
|
EXPECT_TRUE(
|
||||||
ValidateDrawElementsCommon(&testContext, GL_TRIANGLES, 3, GL_UNSIGNED_INT, indexData, 1));
|
ValidateDrawElementsCommon(&testContext, GL_TRIANGLES, 3, GL_UNSIGNED_INT, indexData, 1));
|
||||||
EXPECT_FALSE(
|
if (!testContext.getExtensions().robustBufferAccessBehavior)
|
||||||
ValidateDrawElementsCommon(&testContext, GL_TRIANGLES, 6, GL_UNSIGNED_INT, indexData, 2));
|
{
|
||||||
|
EXPECT_FALSE(ValidateDrawElementsCommon(&testContext, GL_TRIANGLES, 6, GL_UNSIGNED_INT,
|
||||||
|
indexData, 2));
|
||||||
|
}
|
||||||
|
|
||||||
texture->release(nullptr);
|
texture->release(nullptr);
|
||||||
|
|
||||||
|
|
|
@ -785,6 +785,13 @@ TEST_P(VertexAttributeTest, DrawArraysBufferTooSmall)
|
||||||
// Verify that index draw with an out-of-range offset generates INVALID_OPERATION.
|
// Verify that index draw with an out-of-range offset generates INVALID_OPERATION.
|
||||||
TEST_P(VertexAttributeTest, DrawElementsBufferTooSmall)
|
TEST_P(VertexAttributeTest, DrawElementsBufferTooSmall)
|
||||||
{
|
{
|
||||||
|
if (extensionEnabled("GL_KHR_robust_buffer_access_behavior"))
|
||||||
|
{
|
||||||
|
std::cout << "Test skipped due to supporting GL_KHR_robust_buffer_access_behavior"
|
||||||
|
<< std::endl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
std::array<GLfloat, kVertexCount> inputData;
|
std::array<GLfloat, kVertexCount> inputData;
|
||||||
std::array<GLfloat, kVertexCount> expectedData;
|
std::array<GLfloat, kVertexCount> expectedData;
|
||||||
InitTestData(inputData, expectedData);
|
InitTestData(inputData, expectedData);
|
||||||
|
|
|
@ -819,6 +819,11 @@ void ANGLETestBase::setWebGLCompatibilityEnabled(bool webglCompatibility)
|
||||||
mEGLWindow->setWebGLCompatibilityEnabled(webglCompatibility);
|
mEGLWindow->setWebGLCompatibilityEnabled(webglCompatibility);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ANGLETestBase::setRobustAccess(bool enabled)
|
||||||
|
{
|
||||||
|
mEGLWindow->setRobustAccess(enabled);
|
||||||
|
}
|
||||||
|
|
||||||
void ANGLETestBase::setBindGeneratesResource(bool bindGeneratesResource)
|
void ANGLETestBase::setBindGeneratesResource(bool bindGeneratesResource)
|
||||||
{
|
{
|
||||||
mEGLWindow->setBindGeneratesResource(bindGeneratesResource);
|
mEGLWindow->setBindGeneratesResource(bindGeneratesResource);
|
||||||
|
|
|
@ -303,6 +303,7 @@ class ANGLETestBase
|
||||||
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 setRobustAccess(bool enabled);
|
||||||
void setBindGeneratesResource(bool bindGeneratesResource);
|
void setBindGeneratesResource(bool bindGeneratesResource);
|
||||||
void setDebugLayersEnabled(bool enabled);
|
void setDebugLayersEnabled(bool enabled);
|
||||||
void setClientArraysEnabled(bool enabled);
|
void setClientArraysEnabled(bool enabled);
|
||||||
|
|
|
@ -119,6 +119,7 @@ EGLWindow::EGLWindow(EGLint glesMajorVersion,
|
||||||
mWebGLCompatibility(false),
|
mWebGLCompatibility(false),
|
||||||
mBindGeneratesResource(true),
|
mBindGeneratesResource(true),
|
||||||
mClientArraysEnabled(true),
|
mClientArraysEnabled(true),
|
||||||
|
mRobustAccess(false),
|
||||||
mRobustResourceInit(),
|
mRobustResourceInit(),
|
||||||
mSwapInterval(-1),
|
mSwapInterval(-1),
|
||||||
mSamples(-1),
|
mSamples(-1),
|
||||||
|
@ -323,6 +324,13 @@ bool EGLWindow::initializeContext()
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool hasRobustness = strstr(displayExtensions, "EGL_EXT_create_context_robustness") != nullptr;
|
||||||
|
if (mRobustAccess && !hasRobustness)
|
||||||
|
{
|
||||||
|
destroyGL();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
bool hasBindGeneratesResource =
|
bool hasBindGeneratesResource =
|
||||||
strstr(displayExtensions, "EGL_CHROMIUM_create_context_bind_generates_resource") != nullptr;
|
strstr(displayExtensions, "EGL_CHROMIUM_create_context_bind_generates_resource") != nullptr;
|
||||||
if (!mBindGeneratesResource && !hasBindGeneratesResource)
|
if (!mBindGeneratesResource && !hasBindGeneratesResource)
|
||||||
|
@ -380,6 +388,12 @@ bool EGLWindow::initializeContext()
|
||||||
contextAttributes.push_back(mWebGLCompatibility ? EGL_TRUE : EGL_FALSE);
|
contextAttributes.push_back(mWebGLCompatibility ? EGL_TRUE : EGL_FALSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (hasRobustness)
|
||||||
|
{
|
||||||
|
contextAttributes.push_back(EGL_CONTEXT_OPENGL_ROBUST_ACCESS_EXT);
|
||||||
|
contextAttributes.push_back(mRobustAccess ? EGL_TRUE : EGL_FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
if (hasBindGeneratesResource)
|
if (hasBindGeneratesResource)
|
||||||
{
|
{
|
||||||
contextAttributes.push_back(EGL_CONTEXT_BIND_GENERATES_RESOURCE_CHROMIUM);
|
contextAttributes.push_back(EGL_CONTEXT_BIND_GENERATES_RESOURCE_CHROMIUM);
|
||||||
|
|
|
@ -86,6 +86,7 @@ class ANGLE_EXPORT EGLWindow : angle::NonCopyable
|
||||||
}
|
}
|
||||||
void setDebugLayersEnabled(bool enabled) { mDebugLayersEnabled = enabled; }
|
void setDebugLayersEnabled(bool enabled) { mDebugLayersEnabled = enabled; }
|
||||||
void setClientArraysEnabled(bool enabled) { mClientArraysEnabled = enabled; }
|
void setClientArraysEnabled(bool enabled) { mClientArraysEnabled = enabled; }
|
||||||
|
void setRobustAccess(bool enabled) { mRobustAccess = enabled; }
|
||||||
void setRobustResourceInit(bool enabled) { mRobustResourceInit = enabled; }
|
void setRobustResourceInit(bool enabled) { mRobustResourceInit = enabled; }
|
||||||
void setSwapInterval(EGLint swapInterval) { mSwapInterval = swapInterval; }
|
void setSwapInterval(EGLint swapInterval) { mSwapInterval = swapInterval; }
|
||||||
void setPlatformMethods(angle::PlatformMethods *platformMethods)
|
void setPlatformMethods(angle::PlatformMethods *platformMethods)
|
||||||
|
@ -156,6 +157,7 @@ class ANGLE_EXPORT EGLWindow : angle::NonCopyable
|
||||||
bool mWebGLCompatibility;
|
bool mWebGLCompatibility;
|
||||||
bool mBindGeneratesResource;
|
bool mBindGeneratesResource;
|
||||||
bool mClientArraysEnabled;
|
bool mClientArraysEnabled;
|
||||||
|
bool mRobustAccess;
|
||||||
Optional<bool> mRobustResourceInit;
|
Optional<bool> mRobustResourceInit;
|
||||||
EGLint mSwapInterval;
|
EGLint mSwapInterval;
|
||||||
EGLint mSamples;
|
EGLint mSamples;
|
||||||
|
|
Загрузка…
Ссылка в новой задаче