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