OLD | NEW |
| (Empty) |
1 // Copyright (c) 2012 The Chromium 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 #include <GLES2/gl2.h> | |
5 #include <GLES2/gl2ext.h> | |
6 #include <math.h> | |
7 #include <stdio.h> | |
8 #include <string> | |
9 | |
10 // Some tests for occlusion queries. | |
11 #include "gpu/demos/framework/demo_factory.h" | |
12 #include "gpu/demos/gles2_book/example.h" | |
13 | |
14 namespace gpu { | |
15 namespace demos { | |
16 | |
17 namespace { | |
18 | |
19 class OcclusionQueryTest; | |
20 | |
21 struct STUserData { | |
22 OcclusionQueryTest* demo; | |
23 }; | |
24 | |
25 class OcclusionQueryTest : public gles2_book::Example<STUserData> { | |
26 public: | |
27 OcclusionQueryTest() | |
28 : elasped_sec_(0), | |
29 program_(0), | |
30 matrix_loc_(0), | |
31 color_loc_(0), | |
32 vbo_(0), | |
33 query_(0), | |
34 clock_(0), | |
35 last_query_status_(0) { | |
36 test_ = this; | |
37 RegisterCallbacks(stInit, stUpdate, stDraw, stShutDown); | |
38 } | |
39 | |
40 const wchar_t* Title() const { | |
41 return L"Occlusion Query Test"; | |
42 } | |
43 | |
44 bool IsAnimated() { | |
45 return true; | |
46 } | |
47 | |
48 private: | |
49 int Init(ESContext* esContext); | |
50 void Update(ESContext* esContext, float elapsed_sec); | |
51 void Draw(ESContext* esContext); | |
52 void ShutDown(ESContext* esContext); | |
53 | |
54 void InitShaders(); | |
55 void DrawRect(float x, float z, float scale, float* color); | |
56 | |
57 static int stInit(ESContext* esContext) { | |
58 static_cast<STUserData*>(esContext->userData)->demo = test_; | |
59 test_ = NULL; | |
60 return static_cast<STUserData*>(esContext->userData)->demo->Init(esContext); | |
61 } | |
62 | |
63 static void stUpdate (ESContext* esContext, float elapsed_sec) { | |
64 static_cast<STUserData*>(esContext->userData)->demo->Update( | |
65 esContext, elapsed_sec); | |
66 } | |
67 | |
68 static void stShutDown (ESContext* esContext) { | |
69 static_cast<STUserData*>(esContext->userData)->demo->ShutDown( | |
70 esContext); | |
71 } | |
72 | |
73 static void stDraw (ESContext* esContext) { | |
74 static_cast<STUserData*>(esContext->userData)->demo->Draw( | |
75 esContext); | |
76 } | |
77 | |
78 // This is the test being created. Because the GLES2 book's framework | |
79 // has no way to pass anything into the init funciton this is a hacky | |
80 // workaround. | |
81 static OcclusionQueryTest* test_; | |
82 | |
83 float elasped_sec_; | |
84 GLuint program_; | |
85 GLint matrix_loc_; | |
86 GLint color_loc_; | |
87 GLuint vbo_; | |
88 GLuint query_; | |
89 float clock_; | |
90 GLuint last_query_status_; | |
91 | |
92 static float red_[4]; | |
93 static float green_[4]; | |
94 static float blue_[4]; | |
95 }; | |
96 | |
97 OcclusionQueryTest* OcclusionQueryTest::test_; | |
98 float OcclusionQueryTest::red_[4] = { 1, 0, 0, 1, }; | |
99 float OcclusionQueryTest::green_[4] = { 0, 1, 0, 1, }; | |
100 float OcclusionQueryTest::blue_[4] = { 0, 0, 1, 1, }; | |
101 | |
102 void CheckGLError(const char* func_name, int line_no) { | |
103 #ifndef NDEBUG | |
104 GLenum error = GL_NO_ERROR; | |
105 while ((error = glGetError()) != GL_NO_ERROR) { | |
106 fprintf(stderr, "GL ERROR in %s at line %d : 0x%04x\n", | |
107 func_name, line_no, error); | |
108 } | |
109 #endif | |
110 } | |
111 | |
112 GLuint LoadShader(GLenum type, const char* shaderSrc) { | |
113 CheckGLError("LoadShader", __LINE__); | |
114 GLuint shader = glCreateShader(type); | |
115 if (shader == 0) { | |
116 return 0; | |
117 } | |
118 // Load the shader source | |
119 glShaderSource(shader, 1, &shaderSrc, NULL); | |
120 // Compile the shader | |
121 glCompileShader(shader); | |
122 // Check the compile status | |
123 GLint value = 0; | |
124 glGetShaderiv(shader, GL_COMPILE_STATUS, &value); | |
125 if (value == 0) { | |
126 char buffer[1024]; | |
127 GLsizei length = 0; | |
128 glGetShaderInfoLog(shader, sizeof(buffer), &length, buffer); | |
129 std::string log(buffer, length); | |
130 fprintf(stderr, "Error compiling shader: %s\n", log.c_str()); | |
131 glDeleteShader(shader); | |
132 return 0; | |
133 } | |
134 return shader; | |
135 } | |
136 | |
137 void OcclusionQueryTest::InitShaders() { | |
138 static const char* v_shader_str = | |
139 "uniform mat4 worldMatrix;\n" | |
140 "attribute vec3 g_Position;\n" | |
141 "void main()\n" | |
142 "{\n" | |
143 " gl_Position = worldMatrix *\n" | |
144 " vec4(g_Position.x, g_Position.y, g_Position.z, 1.0);\n" | |
145 "}\n"; | |
146 static const char* f_shader_str = | |
147 "precision mediump float;" | |
148 "uniform vec4 color;\n" | |
149 "void main()\n" | |
150 "{\n" | |
151 " gl_FragColor = color;\n" | |
152 "}\n"; | |
153 | |
154 CheckGLError("InitShaders", __LINE__); | |
155 GLuint vertex_shader = LoadShader(GL_VERTEX_SHADER, v_shader_str); | |
156 GLuint fragment_shader = LoadShader(GL_FRAGMENT_SHADER, f_shader_str); | |
157 // Create the program object | |
158 GLuint program = glCreateProgram(); | |
159 if (program == 0) { | |
160 fprintf(stderr, "Creating program failed\n"); | |
161 return; | |
162 } | |
163 glAttachShader(program, vertex_shader); | |
164 glAttachShader(program, fragment_shader); | |
165 // Bind g_Position to attribute 0 | |
166 glBindAttribLocation(program, 0, "g_Position"); | |
167 // Link the program | |
168 glLinkProgram(program); | |
169 // Check the link status | |
170 GLint linked = 0; | |
171 glGetProgramiv(program, GL_LINK_STATUS, &linked); | |
172 if (linked == 0) { | |
173 char buffer[1024]; | |
174 GLsizei length = 0; | |
175 glGetProgramInfoLog(program, sizeof(buffer), &length, buffer); | |
176 std::string log(buffer, length); | |
177 fprintf(stderr, "Error linking program: %s\n", log.c_str()); | |
178 glDeleteProgram(program); | |
179 return; | |
180 } | |
181 program_ = program; | |
182 matrix_loc_ = glGetUniformLocation(program_, "worldMatrix"); | |
183 color_loc_ = glGetUniformLocation(program_, "color"); | |
184 glGenBuffers(1, &vbo_); | |
185 glBindBuffer(GL_ARRAY_BUFFER, vbo_); | |
186 static float vertices[] = { | |
187 1, 1, 0.0, | |
188 -1, 1, 0.0, | |
189 -1, -1, 0.0, | |
190 1, 1, 0.0, | |
191 -1, -1, 0.0, | |
192 1, -1, 0.0, | |
193 }; | |
194 glBufferData(GL_ARRAY_BUFFER, | |
195 sizeof(vertices), | |
196 NULL, | |
197 GL_STATIC_DRAW); | |
198 glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(vertices), vertices); | |
199 CheckGLError("InitShaders", __LINE__); | |
200 | |
201 glGenQueriesEXT(1, &query_); | |
202 glBeginQueryEXT(GL_ANY_SAMPLES_PASSED_EXT, query_); | |
203 glEndQueryEXT(GL_ANY_SAMPLES_PASSED_EXT); | |
204 CheckGLError("InitShaders", __LINE__); | |
205 } | |
206 | |
207 } // anonymous namespace. | |
208 | |
209 int OcclusionQueryTest::Init(ESContext* esContext) { | |
210 CheckGLError("GLFromCPPInit", __LINE__); | |
211 glClearColor(0.0f, 0.1f, 0.2f, 1.0f); | |
212 InitShaders(); | |
213 CheckGLError("GLFromCPPInit", __LINE__); | |
214 return 1; | |
215 } | |
216 | |
217 void OcclusionQueryTest::Update(ESContext* esContext, float elapsed_sec) { | |
218 elasped_sec_ = elapsed_sec; | |
219 } | |
220 | |
221 static void SetMatrix(float x, float z, float scale, float* matrix) { | |
222 matrix[0] = scale; | |
223 matrix[1] = 0.0f; | |
224 matrix[2] = 0.0f; | |
225 matrix[3] = 0.0f; | |
226 | |
227 matrix[4] = 0.0f; | |
228 matrix[5] = scale; | |
229 matrix[6] = 0.0f; | |
230 matrix[7] = 0.0f; | |
231 | |
232 matrix[8] = 0.0f; | |
233 matrix[9] = 0.0f; | |
234 matrix[10] = scale; | |
235 matrix[11] = 0.0f; | |
236 | |
237 matrix[12] = x; | |
238 matrix[13] = 0.0f; | |
239 matrix[14] = z; | |
240 matrix[15] = 1.0f; | |
241 } | |
242 | |
243 void OcclusionQueryTest::DrawRect(float x, float z, float scale, float* color) { | |
244 GLfloat matrix[16]; | |
245 | |
246 SetMatrix(x, z, scale, matrix); | |
247 | |
248 // Set up the model matrix | |
249 glUniformMatrix4fv(matrix_loc_, 1, GL_FALSE, matrix); | |
250 | |
251 glUniform4fv(color_loc_, 1, color); | |
252 CheckGLError("GLFromCPPDraw", __LINE__); | |
253 | |
254 glDrawArrays(GL_TRIANGLES, 0, 6); | |
255 CheckGLError("GLFromCPPDraw", __LINE__); | |
256 } | |
257 | |
258 void OcclusionQueryTest::Draw(ESContext* esContext) { | |
259 CheckGLError("GLFromCPPDraw", __LINE__); | |
260 clock_ += elasped_sec_; | |
261 | |
262 // Note: the viewport is automatically set up to cover the entire Canvas. | |
263 // Clear the color buffer | |
264 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); | |
265 glEnable(GL_DEPTH_TEST); | |
266 CheckGLError("GLFromCPPDraw", __LINE__); | |
267 // Use the program object | |
268 glUseProgram(program_); | |
269 CheckGLError("GLFromCPPDraw", __LINE__); | |
270 | |
271 // Load the vertex data | |
272 glBindBuffer(GL_ARRAY_BUFFER, vbo_); | |
273 glEnableVertexAttribArray(0); | |
274 glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0); | |
275 CheckGLError("GLFromCPPDraw", __LINE__); | |
276 | |
277 DrawRect(sinf(clock_), 0.0f, 0.50f, | |
278 last_query_status_ ? green_ : red_); | |
279 | |
280 bool started_query = false; | |
281 GLuint result = 0; | |
282 glGetQueryObjectuivEXT(query_, GL_QUERY_RESULT_AVAILABLE_EXT, &result); | |
283 CheckGLError("GLFromCPPDraw", __LINE__); | |
284 if (result) { | |
285 glGetQueryObjectuivEXT(query_, GL_QUERY_RESULT_EXT, &last_query_status_); | |
286 CheckGLError("GLFromCPPDraw", __LINE__); | |
287 glBeginQueryEXT(GL_ANY_SAMPLES_PASSED_EXT, query_); | |
288 CheckGLError("GLFromCPPDraw", __LINE__); | |
289 started_query = true; | |
290 } | |
291 | |
292 DrawRect(-0.125f, 0.1f, 0.25f, blue_); | |
293 | |
294 if (started_query) { | |
295 glEndQueryEXT(GL_ANY_SAMPLES_PASSED_EXT); | |
296 CheckGLError("GLFromCPPDraw", __LINE__); | |
297 } | |
298 | |
299 glFlush(); | |
300 } | |
301 | |
302 void OcclusionQueryTest::ShutDown(ESContext* esContext) { | |
303 } | |
304 | |
305 Demo* CreateDemo() { | |
306 return new OcclusionQueryTest(); | |
307 } | |
308 | |
309 } // namespace demos | |
310 } // namespace gpu | |
311 | |
312 | |
OLD | NEW |