summaryrefslogtreecommitdiffstats
path: root/gpu/command_buffer/tests
diff options
context:
space:
mode:
Diffstat (limited to 'gpu/command_buffer/tests')
-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
5 files changed, 320 insertions, 14 deletions
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_