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