Home | History | Annotate | Download | only in src
      1 // Copyright (c) 2010 The Chromium OS 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 <stdio.h>
      6 
      7 #include "main.h"
      8 #include "testbase.h"
      9 #include "utils.h"
     10 
     11 namespace glbench {
     12 
     13 const float kScreenScaleFactor =
     14     1e6f * (WINDOW_WIDTH * WINDOW_HEIGHT) / (1280.f * 768);
     15 
     16 class WindowManagerCompositingTest : public TestBase {
     17  public:
     18   WindowManagerCompositingTest(bool scissor)
     19       : scissor_(scissor),
     20         compositing_background_program_(0),
     21         compositing_foreground_program_(0) {}
     22   virtual ~WindowManagerCompositingTest() {}
     23   virtual bool TestFunc(uint64_t iterations);
     24   virtual bool Run();
     25   virtual const char* Name() const { return "compositing"; }
     26   virtual bool IsDrawTest() const { return true; }
     27   virtual const char* Unit() const { return "1280x768_fps"; }
     28 
     29   void InitializeCompositing();
     30   void TeardownCompositing();
     31   void InitBaseTexture();
     32   void UpdateTexture();
     33   void LoadTexture();
     34 
     35  private:
     36   bool scissor_;
     37   uint32_t texture_base_[WINDOW_HEIGHT * WINDOW_WIDTH];
     38   uint32_t texture_update_[WINDOW_HEIGHT * WINDOW_WIDTH];
     39   GLuint compositing_textures_[5];
     40   GLuint compositing_background_program_;
     41   GLuint compositing_foreground_program_;
     42   DISALLOW_COPY_AND_ASSIGN(WindowManagerCompositingTest);
     43 };
     44 
     45 TestBase* GetWindowManagerCompositingTest(bool enable_scissor) {
     46   return new WindowManagerCompositingTest(enable_scissor);
     47 }
     48 
     49 bool WindowManagerCompositingTest::Run() {
     50   const char* testname = "compositing";
     51   if (scissor_) {
     52     glScissor(0, 0, 1, 1);
     53     glEnable(GL_SCISSOR_TEST);
     54     testname = "compositing_no_fill";
     55   }
     56   InitializeCompositing();
     57   RunTest(this, testname, kScreenScaleFactor, WINDOW_WIDTH, WINDOW_HEIGHT,
     58           true);
     59   TeardownCompositing();
     60   return true;
     61 }
     62 
     63 bool WindowManagerCompositingTest::TestFunc(uint64_t iterations) {
     64   for (uint64_t i = 0; i < iterations; ++i) {
     65     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
     66 
     67     // Draw the background
     68     glDisable(GL_BLEND);
     69     glDisable(GL_DEPTH_TEST);
     70     // We have to blend three textures, but we use multi-texture for this
     71     // blending, not fb blend, to avoid the external memory traffic
     72     glActiveTexture(GL_TEXTURE0);
     73     glBindTexture(GL_TEXTURE_2D, compositing_textures_[0]);
     74     glActiveTexture(GL_TEXTURE1);
     75     glBindTexture(GL_TEXTURE_2D, compositing_textures_[1]);
     76     glActiveTexture(GL_TEXTURE2);
     77     glBindTexture(GL_TEXTURE_2D, compositing_textures_[2]);
     78     // Use the right shader
     79     glUseProgram(compositing_background_program_);
     80     // Draw the quad
     81     glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
     82 
     83     // Use the right shader
     84     glUseProgram(compositing_foreground_program_);
     85 
     86     // Compositing is blending, so we shall blend.
     87     glEnable(GL_BLEND);
     88     // Depth test is on for window occlusion
     89     glEnable(GL_DEPTH_TEST);
     90 
     91     // Draw window number one
     92     // This update acts like a chrome webkit sw rendering update.
     93     glActiveTexture(GL_TEXTURE0);
     94     glBindTexture(GL_TEXTURE_2D, compositing_textures_[3]);
     95     UpdateTexture();
     96     // TODO(papakipos): this LoadTexture is likely doing more CPU memory copies
     97     // than we would like.
     98     LoadTexture();
     99     // TODO(papakipos): add color interpolation here, and modulate
    100     // texture against it.
    101     glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
    102 
    103     // Draw window number two
    104     // This is a static window, so we don't update it.
    105     glActiveTexture(GL_TEXTURE0);
    106     glBindTexture(GL_TEXTURE_2D, compositing_textures_[4]);
    107     // TODO(papakipos): add color interpolation here, and modulate
    108     // texture against it.
    109     glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
    110   }
    111   return true;
    112 }
    113 
    114 const char* kBasicTextureVertexShader =
    115     "attribute vec4 c1;"
    116     "attribute vec4 c2;"
    117     "varying vec4 v1;"
    118     "void main() {"
    119     "    gl_Position = c1;"
    120     "    v1 = c2;"
    121     "}";
    122 
    123 const char* kBasicTextureFragmentShader =
    124     "uniform sampler2D texture_sampler;"
    125     "varying vec4 v1;"
    126     "void main() {"
    127     "    gl_FragColor = texture2D(texture_sampler, v1.st);"
    128     "}";
    129 
    130 GLuint BasicTextureShaderProgram(GLuint vertex_buffer, GLuint texture_buffer) {
    131   GLuint program =
    132       InitShaderProgram(kBasicTextureVertexShader, kBasicTextureFragmentShader);
    133 
    134   // Set up the texture sampler
    135   int textureSampler = glGetUniformLocation(program, "texture_sampler");
    136   glUniform1i(textureSampler, 0);
    137 
    138   // Set up vertex attribute
    139   int attribute_index = glGetAttribLocation(program, "c1");
    140   glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer);
    141   glVertexAttribPointer(attribute_index, 2, GL_FLOAT, GL_FALSE, 0, NULL);
    142   glEnableVertexAttribArray(attribute_index);
    143 
    144   // Set up texture attribute
    145   attribute_index = glGetAttribLocation(program, "c2");
    146   glBindBuffer(GL_ARRAY_BUFFER, texture_buffer);
    147   glVertexAttribPointer(attribute_index, 2, GL_FLOAT, GL_FALSE, 0, NULL);
    148   glEnableVertexAttribArray(attribute_index);
    149 
    150   return program;
    151 }
    152 
    153 const char* kDoubleTextureBlendVertexShader =
    154     "attribute vec4 c1;"
    155     "attribute vec4 c2;"
    156     "attribute vec4 c3;"
    157     "varying vec4 v1;"
    158     "varying vec4 v2;"
    159     "void main() {"
    160     "    gl_Position = c1;"
    161     "    v1 = c2;"
    162     "    v2 = c3;"
    163     "}";
    164 
    165 const char* kDoubleTextureBlendFragmentShader =
    166     "uniform sampler2D texture_sampler_0;"
    167     "uniform sampler2D texture_sampler_1;"
    168     "varying vec4 v1;"
    169     "varying vec4 v2;"
    170     "void main() {"
    171     "    vec4 one = texture2D(texture_sampler_0, v1.st);"
    172     "    vec4 two = texture2D(texture_sampler_1, v2.st);"
    173     "    gl_FragColor = mix(one, two, 0.5);"
    174     "}";
    175 
    176 // This shader blends the three textures
    177 GLuint DoubleTextureBlendShaderProgram(GLuint vertex_buffer,
    178                                        GLuint texture_buffer_0,
    179                                        GLuint texture_buffer_1) {
    180   GLuint program = InitShaderProgram(kDoubleTextureBlendVertexShader,
    181                                      kDoubleTextureBlendFragmentShader);
    182   // Set up the texture sampler
    183   int textureSampler0 = glGetUniformLocation(program, "texture_sampler_0");
    184   glUniform1i(textureSampler0, 0);
    185   int textureSampler1 = glGetUniformLocation(program, "texture_sampler_1");
    186   glUniform1i(textureSampler1, 1);
    187 
    188   // Set up vertex attribute
    189   int attribute_index = glGetAttribLocation(program, "c1");
    190   glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer);
    191   glVertexAttribPointer(attribute_index, 2, GL_FLOAT, GL_FALSE, 0, NULL);
    192   glEnableVertexAttribArray(attribute_index);
    193 
    194   // Set up texture attributes
    195   attribute_index = glGetAttribLocation(program, "c2");
    196   glBindBuffer(GL_ARRAY_BUFFER, texture_buffer_0);
    197   glVertexAttribPointer(attribute_index, 2, GL_FLOAT, GL_FALSE, 0, NULL);
    198   glEnableVertexAttribArray(attribute_index);
    199 
    200   attribute_index = glGetAttribLocation(program, "c3");
    201   glBindBuffer(GL_ARRAY_BUFFER, texture_buffer_1);
    202   glVertexAttribPointer(attribute_index, 2, GL_FLOAT, GL_FALSE, 0, NULL);
    203   glEnableVertexAttribArray(attribute_index);
    204 
    205   return program;
    206 }
    207 
    208 const char* triple_texture_blend_vertex_shader =
    209     "attribute vec4 c1;"
    210     "attribute vec4 c2;"
    211     "attribute vec4 c3;"
    212     "attribute vec4 c4;"
    213     "varying vec4 v1;"
    214     "varying vec4 v2;"
    215     "varying vec4 v3;"
    216     "void main() {"
    217     "    gl_Position = c1;"
    218     "    v1 = c2;"
    219     "    v2 = c3;"
    220     "    v3 = c4;"
    221     "}";
    222 
    223 const char* triple_texture_blend_fragment_shader =
    224     "uniform sampler2D texture_sampler_0;"
    225     "uniform sampler2D texture_sampler_1;"
    226     "uniform sampler2D texture_sampler_2;"
    227     "varying vec4 v1;"
    228     "varying vec4 v2;"
    229     "varying vec4 v3;"
    230     "void main() {"
    231     "    vec4 one = texture2D(texture_sampler_0, v1.st);"
    232     "    vec4 two = texture2D(texture_sampler_1, v2.st);"
    233     "    vec4 three = texture2D(texture_sampler_2, v3.st);"
    234     "    gl_FragColor = mix(mix(one, two, 0.5), three, 0.5);"
    235     "}";
    236 
    237 // This shader blends the three textures
    238 GLuint TripleTextureBlendShaderProgram(GLuint vertex_buffer,
    239                                        GLuint texture_buffer_0,
    240                                        GLuint texture_buffer_1,
    241                                        GLuint texture_buffer_2) {
    242   GLuint program = InitShaderProgram(triple_texture_blend_vertex_shader,
    243                                      triple_texture_blend_fragment_shader);
    244 
    245   // Set up the texture sampler
    246   int textureSampler0 = glGetUniformLocation(program, "texture_sampler_0");
    247   glUniform1i(textureSampler0, 0);
    248   int textureSampler1 = glGetUniformLocation(program, "texture_sampler_1");
    249   glUniform1i(textureSampler1, 1);
    250   int textureSampler2 = glGetUniformLocation(program, "texture_sampler_2");
    251   glUniform1i(textureSampler2, 2);
    252 
    253   // Set up vertex attribute
    254   int attribute_index = glGetAttribLocation(program, "c1");
    255   glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer);
    256   glVertexAttribPointer(attribute_index, 2, GL_FLOAT, GL_FALSE, 0, NULL);
    257   glEnableVertexAttribArray(attribute_index);
    258 
    259   // Set up texture attributes
    260   attribute_index = glGetAttribLocation(program, "c2");
    261   glBindBuffer(GL_ARRAY_BUFFER, texture_buffer_0);
    262   glVertexAttribPointer(attribute_index, 2, GL_FLOAT, GL_FALSE, 0, NULL);
    263   glEnableVertexAttribArray(attribute_index);
    264 
    265   attribute_index = glGetAttribLocation(program, "c3");
    266   glBindBuffer(GL_ARRAY_BUFFER, texture_buffer_1);
    267   glVertexAttribPointer(attribute_index, 2, GL_FLOAT, GL_FALSE, 0, NULL);
    268   glEnableVertexAttribArray(attribute_index);
    269 
    270   attribute_index = glGetAttribLocation(program, "c4");
    271   glBindBuffer(GL_ARRAY_BUFFER, texture_buffer_2);
    272   glVertexAttribPointer(attribute_index, 2, GL_FLOAT, GL_FALSE, 0, NULL);
    273   glEnableVertexAttribArray(attribute_index);
    274 
    275   return program;
    276 }
    277 
    278 void WindowManagerCompositingTest::InitializeCompositing() {
    279   InitBaseTexture();
    280 
    281   glClearColor(0.f, 0.f, 0.f, 0.f);
    282   glDisable(GL_DEPTH_TEST);
    283   glDisable(GL_BLEND);
    284   glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    285   glDepthFunc(GL_LEQUAL);
    286 
    287   glGenTextures(5, compositing_textures_);
    288   glActiveTexture(GL_TEXTURE0);
    289   for (int i = 0; i < 5; i++) {
    290     glBindTexture(GL_TEXTURE_2D, compositing_textures_[i]);
    291     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    292     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    293   }
    294 
    295   // Set up the vertex arrays for drawing textured quads later on.
    296   GLfloat buffer_vertex[8] = {
    297       -1.f, -1.f,
    298       1.f, -1.f,
    299       -1.f, 1.f,
    300       1.f, 1.f,
    301   };
    302   GLuint vbo_vertex =
    303       SetupVBO(GL_ARRAY_BUFFER, sizeof(buffer_vertex), buffer_vertex);
    304 
    305   GLfloat buffer_texture[8] = {
    306       0.f, 0.f,
    307       1.f, 0.f,
    308       0.f, 1.f,
    309       1.f, 1.f,
    310   };
    311   GLuint vbo_texture =
    312       SetupVBO(GL_ARRAY_BUFFER, sizeof(buffer_texture), buffer_texture);
    313 
    314   // Set up the static background textures.
    315   UpdateTexture();
    316   UpdateTexture();
    317   UpdateTexture();
    318   // Load these textures into bound texture ids and keep using them
    319   // from there to avoid having to reload this texture every frame
    320   glActiveTexture(GL_TEXTURE0);
    321   glBindTexture(GL_TEXTURE_2D, compositing_textures_[0]);
    322   LoadTexture();
    323   glActiveTexture(GL_TEXTURE1);
    324   glBindTexture(GL_TEXTURE_2D, compositing_textures_[1]);
    325   LoadTexture();
    326   glActiveTexture(GL_TEXTURE2);
    327   glBindTexture(GL_TEXTURE_2D, compositing_textures_[2]);
    328   LoadTexture();
    329 
    330   glActiveTexture(GL_TEXTURE0);
    331   glBindTexture(GL_TEXTURE_2D, compositing_textures_[3]);
    332   UpdateTexture();
    333   LoadTexture();
    334 
    335   glActiveTexture(GL_TEXTURE0);
    336   glBindTexture(GL_TEXTURE_2D, compositing_textures_[4]);
    337   UpdateTexture();
    338   LoadTexture();
    339 
    340   // Set up vertex & fragment shaders.
    341   compositing_background_program_ = TripleTextureBlendShaderProgram(
    342       vbo_vertex, vbo_texture, vbo_texture, vbo_texture);
    343   compositing_foreground_program_ =
    344       BasicTextureShaderProgram(vbo_vertex, vbo_texture);
    345   if (!compositing_background_program_ || !compositing_foreground_program_) {
    346     printf("# Warning: Could not set up compositing shader.\n");
    347   }
    348 }
    349 
    350 void WindowManagerCompositingTest::TeardownCompositing() {
    351   glDeleteProgram(compositing_background_program_);
    352   glDeleteProgram(compositing_foreground_program_);
    353 }
    354 
    355 void WindowManagerCompositingTest::InitBaseTexture() {
    356   for (int y = 0; y < WINDOW_HEIGHT; y++) {
    357     for (int x = 0; x < WINDOW_WIDTH; x++) {
    358       // This color is gray, half alpha.
    359       texture_base_[y * WINDOW_WIDTH + x] = 0x80808080;
    360     }
    361   }
    362 }
    363 
    364 // UpdateTexture simulates Chrome updating tab contents.
    365 // We cause a bunch of read and write cpu memory bandwidth.
    366 // It's a very rough approximation.
    367 void WindowManagerCompositingTest::UpdateTexture() {
    368   memcpy(texture_update_, texture_base_, sizeof(texture_base_));
    369 }
    370 
    371 void WindowManagerCompositingTest::LoadTexture() {
    372   // Use GL_RGBA for compatibility with GLES2.0.
    373   glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, WINDOW_WIDTH, WINDOW_HEIGHT, 0,
    374                GL_RGBA, GL_UNSIGNED_BYTE, texture_update_);
    375 }
    376 
    377 }  // namespace glbench
    378