1 // 2 // Copyright 2002 The ANGLE Project Authors. All rights reserved. 3 // Use of this source code is governed by a BSD-style license that can be 4 // found in the LICENSE file. 5 // 6 7 // Texture.h: Defines the gl::Texture class [OpenGL ES 2.0.24] section 3.7 page 63. 8 9 #ifndef LIBANGLE_TEXTURE_H_ 10 #define LIBANGLE_TEXTURE_H_ 11 12 #include <map> 13 #include <vector> 14 15 #include "angle_gl.h" 16 #include "common/Optional.h" 17 #include "common/debug.h" 18 #include "common/utilities.h" 19 #include "libANGLE/Caps.h" 20 #include "libANGLE/Constants.h" 21 #include "libANGLE/Debug.h" 22 #include "libANGLE/Error.h" 23 #include "libANGLE/FramebufferAttachment.h" 24 #include "libANGLE/Image.h" 25 #include "libANGLE/Observer.h" 26 #include "libANGLE/Stream.h" 27 #include "libANGLE/angletypes.h" 28 #include "libANGLE/formatutils.h" 29 30 namespace egl 31 { 32 class Surface; 33 class Stream; 34 } // namespace egl 35 36 namespace rx 37 { 38 class GLImplFactory; 39 class TextureImpl; 40 class TextureGL; 41 } // namespace rx 42 43 namespace gl 44 { 45 class Framebuffer; 46 class MemoryObject; 47 class Sampler; 48 class State; 49 class Texture; 50 51 bool IsMipmapFiltered(const SamplerState &samplerState); 52 53 struct ImageDesc final 54 { 55 ImageDesc(); 56 ImageDesc(const Extents &size, const Format &format, const InitState initState); 57 ImageDesc(const Extents &size, 58 const Format &format, 59 const GLsizei samples, 60 const bool fixedSampleLocations, 61 const InitState initState); 62 63 ImageDesc(const ImageDesc &other) = default; 64 ImageDesc &operator=(const ImageDesc &other) = default; 65 66 GLint getMemorySize() const; 67 68 Extents size; 69 Format format; 70 GLsizei samples; 71 bool fixedSampleLocations; 72 73 // Needed for robust resource initialization. 74 InitState initState; 75 }; 76 77 struct SwizzleState final 78 { 79 SwizzleState(); 80 SwizzleState(GLenum red, GLenum green, GLenum blue, GLenum alpha); 81 SwizzleState(const SwizzleState &other) = default; 82 SwizzleState &operator=(const SwizzleState &other) = default; 83 84 bool swizzleRequired() const; 85 86 bool operator==(const SwizzleState &other) const; 87 bool operator!=(const SwizzleState &other) const; 88 89 GLenum swizzleRed; 90 GLenum swizzleGreen; 91 GLenum swizzleBlue; 92 GLenum swizzleAlpha; 93 }; 94 95 struct ContextBindingCount 96 { 97 ContextID contextID; 98 uint32_t samplerBindingCount; 99 uint32_t imageBindingCount; 100 }; 101 102 // State from Table 6.9 (state per texture object) in the OpenGL ES 3.0.2 spec. 103 class TextureState final : private angle::NonCopyable 104 { 105 public: 106 TextureState(TextureType type); 107 ~TextureState(); 108 109 bool swizzleRequired() const; 110 GLuint getEffectiveBaseLevel() const; 111 GLuint getEffectiveMaxLevel() const; 112 113 // Returns the value called "q" in the GLES 3.0.4 spec section 3.8.10. 114 GLuint getMipmapMaxLevel() const; 115 116 // Returns true if base level changed. 117 bool setBaseLevel(GLuint baseLevel); 118 bool setMaxLevel(GLuint maxLevel); 119 120 bool isCubeComplete() const; 121 compatibleWithSamplerFormat(SamplerFormat format,const SamplerState & samplerState)122 ANGLE_INLINE bool compatibleWithSamplerFormat(SamplerFormat format, 123 const SamplerState &samplerState) const 124 { 125 if (!mCachedSamplerFormatValid || 126 mCachedSamplerCompareMode != samplerState.getCompareMode()) 127 { 128 mCachedSamplerFormat = computeRequiredSamplerFormat(samplerState); 129 mCachedSamplerCompareMode = samplerState.getCompareMode(); 130 mCachedSamplerFormatValid = true; 131 } 132 // Incomplete textures are compatible with any sampler format. 133 return mCachedSamplerFormat == SamplerFormat::InvalidEnum || format == mCachedSamplerFormat; 134 } 135 136 const ImageDesc &getImageDesc(TextureTarget target, size_t level) const; 137 const ImageDesc &getImageDesc(const ImageIndex &imageIndex) const; 138 getType()139 TextureType getType() const { return mType; } getSwizzleState()140 const SwizzleState &getSwizzleState() const { return mSwizzleState; } getSamplerState()141 const SamplerState &getSamplerState() const { return mSamplerState; } getUsage()142 GLenum getUsage() const { return mUsage; } getDepthStencilTextureMode()143 GLenum getDepthStencilTextureMode() const { return mDepthStencilTextureMode; } isStencilMode()144 bool isStencilMode() const { return mDepthStencilTextureMode == GL_STENCIL_INDEX; } isBoundAsSamplerTexture(ContextID contextID)145 bool isBoundAsSamplerTexture(ContextID contextID) const 146 { 147 return getBindingCount(contextID).samplerBindingCount > 0; 148 } isBoundAsImageTexture(ContextID contextID)149 bool isBoundAsImageTexture(ContextID contextID) const 150 { 151 return getBindingCount(contextID).imageBindingCount > 0; 152 } 153 getSRGBOverride()154 gl::SrgbOverride getSRGBOverride() const { return mSrgbOverride; } 155 156 // Returns the desc of the base level. Only valid for cube-complete/mip-complete textures. 157 const ImageDesc &getBaseLevelDesc() const; 158 159 // GLES1 emulation: For GL_OES_draw_texture 160 void setCrop(const Rectangle &rect); 161 const Rectangle &getCrop() const; 162 163 // GLES1 emulation: Auto-mipmap generation is a texparameter 164 void setGenerateMipmapHint(GLenum hint); 165 GLenum getGenerateMipmapHint() const; 166 167 // Return the enabled mipmap level count. 168 GLuint getEnabledLevelCount() const; 169 170 private: 171 // Texture needs access to the ImageDesc functions. 172 friend class Texture; 173 // TODO(jmadill): Remove TextureGL from friends. 174 friend class rx::TextureGL; 175 friend bool operator==(const TextureState &a, const TextureState &b); 176 177 bool computeSamplerCompleteness(const SamplerState &samplerState, const State &state) const; 178 bool computeMipmapCompleteness() const; 179 bool computeLevelCompleteness(TextureTarget target, size_t level) const; 180 SamplerFormat computeRequiredSamplerFormat(const SamplerState &samplerState) const; 181 182 TextureTarget getBaseImageTarget() const; 183 184 void setImageDesc(TextureTarget target, size_t level, const ImageDesc &desc); 185 void setImageDescChain(GLuint baselevel, 186 GLuint maxLevel, 187 Extents baseSize, 188 const Format &format, 189 InitState initState); 190 void setImageDescChainMultisample(Extents baseSize, 191 const Format &format, 192 GLsizei samples, 193 bool fixedSampleLocations, 194 InitState initState); 195 196 void clearImageDesc(TextureTarget target, size_t level); 197 void clearImageDescs(); 198 getBindingCount(ContextID contextID)199 ContextBindingCount &getBindingCount(ContextID contextID) 200 { 201 for (ContextBindingCount &bindingCount : mBindingCounts) 202 { 203 if (bindingCount.contextID == contextID) 204 return bindingCount; 205 } 206 mBindingCounts.push_back({contextID, 0, 0}); 207 return mBindingCounts.back(); 208 } 209 getBindingCount(ContextID contextID)210 const ContextBindingCount &getBindingCount(ContextID contextID) const 211 { 212 return const_cast<TextureState *>(this)->getBindingCount(contextID); 213 } 214 215 const TextureType mType; 216 217 SwizzleState mSwizzleState; 218 219 SamplerState mSamplerState; 220 221 SrgbOverride mSrgbOverride; 222 223 GLuint mBaseLevel; 224 GLuint mMaxLevel; 225 226 GLenum mDepthStencilTextureMode; 227 228 std::vector<ContextBindingCount> mBindingCounts; 229 230 bool mImmutableFormat; 231 GLuint mImmutableLevels; 232 233 // From GL_ANGLE_texture_usage 234 GLenum mUsage; 235 236 std::vector<ImageDesc> mImageDescs; 237 238 // GLES1 emulation: Texture crop rectangle 239 // For GL_OES_draw_texture 240 Rectangle mCropRect; 241 242 // GLES1 emulation: Generate-mipmap hint per texture 243 GLenum mGenerateMipmapHint; 244 245 InitState mInitState; 246 247 mutable SamplerFormat mCachedSamplerFormat; 248 mutable GLenum mCachedSamplerCompareMode; 249 mutable bool mCachedSamplerFormatValid; 250 }; 251 252 bool operator==(const TextureState &a, const TextureState &b); 253 bool operator!=(const TextureState &a, const TextureState &b); 254 255 class Texture final : public RefCountObject<TextureID>, 256 public egl::ImageSibling, 257 public LabeledObject 258 { 259 public: 260 Texture(rx::GLImplFactory *factory, TextureID id, TextureType type); 261 ~Texture() override; 262 263 void onDestroy(const Context *context) override; 264 265 void setLabel(const Context *context, const std::string &label) override; 266 const std::string &getLabel() const override; 267 getType()268 TextureType getType() const { return mState.mType; } 269 270 void setSwizzleRed(const Context *context, GLenum swizzleRed); 271 GLenum getSwizzleRed() const; 272 273 void setSwizzleGreen(const Context *context, GLenum swizzleGreen); 274 GLenum getSwizzleGreen() const; 275 276 void setSwizzleBlue(const Context *context, GLenum swizzleBlue); 277 GLenum getSwizzleBlue() const; 278 279 void setSwizzleAlpha(const Context *context, GLenum swizzleAlpha); 280 GLenum getSwizzleAlpha() const; 281 282 void setMinFilter(const Context *context, GLenum minFilter); 283 GLenum getMinFilter() const; 284 285 void setMagFilter(const Context *context, GLenum magFilter); 286 GLenum getMagFilter() const; 287 288 void setWrapS(const Context *context, GLenum wrapS); 289 GLenum getWrapS() const; 290 291 void setWrapT(const Context *context, GLenum wrapT); 292 GLenum getWrapT() const; 293 294 void setWrapR(const Context *context, GLenum wrapR); 295 GLenum getWrapR() const; 296 297 void setMaxAnisotropy(const Context *context, float maxAnisotropy); 298 float getMaxAnisotropy() const; 299 300 void setMinLod(const Context *context, GLfloat minLod); 301 GLfloat getMinLod() const; 302 303 void setMaxLod(const Context *context, GLfloat maxLod); 304 GLfloat getMaxLod() const; 305 306 void setCompareMode(const Context *context, GLenum compareMode); 307 GLenum getCompareMode() const; 308 309 void setCompareFunc(const Context *context, GLenum compareFunc); 310 GLenum getCompareFunc() const; 311 312 void setSRGBDecode(const Context *context, GLenum sRGBDecode); 313 GLenum getSRGBDecode() const; 314 315 void setSRGBOverride(const Context *context, GLenum sRGBOverride); 316 GLenum getSRGBOverride() const; 317 318 const SamplerState &getSamplerState() const; 319 320 angle::Result setBaseLevel(const Context *context, GLuint baseLevel); 321 GLuint getBaseLevel() const; 322 323 void setMaxLevel(const Context *context, GLuint maxLevel); 324 GLuint getMaxLevel() const; 325 326 void setDepthStencilTextureMode(const Context *context, GLenum mode); 327 GLenum getDepthStencilTextureMode() const; 328 329 bool getImmutableFormat() const; 330 331 GLuint getImmutableLevels() const; 332 333 void setUsage(const Context *context, GLenum usage); 334 GLenum getUsage() const; 335 336 void setBorderColor(const Context *context, const ColorGeneric &color); 337 const ColorGeneric &getBorderColor() const; 338 339 const TextureState &getTextureState() const; 340 341 const Extents &getExtents(TextureTarget target, size_t level) const; 342 size_t getWidth(TextureTarget target, size_t level) const; 343 size_t getHeight(TextureTarget target, size_t level) const; 344 size_t getDepth(TextureTarget target, size_t level) const; 345 GLsizei getSamples(TextureTarget target, size_t level) const; 346 bool getFixedSampleLocations(TextureTarget target, size_t level) const; 347 const Format &getFormat(TextureTarget target, size_t level) const; 348 349 // Returns the value called "q" in the GLES 3.0.4 spec section 3.8.10. 350 GLuint getMipmapMaxLevel() const; 351 352 bool isMipmapComplete() const; 353 354 angle::Result setImage(Context *context, 355 const PixelUnpackState &unpackState, 356 Buffer *unpackBuffer, 357 TextureTarget target, 358 GLint level, 359 GLenum internalFormat, 360 const Extents &size, 361 GLenum format, 362 GLenum type, 363 const uint8_t *pixels); 364 angle::Result setSubImage(Context *context, 365 const PixelUnpackState &unpackState, 366 Buffer *unpackBuffer, 367 TextureTarget target, 368 GLint level, 369 const Box &area, 370 GLenum format, 371 GLenum type, 372 const uint8_t *pixels); 373 374 angle::Result setCompressedImage(Context *context, 375 const PixelUnpackState &unpackState, 376 TextureTarget target, 377 GLint level, 378 GLenum internalFormat, 379 const Extents &size, 380 size_t imageSize, 381 const uint8_t *pixels); 382 angle::Result setCompressedSubImage(const Context *context, 383 const PixelUnpackState &unpackState, 384 TextureTarget target, 385 GLint level, 386 const Box &area, 387 GLenum format, 388 size_t imageSize, 389 const uint8_t *pixels); 390 391 angle::Result copyImage(Context *context, 392 TextureTarget target, 393 GLint level, 394 const Rectangle &sourceArea, 395 GLenum internalFormat, 396 Framebuffer *source); 397 angle::Result copySubImage(Context *context, 398 const ImageIndex &index, 399 const Offset &destOffset, 400 const Rectangle &sourceArea, 401 Framebuffer *source); 402 403 angle::Result copyTexture(Context *context, 404 TextureTarget target, 405 GLint level, 406 GLenum internalFormat, 407 GLenum type, 408 GLint sourceLevel, 409 bool unpackFlipY, 410 bool unpackPremultiplyAlpha, 411 bool unpackUnmultiplyAlpha, 412 Texture *source); 413 angle::Result copySubTexture(const Context *context, 414 TextureTarget target, 415 GLint level, 416 const Offset &destOffset, 417 GLint sourceLevel, 418 const Box &sourceBox, 419 bool unpackFlipY, 420 bool unpackPremultiplyAlpha, 421 bool unpackUnmultiplyAlpha, 422 Texture *source); 423 angle::Result copyCompressedTexture(Context *context, const Texture *source); 424 425 angle::Result setStorage(Context *context, 426 TextureType type, 427 GLsizei levels, 428 GLenum internalFormat, 429 const Extents &size); 430 431 angle::Result setStorageMultisample(Context *context, 432 TextureType type, 433 GLsizei samples, 434 GLint internalformat, 435 const Extents &size, 436 bool fixedSampleLocations); 437 438 angle::Result setStorageExternalMemory(Context *context, 439 TextureType type, 440 GLsizei levels, 441 GLenum internalFormat, 442 const Extents &size, 443 MemoryObject *memoryObject, 444 GLuint64 offset); 445 446 angle::Result setImageExternal(Context *context, 447 TextureTarget target, 448 GLint level, 449 GLenum internalFormat, 450 const Extents &size, 451 GLenum format, 452 GLenum type); 453 454 angle::Result setEGLImageTarget(Context *context, TextureType type, egl::Image *imageTarget); 455 456 angle::Result generateMipmap(Context *context); 457 458 void onBindAsImageTexture(ContextID contextID); 459 onUnbindAsImageTexture(ContextID contextID)460 ANGLE_INLINE void onUnbindAsImageTexture(ContextID contextID) 461 { 462 ASSERT(mState.isBoundAsImageTexture(contextID)); 463 mState.getBindingCount(contextID).imageBindingCount--; 464 } 465 onBindAsSamplerTexture(ContextID contextID)466 ANGLE_INLINE void onBindAsSamplerTexture(ContextID contextID) 467 { 468 ContextBindingCount &bindingCount = mState.getBindingCount(contextID); 469 470 ASSERT(bindingCount.samplerBindingCount < std::numeric_limits<uint32_t>::max()); 471 bindingCount.samplerBindingCount++; 472 if (bindingCount.samplerBindingCount == 1) 473 { 474 onStateChange(angle::SubjectMessage::BindingChanged); 475 } 476 } 477 onUnbindAsSamplerTexture(ContextID contextID)478 ANGLE_INLINE void onUnbindAsSamplerTexture(ContextID contextID) 479 { 480 ContextBindingCount &bindingCount = mState.getBindingCount(contextID); 481 482 ASSERT(mState.isBoundAsSamplerTexture(contextID)); 483 bindingCount.samplerBindingCount--; 484 if (bindingCount.samplerBindingCount == 0) 485 { 486 onStateChange(angle::SubjectMessage::BindingChanged); 487 } 488 } 489 490 egl::Surface *getBoundSurface() const; 491 egl::Stream *getBoundStream() const; 492 493 GLint getMemorySize() const; 494 GLint getLevelMemorySize(TextureTarget target, GLint level) const; 495 496 void signalDirtyStorage(InitState initState); 497 498 bool isSamplerComplete(const Context *context, const Sampler *optionalSampler); 499 500 GLenum getImplementationColorReadFormat(const Context *context) const; 501 GLenum getImplementationColorReadType(const Context *context) const; 502 503 // We pass the pack buffer and state explicitly so they can be overridden during capture. 504 angle::Result getTexImage(const Context *context, 505 const PixelPackState &packState, 506 Buffer *packBuffer, 507 TextureTarget target, 508 GLint level, 509 GLenum format, 510 GLenum type, 511 void *pixels); 512 getImplementation()513 rx::TextureImpl *getImplementation() const { return mTexture; } 514 515 // FramebufferAttachmentObject implementation 516 Extents getAttachmentSize(const ImageIndex &imageIndex) const override; 517 Format getAttachmentFormat(GLenum binding, const ImageIndex &imageIndex) const override; 518 GLsizei getAttachmentSamples(const ImageIndex &imageIndex) const override; 519 bool isRenderable(const Context *context, 520 GLenum binding, 521 const ImageIndex &imageIndex) const override; 522 523 bool getAttachmentFixedSampleLocations(const ImageIndex &imageIndex) const; 524 525 // GLES1 emulation 526 void setCrop(const Rectangle &rect); 527 const Rectangle &getCrop() const; 528 void setGenerateMipmapHint(GLenum generate); 529 GLenum getGenerateMipmapHint() const; 530 531 void onAttach(const Context *context) override; 532 void onDetach(const Context *context) override; 533 534 // Used specifically for FramebufferAttachmentObject. 535 GLuint getId() const override; 536 537 GLuint getNativeID() const; 538 539 // Needed for robust resource init. 540 angle::Result ensureInitialized(const Context *context); 541 InitState initState(const ImageIndex &imageIndex) const override; initState()542 InitState initState() const { return mState.mInitState; } 543 void setInitState(const ImageIndex &imageIndex, InitState initState) override; 544 545 enum DirtyBitType 546 { 547 // Sampler state 548 DIRTY_BIT_MIN_FILTER, 549 DIRTY_BIT_MAG_FILTER, 550 DIRTY_BIT_WRAP_S, 551 DIRTY_BIT_WRAP_T, 552 DIRTY_BIT_WRAP_R, 553 DIRTY_BIT_MAX_ANISOTROPY, 554 DIRTY_BIT_MIN_LOD, 555 DIRTY_BIT_MAX_LOD, 556 DIRTY_BIT_COMPARE_MODE, 557 DIRTY_BIT_COMPARE_FUNC, 558 DIRTY_BIT_SRGB_DECODE, 559 DIRTY_BIT_SRGB_OVERRIDE, 560 DIRTY_BIT_BORDER_COLOR, 561 562 // Texture state 563 DIRTY_BIT_SWIZZLE_RED, 564 DIRTY_BIT_SWIZZLE_GREEN, 565 DIRTY_BIT_SWIZZLE_BLUE, 566 DIRTY_BIT_SWIZZLE_ALPHA, 567 DIRTY_BIT_BASE_LEVEL, 568 DIRTY_BIT_MAX_LEVEL, 569 DIRTY_BIT_DEPTH_STENCIL_TEXTURE_MODE, 570 571 // Image state 572 DIRTY_BIT_BOUND_AS_IMAGE, 573 574 // Misc 575 DIRTY_BIT_LABEL, 576 DIRTY_BIT_USAGE, 577 DIRTY_BIT_IMPLEMENTATION, 578 579 DIRTY_BIT_COUNT, 580 }; 581 using DirtyBits = angle::BitSet<DIRTY_BIT_COUNT>; 582 583 angle::Result syncState(const Context *context); hasAnyDirtyBit()584 bool hasAnyDirtyBit() const { return mDirtyBits.any(); } 585 586 // ObserverInterface implementation. 587 void onSubjectStateChange(angle::SubjectIndex index, angle::SubjectMessage message) override; 588 589 private: 590 rx::FramebufferAttachmentObjectImpl *getAttachmentImpl() const override; 591 592 // ANGLE-only method, used internally 593 friend class egl::Surface; 594 angle::Result bindTexImageFromSurface(Context *context, egl::Surface *surface); 595 angle::Result releaseTexImageFromSurface(const Context *context); 596 597 // ANGLE-only methods, used internally 598 friend class egl::Stream; 599 void bindStream(egl::Stream *stream); 600 void releaseStream(); 601 angle::Result acquireImageFromStream(const Context *context, 602 const egl::Stream::GLTextureDescription &desc); 603 angle::Result releaseImageFromStream(const Context *context); 604 605 void invalidateCompletenessCache() const; 606 angle::Result releaseTexImageInternal(Context *context); 607 608 bool doesSubImageNeedInit(const Context *context, 609 const ImageIndex &imageIndex, 610 const Box &area) const; 611 angle::Result ensureSubImageInitialized(const Context *context, 612 const ImageIndex &imageIndex, 613 const Box &area); 614 615 angle::Result handleMipmapGenerationHint(Context *context, int level); 616 617 void signalDirtyState(size_t dirtyBit); 618 619 TextureState mState; 620 DirtyBits mDirtyBits; 621 rx::TextureImpl *mTexture; 622 angle::ObserverBinding mImplObserver; 623 624 std::string mLabel; 625 626 egl::Surface *mBoundSurface; 627 egl::Stream *mBoundStream; 628 629 struct SamplerCompletenessCache 630 { 631 SamplerCompletenessCache(); 632 633 // Context used to generate this cache entry 634 ContextID context; 635 636 // All values that affect sampler completeness that are not stored within 637 // the texture itself 638 SamplerState samplerState; 639 640 // Result of the sampler completeness with the above parameters 641 bool samplerComplete; 642 }; 643 644 mutable SamplerCompletenessCache mCompletenessCache; 645 }; 646 647 inline bool operator==(const TextureState &a, const TextureState &b) 648 { 649 return a.mSwizzleState == b.mSwizzleState && a.mSamplerState == b.mSamplerState && 650 a.mBaseLevel == b.mBaseLevel && a.mMaxLevel == b.mMaxLevel && 651 a.mImmutableFormat == b.mImmutableFormat && a.mImmutableLevels == b.mImmutableLevels && 652 a.mUsage == b.mUsage; 653 } 654 655 inline bool operator!=(const TextureState &a, const TextureState &b) 656 { 657 return !(a == b); 658 } 659 } // namespace gl 660 661 #endif // LIBANGLE_TEXTURE_H_ 662