Chromium Code Reviews| Index: ui/gl/gl_image_unittest.cc |
| diff --git a/ui/gl/gl_image_unittest.cc b/ui/gl/gl_image_unittest.cc |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..8cc952ac1aff41c0bbf82e0c3926d06d2f1620d5 |
| --- /dev/null |
| +++ b/ui/gl/gl_image_unittest.cc |
| @@ -0,0 +1,532 @@ |
| +// Copyright 2015 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. |
| + |
| +#include "ui/gl/gl_image.h" |
| + |
| +#include <vector> |
| + |
| +#include "base/memory/ref_counted_memory.h" |
| +#include "base/memory/shared_memory.h" |
| +#include "base/strings/stringprintf.h" |
| +#include "testing/gtest/include/gtest/gtest.h" |
| +#include "third_party/skia/include/core/SkCanvas.h" |
| +#include "third_party/skia/include/core/SkColor.h" |
| +#include "third_party/skia/include/core/SkSurface.h" |
| +#include "ui/gfx/buffer_format_util.h" |
| +#include "ui/gfx/buffer_types.h" |
| +#include "ui/gl/gl_bindings.h" |
| +#include "ui/gl/gl_context.h" |
| +#include "ui/gl/gl_image_ref_counted_memory.h" |
| +#include "ui/gl/gl_image_shared_memory.h" |
| +#include "ui/gl/gl_implementation.h" |
| +#include "ui/gl/gl_surface.h" |
| +#include "ui/gl/gl_version_info.h" |
| +#include "ui/gl/scoped_make_current.h" |
| +#include "ui/gl/test/gl_surface_test_support.h" |
| + |
| +#if defined(OS_MACOSX) |
| +#include <CoreFoundation/CoreFoundation.h> |
| +#include "ui/gl/gl_image_io_surface.h" |
| +#endif |
| + |
| +#if defined(OS_ANDROID) |
| +#include <android/native_window_jni.h> |
| +#include "base/android/jni_android.h" |
| +#include "ui/gl/android/scoped_java_surface.h" |
| +#include "ui/gl/android/surface_texture.h" |
| +#include "ui/gl/gl_image_surface_texture.h" |
| +#endif |
| + |
| +namespace gfx { |
| +namespace { |
| + |
| +enum class GLImageType { |
|
Daniele Castagna
2015/09/22 15:55:32
Have you considered having one test fixture for ea
reveman
2015/09/24 00:31:42
Latest patch implements this using a test template
|
| + SHARED_MEMORY, |
| + REF_COUNTED_MEMORY, |
| + IO_SURFACE, |
| + SURFACE_TEXTURE, |
| + OZONE_NATIVE_PIXMAP |
| +}; |
| + |
| +#define SHADER(Src) #Src |
| + |
| +// clang-format off |
| + |
| +const char kVertexShader[] = SHADER( |
| + uniform vec2 texScale; |
| + attribute vec2 a_position; |
| + attribute vec2 a_texCoord; |
| + varying vec2 v_texCoord; |
| + void main() { |
| + gl_Position = vec4(a_position.x, a_position.y, 0.0, 1.0); |
| + v_texCoord = vec2(a_texCoord.x * texScale.x, a_texCoord.y * texScale.y); |
| + } |
| +); |
| + |
| +const char kFragmentShader[] = SHADER( |
| + uniform SamplerType a_texture; |
| + varying vec2 v_texCoord; |
| + void main() { |
| + gl_FragColor = TextureLookup(a_texture, v_texCoord); |
| + } |
| +); |
| + |
| +// clang-format on |
| + |
| +const char kTexture2DFragmentShaderPrefix[] = |
| + "#define SamplerType sampler2D\n" |
| + "#define TextureLookup texture2D\n"; |
| + |
| +const char kTextureRectangleFragmentShaderPrefix[] = |
| + "#extension GL_ARB_texture_rectangle : require\n" |
| + "#define SamplerType sampler2DRect\n" |
| + "#define TextureLookup texture2DRect\n"; |
| + |
| +const char kTextureExternalFragmentShaderPrefix[] = |
| + "#extension GL_OES_EGL_image_external : require\n" |
| + "#define SamplerType samplerExternalOES\n" |
| + "#define TextureLookup texture2D\n"; |
| + |
| +GLuint LoadShader(GLenum type, const char* const src) { |
| + GLuint shader = glCreateShader(type); |
| + glShaderSource(shader, 1, &src, nullptr); |
| + glCompileShader(shader); |
| + GLint compiled = 0; |
| + glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled); |
| + DCHECK(compiled); |
| + return shader; |
| +} |
| + |
| +class GLImageTest : public testing::TestWithParam<GLImageType> { |
| + public: |
| + // Overridden from testing::Test: |
| + void SetUp() override { |
| +#if defined(USE_OZONE) |
| + // On Ozone, the backend initializes the event system using a UI thread. |
| + base::MessageLoopForUI main_loop; |
| +#endif |
| + |
| + std::vector<GLImplementation> allowed_impls; |
| + GetAllowedGLImplementations(&allowed_impls); |
| + DCHECK(!allowed_impls.empty()); |
| + |
| + GLImplementation impl = allowed_impls[0]; |
| + GLSurfaceTestSupport::InitializeOneOffImplementation(impl); |
| + |
| + surface_ = GLSurface::CreateOffscreenGLSurface(Size()); |
| + context_ = GLContext::CreateGLContext(nullptr, surface_.get(), |
| + PreferIntegratedGpu); |
| + |
| + ui::ScopedMakeCurrent scoped_make_current(context_.get(), surface_.get()); |
| + |
| + bool has_texture_format_bgra8888 = |
| + context_->HasExtension("GL_APPLE_texture_format_BGRA8888") || |
| + context_->HasExtension("GL_EXT_texture_format_BGRA8888") || |
| + !context_->GetVersionInfo()->is_es; |
| + if (!SK_B32_SHIFT && has_texture_format_bgra8888) { |
| + preferred_format_ = BufferFormat::BGRA_8888; |
| + preferred_internal_format_ = GL_BGRA_EXT; |
| + } |
| + |
| + glGenTextures(1, &color_texture_); |
| + glBindTexture(GL_TEXTURE_2D, color_texture_); |
| + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); |
| + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); |
| + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); |
| + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); |
| + // Create a 1024x1024 color buffer. |
| + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1024, 1024, 0, GL_RGBA, |
| + GL_UNSIGNED_BYTE, nullptr); |
| + glBindTexture(GL_TEXTURE_2D, 0); |
| + glGenFramebuffersEXT(1, &framebuffer_); |
| + glBindFramebufferEXT(GL_FRAMEBUFFER, framebuffer_); |
| + glFramebufferTexture2DEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, |
| + GL_TEXTURE_2D, color_texture_, 0); |
| + DCHECK_EQ(static_cast<GLenum>(GL_FRAMEBUFFER_COMPLETE), |
| + glCheckFramebufferStatusEXT(GL_FRAMEBUFFER)); |
| + |
| + vertex_shader_ = LoadShader(GL_VERTEX_SHADER, kVertexShader); |
| + bool is_gles = context_->GetVersionInfo()->is_es; |
| + fragment_shader_ = |
| + LoadShader(GL_FRAGMENT_SHADER, |
| + base::StringPrintf("%s%s%s", TextureFragmentShaderPrefix(), |
| + is_gles ? "precision mediump float;" : "", |
| + kFragmentShader) |
| + .c_str()); |
| + program_ = glCreateProgram(); |
| + glAttachShader(program_, vertex_shader_); |
| + glAttachShader(program_, fragment_shader_); |
| + glBindAttribLocation(program_, 0, "a_position"); |
| + glBindAttribLocation(program_, 1, "a_texCoord"); |
| + glLinkProgram(program_); |
| + GLint linked = -1; |
| + glGetProgramiv(program_, GL_LINK_STATUS, &linked); |
| + DCHECK_NE(linked, 0); |
| + glUseProgram(program_); |
| + sampler_location_ = glGetUniformLocation(program_, "a_texture"); |
| + DCHECK_NE(sampler_location_, -1); |
| + glUniform1i(sampler_location_, 0); |
| + texture_scale_location_ = glGetUniformLocation(program_, "texScale"); |
| + DCHECK_NE(texture_scale_location_, -1); |
| + glUniform2f(texture_scale_location_, 1.f, 1.0f); |
| + |
| + glGenBuffersARB(1, &vertex_buffer_); |
| + glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer_); |
| + // clang-format off |
| + static GLfloat vertices[] = { |
| + -1.f, -1.f, 0.f, 0.f, |
| + 1.f, -1.f, 1.f, 0.f, |
| + -1.f, 1.f, 0.f, 1.f, |
| + 1.f, 1.f, 1.f, 1.f |
| + }; |
| + // clang-format on |
| + glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); |
| + glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 4, 0); |
| + glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 4, |
| + reinterpret_cast<void*>(sizeof(GLfloat) * 2)); |
| + glEnableVertexAttribArray(0); |
| + glEnableVertexAttribArray(1); |
| + } |
| + void TearDown() override { |
| + { |
| + ui::ScopedMakeCurrent scoped_make_current(context_.get(), surface_.get()); |
| + |
| + glDeleteProgram(program_); |
| + glDeleteShader(vertex_shader_); |
| + glDeleteShader(fragment_shader_); |
| + glBindBuffer(GL_ARRAY_BUFFER, 0); |
| + glDeleteBuffersARB(1, &vertex_buffer_); |
| + glBindFramebufferEXT(GL_FRAMEBUFFER, 0); |
| + glDeleteFramebuffersEXT(1, &framebuffer_); |
| + glDeleteTextures(1, &color_texture_); |
| + } |
| + |
| + context_ = nullptr; |
| + surface_ = nullptr; |
| + |
| + ClearGLBindings(); |
| + } |
| + |
| + protected: |
| + scoped_refptr<GLImage> CreateSolidColorImage(const Size& size, |
| + unsigned internalformat, |
| + BufferFormat format, |
| + SkColor color) { |
| + switch (GetParam()) { |
| + case GLImageType::SHARED_MEMORY: { |
| + DCHECK_EQ(NumberOfPlanesForBufferFormat(format), 1u); |
| + base::SharedMemory shared_memory; |
| + if (!shared_memory.CreateAndMapAnonymous( |
| + BufferSizeForBufferFormat(size, format))) { |
| + return nullptr; |
| + } |
| + ClearDataToSolidColor( |
| + size, format, |
| + static_cast<int>(RowSizeForBufferFormat(size.width(), format, 0)), |
| + reinterpret_cast<uint8_t*>(shared_memory.memory()), color); |
| + |
| + scoped_refptr<GLImageSharedMemory> image( |
| + new GLImageSharedMemory(size, internalformat)); |
| + if (!image->Initialize( |
| + base::SharedMemory::DuplicateHandle(shared_memory.handle()), |
| + NextGenericSharedMemoryId(), format)) { |
| + return nullptr; |
| + } |
| + return image; |
| + } |
| + case GLImageType::REF_COUNTED_MEMORY: { |
| + DCHECK_EQ(NumberOfPlanesForBufferFormat(format), 1u); |
| + std::vector<uint8_t> data(BufferSizeForBufferFormat(size, format), 0); |
| + scoped_refptr<base::RefCountedBytes> bytes( |
| + new base::RefCountedBytes(data)); |
| + ClearDataToSolidColor( |
| + size, format, |
| + static_cast<int>(RowSizeForBufferFormat(size.width(), format, 0)), |
| + &bytes->data().front(), color); |
| + |
| + scoped_refptr<GLImageRefCountedMemory> image( |
| + new GLImageRefCountedMemory(size, internalformat)); |
| + if (!image->Initialize(bytes.get(), format)) |
| + return nullptr; |
| + return image; |
| + } |
| + case GLImageType::IO_SURFACE: { |
| +#if defined(OS_MACOSX) |
| + DCHECK(format == BufferFormat::BGRA_8888); |
| + base::ScopedCFTypeRef<CFMutableDictionaryRef> properties( |
| + CFDictionaryCreateMutable(kCFAllocatorDefault, 0, |
| + &kCFTypeDictionaryKeyCallBacks, |
| + &kCFTypeDictionaryValueCallBacks)); |
| + int32_t width = size.width(); |
| + base::ScopedCFTypeRef<CFNumberRef> cf_width( |
| + CFNumberCreate(nullptr, kCFNumberSInt32Type, &width)); |
| + CFDictionaryAddValue(properties, kIOSurfaceWidth, cf_width.get()); |
| + int32_t height = size.height(); |
| + base::ScopedCFTypeRef<CFNumberRef> cf_height( |
| + CFNumberCreate(nullptr, kCFNumberSInt32Type, &height)); |
| + CFDictionaryAddValue(properties, kIOSurfaceHeight, cf_height.get()); |
| + int32_t pixel_format = 'BGRA'; |
| + base::ScopedCFTypeRef<CFNumberRef> cf_pixel_format( |
| + CFNumberCreate(nullptr, kCFNumberSInt32Type, &pixel_format)); |
| + CFDictionaryAddValue(properties, kIOSurfacePixelFormat, |
| + cf_pixel_format.get()); |
| + int32_t bytes_per_element = 4; |
| + base::ScopedCFTypeRef<CFNumberRef> cf_bytes_per_element( |
| + CFNumberCreate(nullptr, kCFNumberSInt32Type, &bytes_per_element)); |
| + CFDictionaryAddValue(properties, kIOSurfaceBytesPerElement, |
| + cf_bytes_per_element.get()); |
| + base::ScopedCFTypeRef<IOSurfaceRef> io_surface( |
| + IOSurfaceCreate(properties)); |
| + DCHECK(io_surface); |
| + IOReturn status = IOSurfaceLock(io_surface, 0, nullptr); |
| + DCHECK_EQ(status, kIOReturnSuccess); |
| + ClearDataToSolidColor( |
| + size, format, static_cast<int>(IOSurfaceGetBytesPerRow(io_surface)), |
| + reinterpret_cast<uint8_t*>(IOSurfaceGetBaseAddress(io_surface)), |
| + color); |
| + IOSurfaceUnlock(io_surface, 0, nullptr); |
| + |
| + scoped_refptr<GLImageIOSurface> image( |
| + new GLImageIOSurface(size, internalformat)); |
| + if (!image->Initialize(io_surface, NextGenericSharedMemoryId(), |
| + format)) { |
| + return nullptr; |
| + } |
| + return image; |
| +#else |
| + NOTREACHED(); |
| + return nullptr; |
| +#endif |
| + } |
| + case GLImageType::SURFACE_TEXTURE: { |
| +#if defined(OS_ANDROID) |
| + const int kDummyTextureId = 0; |
| + scoped_refptr<SurfaceTexture> surface_texture = |
| + SurfaceTexture::Create(kDummyTextureId); |
| + DCHECK(surface_texture); |
| + DCHECK(format == BufferFormat::RGBA_8888); |
| + ScopedJavaSurface surface(surface_texture.get()); |
| + JNIEnv* env = base::android::AttachCurrentThread(); |
| + ANativeWindow* native_window = |
| + ANativeWindow_fromSurface(env, surface.j_surface().obj()); |
| + ANativeWindow_setBuffersGeometry(native_window, size.width(), |
| + size.height(), |
| + WINDOW_FORMAT_RGBA_8888); |
| + ANativeWindow_Buffer buffer; |
| + int rv = ANativeWindow_lock(native_window, &buffer, nullptr); |
| + DCHECK_EQ(rv, 0); |
| + ClearDataToSolidColor(size, format, buffer.stride, |
| + reinterpret_cast<uint8_t*>(buffer.bits), color); |
| + ANativeWindow_unlockAndPost(native_window); |
| + |
| + scoped_refptr<GLImageSurfaceTexture> image( |
| + new GLImageSurfaceTexture(size)); |
| + if (!image->Initialize(surface_texture.get())) |
| + return nullptr; |
| + return image; |
| +#else |
| + NOTREACHED(); |
| + return nullptr; |
| +#endif |
| + } |
| + case GLImageType::OZONE_NATIVE_PIXMAP: |
| + NOTREACHED(); |
| + return nullptr; |
| + } |
| + NOTREACHED(); |
| + return nullptr; |
| + } |
| + |
| + GLenum GetTextureTarget() { |
| + switch (GetParam()) { |
| + case GLImageType::SHARED_MEMORY: |
| + case GLImageType::REF_COUNTED_MEMORY: |
| + return GL_TEXTURE_2D; |
| + case GLImageType::IO_SURFACE: |
| + return GL_TEXTURE_RECTANGLE_ARB; |
| + case GLImageType::SURFACE_TEXTURE: |
| + case GLImageType::OZONE_NATIVE_PIXMAP: |
| + return GL_TEXTURE_EXTERNAL_OES; |
| + } |
| + NOTREACHED(); |
| + return GL_TEXTURE_2D; |
| + } |
| + |
| + const char* TextureFragmentShaderPrefix() { |
| + switch (GetParam()) { |
| + case GLImageType::SHARED_MEMORY: |
| + case GLImageType::REF_COUNTED_MEMORY: |
| + return kTexture2DFragmentShaderPrefix; |
| + case GLImageType::IO_SURFACE: |
| + return kTextureRectangleFragmentShaderPrefix; |
| + case GLImageType::SURFACE_TEXTURE: |
| + case GLImageType::OZONE_NATIVE_PIXMAP: |
| + return kTextureExternalFragmentShaderPrefix; |
| + } |
| + NOTREACHED(); |
| + return nullptr; |
| + } |
| + |
| + Vector2dF GetTextureScale(Size size) { |
| + switch (GetParam()) { |
| + case GLImageType::SHARED_MEMORY: |
| + case GLImageType::REF_COUNTED_MEMORY: |
| + case GLImageType::SURFACE_TEXTURE: |
| + case GLImageType::OZONE_NATIVE_PIXMAP: |
| + return Vector2dF(1.f, 1.f); |
| + case GLImageType::IO_SURFACE: |
| + return Vector2dF(size.width(), size.height()); |
| + } |
| + NOTREACHED(); |
| + return Vector2dF(); |
| + } |
| + |
| + void DrawTexture(Size size) { |
| + Vector2dF texture_scale = GetTextureScale(size); |
| + glUniform2f(texture_scale_location_, texture_scale.x(), texture_scale.y()); |
| + glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); |
| + } |
| + |
| + GenericSharedMemoryId NextGenericSharedMemoryId() { |
| + return GenericSharedMemoryId(next_generic_shared_memory_id_++); |
| + } |
| + |
| + bool CheckPixels(int x, int y, int width, int height, SkColor color) { |
| + int size = width * height * 4; |
| + scoped_ptr<uint8_t[]> pixels(new uint8_t[size]); |
| + const uint8_t kCheckClearValue = 123u; |
| + memset(pixels.get(), kCheckClearValue, size); |
| + glReadPixels(x, y, width, height, GL_RGBA, GL_UNSIGNED_BYTE, pixels.get()); |
| + uint8_t expected_color[] = { |
| + SkColorGetR(color), SkColorGetG(color), SkColorGetB(color), |
| + SkColorGetA(color), |
| + }; |
| + int bad_count = 0; |
| + for (int yy = 0; yy < height; ++yy) { |
| + for (int xx = 0; xx < width; ++xx) { |
| + int offset = yy * width * 4 + xx * 4; |
| + for (int jj = 0; jj < 4; ++jj) { |
| + uint8_t actual = pixels[offset + jj]; |
| + uint8_t expected = expected_color[jj]; |
| + EXPECT_EQ(expected, actual) << " at " << (xx + x) << ", " << (yy + y) |
| + << " channel " << jj; |
| + bad_count += actual != expected; |
| + // Exit early just so we don't spam the log but we print enough to |
| + // hopefully make it easy to diagnose the issue. |
| + if (bad_count > 16) |
| + return false; |
| + } |
| + } |
| + } |
| + |
| + return !bad_count; |
| + } |
| + |
| + void ClearDataToSolidColor(const Size& size, |
| + BufferFormat format, |
| + int stride, |
| + uint8_t* data, |
| + SkColor color) { |
| + switch (format) { |
| + case BufferFormat::RGBA_8888: |
| + for (int y = 0; y < size.height(); ++y) { |
| + for (int x = 0; x < size.width(); ++x) { |
| + data[y * stride + x * 4 + 0] = SkColorGetR(color); |
| + data[y * stride + x * 4 + 1] = SkColorGetG(color); |
| + data[y * stride + x * 4 + 2] = SkColorGetB(color); |
| + data[y * stride + x * 4 + 3] = SkColorGetA(color); |
| + } |
| + } |
| + return; |
| + case BufferFormat::BGRA_8888: |
| + for (int y = 0; y < size.height(); ++y) { |
| + for (int x = 0; x < size.width(); ++x) { |
| + data[y * stride + x * 4 + 0] = SkColorGetB(color); |
| + data[y * stride + x * 4 + 1] = SkColorGetG(color); |
| + data[y * stride + x * 4 + 2] = SkColorGetR(color); |
| + data[y * stride + x * 4 + 3] = SkColorGetA(color); |
| + } |
| + } |
| + return; |
| + case BufferFormat::ATC: |
| + case BufferFormat::ATCIA: |
| + case BufferFormat::DXT1: |
| + case BufferFormat::DXT5: |
| + case BufferFormat::ETC1: |
| + case BufferFormat::R_8: |
| + case BufferFormat::RGBA_4444: |
| + case BufferFormat::BGRX_8888: |
| + case BufferFormat::UYVY_422: |
| + case BufferFormat::YUV_420_BIPLANAR: |
| + case BufferFormat::YUV_420: |
| + NOTREACHED(); |
| + return; |
| + } |
| + NOTREACHED(); |
| + } |
| + |
| + scoped_refptr<GLContext> context_; |
| + scoped_refptr<GLSurface> surface_; |
| + BufferFormat preferred_format_ = BufferFormat::RGBA_8888; |
| + GLenum preferred_internal_format_ = GL_RGBA; |
| + GLuint color_texture_ = 0; |
| + GLuint framebuffer_ = 0; |
| + GLuint vertex_shader_ = 0; |
| + GLuint fragment_shader_ = 0; |
| + GLuint program_ = 0; |
| + GLuint vertex_buffer_ = 0; |
| + GLint sampler_location_ = -1; |
| + GLint texture_scale_location_ = -1; |
| + int next_generic_shared_memory_id_ = 1; |
| +}; |
| + |
| +TEST_P(GLImageTest, CopyTexSubImage) { |
|
Daniele Castagna
2015/09/22 15:55:32
Can you spend few words here describing CopyTexSub
reveman
2015/09/24 00:31:42
Added some more comments to latest patch but I'd r
|
| + ui::ScopedMakeCurrent scoped_make_current(context_.get(), surface_.get()); |
| + |
| + const Size image_size(256, 256); |
| + scoped_refptr<GLImage> image = CreateSolidColorImage( |
| + image_size, preferred_internal_format_, preferred_format_, SK_ColorGREEN); |
| + if (!image) |
|
Daniele Castagna
2015/09/22 15:55:32
When would this happen?
reveman
2015/09/24 00:31:42
Made it a requirement for this to be supported by
|
| + return; |
| + |
| + GLenum target = GetTextureTarget(); |
| + GLuint texture = 0; |
| + glGenTextures(1, &texture); |
| + glBindTexture(target, texture); |
| + glTexParameteri(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); |
| + glTexParameteri(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); |
| + glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST); |
| + glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST); |
| + glTexImage2D(target, 0, preferred_internal_format_, image_size.width(), |
| + image_size.height(), 0, preferred_internal_format_, |
| + GL_UNSIGNED_BYTE, nullptr); |
| + |
| + // Copy image to |texture|. If supported, check that |texture| contains |
| + // the correct result. |
| + if (image->CopyTexSubImage(target, Point(), Rect(image_size))) { |
|
Daniele Castagna
2015/09/22 15:55:32
Is it OK not to support CopyTexSubImage?
If that i
reveman
2015/09/24 00:31:42
Yes.
|
| + glViewport(0, 0, image_size.width(), image_size.height()); |
| + DrawTexture(image_size); |
| + CheckPixels(0, 0, image_size.width(), image_size.height(), SK_ColorGREEN); |
| + } |
| + |
| + glDeleteTextures(1, &texture); |
| + image->Destroy(true); |
| +} |
| + |
| +static const GLImageType kGLImageTypes[] = { |
| + GLImageType::SHARED_MEMORY, GLImageType::REF_COUNTED_MEMORY, |
| +#if defined(OS_MACOSX) |
| + GLImageType::IO_SURFACE, |
| +#endif |
| +#if defined(OS_ANDROID) |
| + GLImageType::SURFACE_TEXTURE, |
| +#endif |
| +}; |
| + |
| +INSTANTIATE_TEST_CASE_P(GLImageTests, |
| + GLImageTest, |
| + ::testing::ValuesIn(kGLImageTypes)); |
| + |
| +} // namespace |
| +} // namespace gfx |