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:
WindowManagerCompositingTest(bool scissor)19 WindowManagerCompositingTest(bool scissor)
20 : scissor_(scissor),
21 compositing_background_program_(0),
22 compositing_foreground_program_(0) {}
~WindowManagerCompositingTest()23 virtual ~WindowManagerCompositingTest() {}
24 virtual bool TestFunc(uint64_t iterations);
25 virtual bool Run();
Name() const26 virtual const char* Name() const { return "compositing"; }
IsDrawTest() const27 virtual bool IsDrawTest() const { return true; }
Unit() const28 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
GetWindowManagerCompositingTest(bool enable_scissor)46 TestBase* GetWindowManagerCompositingTest(bool enable_scissor) {
47 return new WindowManagerCompositingTest(enable_scissor);
48 }
49
Run()50 bool 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
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 = 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
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 =
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
InitializeCompositing()279 void 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
TeardownCompositing()354 void WindowManagerCompositingTest::TeardownCompositing() {
355 glDeleteProgram(compositing_background_program_);
356 glDeleteProgram(compositing_foreground_program_);
357 }
358
InitBaseTexture()359 void 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.
UpdateTexture()371 void WindowManagerCompositingTest::UpdateTexture() {
372 memcpy(texture_update_, texture_base_, sizeof(texture_base_));
373 }
374
LoadTexture()375 void 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