• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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