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