| 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 |