Home | History | Annotate | Download | only in scheduler
      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