• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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:
WindowManagerCompositingTest(bool scissor)18   WindowManagerCompositingTest(bool scissor)
19       : scissor_(scissor),
20         compositing_background_program_(0),
21         compositing_foreground_program_(0) {}
~WindowManagerCompositingTest()22   virtual ~WindowManagerCompositingTest() {}
23   virtual bool TestFunc(uint64_t iterations);
24   virtual bool Run();
Name() const25   virtual const char* Name() const { return "compositing"; }
IsDrawTest() const26   virtual bool IsDrawTest() const { return true; }
Unit() const27   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 
GetWindowManagerCompositingTest(bool enable_scissor)45 TestBase* GetWindowManagerCompositingTest(bool enable_scissor) {
46   return new WindowManagerCompositingTest(enable_scissor);
47 }
48 
Run()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 
TestFunc(uint64_t iterations)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 
BasicTextureShaderProgram(GLuint vertex_buffer,GLuint texture_buffer)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
DoubleTextureBlendShaderProgram(GLuint vertex_buffer,GLuint texture_buffer_0,GLuint texture_buffer_1)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
TripleTextureBlendShaderProgram(GLuint vertex_buffer,GLuint texture_buffer_0,GLuint texture_buffer_1,GLuint texture_buffer_2)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 
InitializeCompositing()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 
TeardownCompositing()350 void WindowManagerCompositingTest::TeardownCompositing() {
351   glDeleteProgram(compositing_background_program_);
352   glDeleteProgram(compositing_foreground_program_);
353 }
354 
InitBaseTexture()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.
UpdateTexture()367 void WindowManagerCompositingTest::UpdateTexture() {
368   memcpy(texture_update_, texture_base_, sizeof(texture_base_));
369 }
370 
LoadTexture()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