Home | History | Annotate | Download | only in resources
      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 
     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                    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 
    154 TEST(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 
    174 TEST(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 
    196 TEST(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 82x86 LUMINANCE 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 * 82] = 0x1;
    225     buffer[(i + 1) * 82 - 1] = 0x2;
    226   }
    227   UploadTexture(uploader.get(), LUMINANCE_8, gfx::Size(82, 86), buffer);
    228 }
    229 
    230 }  // namespace
    231 }  // namespace cc
    232