Home | History | Annotate | Download | only in src
      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 <fcntl.h>
      6 #include <stdio.h>
      7 #include <string.h>
      8 #include <sys/mman.h>
      9 #include <sys/stat.h>
     10 #include <unistd.h>
     11 
     12 #include "base/logging.h"
     13 
     14 #include "glinterface.h"
     15 #include "main.h"
     16 #include "utils.h"
     17 
     18 using base::FilePath;
     19 
     20 const char* kGlesHeader =
     21     "#ifdef GL_ES\n"
     22     "precision highp float;\n"
     23     "#endif\n";
     24 
     25 FilePath *g_base_path = new FilePath();
     26 double g_initial_temperature = -1000.0;
     27 const char* TEMPERATURE_SCRIPT_PATH = "/usr/local/autotest/bin/temperature.py";
     28 
     29 // Sets the base path for MmapFile to `dirname($argv0)`/$relative.
     30 void SetBasePathFromArgv0(const char* argv0, const char* relative) {
     31   if (g_base_path) {
     32     delete g_base_path;
     33   }
     34   FilePath argv0_path = FilePath(argv0).DirName();
     35   FilePath base_path = relative ? argv0_path.Append(relative) : argv0_path;
     36   g_base_path = new FilePath(base_path);
     37 }
     38 
     39 const FilePath& GetBasePath() {
     40   return *g_base_path;
     41 }
     42 
     43 void *MmapFile(const char* name, size_t* length) {
     44   FilePath filename = g_base_path->Append(name);
     45   int fd = open(filename.value().c_str(), O_RDONLY);
     46   if (fd == -1)
     47     return NULL;
     48 
     49   struct stat sb;
     50   CHECK(fstat(fd, &sb) != -1);
     51 
     52   char *mmap_ptr = static_cast<char *>(
     53     mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0));
     54 
     55   close(fd);
     56 
     57   if (mmap_ptr)
     58     *length = sb.st_size;
     59 
     60   return mmap_ptr;
     61 }
     62 
     63 bool read_int_from_file(FilePath filename, int *value) {
     64   FILE *fd = fopen(filename.value().c_str(), "r");
     65   if (!fd) {
     66     return false;
     67   }
     68   int count = fscanf(fd, "%d", value);
     69   if (count != 1) {
     70     printf("Error: could not read integer from file. (%s)\n",
     71            filename.value().c_str());
     72     if(count != 1)
     73       return false;
     74   }
     75   fclose(fd);
     76   return true;
     77 }
     78 
     79 bool read_float_from_cmd_output(const char *command, double *value) {
     80   FILE *fd = popen(command, "r");
     81   if (!fd) {
     82     printf("Error: could not popen command. (%s)\n", command);
     83     return false;
     84   }
     85   int count = fscanf(fd, "%lf", value);
     86   if (count != 1) {
     87     printf("Error: could not read float from command output. (%s)\n",
     88            command);
     89     return false;
     90   }
     91   pclose(fd);
     92   return true;
     93 }
     94 
     95 // Returns temperature at which CPU gets throttled.
     96 double get_temperature_critical() {
     97   char command[1024];
     98   sprintf(command, "%s %s", TEMPERATURE_SCRIPT_PATH, "--critical");
     99   double temperature_Celsius = 0.0;
    100   if (!read_float_from_cmd_output(command, &temperature_Celsius)) {
    101     // 85'C is the minimum observed critical temperature so far.
    102     printf("Warning: guessing critical temperature as 85'C.\n");
    103     return 85.0;
    104   }
    105   // Simple sanity check for reasonable critical temperatures.
    106   assert(temperature_Celsius >= 60.0);
    107   assert(temperature_Celsius <= 150.0);
    108   return temperature_Celsius;
    109 }
    110 
    111 
    112 // Returns currently measured temperature.
    113 double get_temperature_input() {
    114   char command[1024];
    115   sprintf(command, "%s %s", TEMPERATURE_SCRIPT_PATH, "--maximum");
    116   double temperature_Celsius = -1000.0;
    117   read_float_from_cmd_output(command, &temperature_Celsius);
    118 
    119   if (temperature_Celsius < 10.0 || temperature_Celsius > 150.0) {
    120     printf("Warning: ignoring temperature reading of %f'C.\n",
    121            temperature_Celsius);
    122   }
    123 
    124   return temperature_Celsius;
    125 }
    126 
    127 const double GetInitialMachineTemperature() {
    128   return g_initial_temperature;
    129 }
    130 
    131 double GetMachineTemperature() {
    132   double max_temperature = get_temperature_input();
    133   return max_temperature;
    134 }
    135 
    136 // Waits up to timeout seconds to reach cold_temperature in Celsius.
    137 double WaitForCoolMachine(double cold_temperature, double timeout,
    138                           double *temperature) {
    139   // Integer times are in micro-seconds.
    140   uint64_t time_start = GetUTime();
    141   uint64_t time_now = time_start;
    142   uint64_t time_end = time_now + 1e6 * timeout;
    143   *temperature = GetMachineTemperature();
    144   while (time_now < time_end) {
    145     if (*temperature < cold_temperature)
    146       break;
    147     sleep(1.0);
    148     time_now = GetUTime();
    149     *temperature = GetMachineTemperature();
    150   }
    151   double wait_time = 1.0e-6 * (time_now - time_start);
    152   assert(wait_time >= 0);
    153   assert(wait_time < timeout + 5.0);
    154   return wait_time;
    155 }
    156 
    157 namespace glbench {
    158 
    159 GLuint SetupTexture(GLsizei size_log2) {
    160   GLsizei size = 1 << size_log2;
    161   GLuint name = ~0;
    162   glGenTextures(1, &name);
    163   glBindTexture(GL_TEXTURE_2D, name);
    164   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    165   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
    166 
    167   unsigned char *pixels = new unsigned char[size * size * 4];
    168   if (!pixels)
    169     return 0;
    170 
    171   for (GLint level = 0; size > 0; level++, size /= 2) {
    172     unsigned char *p = pixels;
    173     for (int i = 0; i < size; i++) {
    174       for (int j = 0; j < size; j++) {
    175         *p++ = level %3 != 0 ? (i ^ j) << level : 0;
    176         *p++ = level %3 != 1 ? (i ^ j) << level : 0;
    177         *p++ = level %3 != 2 ? (i ^ j) << level : 0;
    178         *p++ = 255;
    179       }
    180     }
    181     if (size == 1) {
    182       unsigned char *p = pixels;
    183       *p++ = 255;
    184       *p++ = 255;
    185       *p++ = 255;
    186       *p++ = 255;
    187     }
    188     glTexImage2D(GL_TEXTURE_2D, level, GL_RGBA, size, size, 0,
    189                  GL_RGBA, GL_UNSIGNED_BYTE, pixels);
    190   }
    191   delete[] pixels;
    192   return name;
    193 }
    194 
    195 GLuint SetupVBO(GLenum target, GLsizeiptr size, const GLvoid *data) {
    196   GLuint buf = ~0;
    197   glGenBuffers(1, &buf);
    198   glBindBuffer(target, buf);
    199   glBufferData(target, size, data, GL_STATIC_DRAW);
    200   CHECK(!glGetError());
    201   return buf;
    202 }
    203 
    204 // Generates a lattice symmetric around the origin (all quadrants).
    205 void CreateLattice(GLfloat **vertices, GLsizeiptr *size,
    206                    GLfloat size_x, GLfloat size_y, int width, int height)
    207 {
    208   GLfloat *vptr = *vertices = new GLfloat[2 * (width + 1) * (height + 1)];
    209   GLfloat shift_x = size_x * width;
    210   GLfloat shift_y = size_y * height;
    211   for (int j = 0; j <= height; j++) {
    212     for (int i = 0; i <= width; i++) {
    213       *vptr++ = 2 * i * size_x - shift_x;
    214       *vptr++ = 2 * j * size_y - shift_y;
    215     }
    216   }
    217   *size = (vptr - *vertices) * sizeof(GLfloat);
    218 }
    219 
    220 // Generates a mesh of 2*width*height triangles.  The ratio of front facing to
    221 // back facing triangles is culled_ratio/RAND_MAX.  Returns the number of
    222 // vertices in the mesh.
    223 int CreateMesh(GLushort **indices, GLsizeiptr *size,
    224                int width, int height, int culled_ratio) {
    225   srand(0);
    226 
    227   // We use 16 bit indices for compatibility with GL ES
    228   CHECK(height * width + width + height <= 65535);
    229 
    230   GLushort *iptr = *indices = new GLushort[2 * 3 * (width * height)];
    231   const int swath_height = 4;
    232 
    233   CHECK(width % swath_height == 0 && height % swath_height == 0);
    234 
    235   for (int j = 0; j < height; j += swath_height) {
    236     for (int i = 0; i < width; i++) {
    237       for (int j2 = 0; j2 < swath_height; j2++) {
    238         GLushort first = (j + j2) * (width + 1) + i;
    239         GLushort second = first + 1;
    240         GLushort third = first + (width + 1);
    241         GLushort fourth = third + 1;
    242 
    243         bool flag = rand() < culled_ratio;
    244         *iptr++ = first;
    245         *iptr++ = flag ? second : third;
    246         *iptr++ = flag ? third : second;
    247 
    248         *iptr++ = fourth;
    249         *iptr++ = flag ? third : second;
    250         *iptr++ = flag ? second : third;
    251       }
    252     }
    253   }
    254   *size = (iptr - *indices) * sizeof(GLushort);
    255 
    256   return iptr - *indices;
    257 }
    258 
    259 static void print_info_log(int obj, bool shader)
    260 {
    261   char info_log[4096];
    262   int length;
    263 
    264   if (shader)
    265     glGetShaderInfoLog(obj, sizeof(info_log)-1, &length, info_log);
    266   else
    267     glGetProgramInfoLog(obj, sizeof(info_log)-1, &length, info_log);
    268 
    269   char *p = info_log;
    270   while (p < info_log + length) {
    271     char *newline = strchr(p, '\n');
    272     if (newline)
    273       *newline = '\0';
    274     printf("# Info: glGet%sInfoLog: %s\n", shader ? "Shader" : "Program", p);
    275     if (!newline)
    276       break;
    277     p = newline + 1;
    278   }
    279 }
    280 
    281 static void print_shader_log(int shader)
    282 {
    283   print_info_log(shader, true);
    284 }
    285 
    286 static void print_program_log(int program)
    287 {
    288   print_info_log(program, false);
    289 }
    290 
    291 
    292 GLuint InitShaderProgram(const char *vertex_src, const char *fragment_src) {
    293   return InitShaderProgramWithHeader(NULL, vertex_src, fragment_src);
    294 }
    295 
    296 GLuint InitShaderProgramWithHeader(const char* header,
    297                                    const char* vertex_src,
    298                                    const char* fragment_src) {
    299   const char* headers[] = {kGlesHeader, header};
    300   return InitShaderProgramWithHeaders(headers,
    301                                       arraysize(headers) - (header ? 0 : 1),
    302                                       vertex_src, fragment_src);
    303 }
    304 
    305 GLuint InitShaderProgramWithHeaders(const char** headers,
    306                                     int count,
    307                                     const char* vertex_src,
    308                                     const char* fragment_src) {
    309   GLuint vertex_shader = glCreateShader(GL_VERTEX_SHADER);
    310   GLuint fragment_shader = glCreateShader(GL_FRAGMENT_SHADER);
    311 
    312   const char** header_and_body = new const char*[count + 1];
    313   if (count != 0)
    314     memcpy(header_and_body, headers, count * sizeof(const char*));
    315   header_and_body[count] = vertex_src;
    316   glShaderSource(vertex_shader, count + 1, header_and_body, NULL);
    317   header_and_body[count] = fragment_src;
    318   glShaderSource(fragment_shader, count + 1, header_and_body, NULL);
    319   delete[] header_and_body;
    320 
    321   glCompileShader(vertex_shader);
    322   print_shader_log(vertex_shader);
    323   glCompileShader(fragment_shader);
    324   print_shader_log(fragment_shader);
    325 
    326   GLuint program = glCreateProgram();
    327   glAttachShader(program, vertex_shader);
    328   glAttachShader(program, fragment_shader);
    329   glLinkProgram(program);
    330   print_program_log(program);
    331   glUseProgram(program);
    332 
    333   glDeleteShader(vertex_shader);
    334   glDeleteShader(fragment_shader);
    335 
    336   return program;
    337 }
    338 
    339 void ClearBuffers() {
    340   glClearColor(1.f, 0, 0, 1.f);
    341   glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
    342   g_main_gl_interface->SwapBuffers();
    343   glClearColor(0, 1.f, 0, 1.f);
    344   glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
    345   g_main_gl_interface->SwapBuffers();
    346   glClearColor(0, 0, 0.f, 1.f);
    347 }
    348 
    349 } // namespace glbench
    350