1// Copyright 2014 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 "cc/resources/texture_uploader.h" 6 7#include "cc/base/util.h" 8#include "cc/resources/prioritized_resource.h" 9#include "gpu/command_buffer/client/gles2_interface_stub.h" 10#include "testing/gmock/include/gmock/gmock.h" 11#include "testing/gtest/include/gtest/gtest.h" 12#include "third_party/khronos/GLES2/gl2.h" 13#include "third_party/khronos/GLES2/gl2ext.h" 14 15namespace cc { 16namespace { 17 18class TextureUploadTestContext : public gpu::gles2::GLES2InterfaceStub { 19 public: 20 TextureUploadTestContext() : result_available_(0), unpack_alignment_(4) {} 21 22 virtual void PixelStorei(GLenum pname, GLint param) OVERRIDE { 23 switch (pname) { 24 case GL_UNPACK_ALIGNMENT: 25 // Param should be a power of two <= 8. 26 EXPECT_EQ(0, param & (param - 1)); 27 EXPECT_GE(8, param); 28 switch (param) { 29 case 1: 30 case 2: 31 case 4: 32 case 8: 33 unpack_alignment_ = param; 34 break; 35 default: 36 break; 37 } 38 break; 39 default: 40 break; 41 } 42 } 43 44 virtual void GetQueryObjectuivEXT(GLuint, 45 GLenum type, 46 GLuint* value) OVERRIDE { 47 switch (type) { 48 case GL_QUERY_RESULT_AVAILABLE_EXT: 49 *value = result_available_; 50 break; 51 default: 52 *value = 0; 53 break; 54 } 55 } 56 57 virtual void TexSubImage2D(GLenum target, 58 GLint level, 59 GLint xoffset, 60 GLint yoffset, 61 GLsizei width, 62 GLsizei height, 63 GLenum format, 64 GLenum type, 65 const void* pixels) OVERRIDE { 66 EXPECT_EQ(static_cast<unsigned>(GL_TEXTURE_2D), target); 67 EXPECT_EQ(0, level); 68 EXPECT_LE(0, width); 69 EXPECT_LE(0, height); 70 EXPECT_LE(0, xoffset); 71 EXPECT_LE(0, yoffset); 72 EXPECT_LE(0, width); 73 EXPECT_LE(0, height); 74 75 // Check for allowed format/type combination. 76 unsigned int bytes_per_pixel = 0; 77 switch (format) { 78 case GL_ALPHA: 79 EXPECT_EQ(static_cast<unsigned>(GL_UNSIGNED_BYTE), type); 80 bytes_per_pixel = 1; 81 break; 82 case GL_RGB: 83 EXPECT_NE(static_cast<unsigned>(GL_UNSIGNED_SHORT_4_4_4_4), type); 84 EXPECT_NE(static_cast<unsigned>(GL_UNSIGNED_SHORT_5_5_5_1), type); 85 switch (type) { 86 case GL_UNSIGNED_BYTE: 87 bytes_per_pixel = 3; 88 break; 89 case GL_UNSIGNED_SHORT_5_6_5: 90 bytes_per_pixel = 2; 91 break; 92 } 93 break; 94 case GL_RGBA: 95 EXPECT_NE(static_cast<unsigned>(GL_UNSIGNED_SHORT_5_6_5), type); 96 switch (type) { 97 case GL_UNSIGNED_BYTE: 98 bytes_per_pixel = 4; 99 break; 100 case GL_UNSIGNED_SHORT_4_4_4_4: 101 bytes_per_pixel = 2; 102 break; 103 case GL_UNSIGNED_SHORT_5_5_5_1: 104 bytes_per_pixel = 2; 105 break; 106 } 107 break; 108 case GL_LUMINANCE: 109 EXPECT_EQ(static_cast<unsigned>(GL_UNSIGNED_BYTE), type); 110 bytes_per_pixel = 1; 111 break; 112 case GL_LUMINANCE_ALPHA: 113 EXPECT_EQ(static_cast<unsigned>(GL_UNSIGNED_BYTE), type); 114 bytes_per_pixel = 2; 115 break; 116 } 117 118 // If NULL, we aren't checking texture contents. 119 if (pixels == NULL) 120 return; 121 122 const uint8* bytes = static_cast<const uint8*>(pixels); 123 // We'll expect the first byte of every row to be 0x1, and the last byte to 124 // be 0x2. 125 const unsigned int stride = 126 RoundUp(bytes_per_pixel * width, unpack_alignment_); 127 for (GLsizei row = 0; row < height; ++row) { 128 const uint8* row_bytes = 129 bytes + (xoffset * bytes_per_pixel + (yoffset + row) * stride); 130 EXPECT_EQ(0x1, row_bytes[0]); 131 EXPECT_EQ(0x2, row_bytes[width * bytes_per_pixel - 1]); 132 } 133 } 134 135 void SetResultAvailable(unsigned result_available) { 136 result_available_ = result_available; 137 } 138 139 private: 140 unsigned result_available_; 141 unsigned unpack_alignment_; 142 143 DISALLOW_COPY_AND_ASSIGN(TextureUploadTestContext); 144}; 145 146void UploadTexture(TextureUploader* uploader, 147 ResourceFormat format, 148 const gfx::Size& size, 149 const uint8* data) { 150 uploader->Upload( 151 data, gfx::Rect(size), gfx::Rect(size), gfx::Vector2d(), format, size); 152} 153 154TEST(TextureUploaderTest, NumBlockingUploads) { 155 TextureUploadTestContext context; 156 scoped_ptr<TextureUploader> uploader = TextureUploader::Create(&context); 157 158 context.SetResultAvailable(0); 159 EXPECT_EQ(0u, uploader->NumBlockingUploads()); 160 UploadTexture(uploader.get(), RGBA_8888, gfx::Size(), NULL); 161 EXPECT_EQ(1u, uploader->NumBlockingUploads()); 162 UploadTexture(uploader.get(), RGBA_8888, gfx::Size(), NULL); 163 EXPECT_EQ(2u, uploader->NumBlockingUploads()); 164 165 context.SetResultAvailable(1); 166 EXPECT_EQ(0u, uploader->NumBlockingUploads()); 167 UploadTexture(uploader.get(), RGBA_8888, gfx::Size(), NULL); 168 EXPECT_EQ(0u, uploader->NumBlockingUploads()); 169 UploadTexture(uploader.get(), RGBA_8888, gfx::Size(), NULL); 170 UploadTexture(uploader.get(), RGBA_8888, gfx::Size(), NULL); 171 EXPECT_EQ(0u, uploader->NumBlockingUploads()); 172} 173 174TEST(TextureUploaderTest, MarkPendingUploadsAsNonBlocking) { 175 TextureUploadTestContext context; 176 scoped_ptr<TextureUploader> uploader = TextureUploader::Create(&context); 177 178 context.SetResultAvailable(0); 179 EXPECT_EQ(0u, uploader->NumBlockingUploads()); 180 UploadTexture(uploader.get(), RGBA_8888, gfx::Size(), NULL); 181 UploadTexture(uploader.get(), RGBA_8888, gfx::Size(), NULL); 182 EXPECT_EQ(2u, uploader->NumBlockingUploads()); 183 184 uploader->MarkPendingUploadsAsNonBlocking(); 185 EXPECT_EQ(0u, uploader->NumBlockingUploads()); 186 UploadTexture(uploader.get(), RGBA_8888, gfx::Size(), NULL); 187 EXPECT_EQ(1u, uploader->NumBlockingUploads()); 188 189 context.SetResultAvailable(1); 190 EXPECT_EQ(0u, uploader->NumBlockingUploads()); 191 UploadTexture(uploader.get(), RGBA_8888, gfx::Size(), NULL); 192 uploader->MarkPendingUploadsAsNonBlocking(); 193 EXPECT_EQ(0u, uploader->NumBlockingUploads()); 194} 195 196TEST(TextureUploaderTest, UploadContentsTest) { 197 TextureUploadTestContext context; 198 scoped_ptr<TextureUploader> uploader = TextureUploader::Create(&context); 199 200 uint8 buffer[256 * 256 * 4]; 201 202 // Upload a tightly packed 256x256 RGBA texture. 203 memset(buffer, 0, sizeof(buffer)); 204 for (int i = 0; i < 256; ++i) { 205 // Mark the beginning and end of each row, for the test. 206 buffer[i * 4 * 256] = 0x1; 207 buffer[(i + 1) * 4 * 256 - 1] = 0x2; 208 } 209 UploadTexture(uploader.get(), RGBA_8888, gfx::Size(256, 256), buffer); 210 211 // Upload a tightly packed 41x43 RGBA texture. 212 memset(buffer, 0, sizeof(buffer)); 213 for (int i = 0; i < 43; ++i) { 214 // Mark the beginning and end of each row, for the test. 215 buffer[i * 4 * 41] = 0x1; 216 buffer[(i + 1) * 4 * 41 - 1] = 0x2; 217 } 218 UploadTexture(uploader.get(), RGBA_8888, gfx::Size(41, 43), buffer); 219 220 // Upload a tightly packed 41x86 ALPHA texture. 221 memset(buffer, 0, sizeof(buffer)); 222 for (int i = 0; i < 86; ++i) { 223 // Mark the beginning and end of each row, for the test. 224 buffer[i * 1 * 41] = 0x1; 225 buffer[(i + 1) * 41 - 1] = 0x2; 226 } 227 UploadTexture(uploader.get(), ALPHA_8, gfx::Size(41, 86), buffer); 228 229 // Upload a tightly packed 82x86 LUMINANCE texture. 230 memset(buffer, 0, sizeof(buffer)); 231 for (int i = 0; i < 86; ++i) { 232 // Mark the beginning and end of each row, for the test. 233 buffer[i * 1 * 82] = 0x1; 234 buffer[(i + 1) * 82 - 1] = 0x2; 235 } 236 UploadTexture(uploader.get(), LUMINANCE_8, gfx::Size(82, 86), buffer); 237} 238 239} // namespace 240} // namespace cc 241