• 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 
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