Commit 3ad5e7fd authored by boliu's avatar boliu Committed by Commit bot

Avoid EGLImage target texture reuse on PowerVR

This workarounds a memory corruption bug in PowerVR drivers
that cause memory corruption. The bug happens when
EGLImageTargetTexture2DOES is called on an already
defined texture object.

Workaround is to always create a new texture id each time.
This only works if there are no other code saving the
old texture id, and only AsyncPixelTransferDelegateIdle
needed to be updated to not do this.

BUG=480992

Review URL: https://codereview.chromium.org/1105153003

Cr-Commit-Position: refs/heads/master@{#327425}
parent ed75d1b5
...@@ -32,9 +32,10 @@ class AsyncPixelTransferDelegateIdle ...@@ -32,9 +32,10 @@ class AsyncPixelTransferDelegateIdle
: public AsyncPixelTransferDelegate, : public AsyncPixelTransferDelegate,
public base::SupportsWeakPtr<AsyncPixelTransferDelegateIdle> { public base::SupportsWeakPtr<AsyncPixelTransferDelegateIdle> {
public: public:
typedef base::Callback<GLuint()> TextureIdCallback;
AsyncPixelTransferDelegateIdle( AsyncPixelTransferDelegateIdle(
AsyncPixelTransferManagerIdle::SharedState* state, AsyncPixelTransferManagerIdle::SharedState* state,
GLuint texture_id, const TextureIdCallback& texture_id_callback,
const AsyncTexImage2DParams& define_params); const AsyncTexImage2DParams& define_params);
~AsyncPixelTransferDelegateIdle() override; ~AsyncPixelTransferDelegateIdle() override;
...@@ -55,7 +56,7 @@ class AsyncPixelTransferDelegateIdle ...@@ -55,7 +56,7 @@ class AsyncPixelTransferDelegateIdle
AsyncMemoryParams mem_params); AsyncMemoryParams mem_params);
uint64 id_; uint64 id_;
GLuint texture_id_; TextureIdCallback texture_id_callback_;
bool transfer_in_progress_; bool transfer_in_progress_;
AsyncTexImage2DParams define_params_; AsyncTexImage2DParams define_params_;
...@@ -68,10 +69,10 @@ class AsyncPixelTransferDelegateIdle ...@@ -68,10 +69,10 @@ class AsyncPixelTransferDelegateIdle
AsyncPixelTransferDelegateIdle::AsyncPixelTransferDelegateIdle( AsyncPixelTransferDelegateIdle::AsyncPixelTransferDelegateIdle(
AsyncPixelTransferManagerIdle::SharedState* shared_state, AsyncPixelTransferManagerIdle::SharedState* shared_state,
GLuint texture_id, const TextureIdCallback& texture_id_callback,
const AsyncTexImage2DParams& define_params) const AsyncTexImage2DParams& define_params)
: id_(g_next_pixel_transfer_state_id++), : id_(g_next_pixel_transfer_state_id++),
texture_id_(texture_id), texture_id_callback_(texture_id_callback),
transfer_in_progress_(false), transfer_in_progress_(false),
define_params_(define_params), define_params_(define_params),
shared_state_(shared_state) {} shared_state_(shared_state) {}
...@@ -145,7 +146,8 @@ void AsyncPixelTransferDelegateIdle::PerformAsyncTexImage2D( ...@@ -145,7 +146,8 @@ void AsyncPixelTransferDelegateIdle::PerformAsyncTexImage2D(
void* data = mem_params.GetDataAddress(); void* data = mem_params.GetDataAddress();
base::TimeTicks begin_time(base::TimeTicks::Now()); base::TimeTicks begin_time(base::TimeTicks::Now());
gfx::ScopedTextureBinder texture_binder(tex_params.target, texture_id_); gfx::ScopedTextureBinder texture_binder(tex_params.target,
texture_id_callback_.Run());
{ {
TRACE_EVENT0("gpu", "glTexImage2D"); TRACE_EVENT0("gpu", "glTexImage2D");
...@@ -181,7 +183,8 @@ void AsyncPixelTransferDelegateIdle::PerformAsyncTexSubImage2D( ...@@ -181,7 +183,8 @@ void AsyncPixelTransferDelegateIdle::PerformAsyncTexSubImage2D(
void* data = mem_params.GetDataAddress(); void* data = mem_params.GetDataAddress();
base::TimeTicks begin_time(base::TimeTicks::Now()); base::TimeTicks begin_time(base::TimeTicks::Now());
gfx::ScopedTextureBinder texture_binder(tex_params.target, texture_id_); gfx::ScopedTextureBinder texture_binder(tex_params.target,
texture_id_callback_.Run());
if (shared_state_->use_teximage2d_over_texsubimage2d && if (shared_state_->use_teximage2d_over_texsubimage2d &&
tex_params.xoffset == 0 && tex_params.xoffset == 0 &&
...@@ -317,9 +320,15 @@ AsyncPixelTransferDelegate* ...@@ -317,9 +320,15 @@ AsyncPixelTransferDelegate*
AsyncPixelTransferManagerIdle::CreatePixelTransferDelegateImpl( AsyncPixelTransferManagerIdle::CreatePixelTransferDelegateImpl(
gles2::TextureRef* ref, gles2::TextureRef* ref,
const AsyncTexImage2DParams& define_params) { const AsyncTexImage2DParams& define_params) {
return new AsyncPixelTransferDelegateIdle(&shared_state_, return new AsyncPixelTransferDelegateIdle(
ref->service_id(), &shared_state_,
define_params); // Not directly passing texture_ref->service_id here because it can change
// if avoid_egl_image_target_texture_reuse workaround is in effect.
// Unretained is safe because AsyncPixelTransferManager observes
// TextureRef destruction and destroys the delegate before TextureRef
// is destroyed.
base::Bind(&gles2::TextureRef::service_id, base::Unretained(ref)),
define_params);
} }
} // namespace gpu } // namespace gpu
...@@ -14,6 +14,7 @@ ...@@ -14,6 +14,7 @@
#include "base/strings/string_util.h" #include "base/strings/string_util.h"
#include "gpu/command_buffer/service/gl_utils.h" #include "gpu/command_buffer/service/gl_utils.h"
#include "gpu/command_buffer/service/gpu_switches.h" #include "gpu/command_buffer/service/gpu_switches.h"
#include "gpu/command_buffer/service/texture_definition.h"
#include "gpu/config/gpu_switches.h" #include "gpu/config/gpu_switches.h"
#include "ui/gl/gl_fence.h" #include "ui/gl/gl_fence.h"
#include "ui/gl/gl_implementation.h" #include "ui/gl/gl_implementation.h"
...@@ -1100,6 +1101,10 @@ void FeatureInfo::InitializeFeatures() { ...@@ -1100,6 +1101,10 @@ void FeatureInfo::InitializeFeatures() {
} }
#endif #endif
if (workarounds_.avoid_egl_image_target_texture_reuse) {
TextureDefinition::AvoidEGLTargetTextureReuse();
}
if (gl_version_info_->IsLowerThanGL(4, 3)) { if (gl_version_info_->IsLowerThanGL(4, 3)) {
// crbug.com/481184. // crbug.com/481184.
// GL_PRIMITIVE_RESTART_FIXED_INDEX is only available on Desktop GL 4.3+, // GL_PRIMITIVE_RESTART_FIXED_INDEX is only available on Desktop GL 4.3+,
......
...@@ -243,6 +243,8 @@ class NativeImageBufferStub : public NativeImageBuffer { ...@@ -243,6 +243,8 @@ class NativeImageBufferStub : public NativeImageBuffer {
DISALLOW_COPY_AND_ASSIGN(NativeImageBufferStub); DISALLOW_COPY_AND_ASSIGN(NativeImageBufferStub);
}; };
bool g_avoid_egl_target_texture_reuse = false;
} // anonymous namespace } // anonymous namespace
// static // static
...@@ -260,6 +262,11 @@ scoped_refptr<NativeImageBuffer> NativeImageBuffer::Create(GLuint texture_id) { ...@@ -260,6 +262,11 @@ scoped_refptr<NativeImageBuffer> NativeImageBuffer::Create(GLuint texture_id) {
} }
} }
// static
void TextureDefinition::AvoidEGLTargetTextureReuse() {
g_avoid_egl_target_texture_reuse = true;
}
TextureDefinition::LevelInfo::LevelInfo() TextureDefinition::LevelInfo::LevelInfo()
: target(0), : target(0),
internal_format(0), internal_format(0),
...@@ -347,12 +354,12 @@ Texture* TextureDefinition::CreateTexture() const { ...@@ -347,12 +354,12 @@ Texture* TextureDefinition::CreateTexture() const {
glGenTextures(1, &texture_id); glGenTextures(1, &texture_id);
Texture* texture(new Texture(texture_id)); Texture* texture(new Texture(texture_id));
UpdateTexture(texture); UpdateTextureInternal(texture);
return texture; return texture;
} }
void TextureDefinition::UpdateTexture(Texture* texture) const { void TextureDefinition::UpdateTextureInternal(Texture* texture) const {
gfx::ScopedTextureBinder texture_binder(target_, texture->service_id()); gfx::ScopedTextureBinder texture_binder(target_, texture->service_id());
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, min_filter_); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, min_filter_);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, mag_filter_); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, mag_filter_);
...@@ -397,6 +404,22 @@ void TextureDefinition::UpdateTexture(Texture* texture) const { ...@@ -397,6 +404,22 @@ void TextureDefinition::UpdateTexture(Texture* texture) const {
texture->usage_ = usage_; texture->usage_ = usage_;
} }
void TextureDefinition::UpdateTexture(Texture* texture) const {
GLuint old_service_id = 0u;
if (image_buffer_.get() && g_avoid_egl_target_texture_reuse) {
GLuint service_id = 0u;
glGenTextures(1, &service_id);
old_service_id = texture->service_id();
texture->SetServiceId(service_id);
}
UpdateTextureInternal(texture);
if (old_service_id) {
glDeleteTextures(1, &old_service_id);
}
}
bool TextureDefinition::Matches(const Texture* texture) const { bool TextureDefinition::Matches(const Texture* texture) const {
DCHECK(target_ == texture->target()); DCHECK(target_ == texture->target());
if (texture->min_filter_ != min_filter_ || if (texture->min_filter_ != min_filter_ ||
......
...@@ -40,6 +40,8 @@ class NativeImageBuffer : public base::RefCountedThreadSafe<NativeImageBuffer> { ...@@ -40,6 +40,8 @@ class NativeImageBuffer : public base::RefCountedThreadSafe<NativeImageBuffer> {
// the underlying image buffer(s). // the underlying image buffer(s).
class TextureDefinition { class TextureDefinition {
public: public:
static void AvoidEGLTargetTextureReuse();
TextureDefinition(); TextureDefinition();
TextureDefinition(Texture* texture, TextureDefinition(Texture* texture,
unsigned int version, unsigned int version,
...@@ -59,6 +61,7 @@ class TextureDefinition { ...@@ -59,6 +61,7 @@ class TextureDefinition {
private: private:
bool SafeToRenderFrom() const; bool SafeToRenderFrom() const;
void UpdateTextureInternal(Texture* texture) const;
struct LevelInfo { struct LevelInfo {
LevelInfo(); LevelInfo();
......
...@@ -19,7 +19,7 @@ const char kGpuDriverBugListJson[] = LONG_STRING_CONST( ...@@ -19,7 +19,7 @@ const char kGpuDriverBugListJson[] = LONG_STRING_CONST(
{ {
"name": "gpu driver bug list", "name": "gpu driver bug list",
// Please update the version number whenever you change this file. // Please update the version number whenever you change this file.
"version": "7.23", "version": "7.24",
"entries": [ "entries": [
{ {
"id": 1, "id": 1,
...@@ -1232,7 +1232,7 @@ LONG_STRING_CONST( ...@@ -1232,7 +1232,7 @@ LONG_STRING_CONST(
}, },
{ {
"id": 107, "id": 107,
"description": "EGL Sync server wait broken on IMG G6xxx drivers", "description": "Workaround IMG PowerVR G6xxx drivers bugs",
"cr_bugs": [480992], "cr_bugs": [480992],
"os": { "os": {
"type": "android", "type": "android",
...@@ -1250,6 +1250,7 @@ LONG_STRING_CONST( ...@@ -1250,6 +1250,7 @@ LONG_STRING_CONST(
"value2": "1.4" "value2": "1.4"
}, },
"features": [ "features": [
"avoid_egl_image_target_texture_reuse",
"disable_egl_khr_wait_sync" "disable_egl_khr_wait_sync"
] ]
} }
......
...@@ -10,6 +10,8 @@ ...@@ -10,6 +10,8 @@
#include "gpu/gpu_export.h" #include "gpu/gpu_export.h"
#define GPU_DRIVER_BUG_WORKAROUNDS(GPU_OP) \ #define GPU_DRIVER_BUG_WORKAROUNDS(GPU_OP) \
GPU_OP(AVOID_EGL_IMAGE_TARGET_TEXTURE_REUSE, \
avoid_egl_image_target_texture_reuse) \
GPU_OP(CLEAR_ALPHA_IN_READPIXELS, \ GPU_OP(CLEAR_ALPHA_IN_READPIXELS, \
clear_alpha_in_readpixels) \ clear_alpha_in_readpixels) \
GPU_OP(CLEAR_UNIFORMS_BEFORE_FIRST_PROGRAM_USE, \ GPU_OP(CLEAR_UNIFORMS_BEFORE_FIRST_PROGRAM_USE, \
......
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