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 12namespace glbench { 13 14const float kScreenScaleFactor = 1e6f * (WINDOW_WIDTH * WINDOW_HEIGHT) / 15 (1280.f * 768); 16 17class 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 46TestBase* GetWindowManagerCompositingTest(bool enable_scissor) { 47 return new WindowManagerCompositingTest(enable_scissor); 48} 49 50bool 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 63bool 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 114const 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 123const char *kBasicTextureFragmentShader = 124 "uniform sampler2D texture_sampler;" 125 "varying vec4 v1;" 126 "void main() {" 127 " gl_FragColor = texture2D(texture_sampler, v1.st);" 128 "}"; 129 130GLuint 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 153const 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 165const 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 177GLuint 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 208const 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 223const 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 238GLuint 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 279void 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 354void WindowManagerCompositingTest::TeardownCompositing() { 355 glDeleteProgram(compositing_background_program_); 356 glDeleteProgram(compositing_foreground_program_); 357} 358 359void 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. 371void WindowManagerCompositingTest::UpdateTexture() { 372 memcpy(texture_update_, texture_base_, sizeof(texture_base_)); 373} 374 375void 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