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