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 <stdio.h> | 5 #include <stdio.h> |
6 #include <stdlib.h> | 6 #include <stdlib.h> |
7 #include <string.h> | 7 #include <string.h> |
8 #include <time.h> | 8 #include <time.h> |
9 | 9 |
| 10 #include "base/logging.h" |
| 11 |
10 #include "main.h" | 12 #include "main.h" |
11 #include "utils.h" | 13 #include "utils.h" |
12 #include "xlib_window.h" | 14 #include "xlib_window.h" |
13 | 15 |
| 16 #include "teartest.h" |
| 17 |
| 18 |
| 19 static Pixmap pixmap = 0; |
| 20 static int shift_uniform = 0; |
14 | 21 |
15 GLuint GenerateAndBindTexture() { | 22 GLuint GenerateAndBindTexture() { |
16 GLuint name = ~0; | 23 GLuint name = ~0; |
17 glGenTextures(1, &name); | 24 glGenTextures(1, &name); |
18 glBindTexture(GL_TEXTURE_2D, name); | 25 glBindTexture(GL_TEXTURE_2D, name); |
19 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); | 26 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); |
20 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); | 27 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); |
21 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); | 28 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); |
22 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); | 29 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); |
23 return name; | 30 return name; |
24 } | 31 } |
25 | 32 |
26 | 33 |
27 char *CreateBitmap(int w, int h) { | |
28 char *bitmap = new char[w * h]; | |
29 memset(bitmap, 255, w * h); | |
30 memset(bitmap + w * (1 + h / 2), 0, w); | |
31 memset(bitmap + w * (5 + h / 2), 0, w); | |
32 return bitmap; | |
33 } | |
34 | |
35 | |
36 const char *vertex_shader = | 34 const char *vertex_shader = |
37 "attribute vec4 c;" | 35 "attribute vec4 c;" |
38 "uniform float shift;" | 36 "uniform float shift;" |
39 "void main() {" | 37 "void main() {" |
40 " gl_Position = c;" | 38 " gl_Position = c;" |
41 " gl_TexCoord[0] = vec4(c.y, c.x - shift, 0.0, 0.0);" | 39 " gl_TexCoord[0] = vec4(c.y, c.x - shift, 0.0, 0.0);" |
42 "}"; | 40 "}"; |
43 | 41 |
44 const char *fragment_shader = | 42 const char *fragment_shader = |
45 "uniform sampler2D tex;" | 43 "uniform sampler2D tex;" |
(...skipping 22 matching lines...) Expand all Loading... |
68 } | 66 } |
69 } else if (strcmp("-o", argv[i]) == 0) { | 67 } else if (strcmp("-o", argv[i]) == 0) { |
70 g_override_redirect = true; | 68 g_override_redirect = true; |
71 } else if (strcmp("-r", argv[i]) == 0) { | 69 } else if (strcmp("-r", argv[i]) == 0) { |
72 refresh_arg = true; | 70 refresh_arg = true; |
73 } | 71 } |
74 } | 72 } |
75 } | 73 } |
76 | 74 |
77 | 75 |
| 76 void AllocatePixmap() { |
| 77 XWindowAttributes attributes; |
| 78 XGetWindowAttributes(g_xlib_display, g_xlib_window, &attributes); |
| 79 pixmap = XCreatePixmap(g_xlib_display, g_xlib_window, |
| 80 g_height, g_width, attributes.depth); |
| 81 } |
| 82 |
| 83 void InitializePixmap() { |
| 84 GC gc = DefaultGC(g_xlib_display, 0); |
| 85 XSetForeground(g_xlib_display, gc, 0xffffff); |
| 86 XFillRectangle(g_xlib_display, pixmap, gc, 0, 0, g_height, g_width); |
| 87 UpdatePixmap(0); |
| 88 } |
| 89 |
| 90 void UpdatePixmap(int i) { |
| 91 static int last_i = 0; |
| 92 GC gc = DefaultGC(g_xlib_display, 0); |
| 93 XSetForeground(g_xlib_display, gc, 0xffffff); |
| 94 XDrawLine(g_xlib_display, pixmap, gc, |
| 95 0, last_i, g_height - 1, last_i); |
| 96 XDrawLine(g_xlib_display, pixmap, gc, |
| 97 0, last_i + 4, g_height - 1, last_i + 4); |
| 98 |
| 99 XSetForeground(g_xlib_display, gc, 0x000000); |
| 100 XDrawLine(g_xlib_display, pixmap, gc, 0, i, g_height - 1, i); |
| 101 XDrawLine(g_xlib_display, pixmap, gc, 0, i + 4, g_height - 1, i + 4); |
| 102 |
| 103 last_i = i; |
| 104 } |
| 105 |
| 106 void CopyPixmapToTexture() { |
| 107 XImage *xim = XGetImage(g_xlib_display, pixmap, 0, 0, g_height, g_width, |
| 108 AllPlanes, ZPixmap); |
| 109 CHECK(xim != NULL); |
| 110 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, g_height, g_width, 0, |
| 111 GL_RGBA, GL_UNSIGNED_BYTE, (void*)(&xim->data[0])); |
| 112 XDestroyImage(xim); |
| 113 } |
| 114 |
| 115 |
| 116 bool UpdateUniform(TestState state, int shift) { |
| 117 switch (state) { |
| 118 case TestStart: |
| 119 printf("# Plain texture draw.\n"); |
| 120 InitializePixmap(); |
| 121 CopyPixmapToTexture(); |
| 122 break; |
| 123 |
| 124 case TestLoop: |
| 125 glUniform1f(shift_uniform, 1.f / g_width * shift); |
| 126 break; |
| 127 |
| 128 case TestStop: |
| 129 glUniform1f(shift_uniform, 0.f); |
| 130 break; |
| 131 } |
| 132 return true; |
| 133 } |
| 134 |
| 135 bool UpdateTexImage2D(TestState state, int shift) { |
| 136 switch (state) { |
| 137 case TestStart: |
| 138 printf("# Full texture update.\n"); |
| 139 InitializePixmap(); |
| 140 CopyPixmapToTexture(); |
| 141 break; |
| 142 |
| 143 case TestLoop: { |
| 144 UpdatePixmap(shift); |
| 145 // TODO: it's probably much cheaper to not use Pixmap and XImage. |
| 146 CopyPixmapToTexture(); |
| 147 } |
| 148 |
| 149 case TestStop: |
| 150 break; |
| 151 } |
| 152 return true; |
| 153 } |
| 154 |
| 155 |
| 156 Test test[] = { |
| 157 UpdateUniform, |
| 158 UpdateTexImage2D, |
| 159 UpdateBindTexImage |
| 160 }; |
| 161 |
78 int main(int argc, char* argv[]) { | 162 int main(int argc, char* argv[]) { |
79 g_override_redirect = false; | 163 g_override_redirect = false; |
80 g_height = -1; | 164 g_height = -1; |
81 ParseArgs(argc, argv); | 165 ParseArgs(argc, argv); |
82 if (!Init()) { | 166 if (!Init()) { |
83 printf("# Failed to initialize.\n"); | 167 printf("# Failed to initialize.\n"); |
84 return 1; | 168 return 1; |
85 } | 169 } |
86 | 170 |
87 InitContext(); | 171 InitContext(); |
88 glViewport(-g_width, -g_height, g_width*2, g_height*2); | 172 glViewport(-g_width, -g_height, g_width*2, g_height*2); |
89 | 173 |
90 char *bitmap = CreateBitmap(g_height, g_width*2); | |
91 GLuint texture = GenerateAndBindTexture(); | 174 GLuint texture = GenerateAndBindTexture(); |
92 glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, g_height, g_width, 0, | 175 |
93 GL_LUMINANCE, GL_UNSIGNED_BYTE, bitmap + g_height * g_width); | 176 AllocatePixmap(); |
| 177 InitNative(pixmap); |
94 | 178 |
95 GLfloat vertices[8] = { | 179 GLfloat vertices[8] = { |
96 0.f, 0.f, | 180 0.f, 0.f, |
97 1.f, 0.f, | 181 1.f, 0.f, |
98 0.f, 1.f, | 182 0.f, 1.f, |
99 1.f, 1.f, | 183 1.f, 1.f, |
100 }; | 184 }; |
101 | 185 |
102 GLuint program = InitShaderProgram(vertex_shader, fragment_shader); | 186 GLuint program = InitShaderProgram(vertex_shader, fragment_shader); |
103 int attribute_index = glGetAttribLocation(program, "c"); | 187 int attribute_index = glGetAttribLocation(program, "c"); |
104 glVertexAttribPointer(attribute_index, 2, GL_FLOAT, GL_FALSE, 0, vertices); | 188 glVertexAttribPointer(attribute_index, 2, GL_FLOAT, GL_FALSE, 0, vertices); |
105 glEnableVertexAttribArray(attribute_index); | 189 glEnableVertexAttribArray(attribute_index); |
106 | 190 |
107 int texture_sampler = glGetUniformLocation(program, "tex"); | 191 int texture_sampler = glGetUniformLocation(program, "tex"); |
108 glUniform1f(texture_sampler, 0); | 192 glUniform1f(texture_sampler, 0); |
109 | 193 |
110 int shift_uniform = glGetUniformLocation(program, "shift"); | 194 shift_uniform = glGetUniformLocation(program, "shift"); |
111 int i = 0; | |
112 SwapInterval(g_sleep_duration ? 0 : 1); | 195 SwapInterval(g_sleep_duration ? 0 : 1); |
113 for (;;) { | 196 |
| 197 for (unsigned int i = 0; i < sizeof(test)/sizeof(*test); i++) |
| 198 { |
114 XEvent event; | 199 XEvent event; |
115 Bool got_event = XCheckWindowEvent(g_xlib_display, g_xlib_window, | 200 if (!test[i](TestStart, 0)) |
116 KeyPressMask, &event); | 201 continue; |
117 if (got_event) | |
118 break; | |
119 glClear(GL_COLOR_BUFFER_BIT); | |
120 glUniform1f(shift_uniform, 1.f / g_width * | |
121 (i < g_width ? i : 2 * g_width - i)); | |
122 i = (i + 4) % (2 * g_width); | |
123 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); | |
124 glFlush(); | |
125 | 202 |
126 if (g_sleep_duration) | 203 Bool got_event = False; |
127 nanosleep(g_sleep_duration, NULL); | 204 for (int x = 0; !got_event; x = (x + 4) % (2 * g_width)) { |
| 205 const int shift = x < g_width ? x : 2 * g_width - x; |
128 | 206 |
129 SwapBuffers(); | 207 test[i](TestLoop, shift); |
| 208 |
| 209 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); |
| 210 glFlush(); |
| 211 |
| 212 if (g_sleep_duration) |
| 213 nanosleep(g_sleep_duration, NULL); |
| 214 |
| 215 SwapBuffers(); |
| 216 |
| 217 got_event = XCheckWindowEvent(g_xlib_display, g_xlib_window, |
| 218 KeyPressMask, &event); |
| 219 } |
| 220 |
| 221 test[i](TestStop, 0); |
130 } | 222 } |
131 | 223 |
| 224 // TODO: clean teardown. |
| 225 |
132 glDeleteTextures(1, &texture); | 226 glDeleteTextures(1, &texture); |
133 DestroyContext(); | 227 DestroyContext(); |
134 return 0; | 228 return 0; |
135 } | 229 } |
OLD | NEW |