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 <gflags/gflags.h>
6#include <stdio.h>
7#include <stdlib.h>
8#include <string.h>
9#include <ctime>
10
11#include "base/logging.h"
12#include "base/strings/string_split.h"
13#include "base/strings/string_util.h"
14
15#include "glinterface.h"
16#include "main.h"
17#include "utils.h"
18
19#include "all_tests.h"
20#include "testbase.h"
21
22using std::string;
23using std::vector;
24
25DEFINE_int32(duration, 0,
26             "Run all tests again and again in a loop for at least this many seconds.");
27DEFINE_string(tests, "",
28              "Colon-separated list of tests to run; all tests if omitted.");
29DEFINE_string(blacklist, "", "colon-separated list of tests to disable");
30DEFINE_bool(hasty, false,
31            "Run a smaller set of tests with less accurate results. "
32            "Useful for running in BVT or debugging a failure.  Implies notemp");
33DEFINE_bool(list, false, "List available tests");
34DEFINE_bool(notemp, false, "Skip temperature checking");
35DEFINE_bool(verbose, false, "Print extra debugging messages");
36
37bool g_verbose;
38GLint g_max_texture_size;
39bool g_hasty;
40bool g_notemp;
41
42bool test_is_enabled(glbench::TestBase* test,
43                     const vector<string>& enabled_tests) {
44  if (enabled_tests.empty())
45    return true;
46
47  const char* test_name = test->Name();
48  for (vector<string>::const_iterator i = enabled_tests.begin();
49       i != enabled_tests.end(); ++i) {
50    // This is not very precise, but will do until there's a need for something
51    // more flexible.
52    if (strstr(test_name, i->c_str()))
53      return true;
54  }
55
56  return false;
57}
58
59bool test_is_disabled(glbench::TestBase* test,
60                     const vector<string>& disabled_tests) {
61  if (disabled_tests.empty())
62    return false;
63
64  const char* test_name = test->Name();
65  for (vector<string>::const_iterator i = disabled_tests.begin();
66       i != disabled_tests.end(); ++i) {
67    // This is not very precise, but will do until there's a need for something
68    // more flexible.
69    if (strstr(test_name, i->c_str()))
70      return true;
71  }
72
73  return false;
74}
75
76void printDateTime(void) {
77  struct tm *ttime;
78  time_t tm = time(0);
79  char time_string[64];
80  ttime = localtime(&tm);
81  strftime(time_string, 63, "%c",ttime);
82  printf("# DateTime: %s\n", time_string);
83}
84
85bool PassesSanityCheck(void) {
86  GLint size[2];
87  glGetIntegerv(GL_MAX_VIEWPORT_DIMS, size);
88  printf("# MAX_VIEWPORT_DIMS=(%d, %d)\n", size[0], size[1]);
89  if (size[0] < g_width || size[1] < g_height) {
90    printf("# Error: MAX_VIEWPORT_DIMS=(%d, %d) are too small.\n",
91           size[0], size[1]);
92    return false;
93  }
94  glGetIntegerv(GL_MAX_TEXTURE_SIZE, size);
95  printf("# GL_MAX_TEXTURE_SIZE=%d\n", size[0]);
96  if (size[0] < g_width || size[0] < g_height) {
97    printf("# Error: MAX_TEXTURE_SIZE=%d is too small.\n",
98           size[0]);
99    return false;
100  }
101  g_max_texture_size = size[0];
102
103  return true;
104}
105
106int main(int argc, char *argv[]) {
107  SetBasePathFromArgv0(argv[0], "src");
108  google::ParseCommandLineFlags(&argc, &argv, false);
109
110  g_verbose = FLAGS_verbose;
111
112  g_main_gl_interface.reset(GLInterface::Create());
113  if (!g_main_gl_interface->Init()) {
114    printf("# Error: Failed to initialize %s.\n", argv[0]);
115    return 1;
116  }
117
118  printf("# board_id: %s - %s\n",
119         glGetString(GL_VENDOR), glGetString(GL_RENDERER));
120  if (!PassesSanityCheck())
121    return 1;
122  g_main_gl_interface->Cleanup();
123
124  if (argc == 1) {
125    printf("# Usage: %s [-save [-outdir=<directory>]] to save images\n", argv[0]);
126  } else {
127    printf("# Running: ");
128    for (int i = 0; i < argc; i++) printf("%s ", argv[i]);
129    printf("\n");
130  }
131  printDateTime();
132
133  g_hasty = FLAGS_hasty;
134  g_notemp = FLAGS_notemp || g_hasty;
135
136  if (!g_notemp)
137    g_initial_temperature = GetMachineTemperature();
138
139  vector<string> enabled_tests =
140      base::SplitString(FLAGS_tests, ":", base::TRIM_WHITESPACE,
141                        base::SPLIT_WANT_ALL);
142  vector<string> disabled_tests =
143      base::SplitString(FLAGS_blacklist, ":", base::TRIM_WHITESPACE,
144                        base::SPLIT_WANT_ALL);
145
146  glbench::TestBase* tests[] = {
147    // Please add new tests at the end of this list as tests are known to bleed
148    // state. Reordering them or inserting a new test may cause a change in the
149    // output images and MD5 causing graphics_GLBench failures.
150    // TODO(ihf): Fix this.
151    glbench::GetSwapTest(),
152    glbench::GetContextTest(),
153    glbench::GetClearTest(),
154    glbench::GetFillRateTest(),
155    glbench::GetWindowManagerCompositingTest(false),
156    glbench::GetWindowManagerCompositingTest(true),
157    glbench::GetTriangleSetupTest(),
158    glbench::GetYuvToRgbTest(),
159    glbench::GetReadPixelTest(),
160    glbench::GetAttributeFetchShaderTest(),
161    glbench::GetVaryingsAndDdxyShaderTest(),
162    glbench::GetTextureReuseTest(),
163    glbench::GetTextureUpdateTest(),
164    glbench::GetTextureUploadTest(),
165    glbench::GetFboFillRateTest(),
166  };
167
168  if (FLAGS_list) {
169    for (unsigned int i = 0; i < arraysize(tests); i++)
170      printf("%s\n", tests[i]->Name());
171    return 0;
172  }
173
174  uint64_t done = GetUTime() + 1000000ULL * FLAGS_duration;
175  do {
176    for (unsigned int i = 0; i < arraysize(tests); i++) {
177      if (!test_is_enabled(tests[i], enabled_tests) ||
178          test_is_disabled(tests[i], disabled_tests))
179        continue;
180      if (!g_main_gl_interface->Init()) {
181        printf("Initialize failed\n");
182        return 1;
183      }
184      glbench::ClearBuffers();
185      tests[i]->Run();
186      g_main_gl_interface->Cleanup();
187    }
188  } while (GetUTime() < done);
189
190  for (unsigned int i = 0; i < arraysize(tests); i++) {
191    delete tests[i];
192    tests[i] = NULL;
193  }
194
195  printDateTime();
196  // Signal to harness that we finished normally.
197  printf("@TEST_END\n");
198
199  return 0;
200}
201