diff options
author | erikchen <erikchen@chromium.org> | 2016-03-16 10:45:44 -0700 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2016-03-16 17:47:16 +0000 |
commit | 38cbbce8977df77712707f9f64ae2e0b15e6f201 (patch) | |
tree | 5eee57e671cbe8a39a78617b97d8366e70369d30 /gpu | |
parent | 0d12fa25ae367e972d7eb5a00f02a643243c0243 (diff) | |
download | chromium_src-38cbbce8977df77712707f9f64ae2e0b15e6f201.zip chromium_src-38cbbce8977df77712707f9f64ae2e0b15e6f201.tar.gz chromium_src-38cbbce8977df77712707f9f64ae2e0b15e6f201.tar.bz2 |
Add a workaround for copyTexImage2D as it is sometimes broken on OSX.
copyTexImage2D fails when all of these conditions are met:
1. The internal format of the new texture is GL_ALPHA, GL_RED, or GL_RG. There
are probably a couple more. GL_RGB and GL_RGBA always work fine.
2. The GPU is from Nvidia.
3. The source texture is backed by an IOSurface.
BUG=581777
CQ_INCLUDE_TRYBOTS=tryserver.chromium.win:win_optional_gpu_tests_rel
Review URL: https://codereview.chromium.org/1736093002
Cr-Commit-Position: refs/heads/master@{#381488}
Diffstat (limited to 'gpu')
-rw-r--r-- | gpu/BUILD.gn | 1 | ||||
-rw-r--r-- | gpu/command_buffer/service/gles2_cmd_decoder.cc | 112 | ||||
-rw-r--r-- | gpu/command_buffer/tests/gl_copy_tex_image_2d_workaround_unittest.cc | 122 | ||||
-rw-r--r-- | gpu/command_buffer/tests/gl_manager.cc | 114 | ||||
-rw-r--r-- | gpu/command_buffer/tests/gl_manager.h | 8 | ||||
-rw-r--r-- | gpu/command_buffer/tests/gl_test_utils.cc | 84 | ||||
-rw-r--r-- | gpu/command_buffer/tests/gl_test_utils.h | 6 | ||||
-rw-r--r-- | gpu/config/gpu_driver_bug_list_json.cc | 14 | ||||
-rw-r--r-- | gpu/config/gpu_driver_bug_workaround_type.h | 2 | ||||
-rw-r--r-- | gpu/gpu.gyp | 1 |
10 files changed, 446 insertions, 18 deletions
diff --git a/gpu/BUILD.gn b/gpu/BUILD.gn index b10d4c7..cfa2e4a 100644 --- a/gpu/BUILD.gn +++ b/gpu/BUILD.gn @@ -150,6 +150,7 @@ test("gl_tests") { "command_buffer/tests/gl_chromium_path_rendering_unittest.cc", "command_buffer/tests/gl_clear_framebuffer_unittest.cc", "command_buffer/tests/gl_compressed_copy_texture_CHROMIUM_unittest.cc", + "command_buffer/tests/gl_copy_tex_image_2d_workaround_unittest.cc", "command_buffer/tests/gl_copy_texture_CHROMIUM_unittest.cc", "command_buffer/tests/gl_cube_map_texture_unittest.cc", "command_buffer/tests/gl_depth_texture_unittest.cc", diff --git a/gpu/command_buffer/service/gles2_cmd_decoder.cc b/gpu/command_buffer/service/gles2_cmd_decoder.cc index bd2a7f4..5e1ec96 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder.cc +++ b/gpu/command_buffer/service/gles2_cmd_decoder.cc @@ -1905,6 +1905,15 @@ class GLES2DecoderImpl : public GLES2Decoder, public ErrorStateClient { const SamplerState& GetSamplerStateForTextureUnit(GLenum target, GLuint unit); + // copyTexImage2D doesn't work on OSX under very specific conditions. + // Returns whether those conditions have been met. If this method returns + // true, |source_texture_service_id| and |source_texture_target| are also + // populated, since they are needed to implement the workaround. + bool NeedsCopyTextureImageWorkaround(GLenum internal_format, + int32_t channels_exist, + GLuint* source_texture_service_id, + GLenum* source_texture_target); + // Generate a member function prototype for each command in an automated and // typesafe way. #define GLES2_CMD_OP(name) \ @@ -11655,9 +11664,59 @@ void GLES2DecoderImpl::DoCopyTexImage2D( copyWidth, copyHeight); } } else { - glCopyTexImage2D(target, level, texture_manager()->AdjustTexInternalFormat( - internal_format), - copyX, copyY, copyWidth, copyHeight, border); + GLenum final_internal_format = + texture_manager()->AdjustTexInternalFormat(internal_format); + + // The service id and target of the texture attached to READ_FRAMEBUFFER. + GLuint source_texture_service_id = 0; + GLenum source_texture_target = 0; + bool use_workaround = NeedsCopyTextureImageWorkaround( + final_internal_format, channels_exist, &source_texture_service_id, + &source_texture_target); + if (use_workaround) { + GLenum dest_texture_target = target; + GLenum framebuffer_target = features().chromium_framebuffer_multisample + ? GL_READ_FRAMEBUFFER_EXT + : GL_FRAMEBUFFER; + + GLenum temp_internal_format = 0; + if (channels_exist == GLES2Util::kRGBA) { + temp_internal_format = GL_RGBA; + } else if (channels_exist == GLES2Util::kRGB) { + temp_internal_format = GL_RGB; + } else { + NOTREACHED(); + } + + GLuint temp_texture; + { + // Copy from the read framebuffer into |temp_texture|. + glGenTextures(1, &temp_texture); + ScopedTextureBinder binder(&state_, temp_texture, + source_texture_target); + glCopyTexImage2D(source_texture_target, 0, temp_internal_format, copyX, + copyY, copyWidth, copyHeight, border); + + // Attach the temp texture to the read framebuffer. + glFramebufferTexture2DEXT(framebuffer_target, GL_COLOR_ATTACHMENT0, + source_texture_target, temp_texture, 0); + } + + // Copy to the final texture. + DCHECK_EQ(static_cast<GLuint>(GL_TEXTURE_2D), dest_texture_target); + glCopyTexImage2D(dest_texture_target, level, final_internal_format, 0, 0, + copyWidth, copyHeight, 0); + + // Rebind source texture. + glFramebufferTexture2DEXT(framebuffer_target, GL_COLOR_ATTACHMENT0, + source_texture_target, + source_texture_service_id, 0); + + glDeleteTextures(1, &temp_texture); + } else { + glCopyTexImage2D(target, level, final_internal_format, copyX, copyY, + copyWidth, copyHeight, border); + } } GLenum error = LOCAL_PEEK_GL_ERROR("glCopyTexImage2D"); if (error == GL_NO_ERROR) { @@ -15989,6 +16048,53 @@ const SamplerState& GLES2DecoderImpl::GetSamplerStateForTextureUnit( return default_sampler_state_; } +bool GLES2DecoderImpl::NeedsCopyTextureImageWorkaround( + GLenum internal_format, + int32_t channels_exist, + GLuint* source_texture_service_id, + GLenum* source_texture_target) { + // On some OSX devices, copyTexImage2D will fail if all of these conditions + // are met: + // 1. The internal format of the new texture is not GL_RGB or GL_RGBA. + // 2. The image of the read FBO is backed by an IOSurface. + // See https://crbug.com/581777#c4 for more details. + if (!workarounds().use_intermediary_for_copy_texture_image) + return false; + + if (internal_format == GL_RGB || internal_format == GL_RGBA) + return false; + + GLenum framebuffer_target = features().chromium_framebuffer_multisample + ? GL_READ_FRAMEBUFFER_EXT + : GL_FRAMEBUFFER; + Framebuffer* framebuffer = + GetFramebufferInfoForTarget(framebuffer_target); + if (!framebuffer) + return false; + + const Framebuffer::Attachment* attachment = + framebuffer->GetReadBufferAttachment(); + if (!attachment) + return false; + + if (!attachment->IsTextureAttachment()) + return false; + + TextureRef* texture = + texture_manager()->GetTexture(attachment->object_name()); + if (!texture->texture()->HasImages()) + return false; + + // The workaround only works if the source texture consists of the channels + // kRGB or kRGBA. + if (channels_exist != GLES2Util::kRGBA && channels_exist != GLES2Util::kRGB) + return false; + + *source_texture_target = texture->texture()->target(); + *source_texture_service_id = texture->service_id(); + return true; +} + error::Error GLES2DecoderImpl::HandleBindFragmentInputLocationCHROMIUMBucket( uint32_t immediate_data_size, const void* cmd_data) { diff --git a/gpu/command_buffer/tests/gl_copy_tex_image_2d_workaround_unittest.cc b/gpu/command_buffer/tests/gl_copy_tex_image_2d_workaround_unittest.cc new file mode 100644 index 0000000..cb80ae3 --- /dev/null +++ b/gpu/command_buffer/tests/gl_copy_tex_image_2d_workaround_unittest.cc @@ -0,0 +1,122 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef GL_GLEXT_PROTOTYPES +#define GL_GLEXT_PROTOTYPES +#endif + +#include <GLES2/gl2.h> +#include <GLES2/gl2ext.h> +#include <GLES2/gl2extchromium.h> + +#include "base/command_line.h" +#include "base/strings/string_number_conversions.h" +#include "build/build_config.h" +#include "gpu/command_buffer/tests/gl_manager.h" +#include "gpu/command_buffer/tests/gl_test_utils.h" +#include "gpu/config/gpu_switches.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace gpu { + +#if defined(OS_MACOSX) +// A collection of tests that exercise the glCopyTexImage2D workaround. The +// parameter expresses different formats of the destination texture. +class GLCopyTexImage2DWorkaroundTest : public testing::TestWithParam<GLenum> { + public: + GLCopyTexImage2DWorkaroundTest() {} + + protected: + void SetUp() override { + base::CommandLine command_line(0, NULL); + command_line.AppendSwitchASCII( + switches::kGpuDriverBugWorkarounds, + base::IntToString(gpu::USE_INTERMEDIARY_FOR_COPY_TEXTURE_IMAGE)); + gl_.InitializeWithCommandLine(GLManager::Options(), &command_line); + gl_.set_use_iosurface_memory_buffers(true); + DCHECK(gl_.workarounds().use_intermediary_for_copy_texture_image); + } + + void TearDown() override { + GLTestHelper::CheckGLError("no errors", __LINE__); + gl_.Destroy(); + } + + GLManager gl_; +}; + +INSTANTIATE_TEST_CASE_P(GLCopyTexImage2DWorkaroundTestWithParam, + GLCopyTexImage2DWorkaroundTest, + ::testing::Values(GL_RGBA)); + +TEST_P(GLCopyTexImage2DWorkaroundTest, UseIntermediaryTexture) { + int width = 1; + int height = 1; + GLuint source_texture = 0; + GLenum source_target = GL_TEXTURE_RECTANGLE_ARB; + glGenTextures(1, &source_texture); + glBindTexture(source_target, source_texture); + glTexParameteri(source_target, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(source_target, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + GLuint image_id = glCreateGpuMemoryBufferImageCHROMIUM( + width, height, GL_BGRA_EXT, GL_READ_WRITE_CHROMIUM); + ASSERT_NE(0u, image_id); + glBindTexImage2DCHROMIUM(source_target, image_id); + + GLuint framebuffer = 0; + glGenFramebuffers(1, &framebuffer); + glBindFramebuffer(GL_FRAMEBUFFER, framebuffer); + glFramebufferTexture2D( + GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, source_target, source_texture, 0); + EXPECT_EQ(static_cast<GLenum>(GL_FRAMEBUFFER_COMPLETE), + glCheckFramebufferStatus(GL_FRAMEBUFFER)); + + + GLenum dest_formats[] = {GL_RGBA, GL_RGB, GL_ALPHA, GL_LUMINANCE}; + const uint8_t expectations[4][4] = { + {33, 44, 55, 66}, {33, 44, 55, 255}, {0, 0, 0, 66}, {33, 33, 33, 255}}; + for (size_t i = 0; i < sizeof(dest_formats) / sizeof(GLenum); ++i) { + glClearColor(33.0 / 255.0, 44.0 / 255.0, 55.0 / 255.0, 66.0 / 255.0); + glClear(GL_COLOR_BUFFER_BIT); + EXPECT_EQ(glGetError(), GLenum(GL_NO_ERROR)); + + GLuint dest_texture = 0; + GLenum dest_target = GL_TEXTURE_2D; + GLenum dest_format = dest_formats[i]; + glGenTextures(1, &dest_texture); + glBindTexture(dest_target, dest_texture); + glTexParameteri(dest_target, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(dest_target, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + + glCopyTexImage2D(dest_target, 0, dest_format, 0, 0, width, height, 0); + EXPECT_EQ(glGetError(), GLenum(GL_NO_ERROR)); + + // Check that bound textures haven't changed. + GLint boundTexture = -1; + glGetIntegerv(GL_TEXTURE_BINDING_RECTANGLE_ARB, &boundTexture); + EXPECT_EQ(glGetError(), GLenum(GL_NO_ERROR)); + EXPECT_EQ(static_cast<GLint>(source_texture), boundTexture); + + boundTexture = -1; + glGetIntegerv(GL_TEXTURE_BINDING_2D, &boundTexture); + EXPECT_EQ(glGetError(), GLenum(GL_NO_ERROR)); + EXPECT_EQ(static_cast<GLint>(dest_texture), boundTexture); + + glClearColor(1.0 / 255.0, 2.0 / 255.0, 3.0 / 255.0, 4.0 / 255.0); + glClear(GL_COLOR_BUFFER_BIT); + EXPECT_EQ(glGetError(), GLenum(GL_NO_ERROR)); + + glViewport(0, 0, width, height); + GLTestHelper::DrawTextureQuad(dest_target, gfx::Size(width, height)); + + // Verify. + const uint8_t* expected = expectations[i]; + EXPECT_TRUE( + GLTestHelper::CheckPixels(0, 0, 1, 1, 1 /* tolerance */, expected)); + } +} + +#endif // defined(OS_MACOSX) + +} // namespace gpu diff --git a/gpu/command_buffer/tests/gl_manager.cc b/gpu/command_buffer/tests/gl_manager.cc index 6e4cc59..95778c9 100644 --- a/gpu/command_buffer/tests/gl_manager.cc +++ b/gpu/command_buffer/tests/gl_manager.cc @@ -15,6 +15,7 @@ #include "base/at_exit.h" #include "base/bind.h" #include "base/memory/ref_counted_memory.h" +#include "build/build_config.h" #include "gpu/command_buffer/client/gles2_cmd_helper.h" #include "gpu/command_buffer/client/gles2_implementation.h" #include "gpu/command_buffer/client/gles2_lib.h" @@ -42,6 +43,11 @@ #include "ui/gl/gl_share_group.h" #include "ui/gl/gl_surface.h" +#if defined(OS_MACOSX) +#include "ui/gfx/mac/io_surface.h" +#include "ui/gl/gl_image_io_surface.h" +#endif + namespace gpu { namespace { @@ -101,6 +107,65 @@ class GpuMemoryBufferImpl : public gfx::GpuMemoryBuffer { gfx::BufferFormat format_; }; +#if defined(OS_MACOSX) +class IOSurfaceGpuMemoryBuffer : public gfx::GpuMemoryBuffer { + public: + IOSurfaceGpuMemoryBuffer(const gfx::Size& size, gfx::BufferFormat format) + : mapped_(false), size_(size), format_(format) { + iosurface_ = gfx::CreateIOSurface(size, gfx::BufferFormat::BGRA_8888); + } + + ~IOSurfaceGpuMemoryBuffer() override { + CFRelease(iosurface_); + } + + static IOSurfaceGpuMemoryBuffer* FromClientBuffer(ClientBuffer buffer) { + return reinterpret_cast<IOSurfaceGpuMemoryBuffer*>(buffer); + } + + // Overridden from gfx::GpuMemoryBuffer: + bool Map() override { + DCHECK(!mapped_); + mapped_ = true; + return true; + } + void* memory(size_t plane) override { + DCHECK(mapped_); + DCHECK_LT(plane, gfx::NumberOfPlanesForBufferFormat(format_)); + return IOSurfaceGetBaseAddressOfPlane(iosurface_, plane); + } + void Unmap() override { + DCHECK(mapped_); + mapped_ = false; + } + gfx::Size GetSize() const override { return size_; } + gfx::BufferFormat GetFormat() const override { return format_; } + int stride(size_t plane) const override { + DCHECK_LT(plane, gfx::NumberOfPlanesForBufferFormat(format_)); + return IOSurfaceGetWidthOfPlane(iosurface_, plane); + } + gfx::GpuMemoryBufferId GetId() const override { + NOTREACHED(); + return gfx::GpuMemoryBufferId(0); + } + gfx::GpuMemoryBufferHandle GetHandle() const override { + NOTREACHED(); + return gfx::GpuMemoryBufferHandle(); + } + ClientBuffer AsClientBuffer() override { + return reinterpret_cast<ClientBuffer>(this); + } + + IOSurfaceRef iosurface() { return iosurface_; } + + private: + bool mapped_; + IOSurfaceRef iosurface_; + const gfx::Size size_; + gfx::BufferFormat format_; +}; +#endif // defined(OS_MACOSX) + } // namespace int GLManager::use_count_; @@ -149,10 +214,15 @@ GLManager::~GLManager() { } } -// static scoped_ptr<gfx::GpuMemoryBuffer> GLManager::CreateGpuMemoryBuffer( const gfx::Size& size, gfx::BufferFormat format) { +#if defined(OS_MACOSX) + if (use_iosurface_memory_buffers_) { + return make_scoped_ptr<gfx::GpuMemoryBuffer>( + new IOSurfaceGpuMemoryBuffer(size, format)); + } +#endif // defined(OS_MACOSX) std::vector<uint8_t> data(gfx::BufferSizeForBufferFormat(size, format), 0); scoped_refptr<base::RefCountedBytes> bytes(new base::RefCountedBytes(data)); return make_scoped_ptr<gfx::GpuMemoryBuffer>( @@ -449,23 +519,41 @@ int32_t GLManager::CreateImage(ClientBuffer buffer, size_t width, size_t height, unsigned internalformat) { - GpuMemoryBufferImpl* gpu_memory_buffer = - GpuMemoryBufferImpl::FromClientBuffer(buffer); - - scoped_refptr<gl::GLImageRefCountedMemory> image( - new gl::GLImageRefCountedMemory(gfx::Size(width, height), - internalformat)); - if (!image->Initialize(gpu_memory_buffer->bytes(), - gpu_memory_buffer->GetFormat())) { - return -1; + gfx::Size size(width, height); + scoped_refptr<gl::GLImage> gl_image; + +#if defined(OS_MACOSX) + if (use_iosurface_memory_buffers_) { + IOSurfaceGpuMemoryBuffer* gpu_memory_buffer = + IOSurfaceGpuMemoryBuffer::FromClientBuffer(buffer); + scoped_refptr<gl::GLImageIOSurface> image( + new gl::GLImageIOSurface(size, internalformat)); + if (!image->Initialize(gpu_memory_buffer->iosurface(), + gfx::GenericSharedMemoryId(1), + gfx::BufferFormat::BGRA_8888)) { + return -1; + } + gl_image = image; + } +#endif // defined(OS_MACOSX) + if (!gl_image) { + GpuMemoryBufferImpl* gpu_memory_buffer = + GpuMemoryBufferImpl::FromClientBuffer(buffer); + + scoped_refptr<gl::GLImageRefCountedMemory> image( + new gl::GLImageRefCountedMemory(size, internalformat)); + if (!image->Initialize(gpu_memory_buffer->bytes(), + gpu_memory_buffer->GetFormat())) { + return -1; + } + gl_image = image; } static int32_t next_id = 1; int32_t new_id = next_id++; - gpu::gles2::ImageManager* image_manager = decoder_->GetImageManager(); DCHECK(image_manager); - image_manager->AddImage(image.get(), new_id); + image_manager->AddImage(gl_image.get(), new_id); return new_id; } @@ -474,7 +562,7 @@ int32_t GLManager::CreateGpuMemoryBufferImage(size_t width, unsigned internalformat, unsigned usage) { DCHECK_EQ(usage, static_cast<unsigned>(GL_READ_WRITE_CHROMIUM)); - scoped_ptr<gfx::GpuMemoryBuffer> buffer = GLManager::CreateGpuMemoryBuffer( + scoped_ptr<gfx::GpuMemoryBuffer> buffer = CreateGpuMemoryBuffer( gfx::Size(width, height), gfx::BufferFormat::RGBA_8888); return CreateImage(buffer->AsClientBuffer(), width, height, internalformat); } diff --git a/gpu/command_buffer/tests/gl_manager.h b/gpu/command_buffer/tests/gl_manager.h index 4ee1389..1301fe4 100644 --- a/gpu/command_buffer/tests/gl_manager.h +++ b/gpu/command_buffer/tests/gl_manager.h @@ -78,7 +78,7 @@ class GLManager : private GpuControl { GLManager(); ~GLManager() override; - static scoped_ptr<gfx::GpuMemoryBuffer> CreateGpuMemoryBuffer( + scoped_ptr<gfx::GpuMemoryBuffer> CreateGpuMemoryBuffer( const gfx::Size& size, gfx::BufferFormat format); @@ -93,6 +93,10 @@ class GLManager : private GpuControl { void SetSurface(gfx::GLSurface* surface); + void set_use_iosurface_memory_buffers(bool use_iosurface_memory_buffers) { + use_iosurface_memory_buffers_ = use_iosurface_memory_buffers; + } + void SetCommandsPaused(bool paused) { pause_commands_ = paused; } gles2::GLES2Decoder* decoder() const { @@ -175,6 +179,8 @@ class GLManager : private GpuControl { const CommandBufferId command_buffer_id_; uint64_t next_fence_sync_release_; + bool use_iosurface_memory_buffers_ = false; + // Used on Android to virtualize GL for all contexts. static int use_count_; static scoped_refptr<gfx::GLShareGroup>* base_share_group_; diff --git a/gpu/command_buffer/tests/gl_test_utils.cc b/gpu/command_buffer/tests/gl_test_utils.cc index 4878b14..d9a30ce 100644 --- a/gpu/command_buffer/tests/gl_test_utils.cc +++ b/gpu/command_buffer/tests/gl_test_utils.cc @@ -4,19 +4,71 @@ #include "gpu/command_buffer/tests/gl_test_utils.h" +#include <GLES2/gl2extchromium.h> #include <stdint.h> #include <stdio.h> #include <string> #include "base/memory/scoped_ptr.h" +#include "base/strings/stringize_macros.h" +#include "base/strings/stringprintf.h" #include "testing/gtest/include/gtest/gtest.h" +#include "ui/gfx/geometry/size.h" // GCC requires these declarations, but MSVC requires they not be present. #ifndef COMPILER_MSVC const uint8_t GLTestHelper::kCheckClearValue; #endif +// Compiles a fragment shader for sampling out of a texture of |size| bound to +// |target| and checks for compilation errors. +GLuint LoadFragmentShader(unsigned target, const gfx::Size& size) { + // clang-format off + const char kFragmentShader[] = STRINGIZE( + uniform SamplerType a_texture; + varying vec2 v_texCoord; + void main() { + gl_FragColor = TextureLookup(a_texture, v_texCoord * TextureScale); + } + ); + const char kShaderFloatPrecision[] = STRINGIZE( + precision mediump float; + ); + // clang-format on + + switch (target) { + case GL_TEXTURE_2D: + return GLTestHelper::LoadShader( + GL_FRAGMENT_SHADER, + base::StringPrintf("%s\n" + "#define SamplerType sampler2D\n" + "#define TextureLookup texture2D\n" + "#define TextureScale vec2(1.0, 1.0)\n" + "%s", + kShaderFloatPrecision, + kFragmentShader) + .c_str()); + case GL_TEXTURE_RECTANGLE_ARB: + return GLTestHelper::LoadShader( + GL_FRAGMENT_SHADER, + base::StringPrintf("%s\n" + "#extension GL_ARB_texture_rectangle : require\n" + "#define SamplerType sampler2DRect\n" + "#define TextureLookup texture2DRect\n" + "#define TextureScale vec2(%f, %f)\n" + "%s", + kShaderFloatPrecision, + static_cast<double>(size.width()), + static_cast<double>(size.height()), + kFragmentShader) + .c_str()); + default: + NOTREACHED(); + return 0; + } +} + bool GLTestHelper::HasExtension(const char* extension) { std::string extensions( reinterpret_cast<const char*>(glGetString(GL_EXTENSIONS))); @@ -259,3 +311,35 @@ bool GLTestHelper::SaveBackbufferAsBMP( fclose(fp); return true; } + +void GLTestHelper::DrawTextureQuad(GLenum target, const gfx::Size& size) { + // clang-format off + const char kVertexShader[] = STRINGIZE( + attribute vec2 a_position; + varying vec2 v_texCoord; + void main() { + gl_Position = vec4(a_position.x, a_position.y, 0.0, 1.0); + v_texCoord = (a_position + vec2(1.0, 1.0)) * 0.5; + } + ); + // clang-format on + + // Setup program. + GLuint vertex_shader = + GLTestHelper::LoadShader(GL_VERTEX_SHADER, kVertexShader); + GLuint fragment_shader = LoadFragmentShader(target, size); + GLuint program = GLTestHelper::SetupProgram(vertex_shader, fragment_shader); + EXPECT_NE(program, 0u); + glUseProgram(program); + + GLint sampler_location = glGetUniformLocation(program, "a_texture"); + ASSERT_NE(sampler_location, -1); + + GLuint vertex_buffer = GLTestHelper::SetupUnitQuad(sampler_location); + glDrawArrays(GL_TRIANGLES, 0, 6); + + glDeleteShader(vertex_shader); + glDeleteShader(fragment_shader); + glDeleteProgram(program); + glDeleteBuffers(1, &vertex_buffer); +} diff --git a/gpu/command_buffer/tests/gl_test_utils.h b/gpu/command_buffer/tests/gl_test_utils.h index 537442f..e2f88f5 100644 --- a/gpu/command_buffer/tests/gl_test_utils.h +++ b/gpu/command_buffer/tests/gl_test_utils.h @@ -10,6 +10,10 @@ #include <GLES2/gl2.h> #include <stdint.h> +namespace gfx { +class Size; +} // namespace gfx + class GLTestHelper { public: static const uint8_t kCheckClearValue = 123u; @@ -58,6 +62,8 @@ class GLTestHelper { // Uses ReadPixels to save an area of the current FBO/Backbuffer. static bool SaveBackbufferAsBMP(const char* filename, int width, int height); + + static void DrawTextureQuad(GLenum target, const gfx::Size& size); }; #endif // GPU_COMMAND_BUFFER_TESTS_GL_TEST_UTILS_H_ diff --git a/gpu/config/gpu_driver_bug_list_json.cc b/gpu/config/gpu_driver_bug_list_json.cc index 032afe3..7663fa8 100644 --- a/gpu/config/gpu_driver_bug_list_json.cc +++ b/gpu/config/gpu_driver_bug_list_json.cc @@ -19,7 +19,7 @@ const char kGpuDriverBugListJson[] = LONG_STRING_CONST( { "name": "gpu driver bug list", // Please update the version number whenever you change this file. - "version": "8.49", + "version": "8.50", "entries": [ { "id": 1, @@ -1819,6 +1819,18 @@ LONG_STRING_CONST( "features": [ "unpack_alignment_workaround_with_unpack_buffer" ] + }, + { + "id": 152, + "cr_bugs": [581777], + "description": "copyTexImage2D fails when reading from IOSurface on NVIDIA GPUs.", + "os": { + "type": "macosx" + }, + "vendor_id": "0x10de", + "features": [ + "use_intermediary_for_copy_texture_image" + ] } ] } diff --git a/gpu/config/gpu_driver_bug_workaround_type.h b/gpu/config/gpu_driver_bug_workaround_type.h index a0af6ad..b92ae69 100644 --- a/gpu/config/gpu_driver_bug_workaround_type.h +++ b/gpu/config/gpu_driver_bug_workaround_type.h @@ -146,6 +146,8 @@ use_client_side_arrays_for_stream_buffers) \ GPU_OP(USE_CURRENT_PROGRAM_AFTER_SUCCESSFUL_LINK, \ use_current_program_after_successful_link) \ + GPU_OP(USE_INTERMEDIARY_FOR_COPY_TEXTURE_IMAGE, \ + use_intermediary_for_copy_texture_image) \ GPU_OP(USE_NON_ZERO_SIZE_FOR_CLIENT_SIDE_STREAM_BUFFERS, \ use_non_zero_size_for_client_side_stream_buffers) \ GPU_OP(USE_VIRTUALIZED_GL_CONTEXTS, \ diff --git a/gpu/gpu.gyp b/gpu/gpu.gyp index 9d3cc56..1bd8d2f 100644 --- a/gpu/gpu.gyp +++ b/gpu/gpu.gyp @@ -353,6 +353,7 @@ 'command_buffer/tests/gl_clear_framebuffer_unittest.cc', 'command_buffer/tests/gl_compressed_copy_texture_CHROMIUM_unittest.cc', 'command_buffer/tests/gl_copy_texture_CHROMIUM_unittest.cc', + 'command_buffer/tests/gl_copy_tex_image_2d_workaround_unittest.cc', 'command_buffer/tests/gl_cube_map_texture_unittest.cc', 'command_buffer/tests/gl_depth_texture_unittest.cc', 'command_buffer/tests/gl_dynamic_config_unittest.cc', |