Hash :
3625b749
Author :
Date :
2023-04-27T08:19:05
[ContextEGL] Synchronize state only when first making current ContextEGL::onMakeCurrent() can be called when this context is already current, which introduces complexities for the case where this context is wrapping an external context. This CL ensures that in this case we save state from the native context only when first transitioning this context to be current. To test: Exercise the repro steps in crbug.com/1434657: No assert should go off. Bug: chromium:1434657 Change-Id: I9690a76917fcb6d0fa31361bfbd3766bb6074d41 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/4483695 Reviewed-by: Geoff Lang <geofflang@chromium.org> Commit-Queue: Geoff Lang <geofflang@chromium.org> Auto-Submit: Colin Blundell <blundell@chromium.org>
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83
//
// Copyright 2018 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.
//
#include "libANGLE/renderer/gl/egl/ContextEGL.h"
#include "libANGLE/renderer/gl/FramebufferGL.h"
#include "libANGLE/renderer/gl/StateManagerGL.h"
namespace rx
{
ContextEGL::ContextEGL(const gl::State &state,
gl::ErrorSet *errorSet,
const std::shared_ptr<RendererEGL> &renderer,
RobustnessVideoMemoryPurgeStatus robustnessVideoMemoryPurgeStatus)
: ContextGL(state, errorSet, renderer, robustnessVideoMemoryPurgeStatus), mRendererEGL(renderer)
{}
ContextEGL::~ContextEGL() {}
angle::Result ContextEGL::onMakeCurrent(const gl::Context *context)
{
// If this context is wrapping an external native context, save state from
// that external context when first making this context current.
if (!mIsCurrent && context->isExternal())
{
if (!mExtState)
{
mExtState = std::make_unique<ExternalContextState>();
const auto &caps = getCaps();
mExtState->textureBindings.resize(
static_cast<size_t>(caps.maxCombinedTextureImageUnits));
}
getStateManager()->syncFromNativeContext(getNativeExtensions(), mExtState.get());
// Use current FBO as the default framebuffer when the external context is current.
// First save the current ID of the default framebuffer to restore in
// onUnMakeCurrent().
gl::Framebuffer *framebuffer = mState.getDefaultFramebuffer();
auto framebufferGL = GetImplAs<FramebufferGL>(framebuffer);
mPrevDefaultFramebufferID = framebufferGL->getFramebufferID();
framebufferGL->updateDefaultFramebufferID(mExtState->framebufferBinding);
}
mIsCurrent = true;
return ContextGL::onMakeCurrent(context);
}
angle::Result ContextEGL::onUnMakeCurrent(const gl::Context *context)
{
mIsCurrent = false;
if (context->saveAndRestoreState())
{
ASSERT(context->isExternal());
ASSERT(mExtState);
getStateManager()->restoreNativeContext(getNativeExtensions(), mExtState.get());
}
if (context->isExternal())
{
// If the default framebuffer exists, update its ID (note that there can
// be multiple consecutive onUnMakeCurrent() calls in destruction, and
// the default FBO will have been unset by the first one).
gl::Framebuffer *framebuffer = mState.getDefaultFramebuffer();
if (framebuffer)
{
auto framebufferGL = GetImplAs<FramebufferGL>(framebuffer);
framebufferGL->updateDefaultFramebufferID(mPrevDefaultFramebufferID);
}
}
return ContextGL::onUnMakeCurrent(context);
}
EGLContext ContextEGL::getContext() const
{
return mRendererEGL->getContext();
}
} // namespace rx