Commit d128139d authored by Vikas Soni's avatar Vikas Soni Committed by Commit Bot

Fix tabs sharing TEXTURE_2D_ARRAY/TEXTURE_3D data.

In linux and android, we are seeing an issue where texture data from one
tab overwrites the texture data of another tab. This is happening for apps
which are using webgl2 texture of type TEXTURE_2D_ARRAY/TEXTURE_3D.
Due to a bug in virtual context save/restore code for above texture formats,
the texture data is not properly restored while switching tabs. Hence
texture data from one tab overwrites other.

This CL has fix for that issue, an update for existing test expectations
and a new unit test for this bug.


Bug: 788448
Cq-Include-Trybots: master.tryserver.chromium.android:android_optional_gpu_tests_rel;master.tryserver.chromium.linux:linux_optional_gpu_tests_rel;master.tryserver.chromium.mac:mac_optional_gpu_tests_rel;master.tryserver.chromium.win:win_optional_gpu_tests_rel
Change-Id: Ie933984cdd2d1381f42eb4638f730c8245207a28
Reviewed-on: https://chromium-review.googlesource.com/930327Reviewed-by: default avatarZhenyao Mo <zmo@chromium.org>
Commit-Queue: vikas soni <vikassoni@chromium.org>
Cr-Commit-Position: refs/heads/master@{#539111}
parent ccaa8bf9
...@@ -29,6 +29,16 @@ GLuint Get2dServiceId(const TextureUnit& unit) { ...@@ -29,6 +29,16 @@ GLuint Get2dServiceId(const TextureUnit& unit) {
? unit.bound_texture_2d->service_id() : 0; ? unit.bound_texture_2d->service_id() : 0;
} }
GLuint Get2dArrayServiceId(const TextureUnit& unit) {
return unit.bound_texture_2d_array.get()
? unit.bound_texture_2d_array->service_id()
: 0;
}
GLuint Get3dServiceId(const TextureUnit& unit) {
return unit.bound_texture_3d.get() ? unit.bound_texture_3d->service_id() : 0;
}
GLuint GetCubeServiceId(const TextureUnit& unit) { GLuint GetCubeServiceId(const TextureUnit& unit) {
return unit.bound_texture_cube_map.get() return unit.bound_texture_cube_map.get()
? unit.bound_texture_cube_map->service_id() : 0; ? unit.bound_texture_cube_map->service_id() : 0;
...@@ -237,6 +247,8 @@ void ContextState::RestoreTextureUnitBindings( ...@@ -237,6 +247,8 @@ void ContextState::RestoreTextureUnitBindings(
DCHECK_LT(unit, texture_units.size()); DCHECK_LT(unit, texture_units.size());
const TextureUnit& texture_unit = texture_units[unit]; const TextureUnit& texture_unit = texture_units[unit];
GLuint service_id_2d = Get2dServiceId(texture_unit); GLuint service_id_2d = Get2dServiceId(texture_unit);
GLuint service_id_2d_array = Get2dArrayServiceId(texture_unit);
GLuint service_id_3d = Get3dServiceId(texture_unit);
GLuint service_id_cube = GetCubeServiceId(texture_unit); GLuint service_id_cube = GetCubeServiceId(texture_unit);
GLuint service_id_oes = GetOesServiceId(texture_unit); GLuint service_id_oes = GetOesServiceId(texture_unit);
GLuint service_id_arb = GetArbServiceId(texture_unit); GLuint service_id_arb = GetArbServiceId(texture_unit);
...@@ -247,10 +259,22 @@ void ContextState::RestoreTextureUnitBindings( ...@@ -247,10 +259,22 @@ void ContextState::RestoreTextureUnitBindings(
feature_info_->feature_flags().oes_egl_image_external || feature_info_->feature_flags().oes_egl_image_external ||
feature_info_->feature_flags().nv_egl_stream_consumer_external; feature_info_->feature_flags().nv_egl_stream_consumer_external;
bool bind_texture_arb = feature_info_->feature_flags().arb_texture_rectangle; bool bind_texture_arb = feature_info_->feature_flags().arb_texture_rectangle;
// TEXTURE_2D_ARRAY and TEXTURE_3D are only applicable from ES3 version.
// So set it to FALSE by default.
bool bind_texture_2d_array = false;
bool bind_texture_3d = false;
// set the variables to true only if the application is ES3 or newer
if (feature_info_->IsES3Capable()) {
bind_texture_2d_array = true;
bind_texture_3d = true;
}
if (prev_state) { if (prev_state) {
const TextureUnit& prev_unit = prev_state->texture_units[unit]; const TextureUnit& prev_unit = prev_state->texture_units[unit];
bind_texture_2d = service_id_2d != Get2dServiceId(prev_unit); bind_texture_2d = service_id_2d != Get2dServiceId(prev_unit);
bind_texture_2d_array =
service_id_2d_array != Get2dArrayServiceId(prev_unit);
bind_texture_3d = service_id_3d != Get3dServiceId(prev_unit);
bind_texture_cube = service_id_cube != GetCubeServiceId(prev_unit); bind_texture_cube = service_id_cube != GetCubeServiceId(prev_unit);
bind_texture_oes = bind_texture_oes =
bind_texture_oes && service_id_oes != GetOesServiceId(prev_unit); bind_texture_oes && service_id_oes != GetOesServiceId(prev_unit);
...@@ -259,8 +283,8 @@ void ContextState::RestoreTextureUnitBindings( ...@@ -259,8 +283,8 @@ void ContextState::RestoreTextureUnitBindings(
} }
// Early-out if nothing has changed from the previous state. // Early-out if nothing has changed from the previous state.
if (!bind_texture_2d && !bind_texture_cube if (!bind_texture_2d && !bind_texture_2d_array && !bind_texture_3d &&
&& !bind_texture_oes && !bind_texture_arb) { !bind_texture_cube && !bind_texture_oes && !bind_texture_arb) {
return; return;
} }
...@@ -277,6 +301,12 @@ void ContextState::RestoreTextureUnitBindings( ...@@ -277,6 +301,12 @@ void ContextState::RestoreTextureUnitBindings(
if (bind_texture_arb) { if (bind_texture_arb) {
api()->glBindTextureFn(GL_TEXTURE_RECTANGLE_ARB, service_id_arb); api()->glBindTextureFn(GL_TEXTURE_RECTANGLE_ARB, service_id_arb);
} }
if (bind_texture_2d_array) {
api()->glBindTextureFn(GL_TEXTURE_2D_ARRAY, service_id_2d_array);
}
if (bind_texture_3d) {
api()->glBindTextureFn(GL_TEXTURE_3D, service_id_3d);
}
} }
void ContextState::RestoreSamplerBinding(GLuint unit, void ContextState::RestoreSamplerBinding(GLuint unit,
......
...@@ -418,6 +418,8 @@ TEST_P(GLES2DecoderRestoreStateTest, ES3NullPreviousStateWithSampler) { ...@@ -418,6 +418,8 @@ TEST_P(GLES2DecoderRestoreStateTest, ES3NullPreviousStateWithSampler) {
AddExpectationsForActiveTexture(GL_TEXTURE0); AddExpectationsForActiveTexture(GL_TEXTURE0);
AddExpectationsForBindTexture(GL_TEXTURE_2D, kServiceTextureId); AddExpectationsForBindTexture(GL_TEXTURE_2D, kServiceTextureId);
AddExpectationsForBindTexture(GL_TEXTURE_CUBE_MAP, 0); AddExpectationsForBindTexture(GL_TEXTURE_CUBE_MAP, 0);
AddExpectationsForBindTexture(GL_TEXTURE_2D_ARRAY, 0);
AddExpectationsForBindTexture(GL_TEXTURE_3D, 0);
// Expect to restore sampler binding for unit GL_TEXTURE0. // Expect to restore sampler binding for unit GL_TEXTURE0.
AddExpectationsForBindSampler(0, kServiceSamplerId); AddExpectationsForBindSampler(0, kServiceSamplerId);
...@@ -426,6 +428,8 @@ TEST_P(GLES2DecoderRestoreStateTest, ES3NullPreviousStateWithSampler) { ...@@ -426,6 +428,8 @@ TEST_P(GLES2DecoderRestoreStateTest, ES3NullPreviousStateWithSampler) {
AddExpectationsForActiveTexture(GL_TEXTURE0 + i); AddExpectationsForActiveTexture(GL_TEXTURE0 + i);
AddExpectationsForBindTexture(GL_TEXTURE_2D, 0); AddExpectationsForBindTexture(GL_TEXTURE_2D, 0);
AddExpectationsForBindTexture(GL_TEXTURE_CUBE_MAP, 0); AddExpectationsForBindTexture(GL_TEXTURE_CUBE_MAP, 0);
AddExpectationsForBindTexture(GL_TEXTURE_2D_ARRAY, 0);
AddExpectationsForBindTexture(GL_TEXTURE_3D, 0);
AddExpectationsForBindSampler(i, 0); AddExpectationsForBindSampler(i, 0);
} }
......
...@@ -269,6 +269,7 @@ void GLManager::InitializeWithWorkaroundsImpl( ...@@ -269,6 +269,7 @@ void GLManager::InitializeWithWorkaroundsImpl(
InitializeGpuPreferencesForTestingFromCommandLine(command_line, InitializeGpuPreferencesForTestingFromCommandLine(command_line,
&gpu_preferences_); &gpu_preferences_);
context_type_ = options.context_type;
if (options.share_mailbox_manager) { if (options.share_mailbox_manager) {
mailbox_manager_ = options.share_mailbox_manager->mailbox_manager(); mailbox_manager_ = options.share_mailbox_manager->mailbox_manager();
} else if (options.share_group_manager) { } else if (options.share_group_manager) {
...@@ -574,4 +575,7 @@ bool GLManager::CanWaitUnverifiedSyncToken(const gpu::SyncToken& sync_token) { ...@@ -574,4 +575,7 @@ bool GLManager::CanWaitUnverifiedSyncToken(const gpu::SyncToken& sync_token) {
void GLManager::SetSnapshotRequested() {} void GLManager::SetSnapshotRequested() {}
ContextType GLManager::GetContextType() const {
return context_type_;
}
} // namespace gpu } // namespace gpu
...@@ -155,6 +155,7 @@ class GLManager : private GpuControl { ...@@ -155,6 +155,7 @@ class GLManager : private GpuControl {
void SetSnapshotRequested() override; void SetSnapshotRequested() override;
size_t GetSharedMemoryBytesAllocated() const; size_t GetSharedMemoryBytesAllocated() const;
ContextType GetContextType() const;
private: private:
void SetupBaseContext(); void SetupBaseContext();
...@@ -192,6 +193,7 @@ class GLManager : private GpuControl { ...@@ -192,6 +193,7 @@ class GLManager : private GpuControl {
static scoped_refptr<gl::GLShareGroup>* base_share_group_; static scoped_refptr<gl::GLShareGroup>* base_share_group_;
static scoped_refptr<gl::GLSurface>* base_surface_; static scoped_refptr<gl::GLSurface>* base_surface_;
static scoped_refptr<gl::GLContext>* base_context_; static scoped_refptr<gl::GLContext>* base_context_;
ContextType context_type_ = CONTEXT_TYPE_OPENGLES2;
}; };
} // namespace gpu } // namespace gpu
......
...@@ -27,8 +27,15 @@ class GLVirtualContextsTest ...@@ -27,8 +27,15 @@ class GLVirtualContextsTest
void SetUp() override { void SetUp() override {
GpuDriverBugWorkarounds workarounds = GetParam(); GpuDriverBugWorkarounds workarounds = GetParam();
GLManager::Options options; GLManager::Options options;
options.context_type = CONTEXT_TYPE_OPENGLES3;
options.size = gfx::Size(kSize0, kSize0); options.size = gfx::Size(kSize0, kSize0);
gl_real_.InitializeWithWorkarounds(options, workarounds); gl_real_.InitializeWithWorkarounds(options, workarounds);
// If the gl_real context is not initialised, switch to ES2 context type
// and re-initialise
if (!gl_real_.IsInitialized()) {
options.context_type = CONTEXT_TYPE_OPENGLES2;
gl_real_.InitializeWithWorkarounds(options, workarounds);
}
gl_real_shared_.InitializeWithWorkarounds(options, workarounds); gl_real_shared_.InitializeWithWorkarounds(options, workarounds);
options.virtual_manager = &gl_real_shared_; options.virtual_manager = &gl_real_shared_;
options.size = gfx::Size(kSize1, kSize1); options.size = gfx::Size(kSize1, kSize1);
...@@ -363,6 +370,57 @@ TEST_P(GLVirtualContextsTest, VirtualQueries) { ...@@ -363,6 +370,57 @@ TEST_P(GLVirtualContextsTest, VirtualQueries) {
} }
} }
// http://crbug.com/930327
TEST_P(GLVirtualContextsTest, Texture2DArrayAnd3DRestore) {
// This test should only be run for ES3 or higher context
// So if the current version is ES2, do not run this test
if (gl1_.GetContextType() == CONTEXT_TYPE_OPENGLES2)
return;
// Context 1
gl1_.MakeCurrent();
GLuint tex1_2d_array = 0, tex1_3d = 0;
glActiveTexture(GL_TEXTURE0);
// 2d array texture
glGenTextures(1, &tex1_2d_array);
glBindTexture(GL_TEXTURE_2D_ARRAY, tex1_2d_array);
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
// 3d texture
glGenTextures(1, &tex1_3d);
glBindTexture(GL_TEXTURE_3D, tex1_3d);
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER,
GL_NEAREST_MIPMAP_NEAREST);
glFinish();
// switch to context 2
gl2_.MakeCurrent();
GLuint tex2_2d_array = 0, tex2_3d = 0;
glActiveTexture(GL_TEXTURE0);
// 2d array texture
glGenTextures(1, &tex2_2d_array);
glBindTexture(GL_TEXTURE_2D_ARRAY, tex2_2d_array);
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
// 3d texture
glGenTextures(1, &tex2_3d);
glBindTexture(GL_TEXTURE_3D, tex2_3d);
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER,
GL_LINEAR_MIPMAP_LINEAR);
glFinish();
// switch back to context1
gl1_.MakeCurrent();
// get the texture parameters which were programmed earlier for context1
GLint tex_2d_array_params = 0, tex_3d_params = 0;
glGetTexParameteriv(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER,
&tex_2d_array_params);
glGetTexParameteriv(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, &tex_3d_params);
// Do checks to make sure texture params are restored correctly after context
// switching
EXPECT_EQ(GL_NEAREST, tex_2d_array_params);
EXPECT_EQ(GL_NEAREST_MIPMAP_NEAREST, tex_3d_params);
GLTestHelper::CheckGLError("no errors", __LINE__);
}
static const GpuDriverBugWorkarounds workarounds_cases[] = { static const GpuDriverBugWorkarounds workarounds_cases[] = {
// No extra workarounds. // No extra workarounds.
GpuDriverBugWorkarounds(), GpuDriverBugWorkarounds(),
......
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