1 // Copyright 2012 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/scheduler/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 15 namespace cc { 16 namespace { 17 18 class 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 146 void UploadTexture(TextureUploader* uploader, 147 ResourceFormat format, 148 gfx::Size size, 149 const uint8* data) { 150 uploader->Upload(data, 151 gfx::Rect(size), 152 gfx::Rect(size), 153 gfx::Vector2d(), 154 format, 155 size); 156 } 157 158 TEST(TextureUploaderTest, NumBlockingUploads) { 159 TextureUploadTestContext context; 160 scoped_ptr<TextureUploader> uploader = TextureUploader::Create(&context); 161 162 context.SetResultAvailable(0); 163 EXPECT_EQ(0u, uploader->NumBlockingUploads()); 164 UploadTexture(uploader.get(), RGBA_8888, gfx::Size(), NULL); 165 EXPECT_EQ(1u, uploader->NumBlockingUploads()); 166 UploadTexture(uploader.get(), RGBA_8888, gfx::Size(), NULL); 167 EXPECT_EQ(2u, uploader->NumBlockingUploads()); 168 169 context.SetResultAvailable(1); 170 EXPECT_EQ(0u, uploader->NumBlockingUploads()); 171 UploadTexture(uploader.get(), RGBA_8888, gfx::Size(), NULL); 172 EXPECT_EQ(0u, uploader->NumBlockingUploads()); 173 UploadTexture(uploader.get(), RGBA_8888, gfx::Size(), NULL); 174 UploadTexture(uploader.get(), RGBA_8888, gfx::Size(), NULL); 175 EXPECT_EQ(0u, uploader->NumBlockingUploads()); 176 } 177 178 TEST(TextureUploaderTest, MarkPendingUploadsAsNonBlocking) { 179 TextureUploadTestContext context; 180 scoped_ptr<TextureUploader> uploader = TextureUploader::Create(&context); 181 182 context.SetResultAvailable(0); 183 EXPECT_EQ(0u, uploader->NumBlockingUploads()); 184 UploadTexture(uploader.get(), RGBA_8888, gfx::Size(), NULL); 185 UploadTexture(uploader.get(), RGBA_8888, gfx::Size(), NULL); 186 EXPECT_EQ(2u, uploader->NumBlockingUploads()); 187 188 uploader->MarkPendingUploadsAsNonBlocking(); 189 EXPECT_EQ(0u, uploader->NumBlockingUploads()); 190 UploadTexture(uploader.get(), RGBA_8888, gfx::Size(), NULL); 191 EXPECT_EQ(1u, uploader->NumBlockingUploads()); 192 193 context.SetResultAvailable(1); 194 EXPECT_EQ(0u, uploader->NumBlockingUploads()); 195 UploadTexture(uploader.get(), RGBA_8888, gfx::Size(), NULL); 196 uploader->MarkPendingUploadsAsNonBlocking(); 197 EXPECT_EQ(0u, uploader->NumBlockingUploads()); 198 } 199 200 TEST(TextureUploaderTest, UploadContentsTest) { 201 TextureUploadTestContext context; 202 scoped_ptr<TextureUploader> uploader = TextureUploader::Create(&context); 203 204 uint8 buffer[256 * 256 * 4]; 205 206 // Upload a tightly packed 256x256 RGBA texture. 207 memset(buffer, 0, sizeof(buffer)); 208 for (int i = 0; i < 256; ++i) { 209 // Mark the beginning and end of each row, for the test. 210 buffer[i * 4 * 256] = 0x1; 211 buffer[(i + 1) * 4 * 256 - 1] = 0x2; 212 } 213 UploadTexture(uploader.get(), RGBA_8888, gfx::Size(256, 256), buffer); 214 215 // Upload a tightly packed 41x43 RGBA texture. 216 memset(buffer, 0, sizeof(buffer)); 217 for (int i = 0; i < 43; ++i) { 218 // Mark the beginning and end of each row, for the test. 219 buffer[i * 4 * 41] = 0x1; 220 buffer[(i + 1) * 4 * 41 - 1] = 0x2; 221 } 222 UploadTexture(uploader.get(), RGBA_8888, gfx::Size(41, 43), buffer); 223 224 // Upload a tightly packed 82x86 LUMINANCE texture. 225 memset(buffer, 0, sizeof(buffer)); 226 for (int i = 0; i < 86; ++i) { 227 // Mark the beginning and end of each row, for the test. 228 buffer[i * 1 * 82] = 0x1; 229 buffer[(i + 1) * 82 - 1] = 0x2; 230 } 231 UploadTexture(uploader.get(), LUMINANCE_8, gfx::Size(82, 86), buffer); 232 } 233 234 } // namespace 235 } // namespace cc 236