OLD | NEW |
1 // Copyright (c) 2010 The Chromium OS Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include <gflags/gflags.h> | 5 #include <gflags/gflags.h> |
| 6 #include <map> |
6 #include <stdio.h> | 7 #include <stdio.h> |
7 #include <stdlib.h> | 8 #include <stdlib.h> |
8 #include <string.h> | 9 #include <string.h> |
9 #include <time.h> | 10 #include <time.h> |
10 | 11 |
11 #include "base/logging.h" | 12 #include "base/logging.h" |
12 | 13 |
13 #include "main.h" | 14 #include "main.h" |
14 #include "utils.h" | 15 #include "utils.h" |
15 #include "xlib_window.h" | 16 #include "xlib_window.h" |
16 | 17 |
17 #include "teartest.h" | 18 #include "teartest.h" |
18 | 19 |
| 20 typedef std::map<const char*, Test*> TestMap; |
19 | 21 |
20 static Pixmap pixmap = 0; | 22 |
21 static int shift_uniform = 0; | |
22 DEFINE_int32(refresh, 0, | 23 DEFINE_int32(refresh, 0, |
23 "If 1 or more, target refresh rate; otherwise enable vsync"); | 24 "If 1 or more, target refresh rate; otherwise enable vsync"); |
24 | 25 |
25 GLuint GenerateAndBindTexture() { | 26 GLuint GenerateAndBindTexture() { |
26 GLuint name = ~0; | 27 GLuint name = ~0; |
27 glGenTextures(1, &name); | 28 glGenTextures(1, &name); |
28 glBindTexture(GL_TEXTURE_2D, name); | 29 glBindTexture(GL_TEXTURE_2D, name); |
29 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); | 30 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); |
30 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); | 31 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); |
31 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); | 32 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); |
(...skipping 10 matching lines...) Expand all Loading... |
42 " gl_TexCoord[0] = vec4(c.y, c.x - shift, 0.0, 0.0);" | 43 " gl_TexCoord[0] = vec4(c.y, c.x - shift, 0.0, 0.0);" |
43 "}"; | 44 "}"; |
44 | 45 |
45 const char *fragment_shader = | 46 const char *fragment_shader = |
46 "uniform sampler2D tex;" | 47 "uniform sampler2D tex;" |
47 "void main() {" | 48 "void main() {" |
48 " gl_FragColor = texture2D(tex, gl_TexCoord[0].xy);" | 49 " gl_FragColor = texture2D(tex, gl_TexCoord[0].xy);" |
49 "}"; | 50 "}"; |
50 | 51 |
51 | 52 |
52 void AllocatePixmap() { | 53 Pixmap AllocatePixmap() { |
53 XWindowAttributes attributes; | 54 XWindowAttributes attributes; |
54 XGetWindowAttributes(g_xlib_display, g_xlib_window, &attributes); | 55 XGetWindowAttributes(g_xlib_display, g_xlib_window, &attributes); |
55 pixmap = XCreatePixmap(g_xlib_display, g_xlib_window, | 56 Pixmap pixmap = XCreatePixmap(g_xlib_display, g_xlib_window, |
56 g_height, g_width, attributes.depth); | 57 g_height, g_width, attributes.depth); |
57 } | |
58 | |
59 void InitializePixmap() { | |
60 GC gc = DefaultGC(g_xlib_display, 0); | 58 GC gc = DefaultGC(g_xlib_display, 0); |
61 XSetForeground(g_xlib_display, gc, 0xffffff); | 59 XSetForeground(g_xlib_display, gc, 0xffffff); |
62 XFillRectangle(g_xlib_display, pixmap, gc, 0, 0, g_height, g_width); | 60 XFillRectangle(g_xlib_display, pixmap, gc, 0, 0, g_height, g_width); |
63 UpdatePixmap(0); | 61 UpdatePixmap(pixmap, 0); |
| 62 return pixmap; |
64 } | 63 } |
65 | 64 |
66 void UpdatePixmap(int i) { | 65 |
| 66 void UpdatePixmap(Pixmap pixmap, int i) { |
67 static int last_i = 0; | 67 static int last_i = 0; |
68 GC gc = DefaultGC(g_xlib_display, 0); | 68 GC gc = DefaultGC(g_xlib_display, 0); |
69 XSetForeground(g_xlib_display, gc, 0xffffff); | 69 XSetForeground(g_xlib_display, gc, 0xffffff); |
70 XDrawLine(g_xlib_display, pixmap, gc, | 70 XDrawLine(g_xlib_display, pixmap, gc, |
71 0, last_i, g_height - 1, last_i); | 71 0, last_i, g_height - 1, last_i); |
72 XDrawLine(g_xlib_display, pixmap, gc, | 72 XDrawLine(g_xlib_display, pixmap, gc, |
73 0, last_i + 4, g_height - 1, last_i + 4); | 73 0, last_i + 4, g_height - 1, last_i + 4); |
74 | 74 |
75 XSetForeground(g_xlib_display, gc, 0x000000); | 75 XSetForeground(g_xlib_display, gc, 0x000000); |
76 XDrawLine(g_xlib_display, pixmap, gc, 0, i, g_height - 1, i); | 76 XDrawLine(g_xlib_display, pixmap, gc, 0, i, g_height - 1, i); |
77 XDrawLine(g_xlib_display, pixmap, gc, 0, i + 4, g_height - 1, i + 4); | 77 XDrawLine(g_xlib_display, pixmap, gc, 0, i + 4, g_height - 1, i + 4); |
78 | 78 |
79 last_i = i; | 79 last_i = i; |
80 } | 80 } |
81 | 81 |
82 void CopyPixmapToTexture() { | 82 |
| 83 void CopyPixmapToTexture(Pixmap pixmap) { |
83 XImage *xim = XGetImage(g_xlib_display, pixmap, 0, 0, g_height, g_width, | 84 XImage *xim = XGetImage(g_xlib_display, pixmap, 0, 0, g_height, g_width, |
84 AllPlanes, ZPixmap); | 85 AllPlanes, ZPixmap); |
85 CHECK(xim != NULL); | 86 CHECK(xim != NULL); |
86 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, g_height, g_width, 0, | 87 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, g_height, g_width, 0, |
87 GL_RGBA, GL_UNSIGNED_BYTE, (void*)(&xim->data[0])); | 88 GL_RGBA, GL_UNSIGNED_BYTE, (void*)(&xim->data[0])); |
88 XDestroyImage(xim); | 89 XDestroyImage(xim); |
89 } | 90 } |
90 | 91 |
91 | 92 |
92 bool UpdateUniform(TestState state, int shift) { | 93 // This test needs shift_uniform from outside, don't add it right away. |
93 switch (state) { | 94 class UniformTest : public Test { |
94 case TestStart: | 95 public: |
95 printf("# Plain texture draw.\n"); | 96 UniformTest() : pixmap_(0), shift_uniform_(-1) {} |
96 InitializePixmap(); | 97 virtual bool Start() { |
97 CopyPixmapToTexture(); | 98 printf("# Plain texture draw.\n"); |
98 break; | 99 pixmap_ = AllocatePixmap(); |
| 100 CopyPixmapToTexture(pixmap_); |
| 101 return true; |
| 102 } |
99 | 103 |
100 case TestLoop: | 104 virtual bool Loop(int shift) { |
101 glUniform1f(shift_uniform, 1.f / g_width * shift); | 105 glUniform1f(shift_uniform_, 1.f / g_width * shift); |
102 break; | 106 return true; |
| 107 } |
103 | 108 |
104 case TestStop: | 109 virtual void Stop() { |
105 glUniform1f(shift_uniform, 0.f); | 110 glUniform1f(shift_uniform_, 0.f); |
106 break; | 111 XFreePixmap(g_xlib_display, pixmap_); |
107 } | 112 } |
108 return true; | |
109 } | |
110 | 113 |
111 bool UpdateTexImage2D(TestState state, int shift) { | 114 void SetUniform(int shift_uniform) { |
112 switch (state) { | 115 shift_uniform_ = shift_uniform; |
113 case TestStart: | 116 } |
114 printf("# Full texture update.\n"); | |
115 InitializePixmap(); | |
116 CopyPixmapToTexture(); | |
117 break; | |
118 | 117 |
119 case TestLoop: { | 118 private: |
120 UpdatePixmap(shift); | 119 Pixmap pixmap_; |
121 // TODO: it's probably much cheaper to not use Pixmap and XImage. | 120 int shift_uniform_; |
122 CopyPixmapToTexture(); | 121 }; |
123 } | |
124 | 122 |
125 case TestStop: | 123 Test* GetUniformTest(int uniform) { |
126 break; | 124 UniformTest* ret = new UniformTest(); |
127 } | 125 ret->SetUniform(uniform); |
128 return true; | 126 return ret; |
129 } | 127 } |
130 | 128 |
131 | 129 |
132 Test test[] = { | 130 class TexImage2DTest : public Test { |
133 UpdateUniform, | 131 public: |
134 UpdateTexImage2D, | 132 TexImage2DTest() : pixmap_(0) {} |
135 UpdateBindTexImage | 133 virtual bool Start() { |
| 134 printf("# Full texture update.\n"); |
| 135 pixmap_ = AllocatePixmap(); |
| 136 CopyPixmapToTexture(pixmap_); |
| 137 return true; |
| 138 } |
| 139 |
| 140 virtual bool Loop(int shift) { |
| 141 UpdatePixmap(pixmap_, shift); |
| 142 // TODO: it's probably much cheaper to not use Pixmap and XImage. |
| 143 CopyPixmapToTexture(pixmap_); |
| 144 return true; |
| 145 } |
| 146 |
| 147 virtual void Stop() { |
| 148 XFreePixmap(g_xlib_display, pixmap_); |
| 149 } |
| 150 |
| 151 private: |
| 152 Pixmap pixmap_; |
136 }; | 153 }; |
137 | 154 |
| 155 Test* GetTexImage2DTest() { |
| 156 return new TexImage2DTest(); |
| 157 } |
| 158 |
| 159 |
138 int main(int argc, char* argv[]) { | 160 int main(int argc, char* argv[]) { |
139 struct timespec* sleep_duration = NULL; | 161 struct timespec* sleep_duration = NULL; |
140 g_height = -1; | 162 g_height = -1; |
| 163 TestMap test_map; |
| 164 |
141 google::ParseCommandLineFlags(&argc, &argv, true); | 165 google::ParseCommandLineFlags(&argc, &argv, true); |
142 if (FLAGS_refresh >= 1) { | 166 if (FLAGS_refresh >= 1) { |
143 sleep_duration = new struct timespec; | 167 sleep_duration = new struct timespec; |
144 sleep_duration->tv_sec = 0; | 168 sleep_duration->tv_sec = 0; |
145 sleep_duration->tv_nsec = static_cast<long>(1.e9 / FLAGS_refresh); | 169 sleep_duration->tv_nsec = static_cast<long>(1.e9 / FLAGS_refresh); |
146 } | 170 } |
147 if (!Init()) { | 171 if (!Init()) { |
148 printf("# Failed to initialize.\n"); | 172 printf("# Failed to initialize.\n"); |
149 return 1; | 173 return 1; |
150 } | 174 } |
151 | 175 |
152 InitContext(); | 176 InitContext(); |
153 glViewport(-g_width, -g_height, g_width*2, g_height*2); | 177 glViewport(-g_width, -g_height, g_width*2, g_height*2); |
154 | 178 |
155 GLuint texture = GenerateAndBindTexture(); | 179 GLuint texture = GenerateAndBindTexture(); |
156 | 180 |
157 AllocatePixmap(); | |
158 InitNative(pixmap); | |
159 | |
160 GLfloat vertices[8] = { | 181 GLfloat vertices[8] = { |
161 0.f, 0.f, | 182 0.f, 0.f, |
162 1.f, 0.f, | 183 1.f, 0.f, |
163 0.f, 1.f, | 184 0.f, 1.f, |
164 1.f, 1.f, | 185 1.f, 1.f, |
165 }; | 186 }; |
166 | 187 |
167 GLuint program = InitShaderProgram(vertex_shader, fragment_shader); | 188 GLuint program = InitShaderProgram(vertex_shader, fragment_shader); |
168 int attribute_index = glGetAttribLocation(program, "c"); | 189 int attribute_index = glGetAttribLocation(program, "c"); |
169 glVertexAttribPointer(attribute_index, 2, GL_FLOAT, GL_FALSE, 0, vertices); | 190 glVertexAttribPointer(attribute_index, 2, GL_FLOAT, GL_FALSE, 0, vertices); |
170 glEnableVertexAttribArray(attribute_index); | 191 glEnableVertexAttribArray(attribute_index); |
171 | 192 |
172 int texture_sampler = glGetUniformLocation(program, "tex"); | 193 int texture_sampler = glGetUniformLocation(program, "tex"); |
173 glUniform1f(texture_sampler, 0); | 194 glUniform1f(texture_sampler, 0); |
174 | 195 |
175 shift_uniform = glGetUniformLocation(program, "shift"); | 196 // UniformTest needs a uniform from the shader program. Get the uniform |
| 197 // and instantiate the test. |
| 198 Test* uniform_test = GetUniformTest(glGetUniformLocation(program, "shift")); |
| 199 test_map["uniform"] = uniform_test; |
| 200 test_map["teximage2d"] = GetTexImage2DTest(); |
| 201 #ifdef USE_EGL |
| 202 test_map["pixmap_to_texture"] = GetPixmapToTextureTestEGL(); |
| 203 #else |
| 204 test_map["pixmap_to_texture"] = GetPixmapToTextureTest(); |
| 205 #endif |
| 206 |
176 SwapInterval(sleep_duration ? 0 : 1); | 207 SwapInterval(sleep_duration ? 0 : 1); |
177 | 208 |
178 for (unsigned int i = 0; i < sizeof(test)/sizeof(*test); i++) | 209 for (TestMap::iterator it = test_map.begin(); it != test_map.end(); it++) { |
179 { | 210 Test* t = it->second; |
180 XEvent event; | 211 if (!t->Start()) |
181 if (!test[i](TestStart, 0)) | |
182 continue; | 212 continue; |
183 | 213 |
184 Bool got_event = False; | 214 Bool got_event = False; |
185 for (int x = 0; !got_event; x = (x + 4) % (2 * g_width)) { | 215 for (int x = 0; !got_event; x = (x + 4) % (2 * g_width)) { |
186 const int shift = x < g_width ? x : 2 * g_width - x; | 216 const int shift = x < g_width ? x : 2 * g_width - x; |
187 | 217 |
188 test[i](TestLoop, shift); | 218 t->Loop(shift); |
189 | 219 |
190 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); | 220 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); |
191 glFlush(); | 221 glFlush(); |
192 | 222 |
193 if (sleep_duration) | 223 if (sleep_duration) |
194 nanosleep(sleep_duration, NULL); | 224 nanosleep(sleep_duration, NULL); |
195 | 225 |
196 SwapBuffers(); | 226 SwapBuffers(); |
197 | 227 |
| 228 XEvent event; |
198 got_event = XCheckWindowEvent(g_xlib_display, g_xlib_window, | 229 got_event = XCheckWindowEvent(g_xlib_display, g_xlib_window, |
199 KeyPressMask, &event); | 230 KeyPressMask, &event); |
200 } | 231 } |
201 | 232 |
202 test[i](TestStop, 0); | 233 t->Stop(); |
203 } | 234 } |
204 | 235 |
205 // TODO: clean teardown. | 236 // TODO: cleaner teardown. |
206 | 237 |
207 glDeleteTextures(1, &texture); | 238 glDeleteTextures(1, &texture); |
208 DestroyContext(); | 239 DestroyContext(); |
209 return 0; | 240 return 0; |
210 } | 241 } |
OLD | NEW |