From 37b5fe3597c6f0912e7fd6b2d6ab17a0ab2cbc30 Mon Sep 17 00:00:00 2001 From: Allan Sandfeld Jensen Date: Wed, 24 Oct 2018 15:48:34 +0200 Subject: [Backport] Fix for CVE-2018-17470 Implement immutable texture base/max level clamping It seems some drivers fail to handle that gracefully, so let's always clamp to be on the safe side. BUG=877874 TEST=test case in the bug, gpu_unittests R=kbr@chromium.org Cq-Include-Trybots: luci.chromium.try:android_optional_gpu_tests_rel;luci.chromium.try:linux_optional_gpu_tests_rel;luci.chromium.try:mac_optional_gpu_tests_rel;luci.chromium.try:win_optional_gpu_tests_rel Reviewed-on: https://chromium-review.googlesource.com/1194994 Reviewed-by: Kenneth Russell Commit-Queue: Zhenyao Mo Cr-Commit-Position: refs/heads/master@{#587264} Change-Id: Ia409bc5607e2c9e17c7a6c95904b6e4d05e9e318 Reviewed-by: Allan Sandfeld Jensen --- .../command_buffer/service/gles2_cmd_decoder.cc | 75 ++++--- .../service/gles2_cmd_decoder_unittest_textures.cc | 164 ++++++++++++++ .../gpu/command_buffer/service/texture_manager.cc | 52 +++-- .../gpu/command_buffer/service/texture_manager.h | 7 + chromium/gpu/config/gpu_driver_bug_list.json | 239 +++++++++++++++++++-- 5 files changed, 470 insertions(+), 67 deletions(-) diff --git a/chromium/gpu/command_buffer/service/gles2_cmd_decoder.cc b/chromium/gpu/command_buffer/service/gles2_cmd_decoder.cc index bb809b0ba7e..d6c5828a132 100644 --- a/chromium/gpu/command_buffer/service/gles2_cmd_decoder.cc +++ b/chromium/gpu/command_buffer/service/gles2_cmd_decoder.cc @@ -11212,29 +11212,24 @@ void GLES2DecoderImpl::GetTexParameterImpl( return; } break; - // Get the level information from the texture to avoid a Mac driver - // bug where they store the levels in int16_t, making values bigger - // than 2^15-1 overflow in the negative range. case GL_TEXTURE_BASE_LEVEL: - if (workarounds().use_shadowed_tex_level_params) { - if (fparams) { - fparams[0] = static_cast(texture->base_level()); - } else { - iparams[0] = texture->base_level(); - } - return; + // Use shadowed value in case it's clamped; also because older MacOSX + // stores the value on int16_t (see https://crbug.com/610153). + if (fparams) { + fparams[0] = static_cast(texture->unclamped_base_level()); + } else { + iparams[0] = texture->unclamped_base_level(); } - break; + return; case GL_TEXTURE_MAX_LEVEL: - if (workarounds().use_shadowed_tex_level_params) { - if (fparams) { - fparams[0] = static_cast(texture->max_level()); - } else { - iparams[0] = texture->max_level(); - } - return; + // Use shadowed value in case it's clamped; also because older MacOSX + // stores the value on int16_t (see https://crbug.com/610153). + if (fparams) { + fparams[0] = static_cast(texture->unclamped_max_level()); + } else { + iparams[0] = texture->unclamped_max_level(); } - break; + return; case GL_TEXTURE_SWIZZLE_R: if (fparams) { fparams[0] = static_cast(texture->swizzle_r()); @@ -18010,25 +18005,6 @@ void GLES2DecoderImpl::TexStorageImpl(GLenum target, compatibility_internal_format = format_info->decompressed_internal_format; } - if (workarounds().reset_base_mipmap_level_before_texstorage && - texture->base_level() > 0) - api()->glTexParameteriFn(target, GL_TEXTURE_BASE_LEVEL, 0); - - // TODO(zmo): We might need to emulate TexStorage using TexImage or - // CompressedTexImage on Mac OSX where we expose ES3 APIs when the underlying - // driver is lower than 4.2 and ARB_texture_storage extension doesn't exist. - if (dimension == ContextState::k2D) { - api()->glTexStorage2DEXTFn(target, levels, compatibility_internal_format, - width, height); - } else { - api()->glTexStorage3DFn(target, levels, compatibility_internal_format, - width, height, depth); - } - if (workarounds().reset_base_mipmap_level_before_texstorage && - texture->base_level() > 0) - api()->glTexParameteriFn(target, GL_TEXTURE_BASE_LEVEL, - texture->base_level()); - { GLsizei level_width = width; GLsizei level_height = height; @@ -18056,6 +18032,29 @@ void GLES2DecoderImpl::TexStorageImpl(GLenum target, } texture->SetImmutable(true); } + + if (workarounds().reset_base_mipmap_level_before_texstorage && + texture->base_level() > 0) + api()->glTexParameteriFn(target, GL_TEXTURE_BASE_LEVEL, 0); + + // TODO(zmo): We might need to emulate TexStorage using TexImage or + // CompressedTexImage on Mac OSX where we expose ES3 APIs when the underlying + // driver is lower than 4.2 and ARB_texture_storage extension doesn't exist. + if (dimension == ContextState::k2D) { + api()->glTexStorage2DEXTFn(target, levels, compatibility_internal_format, + width, height); + } else { + api()->glTexStorage3DFn(target, levels, compatibility_internal_format, + width, height, depth); + } + if (workarounds().reset_base_mipmap_level_before_texstorage && + texture->base_level() > 0) { + // Note base_level is already clamped due to texture->SetImmutable(true). + // This is necessary for certain NVidia Linux drivers; otherwise they + // may trigger segmentation fault. See https://crbug.com/877874. + api()->glTexParameteriFn(target, GL_TEXTURE_BASE_LEVEL, + texture->base_level()); + } } void GLES2DecoderImpl::DoTexStorage2DEXT(GLenum target, diff --git a/chromium/gpu/command_buffer/service/gles2_cmd_decoder_unittest_textures.cc b/chromium/gpu/command_buffer/service/gles2_cmd_decoder_unittest_textures.cc index 17d773b3569..63434c3f309 100644 --- a/chromium/gpu/command_buffer/service/gles2_cmd_decoder_unittest_textures.cc +++ b/chromium/gpu/command_buffer/service/gles2_cmd_decoder_unittest_textures.cc @@ -4809,6 +4809,170 @@ TEST_P(GLES2DecoderTest, TestDiscardableTextureBindGeneratesUnlocked) { EXPECT_EQ(GL_NO_ERROR, GetGLError()); } +TEST_P(GLES2DecoderTest, CopySubTextureCHROMIUMTwiceClearsUnclearedTexture) { + // Create uninitialized source texture. + EXPECT_CALL(*gl_, GenTextures(1, _)) + .WillOnce(SetArgPointee<1>(kNewServiceId)) + .RetiresOnSaturation(); + GenHelper(kNewClientId); + DoBindTexture(GL_TEXTURE_2D, kNewClientId, kNewServiceId); + DoTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0, + 0); + + // Create uninitialized dest texture. + DoBindTexture(GL_TEXTURE_2D, client_texture_id_, kServiceTextureId); + DoTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0, + 0); + + // This will write the top half of the destination. + { + // Source is undefined, so first call to CopySubTexture will clear the + // source. + SetupClearTextureExpectations(kNewServiceId, kServiceTextureId, + GL_TEXTURE_2D, GL_TEXTURE_2D, 0, GL_RGBA, + GL_UNSIGNED_BYTE, 0, 0, 2, 2, 0); + CopySubTextureCHROMIUM cmd; + cmd.Init(kNewClientId /* source_id */, 0 /* source_level */, + GL_TEXTURE_2D /* dest_target */, client_texture_id_ /* dest_id */, + 0 /* dest_level */, 0 /* xoffset */, 0 /* yoffset */, 0 /* x */, + 0 /* y */, 2 /* width */, 1 /* height */, + false /* unpack_flip_y */, false /* unpack_premultiply_alpha */, + false /* unpack_unmultiply_alpha */); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + } + + // This will write the bottom right pixel of the destination. + { + // This will clear the bottom part of destination as a rectangle is not + // sufficient to keep track of the initialized area. + SetupClearTextureExpectations(kServiceTextureId, kServiceTextureId, + GL_TEXTURE_2D, GL_TEXTURE_2D, 0, GL_RGBA, + GL_UNSIGNED_BYTE, 0, 1, 2, 1, 0); + CopySubTextureCHROMIUM cmd; + cmd.Init(kNewClientId /* source_id */, 0 /* source_level */, + GL_TEXTURE_2D /* dest_target */, client_texture_id_ /* dest_id */, + 0 /* dest_level */, 1 /* xoffset */, 1 /* yoffset */, 0 /* x */, + 0 /* y */, 1 /* width */, 1 /* height */, + false /* unpack_flip_y */, false /* unpack_premultiply_alpha */, + false /* unpack_unmultiply_alpha */); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + } + + TextureManager* manager = group().texture_manager(); + TextureRef* texture_ref = manager->GetTexture(client_texture_id_); + ASSERT_TRUE(texture_ref != nullptr); + Texture* texture = texture_ref->texture(); + EXPECT_TRUE(texture->SafeToRenderFrom()); +} + +TEST_P(GLES3DecoderTest, ImmutableTextureBaseLevelMaxLevelClamping) { + GLenum kTarget = GL_TEXTURE_3D; + GLint kBaseLevel = 1416354905; + GLint kMaxLevel = 800; + GLsizei kLevels = 4; + GLenum kInternalFormat = GL_R8; + GLsizei kWidth = 20; + GLsizei kHeight = 20; + GLsizei kDepth = 20; + GLint kClampedBaseLevel = kLevels - 1; + GLint kClampedMaxLevel = kLevels - 1; + + DoBindTexture(kTarget, client_texture_id_, kServiceTextureId); + TextureRef* texture_ref = + group().texture_manager()->GetTexture(client_texture_id_); + ASSERT_TRUE(texture_ref != nullptr); + Texture* texture = texture_ref->texture(); + + // Before TexStorage3D call, base/max levels are not clamped. + { + EXPECT_CALL(*gl_, TexParameteri(kTarget, GL_TEXTURE_BASE_LEVEL, kBaseLevel)) + .Times(1) + .RetiresOnSaturation(); + TexParameteri cmd; + cmd.Init(kTarget, GL_TEXTURE_BASE_LEVEL, kBaseLevel); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + } + { + EXPECT_CALL(*gl_, TexParameteri(kTarget, GL_TEXTURE_MAX_LEVEL, kMaxLevel)) + .Times(1) + .RetiresOnSaturation(); + TexParameteri cmd; + cmd.Init(kTarget, GL_TEXTURE_MAX_LEVEL, kMaxLevel); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + } + EXPECT_EQ(GL_NO_ERROR, GetGLError()); + EXPECT_EQ(kBaseLevel, texture->base_level()); + EXPECT_EQ(kMaxLevel, texture->max_level()); + + { + EXPECT_CALL(*gl_, TexStorage3D(kTarget, kLevels, kInternalFormat, kWidth, + kHeight, kDepth)) + .Times(1) + .RetiresOnSaturation(); + TexStorage3D cmd; + cmd.Init(kTarget, kLevels, kInternalFormat, kWidth, kHeight, kDepth); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); + } + EXPECT_EQ(kClampedBaseLevel, texture->base_level()); + EXPECT_EQ(kClampedMaxLevel, texture->max_level()); + + GLint kNewBaseLevel = 827344; + GLint kNewMaxLevel = 17619; + // After TexStorage3D call, base/max levels are clamped. + { + EXPECT_CALL( + *gl_, TexParameteri(kTarget, GL_TEXTURE_BASE_LEVEL, kClampedBaseLevel)) + .Times(1) + .RetiresOnSaturation(); + TexParameteri cmd; + cmd.Init(kTarget, GL_TEXTURE_BASE_LEVEL, kNewBaseLevel); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + } + { + EXPECT_CALL(*gl_, + TexParameteri(kTarget, GL_TEXTURE_MAX_LEVEL, kClampedMaxLevel)) + .Times(1) + .RetiresOnSaturation(); + TexParameteri cmd; + cmd.Init(kTarget, GL_TEXTURE_MAX_LEVEL, kNewMaxLevel); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + } + EXPECT_EQ(GL_NO_ERROR, GetGLError()); + EXPECT_EQ(kClampedBaseLevel, texture->base_level()); + EXPECT_EQ(kClampedMaxLevel, texture->max_level()); + + // GetTexParameteriv still returns unclamped values. + { + EXPECT_CALL(*gl_, GetError()) + .WillOnce(Return(GL_NO_ERROR)) + .WillOnce(Return(GL_NO_ERROR)) + .RetiresOnSaturation(); + typedef GetTexParameteriv::Result Result; + Result* result = static_cast(shared_memory_address_); + result->size = 0; + GetTexParameteriv cmd; + cmd.Init(kTarget, GL_TEXTURE_BASE_LEVEL, shared_memory_id_, + shared_memory_offset_); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(kNewBaseLevel, static_cast(result->GetData()[0])); + } + { + EXPECT_CALL(*gl_, GetError()) + .WillOnce(Return(GL_NO_ERROR)) + .WillOnce(Return(GL_NO_ERROR)) + .RetiresOnSaturation(); + typedef GetTexParameteriv::Result Result; + Result* result = static_cast(shared_memory_address_); + result->size = 0; + GetTexParameteriv cmd; + cmd.Init(kTarget, GL_TEXTURE_MAX_LEVEL, shared_memory_id_, + shared_memory_offset_); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(kNewMaxLevel, static_cast(result->GetData()[0])); + } +} + // TODO(gman): Complete this test. // TEST_P(GLES2DecoderTest, CompressedTexImage2DGLError) { // } diff --git a/chromium/gpu/command_buffer/service/texture_manager.cc b/chromium/gpu/command_buffer/service/texture_manager.cc index 683e216abf3..4e5971cda00 100644 --- a/chromium/gpu/command_buffer/service/texture_manager.cc +++ b/chromium/gpu/command_buffer/service/texture_manager.cc @@ -1078,17 +1078,17 @@ void Texture::IncAllFramebufferStateChangeCount() { } void Texture::UpdateBaseLevel(GLint base_level) { - if (base_level_ == base_level) + if (unclamped_base_level_ == base_level) return; - base_level_ = base_level; + unclamped_base_level_ = base_level; UpdateNumMipLevels(); } void Texture::UpdateMaxLevel(GLint max_level) { - if (max_level_ == max_level) + if (unclamped_max_level_ == max_level) return; - max_level_ = max_level; + unclamped_max_level_ = max_level; UpdateNumMipLevels(); } @@ -1097,22 +1097,24 @@ void Texture::UpdateNumMipLevels() { if (face_infos_.empty()) return; - GLint base_level = base_level_; - GLint max_level = max_level_; if (immutable_) { GLint levels = GetImmutableLevels(); DCHECK_LE(1, levels); - DCHECK_LE(0, base_level_); - base_level = std::min(base_level_, levels - 1); - max_level = std::max(base_level, max_level_); - max_level = std::min(max_level, levels - 1); + DCHECK_LE(0, unclamped_base_level_); + DCHECK_LE(0, unclamped_max_level_); + base_level_ = std::min(unclamped_base_level_, levels - 1); + max_level_ = std::max(base_level_, unclamped_max_level_); + max_level_ = std::min(max_level_, levels - 1); + } else { + base_level_ = unclamped_base_level_; + max_level_ = unclamped_max_level_; } - GLint max_num_mip_levels = std::max(0, max_level - base_level + 1); + GLint max_num_mip_levels = std::max(0, max_level_ - base_level_ + 1); for (size_t ii = 0; ii < face_infos_.size(); ++ii) { Texture::FaceInfo& face_info = face_infos_[ii]; - if (static_cast(base_level) >= face_info.level_infos.size()) + if (static_cast(base_level_) >= face_info.level_infos.size()) continue; - const Texture::LevelInfo& info = face_info.level_infos[base_level]; + const Texture::LevelInfo& info = face_info.level_infos[base_level_]; face_info.num_mip_levels = std::min( max_num_mip_levels, TextureManager::ComputeMipMapCount( target_, info.width, info.height, info.depth)); @@ -2223,6 +2225,14 @@ void TextureManager::SetParameteri( glTexParameteri(texture->target(), pname, texture->GetCompatibilitySwizzleForChannel(param)); break; + case GL_TEXTURE_BASE_LEVEL: + // base level might have been clamped. + glTexParameteri(texture->target(), pname, texture->base_level()); + break; + case GL_TEXTURE_MAX_LEVEL: + // max level might have been clamped. + glTexParameteri(texture->target(), pname, texture->max_level()); + break; default: glTexParameteri(texture->target(), pname, param); break; @@ -2246,7 +2256,21 @@ void TextureManager::SetParameterf( error_state, result, function_name, pname, param); } } else { - glTexParameterf(texture->target(), pname, param); + switch (pname) { + case GL_TEXTURE_BASE_LEVEL: + // base level might have been clamped. + glTexParameterf(texture->target(), pname, + static_cast(texture->base_level())); + break; + case GL_TEXTURE_MAX_LEVEL: + // max level might have been clamped. + glTexParameterf(texture->target(), pname, + static_cast(texture->max_level())); + break; + default: + glTexParameterf(texture->target(), pname, param); + break; + } } } diff --git a/chromium/gpu/command_buffer/service/texture_manager.h b/chromium/gpu/command_buffer/service/texture_manager.h index ec79a33ce40..2c3183947bc 100644 --- a/chromium/gpu/command_buffer/service/texture_manager.h +++ b/chromium/gpu/command_buffer/service/texture_manager.h @@ -155,6 +155,10 @@ class GPU_GLES2_EXPORT Texture final : public TextureBase { return max_level_; } + GLint unclamped_base_level() const { return unclamped_base_level_; } + + GLint unclamped_max_level() const { return unclamped_max_level_; } + GLenum swizzle_r() const { return swizzle_r_; } GLenum swizzle_g() const { return swizzle_g_; } @@ -578,6 +582,9 @@ class GPU_GLES2_EXPORT Texture final : public TextureBase { GLenum swizzle_b_; GLenum swizzle_a_; + GLint unclamped_base_level_ = 0; + GLint unclamped_max_level_ = 1000; + // The maximum level that has been set. GLint max_level_set_; diff --git a/chromium/gpu/config/gpu_driver_bug_list.json b/chromium/gpu/config/gpu_driver_bug_list.json index 0b1ed081cc6..5e9c63156e9 100644 --- a/chromium/gpu/config/gpu_driver_bug_list.json +++ b/chromium/gpu/config/gpu_driver_bug_list.json @@ -1682,21 +1682,6 @@ "disable_post_sub_buffers_for_onscreen_surfaces" ] }, - { - "id": 169, - "description": "Mac Drivers store texture level parameters on int16_t that overflow", - "cr_bugs": [610153], - "os": { - "type": "macosx", - "version": { - "op": "<", - "value": "10.12.2" - } - }, - "features": [ - "use_shadowed_tex_level_params" - ] - }, { "id": 170, "description": "Zero copy DXGI video hangs on shutdown on Win < 8.1", @@ -2832,6 +2817,230 @@ "features": [ "max_msaa_sample_count_4" ] + }, + { + "id": 260, + "cr_bugs": [760389], + "description": "eglClientWaitSyncKHR with nonzero timeout waits too long", + "comment": [ + "This bug is specific to Samsung S8/S8+ on Android N, but there ", + "isn't currently a way to restrict the filter to those devices. The ", + "functionality is currently only used for WebVR on Daydream ready ", + "devices, and the non-Samsung Daydream devices generally use ", + "Android O, so an overbroad match seems acceptable." + ], + "os": { + "type": "android", + "version": { + "op": "<", + "value": "8.0" + } + }, + "gl_renderer": "Adreno \\(TM\\) 540", + "features": [ + "dont_use_eglclientwaitsync_with_timeout" + ] + }, + { + "id": 261, + "cr_bugs": [817286], + "description": "Fallback to D3D9 if basic info collection fails on Win7", + "os": { + "type": "win", + "version": { + "op": "=", + "value": "6.1" + } + }, + "vendor_id": "0xffff", + "device_id": ["0xfffe"], + "features": [ + "disable_d3d11" + ] + }, + { + "id": 262, + "description": "Program fails in PowerVR*GX6250 drivers if gl_Position is not set", + "cr_bugs": [286468, 416670], + "os": { + "type": "android" + }, + "gl_vendor": "Imagination.*", + "gl_renderer": "PowerVR.*GX6250", + "features": [ + "init_gl_position_in_vertex_shader" + ] + }, + { + "id": 263, + "description": "Program fails in PowerVR SGX54x drivers if gl_Position is not set", + "cr_bugs": [286468, 416670], + "os": { + "type": "android" + }, + "gl_vendor": "Imagination.*", + "gl_renderer": "PowerVR SGX 54.*", + "features": [ + "init_gl_position_in_vertex_shader" + ] + }, + { + "id": 264, + "description": "Program fails in PowerVR G6200 drivers if gl_Position is not set", + "cr_bugs": [286468, 416670], + "os": { + "type": "android" + }, + "gl_vendor": "Imagination.*", + "gl_renderer": "PowerVR.*G6200.*", + "features": [ + "init_gl_position_in_vertex_shader" + ] + }, + { + "id": 265, + "cr_bugs": [811661], + "description": "Crash in glQueryCounter() and glBeginQuery() with VMware driver ", + "os": { + "type": "linux" + }, + "gl_vendor": "VMware.*", + "features": [ + "disable_timestamp_queries" + ], + "disabled_extensions": [ + "GL_ARB_timer_query", + "GL_EXT_disjoint_timer_query", + "GL_EXT_disjoint_timer_query_webgl2" + ] + }, + { + "id": 266, + "cr_bugs": [828721], + "description": "Crash in gl::GLApiBase::glGetQueryObjectui64vFn with NetEase devices ", + "os": { + "type": "android" + }, + "gl_vendor": "NetEase", + "gl_renderer": "MuMu GL.*", + "features": [ + "disable_timestamp_queries" + ], + "disabled_extensions": [ + "GL_EXT_disjoint_timer_query", + "GL_EXT_disjoint_timer_query_webgl2" + ] + }, + { + "id": 267, + "cr_bugs": [831781], + "description": "WebGL with multisampling produces errors on Mali", + "os": { + "type": "linux" + }, + "gl_vendor": "ARM", + "gl_renderer": "Mali-TDVX", + "disabled_extensions": [ + "GL_EXT_multisampled_render_to_texture" + ], + "features": [ + "disable_chromium_framebuffer_multisample" + ] + }, + { + "id": 268, + "cr_bugs": [797243], + "description": "Limit MSAA to 4x on Android devices", + "os": { + "type": "android" + }, + "features": [ + "max_msaa_sample_count_4" + ] + }, + { + "id": 269, + "cr_bugs": [841755], + "description": "glFlush error on Mac", + "os": { + "type": "macosx" + }, + "features": [ + "disable_2d_canvas_auto_flush" + ] + }, + { + "id": 270, + "cr_bugs": [859998], + "description": "AMD Linux driver crashes when copyTexImage2D is called with PIXEL_UNPACK_BUFFER set to an uninitialized buffer", + "os": { + "type": "linux" + }, + "vendor_id": "0x1002", + "features": [ + "clear_pixel_unpack_buffer_before_copyteximage" + ] + }, + { + "id": 271, + "cr_bugs": [860418], + "description": "Frequent crashes in glClear on Mali-T7xx on N with driver 12.1.01alp0", + "os": { + "type": "android", + "version": { + "op": "<", + "value": "8.0" + } + }, + "driver_version": { + "op": "=", + "value": "12.1.01alp0" + }, + "gl_renderer": ".*Mali-T7.*", + "features": [ + "gl_clear_broken" + ] + }, + { + "id": 272, + "cr_bugs": [858879], + "description": "A deleted query id for GL_TIMESTAMP cannot be reused for other query targets", + "os": { + "type": "android" + }, + "gl_vendor": "Qualcomm.*", + "features": [ + "disable_timestamp_queries" + ] + }, + { + "id":273, + "cr_bugs": [866613], + "description": "Frequent crashes on Adreno (TM) on L and below", + "os": { + "type": "android", + "version": { + "op": "<", + "value": "6.0" + } + }, + "gl_renderer": "Adreno.*", + "features": [ + "use_es2_for_oopr" + ] + }, + { + "id": 274, + "description": "glTexStorage* are buggy when base mipmap level is not 0", + "cr_bugs": [877874], + "os": { + "type": "linux" + }, + "vendor_id": "0x10de", + "gl_vendor": "NVIDIA.*", + "features": [ + "reset_base_mipmap_level_before_texstorage" + ] } ] } -- cgit v1.2.3