summaryrefslogtreecommitdiffstats
path: root/gpu
diff options
context:
space:
mode:
authorerikchen <erikchen@chromium.org>2016-03-16 10:45:44 -0700
committerCommit bot <commit-bot@chromium.org>2016-03-16 17:47:16 +0000
commit38cbbce8977df77712707f9f64ae2e0b15e6f201 (patch)
tree5eee57e671cbe8a39a78617b97d8366e70369d30 /gpu
parent0d12fa25ae367e972d7eb5a00f02a643243c0243 (diff)
downloadchromium_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.gn1
-rw-r--r--gpu/command_buffer/service/gles2_cmd_decoder.cc112
-rw-r--r--gpu/command_buffer/tests/gl_copy_tex_image_2d_workaround_unittest.cc122
-rw-r--r--gpu/command_buffer/tests/gl_manager.cc114
-rw-r--r--gpu/command_buffer/tests/gl_manager.h8
-rw-r--r--gpu/command_buffer/tests/gl_test_utils.cc84
-rw-r--r--gpu/command_buffer/tests/gl_test_utils.h6
-rw-r--r--gpu/config/gpu_driver_bug_list_json.cc14
-rw-r--r--gpu/config/gpu_driver_bug_workaround_type.h2
-rw-r--r--gpu/gpu.gyp1
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',