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 // Application that displays graphics using OpenGL [ES] with the intent 6 // of being used in functional tests. 7 8 #include <gflags/gflags.h> 9 #include <stdio.h> 10 #include <stdlib.h> 11 #include <string.h> 12 #include <time.h> 13 14 #include <cmath> 15 16 #include "glinterface.h" 17 #include "main.h" 18 #include "utils.h" 19 20 21 GLuint GenerateAndBindTexture() { 22 GLuint name = ~0; 23 glGenTextures(1, &name); 24 glBindTexture(GL_TEXTURE_2D, name); 25 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 26 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 27 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); 28 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 29 return name; 30 } 31 32 unsigned char* CreateBitmap(int w, int h) { 33 unsigned char* bitmap = new unsigned char[4 * w * h]; 34 unsigned char* pixel = bitmap; 35 float w2 = 0.5f * w; 36 float h2 = 0.5f * h; 37 for (int y = 0; y < h; y++) { 38 for (int x = 0; x < w; x++) { 39 // Fill with soft ellipse 40 float dx = fabs((x - w2) / w2); 41 float dy = fabs((y - h2) / h2); 42 float dist2 = dx*dx + dy*dy; 43 if (dist2 > 1.f) 44 dist2 = 1.f; 45 *pixel = (1.f - dist2) * 255.f; 46 pixel++; 47 *pixel = (1.f - dist2) * 255.f; 48 pixel++; 49 *pixel = (1.f - dist2) * 255.f; 50 pixel++; 51 *pixel = 0; 52 pixel++; 53 } 54 } 55 return bitmap; 56 } 57 58 59 const char kVertexShader[] = 60 "attribute vec4 vertices;" 61 "varying vec2 v1;" 62 "void main() {" 63 " gl_Position = vec4(vertices.x, vertices.y, 0.0, 1.0);" 64 " v1 = vec2(0.5 * vertices.x + 0.5, 0.5 * vertices.y + 0.5);" 65 "}"; 66 67 const char kFragmentShader[] = 68 "uniform sampler2D tex;" 69 "uniform vec4 color;" 70 "varying vec2 v1;" 71 "void main() {" 72 " gl_FragColor = color * texture2D(tex, v1);" 73 "}"; 74 75 // Command line flags 76 DEFINE_double(screenshot1_sec, 2.f, "seconds delay before screenshot1_cmd"); 77 DEFINE_double(screenshot2_sec, 1.f, "seconds delay before screenshot2_cmd"); 78 DEFINE_string(screenshot1_cmd, "", "system command to take a screen shot 1"); 79 DEFINE_string(screenshot2_cmd, "", "system command to take a screen shot 2"); 80 DEFINE_double(cooldown_sec, 1.f, "seconds delay after all screenshots"); 81 82 int main(int argc, char* argv[]) { 83 // Configure full screen 84 g_width = -1; 85 g_height = -1; 86 87 google::ParseCommandLineFlags(&argc, &argv, true); 88 89 g_main_gl_interface.reset(GLInterface::Create()); 90 if (!g_main_gl_interface->Init()) { 91 printf("# Error: Failed to initialize %s.\n", argv[0]); 92 return 1; 93 } 94 95 GLint viewport[2]; 96 glGetIntegerv(GL_MAX_VIEWPORT_DIMS, viewport); 97 printf("# MAX_VIEWPORT_DIMS=(%d, %d)\n", viewport[0], viewport[1]); 98 if (viewport[0] < g_width || viewport[1] < g_height) { 99 printf("# Error: MAX_VIEWPORT_DIMS too small\n"); 100 return 1; 101 } 102 glViewport(0, 0, g_width, g_height); 103 104 unsigned char* bitmap = CreateBitmap(g_height, g_width); 105 GLuint texture = GenerateAndBindTexture(); 106 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, g_height, g_width, 0, 107 GL_RGBA, GL_UNSIGNED_BYTE, bitmap); 108 109 GLfloat vertices[8] = { 110 -1.f, -1.f, 111 1.f, -1.f, 112 -1.f, 1.f, 113 1.f, 1.f, 114 }; 115 116 GLuint program = glbench::InitShaderProgram(kVertexShader, kFragmentShader); 117 int attribute_index = glGetAttribLocation(program, "vertices"); 118 glVertexAttribPointer(attribute_index, 2, GL_FLOAT, GL_FALSE, 0, vertices); 119 glEnableVertexAttribArray(attribute_index); 120 121 int texture_sampler = glGetUniformLocation(program, "tex"); 122 glUniform1i(texture_sampler, 0); 123 124 int display_color = glGetUniformLocation(program, "color"); 125 float white[4] = {1.0f, 1.0f, 1.0f, 1.0f}; 126 float blue[4] = {0.5f, 0.5f, 1.0f, 1.0f}; 127 128 uint64_t last_event_time = GetUTime(); 129 enum State { 130 kStateScreenShot1, 131 kStateScreenShot2, 132 kStateCooldown, 133 kStateExit 134 } state = kStateScreenShot1; 135 float seconds_delay_for_next_state[] = { 136 static_cast<float>(FLAGS_screenshot1_sec), 137 static_cast<float>(FLAGS_screenshot2_sec), 138 static_cast<float>(FLAGS_cooldown_sec), 139 0 140 }; 141 142 do { 143 // Draw 144 glClear(GL_COLOR_BUFFER_BIT); 145 if (state == kStateScreenShot1) 146 glUniform4fv(display_color, 1, white); 147 else 148 glUniform4fv(display_color, 1, blue); 149 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); 150 g_main_gl_interface->SwapBuffers(); 151 // Loop until next event 152 float seconds_since_last_event = 153 static_cast<float>(GetUTime() - last_event_time) / 1000000ULL; 154 if (seconds_since_last_event < seconds_delay_for_next_state[state]) 155 continue; 156 157 // State change. Perform action. 158 switch(state) { 159 case kStateScreenShot1: 160 system(FLAGS_screenshot1_cmd.c_str()); 161 break; 162 case kStateScreenShot2: 163 system(FLAGS_screenshot2_cmd.c_str()); 164 break; 165 default: 166 break; 167 } 168 169 // Advance to next state 170 last_event_time = GetUTime(); 171 state = static_cast<State>(state + 1); 172 173 } while (state != kStateExit); 174 175 glDeleteTextures(1, &texture); 176 g_main_gl_interface->Cleanup(); 177 return 0; 178 } 179