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