• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.
SetBasePathFromArgv0(const char * argv0,const char * 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 
GetBasePath()39 const FilePath& GetBasePath() {
40   return *g_base_path;
41 }
42 
MmapFile(const char * name,size_t * length)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 
read_int_from_file(FilePath filename,int * value)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 
read_float_from_cmd_output(const char * command,double * value)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.
get_temperature_critical()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.
get_temperature_input()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 
GetInitialMachineTemperature()127 const double GetInitialMachineTemperature() {
128   return g_initial_temperature;
129 }
130 
GetMachineTemperature()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.
WaitForCoolMachine(double cold_temperature,double timeout,double * temperature)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 
SetupTexture(GLsizei size_log2)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 
SetupVBO(GLenum target,GLsizeiptr size,const GLvoid * data)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).
CreateLattice(GLfloat ** vertices,GLsizeiptr * size,GLfloat size_x,GLfloat size_y,int width,int height)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.
CreateMesh(GLushort ** indices,GLsizeiptr * size,int width,int height,int culled_ratio)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 
print_info_log(int obj,bool shader)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 
print_shader_log(int shader)281 static void print_shader_log(int shader)
282 {
283   print_info_log(shader, true);
284 }
285 
print_program_log(int program)286 static void print_program_log(int program)
287 {
288   print_info_log(program, false);
289 }
290 
291 
InitShaderProgram(const char * vertex_src,const char * fragment_src)292 GLuint InitShaderProgram(const char *vertex_src, const char *fragment_src) {
293   return InitShaderProgramWithHeader(NULL, vertex_src, fragment_src);
294 }
295 
InitShaderProgramWithHeader(const char * header,const char * vertex_src,const char * fragment_src)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 
InitShaderProgramWithHeaders(const char ** headers,int count,const char * vertex_src,const char * fragment_src)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 
ClearBuffers()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