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