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 #include <set> 37 38 // Tracking framebuffer objects: 39 // which framebuffer is bound, 40 // and which texture names 41 // are currently bound to which attachment points. 42 struct FboProps { 43 GLenum target; 44 GLuint name; 45 bool previouslyBound; 46 GLuint colorAttachment0_texture; 47 GLuint depthAttachment_texture; 48 GLuint stencilAttachment_texture; 49 50 bool colorAttachment0_hasTexObj; 51 bool depthAttachment_hasTexObj; 52 bool stencilAttachment_hasTexObj; 53 54 GLuint colorAttachment0_rbo; 55 GLuint depthAttachment_rbo; 56 GLuint stencilAttachment_rbo; 57 58 bool colorAttachment0_hasRbo; 59 bool depthAttachment_hasRbo; 60 bool stencilAttachment_hasRbo; 61 }; 62 63 // Same for Rbo's 64 struct RboProps { 65 GLenum target; 66 GLuint name; 67 GLenum format; 68 bool previouslyBound; 69 }; 70 71 // Enum for describing whether a framebuffer attachment 72 // is a texture or renderbuffer. 73 enum FboAttachmentType { 74 FBO_ATTACHMENT_RENDERBUFFER = 0, 75 FBO_ATTACHMENT_TEXTURE = 1, 76 FBO_ATTACHMENT_NONE = 2 77 }; 78 79 // Tracking FBO format 80 struct FboFormatInfo { 81 FboAttachmentType type; 82 GLenum rb_format; 83 GLint tex_internalformat; 84 GLenum tex_format; 85 GLenum tex_type; 86 }; 87 88 class GLClientState { 89 public: 90 typedef enum { 91 VERTEX_LOCATION = 0, 92 NORMAL_LOCATION = 1, 93 COLOR_LOCATION = 2, 94 POINTSIZE_LOCATION = 3, 95 TEXCOORD0_LOCATION = 4, 96 TEXCOORD1_LOCATION = 5, 97 TEXCOORD2_LOCATION = 6, 98 TEXCOORD3_LOCATION = 7, 99 TEXCOORD4_LOCATION = 8, 100 TEXCOORD5_LOCATION = 9, 101 TEXCOORD6_LOCATION = 10, 102 TEXCOORD7_LOCATION = 11, 103 MATRIXINDEX_LOCATION = 12, 104 WEIGHT_LOCATION = 13, 105 LAST_LOCATION = 14 106 } StateLocation; 107 108 typedef struct { 109 GLint enabled; 110 GLint size; 111 GLenum type; 112 GLsizei stride; 113 void *data; 114 GLuint bufferObject; 115 GLenum glConst; 116 unsigned int elementSize; 117 bool enableDirty; // true if any enable state has changed since last draw 118 bool normalized; 119 } VertexAttribState; 120 121 typedef struct { 122 int unpack_alignment; 123 int pack_alignment; 124 } PixelStoreState; 125 126 enum { 127 MAX_TEXTURE_UNITS = 32, 128 }; 129 130 public: 131 GLClientState(int nLocations = CODEC_MAX_VERTEX_ATTRIBUTES); 132 ~GLClientState(); 133 int nLocations() { return m_nLocations; } 134 const PixelStoreState *pixelStoreState() { return &m_pixelStore; } 135 int setPixelStore(GLenum param, GLint value); 136 GLuint currentArrayVbo() { return m_currentArrayVbo; } 137 GLuint currentIndexVbo() { return m_currentIndexVbo; } 138 void enable(int location, int state); 139 void setState(int location, int size, GLenum type, GLboolean normalized, GLsizei stride, const void *data); 140 void setBufferObject(int location, GLuint id); 141 const VertexAttribState *getState(int location); 142 const VertexAttribState *getStateAndEnableDirty(int location, bool *enableChanged); 143 int getLocation(GLenum loc); 144 void setActiveTexture(int texUnit) {m_activeTexture = texUnit; }; 145 int getActiveTexture() const { return m_activeTexture; } 146 void setMaxVertexAttribs(int val) { 147 m_maxVertexAttribs = val; 148 m_maxVertexAttribsDirty = false; 149 } 150 151 void unBindBuffer(GLuint id) 152 { 153 if (m_currentArrayVbo == id) m_currentArrayVbo = 0; 154 else if (m_currentIndexVbo == id) m_currentIndexVbo = 0; 155 } 156 157 int bindBuffer(GLenum target, GLuint id) 158 { 159 int err = 0; 160 switch(target) { 161 case GL_ARRAY_BUFFER: 162 m_currentArrayVbo = id; 163 break; 164 case GL_ELEMENT_ARRAY_BUFFER: 165 m_currentIndexVbo = id; 166 break; 167 default: 168 err = -1; 169 } 170 return err; 171 } 172 173 int getBuffer(GLenum target) 174 { 175 int ret=0; 176 switch (target) { 177 case GL_ARRAY_BUFFER: 178 ret = m_currentArrayVbo; 179 break; 180 case GL_ELEMENT_ARRAY_BUFFER: 181 ret = m_currentIndexVbo; 182 break; 183 default: 184 ret = -1; 185 } 186 return ret; 187 } 188 size_t pixelDataSize(GLsizei width, GLsizei height, GLenum format, GLenum type, int pack) const; 189 190 void setCurrentProgram(GLint program) { m_currentProgram = program; } 191 GLint currentProgram() const { return m_currentProgram; } 192 193 /* OES_EGL_image_external 194 * 195 * These functions manipulate GL state which interacts with the 196 * OES_EGL_image_external extension, to support client-side emulation on 197 * top of host implementations that don't have it. 198 * 199 * Most of these calls should only be used with TEXTURE_2D or 200 * TEXTURE_EXTERNAL_OES texture targets; TEXTURE_CUBE_MAP or other extension 201 * targets should bypass this. An exception is bindTexture(), which should 202 * see all glBindTexture() calls for any target. 203 */ 204 205 // glActiveTexture(GL_TEXTURE0 + i) 206 // Sets the active texture unit. Up to MAX_TEXTURE_UNITS are supported. 207 GLenum setActiveTextureUnit(GLenum texture); 208 GLenum getActiveTextureUnit() const; 209 210 // glEnable(GL_TEXTURE_(2D|EXTERNAL_OES)) 211 void enableTextureTarget(GLenum target); 212 213 // glDisable(GL_TEXTURE_(2D|EXTERNAL_OES)) 214 void disableTextureTarget(GLenum target); 215 216 // Implements the target priority logic: 217 // * Return GL_TEXTURE_EXTERNAL_OES if enabled, else 218 // * Return GL_TEXTURE_2D if enabled, else 219 // * Return the allDisabled value. 220 // For some cases passing GL_TEXTURE_2D for allDisabled makes callee code 221 // simpler; for other cases passing a recognizable enum like GL_ZERO or 222 // GL_INVALID_ENUM is appropriate. 223 GLenum getPriorityEnabledTarget(GLenum allDisabled) const; 224 225 // glBindTexture(GL_TEXTURE_*, ...) 226 // Set the target binding of the active texture unit to texture. Returns 227 // GL_NO_ERROR on success or GL_INVALID_OPERATION if the texture has 228 // previously been bound to a different target. If firstUse is not NULL, 229 // it is set to indicate whether this is the first use of the texture. 230 // For accurate error detection, bindTexture should be called for *all* 231 // targets, not just 2D and EXTERNAL_OES. 232 GLenum bindTexture(GLenum target, GLuint texture, GLboolean* firstUse); 233 234 // Return the texture currently bound to GL_TEXTURE_(2D|EXTERNAL_OES). 235 GLuint getBoundTexture(GLenum target) const; 236 237 // For AMD GPUs, it is easy for the emulator to segfault 238 // (esp. in dEQP) when a cube map is defined using glCopyTexImage2D 239 // and uses GL_LUMINANCE as internal format. 240 // In particular, the segfault happens when negative components of 241 // cube maps are defined before positive ones, 242 // This procedure checks internal state to see if we have defined 243 // the positive component of a cube map already. If not, it returns 244 // which positive component needs to be defined first. 245 // If there is no need for the extra definition, 0 is returned. 246 GLenum copyTexImageLuminanceCubeMapAMDWorkaround(GLenum target, GLint level, 247 GLenum internalformat); 248 249 // Tracks the format of the currently bound texture. 250 // This is to pass dEQP tests for fbo completeness. 251 void setBoundTextureInternalFormat(GLenum target, GLint format); 252 void setBoundTextureFormat(GLenum target, GLenum format); 253 void setBoundTextureType(GLenum target, GLenum type); 254 255 // glDeleteTextures(...) 256 // Remove references to the to-be-deleted textures. 257 void deleteTextures(GLsizei n, const GLuint* textures); 258 259 // Render buffer objects 260 void addRenderbuffers(GLsizei n, GLuint* renderbuffers); 261 void removeRenderbuffers(GLsizei n, const GLuint* renderbuffers); 262 bool usedRenderbufferName(GLuint name) const; 263 void bindRenderbuffer(GLenum target, GLuint name); 264 GLuint boundRenderbuffer() const; 265 void setBoundRenderbufferFormat(GLenum format); 266 267 // Frame buffer objects 268 void addFramebuffers(GLsizei n, GLuint* framebuffers); 269 void removeFramebuffers(GLsizei n, const GLuint* framebuffers); 270 bool usedFramebufferName(GLuint name) const; 271 void bindFramebuffer(GLenum target, GLuint name); 272 void setCheckFramebufferStatus(GLenum status); 273 GLenum getCheckFramebufferStatus() const; 274 GLuint boundFramebuffer() const; 275 276 // Texture object -> FBO 277 void attachTextureObject(GLenum attachment, GLuint texture); 278 GLuint getFboAttachmentTextureId(GLenum attachment) const; 279 280 // RBO -> FBO 281 void attachRbo(GLenum attachment, GLuint renderbuffer); 282 GLuint getFboAttachmentRboId(GLenum attachment) const; 283 284 // FBO attachments in general 285 bool attachmentHasObject(GLenum attachment) const; 286 287 // set eglsurface property on default framebuffer 288 // if coming from eglMakeCurrent 289 void fromMakeCurrent(); 290 291 // Queries the format backing the current framebuffer. 292 // Type differs depending on whether the attachment 293 // is a texture or renderbuffer. 294 void getBoundFramebufferFormat( 295 GLenum attachment, FboFormatInfo* res_info) const; 296 297 private: 298 PixelStoreState m_pixelStore; 299 VertexAttribState *m_states; 300 int m_maxVertexAttribs; 301 bool m_maxVertexAttribsDirty; 302 int m_nLocations; 303 GLuint m_currentArrayVbo; 304 GLuint m_currentIndexVbo; 305 int m_activeTexture; 306 GLint m_currentProgram; 307 308 bool validLocation(int location) { return (location >= 0 && location < m_nLocations); } 309 310 enum TextureTarget { 311 TEXTURE_2D = 0, 312 TEXTURE_EXTERNAL = 1, 313 TEXTURE_TARGET_COUNT 314 }; 315 struct TextureUnit { 316 unsigned int enables; 317 GLuint texture[TEXTURE_TARGET_COUNT]; 318 }; 319 struct TextureRec { 320 GLuint id; 321 GLenum target; 322 GLint internalformat; 323 GLenum format; 324 GLenum type; 325 }; 326 struct TextureState { 327 TextureUnit unit[MAX_TEXTURE_UNITS]; 328 TextureUnit* activeUnit; 329 TextureRec* textures; 330 GLuint numTextures; 331 GLuint allocTextures; 332 }; 333 TextureState m_tex; 334 335 // State tracking of cube map definitions. 336 // Currently used only for driver workarounds 337 // when using GL_LUMINANCE and defining cube maps with 338 // glCopyTexImage2D. 339 struct CubeMapDef { 340 GLuint id; 341 GLenum target; 342 GLint level; 343 GLenum internalformat; 344 }; 345 struct CubeMapDefCompare { 346 bool operator() (const CubeMapDef& a, 347 const CubeMapDef& b) const { 348 if (a.id != b.id) return a.id < b.id; 349 if (a.target != b.target) return a.target < b.target; 350 if (a.level != b.level) return a.level < b.level; 351 if (a.internalformat != b.internalformat) 352 return a.internalformat < b.internalformat; 353 return false; 354 } 355 }; 356 std::set<CubeMapDef, CubeMapDefCompare> m_cubeMapDefs; 357 void writeCopyTexImageState(GLenum target, GLint level, 358 GLenum internalformat); 359 GLenum copyTexImageNeededTarget(GLenum target, GLint level, 360 GLenum internalformat); 361 362 struct RboState { 363 GLuint boundRenderbuffer; 364 size_t boundRenderbufferIndex; 365 std::vector<RboProps> rboData; 366 }; 367 RboState mRboState; 368 void addFreshRenderbuffer(GLuint name); 369 void setBoundRenderbufferIndex(); 370 size_t getRboIndex(GLuint name) const; 371 RboProps& boundRboProps(); 372 const RboProps& boundRboProps_const() const; 373 374 struct FboState { 375 GLuint boundFramebuffer; 376 size_t boundFramebufferIndex; 377 std::vector<FboProps> fboData; 378 GLenum fboCheckStatus; 379 }; 380 FboState mFboState; 381 void addFreshFramebuffer(GLuint name); 382 void setBoundFramebufferIndex(); 383 size_t getFboIndex(GLuint name) const; 384 FboProps& boundFboProps(); 385 const FboProps& boundFboProps_const() const; 386 387 // Querying framebuffer format 388 GLenum queryRboFormat(GLuint name) const; 389 GLint queryTexInternalFormat(GLuint name) const; 390 GLenum queryTexFormat(GLuint name) const; 391 GLenum queryTexType(GLuint name) const; 392 393 static int compareTexId(const void* pid, const void* prec); 394 TextureRec* addTextureRec(GLuint id, GLenum target); 395 396 public: 397 void getClientStatePointer(GLenum pname, GLvoid** params); 398 399 template <class T> 400 int getVertexAttribParameter(GLuint index, GLenum param, T *ptr) 401 { 402 bool handled = true; 403 const VertexAttribState *vertexAttrib = getState(index); 404 if (vertexAttrib == NULL) { 405 ERR("getVeterxAttriParameter for non existant index %d\n", index); 406 // set gl error; 407 return handled; 408 } 409 410 switch(param) { 411 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING: 412 *ptr = (T)(vertexAttrib->bufferObject); 413 break; 414 case GL_VERTEX_ATTRIB_ARRAY_ENABLED: 415 *ptr = (T)(vertexAttrib->enabled); 416 break; 417 case GL_VERTEX_ATTRIB_ARRAY_SIZE: 418 *ptr = (T)(vertexAttrib->size); 419 break; 420 case GL_VERTEX_ATTRIB_ARRAY_STRIDE: 421 *ptr = (T)(vertexAttrib->stride); 422 break; 423 case GL_VERTEX_ATTRIB_ARRAY_TYPE: 424 *ptr = (T)(vertexAttrib->type); 425 break; 426 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED: 427 *ptr = (T)(vertexAttrib->normalized); 428 break; 429 case GL_CURRENT_VERTEX_ATTRIB: 430 handled = false; 431 break; 432 default: 433 handled = false; 434 ERR("unknown vertex-attrib parameter param %d\n", param); 435 } 436 return handled; 437 } 438 439 template <class T> 440 bool getClientStateParameter(GLenum param, T* ptr) 441 { 442 bool isClientStateParam = false; 443 switch (param) { 444 case GL_CLIENT_ACTIVE_TEXTURE: { 445 GLint tex = getActiveTexture() + GL_TEXTURE0; 446 *ptr = tex; 447 isClientStateParam = true; 448 break; 449 } 450 case GL_VERTEX_ARRAY_SIZE: { 451 const GLClientState::VertexAttribState *state = getState(GLClientState::VERTEX_LOCATION); 452 *ptr = state->size; 453 isClientStateParam = true; 454 break; 455 } 456 case GL_VERTEX_ARRAY_TYPE: { 457 const GLClientState::VertexAttribState *state = getState(GLClientState::VERTEX_LOCATION); 458 *ptr = state->type; 459 isClientStateParam = true; 460 break; 461 } 462 case GL_VERTEX_ARRAY_STRIDE: { 463 const GLClientState::VertexAttribState *state = getState(GLClientState::VERTEX_LOCATION); 464 *ptr = state->stride; 465 isClientStateParam = true; 466 break; 467 } 468 case GL_COLOR_ARRAY_SIZE: { 469 const GLClientState::VertexAttribState *state = getState(GLClientState::COLOR_LOCATION); 470 *ptr = state->size; 471 isClientStateParam = true; 472 break; 473 } 474 case GL_COLOR_ARRAY_TYPE: { 475 const GLClientState::VertexAttribState *state = getState(GLClientState::COLOR_LOCATION); 476 *ptr = state->type; 477 isClientStateParam = true; 478 break; 479 } 480 case GL_COLOR_ARRAY_STRIDE: { 481 const GLClientState::VertexAttribState *state = getState(GLClientState::COLOR_LOCATION); 482 *ptr = state->stride; 483 isClientStateParam = true; 484 break; 485 } 486 case GL_NORMAL_ARRAY_TYPE: { 487 const GLClientState::VertexAttribState *state = getState(GLClientState::NORMAL_LOCATION); 488 *ptr = state->type; 489 isClientStateParam = true; 490 break; 491 } 492 case GL_NORMAL_ARRAY_STRIDE: { 493 const GLClientState::VertexAttribState *state = getState(GLClientState::NORMAL_LOCATION); 494 *ptr = state->stride; 495 isClientStateParam = true; 496 break; 497 } 498 case GL_TEXTURE_COORD_ARRAY_SIZE: { 499 const GLClientState::VertexAttribState *state = getState(getActiveTexture() + GLClientState::TEXCOORD0_LOCATION); 500 *ptr = state->size; 501 isClientStateParam = true; 502 break; 503 } 504 case GL_TEXTURE_COORD_ARRAY_TYPE: { 505 const GLClientState::VertexAttribState *state = getState(getActiveTexture() + GLClientState::TEXCOORD0_LOCATION); 506 *ptr = state->type; 507 isClientStateParam = true; 508 break; 509 } 510 case GL_TEXTURE_COORD_ARRAY_STRIDE: { 511 const GLClientState::VertexAttribState *state = getState(getActiveTexture() + GLClientState::TEXCOORD0_LOCATION); 512 *ptr = state->stride; 513 isClientStateParam = true; 514 break; 515 } 516 case GL_POINT_SIZE_ARRAY_TYPE_OES: { 517 const GLClientState::VertexAttribState *state = getState(GLClientState::POINTSIZE_LOCATION); 518 *ptr = state->type; 519 isClientStateParam = true; 520 break; 521 } 522 case GL_POINT_SIZE_ARRAY_STRIDE_OES: { 523 const GLClientState::VertexAttribState *state = getState(GLClientState::POINTSIZE_LOCATION); 524 *ptr = state->stride; 525 isClientStateParam = true; 526 break; 527 } 528 case GL_MATRIX_INDEX_ARRAY_SIZE_OES: { 529 const GLClientState::VertexAttribState *state = getState(GLClientState::MATRIXINDEX_LOCATION); 530 *ptr = state->size; 531 isClientStateParam = true; 532 break; 533 } 534 case GL_MATRIX_INDEX_ARRAY_TYPE_OES: { 535 const GLClientState::VertexAttribState *state = getState(GLClientState::MATRIXINDEX_LOCATION); 536 *ptr = state->type; 537 isClientStateParam = true; 538 break; 539 } 540 case GL_MATRIX_INDEX_ARRAY_STRIDE_OES: { 541 const GLClientState::VertexAttribState *state = getState(GLClientState::MATRIXINDEX_LOCATION); 542 *ptr = state->stride; 543 isClientStateParam = true; 544 break; 545 } 546 case GL_WEIGHT_ARRAY_SIZE_OES: { 547 const GLClientState::VertexAttribState *state = getState(GLClientState::WEIGHT_LOCATION); 548 *ptr = state->size; 549 isClientStateParam = true; 550 break; 551 } 552 case GL_WEIGHT_ARRAY_TYPE_OES: { 553 const GLClientState::VertexAttribState *state = getState(GLClientState::WEIGHT_LOCATION); 554 *ptr = state->type; 555 isClientStateParam = true; 556 break; 557 } 558 case GL_WEIGHT_ARRAY_STRIDE_OES: { 559 const GLClientState::VertexAttribState *state = getState(GLClientState::WEIGHT_LOCATION); 560 *ptr = state->stride; 561 isClientStateParam = true; 562 break; 563 } 564 case GL_VERTEX_ARRAY_BUFFER_BINDING: { 565 const GLClientState::VertexAttribState *state = getState(GLClientState::VERTEX_LOCATION); 566 *ptr = state->bufferObject; 567 isClientStateParam = true; 568 break; 569 } 570 case GL_NORMAL_ARRAY_BUFFER_BINDING: { 571 const GLClientState::VertexAttribState *state = getState(GLClientState::NORMAL_LOCATION); 572 *ptr = state->bufferObject; 573 isClientStateParam = true; 574 break; 575 } 576 case GL_COLOR_ARRAY_BUFFER_BINDING: { 577 const GLClientState::VertexAttribState *state = getState(GLClientState::COLOR_LOCATION); 578 *ptr = state->bufferObject; 579 isClientStateParam = true; 580 break; 581 } 582 case GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING: { 583 const GLClientState::VertexAttribState *state = getState(getActiveTexture()+GLClientState::TEXCOORD0_LOCATION); 584 *ptr = state->bufferObject; 585 isClientStateParam = true; 586 break; 587 } 588 case GL_POINT_SIZE_ARRAY_BUFFER_BINDING_OES: { 589 const GLClientState::VertexAttribState *state = getState(GLClientState::POINTSIZE_LOCATION); 590 *ptr = state->bufferObject; 591 isClientStateParam = true; 592 break; 593 } 594 case GL_MATRIX_INDEX_ARRAY_BUFFER_BINDING_OES: { 595 const GLClientState::VertexAttribState *state = getState(GLClientState::MATRIXINDEX_LOCATION); 596 *ptr = state->bufferObject; 597 isClientStateParam = true; 598 break; 599 } 600 case GL_WEIGHT_ARRAY_BUFFER_BINDING_OES: { 601 const GLClientState::VertexAttribState *state = getState(GLClientState::WEIGHT_LOCATION); 602 *ptr = state->bufferObject; 603 isClientStateParam = true; 604 break; 605 } 606 case GL_ARRAY_BUFFER_BINDING: { 607 int buffer = getBuffer(GL_ARRAY_BUFFER); 608 *ptr = buffer; 609 isClientStateParam = true; 610 break; 611 } 612 case GL_ELEMENT_ARRAY_BUFFER_BINDING: { 613 int buffer = getBuffer(GL_ELEMENT_ARRAY_BUFFER); 614 *ptr = buffer; 615 isClientStateParam = true; 616 break; 617 } 618 case GL_MAX_VERTEX_ATTRIBS: { 619 if (m_maxVertexAttribsDirty) { 620 isClientStateParam = false; 621 } else { 622 *ptr = m_maxVertexAttribs; 623 isClientStateParam = true; 624 } 625 break; 626 } 627 } 628 return isClientStateParam; 629 } 630 631 }; 632 #endif 633