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
|
// Copyright 2022 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "ui/gl/scoped_restore_texture.h"
#include "base/feature_list.h"
#include "base/notreached.h"
namespace gl {
namespace {
// The `restore_prev_even_if_invalid` param was introduced to support legacy
// behavior while porting clients of duplicate solutions. Our suspicion is that
// it's not necessary to guard restoring the previous binding with a check that
// it's valid; that behavior was introduced as a speculative fix for a crash
// in https://chromium-review.googlesource.com/c/chromium/src/+/3669775 but
// didn't seem to help
// (https://bugs.chromium.org/p/chromium/issues/detail?id=1327231#c13). This
// killswitch guards switching to unconditionally restore the previous binding.
// Once this change definitively lands, we will unconditionally restore the
// previous binding and remove the `restore_prev_even_if_invalid` parameter
// altogether.
BASE_FEATURE(kAlwaysRestorePrevEvenIfInvalid,
"AlwaysRestorePrevEvenIfInvalid",
base::FEATURE_ENABLED_BY_DEFAULT);
} // namespace
ScopedRestoreTexture::ScopedRestoreTexture(
gl::GLApi* api,
GLenum target,
bool restore_prev_even_if_invalid /*=false*/,
GLuint new_binding /*= 0*/)
: api_(api), target_(target) {
DCHECK(target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES ||
target == GL_TEXTURE_RECTANGLE_ARB);
GLenum get_target = GL_TEXTURE_BINDING_2D;
switch (target) {
case GL_TEXTURE_2D:
get_target = GL_TEXTURE_BINDING_2D;
break;
case GL_TEXTURE_RECTANGLE_ARB:
get_target = GL_TEXTURE_BINDING_RECTANGLE_ARB;
break;
case GL_TEXTURE_EXTERNAL_OES:
get_target = GL_TEXTURE_BINDING_EXTERNAL_OES;
break;
default:
NOTREACHED();
}
GLint binding = 0;
api->glGetIntegervFn(get_target, &binding);
// The bound texture could be already deleted by another context, and the
// texture ID |binding| could be reused and points to a different texture.
// NOTE: See comment on killswitch above.
if (api->glIsTextureFn(binding) || restore_prev_even_if_invalid ||
base::FeatureList::IsEnabled(kAlwaysRestorePrevEvenIfInvalid)) {
prev_binding_ = binding;
}
if (new_binding) {
api->glBindTextureFn(target, new_binding);
}
}
ScopedRestoreTexture::~ScopedRestoreTexture() {
api_->glBindTextureFn(target_, prev_binding_);
}
} // namespace gl
|