Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | |
| 2 // Use of this source code is governed by a BSD-style license that can be | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #include "ui/gl/gl_image.h" | |
| 6 | |
| 7 #include <vector> | |
| 8 | |
| 9 #include "base/memory/ref_counted_memory.h" | |
| 10 #include "base/memory/shared_memory.h" | |
| 11 #include "base/strings/stringprintf.h" | |
| 12 #include "testing/gtest/include/gtest/gtest.h" | |
| 13 #include "third_party/skia/include/core/SkCanvas.h" | |
| 14 #include "third_party/skia/include/core/SkColor.h" | |
| 15 #include "third_party/skia/include/core/SkSurface.h" | |
| 16 #include "ui/gfx/buffer_format_util.h" | |
| 17 #include "ui/gfx/buffer_types.h" | |
| 18 #include "ui/gl/gl_bindings.h" | |
| 19 #include "ui/gl/gl_context.h" | |
| 20 #include "ui/gl/gl_image_ref_counted_memory.h" | |
| 21 #include "ui/gl/gl_image_shared_memory.h" | |
| 22 #include "ui/gl/gl_implementation.h" | |
| 23 #include "ui/gl/gl_surface.h" | |
| 24 #include "ui/gl/gl_version_info.h" | |
| 25 #include "ui/gl/scoped_make_current.h" | |
| 26 #include "ui/gl/test/gl_surface_test_support.h" | |
| 27 | |
| 28 #if defined(OS_MACOSX) | |
| 29 #include <CoreFoundation/CoreFoundation.h> | |
| 30 #include "ui/gl/gl_image_io_surface.h" | |
| 31 #endif | |
| 32 | |
| 33 #if defined(OS_ANDROID) | |
| 34 #include <android/native_window_jni.h> | |
| 35 #include "base/android/jni_android.h" | |
| 36 #include "ui/gl/android/scoped_java_surface.h" | |
| 37 #include "ui/gl/android/surface_texture.h" | |
| 38 #include "ui/gl/gl_image_surface_texture.h" | |
| 39 #endif | |
| 40 | |
| 41 namespace gfx { | |
| 42 namespace { | |
| 43 | |
| 44 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
| |
| 45 SHARED_MEMORY, | |
| 46 REF_COUNTED_MEMORY, | |
| 47 IO_SURFACE, | |
| 48 SURFACE_TEXTURE, | |
| 49 OZONE_NATIVE_PIXMAP | |
| 50 }; | |
| 51 | |
| 52 #define SHADER(Src) #Src | |
| 53 | |
| 54 // clang-format off | |
| 55 | |
| 56 const char kVertexShader[] = SHADER( | |
| 57 uniform vec2 texScale; | |
| 58 attribute vec2 a_position; | |
| 59 attribute vec2 a_texCoord; | |
| 60 varying vec2 v_texCoord; | |
| 61 void main() { | |
| 62 gl_Position = vec4(a_position.x, a_position.y, 0.0, 1.0); | |
| 63 v_texCoord = vec2(a_texCoord.x * texScale.x, a_texCoord.y * texScale.y); | |
| 64 } | |
| 65 ); | |
| 66 | |
| 67 const char kFragmentShader[] = SHADER( | |
| 68 uniform SamplerType a_texture; | |
| 69 varying vec2 v_texCoord; | |
| 70 void main() { | |
| 71 gl_FragColor = TextureLookup(a_texture, v_texCoord); | |
| 72 } | |
| 73 ); | |
| 74 | |
| 75 // clang-format on | |
| 76 | |
| 77 const char kTexture2DFragmentShaderPrefix[] = | |
| 78 "#define SamplerType sampler2D\n" | |
| 79 "#define TextureLookup texture2D\n"; | |
| 80 | |
| 81 const char kTextureRectangleFragmentShaderPrefix[] = | |
| 82 "#extension GL_ARB_texture_rectangle : require\n" | |
| 83 "#define SamplerType sampler2DRect\n" | |
| 84 "#define TextureLookup texture2DRect\n"; | |
| 85 | |
| 86 const char kTextureExternalFragmentShaderPrefix[] = | |
| 87 "#extension GL_OES_EGL_image_external : require\n" | |
| 88 "#define SamplerType samplerExternalOES\n" | |
| 89 "#define TextureLookup texture2D\n"; | |
| 90 | |
| 91 GLuint LoadShader(GLenum type, const char* const src) { | |
| 92 GLuint shader = glCreateShader(type); | |
| 93 glShaderSource(shader, 1, &src, nullptr); | |
| 94 glCompileShader(shader); | |
| 95 GLint compiled = 0; | |
| 96 glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled); | |
| 97 DCHECK(compiled); | |
| 98 return shader; | |
| 99 } | |
| 100 | |
| 101 class GLImageTest : public testing::TestWithParam<GLImageType> { | |
| 102 public: | |
| 103 // Overridden from testing::Test: | |
| 104 void SetUp() override { | |
| 105 #if defined(USE_OZONE) | |
| 106 // On Ozone, the backend initializes the event system using a UI thread. | |
| 107 base::MessageLoopForUI main_loop; | |
| 108 #endif | |
| 109 | |
| 110 std::vector<GLImplementation> allowed_impls; | |
| 111 GetAllowedGLImplementations(&allowed_impls); | |
| 112 DCHECK(!allowed_impls.empty()); | |
| 113 | |
| 114 GLImplementation impl = allowed_impls[0]; | |
| 115 GLSurfaceTestSupport::InitializeOneOffImplementation(impl); | |
| 116 | |
| 117 surface_ = GLSurface::CreateOffscreenGLSurface(Size()); | |
| 118 context_ = GLContext::CreateGLContext(nullptr, surface_.get(), | |
| 119 PreferIntegratedGpu); | |
| 120 | |
| 121 ui::ScopedMakeCurrent scoped_make_current(context_.get(), surface_.get()); | |
| 122 | |
| 123 bool has_texture_format_bgra8888 = | |
| 124 context_->HasExtension("GL_APPLE_texture_format_BGRA8888") || | |
| 125 context_->HasExtension("GL_EXT_texture_format_BGRA8888") || | |
| 126 !context_->GetVersionInfo()->is_es; | |
| 127 if (!SK_B32_SHIFT && has_texture_format_bgra8888) { | |
| 128 preferred_format_ = BufferFormat::BGRA_8888; | |
| 129 preferred_internal_format_ = GL_BGRA_EXT; | |
| 130 } | |
| 131 | |
| 132 glGenTextures(1, &color_texture_); | |
| 133 glBindTexture(GL_TEXTURE_2D, color_texture_); | |
| 134 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); | |
| 135 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); | |
| 136 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); | |
| 137 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); | |
| 138 // Create a 1024x1024 color buffer. | |
| 139 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1024, 1024, 0, GL_RGBA, | |
| 140 GL_UNSIGNED_BYTE, nullptr); | |
| 141 glBindTexture(GL_TEXTURE_2D, 0); | |
| 142 glGenFramebuffersEXT(1, &framebuffer_); | |
| 143 glBindFramebufferEXT(GL_FRAMEBUFFER, framebuffer_); | |
| 144 glFramebufferTexture2DEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, | |
| 145 GL_TEXTURE_2D, color_texture_, 0); | |
| 146 DCHECK_EQ(static_cast<GLenum>(GL_FRAMEBUFFER_COMPLETE), | |
| 147 glCheckFramebufferStatusEXT(GL_FRAMEBUFFER)); | |
| 148 | |
| 149 vertex_shader_ = LoadShader(GL_VERTEX_SHADER, kVertexShader); | |
| 150 bool is_gles = context_->GetVersionInfo()->is_es; | |
| 151 fragment_shader_ = | |
| 152 LoadShader(GL_FRAGMENT_SHADER, | |
| 153 base::StringPrintf("%s%s%s", TextureFragmentShaderPrefix(), | |
| 154 is_gles ? "precision mediump float;" : "", | |
| 155 kFragmentShader) | |
| 156 .c_str()); | |
| 157 program_ = glCreateProgram(); | |
| 158 glAttachShader(program_, vertex_shader_); | |
| 159 glAttachShader(program_, fragment_shader_); | |
| 160 glBindAttribLocation(program_, 0, "a_position"); | |
| 161 glBindAttribLocation(program_, 1, "a_texCoord"); | |
| 162 glLinkProgram(program_); | |
| 163 GLint linked = -1; | |
| 164 glGetProgramiv(program_, GL_LINK_STATUS, &linked); | |
| 165 DCHECK_NE(linked, 0); | |
| 166 glUseProgram(program_); | |
| 167 sampler_location_ = glGetUniformLocation(program_, "a_texture"); | |
| 168 DCHECK_NE(sampler_location_, -1); | |
| 169 glUniform1i(sampler_location_, 0); | |
| 170 texture_scale_location_ = glGetUniformLocation(program_, "texScale"); | |
| 171 DCHECK_NE(texture_scale_location_, -1); | |
| 172 glUniform2f(texture_scale_location_, 1.f, 1.0f); | |
| 173 | |
| 174 glGenBuffersARB(1, &vertex_buffer_); | |
| 175 glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer_); | |
| 176 // clang-format off | |
| 177 static GLfloat vertices[] = { | |
| 178 -1.f, -1.f, 0.f, 0.f, | |
| 179 1.f, -1.f, 1.f, 0.f, | |
| 180 -1.f, 1.f, 0.f, 1.f, | |
| 181 1.f, 1.f, 1.f, 1.f | |
| 182 }; | |
| 183 // clang-format on | |
| 184 glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); | |
| 185 glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 4, 0); | |
| 186 glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 4, | |
| 187 reinterpret_cast<void*>(sizeof(GLfloat) * 2)); | |
| 188 glEnableVertexAttribArray(0); | |
| 189 glEnableVertexAttribArray(1); | |
| 190 } | |
| 191 void TearDown() override { | |
| 192 { | |
| 193 ui::ScopedMakeCurrent scoped_make_current(context_.get(), surface_.get()); | |
| 194 | |
| 195 glDeleteProgram(program_); | |
| 196 glDeleteShader(vertex_shader_); | |
| 197 glDeleteShader(fragment_shader_); | |
| 198 glBindBuffer(GL_ARRAY_BUFFER, 0); | |
| 199 glDeleteBuffersARB(1, &vertex_buffer_); | |
| 200 glBindFramebufferEXT(GL_FRAMEBUFFER, 0); | |
| 201 glDeleteFramebuffersEXT(1, &framebuffer_); | |
| 202 glDeleteTextures(1, &color_texture_); | |
| 203 } | |
| 204 | |
| 205 context_ = nullptr; | |
| 206 surface_ = nullptr; | |
| 207 | |
| 208 ClearGLBindings(); | |
| 209 } | |
| 210 | |
| 211 protected: | |
| 212 scoped_refptr<GLImage> CreateSolidColorImage(const Size& size, | |
| 213 unsigned internalformat, | |
| 214 BufferFormat format, | |
| 215 SkColor color) { | |
| 216 switch (GetParam()) { | |
| 217 case GLImageType::SHARED_MEMORY: { | |
| 218 DCHECK_EQ(NumberOfPlanesForBufferFormat(format), 1u); | |
| 219 base::SharedMemory shared_memory; | |
| 220 if (!shared_memory.CreateAndMapAnonymous( | |
| 221 BufferSizeForBufferFormat(size, format))) { | |
| 222 return nullptr; | |
| 223 } | |
| 224 ClearDataToSolidColor( | |
| 225 size, format, | |
| 226 static_cast<int>(RowSizeForBufferFormat(size.width(), format, 0)), | |
| 227 reinterpret_cast<uint8_t*>(shared_memory.memory()), color); | |
| 228 | |
| 229 scoped_refptr<GLImageSharedMemory> image( | |
| 230 new GLImageSharedMemory(size, internalformat)); | |
| 231 if (!image->Initialize( | |
| 232 base::SharedMemory::DuplicateHandle(shared_memory.handle()), | |
| 233 NextGenericSharedMemoryId(), format)) { | |
| 234 return nullptr; | |
| 235 } | |
| 236 return image; | |
| 237 } | |
| 238 case GLImageType::REF_COUNTED_MEMORY: { | |
| 239 DCHECK_EQ(NumberOfPlanesForBufferFormat(format), 1u); | |
| 240 std::vector<uint8_t> data(BufferSizeForBufferFormat(size, format), 0); | |
| 241 scoped_refptr<base::RefCountedBytes> bytes( | |
| 242 new base::RefCountedBytes(data)); | |
| 243 ClearDataToSolidColor( | |
| 244 size, format, | |
| 245 static_cast<int>(RowSizeForBufferFormat(size.width(), format, 0)), | |
| 246 &bytes->data().front(), color); | |
| 247 | |
| 248 scoped_refptr<GLImageRefCountedMemory> image( | |
| 249 new GLImageRefCountedMemory(size, internalformat)); | |
| 250 if (!image->Initialize(bytes.get(), format)) | |
| 251 return nullptr; | |
| 252 return image; | |
| 253 } | |
| 254 case GLImageType::IO_SURFACE: { | |
| 255 #if defined(OS_MACOSX) | |
| 256 DCHECK(format == BufferFormat::BGRA_8888); | |
| 257 base::ScopedCFTypeRef<CFMutableDictionaryRef> properties( | |
| 258 CFDictionaryCreateMutable(kCFAllocatorDefault, 0, | |
| 259 &kCFTypeDictionaryKeyCallBacks, | |
| 260 &kCFTypeDictionaryValueCallBacks)); | |
| 261 int32_t width = size.width(); | |
| 262 base::ScopedCFTypeRef<CFNumberRef> cf_width( | |
| 263 CFNumberCreate(nullptr, kCFNumberSInt32Type, &width)); | |
| 264 CFDictionaryAddValue(properties, kIOSurfaceWidth, cf_width.get()); | |
| 265 int32_t height = size.height(); | |
| 266 base::ScopedCFTypeRef<CFNumberRef> cf_height( | |
| 267 CFNumberCreate(nullptr, kCFNumberSInt32Type, &height)); | |
| 268 CFDictionaryAddValue(properties, kIOSurfaceHeight, cf_height.get()); | |
| 269 int32_t pixel_format = 'BGRA'; | |
| 270 base::ScopedCFTypeRef<CFNumberRef> cf_pixel_format( | |
| 271 CFNumberCreate(nullptr, kCFNumberSInt32Type, &pixel_format)); | |
| 272 CFDictionaryAddValue(properties, kIOSurfacePixelFormat, | |
| 273 cf_pixel_format.get()); | |
| 274 int32_t bytes_per_element = 4; | |
| 275 base::ScopedCFTypeRef<CFNumberRef> cf_bytes_per_element( | |
| 276 CFNumberCreate(nullptr, kCFNumberSInt32Type, &bytes_per_element)); | |
| 277 CFDictionaryAddValue(properties, kIOSurfaceBytesPerElement, | |
| 278 cf_bytes_per_element.get()); | |
| 279 base::ScopedCFTypeRef<IOSurfaceRef> io_surface( | |
| 280 IOSurfaceCreate(properties)); | |
| 281 DCHECK(io_surface); | |
| 282 IOReturn status = IOSurfaceLock(io_surface, 0, nullptr); | |
| 283 DCHECK_EQ(status, kIOReturnSuccess); | |
| 284 ClearDataToSolidColor( | |
| 285 size, format, static_cast<int>(IOSurfaceGetBytesPerRow(io_surface)), | |
| 286 reinterpret_cast<uint8_t*>(IOSurfaceGetBaseAddress(io_surface)), | |
| 287 color); | |
| 288 IOSurfaceUnlock(io_surface, 0, nullptr); | |
| 289 | |
| 290 scoped_refptr<GLImageIOSurface> image( | |
| 291 new GLImageIOSurface(size, internalformat)); | |
| 292 if (!image->Initialize(io_surface, NextGenericSharedMemoryId(), | |
| 293 format)) { | |
| 294 return nullptr; | |
| 295 } | |
| 296 return image; | |
| 297 #else | |
| 298 NOTREACHED(); | |
| 299 return nullptr; | |
| 300 #endif | |
| 301 } | |
| 302 case GLImageType::SURFACE_TEXTURE: { | |
| 303 #if defined(OS_ANDROID) | |
| 304 const int kDummyTextureId = 0; | |
| 305 scoped_refptr<SurfaceTexture> surface_texture = | |
| 306 SurfaceTexture::Create(kDummyTextureId); | |
| 307 DCHECK(surface_texture); | |
| 308 DCHECK(format == BufferFormat::RGBA_8888); | |
| 309 ScopedJavaSurface surface(surface_texture.get()); | |
| 310 JNIEnv* env = base::android::AttachCurrentThread(); | |
| 311 ANativeWindow* native_window = | |
| 312 ANativeWindow_fromSurface(env, surface.j_surface().obj()); | |
| 313 ANativeWindow_setBuffersGeometry(native_window, size.width(), | |
| 314 size.height(), | |
| 315 WINDOW_FORMAT_RGBA_8888); | |
| 316 ANativeWindow_Buffer buffer; | |
| 317 int rv = ANativeWindow_lock(native_window, &buffer, nullptr); | |
| 318 DCHECK_EQ(rv, 0); | |
| 319 ClearDataToSolidColor(size, format, buffer.stride, | |
| 320 reinterpret_cast<uint8_t*>(buffer.bits), color); | |
| 321 ANativeWindow_unlockAndPost(native_window); | |
| 322 | |
| 323 scoped_refptr<GLImageSurfaceTexture> image( | |
| 324 new GLImageSurfaceTexture(size)); | |
| 325 if (!image->Initialize(surface_texture.get())) | |
| 326 return nullptr; | |
| 327 return image; | |
| 328 #else | |
| 329 NOTREACHED(); | |
| 330 return nullptr; | |
| 331 #endif | |
| 332 } | |
| 333 case GLImageType::OZONE_NATIVE_PIXMAP: | |
| 334 NOTREACHED(); | |
| 335 return nullptr; | |
| 336 } | |
| 337 NOTREACHED(); | |
| 338 return nullptr; | |
| 339 } | |
| 340 | |
| 341 GLenum GetTextureTarget() { | |
| 342 switch (GetParam()) { | |
| 343 case GLImageType::SHARED_MEMORY: | |
| 344 case GLImageType::REF_COUNTED_MEMORY: | |
| 345 return GL_TEXTURE_2D; | |
| 346 case GLImageType::IO_SURFACE: | |
| 347 return GL_TEXTURE_RECTANGLE_ARB; | |
| 348 case GLImageType::SURFACE_TEXTURE: | |
| 349 case GLImageType::OZONE_NATIVE_PIXMAP: | |
| 350 return GL_TEXTURE_EXTERNAL_OES; | |
| 351 } | |
| 352 NOTREACHED(); | |
| 353 return GL_TEXTURE_2D; | |
| 354 } | |
| 355 | |
| 356 const char* TextureFragmentShaderPrefix() { | |
| 357 switch (GetParam()) { | |
| 358 case GLImageType::SHARED_MEMORY: | |
| 359 case GLImageType::REF_COUNTED_MEMORY: | |
| 360 return kTexture2DFragmentShaderPrefix; | |
| 361 case GLImageType::IO_SURFACE: | |
| 362 return kTextureRectangleFragmentShaderPrefix; | |
| 363 case GLImageType::SURFACE_TEXTURE: | |
| 364 case GLImageType::OZONE_NATIVE_PIXMAP: | |
| 365 return kTextureExternalFragmentShaderPrefix; | |
| 366 } | |
| 367 NOTREACHED(); | |
| 368 return nullptr; | |
| 369 } | |
| 370 | |
| 371 Vector2dF GetTextureScale(Size size) { | |
| 372 switch (GetParam()) { | |
| 373 case GLImageType::SHARED_MEMORY: | |
| 374 case GLImageType::REF_COUNTED_MEMORY: | |
| 375 case GLImageType::SURFACE_TEXTURE: | |
| 376 case GLImageType::OZONE_NATIVE_PIXMAP: | |
| 377 return Vector2dF(1.f, 1.f); | |
| 378 case GLImageType::IO_SURFACE: | |
| 379 return Vector2dF(size.width(), size.height()); | |
| 380 } | |
| 381 NOTREACHED(); | |
| 382 return Vector2dF(); | |
| 383 } | |
| 384 | |
| 385 void DrawTexture(Size size) { | |
| 386 Vector2dF texture_scale = GetTextureScale(size); | |
| 387 glUniform2f(texture_scale_location_, texture_scale.x(), texture_scale.y()); | |
| 388 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); | |
| 389 } | |
| 390 | |
| 391 GenericSharedMemoryId NextGenericSharedMemoryId() { | |
| 392 return GenericSharedMemoryId(next_generic_shared_memory_id_++); | |
| 393 } | |
| 394 | |
| 395 bool CheckPixels(int x, int y, int width, int height, SkColor color) { | |
| 396 int size = width * height * 4; | |
| 397 scoped_ptr<uint8_t[]> pixels(new uint8_t[size]); | |
| 398 const uint8_t kCheckClearValue = 123u; | |
| 399 memset(pixels.get(), kCheckClearValue, size); | |
| 400 glReadPixels(x, y, width, height, GL_RGBA, GL_UNSIGNED_BYTE, pixels.get()); | |
| 401 uint8_t expected_color[] = { | |
| 402 SkColorGetR(color), SkColorGetG(color), SkColorGetB(color), | |
| 403 SkColorGetA(color), | |
| 404 }; | |
| 405 int bad_count = 0; | |
| 406 for (int yy = 0; yy < height; ++yy) { | |
| 407 for (int xx = 0; xx < width; ++xx) { | |
| 408 int offset = yy * width * 4 + xx * 4; | |
| 409 for (int jj = 0; jj < 4; ++jj) { | |
| 410 uint8_t actual = pixels[offset + jj]; | |
| 411 uint8_t expected = expected_color[jj]; | |
| 412 EXPECT_EQ(expected, actual) << " at " << (xx + x) << ", " << (yy + y) | |
| 413 << " channel " << jj; | |
| 414 bad_count += actual != expected; | |
| 415 // Exit early just so we don't spam the log but we print enough to | |
| 416 // hopefully make it easy to diagnose the issue. | |
| 417 if (bad_count > 16) | |
| 418 return false; | |
| 419 } | |
| 420 } | |
| 421 } | |
| 422 | |
| 423 return !bad_count; | |
| 424 } | |
| 425 | |
| 426 void ClearDataToSolidColor(const Size& size, | |
| 427 BufferFormat format, | |
| 428 int stride, | |
| 429 uint8_t* data, | |
| 430 SkColor color) { | |
| 431 switch (format) { | |
| 432 case BufferFormat::RGBA_8888: | |
| 433 for (int y = 0; y < size.height(); ++y) { | |
| 434 for (int x = 0; x < size.width(); ++x) { | |
| 435 data[y * stride + x * 4 + 0] = SkColorGetR(color); | |
| 436 data[y * stride + x * 4 + 1] = SkColorGetG(color); | |
| 437 data[y * stride + x * 4 + 2] = SkColorGetB(color); | |
| 438 data[y * stride + x * 4 + 3] = SkColorGetA(color); | |
| 439 } | |
| 440 } | |
| 441 return; | |
| 442 case BufferFormat::BGRA_8888: | |
| 443 for (int y = 0; y < size.height(); ++y) { | |
| 444 for (int x = 0; x < size.width(); ++x) { | |
| 445 data[y * stride + x * 4 + 0] = SkColorGetB(color); | |
| 446 data[y * stride + x * 4 + 1] = SkColorGetG(color); | |
| 447 data[y * stride + x * 4 + 2] = SkColorGetR(color); | |
| 448 data[y * stride + x * 4 + 3] = SkColorGetA(color); | |
| 449 } | |
| 450 } | |
| 451 return; | |
| 452 case BufferFormat::ATC: | |
| 453 case BufferFormat::ATCIA: | |
| 454 case BufferFormat::DXT1: | |
| 455 case BufferFormat::DXT5: | |
| 456 case BufferFormat::ETC1: | |
| 457 case BufferFormat::R_8: | |
| 458 case BufferFormat::RGBA_4444: | |
| 459 case BufferFormat::BGRX_8888: | |
| 460 case BufferFormat::UYVY_422: | |
| 461 case BufferFormat::YUV_420_BIPLANAR: | |
| 462 case BufferFormat::YUV_420: | |
| 463 NOTREACHED(); | |
| 464 return; | |
| 465 } | |
| 466 NOTREACHED(); | |
| 467 } | |
| 468 | |
| 469 scoped_refptr<GLContext> context_; | |
| 470 scoped_refptr<GLSurface> surface_; | |
| 471 BufferFormat preferred_format_ = BufferFormat::RGBA_8888; | |
| 472 GLenum preferred_internal_format_ = GL_RGBA; | |
| 473 GLuint color_texture_ = 0; | |
| 474 GLuint framebuffer_ = 0; | |
| 475 GLuint vertex_shader_ = 0; | |
| 476 GLuint fragment_shader_ = 0; | |
| 477 GLuint program_ = 0; | |
| 478 GLuint vertex_buffer_ = 0; | |
| 479 GLint sampler_location_ = -1; | |
| 480 GLint texture_scale_location_ = -1; | |
| 481 int next_generic_shared_memory_id_ = 1; | |
| 482 }; | |
| 483 | |
| 484 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
| |
| 485 ui::ScopedMakeCurrent scoped_make_current(context_.get(), surface_.get()); | |
| 486 | |
| 487 const Size image_size(256, 256); | |
| 488 scoped_refptr<GLImage> image = CreateSolidColorImage( | |
| 489 image_size, preferred_internal_format_, preferred_format_, SK_ColorGREEN); | |
| 490 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
| |
| 491 return; | |
| 492 | |
| 493 GLenum target = GetTextureTarget(); | |
| 494 GLuint texture = 0; | |
| 495 glGenTextures(1, &texture); | |
| 496 glBindTexture(target, texture); | |
| 497 glTexParameteri(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); | |
| 498 glTexParameteri(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); | |
| 499 glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST); | |
| 500 glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST); | |
| 501 glTexImage2D(target, 0, preferred_internal_format_, image_size.width(), | |
| 502 image_size.height(), 0, preferred_internal_format_, | |
| 503 GL_UNSIGNED_BYTE, nullptr); | |
| 504 | |
| 505 // Copy image to |texture|. If supported, check that |texture| contains | |
| 506 // the correct result. | |
| 507 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.
| |
| 508 glViewport(0, 0, image_size.width(), image_size.height()); | |
| 509 DrawTexture(image_size); | |
| 510 CheckPixels(0, 0, image_size.width(), image_size.height(), SK_ColorGREEN); | |
| 511 } | |
| 512 | |
| 513 glDeleteTextures(1, &texture); | |
| 514 image->Destroy(true); | |
| 515 } | |
| 516 | |
| 517 static const GLImageType kGLImageTypes[] = { | |
| 518 GLImageType::SHARED_MEMORY, GLImageType::REF_COUNTED_MEMORY, | |
| 519 #if defined(OS_MACOSX) | |
| 520 GLImageType::IO_SURFACE, | |
| 521 #endif | |
| 522 #if defined(OS_ANDROID) | |
| 523 GLImageType::SURFACE_TEXTURE, | |
| 524 #endif | |
| 525 }; | |
| 526 | |
| 527 INSTANTIATE_TEST_CASE_P(GLImageTests, | |
| 528 GLImageTest, | |
| 529 ::testing::ValuesIn(kGLImageTypes)); | |
| 530 | |
| 531 } // namespace | |
| 532 } // namespace gfx | |
| OLD | NEW |