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