GLClientState.h revision 57cb41b7ed8c951b1d28fe591c2d2fad97823060
1/* 2* Copyright (C) 2011 The Android Open Source Project 3* 4* Licensed under the Apache License, Version 2.0 (the "License"); 5* you may not use this file except in compliance with the License. 6* You may obtain a copy of the License at 7* 8* http://www.apache.org/licenses/LICENSE-2.0 9* 10* Unless required by applicable law or agreed to in writing, software 11* distributed under the License is distributed on an "AS IS" BASIS, 12* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13* See the License for the specific language governing permissions and 14* limitations under the License. 15*/ 16#ifndef _GL_CLIENT_STATE_H_ 17#define _GL_CLIENT_STATE_H_ 18 19#define GL_API 20#ifndef ANDROID 21#define GL_APIENTRY 22#define GL_APIENTRYP 23#endif 24 25#include <GLES/gl.h> 26#include <GLES/glext.h> 27#include <GLES2/gl2.h> 28#include <GLES2/gl2ext.h> 29 30#include <stdio.h> 31#include <stdlib.h> 32#include "ErrorLog.h" 33#include "codec_defs.h" 34 35#include <vector> 36 37// Tracking framebuffer objects: 38// which framebuffer is bound, 39// and which texture names 40// are currently bound to which attachment points. 41struct FboProps { 42 GLenum target; 43 GLuint name; 44 bool previouslyBound; 45 GLuint colorAttachment0_texture; 46 GLuint depthAttachment_texture; 47 GLuint stencilAttachment_texture; 48 49 bool colorAttachment0_hasTexObj; 50 bool depthAttachment_hasTexObj; 51 bool stencilAttachment_hasTexObj; 52 53 GLuint colorAttachment0_rbo; 54 GLuint depthAttachment_rbo; 55 GLuint stencilAttachment_rbo; 56 57 bool colorAttachment0_hasRbo; 58 bool depthAttachment_hasRbo; 59 bool stencilAttachment_hasRbo; 60}; 61 62// Same for Rbo's 63struct RboProps { 64 GLenum target; 65 GLuint name; 66 bool previouslyBound; 67}; 68 69class GLClientState { 70public: 71 typedef enum { 72 VERTEX_LOCATION = 0, 73 NORMAL_LOCATION = 1, 74 COLOR_LOCATION = 2, 75 POINTSIZE_LOCATION = 3, 76 TEXCOORD0_LOCATION = 4, 77 TEXCOORD1_LOCATION = 5, 78 TEXCOORD2_LOCATION = 6, 79 TEXCOORD3_LOCATION = 7, 80 TEXCOORD4_LOCATION = 8, 81 TEXCOORD5_LOCATION = 9, 82 TEXCOORD6_LOCATION = 10, 83 TEXCOORD7_LOCATION = 11, 84 MATRIXINDEX_LOCATION = 12, 85 WEIGHT_LOCATION = 13, 86 LAST_LOCATION = 14 87 } StateLocation; 88 89 typedef struct { 90 GLint enabled; 91 GLint size; 92 GLenum type; 93 GLsizei stride; 94 void *data; 95 GLuint bufferObject; 96 GLenum glConst; 97 unsigned int elementSize; 98 bool enableDirty; // true if any enable state has changed since last draw 99 bool normalized; 100 } VertexAttribState; 101 102 typedef struct { 103 int unpack_alignment; 104 int pack_alignment; 105 } PixelStoreState; 106 107 enum { 108 MAX_TEXTURE_UNITS = 32, 109 }; 110 111public: 112 GLClientState(int nLocations = CODEC_MAX_VERTEX_ATTRIBUTES); 113 ~GLClientState(); 114 int nLocations() { return m_nLocations; } 115 const PixelStoreState *pixelStoreState() { return &m_pixelStore; } 116 int setPixelStore(GLenum param, GLint value); 117 GLuint currentArrayVbo() { return m_currentArrayVbo; } 118 GLuint currentIndexVbo() { return m_currentIndexVbo; } 119 void enable(int location, int state); 120 void setState(int location, int size, GLenum type, GLboolean normalized, GLsizei stride, const void *data); 121 void setBufferObject(int location, GLuint id); 122 const VertexAttribState *getState(int location); 123 const VertexAttribState *getStateAndEnableDirty(int location, bool *enableChanged); 124 int getLocation(GLenum loc); 125 void setActiveTexture(int texUnit) {m_activeTexture = texUnit; }; 126 int getActiveTexture() const { return m_activeTexture; } 127 void setMaxVertexAttribs(int val) { 128 m_maxVertexAttribs = val; 129 m_maxVertexAttribsDirty = false; 130 } 131 132 void unBindBuffer(GLuint id) 133 { 134 if (m_currentArrayVbo == id) m_currentArrayVbo = 0; 135 else if (m_currentIndexVbo == id) m_currentIndexVbo = 0; 136 } 137 138 int bindBuffer(GLenum target, GLuint id) 139 { 140 int err = 0; 141 switch(target) { 142 case GL_ARRAY_BUFFER: 143 m_currentArrayVbo = id; 144 break; 145 case GL_ELEMENT_ARRAY_BUFFER: 146 m_currentIndexVbo = id; 147 break; 148 default: 149 err = -1; 150 } 151 return err; 152 } 153 154 int getBuffer(GLenum target) 155 { 156 int ret=0; 157 switch (target) { 158 case GL_ARRAY_BUFFER: 159 ret = m_currentArrayVbo; 160 break; 161 case GL_ELEMENT_ARRAY_BUFFER: 162 ret = m_currentIndexVbo; 163 break; 164 default: 165 ret = -1; 166 } 167 return ret; 168 } 169 size_t pixelDataSize(GLsizei width, GLsizei height, GLenum format, GLenum type, int pack) const; 170 171 void setCurrentProgram(GLint program) { m_currentProgram = program; } 172 GLint currentProgram() const { return m_currentProgram; } 173 174 /* OES_EGL_image_external 175 * 176 * These functions manipulate GL state which interacts with the 177 * OES_EGL_image_external extension, to support client-side emulation on 178 * top of host implementations that don't have it. 179 * 180 * Most of these calls should only be used with TEXTURE_2D or 181 * TEXTURE_EXTERNAL_OES texture targets; TEXTURE_CUBE_MAP or other extension 182 * targets should bypass this. An exception is bindTexture(), which should 183 * see all glBindTexture() calls for any target. 184 */ 185 186 // glActiveTexture(GL_TEXTURE0 + i) 187 // Sets the active texture unit. Up to MAX_TEXTURE_UNITS are supported. 188 GLenum setActiveTextureUnit(GLenum texture); 189 GLenum getActiveTextureUnit() const; 190 191 // glEnable(GL_TEXTURE_(2D|EXTERNAL_OES)) 192 void enableTextureTarget(GLenum target); 193 194 // glDisable(GL_TEXTURE_(2D|EXTERNAL_OES)) 195 void disableTextureTarget(GLenum target); 196 197 // Implements the target priority logic: 198 // * Return GL_TEXTURE_EXTERNAL_OES if enabled, else 199 // * Return GL_TEXTURE_2D if enabled, else 200 // * Return the allDisabled value. 201 // For some cases passing GL_TEXTURE_2D for allDisabled makes callee code 202 // simpler; for other cases passing a recognizable enum like GL_ZERO or 203 // GL_INVALID_ENUM is appropriate. 204 GLenum getPriorityEnabledTarget(GLenum allDisabled) const; 205 206 // glBindTexture(GL_TEXTURE_*, ...) 207 // Set the target binding of the active texture unit to texture. Returns 208 // GL_NO_ERROR on success or GL_INVALID_OPERATION if the texture has 209 // previously been bound to a different target. If firstUse is not NULL, 210 // it is set to indicate whether this is the first use of the texture. 211 // For accurate error detection, bindTexture should be called for *all* 212 // targets, not just 2D and EXTERNAL_OES. 213 GLenum bindTexture(GLenum target, GLuint texture, GLboolean* firstUse); 214 215 // Return the texture currently bound to GL_TEXTURE_(2D|EXTERNAL_OES). 216 GLuint getBoundTexture(GLenum target) const; 217 218 // glDeleteTextures(...) 219 // Remove references to the to-be-deleted textures. 220 void deleteTextures(GLsizei n, const GLuint* textures); 221 222 // Render buffer objects 223 void addRenderbuffers(GLsizei n, GLuint* renderbuffers); 224 void removeRenderbuffers(GLsizei n, const GLuint* renderbuffers); 225 bool usedRenderbufferName(GLuint name) const; 226 void bindRenderbuffer(GLenum target, GLuint name); 227 GLuint boundRenderbuffer() const; 228 229 // Frame buffer objects 230 void addFramebuffers(GLsizei n, GLuint* framebuffers); 231 void removeFramebuffers(GLsizei n, const GLuint* framebuffers); 232 bool usedFramebufferName(GLuint name) const; 233 void bindFramebuffer(GLenum target, GLuint name); 234 GLuint boundFramebuffer() const; 235 236 // Texture object -> FBO 237 void attachTextureObject(GLenum attachment, GLuint texture); 238 GLuint getFboAttachmentTextureId(GLenum attachment) const; 239 240 // RBO -> FBO 241 void attachRbo(GLenum attachment, GLuint renderbuffer); 242 GLuint getFboAttachmentRboId(GLenum attachment) const; 243 244 // FBO attachments in general 245 bool attachmentHasObject(GLenum attachment) const; 246 247 // set eglsurface property on default framebuffer 248 // if coming from eglMakeCurrent 249 void fromMakeCurrent(); 250 251private: 252 PixelStoreState m_pixelStore; 253 VertexAttribState *m_states; 254 int m_maxVertexAttribs; 255 bool m_maxVertexAttribsDirty; 256 int m_nLocations; 257 GLuint m_currentArrayVbo; 258 GLuint m_currentIndexVbo; 259 int m_activeTexture; 260 GLint m_currentProgram; 261 262 bool validLocation(int location) { return (location >= 0 && location < m_nLocations); } 263 264 enum TextureTarget { 265 TEXTURE_2D = 0, 266 TEXTURE_EXTERNAL = 1, 267 TEXTURE_TARGET_COUNT 268 }; 269 struct TextureUnit { 270 unsigned int enables; 271 GLuint texture[TEXTURE_TARGET_COUNT]; 272 }; 273 struct TextureRec { 274 GLuint id; 275 GLenum target; 276 }; 277 struct TextureState { 278 TextureUnit unit[MAX_TEXTURE_UNITS]; 279 TextureUnit* activeUnit; 280 TextureRec* textures; 281 GLuint numTextures; 282 GLuint allocTextures; 283 }; 284 TextureState m_tex; 285 286 287 struct RboState { 288 GLuint boundRenderbuffer; 289 size_t boundRenderbufferIndex; 290 std::vector<RboProps> rboData; 291 }; 292 RboState mRboState; 293 void addFreshRenderbuffer(GLuint name); 294 void setBoundRenderbufferIndex(); 295 size_t getRboIndex(GLuint name) const; 296 RboProps& boundRboProps(); 297 const RboProps& boundRboProps_const() const; 298 299 struct FboState { 300 GLuint boundFramebuffer; 301 size_t boundFramebufferIndex; 302 std::vector<FboProps> fboData; 303 }; 304 FboState mFboState; 305 void addFreshFramebuffer(GLuint name); 306 void setBoundFramebufferIndex(); 307 size_t getFboIndex(GLuint name) const; 308 FboProps& boundFboProps(); 309 const FboProps& boundFboProps_const() const; 310 311 static int compareTexId(const void* pid, const void* prec); 312 TextureRec* addTextureRec(GLuint id, GLenum target); 313 314public: 315 void getClientStatePointer(GLenum pname, GLvoid** params); 316 317 template <class T> 318 int getVertexAttribParameter(GLuint index, GLenum param, T *ptr) 319 { 320 bool handled = true; 321 const VertexAttribState *vertexAttrib = getState(index); 322 if (vertexAttrib == NULL) { 323 ERR("getVeterxAttriParameter for non existant index %d\n", index); 324 // set gl error; 325 return handled; 326 } 327 328 switch(param) { 329 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING: 330 *ptr = (T)(vertexAttrib->bufferObject); 331 break; 332 case GL_VERTEX_ATTRIB_ARRAY_ENABLED: 333 *ptr = (T)(vertexAttrib->enabled); 334 break; 335 case GL_VERTEX_ATTRIB_ARRAY_SIZE: 336 *ptr = (T)(vertexAttrib->size); 337 break; 338 case GL_VERTEX_ATTRIB_ARRAY_STRIDE: 339 *ptr = (T)(vertexAttrib->stride); 340 break; 341 case GL_VERTEX_ATTRIB_ARRAY_TYPE: 342 *ptr = (T)(vertexAttrib->type); 343 break; 344 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED: 345 *ptr = (T)(vertexAttrib->normalized); 346 break; 347 case GL_CURRENT_VERTEX_ATTRIB: 348 handled = false; 349 break; 350 default: 351 handled = false; 352 ERR("unknown vertex-attrib parameter param %d\n", param); 353 } 354 return handled; 355 } 356 357 template <class T> 358 bool getClientStateParameter(GLenum param, T* ptr) 359 { 360 bool isClientStateParam = false; 361 switch (param) { 362 case GL_CLIENT_ACTIVE_TEXTURE: { 363 GLint tex = getActiveTexture() + GL_TEXTURE0; 364 *ptr = tex; 365 isClientStateParam = true; 366 break; 367 } 368 case GL_VERTEX_ARRAY_SIZE: { 369 const GLClientState::VertexAttribState *state = getState(GLClientState::VERTEX_LOCATION); 370 *ptr = state->size; 371 isClientStateParam = true; 372 break; 373 } 374 case GL_VERTEX_ARRAY_TYPE: { 375 const GLClientState::VertexAttribState *state = getState(GLClientState::VERTEX_LOCATION); 376 *ptr = state->type; 377 isClientStateParam = true; 378 break; 379 } 380 case GL_VERTEX_ARRAY_STRIDE: { 381 const GLClientState::VertexAttribState *state = getState(GLClientState::VERTEX_LOCATION); 382 *ptr = state->stride; 383 isClientStateParam = true; 384 break; 385 } 386 case GL_COLOR_ARRAY_SIZE: { 387 const GLClientState::VertexAttribState *state = getState(GLClientState::COLOR_LOCATION); 388 *ptr = state->size; 389 isClientStateParam = true; 390 break; 391 } 392 case GL_COLOR_ARRAY_TYPE: { 393 const GLClientState::VertexAttribState *state = getState(GLClientState::COLOR_LOCATION); 394 *ptr = state->type; 395 isClientStateParam = true; 396 break; 397 } 398 case GL_COLOR_ARRAY_STRIDE: { 399 const GLClientState::VertexAttribState *state = getState(GLClientState::COLOR_LOCATION); 400 *ptr = state->stride; 401 isClientStateParam = true; 402 break; 403 } 404 case GL_NORMAL_ARRAY_TYPE: { 405 const GLClientState::VertexAttribState *state = getState(GLClientState::NORMAL_LOCATION); 406 *ptr = state->type; 407 isClientStateParam = true; 408 break; 409 } 410 case GL_NORMAL_ARRAY_STRIDE: { 411 const GLClientState::VertexAttribState *state = getState(GLClientState::NORMAL_LOCATION); 412 *ptr = state->stride; 413 isClientStateParam = true; 414 break; 415 } 416 case GL_TEXTURE_COORD_ARRAY_SIZE: { 417 const GLClientState::VertexAttribState *state = getState(getActiveTexture() + GLClientState::TEXCOORD0_LOCATION); 418 *ptr = state->size; 419 isClientStateParam = true; 420 break; 421 } 422 case GL_TEXTURE_COORD_ARRAY_TYPE: { 423 const GLClientState::VertexAttribState *state = getState(getActiveTexture() + GLClientState::TEXCOORD0_LOCATION); 424 *ptr = state->type; 425 isClientStateParam = true; 426 break; 427 } 428 case GL_TEXTURE_COORD_ARRAY_STRIDE: { 429 const GLClientState::VertexAttribState *state = getState(getActiveTexture() + GLClientState::TEXCOORD0_LOCATION); 430 *ptr = state->stride; 431 isClientStateParam = true; 432 break; 433 } 434 case GL_POINT_SIZE_ARRAY_TYPE_OES: { 435 const GLClientState::VertexAttribState *state = getState(GLClientState::POINTSIZE_LOCATION); 436 *ptr = state->type; 437 isClientStateParam = true; 438 break; 439 } 440 case GL_POINT_SIZE_ARRAY_STRIDE_OES: { 441 const GLClientState::VertexAttribState *state = getState(GLClientState::POINTSIZE_LOCATION); 442 *ptr = state->stride; 443 isClientStateParam = true; 444 break; 445 } 446 case GL_MATRIX_INDEX_ARRAY_SIZE_OES: { 447 const GLClientState::VertexAttribState *state = getState(GLClientState::MATRIXINDEX_LOCATION); 448 *ptr = state->size; 449 isClientStateParam = true; 450 break; 451 } 452 case GL_MATRIX_INDEX_ARRAY_TYPE_OES: { 453 const GLClientState::VertexAttribState *state = getState(GLClientState::MATRIXINDEX_LOCATION); 454 *ptr = state->type; 455 isClientStateParam = true; 456 break; 457 } 458 case GL_MATRIX_INDEX_ARRAY_STRIDE_OES: { 459 const GLClientState::VertexAttribState *state = getState(GLClientState::MATRIXINDEX_LOCATION); 460 *ptr = state->stride; 461 isClientStateParam = true; 462 break; 463 } 464 case GL_WEIGHT_ARRAY_SIZE_OES: { 465 const GLClientState::VertexAttribState *state = getState(GLClientState::WEIGHT_LOCATION); 466 *ptr = state->size; 467 isClientStateParam = true; 468 break; 469 } 470 case GL_WEIGHT_ARRAY_TYPE_OES: { 471 const GLClientState::VertexAttribState *state = getState(GLClientState::WEIGHT_LOCATION); 472 *ptr = state->type; 473 isClientStateParam = true; 474 break; 475 } 476 case GL_WEIGHT_ARRAY_STRIDE_OES: { 477 const GLClientState::VertexAttribState *state = getState(GLClientState::WEIGHT_LOCATION); 478 *ptr = state->stride; 479 isClientStateParam = true; 480 break; 481 } 482 case GL_VERTEX_ARRAY_BUFFER_BINDING: { 483 const GLClientState::VertexAttribState *state = getState(GLClientState::VERTEX_LOCATION); 484 *ptr = state->bufferObject; 485 isClientStateParam = true; 486 break; 487 } 488 case GL_NORMAL_ARRAY_BUFFER_BINDING: { 489 const GLClientState::VertexAttribState *state = getState(GLClientState::NORMAL_LOCATION); 490 *ptr = state->bufferObject; 491 isClientStateParam = true; 492 break; 493 } 494 case GL_COLOR_ARRAY_BUFFER_BINDING: { 495 const GLClientState::VertexAttribState *state = getState(GLClientState::COLOR_LOCATION); 496 *ptr = state->bufferObject; 497 isClientStateParam = true; 498 break; 499 } 500 case GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING: { 501 const GLClientState::VertexAttribState *state = getState(getActiveTexture()+GLClientState::TEXCOORD0_LOCATION); 502 *ptr = state->bufferObject; 503 isClientStateParam = true; 504 break; 505 } 506 case GL_POINT_SIZE_ARRAY_BUFFER_BINDING_OES: { 507 const GLClientState::VertexAttribState *state = getState(GLClientState::POINTSIZE_LOCATION); 508 *ptr = state->bufferObject; 509 isClientStateParam = true; 510 break; 511 } 512 case GL_MATRIX_INDEX_ARRAY_BUFFER_BINDING_OES: { 513 const GLClientState::VertexAttribState *state = getState(GLClientState::MATRIXINDEX_LOCATION); 514 *ptr = state->bufferObject; 515 isClientStateParam = true; 516 break; 517 } 518 case GL_WEIGHT_ARRAY_BUFFER_BINDING_OES: { 519 const GLClientState::VertexAttribState *state = getState(GLClientState::WEIGHT_LOCATION); 520 *ptr = state->bufferObject; 521 isClientStateParam = true; 522 break; 523 } 524 case GL_ARRAY_BUFFER_BINDING: { 525 int buffer = getBuffer(GL_ARRAY_BUFFER); 526 *ptr = buffer; 527 isClientStateParam = true; 528 break; 529 } 530 case GL_ELEMENT_ARRAY_BUFFER_BINDING: { 531 int buffer = getBuffer(GL_ELEMENT_ARRAY_BUFFER); 532 *ptr = buffer; 533 isClientStateParam = true; 534 break; 535 } 536 case GL_MAX_VERTEX_ATTRIBS: { 537 if (m_maxVertexAttribsDirty) { 538 isClientStateParam = false; 539 } else { 540 *ptr = m_maxVertexAttribs; 541 isClientStateParam = true; 542 } 543 break; 544 } 545 } 546 return isClientStateParam; 547 } 548 549}; 550#endif 551