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 
     12 namespace glbench {
     13 
     14 const float kScreenScaleFactor = 1e6f * (WINDOW_WIDTH * WINDOW_HEIGHT) /
     15     (1280.f * 768);
     16 
     17 class WindowManagerCompositingTest : public TestBase {
     18  public:
     19   WindowManagerCompositingTest(bool scissor)
     20       : scissor_(scissor),
     21       compositing_background_program_(0),
     22       compositing_foreground_program_(0) {}
     23   virtual ~WindowManagerCompositingTest() {}
     24   virtual bool TestFunc(uint64_t iterations);
     25   virtual bool Run();
     26   virtual const char* Name() const { return "compositing"; }
     27   virtual bool IsDrawTest() const { return true; }
     28   virtual const char* Unit() const { return "1280x768_fps"; }
     29 
     30   void InitializeCompositing();
     31   void TeardownCompositing();
     32   void InitBaseTexture();
     33   void UpdateTexture();
     34   void LoadTexture();
     35 
     36  private:
     37   bool scissor_;
     38   uint32_t texture_base_[WINDOW_HEIGHT*WINDOW_WIDTH];
     39   uint32_t texture_update_[WINDOW_HEIGHT*WINDOW_WIDTH];
     40   GLuint compositing_textures_[5];
     41   GLuint compositing_background_program_;
     42   GLuint compositing_foreground_program_;
     43   DISALLOW_COPY_AND_ASSIGN(WindowManagerCompositingTest);
     44 };
     45 
     46 TestBase* GetWindowManagerCompositingTest(bool enable_scissor) {
     47   return new WindowManagerCompositingTest(enable_scissor);
     48 }
     49 
     50 bool WindowManagerCompositingTest::Run() {
     51   const char* testname = "compositing";
     52   if (scissor_) {
     53     glScissor(0, 0, 1, 1);
     54     glEnable(GL_SCISSOR_TEST);
     55     testname = "compositing_no_fill";
     56   }
     57   InitializeCompositing();
     58   RunTest(this, testname, kScreenScaleFactor, WINDOW_WIDTH, WINDOW_HEIGHT, 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 = InitShaderProgram(kBasicTextureVertexShader,
    132                                      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 =
    243     InitShaderProgram(triple_texture_blend_vertex_shader,
    244                       triple_texture_blend_fragment_shader);
    245 
    246   // Set up the texture sampler
    247   int textureSampler0 = glGetUniformLocation(program, "texture_sampler_0");
    248   glUniform1i(textureSampler0, 0);
    249   int textureSampler1 = glGetUniformLocation(program, "texture_sampler_1");
    250   glUniform1i(textureSampler1, 1);
    251   int textureSampler2 = glGetUniformLocation(program, "texture_sampler_2");
    252   glUniform1i(textureSampler2, 2);
    253 
    254   // Set up vertex attribute
    255   int attribute_index = glGetAttribLocation(program, "c1");
    256   glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer);
    257   glVertexAttribPointer(attribute_index, 2, GL_FLOAT, GL_FALSE, 0, NULL);
    258   glEnableVertexAttribArray(attribute_index);
    259 
    260   // Set up texture attributes
    261   attribute_index = glGetAttribLocation(program, "c2");
    262   glBindBuffer(GL_ARRAY_BUFFER, texture_buffer_0);
    263   glVertexAttribPointer(attribute_index, 2, GL_FLOAT, GL_FALSE, 0, NULL);
    264   glEnableVertexAttribArray(attribute_index);
    265 
    266   attribute_index = glGetAttribLocation(program, "c3");
    267   glBindBuffer(GL_ARRAY_BUFFER, texture_buffer_1);
    268   glVertexAttribPointer(attribute_index, 2, GL_FLOAT, GL_FALSE, 0, NULL);
    269   glEnableVertexAttribArray(attribute_index);
    270 
    271   attribute_index = glGetAttribLocation(program, "c4");
    272   glBindBuffer(GL_ARRAY_BUFFER, texture_buffer_2);
    273   glVertexAttribPointer(attribute_index, 2, GL_FLOAT, GL_FALSE, 0, NULL);
    274   glEnableVertexAttribArray(attribute_index);
    275 
    276   return program;
    277 }
    278 
    279 void WindowManagerCompositingTest::InitializeCompositing() {
    280   InitBaseTexture();
    281 
    282   glClearColor(0.f, 0.f, 0.f, 0.f);
    283   glDisable(GL_DEPTH_TEST);
    284   glDisable(GL_BLEND);
    285   glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    286   glDepthFunc(GL_LEQUAL);
    287 
    288   glGenTextures(5, compositing_textures_);
    289   glActiveTexture(GL_TEXTURE0);
    290   for (int i = 0; i < 5; i++) {
    291     glBindTexture(GL_TEXTURE_2D, compositing_textures_[i]);
    292     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
    293                     GL_LINEAR);
    294     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
    295                     GL_LINEAR);
    296   }
    297 
    298   // Set up the vertex arrays for drawing textured quads later on.
    299   GLfloat buffer_vertex[8] = {
    300     -1.f, -1.f,
    301     1.f,  -1.f,
    302     -1.f, 1.f,
    303     1.f,  1.f,
    304   };
    305   GLuint vbo_vertex = SetupVBO(GL_ARRAY_BUFFER,
    306                                sizeof(buffer_vertex), buffer_vertex);
    307 
    308   GLfloat buffer_texture[8] = {
    309     0.f, 0.f,
    310     1.f, 0.f,
    311     0.f, 1.f,
    312     1.f, 1.f,
    313   };
    314   GLuint vbo_texture = SetupVBO(GL_ARRAY_BUFFER,
    315                                 sizeof(buffer_texture), buffer_texture);
    316 
    317   // Set up the static background textures.
    318   UpdateTexture();
    319   UpdateTexture();
    320   UpdateTexture();
    321   // Load these textures into bound texture ids and keep using them
    322   // from there to avoid having to reload this texture every frame
    323   glActiveTexture(GL_TEXTURE0);
    324   glBindTexture(GL_TEXTURE_2D, compositing_textures_[0]);
    325   LoadTexture();
    326   glActiveTexture(GL_TEXTURE1);
    327   glBindTexture(GL_TEXTURE_2D, compositing_textures_[1]);
    328   LoadTexture();
    329   glActiveTexture(GL_TEXTURE2);
    330   glBindTexture(GL_TEXTURE_2D, compositing_textures_[2]);
    331   LoadTexture();
    332 
    333   glActiveTexture(GL_TEXTURE0);
    334   glBindTexture(GL_TEXTURE_2D, compositing_textures_[3]);
    335   UpdateTexture();
    336   LoadTexture();
    337 
    338   glActiveTexture(GL_TEXTURE0);
    339   glBindTexture(GL_TEXTURE_2D, compositing_textures_[4]);
    340   UpdateTexture();
    341   LoadTexture();
    342 
    343   // Set up vertex & fragment shaders.
    344   compositing_background_program_ =
    345       TripleTextureBlendShaderProgram(vbo_vertex,
    346                                       vbo_texture, vbo_texture, vbo_texture);
    347   compositing_foreground_program_ =
    348       BasicTextureShaderProgram(vbo_vertex, vbo_texture);
    349   if (!compositing_background_program_ || !compositing_foreground_program_) {
    350     printf("# Warning: Could not set up compositing shader.\n");
    351   }
    352 }
    353 
    354 void WindowManagerCompositingTest::TeardownCompositing() {
    355   glDeleteProgram(compositing_background_program_);
    356   glDeleteProgram(compositing_foreground_program_);
    357 }
    358 
    359 void WindowManagerCompositingTest::InitBaseTexture() {
    360   for (int y = 0; y < WINDOW_HEIGHT; y++) {
    361     for (int x = 0; x < WINDOW_WIDTH; x++) {
    362       // This color is gray, half alpha.
    363       texture_base_[y*WINDOW_WIDTH+x] = 0x80808080;
    364     }
    365   }
    366 }
    367 
    368 // UpdateTexture simulates Chrome updating tab contents.
    369 // We cause a bunch of read and write cpu memory bandwidth.
    370 // It's a very rough approximation.
    371 void WindowManagerCompositingTest::UpdateTexture() {
    372   memcpy(texture_update_, texture_base_, sizeof(texture_base_));
    373 }
    374 
    375 void WindowManagerCompositingTest::LoadTexture() {
    376   // Use GL_RGBA for compatibility with GLES2.0.
    377   glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA,
    378                WINDOW_WIDTH, WINDOW_HEIGHT, 0,
    379                GL_RGBA, GL_UNSIGNED_BYTE, texture_update_);
    380 }
    381 
    382 } // namespace glbench
    383