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