xref: /aosp_15_r20/external/angle/src/libANGLE/Texture.cpp (revision 8975f5c5ed3d1c378011245431ada316dfb6f244)
1*8975f5c5SAndroid Build Coastguard Worker //
2*8975f5c5SAndroid Build Coastguard Worker // Copyright 2002 The ANGLE Project Authors. All rights reserved.
3*8975f5c5SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
4*8975f5c5SAndroid Build Coastguard Worker // found in the LICENSE file.
5*8975f5c5SAndroid Build Coastguard Worker //
6*8975f5c5SAndroid Build Coastguard Worker 
7*8975f5c5SAndroid Build Coastguard Worker // Texture.cpp: Implements the gl::Texture class. [OpenGL ES 2.0.24] section 3.7 page 63.
8*8975f5c5SAndroid Build Coastguard Worker 
9*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/Texture.h"
10*8975f5c5SAndroid Build Coastguard Worker 
11*8975f5c5SAndroid Build Coastguard Worker #include "common/mathutil.h"
12*8975f5c5SAndroid Build Coastguard Worker #include "common/utilities.h"
13*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/Config.h"
14*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/Context.h"
15*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/Image.h"
16*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/State.h"
17*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/Surface.h"
18*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/formatutils.h"
19*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/renderer/ContextImpl.h"
20*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/renderer/GLImplFactory.h"
21*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/renderer/TextureImpl.h"
22*8975f5c5SAndroid Build Coastguard Worker 
23*8975f5c5SAndroid Build Coastguard Worker namespace gl
24*8975f5c5SAndroid Build Coastguard Worker {
25*8975f5c5SAndroid Build Coastguard Worker 
26*8975f5c5SAndroid Build Coastguard Worker namespace
27*8975f5c5SAndroid Build Coastguard Worker {
28*8975f5c5SAndroid Build Coastguard Worker constexpr angle::SubjectIndex kBufferSubjectIndex = 2;
29*8975f5c5SAndroid Build Coastguard Worker static_assert(kBufferSubjectIndex != rx::kTextureImageImplObserverMessageIndex, "Index collision");
30*8975f5c5SAndroid Build Coastguard Worker static_assert(kBufferSubjectIndex != rx::kTextureImageSiblingMessageIndex, "Index collision");
31*8975f5c5SAndroid Build Coastguard Worker 
IsPointSampled(const SamplerState & samplerState)32*8975f5c5SAndroid Build Coastguard Worker bool IsPointSampled(const SamplerState &samplerState)
33*8975f5c5SAndroid Build Coastguard Worker {
34*8975f5c5SAndroid Build Coastguard Worker     return (samplerState.getMagFilter() == GL_NEAREST &&
35*8975f5c5SAndroid Build Coastguard Worker             (samplerState.getMinFilter() == GL_NEAREST ||
36*8975f5c5SAndroid Build Coastguard Worker              samplerState.getMinFilter() == GL_NEAREST_MIPMAP_NEAREST));
37*8975f5c5SAndroid Build Coastguard Worker }
38*8975f5c5SAndroid Build Coastguard Worker 
GetImageDescIndex(TextureTarget target,size_t level)39*8975f5c5SAndroid Build Coastguard Worker size_t GetImageDescIndex(TextureTarget target, size_t level)
40*8975f5c5SAndroid Build Coastguard Worker {
41*8975f5c5SAndroid Build Coastguard Worker     return IsCubeMapFaceTarget(target) ? (level * 6 + CubeMapTextureTargetToFaceIndex(target))
42*8975f5c5SAndroid Build Coastguard Worker                                        : level;
43*8975f5c5SAndroid Build Coastguard Worker }
44*8975f5c5SAndroid Build Coastguard Worker 
DetermineInitState(const Context * context,Buffer * unpackBuffer,const uint8_t * pixels)45*8975f5c5SAndroid Build Coastguard Worker InitState DetermineInitState(const Context *context, Buffer *unpackBuffer, const uint8_t *pixels)
46*8975f5c5SAndroid Build Coastguard Worker {
47*8975f5c5SAndroid Build Coastguard Worker     // Can happen in tests.
48*8975f5c5SAndroid Build Coastguard Worker     if (!context || !context->isRobustResourceInitEnabled())
49*8975f5c5SAndroid Build Coastguard Worker     {
50*8975f5c5SAndroid Build Coastguard Worker         return InitState::Initialized;
51*8975f5c5SAndroid Build Coastguard Worker     }
52*8975f5c5SAndroid Build Coastguard Worker 
53*8975f5c5SAndroid Build Coastguard Worker     return (!pixels && !unpackBuffer) ? InitState::MayNeedInit : InitState::Initialized;
54*8975f5c5SAndroid Build Coastguard Worker }
55*8975f5c5SAndroid Build Coastguard Worker }  // namespace
56*8975f5c5SAndroid Build Coastguard Worker 
ConvertToNearestFilterMode(GLenum filterMode)57*8975f5c5SAndroid Build Coastguard Worker GLenum ConvertToNearestFilterMode(GLenum filterMode)
58*8975f5c5SAndroid Build Coastguard Worker {
59*8975f5c5SAndroid Build Coastguard Worker     switch (filterMode)
60*8975f5c5SAndroid Build Coastguard Worker     {
61*8975f5c5SAndroid Build Coastguard Worker         case GL_LINEAR:
62*8975f5c5SAndroid Build Coastguard Worker             return GL_NEAREST;
63*8975f5c5SAndroid Build Coastguard Worker         case GL_LINEAR_MIPMAP_NEAREST:
64*8975f5c5SAndroid Build Coastguard Worker             return GL_NEAREST_MIPMAP_NEAREST;
65*8975f5c5SAndroid Build Coastguard Worker         case GL_LINEAR_MIPMAP_LINEAR:
66*8975f5c5SAndroid Build Coastguard Worker             return GL_NEAREST_MIPMAP_LINEAR;
67*8975f5c5SAndroid Build Coastguard Worker         default:
68*8975f5c5SAndroid Build Coastguard Worker             return filterMode;
69*8975f5c5SAndroid Build Coastguard Worker     }
70*8975f5c5SAndroid Build Coastguard Worker }
71*8975f5c5SAndroid Build Coastguard Worker 
ConvertToNearestMipFilterMode(GLenum filterMode)72*8975f5c5SAndroid Build Coastguard Worker GLenum ConvertToNearestMipFilterMode(GLenum filterMode)
73*8975f5c5SAndroid Build Coastguard Worker {
74*8975f5c5SAndroid Build Coastguard Worker     switch (filterMode)
75*8975f5c5SAndroid Build Coastguard Worker     {
76*8975f5c5SAndroid Build Coastguard Worker         case GL_LINEAR_MIPMAP_LINEAR:
77*8975f5c5SAndroid Build Coastguard Worker             return GL_LINEAR_MIPMAP_NEAREST;
78*8975f5c5SAndroid Build Coastguard Worker         case GL_NEAREST_MIPMAP_LINEAR:
79*8975f5c5SAndroid Build Coastguard Worker             return GL_NEAREST_MIPMAP_NEAREST;
80*8975f5c5SAndroid Build Coastguard Worker         default:
81*8975f5c5SAndroid Build Coastguard Worker             return filterMode;
82*8975f5c5SAndroid Build Coastguard Worker     }
83*8975f5c5SAndroid Build Coastguard Worker }
84*8975f5c5SAndroid Build Coastguard Worker 
IsMipmapSupported(const TextureType & type)85*8975f5c5SAndroid Build Coastguard Worker bool IsMipmapSupported(const TextureType &type)
86*8975f5c5SAndroid Build Coastguard Worker {
87*8975f5c5SAndroid Build Coastguard Worker     switch (type)
88*8975f5c5SAndroid Build Coastguard Worker     {
89*8975f5c5SAndroid Build Coastguard Worker         case TextureType::_2DMultisample:
90*8975f5c5SAndroid Build Coastguard Worker         case TextureType::_2DMultisampleArray:
91*8975f5c5SAndroid Build Coastguard Worker         case TextureType::Buffer:
92*8975f5c5SAndroid Build Coastguard Worker             return false;
93*8975f5c5SAndroid Build Coastguard Worker         default:
94*8975f5c5SAndroid Build Coastguard Worker             return true;
95*8975f5c5SAndroid Build Coastguard Worker     }
96*8975f5c5SAndroid Build Coastguard Worker }
97*8975f5c5SAndroid Build Coastguard Worker 
SwizzleState()98*8975f5c5SAndroid Build Coastguard Worker SwizzleState::SwizzleState()
99*8975f5c5SAndroid Build Coastguard Worker     : swizzleRed(GL_RED), swizzleGreen(GL_GREEN), swizzleBlue(GL_BLUE), swizzleAlpha(GL_ALPHA)
100*8975f5c5SAndroid Build Coastguard Worker {}
101*8975f5c5SAndroid Build Coastguard Worker 
SwizzleState(GLenum red,GLenum green,GLenum blue,GLenum alpha)102*8975f5c5SAndroid Build Coastguard Worker SwizzleState::SwizzleState(GLenum red, GLenum green, GLenum blue, GLenum alpha)
103*8975f5c5SAndroid Build Coastguard Worker     : swizzleRed(red), swizzleGreen(green), swizzleBlue(blue), swizzleAlpha(alpha)
104*8975f5c5SAndroid Build Coastguard Worker {}
105*8975f5c5SAndroid Build Coastguard Worker 
swizzleRequired() const106*8975f5c5SAndroid Build Coastguard Worker bool SwizzleState::swizzleRequired() const
107*8975f5c5SAndroid Build Coastguard Worker {
108*8975f5c5SAndroid Build Coastguard Worker     return swizzleRed != GL_RED || swizzleGreen != GL_GREEN || swizzleBlue != GL_BLUE ||
109*8975f5c5SAndroid Build Coastguard Worker            swizzleAlpha != GL_ALPHA;
110*8975f5c5SAndroid Build Coastguard Worker }
111*8975f5c5SAndroid Build Coastguard Worker 
operator ==(const SwizzleState & other) const112*8975f5c5SAndroid Build Coastguard Worker bool SwizzleState::operator==(const SwizzleState &other) const
113*8975f5c5SAndroid Build Coastguard Worker {
114*8975f5c5SAndroid Build Coastguard Worker     return swizzleRed == other.swizzleRed && swizzleGreen == other.swizzleGreen &&
115*8975f5c5SAndroid Build Coastguard Worker            swizzleBlue == other.swizzleBlue && swizzleAlpha == other.swizzleAlpha;
116*8975f5c5SAndroid Build Coastguard Worker }
117*8975f5c5SAndroid Build Coastguard Worker 
operator !=(const SwizzleState & other) const118*8975f5c5SAndroid Build Coastguard Worker bool SwizzleState::operator!=(const SwizzleState &other) const
119*8975f5c5SAndroid Build Coastguard Worker {
120*8975f5c5SAndroid Build Coastguard Worker     return !(*this == other);
121*8975f5c5SAndroid Build Coastguard Worker }
122*8975f5c5SAndroid Build Coastguard Worker 
TextureState(TextureType type)123*8975f5c5SAndroid Build Coastguard Worker TextureState::TextureState(TextureType type)
124*8975f5c5SAndroid Build Coastguard Worker     : mType(type),
125*8975f5c5SAndroid Build Coastguard Worker       mSamplerState(SamplerState::CreateDefaultForTarget(type)),
126*8975f5c5SAndroid Build Coastguard Worker       mSrgbOverride(SrgbOverride::Default),
127*8975f5c5SAndroid Build Coastguard Worker       mBaseLevel(0),
128*8975f5c5SAndroid Build Coastguard Worker       mMaxLevel(kInitialMaxLevel),
129*8975f5c5SAndroid Build Coastguard Worker       mDepthStencilTextureMode(GL_DEPTH_COMPONENT),
130*8975f5c5SAndroid Build Coastguard Worker       mIsInternalIncompleteTexture(false),
131*8975f5c5SAndroid Build Coastguard Worker       mHasBeenBoundAsImage(false),
132*8975f5c5SAndroid Build Coastguard Worker       mHasBeenBoundAsAttachment(false),
133*8975f5c5SAndroid Build Coastguard Worker       mHasBeenBoundToMSRTTFramebuffer(false),
134*8975f5c5SAndroid Build Coastguard Worker       mImmutableFormat(false),
135*8975f5c5SAndroid Build Coastguard Worker       mImmutableLevels(0),
136*8975f5c5SAndroid Build Coastguard Worker       mUsage(GL_NONE),
137*8975f5c5SAndroid Build Coastguard Worker       mHasProtectedContent(false),
138*8975f5c5SAndroid Build Coastguard Worker       mRenderabilityValidation(true),
139*8975f5c5SAndroid Build Coastguard Worker       mTilingMode(gl::TilingMode::Optimal),
140*8975f5c5SAndroid Build Coastguard Worker       mImageDescs((IMPLEMENTATION_MAX_TEXTURE_LEVELS + 1) * (type == TextureType::CubeMap ? 6 : 1)),
141*8975f5c5SAndroid Build Coastguard Worker       mCropRect(0, 0, 0, 0),
142*8975f5c5SAndroid Build Coastguard Worker       mGenerateMipmapHint(GL_FALSE),
143*8975f5c5SAndroid Build Coastguard Worker       mInitState(InitState::Initialized),
144*8975f5c5SAndroid Build Coastguard Worker       mCachedSamplerFormat(SamplerFormat::InvalidEnum),
145*8975f5c5SAndroid Build Coastguard Worker       mCachedSamplerCompareMode(GL_NONE),
146*8975f5c5SAndroid Build Coastguard Worker       mCachedSamplerFormatValid(false),
147*8975f5c5SAndroid Build Coastguard Worker       mCompressionFixedRate(GL_SURFACE_COMPRESSION_FIXED_RATE_NONE_EXT)
148*8975f5c5SAndroid Build Coastguard Worker {}
149*8975f5c5SAndroid Build Coastguard Worker 
~TextureState()150*8975f5c5SAndroid Build Coastguard Worker TextureState::~TextureState() {}
151*8975f5c5SAndroid Build Coastguard Worker 
swizzleRequired() const152*8975f5c5SAndroid Build Coastguard Worker bool TextureState::swizzleRequired() const
153*8975f5c5SAndroid Build Coastguard Worker {
154*8975f5c5SAndroid Build Coastguard Worker     return mSwizzleState.swizzleRequired();
155*8975f5c5SAndroid Build Coastguard Worker }
156*8975f5c5SAndroid Build Coastguard Worker 
getEffectiveBaseLevel() const157*8975f5c5SAndroid Build Coastguard Worker GLuint TextureState::getEffectiveBaseLevel() const
158*8975f5c5SAndroid Build Coastguard Worker {
159*8975f5c5SAndroid Build Coastguard Worker     if (mImmutableFormat)
160*8975f5c5SAndroid Build Coastguard Worker     {
161*8975f5c5SAndroid Build Coastguard Worker         // GLES 3.0.4 section 3.8.10
162*8975f5c5SAndroid Build Coastguard Worker         return std::min(mBaseLevel, mImmutableLevels - 1);
163*8975f5c5SAndroid Build Coastguard Worker     }
164*8975f5c5SAndroid Build Coastguard Worker     // Some classes use the effective base level to index arrays with level data. By clamping the
165*8975f5c5SAndroid Build Coastguard Worker     // effective base level to max levels these arrays need just one extra item to store properties
166*8975f5c5SAndroid Build Coastguard Worker     // that should be returned for all out-of-range base level values, instead of needing special
167*8975f5c5SAndroid Build Coastguard Worker     // handling for out-of-range base levels.
168*8975f5c5SAndroid Build Coastguard Worker     return std::min(mBaseLevel, static_cast<GLuint>(IMPLEMENTATION_MAX_TEXTURE_LEVELS));
169*8975f5c5SAndroid Build Coastguard Worker }
170*8975f5c5SAndroid Build Coastguard Worker 
getEffectiveMaxLevel() const171*8975f5c5SAndroid Build Coastguard Worker GLuint TextureState::getEffectiveMaxLevel() const
172*8975f5c5SAndroid Build Coastguard Worker {
173*8975f5c5SAndroid Build Coastguard Worker     if (mImmutableFormat)
174*8975f5c5SAndroid Build Coastguard Worker     {
175*8975f5c5SAndroid Build Coastguard Worker         // GLES 3.0.4 section 3.8.10
176*8975f5c5SAndroid Build Coastguard Worker         GLuint clampedMaxLevel = std::max(mMaxLevel, getEffectiveBaseLevel());
177*8975f5c5SAndroid Build Coastguard Worker         clampedMaxLevel        = std::min(clampedMaxLevel, mImmutableLevels - 1);
178*8975f5c5SAndroid Build Coastguard Worker         return clampedMaxLevel;
179*8975f5c5SAndroid Build Coastguard Worker     }
180*8975f5c5SAndroid Build Coastguard Worker     return mMaxLevel;
181*8975f5c5SAndroid Build Coastguard Worker }
182*8975f5c5SAndroid Build Coastguard Worker 
getMipmapMaxLevel() const183*8975f5c5SAndroid Build Coastguard Worker GLuint TextureState::getMipmapMaxLevel() const
184*8975f5c5SAndroid Build Coastguard Worker {
185*8975f5c5SAndroid Build Coastguard Worker     const ImageDesc &baseImageDesc = getImageDesc(getBaseImageTarget(), getEffectiveBaseLevel());
186*8975f5c5SAndroid Build Coastguard Worker     GLuint expectedMipLevels       = 0;
187*8975f5c5SAndroid Build Coastguard Worker     if (mType == TextureType::_3D)
188*8975f5c5SAndroid Build Coastguard Worker     {
189*8975f5c5SAndroid Build Coastguard Worker         const int maxDim = std::max(
190*8975f5c5SAndroid Build Coastguard Worker             {baseImageDesc.size.width, baseImageDesc.size.height, baseImageDesc.size.depth});
191*8975f5c5SAndroid Build Coastguard Worker         expectedMipLevels = static_cast<GLuint>(log2(maxDim));
192*8975f5c5SAndroid Build Coastguard Worker     }
193*8975f5c5SAndroid Build Coastguard Worker     else
194*8975f5c5SAndroid Build Coastguard Worker     {
195*8975f5c5SAndroid Build Coastguard Worker         expectedMipLevels = static_cast<GLuint>(
196*8975f5c5SAndroid Build Coastguard Worker             log2(std::max(baseImageDesc.size.width, baseImageDesc.size.height)));
197*8975f5c5SAndroid Build Coastguard Worker     }
198*8975f5c5SAndroid Build Coastguard Worker 
199*8975f5c5SAndroid Build Coastguard Worker     return std::min<GLuint>(getEffectiveBaseLevel() + expectedMipLevels, getEffectiveMaxLevel());
200*8975f5c5SAndroid Build Coastguard Worker }
201*8975f5c5SAndroid Build Coastguard Worker 
setBaseLevel(GLuint baseLevel)202*8975f5c5SAndroid Build Coastguard Worker bool TextureState::setBaseLevel(GLuint baseLevel)
203*8975f5c5SAndroid Build Coastguard Worker {
204*8975f5c5SAndroid Build Coastguard Worker     if (mBaseLevel != baseLevel)
205*8975f5c5SAndroid Build Coastguard Worker     {
206*8975f5c5SAndroid Build Coastguard Worker         mBaseLevel = baseLevel;
207*8975f5c5SAndroid Build Coastguard Worker         return true;
208*8975f5c5SAndroid Build Coastguard Worker     }
209*8975f5c5SAndroid Build Coastguard Worker     return false;
210*8975f5c5SAndroid Build Coastguard Worker }
211*8975f5c5SAndroid Build Coastguard Worker 
setMaxLevel(GLuint maxLevel)212*8975f5c5SAndroid Build Coastguard Worker bool TextureState::setMaxLevel(GLuint maxLevel)
213*8975f5c5SAndroid Build Coastguard Worker {
214*8975f5c5SAndroid Build Coastguard Worker     if (mMaxLevel != maxLevel)
215*8975f5c5SAndroid Build Coastguard Worker     {
216*8975f5c5SAndroid Build Coastguard Worker         mMaxLevel = maxLevel;
217*8975f5c5SAndroid Build Coastguard Worker         return true;
218*8975f5c5SAndroid Build Coastguard Worker     }
219*8975f5c5SAndroid Build Coastguard Worker 
220*8975f5c5SAndroid Build Coastguard Worker     return false;
221*8975f5c5SAndroid Build Coastguard Worker }
222*8975f5c5SAndroid Build Coastguard Worker 
223*8975f5c5SAndroid Build Coastguard Worker // Tests for cube texture completeness. [OpenGL ES 2.0.24] section 3.7.10 page 81.
224*8975f5c5SAndroid Build Coastguard Worker // According to [OpenGL ES 3.0.5] section 3.8.13 Texture Completeness page 160 any
225*8975f5c5SAndroid Build Coastguard Worker // per-level checks begin at the base-level.
226*8975f5c5SAndroid Build Coastguard Worker // For OpenGL ES2 the base level is always zero.
isCubeComplete() const227*8975f5c5SAndroid Build Coastguard Worker bool TextureState::isCubeComplete() const
228*8975f5c5SAndroid Build Coastguard Worker {
229*8975f5c5SAndroid Build Coastguard Worker     ASSERT(mType == TextureType::CubeMap);
230*8975f5c5SAndroid Build Coastguard Worker 
231*8975f5c5SAndroid Build Coastguard Worker     angle::EnumIterator<TextureTarget> face = kCubeMapTextureTargetMin;
232*8975f5c5SAndroid Build Coastguard Worker     const ImageDesc &baseImageDesc          = getImageDesc(*face, getEffectiveBaseLevel());
233*8975f5c5SAndroid Build Coastguard Worker     if (baseImageDesc.size.width == 0 || baseImageDesc.size.width != baseImageDesc.size.height)
234*8975f5c5SAndroid Build Coastguard Worker     {
235*8975f5c5SAndroid Build Coastguard Worker         return false;
236*8975f5c5SAndroid Build Coastguard Worker     }
237*8975f5c5SAndroid Build Coastguard Worker 
238*8975f5c5SAndroid Build Coastguard Worker     ++face;
239*8975f5c5SAndroid Build Coastguard Worker 
240*8975f5c5SAndroid Build Coastguard Worker     for (; face != kAfterCubeMapTextureTargetMax; ++face)
241*8975f5c5SAndroid Build Coastguard Worker     {
242*8975f5c5SAndroid Build Coastguard Worker         const ImageDesc &faceImageDesc = getImageDesc(*face, getEffectiveBaseLevel());
243*8975f5c5SAndroid Build Coastguard Worker         if (faceImageDesc.size.width != baseImageDesc.size.width ||
244*8975f5c5SAndroid Build Coastguard Worker             faceImageDesc.size.height != baseImageDesc.size.height ||
245*8975f5c5SAndroid Build Coastguard Worker             !Format::SameSized(faceImageDesc.format, baseImageDesc.format))
246*8975f5c5SAndroid Build Coastguard Worker         {
247*8975f5c5SAndroid Build Coastguard Worker             return false;
248*8975f5c5SAndroid Build Coastguard Worker         }
249*8975f5c5SAndroid Build Coastguard Worker     }
250*8975f5c5SAndroid Build Coastguard Worker 
251*8975f5c5SAndroid Build Coastguard Worker     return true;
252*8975f5c5SAndroid Build Coastguard Worker }
253*8975f5c5SAndroid Build Coastguard Worker 
getBaseLevelDesc() const254*8975f5c5SAndroid Build Coastguard Worker const ImageDesc &TextureState::getBaseLevelDesc() const
255*8975f5c5SAndroid Build Coastguard Worker {
256*8975f5c5SAndroid Build Coastguard Worker     ASSERT(mType != TextureType::CubeMap || isCubeComplete());
257*8975f5c5SAndroid Build Coastguard Worker     return getImageDesc(getBaseImageTarget(), getEffectiveBaseLevel());
258*8975f5c5SAndroid Build Coastguard Worker }
259*8975f5c5SAndroid Build Coastguard Worker 
getLevelZeroDesc() const260*8975f5c5SAndroid Build Coastguard Worker const ImageDesc &TextureState::getLevelZeroDesc() const
261*8975f5c5SAndroid Build Coastguard Worker {
262*8975f5c5SAndroid Build Coastguard Worker     ASSERT(mType != TextureType::CubeMap || isCubeComplete());
263*8975f5c5SAndroid Build Coastguard Worker     return getImageDesc(getBaseImageTarget(), 0);
264*8975f5c5SAndroid Build Coastguard Worker }
265*8975f5c5SAndroid Build Coastguard Worker 
setCrop(const Rectangle & rect)266*8975f5c5SAndroid Build Coastguard Worker void TextureState::setCrop(const Rectangle &rect)
267*8975f5c5SAndroid Build Coastguard Worker {
268*8975f5c5SAndroid Build Coastguard Worker     mCropRect = rect;
269*8975f5c5SAndroid Build Coastguard Worker }
270*8975f5c5SAndroid Build Coastguard Worker 
getCrop() const271*8975f5c5SAndroid Build Coastguard Worker const Rectangle &TextureState::getCrop() const
272*8975f5c5SAndroid Build Coastguard Worker {
273*8975f5c5SAndroid Build Coastguard Worker     return mCropRect;
274*8975f5c5SAndroid Build Coastguard Worker }
275*8975f5c5SAndroid Build Coastguard Worker 
setGenerateMipmapHint(GLenum hint)276*8975f5c5SAndroid Build Coastguard Worker void TextureState::setGenerateMipmapHint(GLenum hint)
277*8975f5c5SAndroid Build Coastguard Worker {
278*8975f5c5SAndroid Build Coastguard Worker     mGenerateMipmapHint = hint;
279*8975f5c5SAndroid Build Coastguard Worker }
280*8975f5c5SAndroid Build Coastguard Worker 
getGenerateMipmapHint() const281*8975f5c5SAndroid Build Coastguard Worker GLenum TextureState::getGenerateMipmapHint() const
282*8975f5c5SAndroid Build Coastguard Worker {
283*8975f5c5SAndroid Build Coastguard Worker     return mGenerateMipmapHint;
284*8975f5c5SAndroid Build Coastguard Worker }
285*8975f5c5SAndroid Build Coastguard Worker 
computeRequiredSamplerFormat(const SamplerState & samplerState) const286*8975f5c5SAndroid Build Coastguard Worker SamplerFormat TextureState::computeRequiredSamplerFormat(const SamplerState &samplerState) const
287*8975f5c5SAndroid Build Coastguard Worker {
288*8975f5c5SAndroid Build Coastguard Worker     const InternalFormat &info =
289*8975f5c5SAndroid Build Coastguard Worker         *getImageDesc(getBaseImageTarget(), getEffectiveBaseLevel()).format.info;
290*8975f5c5SAndroid Build Coastguard Worker     if ((info.format == GL_DEPTH_COMPONENT ||
291*8975f5c5SAndroid Build Coastguard Worker          (info.format == GL_DEPTH_STENCIL && mDepthStencilTextureMode == GL_DEPTH_COMPONENT)) &&
292*8975f5c5SAndroid Build Coastguard Worker         samplerState.getCompareMode() != GL_NONE)
293*8975f5c5SAndroid Build Coastguard Worker     {
294*8975f5c5SAndroid Build Coastguard Worker         return SamplerFormat::Shadow;
295*8975f5c5SAndroid Build Coastguard Worker     }
296*8975f5c5SAndroid Build Coastguard Worker     else if (info.format == GL_STENCIL_INDEX ||
297*8975f5c5SAndroid Build Coastguard Worker              (info.format == GL_DEPTH_STENCIL && mDepthStencilTextureMode == GL_STENCIL_INDEX))
298*8975f5c5SAndroid Build Coastguard Worker     {
299*8975f5c5SAndroid Build Coastguard Worker         return SamplerFormat::Unsigned;
300*8975f5c5SAndroid Build Coastguard Worker     }
301*8975f5c5SAndroid Build Coastguard Worker     else
302*8975f5c5SAndroid Build Coastguard Worker     {
303*8975f5c5SAndroid Build Coastguard Worker         switch (info.componentType)
304*8975f5c5SAndroid Build Coastguard Worker         {
305*8975f5c5SAndroid Build Coastguard Worker             case GL_UNSIGNED_NORMALIZED:
306*8975f5c5SAndroid Build Coastguard Worker             case GL_SIGNED_NORMALIZED:
307*8975f5c5SAndroid Build Coastguard Worker             case GL_FLOAT:
308*8975f5c5SAndroid Build Coastguard Worker                 return SamplerFormat::Float;
309*8975f5c5SAndroid Build Coastguard Worker             case GL_INT:
310*8975f5c5SAndroid Build Coastguard Worker                 return SamplerFormat::Signed;
311*8975f5c5SAndroid Build Coastguard Worker             case GL_UNSIGNED_INT:
312*8975f5c5SAndroid Build Coastguard Worker                 return SamplerFormat::Unsigned;
313*8975f5c5SAndroid Build Coastguard Worker             default:
314*8975f5c5SAndroid Build Coastguard Worker                 return SamplerFormat::InvalidEnum;
315*8975f5c5SAndroid Build Coastguard Worker         }
316*8975f5c5SAndroid Build Coastguard Worker     }
317*8975f5c5SAndroid Build Coastguard Worker }
318*8975f5c5SAndroid Build Coastguard Worker 
computeSamplerCompleteness(const SamplerState & samplerState,const State & state) const319*8975f5c5SAndroid Build Coastguard Worker bool TextureState::computeSamplerCompleteness(const SamplerState &samplerState,
320*8975f5c5SAndroid Build Coastguard Worker                                               const State &state) const
321*8975f5c5SAndroid Build Coastguard Worker {
322*8975f5c5SAndroid Build Coastguard Worker     // Buffer textures cannot be incomplete. But if they are, the spec says -
323*8975f5c5SAndroid Build Coastguard Worker     //
324*8975f5c5SAndroid Build Coastguard Worker     //     If no buffer object is bound to the buffer texture,
325*8975f5c5SAndroid Build Coastguard Worker     //     the results of the texel access are undefined.
326*8975f5c5SAndroid Build Coastguard Worker     //
327*8975f5c5SAndroid Build Coastguard Worker     // Mark as incomplete so we use the default IncompleteTexture instead
328*8975f5c5SAndroid Build Coastguard Worker     if (mType == TextureType::Buffer)
329*8975f5c5SAndroid Build Coastguard Worker     {
330*8975f5c5SAndroid Build Coastguard Worker         return mBuffer.get() != nullptr;
331*8975f5c5SAndroid Build Coastguard Worker     }
332*8975f5c5SAndroid Build Coastguard Worker 
333*8975f5c5SAndroid Build Coastguard Worker     // Check for all non-format-based completeness rules
334*8975f5c5SAndroid Build Coastguard Worker     if (!computeSamplerCompletenessForCopyImage(samplerState, state))
335*8975f5c5SAndroid Build Coastguard Worker     {
336*8975f5c5SAndroid Build Coastguard Worker         return false;
337*8975f5c5SAndroid Build Coastguard Worker     }
338*8975f5c5SAndroid Build Coastguard Worker 
339*8975f5c5SAndroid Build Coastguard Worker     // OpenGL ES 3.2, Sections 8.8 and 11.1.3.3
340*8975f5c5SAndroid Build Coastguard Worker     // Multisample textures do not have mipmaps and filter state is ignored.
341*8975f5c5SAndroid Build Coastguard Worker     if (IsMultisampled(mType))
342*8975f5c5SAndroid Build Coastguard Worker     {
343*8975f5c5SAndroid Build Coastguard Worker         return true;
344*8975f5c5SAndroid Build Coastguard Worker     }
345*8975f5c5SAndroid Build Coastguard Worker 
346*8975f5c5SAndroid Build Coastguard Worker     // OpenGL ES 3.2, Section 8.17
347*8975f5c5SAndroid Build Coastguard Worker     // A texture is complete unless either the magnification filter is not NEAREST,
348*8975f5c5SAndroid Build Coastguard Worker     // or the minification filter is neither NEAREST nor NEAREST_MIPMAP_NEAREST; and any of
349*8975f5c5SAndroid Build Coastguard Worker     if (IsPointSampled(samplerState))
350*8975f5c5SAndroid Build Coastguard Worker     {
351*8975f5c5SAndroid Build Coastguard Worker         return true;
352*8975f5c5SAndroid Build Coastguard Worker     }
353*8975f5c5SAndroid Build Coastguard Worker 
354*8975f5c5SAndroid Build Coastguard Worker     const InternalFormat *info =
355*8975f5c5SAndroid Build Coastguard Worker         getImageDesc(getBaseImageTarget(), getEffectiveBaseLevel()).format.info;
356*8975f5c5SAndroid Build Coastguard Worker 
357*8975f5c5SAndroid Build Coastguard Worker     // The effective internal format specified for the texture images
358*8975f5c5SAndroid Build Coastguard Worker     // is a sized internal color format that is not texture-filterable.
359*8975f5c5SAndroid Build Coastguard Worker     if (!info->isDepthOrStencil())
360*8975f5c5SAndroid Build Coastguard Worker     {
361*8975f5c5SAndroid Build Coastguard Worker         return info->filterSupport(state.getClientVersion(), state.getExtensions());
362*8975f5c5SAndroid Build Coastguard Worker     }
363*8975f5c5SAndroid Build Coastguard Worker 
364*8975f5c5SAndroid Build Coastguard Worker     // The effective internal format specified for the texture images
365*8975f5c5SAndroid Build Coastguard Worker     // is a sized internal depth or depth and stencil format (see table 8.11),
366*8975f5c5SAndroid Build Coastguard Worker     // and the value of TEXTURE_COMPARE_MODE is NONE.
367*8975f5c5SAndroid Build Coastguard Worker     if (info->depthBits > 0 && samplerState.getCompareMode() == GL_NONE)
368*8975f5c5SAndroid Build Coastguard Worker     {
369*8975f5c5SAndroid Build Coastguard Worker         // Note: we restrict this validation to sized types. For the OES_depth_textures
370*8975f5c5SAndroid Build Coastguard Worker         // extension, due to some underspecification problems, we must allow linear filtering
371*8975f5c5SAndroid Build Coastguard Worker         // for legacy compatibility with WebGL 1.0.
372*8975f5c5SAndroid Build Coastguard Worker         // See http://crbug.com/649200
373*8975f5c5SAndroid Build Coastguard Worker         if (state.getClientMajorVersion() >= 3 && info->sized)
374*8975f5c5SAndroid Build Coastguard Worker         {
375*8975f5c5SAndroid Build Coastguard Worker             return false;
376*8975f5c5SAndroid Build Coastguard Worker         }
377*8975f5c5SAndroid Build Coastguard Worker     }
378*8975f5c5SAndroid Build Coastguard Worker 
379*8975f5c5SAndroid Build Coastguard Worker     if (info->stencilBits > 0)
380*8975f5c5SAndroid Build Coastguard Worker     {
381*8975f5c5SAndroid Build Coastguard Worker         if (info->depthBits > 0)
382*8975f5c5SAndroid Build Coastguard Worker         {
383*8975f5c5SAndroid Build Coastguard Worker             // The internal format of the texture is DEPTH_STENCIL,
384*8975f5c5SAndroid Build Coastguard Worker             // and the value of DEPTH_STENCIL_TEXTURE_MODE for the
385*8975f5c5SAndroid Build Coastguard Worker             // texture is STENCIL_INDEX.
386*8975f5c5SAndroid Build Coastguard Worker             if (mDepthStencilTextureMode == GL_STENCIL_INDEX)
387*8975f5c5SAndroid Build Coastguard Worker             {
388*8975f5c5SAndroid Build Coastguard Worker                 return false;
389*8975f5c5SAndroid Build Coastguard Worker             }
390*8975f5c5SAndroid Build Coastguard Worker         }
391*8975f5c5SAndroid Build Coastguard Worker         else
392*8975f5c5SAndroid Build Coastguard Worker         {
393*8975f5c5SAndroid Build Coastguard Worker             // The internal format is STENCIL_INDEX.
394*8975f5c5SAndroid Build Coastguard Worker             return false;
395*8975f5c5SAndroid Build Coastguard Worker         }
396*8975f5c5SAndroid Build Coastguard Worker     }
397*8975f5c5SAndroid Build Coastguard Worker 
398*8975f5c5SAndroid Build Coastguard Worker     return true;
399*8975f5c5SAndroid Build Coastguard Worker }
400*8975f5c5SAndroid Build Coastguard Worker 
401*8975f5c5SAndroid Build Coastguard Worker // CopyImageSubData has more lax rules for texture completeness: format-based completeness rules are
402*8975f5c5SAndroid Build Coastguard Worker // ignored, so a texture can still be considered complete even if it violates format-specific
403*8975f5c5SAndroid Build Coastguard Worker // conditions
computeSamplerCompletenessForCopyImage(const SamplerState & samplerState,const State & state) const404*8975f5c5SAndroid Build Coastguard Worker bool TextureState::computeSamplerCompletenessForCopyImage(const SamplerState &samplerState,
405*8975f5c5SAndroid Build Coastguard Worker                                                           const State &state) const
406*8975f5c5SAndroid Build Coastguard Worker {
407*8975f5c5SAndroid Build Coastguard Worker     // Buffer textures cannot be incomplete. But if they are, the spec says -
408*8975f5c5SAndroid Build Coastguard Worker     //
409*8975f5c5SAndroid Build Coastguard Worker     //     If no buffer object is bound to the buffer texture,
410*8975f5c5SAndroid Build Coastguard Worker     //     the results of the texel access are undefined.
411*8975f5c5SAndroid Build Coastguard Worker     //
412*8975f5c5SAndroid Build Coastguard Worker     // Mark as incomplete so we use the default IncompleteTexture instead
413*8975f5c5SAndroid Build Coastguard Worker     if (mType == TextureType::Buffer)
414*8975f5c5SAndroid Build Coastguard Worker     {
415*8975f5c5SAndroid Build Coastguard Worker         return mBuffer.get() != nullptr;
416*8975f5c5SAndroid Build Coastguard Worker     }
417*8975f5c5SAndroid Build Coastguard Worker 
418*8975f5c5SAndroid Build Coastguard Worker     if (!mImmutableFormat && mBaseLevel > mMaxLevel)
419*8975f5c5SAndroid Build Coastguard Worker     {
420*8975f5c5SAndroid Build Coastguard Worker         return false;
421*8975f5c5SAndroid Build Coastguard Worker     }
422*8975f5c5SAndroid Build Coastguard Worker     const ImageDesc &baseImageDesc = getImageDesc(getBaseImageTarget(), getEffectiveBaseLevel());
423*8975f5c5SAndroid Build Coastguard Worker     if (baseImageDesc.size.width == 0 || baseImageDesc.size.height == 0 ||
424*8975f5c5SAndroid Build Coastguard Worker         baseImageDesc.size.depth == 0)
425*8975f5c5SAndroid Build Coastguard Worker     {
426*8975f5c5SAndroid Build Coastguard Worker         return false;
427*8975f5c5SAndroid Build Coastguard Worker     }
428*8975f5c5SAndroid Build Coastguard Worker     // The cases where the texture is incomplete because base level is out of range should be
429*8975f5c5SAndroid Build Coastguard Worker     // handled by the above condition.
430*8975f5c5SAndroid Build Coastguard Worker     ASSERT(mBaseLevel < IMPLEMENTATION_MAX_TEXTURE_LEVELS || mImmutableFormat);
431*8975f5c5SAndroid Build Coastguard Worker 
432*8975f5c5SAndroid Build Coastguard Worker     if (mType == TextureType::CubeMap && baseImageDesc.size.width != baseImageDesc.size.height)
433*8975f5c5SAndroid Build Coastguard Worker     {
434*8975f5c5SAndroid Build Coastguard Worker         return false;
435*8975f5c5SAndroid Build Coastguard Worker     }
436*8975f5c5SAndroid Build Coastguard Worker 
437*8975f5c5SAndroid Build Coastguard Worker     bool npotSupport = state.getExtensions().textureNpotOES || state.getClientMajorVersion() >= 3;
438*8975f5c5SAndroid Build Coastguard Worker     if (!npotSupport)
439*8975f5c5SAndroid Build Coastguard Worker     {
440*8975f5c5SAndroid Build Coastguard Worker         if ((samplerState.getWrapS() != GL_CLAMP_TO_EDGE &&
441*8975f5c5SAndroid Build Coastguard Worker              samplerState.getWrapS() != GL_CLAMP_TO_BORDER && !isPow2(baseImageDesc.size.width)) ||
442*8975f5c5SAndroid Build Coastguard Worker             (samplerState.getWrapT() != GL_CLAMP_TO_EDGE &&
443*8975f5c5SAndroid Build Coastguard Worker              samplerState.getWrapT() != GL_CLAMP_TO_BORDER && !isPow2(baseImageDesc.size.height)))
444*8975f5c5SAndroid Build Coastguard Worker         {
445*8975f5c5SAndroid Build Coastguard Worker             return false;
446*8975f5c5SAndroid Build Coastguard Worker         }
447*8975f5c5SAndroid Build Coastguard Worker     }
448*8975f5c5SAndroid Build Coastguard Worker 
449*8975f5c5SAndroid Build Coastguard Worker     if (IsMipmapSupported(mType) && IsMipmapFiltered(samplerState.getMinFilter()))
450*8975f5c5SAndroid Build Coastguard Worker     {
451*8975f5c5SAndroid Build Coastguard Worker         if (!npotSupport)
452*8975f5c5SAndroid Build Coastguard Worker         {
453*8975f5c5SAndroid Build Coastguard Worker             if (!isPow2(baseImageDesc.size.width) || !isPow2(baseImageDesc.size.height))
454*8975f5c5SAndroid Build Coastguard Worker             {
455*8975f5c5SAndroid Build Coastguard Worker                 return false;
456*8975f5c5SAndroid Build Coastguard Worker             }
457*8975f5c5SAndroid Build Coastguard Worker         }
458*8975f5c5SAndroid Build Coastguard Worker 
459*8975f5c5SAndroid Build Coastguard Worker         if (!computeMipmapCompleteness())
460*8975f5c5SAndroid Build Coastguard Worker         {
461*8975f5c5SAndroid Build Coastguard Worker             return false;
462*8975f5c5SAndroid Build Coastguard Worker         }
463*8975f5c5SAndroid Build Coastguard Worker     }
464*8975f5c5SAndroid Build Coastguard Worker     else
465*8975f5c5SAndroid Build Coastguard Worker     {
466*8975f5c5SAndroid Build Coastguard Worker         if (mType == TextureType::CubeMap && !isCubeComplete())
467*8975f5c5SAndroid Build Coastguard Worker         {
468*8975f5c5SAndroid Build Coastguard Worker             return false;
469*8975f5c5SAndroid Build Coastguard Worker         }
470*8975f5c5SAndroid Build Coastguard Worker     }
471*8975f5c5SAndroid Build Coastguard Worker 
472*8975f5c5SAndroid Build Coastguard Worker     // From GL_OES_EGL_image_external_essl3: If state is present in a sampler object bound to a
473*8975f5c5SAndroid Build Coastguard Worker     // texture unit that would have been rejected by a call to TexParameter* for the texture bound
474*8975f5c5SAndroid Build Coastguard Worker     // to that unit, the behavior of the implementation is as if the texture were incomplete. For
475*8975f5c5SAndroid Build Coastguard Worker     // example, if TEXTURE_WRAP_S or TEXTURE_WRAP_T is set to anything but CLAMP_TO_EDGE on the
476*8975f5c5SAndroid Build Coastguard Worker     // sampler object bound to a texture unit and the texture bound to that unit is an external
477*8975f5c5SAndroid Build Coastguard Worker     // texture and EXT_EGL_image_external_wrap_modes is not enabled, the texture will be considered
478*8975f5c5SAndroid Build Coastguard Worker     // incomplete.
479*8975f5c5SAndroid Build Coastguard Worker     // Sampler object state which does not affect sampling for the type of texture bound
480*8975f5c5SAndroid Build Coastguard Worker     // to a texture unit, such as TEXTURE_WRAP_R for an external texture, does not affect
481*8975f5c5SAndroid Build Coastguard Worker     // completeness.
482*8975f5c5SAndroid Build Coastguard Worker     if (mType == TextureType::External)
483*8975f5c5SAndroid Build Coastguard Worker     {
484*8975f5c5SAndroid Build Coastguard Worker         if (!state.getExtensions().EGLImageExternalWrapModesEXT)
485*8975f5c5SAndroid Build Coastguard Worker         {
486*8975f5c5SAndroid Build Coastguard Worker             if (samplerState.getWrapS() != GL_CLAMP_TO_EDGE ||
487*8975f5c5SAndroid Build Coastguard Worker                 samplerState.getWrapT() != GL_CLAMP_TO_EDGE)
488*8975f5c5SAndroid Build Coastguard Worker             {
489*8975f5c5SAndroid Build Coastguard Worker                 return false;
490*8975f5c5SAndroid Build Coastguard Worker             }
491*8975f5c5SAndroid Build Coastguard Worker         }
492*8975f5c5SAndroid Build Coastguard Worker 
493*8975f5c5SAndroid Build Coastguard Worker         if (samplerState.getMinFilter() != GL_LINEAR && samplerState.getMinFilter() != GL_NEAREST)
494*8975f5c5SAndroid Build Coastguard Worker         {
495*8975f5c5SAndroid Build Coastguard Worker             return false;
496*8975f5c5SAndroid Build Coastguard Worker         }
497*8975f5c5SAndroid Build Coastguard Worker     }
498*8975f5c5SAndroid Build Coastguard Worker 
499*8975f5c5SAndroid Build Coastguard Worker     return true;
500*8975f5c5SAndroid Build Coastguard Worker }
501*8975f5c5SAndroid Build Coastguard Worker 
computeMipmapCompleteness() const502*8975f5c5SAndroid Build Coastguard Worker bool TextureState::computeMipmapCompleteness() const
503*8975f5c5SAndroid Build Coastguard Worker {
504*8975f5c5SAndroid Build Coastguard Worker     const GLuint maxLevel = getMipmapMaxLevel();
505*8975f5c5SAndroid Build Coastguard Worker 
506*8975f5c5SAndroid Build Coastguard Worker     for (GLuint level = getEffectiveBaseLevel(); level <= maxLevel; level++)
507*8975f5c5SAndroid Build Coastguard Worker     {
508*8975f5c5SAndroid Build Coastguard Worker         if (mType == TextureType::CubeMap)
509*8975f5c5SAndroid Build Coastguard Worker         {
510*8975f5c5SAndroid Build Coastguard Worker             for (TextureTarget face : AllCubeFaceTextureTargets())
511*8975f5c5SAndroid Build Coastguard Worker             {
512*8975f5c5SAndroid Build Coastguard Worker                 if (!computeLevelCompleteness(face, level))
513*8975f5c5SAndroid Build Coastguard Worker                 {
514*8975f5c5SAndroid Build Coastguard Worker                     return false;
515*8975f5c5SAndroid Build Coastguard Worker                 }
516*8975f5c5SAndroid Build Coastguard Worker             }
517*8975f5c5SAndroid Build Coastguard Worker         }
518*8975f5c5SAndroid Build Coastguard Worker         else
519*8975f5c5SAndroid Build Coastguard Worker         {
520*8975f5c5SAndroid Build Coastguard Worker             if (!computeLevelCompleteness(NonCubeTextureTypeToTarget(mType), level))
521*8975f5c5SAndroid Build Coastguard Worker             {
522*8975f5c5SAndroid Build Coastguard Worker                 return false;
523*8975f5c5SAndroid Build Coastguard Worker             }
524*8975f5c5SAndroid Build Coastguard Worker         }
525*8975f5c5SAndroid Build Coastguard Worker     }
526*8975f5c5SAndroid Build Coastguard Worker 
527*8975f5c5SAndroid Build Coastguard Worker     return true;
528*8975f5c5SAndroid Build Coastguard Worker }
529*8975f5c5SAndroid Build Coastguard Worker 
computeLevelCompleteness(TextureTarget target,size_t level) const530*8975f5c5SAndroid Build Coastguard Worker bool TextureState::computeLevelCompleteness(TextureTarget target, size_t level) const
531*8975f5c5SAndroid Build Coastguard Worker {
532*8975f5c5SAndroid Build Coastguard Worker     ASSERT(level < IMPLEMENTATION_MAX_TEXTURE_LEVELS);
533*8975f5c5SAndroid Build Coastguard Worker 
534*8975f5c5SAndroid Build Coastguard Worker     if (mImmutableFormat)
535*8975f5c5SAndroid Build Coastguard Worker     {
536*8975f5c5SAndroid Build Coastguard Worker         return true;
537*8975f5c5SAndroid Build Coastguard Worker     }
538*8975f5c5SAndroid Build Coastguard Worker 
539*8975f5c5SAndroid Build Coastguard Worker     const ImageDesc &baseImageDesc = getImageDesc(getBaseImageTarget(), getEffectiveBaseLevel());
540*8975f5c5SAndroid Build Coastguard Worker     if (baseImageDesc.size.width == 0 || baseImageDesc.size.height == 0 ||
541*8975f5c5SAndroid Build Coastguard Worker         baseImageDesc.size.depth == 0)
542*8975f5c5SAndroid Build Coastguard Worker     {
543*8975f5c5SAndroid Build Coastguard Worker         return false;
544*8975f5c5SAndroid Build Coastguard Worker     }
545*8975f5c5SAndroid Build Coastguard Worker 
546*8975f5c5SAndroid Build Coastguard Worker     const ImageDesc &levelImageDesc = getImageDesc(target, level);
547*8975f5c5SAndroid Build Coastguard Worker     if (levelImageDesc.size.width == 0 || levelImageDesc.size.height == 0 ||
548*8975f5c5SAndroid Build Coastguard Worker         levelImageDesc.size.depth == 0)
549*8975f5c5SAndroid Build Coastguard Worker     {
550*8975f5c5SAndroid Build Coastguard Worker         return false;
551*8975f5c5SAndroid Build Coastguard Worker     }
552*8975f5c5SAndroid Build Coastguard Worker 
553*8975f5c5SAndroid Build Coastguard Worker     if (!Format::SameSized(levelImageDesc.format, baseImageDesc.format))
554*8975f5c5SAndroid Build Coastguard Worker     {
555*8975f5c5SAndroid Build Coastguard Worker         return false;
556*8975f5c5SAndroid Build Coastguard Worker     }
557*8975f5c5SAndroid Build Coastguard Worker 
558*8975f5c5SAndroid Build Coastguard Worker     ASSERT(level >= getEffectiveBaseLevel());
559*8975f5c5SAndroid Build Coastguard Worker     const size_t relativeLevel = level - getEffectiveBaseLevel();
560*8975f5c5SAndroid Build Coastguard Worker     if (levelImageDesc.size.width != std::max(1, baseImageDesc.size.width >> relativeLevel))
561*8975f5c5SAndroid Build Coastguard Worker     {
562*8975f5c5SAndroid Build Coastguard Worker         return false;
563*8975f5c5SAndroid Build Coastguard Worker     }
564*8975f5c5SAndroid Build Coastguard Worker 
565*8975f5c5SAndroid Build Coastguard Worker     if (levelImageDesc.size.height != std::max(1, baseImageDesc.size.height >> relativeLevel))
566*8975f5c5SAndroid Build Coastguard Worker     {
567*8975f5c5SAndroid Build Coastguard Worker         return false;
568*8975f5c5SAndroid Build Coastguard Worker     }
569*8975f5c5SAndroid Build Coastguard Worker 
570*8975f5c5SAndroid Build Coastguard Worker     if (mType == TextureType::_3D)
571*8975f5c5SAndroid Build Coastguard Worker     {
572*8975f5c5SAndroid Build Coastguard Worker         if (levelImageDesc.size.depth != std::max(1, baseImageDesc.size.depth >> relativeLevel))
573*8975f5c5SAndroid Build Coastguard Worker         {
574*8975f5c5SAndroid Build Coastguard Worker             return false;
575*8975f5c5SAndroid Build Coastguard Worker         }
576*8975f5c5SAndroid Build Coastguard Worker     }
577*8975f5c5SAndroid Build Coastguard Worker     else if (IsArrayTextureType(mType))
578*8975f5c5SAndroid Build Coastguard Worker     {
579*8975f5c5SAndroid Build Coastguard Worker         if (levelImageDesc.size.depth != baseImageDesc.size.depth)
580*8975f5c5SAndroid Build Coastguard Worker         {
581*8975f5c5SAndroid Build Coastguard Worker             return false;
582*8975f5c5SAndroid Build Coastguard Worker         }
583*8975f5c5SAndroid Build Coastguard Worker     }
584*8975f5c5SAndroid Build Coastguard Worker 
585*8975f5c5SAndroid Build Coastguard Worker     return true;
586*8975f5c5SAndroid Build Coastguard Worker }
587*8975f5c5SAndroid Build Coastguard Worker 
getBaseImageTarget() const588*8975f5c5SAndroid Build Coastguard Worker TextureTarget TextureState::getBaseImageTarget() const
589*8975f5c5SAndroid Build Coastguard Worker {
590*8975f5c5SAndroid Build Coastguard Worker     return mType == TextureType::CubeMap ? kCubeMapTextureTargetMin
591*8975f5c5SAndroid Build Coastguard Worker                                          : NonCubeTextureTypeToTarget(mType);
592*8975f5c5SAndroid Build Coastguard Worker }
593*8975f5c5SAndroid Build Coastguard Worker 
getEnabledLevelCount() const594*8975f5c5SAndroid Build Coastguard Worker GLuint TextureState::getEnabledLevelCount() const
595*8975f5c5SAndroid Build Coastguard Worker {
596*8975f5c5SAndroid Build Coastguard Worker     GLuint levelCount      = 0;
597*8975f5c5SAndroid Build Coastguard Worker     const GLuint baseLevel = getEffectiveBaseLevel();
598*8975f5c5SAndroid Build Coastguard Worker     const GLuint maxLevel  = getMipmapMaxLevel();
599*8975f5c5SAndroid Build Coastguard Worker 
600*8975f5c5SAndroid Build Coastguard Worker     // The mip chain will have either one or more sequential levels, or max levels,
601*8975f5c5SAndroid Build Coastguard Worker     // but not a sparse one.
602*8975f5c5SAndroid Build Coastguard Worker     Optional<Extents> expectedSize;
603*8975f5c5SAndroid Build Coastguard Worker     for (size_t enabledLevel = baseLevel; enabledLevel <= maxLevel; ++enabledLevel, ++levelCount)
604*8975f5c5SAndroid Build Coastguard Worker     {
605*8975f5c5SAndroid Build Coastguard Worker         // Note: for cube textures, we only check the first face.
606*8975f5c5SAndroid Build Coastguard Worker         TextureTarget target     = TextureTypeToTarget(mType, 0);
607*8975f5c5SAndroid Build Coastguard Worker         size_t descIndex         = GetImageDescIndex(target, enabledLevel);
608*8975f5c5SAndroid Build Coastguard Worker         const Extents &levelSize = mImageDescs[descIndex].size;
609*8975f5c5SAndroid Build Coastguard Worker 
610*8975f5c5SAndroid Build Coastguard Worker         if (levelSize.empty())
611*8975f5c5SAndroid Build Coastguard Worker         {
612*8975f5c5SAndroid Build Coastguard Worker             break;
613*8975f5c5SAndroid Build Coastguard Worker         }
614*8975f5c5SAndroid Build Coastguard Worker         if (expectedSize.valid())
615*8975f5c5SAndroid Build Coastguard Worker         {
616*8975f5c5SAndroid Build Coastguard Worker             Extents newSize = expectedSize.value();
617*8975f5c5SAndroid Build Coastguard Worker             newSize.width   = std::max(1, newSize.width >> 1);
618*8975f5c5SAndroid Build Coastguard Worker             newSize.height  = std::max(1, newSize.height >> 1);
619*8975f5c5SAndroid Build Coastguard Worker 
620*8975f5c5SAndroid Build Coastguard Worker             if (!IsArrayTextureType(mType))
621*8975f5c5SAndroid Build Coastguard Worker             {
622*8975f5c5SAndroid Build Coastguard Worker                 newSize.depth = std::max(1, newSize.depth >> 1);
623*8975f5c5SAndroid Build Coastguard Worker             }
624*8975f5c5SAndroid Build Coastguard Worker 
625*8975f5c5SAndroid Build Coastguard Worker             if (newSize != levelSize)
626*8975f5c5SAndroid Build Coastguard Worker             {
627*8975f5c5SAndroid Build Coastguard Worker                 break;
628*8975f5c5SAndroid Build Coastguard Worker             }
629*8975f5c5SAndroid Build Coastguard Worker         }
630*8975f5c5SAndroid Build Coastguard Worker         expectedSize = levelSize;
631*8975f5c5SAndroid Build Coastguard Worker     }
632*8975f5c5SAndroid Build Coastguard Worker 
633*8975f5c5SAndroid Build Coastguard Worker     return levelCount;
634*8975f5c5SAndroid Build Coastguard Worker }
635*8975f5c5SAndroid Build Coastguard Worker 
ImageDesc()636*8975f5c5SAndroid Build Coastguard Worker ImageDesc::ImageDesc()
637*8975f5c5SAndroid Build Coastguard Worker     : ImageDesc(Extents(0, 0, 0), Format::Invalid(), 0, GL_TRUE, InitState::Initialized)
638*8975f5c5SAndroid Build Coastguard Worker {}
639*8975f5c5SAndroid Build Coastguard Worker 
ImageDesc(const Extents & size,const Format & format,const InitState initState)640*8975f5c5SAndroid Build Coastguard Worker ImageDesc::ImageDesc(const Extents &size, const Format &format, const InitState initState)
641*8975f5c5SAndroid Build Coastguard Worker     : size(size), format(format), samples(0), fixedSampleLocations(GL_TRUE), initState(initState)
642*8975f5c5SAndroid Build Coastguard Worker {}
643*8975f5c5SAndroid Build Coastguard Worker 
ImageDesc(const Extents & size,const Format & format,const GLsizei samples,const bool fixedSampleLocations,const InitState initState)644*8975f5c5SAndroid Build Coastguard Worker ImageDesc::ImageDesc(const Extents &size,
645*8975f5c5SAndroid Build Coastguard Worker                      const Format &format,
646*8975f5c5SAndroid Build Coastguard Worker                      const GLsizei samples,
647*8975f5c5SAndroid Build Coastguard Worker                      const bool fixedSampleLocations,
648*8975f5c5SAndroid Build Coastguard Worker                      const InitState initState)
649*8975f5c5SAndroid Build Coastguard Worker     : size(size),
650*8975f5c5SAndroid Build Coastguard Worker       format(format),
651*8975f5c5SAndroid Build Coastguard Worker       samples(samples),
652*8975f5c5SAndroid Build Coastguard Worker       fixedSampleLocations(fixedSampleLocations),
653*8975f5c5SAndroid Build Coastguard Worker       initState(initState)
654*8975f5c5SAndroid Build Coastguard Worker {}
655*8975f5c5SAndroid Build Coastguard Worker 
getMemorySize() const656*8975f5c5SAndroid Build Coastguard Worker GLint ImageDesc::getMemorySize() const
657*8975f5c5SAndroid Build Coastguard Worker {
658*8975f5c5SAndroid Build Coastguard Worker     // Assume allocated size is around width * height * depth * samples * pixelBytes
659*8975f5c5SAndroid Build Coastguard Worker     angle::CheckedNumeric<GLint> levelSize = 1;
660*8975f5c5SAndroid Build Coastguard Worker     levelSize *= format.info->pixelBytes;
661*8975f5c5SAndroid Build Coastguard Worker     levelSize *= size.width;
662*8975f5c5SAndroid Build Coastguard Worker     levelSize *= size.height;
663*8975f5c5SAndroid Build Coastguard Worker     levelSize *= size.depth;
664*8975f5c5SAndroid Build Coastguard Worker     levelSize *= std::max(samples, 1);
665*8975f5c5SAndroid Build Coastguard Worker     return levelSize.ValueOrDefault(std::numeric_limits<GLint>::max());
666*8975f5c5SAndroid Build Coastguard Worker }
667*8975f5c5SAndroid Build Coastguard Worker 
getImageDesc(TextureTarget target,size_t level) const668*8975f5c5SAndroid Build Coastguard Worker const ImageDesc &TextureState::getImageDesc(TextureTarget target, size_t level) const
669*8975f5c5SAndroid Build Coastguard Worker {
670*8975f5c5SAndroid Build Coastguard Worker     size_t descIndex = GetImageDescIndex(target, level);
671*8975f5c5SAndroid Build Coastguard Worker     ASSERT(descIndex < mImageDescs.size());
672*8975f5c5SAndroid Build Coastguard Worker     return mImageDescs[descIndex];
673*8975f5c5SAndroid Build Coastguard Worker }
674*8975f5c5SAndroid Build Coastguard Worker 
setImageDesc(TextureTarget target,size_t level,const ImageDesc & desc)675*8975f5c5SAndroid Build Coastguard Worker void TextureState::setImageDesc(TextureTarget target, size_t level, const ImageDesc &desc)
676*8975f5c5SAndroid Build Coastguard Worker {
677*8975f5c5SAndroid Build Coastguard Worker     size_t descIndex = GetImageDescIndex(target, level);
678*8975f5c5SAndroid Build Coastguard Worker     ASSERT(descIndex < mImageDescs.size());
679*8975f5c5SAndroid Build Coastguard Worker     mImageDescs[descIndex] = desc;
680*8975f5c5SAndroid Build Coastguard Worker     if (desc.initState == InitState::MayNeedInit)
681*8975f5c5SAndroid Build Coastguard Worker     {
682*8975f5c5SAndroid Build Coastguard Worker         mInitState = InitState::MayNeedInit;
683*8975f5c5SAndroid Build Coastguard Worker     }
684*8975f5c5SAndroid Build Coastguard Worker     else
685*8975f5c5SAndroid Build Coastguard Worker     {
686*8975f5c5SAndroid Build Coastguard Worker         // Scan for any uninitialized images. If there are none, set the init state of the entire
687*8975f5c5SAndroid Build Coastguard Worker         // texture to initialized. The cost of the scan is only paid after doing image
688*8975f5c5SAndroid Build Coastguard Worker         // initialization which is already very expensive.
689*8975f5c5SAndroid Build Coastguard Worker         bool allImagesInitialized = true;
690*8975f5c5SAndroid Build Coastguard Worker 
691*8975f5c5SAndroid Build Coastguard Worker         for (const ImageDesc &initDesc : mImageDescs)
692*8975f5c5SAndroid Build Coastguard Worker         {
693*8975f5c5SAndroid Build Coastguard Worker             if (initDesc.initState == InitState::MayNeedInit)
694*8975f5c5SAndroid Build Coastguard Worker             {
695*8975f5c5SAndroid Build Coastguard Worker                 allImagesInitialized = false;
696*8975f5c5SAndroid Build Coastguard Worker                 break;
697*8975f5c5SAndroid Build Coastguard Worker             }
698*8975f5c5SAndroid Build Coastguard Worker         }
699*8975f5c5SAndroid Build Coastguard Worker 
700*8975f5c5SAndroid Build Coastguard Worker         if (allImagesInitialized)
701*8975f5c5SAndroid Build Coastguard Worker         {
702*8975f5c5SAndroid Build Coastguard Worker             mInitState = InitState::Initialized;
703*8975f5c5SAndroid Build Coastguard Worker         }
704*8975f5c5SAndroid Build Coastguard Worker     }
705*8975f5c5SAndroid Build Coastguard Worker }
706*8975f5c5SAndroid Build Coastguard Worker 
707*8975f5c5SAndroid Build Coastguard Worker // Note that an ImageIndex that represents an entire level of a cube map corresponds to 6
708*8975f5c5SAndroid Build Coastguard Worker // ImageDescs, so if the cube map is cube complete, we return the ImageDesc of the first cube
709*8975f5c5SAndroid Build Coastguard Worker // face, and we don't allow using this function when the cube map is not cube complete.
getImageDesc(const ImageIndex & imageIndex) const710*8975f5c5SAndroid Build Coastguard Worker const ImageDesc &TextureState::getImageDesc(const ImageIndex &imageIndex) const
711*8975f5c5SAndroid Build Coastguard Worker {
712*8975f5c5SAndroid Build Coastguard Worker     if (imageIndex.isEntireLevelCubeMap())
713*8975f5c5SAndroid Build Coastguard Worker     {
714*8975f5c5SAndroid Build Coastguard Worker         ASSERT(isCubeComplete());
715*8975f5c5SAndroid Build Coastguard Worker         const GLint levelIndex = imageIndex.getLevelIndex();
716*8975f5c5SAndroid Build Coastguard Worker         return getImageDesc(kCubeMapTextureTargetMin, levelIndex);
717*8975f5c5SAndroid Build Coastguard Worker     }
718*8975f5c5SAndroid Build Coastguard Worker 
719*8975f5c5SAndroid Build Coastguard Worker     return getImageDesc(imageIndex.getTarget(), imageIndex.getLevelIndex());
720*8975f5c5SAndroid Build Coastguard Worker }
721*8975f5c5SAndroid Build Coastguard Worker 
setImageDescChain(GLuint baseLevel,GLuint maxLevel,Extents baseSize,const Format & format,InitState initState)722*8975f5c5SAndroid Build Coastguard Worker void TextureState::setImageDescChain(GLuint baseLevel,
723*8975f5c5SAndroid Build Coastguard Worker                                      GLuint maxLevel,
724*8975f5c5SAndroid Build Coastguard Worker                                      Extents baseSize,
725*8975f5c5SAndroid Build Coastguard Worker                                      const Format &format,
726*8975f5c5SAndroid Build Coastguard Worker                                      InitState initState)
727*8975f5c5SAndroid Build Coastguard Worker {
728*8975f5c5SAndroid Build Coastguard Worker     for (GLuint level = baseLevel; level <= maxLevel; level++)
729*8975f5c5SAndroid Build Coastguard Worker     {
730*8975f5c5SAndroid Build Coastguard Worker         int relativeLevel = (level - baseLevel);
731*8975f5c5SAndroid Build Coastguard Worker         Extents levelSize(std::max<int>(baseSize.width >> relativeLevel, 1),
732*8975f5c5SAndroid Build Coastguard Worker                           std::max<int>(baseSize.height >> relativeLevel, 1),
733*8975f5c5SAndroid Build Coastguard Worker                           (IsArrayTextureType(mType))
734*8975f5c5SAndroid Build Coastguard Worker                               ? baseSize.depth
735*8975f5c5SAndroid Build Coastguard Worker                               : std::max<int>(baseSize.depth >> relativeLevel, 1));
736*8975f5c5SAndroid Build Coastguard Worker         ImageDesc levelInfo(levelSize, format, initState);
737*8975f5c5SAndroid Build Coastguard Worker 
738*8975f5c5SAndroid Build Coastguard Worker         if (mType == TextureType::CubeMap)
739*8975f5c5SAndroid Build Coastguard Worker         {
740*8975f5c5SAndroid Build Coastguard Worker             for (TextureTarget face : AllCubeFaceTextureTargets())
741*8975f5c5SAndroid Build Coastguard Worker             {
742*8975f5c5SAndroid Build Coastguard Worker                 setImageDesc(face, level, levelInfo);
743*8975f5c5SAndroid Build Coastguard Worker             }
744*8975f5c5SAndroid Build Coastguard Worker         }
745*8975f5c5SAndroid Build Coastguard Worker         else
746*8975f5c5SAndroid Build Coastguard Worker         {
747*8975f5c5SAndroid Build Coastguard Worker             setImageDesc(NonCubeTextureTypeToTarget(mType), level, levelInfo);
748*8975f5c5SAndroid Build Coastguard Worker         }
749*8975f5c5SAndroid Build Coastguard Worker     }
750*8975f5c5SAndroid Build Coastguard Worker }
751*8975f5c5SAndroid Build Coastguard Worker 
setImageDescChainMultisample(Extents baseSize,const Format & format,GLsizei samples,bool fixedSampleLocations,InitState initState)752*8975f5c5SAndroid Build Coastguard Worker void TextureState::setImageDescChainMultisample(Extents baseSize,
753*8975f5c5SAndroid Build Coastguard Worker                                                 const Format &format,
754*8975f5c5SAndroid Build Coastguard Worker                                                 GLsizei samples,
755*8975f5c5SAndroid Build Coastguard Worker                                                 bool fixedSampleLocations,
756*8975f5c5SAndroid Build Coastguard Worker                                                 InitState initState)
757*8975f5c5SAndroid Build Coastguard Worker {
758*8975f5c5SAndroid Build Coastguard Worker     ASSERT(mType == TextureType::_2DMultisample || mType == TextureType::_2DMultisampleArray);
759*8975f5c5SAndroid Build Coastguard Worker     ImageDesc levelInfo(baseSize, format, samples, fixedSampleLocations, initState);
760*8975f5c5SAndroid Build Coastguard Worker     setImageDesc(NonCubeTextureTypeToTarget(mType), 0, levelInfo);
761*8975f5c5SAndroid Build Coastguard Worker }
762*8975f5c5SAndroid Build Coastguard Worker 
clearImageDesc(TextureTarget target,size_t level)763*8975f5c5SAndroid Build Coastguard Worker void TextureState::clearImageDesc(TextureTarget target, size_t level)
764*8975f5c5SAndroid Build Coastguard Worker {
765*8975f5c5SAndroid Build Coastguard Worker     setImageDesc(target, level, ImageDesc());
766*8975f5c5SAndroid Build Coastguard Worker }
767*8975f5c5SAndroid Build Coastguard Worker 
clearImageDescs()768*8975f5c5SAndroid Build Coastguard Worker void TextureState::clearImageDescs()
769*8975f5c5SAndroid Build Coastguard Worker {
770*8975f5c5SAndroid Build Coastguard Worker     for (size_t descIndex = 0; descIndex < mImageDescs.size(); descIndex++)
771*8975f5c5SAndroid Build Coastguard Worker     {
772*8975f5c5SAndroid Build Coastguard Worker         mImageDescs[descIndex] = ImageDesc();
773*8975f5c5SAndroid Build Coastguard Worker     }
774*8975f5c5SAndroid Build Coastguard Worker }
775*8975f5c5SAndroid Build Coastguard Worker 
TextureBufferContentsObservers(Texture * texture)776*8975f5c5SAndroid Build Coastguard Worker TextureBufferContentsObservers::TextureBufferContentsObservers(Texture *texture) : mTexture(texture)
777*8975f5c5SAndroid Build Coastguard Worker {}
778*8975f5c5SAndroid Build Coastguard Worker 
enableForBuffer(Buffer * buffer)779*8975f5c5SAndroid Build Coastguard Worker void TextureBufferContentsObservers::enableForBuffer(Buffer *buffer)
780*8975f5c5SAndroid Build Coastguard Worker {
781*8975f5c5SAndroid Build Coastguard Worker     buffer->addContentsObserver(mTexture);
782*8975f5c5SAndroid Build Coastguard Worker }
783*8975f5c5SAndroid Build Coastguard Worker 
disableForBuffer(Buffer * buffer)784*8975f5c5SAndroid Build Coastguard Worker void TextureBufferContentsObservers::disableForBuffer(Buffer *buffer)
785*8975f5c5SAndroid Build Coastguard Worker {
786*8975f5c5SAndroid Build Coastguard Worker     buffer->removeContentsObserver(mTexture);
787*8975f5c5SAndroid Build Coastguard Worker }
788*8975f5c5SAndroid Build Coastguard Worker 
Texture(rx::GLImplFactory * factory,TextureID id,TextureType type)789*8975f5c5SAndroid Build Coastguard Worker Texture::Texture(rx::GLImplFactory *factory, TextureID id, TextureType type)
790*8975f5c5SAndroid Build Coastguard Worker     : RefCountObject(factory->generateSerial(), id),
791*8975f5c5SAndroid Build Coastguard Worker       mState(type),
792*8975f5c5SAndroid Build Coastguard Worker       mTexture(factory->createTexture(mState)),
793*8975f5c5SAndroid Build Coastguard Worker       mImplObserver(this, rx::kTextureImageImplObserverMessageIndex),
794*8975f5c5SAndroid Build Coastguard Worker       mBufferObserver(this, kBufferSubjectIndex),
795*8975f5c5SAndroid Build Coastguard Worker       mBoundSurface(nullptr),
796*8975f5c5SAndroid Build Coastguard Worker       mBoundStream(nullptr),
797*8975f5c5SAndroid Build Coastguard Worker       mBufferContentsObservers(this)
798*8975f5c5SAndroid Build Coastguard Worker {
799*8975f5c5SAndroid Build Coastguard Worker     mImplObserver.bind(mTexture);
800*8975f5c5SAndroid Build Coastguard Worker     if (mTexture)
801*8975f5c5SAndroid Build Coastguard Worker     {
802*8975f5c5SAndroid Build Coastguard Worker         mTexture->setContentsObservers(&mBufferContentsObservers);
803*8975f5c5SAndroid Build Coastguard Worker     }
804*8975f5c5SAndroid Build Coastguard Worker 
805*8975f5c5SAndroid Build Coastguard Worker     // Initially assume the implementation is dirty.
806*8975f5c5SAndroid Build Coastguard Worker     mDirtyBits.set(DIRTY_BIT_IMPLEMENTATION);
807*8975f5c5SAndroid Build Coastguard Worker }
808*8975f5c5SAndroid Build Coastguard Worker 
onDestroy(const Context * context)809*8975f5c5SAndroid Build Coastguard Worker void Texture::onDestroy(const Context *context)
810*8975f5c5SAndroid Build Coastguard Worker {
811*8975f5c5SAndroid Build Coastguard Worker     onStateChange(angle::SubjectMessage::TextureIDDeleted);
812*8975f5c5SAndroid Build Coastguard Worker 
813*8975f5c5SAndroid Build Coastguard Worker     if (mBoundSurface)
814*8975f5c5SAndroid Build Coastguard Worker     {
815*8975f5c5SAndroid Build Coastguard Worker         ANGLE_SWALLOW_ERR(mBoundSurface->releaseTexImage(context, EGL_BACK_BUFFER));
816*8975f5c5SAndroid Build Coastguard Worker         mBoundSurface = nullptr;
817*8975f5c5SAndroid Build Coastguard Worker     }
818*8975f5c5SAndroid Build Coastguard Worker     if (mBoundStream)
819*8975f5c5SAndroid Build Coastguard Worker     {
820*8975f5c5SAndroid Build Coastguard Worker         mBoundStream->releaseTextures();
821*8975f5c5SAndroid Build Coastguard Worker         mBoundStream = nullptr;
822*8975f5c5SAndroid Build Coastguard Worker     }
823*8975f5c5SAndroid Build Coastguard Worker 
824*8975f5c5SAndroid Build Coastguard Worker     egl::RefCountObjectReleaser<egl::Image> releaseImage;
825*8975f5c5SAndroid Build Coastguard Worker     (void)orphanImages(context, &releaseImage);
826*8975f5c5SAndroid Build Coastguard Worker 
827*8975f5c5SAndroid Build Coastguard Worker     mState.mBuffer.set(context, nullptr, 0, 0);
828*8975f5c5SAndroid Build Coastguard Worker 
829*8975f5c5SAndroid Build Coastguard Worker     if (mTexture)
830*8975f5c5SAndroid Build Coastguard Worker     {
831*8975f5c5SAndroid Build Coastguard Worker         mTexture->onDestroy(context);
832*8975f5c5SAndroid Build Coastguard Worker     }
833*8975f5c5SAndroid Build Coastguard Worker }
834*8975f5c5SAndroid Build Coastguard Worker 
~Texture()835*8975f5c5SAndroid Build Coastguard Worker Texture::~Texture()
836*8975f5c5SAndroid Build Coastguard Worker {
837*8975f5c5SAndroid Build Coastguard Worker     SafeDelete(mTexture);
838*8975f5c5SAndroid Build Coastguard Worker }
839*8975f5c5SAndroid Build Coastguard Worker 
setLabel(const Context * context,const std::string & label)840*8975f5c5SAndroid Build Coastguard Worker angle::Result Texture::setLabel(const Context *context, const std::string &label)
841*8975f5c5SAndroid Build Coastguard Worker {
842*8975f5c5SAndroid Build Coastguard Worker     mState.mLabel = label;
843*8975f5c5SAndroid Build Coastguard Worker     return mTexture->onLabelUpdate(context);
844*8975f5c5SAndroid Build Coastguard Worker }
845*8975f5c5SAndroid Build Coastguard Worker 
getLabel() const846*8975f5c5SAndroid Build Coastguard Worker const std::string &Texture::getLabel() const
847*8975f5c5SAndroid Build Coastguard Worker {
848*8975f5c5SAndroid Build Coastguard Worker     return mState.mLabel;
849*8975f5c5SAndroid Build Coastguard Worker }
850*8975f5c5SAndroid Build Coastguard Worker 
setSwizzleRed(const Context * context,GLenum swizzleRed)851*8975f5c5SAndroid Build Coastguard Worker void Texture::setSwizzleRed(const Context *context, GLenum swizzleRed)
852*8975f5c5SAndroid Build Coastguard Worker {
853*8975f5c5SAndroid Build Coastguard Worker     if (mState.mSwizzleState.swizzleRed != swizzleRed)
854*8975f5c5SAndroid Build Coastguard Worker     {
855*8975f5c5SAndroid Build Coastguard Worker         mState.mSwizzleState.swizzleRed = swizzleRed;
856*8975f5c5SAndroid Build Coastguard Worker         signalDirtyState(DIRTY_BIT_SWIZZLE_RED);
857*8975f5c5SAndroid Build Coastguard Worker     }
858*8975f5c5SAndroid Build Coastguard Worker }
859*8975f5c5SAndroid Build Coastguard Worker 
getSwizzleRed() const860*8975f5c5SAndroid Build Coastguard Worker GLenum Texture::getSwizzleRed() const
861*8975f5c5SAndroid Build Coastguard Worker {
862*8975f5c5SAndroid Build Coastguard Worker     return mState.mSwizzleState.swizzleRed;
863*8975f5c5SAndroid Build Coastguard Worker }
864*8975f5c5SAndroid Build Coastguard Worker 
setSwizzleGreen(const Context * context,GLenum swizzleGreen)865*8975f5c5SAndroid Build Coastguard Worker void Texture::setSwizzleGreen(const Context *context, GLenum swizzleGreen)
866*8975f5c5SAndroid Build Coastguard Worker {
867*8975f5c5SAndroid Build Coastguard Worker     if (mState.mSwizzleState.swizzleGreen != swizzleGreen)
868*8975f5c5SAndroid Build Coastguard Worker     {
869*8975f5c5SAndroid Build Coastguard Worker         mState.mSwizzleState.swizzleGreen = swizzleGreen;
870*8975f5c5SAndroid Build Coastguard Worker         signalDirtyState(DIRTY_BIT_SWIZZLE_GREEN);
871*8975f5c5SAndroid Build Coastguard Worker     }
872*8975f5c5SAndroid Build Coastguard Worker }
873*8975f5c5SAndroid Build Coastguard Worker 
getSwizzleGreen() const874*8975f5c5SAndroid Build Coastguard Worker GLenum Texture::getSwizzleGreen() const
875*8975f5c5SAndroid Build Coastguard Worker {
876*8975f5c5SAndroid Build Coastguard Worker     return mState.mSwizzleState.swizzleGreen;
877*8975f5c5SAndroid Build Coastguard Worker }
878*8975f5c5SAndroid Build Coastguard Worker 
setSwizzleBlue(const Context * context,GLenum swizzleBlue)879*8975f5c5SAndroid Build Coastguard Worker void Texture::setSwizzleBlue(const Context *context, GLenum swizzleBlue)
880*8975f5c5SAndroid Build Coastguard Worker {
881*8975f5c5SAndroid Build Coastguard Worker     if (mState.mSwizzleState.swizzleBlue != swizzleBlue)
882*8975f5c5SAndroid Build Coastguard Worker     {
883*8975f5c5SAndroid Build Coastguard Worker         mState.mSwizzleState.swizzleBlue = swizzleBlue;
884*8975f5c5SAndroid Build Coastguard Worker         signalDirtyState(DIRTY_BIT_SWIZZLE_BLUE);
885*8975f5c5SAndroid Build Coastguard Worker     }
886*8975f5c5SAndroid Build Coastguard Worker }
887*8975f5c5SAndroid Build Coastguard Worker 
getSwizzleBlue() const888*8975f5c5SAndroid Build Coastguard Worker GLenum Texture::getSwizzleBlue() const
889*8975f5c5SAndroid Build Coastguard Worker {
890*8975f5c5SAndroid Build Coastguard Worker     return mState.mSwizzleState.swizzleBlue;
891*8975f5c5SAndroid Build Coastguard Worker }
892*8975f5c5SAndroid Build Coastguard Worker 
setSwizzleAlpha(const Context * context,GLenum swizzleAlpha)893*8975f5c5SAndroid Build Coastguard Worker void Texture::setSwizzleAlpha(const Context *context, GLenum swizzleAlpha)
894*8975f5c5SAndroid Build Coastguard Worker {
895*8975f5c5SAndroid Build Coastguard Worker     if (mState.mSwizzleState.swizzleAlpha != swizzleAlpha)
896*8975f5c5SAndroid Build Coastguard Worker     {
897*8975f5c5SAndroid Build Coastguard Worker         mState.mSwizzleState.swizzleAlpha = swizzleAlpha;
898*8975f5c5SAndroid Build Coastguard Worker         signalDirtyState(DIRTY_BIT_SWIZZLE_ALPHA);
899*8975f5c5SAndroid Build Coastguard Worker     }
900*8975f5c5SAndroid Build Coastguard Worker }
901*8975f5c5SAndroid Build Coastguard Worker 
getSwizzleAlpha() const902*8975f5c5SAndroid Build Coastguard Worker GLenum Texture::getSwizzleAlpha() const
903*8975f5c5SAndroid Build Coastguard Worker {
904*8975f5c5SAndroid Build Coastguard Worker     return mState.mSwizzleState.swizzleAlpha;
905*8975f5c5SAndroid Build Coastguard Worker }
906*8975f5c5SAndroid Build Coastguard Worker 
setMinFilter(const Context * context,GLenum minFilter)907*8975f5c5SAndroid Build Coastguard Worker void Texture::setMinFilter(const Context *context, GLenum minFilter)
908*8975f5c5SAndroid Build Coastguard Worker {
909*8975f5c5SAndroid Build Coastguard Worker     if (mState.mSamplerState.setMinFilter(minFilter))
910*8975f5c5SAndroid Build Coastguard Worker     {
911*8975f5c5SAndroid Build Coastguard Worker         signalDirtyState(DIRTY_BIT_MIN_FILTER);
912*8975f5c5SAndroid Build Coastguard Worker     }
913*8975f5c5SAndroid Build Coastguard Worker }
914*8975f5c5SAndroid Build Coastguard Worker 
getMinFilter() const915*8975f5c5SAndroid Build Coastguard Worker GLenum Texture::getMinFilter() const
916*8975f5c5SAndroid Build Coastguard Worker {
917*8975f5c5SAndroid Build Coastguard Worker     return mState.mSamplerState.getMinFilter();
918*8975f5c5SAndroid Build Coastguard Worker }
919*8975f5c5SAndroid Build Coastguard Worker 
setMagFilter(const Context * context,GLenum magFilter)920*8975f5c5SAndroid Build Coastguard Worker void Texture::setMagFilter(const Context *context, GLenum magFilter)
921*8975f5c5SAndroid Build Coastguard Worker {
922*8975f5c5SAndroid Build Coastguard Worker     if (mState.mSamplerState.setMagFilter(magFilter))
923*8975f5c5SAndroid Build Coastguard Worker     {
924*8975f5c5SAndroid Build Coastguard Worker         signalDirtyState(DIRTY_BIT_MAG_FILTER);
925*8975f5c5SAndroid Build Coastguard Worker     }
926*8975f5c5SAndroid Build Coastguard Worker }
927*8975f5c5SAndroid Build Coastguard Worker 
getMagFilter() const928*8975f5c5SAndroid Build Coastguard Worker GLenum Texture::getMagFilter() const
929*8975f5c5SAndroid Build Coastguard Worker {
930*8975f5c5SAndroid Build Coastguard Worker     return mState.mSamplerState.getMagFilter();
931*8975f5c5SAndroid Build Coastguard Worker }
932*8975f5c5SAndroid Build Coastguard Worker 
setWrapS(const Context * context,GLenum wrapS)933*8975f5c5SAndroid Build Coastguard Worker void Texture::setWrapS(const Context *context, GLenum wrapS)
934*8975f5c5SAndroid Build Coastguard Worker {
935*8975f5c5SAndroid Build Coastguard Worker     if (mState.mSamplerState.setWrapS(wrapS))
936*8975f5c5SAndroid Build Coastguard Worker     {
937*8975f5c5SAndroid Build Coastguard Worker         signalDirtyState(DIRTY_BIT_WRAP_S);
938*8975f5c5SAndroid Build Coastguard Worker     }
939*8975f5c5SAndroid Build Coastguard Worker }
940*8975f5c5SAndroid Build Coastguard Worker 
getWrapS() const941*8975f5c5SAndroid Build Coastguard Worker GLenum Texture::getWrapS() const
942*8975f5c5SAndroid Build Coastguard Worker {
943*8975f5c5SAndroid Build Coastguard Worker     return mState.mSamplerState.getWrapS();
944*8975f5c5SAndroid Build Coastguard Worker }
945*8975f5c5SAndroid Build Coastguard Worker 
setWrapT(const Context * context,GLenum wrapT)946*8975f5c5SAndroid Build Coastguard Worker void Texture::setWrapT(const Context *context, GLenum wrapT)
947*8975f5c5SAndroid Build Coastguard Worker {
948*8975f5c5SAndroid Build Coastguard Worker     if (mState.mSamplerState.getWrapT() == wrapT)
949*8975f5c5SAndroid Build Coastguard Worker         return;
950*8975f5c5SAndroid Build Coastguard Worker     if (mState.mSamplerState.setWrapT(wrapT))
951*8975f5c5SAndroid Build Coastguard Worker     {
952*8975f5c5SAndroid Build Coastguard Worker         signalDirtyState(DIRTY_BIT_WRAP_T);
953*8975f5c5SAndroid Build Coastguard Worker     }
954*8975f5c5SAndroid Build Coastguard Worker }
955*8975f5c5SAndroid Build Coastguard Worker 
getWrapT() const956*8975f5c5SAndroid Build Coastguard Worker GLenum Texture::getWrapT() const
957*8975f5c5SAndroid Build Coastguard Worker {
958*8975f5c5SAndroid Build Coastguard Worker     return mState.mSamplerState.getWrapT();
959*8975f5c5SAndroid Build Coastguard Worker }
960*8975f5c5SAndroid Build Coastguard Worker 
setWrapR(const Context * context,GLenum wrapR)961*8975f5c5SAndroid Build Coastguard Worker void Texture::setWrapR(const Context *context, GLenum wrapR)
962*8975f5c5SAndroid Build Coastguard Worker {
963*8975f5c5SAndroid Build Coastguard Worker     if (mState.mSamplerState.setWrapR(wrapR))
964*8975f5c5SAndroid Build Coastguard Worker     {
965*8975f5c5SAndroid Build Coastguard Worker         signalDirtyState(DIRTY_BIT_WRAP_R);
966*8975f5c5SAndroid Build Coastguard Worker     }
967*8975f5c5SAndroid Build Coastguard Worker }
968*8975f5c5SAndroid Build Coastguard Worker 
getWrapR() const969*8975f5c5SAndroid Build Coastguard Worker GLenum Texture::getWrapR() const
970*8975f5c5SAndroid Build Coastguard Worker {
971*8975f5c5SAndroid Build Coastguard Worker     return mState.mSamplerState.getWrapR();
972*8975f5c5SAndroid Build Coastguard Worker }
973*8975f5c5SAndroid Build Coastguard Worker 
setMaxAnisotropy(const Context * context,float maxAnisotropy)974*8975f5c5SAndroid Build Coastguard Worker void Texture::setMaxAnisotropy(const Context *context, float maxAnisotropy)
975*8975f5c5SAndroid Build Coastguard Worker {
976*8975f5c5SAndroid Build Coastguard Worker     if (mState.mSamplerState.setMaxAnisotropy(maxAnisotropy))
977*8975f5c5SAndroid Build Coastguard Worker     {
978*8975f5c5SAndroid Build Coastguard Worker         signalDirtyState(DIRTY_BIT_MAX_ANISOTROPY);
979*8975f5c5SAndroid Build Coastguard Worker     }
980*8975f5c5SAndroid Build Coastguard Worker }
981*8975f5c5SAndroid Build Coastguard Worker 
getMaxAnisotropy() const982*8975f5c5SAndroid Build Coastguard Worker float Texture::getMaxAnisotropy() const
983*8975f5c5SAndroid Build Coastguard Worker {
984*8975f5c5SAndroid Build Coastguard Worker     return mState.mSamplerState.getMaxAnisotropy();
985*8975f5c5SAndroid Build Coastguard Worker }
986*8975f5c5SAndroid Build Coastguard Worker 
setMinLod(const Context * context,GLfloat minLod)987*8975f5c5SAndroid Build Coastguard Worker void Texture::setMinLod(const Context *context, GLfloat minLod)
988*8975f5c5SAndroid Build Coastguard Worker {
989*8975f5c5SAndroid Build Coastguard Worker     if (mState.mSamplerState.setMinLod(minLod))
990*8975f5c5SAndroid Build Coastguard Worker     {
991*8975f5c5SAndroid Build Coastguard Worker         signalDirtyState(DIRTY_BIT_MIN_LOD);
992*8975f5c5SAndroid Build Coastguard Worker     }
993*8975f5c5SAndroid Build Coastguard Worker }
994*8975f5c5SAndroid Build Coastguard Worker 
getMinLod() const995*8975f5c5SAndroid Build Coastguard Worker GLfloat Texture::getMinLod() const
996*8975f5c5SAndroid Build Coastguard Worker {
997*8975f5c5SAndroid Build Coastguard Worker     return mState.mSamplerState.getMinLod();
998*8975f5c5SAndroid Build Coastguard Worker }
999*8975f5c5SAndroid Build Coastguard Worker 
setMaxLod(const Context * context,GLfloat maxLod)1000*8975f5c5SAndroid Build Coastguard Worker void Texture::setMaxLod(const Context *context, GLfloat maxLod)
1001*8975f5c5SAndroid Build Coastguard Worker {
1002*8975f5c5SAndroid Build Coastguard Worker     if (mState.mSamplerState.setMaxLod(maxLod))
1003*8975f5c5SAndroid Build Coastguard Worker     {
1004*8975f5c5SAndroid Build Coastguard Worker         signalDirtyState(DIRTY_BIT_MAX_LOD);
1005*8975f5c5SAndroid Build Coastguard Worker     }
1006*8975f5c5SAndroid Build Coastguard Worker }
1007*8975f5c5SAndroid Build Coastguard Worker 
getMaxLod() const1008*8975f5c5SAndroid Build Coastguard Worker GLfloat Texture::getMaxLod() const
1009*8975f5c5SAndroid Build Coastguard Worker {
1010*8975f5c5SAndroid Build Coastguard Worker     return mState.mSamplerState.getMaxLod();
1011*8975f5c5SAndroid Build Coastguard Worker }
1012*8975f5c5SAndroid Build Coastguard Worker 
setCompareMode(const Context * context,GLenum compareMode)1013*8975f5c5SAndroid Build Coastguard Worker void Texture::setCompareMode(const Context *context, GLenum compareMode)
1014*8975f5c5SAndroid Build Coastguard Worker {
1015*8975f5c5SAndroid Build Coastguard Worker     if (mState.mSamplerState.setCompareMode(compareMode))
1016*8975f5c5SAndroid Build Coastguard Worker     {
1017*8975f5c5SAndroid Build Coastguard Worker         signalDirtyState(DIRTY_BIT_COMPARE_MODE);
1018*8975f5c5SAndroid Build Coastguard Worker     }
1019*8975f5c5SAndroid Build Coastguard Worker }
1020*8975f5c5SAndroid Build Coastguard Worker 
getCompareMode() const1021*8975f5c5SAndroid Build Coastguard Worker GLenum Texture::getCompareMode() const
1022*8975f5c5SAndroid Build Coastguard Worker {
1023*8975f5c5SAndroid Build Coastguard Worker     return mState.mSamplerState.getCompareMode();
1024*8975f5c5SAndroid Build Coastguard Worker }
1025*8975f5c5SAndroid Build Coastguard Worker 
setCompareFunc(const Context * context,GLenum compareFunc)1026*8975f5c5SAndroid Build Coastguard Worker void Texture::setCompareFunc(const Context *context, GLenum compareFunc)
1027*8975f5c5SAndroid Build Coastguard Worker {
1028*8975f5c5SAndroid Build Coastguard Worker     if (mState.mSamplerState.setCompareFunc(compareFunc))
1029*8975f5c5SAndroid Build Coastguard Worker     {
1030*8975f5c5SAndroid Build Coastguard Worker         signalDirtyState(DIRTY_BIT_COMPARE_FUNC);
1031*8975f5c5SAndroid Build Coastguard Worker     }
1032*8975f5c5SAndroid Build Coastguard Worker }
1033*8975f5c5SAndroid Build Coastguard Worker 
getCompareFunc() const1034*8975f5c5SAndroid Build Coastguard Worker GLenum Texture::getCompareFunc() const
1035*8975f5c5SAndroid Build Coastguard Worker {
1036*8975f5c5SAndroid Build Coastguard Worker     return mState.mSamplerState.getCompareFunc();
1037*8975f5c5SAndroid Build Coastguard Worker }
1038*8975f5c5SAndroid Build Coastguard Worker 
setSRGBDecode(const Context * context,GLenum sRGBDecode)1039*8975f5c5SAndroid Build Coastguard Worker void Texture::setSRGBDecode(const Context *context, GLenum sRGBDecode)
1040*8975f5c5SAndroid Build Coastguard Worker {
1041*8975f5c5SAndroid Build Coastguard Worker     if (mState.mSamplerState.setSRGBDecode(sRGBDecode))
1042*8975f5c5SAndroid Build Coastguard Worker     {
1043*8975f5c5SAndroid Build Coastguard Worker         signalDirtyState(DIRTY_BIT_SRGB_DECODE);
1044*8975f5c5SAndroid Build Coastguard Worker     }
1045*8975f5c5SAndroid Build Coastguard Worker }
1046*8975f5c5SAndroid Build Coastguard Worker 
getSRGBDecode() const1047*8975f5c5SAndroid Build Coastguard Worker GLenum Texture::getSRGBDecode() const
1048*8975f5c5SAndroid Build Coastguard Worker {
1049*8975f5c5SAndroid Build Coastguard Worker     return mState.mSamplerState.getSRGBDecode();
1050*8975f5c5SAndroid Build Coastguard Worker }
1051*8975f5c5SAndroid Build Coastguard Worker 
setSRGBOverride(const Context * context,GLenum sRGBOverride)1052*8975f5c5SAndroid Build Coastguard Worker void Texture::setSRGBOverride(const Context *context, GLenum sRGBOverride)
1053*8975f5c5SAndroid Build Coastguard Worker {
1054*8975f5c5SAndroid Build Coastguard Worker     SrgbOverride oldOverride = mState.mSrgbOverride;
1055*8975f5c5SAndroid Build Coastguard Worker     mState.mSrgbOverride = (sRGBOverride == GL_SRGB) ? SrgbOverride::SRGB : SrgbOverride::Default;
1056*8975f5c5SAndroid Build Coastguard Worker     if (mState.mSrgbOverride != oldOverride)
1057*8975f5c5SAndroid Build Coastguard Worker     {
1058*8975f5c5SAndroid Build Coastguard Worker         signalDirtyState(DIRTY_BIT_SRGB_OVERRIDE);
1059*8975f5c5SAndroid Build Coastguard Worker     }
1060*8975f5c5SAndroid Build Coastguard Worker }
1061*8975f5c5SAndroid Build Coastguard Worker 
getSRGBOverride() const1062*8975f5c5SAndroid Build Coastguard Worker GLenum Texture::getSRGBOverride() const
1063*8975f5c5SAndroid Build Coastguard Worker {
1064*8975f5c5SAndroid Build Coastguard Worker     return (mState.mSrgbOverride == SrgbOverride::SRGB) ? GL_SRGB : GL_NONE;
1065*8975f5c5SAndroid Build Coastguard Worker }
1066*8975f5c5SAndroid Build Coastguard Worker 
getSamplerState() const1067*8975f5c5SAndroid Build Coastguard Worker const SamplerState &Texture::getSamplerState() const
1068*8975f5c5SAndroid Build Coastguard Worker {
1069*8975f5c5SAndroid Build Coastguard Worker     return mState.mSamplerState;
1070*8975f5c5SAndroid Build Coastguard Worker }
1071*8975f5c5SAndroid Build Coastguard Worker 
setBaseLevel(const Context * context,GLuint baseLevel)1072*8975f5c5SAndroid Build Coastguard Worker angle::Result Texture::setBaseLevel(const Context *context, GLuint baseLevel)
1073*8975f5c5SAndroid Build Coastguard Worker {
1074*8975f5c5SAndroid Build Coastguard Worker     if (mState.setBaseLevel(baseLevel))
1075*8975f5c5SAndroid Build Coastguard Worker     {
1076*8975f5c5SAndroid Build Coastguard Worker         ANGLE_TRY(mTexture->setBaseLevel(context, mState.getEffectiveBaseLevel()));
1077*8975f5c5SAndroid Build Coastguard Worker         signalDirtyState(DIRTY_BIT_BASE_LEVEL);
1078*8975f5c5SAndroid Build Coastguard Worker     }
1079*8975f5c5SAndroid Build Coastguard Worker 
1080*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
1081*8975f5c5SAndroid Build Coastguard Worker }
1082*8975f5c5SAndroid Build Coastguard Worker 
getBaseLevel() const1083*8975f5c5SAndroid Build Coastguard Worker GLuint Texture::getBaseLevel() const
1084*8975f5c5SAndroid Build Coastguard Worker {
1085*8975f5c5SAndroid Build Coastguard Worker     return mState.mBaseLevel;
1086*8975f5c5SAndroid Build Coastguard Worker }
1087*8975f5c5SAndroid Build Coastguard Worker 
setMaxLevel(const Context * context,GLuint maxLevel)1088*8975f5c5SAndroid Build Coastguard Worker void Texture::setMaxLevel(const Context *context, GLuint maxLevel)
1089*8975f5c5SAndroid Build Coastguard Worker {
1090*8975f5c5SAndroid Build Coastguard Worker     if (mState.setMaxLevel(maxLevel))
1091*8975f5c5SAndroid Build Coastguard Worker     {
1092*8975f5c5SAndroid Build Coastguard Worker         signalDirtyState(DIRTY_BIT_MAX_LEVEL);
1093*8975f5c5SAndroid Build Coastguard Worker     }
1094*8975f5c5SAndroid Build Coastguard Worker }
1095*8975f5c5SAndroid Build Coastguard Worker 
getMaxLevel() const1096*8975f5c5SAndroid Build Coastguard Worker GLuint Texture::getMaxLevel() const
1097*8975f5c5SAndroid Build Coastguard Worker {
1098*8975f5c5SAndroid Build Coastguard Worker     return mState.mMaxLevel;
1099*8975f5c5SAndroid Build Coastguard Worker }
1100*8975f5c5SAndroid Build Coastguard Worker 
setDepthStencilTextureMode(const Context * context,GLenum mode)1101*8975f5c5SAndroid Build Coastguard Worker void Texture::setDepthStencilTextureMode(const Context *context, GLenum mode)
1102*8975f5c5SAndroid Build Coastguard Worker {
1103*8975f5c5SAndroid Build Coastguard Worker     if (mState.mDepthStencilTextureMode != mode)
1104*8975f5c5SAndroid Build Coastguard Worker     {
1105*8975f5c5SAndroid Build Coastguard Worker         mState.mDepthStencilTextureMode = mode;
1106*8975f5c5SAndroid Build Coastguard Worker         signalDirtyState(DIRTY_BIT_DEPTH_STENCIL_TEXTURE_MODE);
1107*8975f5c5SAndroid Build Coastguard Worker     }
1108*8975f5c5SAndroid Build Coastguard Worker }
1109*8975f5c5SAndroid Build Coastguard Worker 
getDepthStencilTextureMode() const1110*8975f5c5SAndroid Build Coastguard Worker GLenum Texture::getDepthStencilTextureMode() const
1111*8975f5c5SAndroid Build Coastguard Worker {
1112*8975f5c5SAndroid Build Coastguard Worker     return mState.mDepthStencilTextureMode;
1113*8975f5c5SAndroid Build Coastguard Worker }
1114*8975f5c5SAndroid Build Coastguard Worker 
getImmutableFormat() const1115*8975f5c5SAndroid Build Coastguard Worker bool Texture::getImmutableFormat() const
1116*8975f5c5SAndroid Build Coastguard Worker {
1117*8975f5c5SAndroid Build Coastguard Worker     return mState.mImmutableFormat;
1118*8975f5c5SAndroid Build Coastguard Worker }
1119*8975f5c5SAndroid Build Coastguard Worker 
getImmutableLevels() const1120*8975f5c5SAndroid Build Coastguard Worker GLuint Texture::getImmutableLevels() const
1121*8975f5c5SAndroid Build Coastguard Worker {
1122*8975f5c5SAndroid Build Coastguard Worker     return mState.mImmutableLevels;
1123*8975f5c5SAndroid Build Coastguard Worker }
1124*8975f5c5SAndroid Build Coastguard Worker 
setUsage(const Context * context,GLenum usage)1125*8975f5c5SAndroid Build Coastguard Worker void Texture::setUsage(const Context *context, GLenum usage)
1126*8975f5c5SAndroid Build Coastguard Worker {
1127*8975f5c5SAndroid Build Coastguard Worker     mState.mUsage = usage;
1128*8975f5c5SAndroid Build Coastguard Worker     signalDirtyState(DIRTY_BIT_USAGE);
1129*8975f5c5SAndroid Build Coastguard Worker }
1130*8975f5c5SAndroid Build Coastguard Worker 
getUsage() const1131*8975f5c5SAndroid Build Coastguard Worker GLenum Texture::getUsage() const
1132*8975f5c5SAndroid Build Coastguard Worker {
1133*8975f5c5SAndroid Build Coastguard Worker     return mState.mUsage;
1134*8975f5c5SAndroid Build Coastguard Worker }
1135*8975f5c5SAndroid Build Coastguard Worker 
setProtectedContent(Context * context,bool hasProtectedContent)1136*8975f5c5SAndroid Build Coastguard Worker void Texture::setProtectedContent(Context *context, bool hasProtectedContent)
1137*8975f5c5SAndroid Build Coastguard Worker {
1138*8975f5c5SAndroid Build Coastguard Worker     mState.mHasProtectedContent = hasProtectedContent;
1139*8975f5c5SAndroid Build Coastguard Worker }
1140*8975f5c5SAndroid Build Coastguard Worker 
hasProtectedContent() const1141*8975f5c5SAndroid Build Coastguard Worker bool Texture::hasProtectedContent() const
1142*8975f5c5SAndroid Build Coastguard Worker {
1143*8975f5c5SAndroid Build Coastguard Worker     return mState.mHasProtectedContent;
1144*8975f5c5SAndroid Build Coastguard Worker }
1145*8975f5c5SAndroid Build Coastguard Worker 
setRenderabilityValidation(Context * context,bool renderabilityValidation)1146*8975f5c5SAndroid Build Coastguard Worker void Texture::setRenderabilityValidation(Context *context, bool renderabilityValidation)
1147*8975f5c5SAndroid Build Coastguard Worker {
1148*8975f5c5SAndroid Build Coastguard Worker     mState.mRenderabilityValidation = renderabilityValidation;
1149*8975f5c5SAndroid Build Coastguard Worker     signalDirtyState(DIRTY_BIT_RENDERABILITY_VALIDATION_ANGLE);
1150*8975f5c5SAndroid Build Coastguard Worker }
1151*8975f5c5SAndroid Build Coastguard Worker 
setTilingMode(Context * context,GLenum tilingMode)1152*8975f5c5SAndroid Build Coastguard Worker void Texture::setTilingMode(Context *context, GLenum tilingMode)
1153*8975f5c5SAndroid Build Coastguard Worker {
1154*8975f5c5SAndroid Build Coastguard Worker     mState.mTilingMode = gl::FromGLenum<gl::TilingMode>(tilingMode);
1155*8975f5c5SAndroid Build Coastguard Worker }
1156*8975f5c5SAndroid Build Coastguard Worker 
getTilingMode() const1157*8975f5c5SAndroid Build Coastguard Worker GLenum Texture::getTilingMode() const
1158*8975f5c5SAndroid Build Coastguard Worker {
1159*8975f5c5SAndroid Build Coastguard Worker     return gl::ToGLenum(mState.mTilingMode);
1160*8975f5c5SAndroid Build Coastguard Worker }
1161*8975f5c5SAndroid Build Coastguard Worker 
getTextureState() const1162*8975f5c5SAndroid Build Coastguard Worker const TextureState &Texture::getTextureState() const
1163*8975f5c5SAndroid Build Coastguard Worker {
1164*8975f5c5SAndroid Build Coastguard Worker     return mState;
1165*8975f5c5SAndroid Build Coastguard Worker }
1166*8975f5c5SAndroid Build Coastguard Worker 
getExtents(TextureTarget target,size_t level) const1167*8975f5c5SAndroid Build Coastguard Worker const Extents &Texture::getExtents(TextureTarget target, size_t level) const
1168*8975f5c5SAndroid Build Coastguard Worker {
1169*8975f5c5SAndroid Build Coastguard Worker     ASSERT(TextureTargetToType(target) == mState.mType);
1170*8975f5c5SAndroid Build Coastguard Worker     return mState.getImageDesc(target, level).size;
1171*8975f5c5SAndroid Build Coastguard Worker }
1172*8975f5c5SAndroid Build Coastguard Worker 
getWidth(TextureTarget target,size_t level) const1173*8975f5c5SAndroid Build Coastguard Worker size_t Texture::getWidth(TextureTarget target, size_t level) const
1174*8975f5c5SAndroid Build Coastguard Worker {
1175*8975f5c5SAndroid Build Coastguard Worker     ASSERT(TextureTargetToType(target) == mState.mType);
1176*8975f5c5SAndroid Build Coastguard Worker     return mState.getImageDesc(target, level).size.width;
1177*8975f5c5SAndroid Build Coastguard Worker }
1178*8975f5c5SAndroid Build Coastguard Worker 
getHeight(TextureTarget target,size_t level) const1179*8975f5c5SAndroid Build Coastguard Worker size_t Texture::getHeight(TextureTarget target, size_t level) const
1180*8975f5c5SAndroid Build Coastguard Worker {
1181*8975f5c5SAndroid Build Coastguard Worker     ASSERT(TextureTargetToType(target) == mState.mType);
1182*8975f5c5SAndroid Build Coastguard Worker     return mState.getImageDesc(target, level).size.height;
1183*8975f5c5SAndroid Build Coastguard Worker }
1184*8975f5c5SAndroid Build Coastguard Worker 
getDepth(TextureTarget target,size_t level) const1185*8975f5c5SAndroid Build Coastguard Worker size_t Texture::getDepth(TextureTarget target, size_t level) const
1186*8975f5c5SAndroid Build Coastguard Worker {
1187*8975f5c5SAndroid Build Coastguard Worker     ASSERT(TextureTargetToType(target) == mState.mType);
1188*8975f5c5SAndroid Build Coastguard Worker     return mState.getImageDesc(target, level).size.depth;
1189*8975f5c5SAndroid Build Coastguard Worker }
1190*8975f5c5SAndroid Build Coastguard Worker 
getFormat(TextureTarget target,size_t level) const1191*8975f5c5SAndroid Build Coastguard Worker const Format &Texture::getFormat(TextureTarget target, size_t level) const
1192*8975f5c5SAndroid Build Coastguard Worker {
1193*8975f5c5SAndroid Build Coastguard Worker     ASSERT(TextureTargetToType(target) == mState.mType);
1194*8975f5c5SAndroid Build Coastguard Worker     return mState.getImageDesc(target, level).format;
1195*8975f5c5SAndroid Build Coastguard Worker }
1196*8975f5c5SAndroid Build Coastguard Worker 
getSamples(TextureTarget target,size_t level) const1197*8975f5c5SAndroid Build Coastguard Worker GLsizei Texture::getSamples(TextureTarget target, size_t level) const
1198*8975f5c5SAndroid Build Coastguard Worker {
1199*8975f5c5SAndroid Build Coastguard Worker     ASSERT(TextureTargetToType(target) == mState.mType);
1200*8975f5c5SAndroid Build Coastguard Worker     return mState.getImageDesc(target, level).samples;
1201*8975f5c5SAndroid Build Coastguard Worker }
1202*8975f5c5SAndroid Build Coastguard Worker 
getFixedSampleLocations(TextureTarget target,size_t level) const1203*8975f5c5SAndroid Build Coastguard Worker bool Texture::getFixedSampleLocations(TextureTarget target, size_t level) const
1204*8975f5c5SAndroid Build Coastguard Worker {
1205*8975f5c5SAndroid Build Coastguard Worker     ASSERT(TextureTargetToType(target) == mState.mType);
1206*8975f5c5SAndroid Build Coastguard Worker     return mState.getImageDesc(target, level).fixedSampleLocations;
1207*8975f5c5SAndroid Build Coastguard Worker }
1208*8975f5c5SAndroid Build Coastguard Worker 
getMipmapMaxLevel() const1209*8975f5c5SAndroid Build Coastguard Worker GLuint Texture::getMipmapMaxLevel() const
1210*8975f5c5SAndroid Build Coastguard Worker {
1211*8975f5c5SAndroid Build Coastguard Worker     return mState.getMipmapMaxLevel();
1212*8975f5c5SAndroid Build Coastguard Worker }
1213*8975f5c5SAndroid Build Coastguard Worker 
isMipmapComplete() const1214*8975f5c5SAndroid Build Coastguard Worker bool Texture::isMipmapComplete() const
1215*8975f5c5SAndroid Build Coastguard Worker {
1216*8975f5c5SAndroid Build Coastguard Worker     return mState.computeMipmapCompleteness();
1217*8975f5c5SAndroid Build Coastguard Worker }
1218*8975f5c5SAndroid Build Coastguard Worker 
getFoveatedFeatureBits() const1219*8975f5c5SAndroid Build Coastguard Worker GLuint Texture::getFoveatedFeatureBits() const
1220*8975f5c5SAndroid Build Coastguard Worker {
1221*8975f5c5SAndroid Build Coastguard Worker     return mState.mFoveationState.getFoveatedFeatureBits();
1222*8975f5c5SAndroid Build Coastguard Worker }
1223*8975f5c5SAndroid Build Coastguard Worker 
setFoveatedFeatureBits(const GLuint features)1224*8975f5c5SAndroid Build Coastguard Worker void Texture::setFoveatedFeatureBits(const GLuint features)
1225*8975f5c5SAndroid Build Coastguard Worker {
1226*8975f5c5SAndroid Build Coastguard Worker     mState.mFoveationState.setFoveatedFeatureBits(features);
1227*8975f5c5SAndroid Build Coastguard Worker }
1228*8975f5c5SAndroid Build Coastguard Worker 
isFoveationEnabled() const1229*8975f5c5SAndroid Build Coastguard Worker bool Texture::isFoveationEnabled() const
1230*8975f5c5SAndroid Build Coastguard Worker {
1231*8975f5c5SAndroid Build Coastguard Worker     return (mState.mFoveationState.getFoveatedFeatureBits() & GL_FOVEATION_ENABLE_BIT_QCOM);
1232*8975f5c5SAndroid Build Coastguard Worker }
1233*8975f5c5SAndroid Build Coastguard Worker 
getSupportedFoveationFeatures() const1234*8975f5c5SAndroid Build Coastguard Worker GLuint Texture::getSupportedFoveationFeatures() const
1235*8975f5c5SAndroid Build Coastguard Worker {
1236*8975f5c5SAndroid Build Coastguard Worker     return mState.mFoveationState.getSupportedFoveationFeatures();
1237*8975f5c5SAndroid Build Coastguard Worker }
1238*8975f5c5SAndroid Build Coastguard Worker 
getMinPixelDensity() const1239*8975f5c5SAndroid Build Coastguard Worker GLfloat Texture::getMinPixelDensity() const
1240*8975f5c5SAndroid Build Coastguard Worker {
1241*8975f5c5SAndroid Build Coastguard Worker     return mState.mFoveationState.getMinPixelDensity();
1242*8975f5c5SAndroid Build Coastguard Worker }
1243*8975f5c5SAndroid Build Coastguard Worker 
setMinPixelDensity(const GLfloat density)1244*8975f5c5SAndroid Build Coastguard Worker void Texture::setMinPixelDensity(const GLfloat density)
1245*8975f5c5SAndroid Build Coastguard Worker {
1246*8975f5c5SAndroid Build Coastguard Worker     mState.mFoveationState.setMinPixelDensity(density);
1247*8975f5c5SAndroid Build Coastguard Worker }
1248*8975f5c5SAndroid Build Coastguard Worker 
setFocalPoint(uint32_t layer,uint32_t focalPointIndex,float focalX,float focalY,float gainX,float gainY,float foveaArea)1249*8975f5c5SAndroid Build Coastguard Worker void Texture::setFocalPoint(uint32_t layer,
1250*8975f5c5SAndroid Build Coastguard Worker                             uint32_t focalPointIndex,
1251*8975f5c5SAndroid Build Coastguard Worker                             float focalX,
1252*8975f5c5SAndroid Build Coastguard Worker                             float focalY,
1253*8975f5c5SAndroid Build Coastguard Worker                             float gainX,
1254*8975f5c5SAndroid Build Coastguard Worker                             float gainY,
1255*8975f5c5SAndroid Build Coastguard Worker                             float foveaArea)
1256*8975f5c5SAndroid Build Coastguard Worker {
1257*8975f5c5SAndroid Build Coastguard Worker     gl::FocalPoint newFocalPoint(focalX, focalY, gainX, gainY, foveaArea);
1258*8975f5c5SAndroid Build Coastguard Worker     if (mState.mFoveationState.getFocalPoint(layer, focalPointIndex) == newFocalPoint)
1259*8975f5c5SAndroid Build Coastguard Worker     {
1260*8975f5c5SAndroid Build Coastguard Worker         // Nothing to do, early out.
1261*8975f5c5SAndroid Build Coastguard Worker         return;
1262*8975f5c5SAndroid Build Coastguard Worker     }
1263*8975f5c5SAndroid Build Coastguard Worker 
1264*8975f5c5SAndroid Build Coastguard Worker     mState.mFoveationState.setFocalPoint(layer, focalPointIndex, newFocalPoint);
1265*8975f5c5SAndroid Build Coastguard Worker     mState.mFoveationState.setFoveatedFeatureBits(GL_FOVEATION_ENABLE_BIT_QCOM);
1266*8975f5c5SAndroid Build Coastguard Worker     onStateChange(angle::SubjectMessage::FoveatedRenderingStateChanged);
1267*8975f5c5SAndroid Build Coastguard Worker }
1268*8975f5c5SAndroid Build Coastguard Worker 
getFocalPoint(uint32_t layer,uint32_t focalPoint) const1269*8975f5c5SAndroid Build Coastguard Worker const FocalPoint &Texture::getFocalPoint(uint32_t layer, uint32_t focalPoint) const
1270*8975f5c5SAndroid Build Coastguard Worker {
1271*8975f5c5SAndroid Build Coastguard Worker     return mState.mFoveationState.getFocalPoint(layer, focalPoint);
1272*8975f5c5SAndroid Build Coastguard Worker }
1273*8975f5c5SAndroid Build Coastguard Worker 
getBoundSurface() const1274*8975f5c5SAndroid Build Coastguard Worker egl::Surface *Texture::getBoundSurface() const
1275*8975f5c5SAndroid Build Coastguard Worker {
1276*8975f5c5SAndroid Build Coastguard Worker     return mBoundSurface;
1277*8975f5c5SAndroid Build Coastguard Worker }
1278*8975f5c5SAndroid Build Coastguard Worker 
getBoundStream() const1279*8975f5c5SAndroid Build Coastguard Worker egl::Stream *Texture::getBoundStream() const
1280*8975f5c5SAndroid Build Coastguard Worker {
1281*8975f5c5SAndroid Build Coastguard Worker     return mBoundStream;
1282*8975f5c5SAndroid Build Coastguard Worker }
1283*8975f5c5SAndroid Build Coastguard Worker 
getMemorySize() const1284*8975f5c5SAndroid Build Coastguard Worker GLint Texture::getMemorySize() const
1285*8975f5c5SAndroid Build Coastguard Worker {
1286*8975f5c5SAndroid Build Coastguard Worker     GLint implSize = mTexture->getMemorySize();
1287*8975f5c5SAndroid Build Coastguard Worker     if (implSize > 0)
1288*8975f5c5SAndroid Build Coastguard Worker     {
1289*8975f5c5SAndroid Build Coastguard Worker         return implSize;
1290*8975f5c5SAndroid Build Coastguard Worker     }
1291*8975f5c5SAndroid Build Coastguard Worker 
1292*8975f5c5SAndroid Build Coastguard Worker     angle::CheckedNumeric<GLint> size = 0;
1293*8975f5c5SAndroid Build Coastguard Worker     for (const ImageDesc &imageDesc : mState.mImageDescs)
1294*8975f5c5SAndroid Build Coastguard Worker     {
1295*8975f5c5SAndroid Build Coastguard Worker         size += imageDesc.getMemorySize();
1296*8975f5c5SAndroid Build Coastguard Worker     }
1297*8975f5c5SAndroid Build Coastguard Worker     return size.ValueOrDefault(std::numeric_limits<GLint>::max());
1298*8975f5c5SAndroid Build Coastguard Worker }
1299*8975f5c5SAndroid Build Coastguard Worker 
getLevelMemorySize(TextureTarget target,GLint level) const1300*8975f5c5SAndroid Build Coastguard Worker GLint Texture::getLevelMemorySize(TextureTarget target, GLint level) const
1301*8975f5c5SAndroid Build Coastguard Worker {
1302*8975f5c5SAndroid Build Coastguard Worker     GLint implSize = mTexture->getLevelMemorySize(target, level);
1303*8975f5c5SAndroid Build Coastguard Worker     if (implSize > 0)
1304*8975f5c5SAndroid Build Coastguard Worker     {
1305*8975f5c5SAndroid Build Coastguard Worker         return implSize;
1306*8975f5c5SAndroid Build Coastguard Worker     }
1307*8975f5c5SAndroid Build Coastguard Worker 
1308*8975f5c5SAndroid Build Coastguard Worker     return mState.getImageDesc(target, level).getMemorySize();
1309*8975f5c5SAndroid Build Coastguard Worker }
1310*8975f5c5SAndroid Build Coastguard Worker 
signalDirtyStorage(InitState initState)1311*8975f5c5SAndroid Build Coastguard Worker void Texture::signalDirtyStorage(InitState initState)
1312*8975f5c5SAndroid Build Coastguard Worker {
1313*8975f5c5SAndroid Build Coastguard Worker     mState.mInitState = initState;
1314*8975f5c5SAndroid Build Coastguard Worker     invalidateCompletenessCache();
1315*8975f5c5SAndroid Build Coastguard Worker     mState.mCachedSamplerFormatValid = false;
1316*8975f5c5SAndroid Build Coastguard Worker     onStateChange(angle::SubjectMessage::SubjectChanged);
1317*8975f5c5SAndroid Build Coastguard Worker }
1318*8975f5c5SAndroid Build Coastguard Worker 
signalDirtyState(size_t dirtyBit)1319*8975f5c5SAndroid Build Coastguard Worker void Texture::signalDirtyState(size_t dirtyBit)
1320*8975f5c5SAndroid Build Coastguard Worker {
1321*8975f5c5SAndroid Build Coastguard Worker     mDirtyBits.set(dirtyBit);
1322*8975f5c5SAndroid Build Coastguard Worker     invalidateCompletenessCache();
1323*8975f5c5SAndroid Build Coastguard Worker     mState.mCachedSamplerFormatValid = false;
1324*8975f5c5SAndroid Build Coastguard Worker 
1325*8975f5c5SAndroid Build Coastguard Worker     if (dirtyBit == DIRTY_BIT_BASE_LEVEL || dirtyBit == DIRTY_BIT_MAX_LEVEL)
1326*8975f5c5SAndroid Build Coastguard Worker     {
1327*8975f5c5SAndroid Build Coastguard Worker         onStateChange(angle::SubjectMessage::SubjectChanged);
1328*8975f5c5SAndroid Build Coastguard Worker     }
1329*8975f5c5SAndroid Build Coastguard Worker     else
1330*8975f5c5SAndroid Build Coastguard Worker     {
1331*8975f5c5SAndroid Build Coastguard Worker         onStateChange(angle::SubjectMessage::DirtyBitsFlagged);
1332*8975f5c5SAndroid Build Coastguard Worker     }
1333*8975f5c5SAndroid Build Coastguard Worker }
1334*8975f5c5SAndroid Build Coastguard Worker 
setImage(Context * context,const PixelUnpackState & unpackState,Buffer * unpackBuffer,TextureTarget target,GLint level,GLenum internalFormat,const Extents & size,GLenum format,GLenum type,const uint8_t * pixels)1335*8975f5c5SAndroid Build Coastguard Worker angle::Result Texture::setImage(Context *context,
1336*8975f5c5SAndroid Build Coastguard Worker                                 const PixelUnpackState &unpackState,
1337*8975f5c5SAndroid Build Coastguard Worker                                 Buffer *unpackBuffer,
1338*8975f5c5SAndroid Build Coastguard Worker                                 TextureTarget target,
1339*8975f5c5SAndroid Build Coastguard Worker                                 GLint level,
1340*8975f5c5SAndroid Build Coastguard Worker                                 GLenum internalFormat,
1341*8975f5c5SAndroid Build Coastguard Worker                                 const Extents &size,
1342*8975f5c5SAndroid Build Coastguard Worker                                 GLenum format,
1343*8975f5c5SAndroid Build Coastguard Worker                                 GLenum type,
1344*8975f5c5SAndroid Build Coastguard Worker                                 const uint8_t *pixels)
1345*8975f5c5SAndroid Build Coastguard Worker {
1346*8975f5c5SAndroid Build Coastguard Worker     ASSERT(TextureTargetToType(target) == mState.mType);
1347*8975f5c5SAndroid Build Coastguard Worker 
1348*8975f5c5SAndroid Build Coastguard Worker     // Release from previous calls to eglBindTexImage, to avoid calling the Impl after
1349*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(releaseTexImageInternal(context));
1350*8975f5c5SAndroid Build Coastguard Worker 
1351*8975f5c5SAndroid Build Coastguard Worker     egl::RefCountObjectReleaser<egl::Image> releaseImage;
1352*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(orphanImages(context, &releaseImage));
1353*8975f5c5SAndroid Build Coastguard Worker 
1354*8975f5c5SAndroid Build Coastguard Worker     ImageIndex index = ImageIndex::MakeFromTarget(target, level, size.depth);
1355*8975f5c5SAndroid Build Coastguard Worker 
1356*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(mTexture->setImage(context, index, internalFormat, size, format, type, unpackState,
1357*8975f5c5SAndroid Build Coastguard Worker                                  unpackBuffer, pixels));
1358*8975f5c5SAndroid Build Coastguard Worker 
1359*8975f5c5SAndroid Build Coastguard Worker     InitState initState = DetermineInitState(context, unpackBuffer, pixels);
1360*8975f5c5SAndroid Build Coastguard Worker     mState.setImageDesc(target, level, ImageDesc(size, Format(internalFormat, type), initState));
1361*8975f5c5SAndroid Build Coastguard Worker 
1362*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(handleMipmapGenerationHint(context, level));
1363*8975f5c5SAndroid Build Coastguard Worker 
1364*8975f5c5SAndroid Build Coastguard Worker     signalDirtyStorage(initState);
1365*8975f5c5SAndroid Build Coastguard Worker 
1366*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
1367*8975f5c5SAndroid Build Coastguard Worker }
1368*8975f5c5SAndroid Build Coastguard Worker 
setSubImage(Context * context,const PixelUnpackState & unpackState,Buffer * unpackBuffer,TextureTarget target,GLint level,const Box & area,GLenum format,GLenum type,const uint8_t * pixels)1369*8975f5c5SAndroid Build Coastguard Worker angle::Result Texture::setSubImage(Context *context,
1370*8975f5c5SAndroid Build Coastguard Worker                                    const PixelUnpackState &unpackState,
1371*8975f5c5SAndroid Build Coastguard Worker                                    Buffer *unpackBuffer,
1372*8975f5c5SAndroid Build Coastguard Worker                                    TextureTarget target,
1373*8975f5c5SAndroid Build Coastguard Worker                                    GLint level,
1374*8975f5c5SAndroid Build Coastguard Worker                                    const Box &area,
1375*8975f5c5SAndroid Build Coastguard Worker                                    GLenum format,
1376*8975f5c5SAndroid Build Coastguard Worker                                    GLenum type,
1377*8975f5c5SAndroid Build Coastguard Worker                                    const uint8_t *pixels)
1378*8975f5c5SAndroid Build Coastguard Worker {
1379*8975f5c5SAndroid Build Coastguard Worker     ASSERT(TextureTargetToType(target) == mState.mType);
1380*8975f5c5SAndroid Build Coastguard Worker 
1381*8975f5c5SAndroid Build Coastguard Worker     ImageIndex index = ImageIndex::MakeFromTarget(target, level, area.depth);
1382*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(ensureSubImageInitialized(context, index, area));
1383*8975f5c5SAndroid Build Coastguard Worker 
1384*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(mTexture->setSubImage(context, index, area, format, type, unpackState, unpackBuffer,
1385*8975f5c5SAndroid Build Coastguard Worker                                     pixels));
1386*8975f5c5SAndroid Build Coastguard Worker 
1387*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(handleMipmapGenerationHint(context, level));
1388*8975f5c5SAndroid Build Coastguard Worker 
1389*8975f5c5SAndroid Build Coastguard Worker     onStateChange(angle::SubjectMessage::ContentsChanged);
1390*8975f5c5SAndroid Build Coastguard Worker 
1391*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
1392*8975f5c5SAndroid Build Coastguard Worker }
1393*8975f5c5SAndroid Build Coastguard Worker 
setCompressedImage(Context * context,const PixelUnpackState & unpackState,TextureTarget target,GLint level,GLenum internalFormat,const Extents & size,size_t imageSize,const uint8_t * pixels)1394*8975f5c5SAndroid Build Coastguard Worker angle::Result Texture::setCompressedImage(Context *context,
1395*8975f5c5SAndroid Build Coastguard Worker                                           const PixelUnpackState &unpackState,
1396*8975f5c5SAndroid Build Coastguard Worker                                           TextureTarget target,
1397*8975f5c5SAndroid Build Coastguard Worker                                           GLint level,
1398*8975f5c5SAndroid Build Coastguard Worker                                           GLenum internalFormat,
1399*8975f5c5SAndroid Build Coastguard Worker                                           const Extents &size,
1400*8975f5c5SAndroid Build Coastguard Worker                                           size_t imageSize,
1401*8975f5c5SAndroid Build Coastguard Worker                                           const uint8_t *pixels)
1402*8975f5c5SAndroid Build Coastguard Worker {
1403*8975f5c5SAndroid Build Coastguard Worker     ASSERT(TextureTargetToType(target) == mState.mType);
1404*8975f5c5SAndroid Build Coastguard Worker 
1405*8975f5c5SAndroid Build Coastguard Worker     // Release from previous calls to eglBindTexImage, to avoid calling the Impl after
1406*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(releaseTexImageInternal(context));
1407*8975f5c5SAndroid Build Coastguard Worker 
1408*8975f5c5SAndroid Build Coastguard Worker     egl::RefCountObjectReleaser<egl::Image> releaseImage;
1409*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(orphanImages(context, &releaseImage));
1410*8975f5c5SAndroid Build Coastguard Worker 
1411*8975f5c5SAndroid Build Coastguard Worker     ImageIndex index = ImageIndex::MakeFromTarget(target, level, size.depth);
1412*8975f5c5SAndroid Build Coastguard Worker 
1413*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(mTexture->setCompressedImage(context, index, internalFormat, size, unpackState,
1414*8975f5c5SAndroid Build Coastguard Worker                                            imageSize, pixels));
1415*8975f5c5SAndroid Build Coastguard Worker 
1416*8975f5c5SAndroid Build Coastguard Worker     Buffer *unpackBuffer = context->getState().getTargetBuffer(BufferBinding::PixelUnpack);
1417*8975f5c5SAndroid Build Coastguard Worker 
1418*8975f5c5SAndroid Build Coastguard Worker     InitState initState = DetermineInitState(context, unpackBuffer, pixels);
1419*8975f5c5SAndroid Build Coastguard Worker     mState.setImageDesc(target, level, ImageDesc(size, Format(internalFormat), initState));
1420*8975f5c5SAndroid Build Coastguard Worker     signalDirtyStorage(initState);
1421*8975f5c5SAndroid Build Coastguard Worker 
1422*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
1423*8975f5c5SAndroid Build Coastguard Worker }
1424*8975f5c5SAndroid Build Coastguard Worker 
setCompressedSubImage(const Context * context,const PixelUnpackState & unpackState,TextureTarget target,GLint level,const Box & area,GLenum format,size_t imageSize,const uint8_t * pixels)1425*8975f5c5SAndroid Build Coastguard Worker angle::Result Texture::setCompressedSubImage(const Context *context,
1426*8975f5c5SAndroid Build Coastguard Worker                                              const PixelUnpackState &unpackState,
1427*8975f5c5SAndroid Build Coastguard Worker                                              TextureTarget target,
1428*8975f5c5SAndroid Build Coastguard Worker                                              GLint level,
1429*8975f5c5SAndroid Build Coastguard Worker                                              const Box &area,
1430*8975f5c5SAndroid Build Coastguard Worker                                              GLenum format,
1431*8975f5c5SAndroid Build Coastguard Worker                                              size_t imageSize,
1432*8975f5c5SAndroid Build Coastguard Worker                                              const uint8_t *pixels)
1433*8975f5c5SAndroid Build Coastguard Worker {
1434*8975f5c5SAndroid Build Coastguard Worker     ASSERT(TextureTargetToType(target) == mState.mType);
1435*8975f5c5SAndroid Build Coastguard Worker 
1436*8975f5c5SAndroid Build Coastguard Worker     ImageIndex index = ImageIndex::MakeFromTarget(target, level, area.depth);
1437*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(ensureSubImageInitialized(context, index, area));
1438*8975f5c5SAndroid Build Coastguard Worker 
1439*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(mTexture->setCompressedSubImage(context, index, area, format, unpackState, imageSize,
1440*8975f5c5SAndroid Build Coastguard Worker                                               pixels));
1441*8975f5c5SAndroid Build Coastguard Worker 
1442*8975f5c5SAndroid Build Coastguard Worker     onStateChange(angle::SubjectMessage::ContentsChanged);
1443*8975f5c5SAndroid Build Coastguard Worker 
1444*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
1445*8975f5c5SAndroid Build Coastguard Worker }
1446*8975f5c5SAndroid Build Coastguard Worker 
copyImage(Context * context,TextureTarget target,GLint level,const Rectangle & sourceArea,GLenum internalFormat,Framebuffer * source)1447*8975f5c5SAndroid Build Coastguard Worker angle::Result Texture::copyImage(Context *context,
1448*8975f5c5SAndroid Build Coastguard Worker                                  TextureTarget target,
1449*8975f5c5SAndroid Build Coastguard Worker                                  GLint level,
1450*8975f5c5SAndroid Build Coastguard Worker                                  const Rectangle &sourceArea,
1451*8975f5c5SAndroid Build Coastguard Worker                                  GLenum internalFormat,
1452*8975f5c5SAndroid Build Coastguard Worker                                  Framebuffer *source)
1453*8975f5c5SAndroid Build Coastguard Worker {
1454*8975f5c5SAndroid Build Coastguard Worker     ASSERT(TextureTargetToType(target) == mState.mType);
1455*8975f5c5SAndroid Build Coastguard Worker 
1456*8975f5c5SAndroid Build Coastguard Worker     // Release from previous calls to eglBindTexImage, to avoid calling the Impl after
1457*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(releaseTexImageInternal(context));
1458*8975f5c5SAndroid Build Coastguard Worker 
1459*8975f5c5SAndroid Build Coastguard Worker     egl::RefCountObjectReleaser<egl::Image> releaseImage;
1460*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(orphanImages(context, &releaseImage));
1461*8975f5c5SAndroid Build Coastguard Worker 
1462*8975f5c5SAndroid Build Coastguard Worker     ImageIndex index = ImageIndex::MakeFromTarget(target, level, 1);
1463*8975f5c5SAndroid Build Coastguard Worker 
1464*8975f5c5SAndroid Build Coastguard Worker     const InternalFormat &internalFormatInfo =
1465*8975f5c5SAndroid Build Coastguard Worker         GetInternalFormatInfo(internalFormat, GL_UNSIGNED_BYTE);
1466*8975f5c5SAndroid Build Coastguard Worker 
1467*8975f5c5SAndroid Build Coastguard Worker     // Most if not all renderers clip these copies to the size of the source framebuffer, leaving
1468*8975f5c5SAndroid Build Coastguard Worker     // other pixels untouched. For safety in robust resource initialization, assume that that
1469*8975f5c5SAndroid Build Coastguard Worker     // clipping is going to occur when computing the region for which to ensure initialization. If
1470*8975f5c5SAndroid Build Coastguard Worker     // the copy lies entirely off the source framebuffer, initialize as though a zero-size box is
1471*8975f5c5SAndroid Build Coastguard Worker     // going to be set during the copy operation.
1472*8975f5c5SAndroid Build Coastguard Worker     Box destBox;
1473*8975f5c5SAndroid Build Coastguard Worker     bool forceCopySubImage = false;
1474*8975f5c5SAndroid Build Coastguard Worker     if (context->isRobustResourceInitEnabled())
1475*8975f5c5SAndroid Build Coastguard Worker     {
1476*8975f5c5SAndroid Build Coastguard Worker         const FramebufferAttachment *sourceReadAttachment = source->getReadColorAttachment();
1477*8975f5c5SAndroid Build Coastguard Worker         Extents fbSize                                    = sourceReadAttachment->getSize();
1478*8975f5c5SAndroid Build Coastguard Worker         // Force using copySubImage when the source area is out of bounds AND
1479*8975f5c5SAndroid Build Coastguard Worker         // we're not copying to and from the same texture
1480*8975f5c5SAndroid Build Coastguard Worker         forceCopySubImage = ((sourceArea.x < 0) || (sourceArea.y < 0) ||
1481*8975f5c5SAndroid Build Coastguard Worker                              ((sourceArea.x + sourceArea.width) > fbSize.width) ||
1482*8975f5c5SAndroid Build Coastguard Worker                              ((sourceArea.y + sourceArea.height) > fbSize.height)) &&
1483*8975f5c5SAndroid Build Coastguard Worker                             (sourceReadAttachment->getResource() != this);
1484*8975f5c5SAndroid Build Coastguard Worker         Rectangle clippedArea;
1485*8975f5c5SAndroid Build Coastguard Worker         if (ClipRectangle(sourceArea, Rectangle(0, 0, fbSize.width, fbSize.height), &clippedArea))
1486*8975f5c5SAndroid Build Coastguard Worker         {
1487*8975f5c5SAndroid Build Coastguard Worker             const Offset clippedOffset(clippedArea.x - sourceArea.x, clippedArea.y - sourceArea.y,
1488*8975f5c5SAndroid Build Coastguard Worker                                        0);
1489*8975f5c5SAndroid Build Coastguard Worker             destBox = Box(clippedOffset.x, clippedOffset.y, clippedOffset.z, clippedArea.width,
1490*8975f5c5SAndroid Build Coastguard Worker                           clippedArea.height, 1);
1491*8975f5c5SAndroid Build Coastguard Worker         }
1492*8975f5c5SAndroid Build Coastguard Worker     }
1493*8975f5c5SAndroid Build Coastguard Worker 
1494*8975f5c5SAndroid Build Coastguard Worker     InitState initState = DetermineInitState(context, nullptr, nullptr);
1495*8975f5c5SAndroid Build Coastguard Worker 
1496*8975f5c5SAndroid Build Coastguard Worker     // If we need to initialize the destination texture we split the call into a create call,
1497*8975f5c5SAndroid Build Coastguard Worker     // an initializeContents call, and then a copySubImage call. This ensures the destination
1498*8975f5c5SAndroid Build Coastguard Worker     // texture exists before we try to clear it.
1499*8975f5c5SAndroid Build Coastguard Worker     Extents size(sourceArea.width, sourceArea.height, 1);
1500*8975f5c5SAndroid Build Coastguard Worker     if (forceCopySubImage || doesSubImageNeedInit(context, index, destBox))
1501*8975f5c5SAndroid Build Coastguard Worker     {
1502*8975f5c5SAndroid Build Coastguard Worker         ANGLE_TRY(mTexture->setImage(context, index, internalFormat, size,
1503*8975f5c5SAndroid Build Coastguard Worker                                      internalFormatInfo.format, internalFormatInfo.type,
1504*8975f5c5SAndroid Build Coastguard Worker                                      PixelUnpackState(), nullptr, nullptr));
1505*8975f5c5SAndroid Build Coastguard Worker         mState.setImageDesc(target, level, ImageDesc(size, Format(internalFormatInfo), initState));
1506*8975f5c5SAndroid Build Coastguard Worker         ANGLE_TRY(ensureSubImageInitialized(context, index, destBox));
1507*8975f5c5SAndroid Build Coastguard Worker         ANGLE_TRY(mTexture->copySubImage(context, index, Offset(), sourceArea, source));
1508*8975f5c5SAndroid Build Coastguard Worker     }
1509*8975f5c5SAndroid Build Coastguard Worker     else
1510*8975f5c5SAndroid Build Coastguard Worker     {
1511*8975f5c5SAndroid Build Coastguard Worker         ANGLE_TRY(mTexture->copyImage(context, index, sourceArea, internalFormat, source));
1512*8975f5c5SAndroid Build Coastguard Worker     }
1513*8975f5c5SAndroid Build Coastguard Worker 
1514*8975f5c5SAndroid Build Coastguard Worker     mState.setImageDesc(target, level,
1515*8975f5c5SAndroid Build Coastguard Worker                         ImageDesc(size, Format(internalFormatInfo), InitState::Initialized));
1516*8975f5c5SAndroid Build Coastguard Worker 
1517*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(handleMipmapGenerationHint(context, level));
1518*8975f5c5SAndroid Build Coastguard Worker 
1519*8975f5c5SAndroid Build Coastguard Worker     // Because this could affect the texture storage we might need to init other layers/levels.
1520*8975f5c5SAndroid Build Coastguard Worker     signalDirtyStorage(initState);
1521*8975f5c5SAndroid Build Coastguard Worker 
1522*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
1523*8975f5c5SAndroid Build Coastguard Worker }
1524*8975f5c5SAndroid Build Coastguard Worker 
copySubImage(Context * context,const ImageIndex & index,const Offset & destOffset,const Rectangle & sourceArea,Framebuffer * source)1525*8975f5c5SAndroid Build Coastguard Worker angle::Result Texture::copySubImage(Context *context,
1526*8975f5c5SAndroid Build Coastguard Worker                                     const ImageIndex &index,
1527*8975f5c5SAndroid Build Coastguard Worker                                     const Offset &destOffset,
1528*8975f5c5SAndroid Build Coastguard Worker                                     const Rectangle &sourceArea,
1529*8975f5c5SAndroid Build Coastguard Worker                                     Framebuffer *source)
1530*8975f5c5SAndroid Build Coastguard Worker {
1531*8975f5c5SAndroid Build Coastguard Worker     ASSERT(TextureTargetToType(index.getTarget()) == mState.mType);
1532*8975f5c5SAndroid Build Coastguard Worker 
1533*8975f5c5SAndroid Build Coastguard Worker     // Most if not all renderers clip these copies to the size of the source framebuffer, leaving
1534*8975f5c5SAndroid Build Coastguard Worker     // other pixels untouched. For safety in robust resource initialization, assume that that
1535*8975f5c5SAndroid Build Coastguard Worker     // clipping is going to occur when computing the region for which to ensure initialization. If
1536*8975f5c5SAndroid Build Coastguard Worker     // the copy lies entirely off the source framebuffer, initialize as though a zero-size box is
1537*8975f5c5SAndroid Build Coastguard Worker     // going to be set during the copy operation. Note that this assumes that
1538*8975f5c5SAndroid Build Coastguard Worker     // ensureSubImageInitialized ensures initialization of the entire destination texture, and not
1539*8975f5c5SAndroid Build Coastguard Worker     // just a sub-region.
1540*8975f5c5SAndroid Build Coastguard Worker     Box destBox;
1541*8975f5c5SAndroid Build Coastguard Worker     if (context->isRobustResourceInitEnabled())
1542*8975f5c5SAndroid Build Coastguard Worker     {
1543*8975f5c5SAndroid Build Coastguard Worker         Extents fbSize = source->getReadColorAttachment()->getSize();
1544*8975f5c5SAndroid Build Coastguard Worker         Rectangle clippedArea;
1545*8975f5c5SAndroid Build Coastguard Worker         if (ClipRectangle(sourceArea, Rectangle(0, 0, fbSize.width, fbSize.height), &clippedArea))
1546*8975f5c5SAndroid Build Coastguard Worker         {
1547*8975f5c5SAndroid Build Coastguard Worker             const Offset clippedOffset(destOffset.x + clippedArea.x - sourceArea.x,
1548*8975f5c5SAndroid Build Coastguard Worker                                        destOffset.y + clippedArea.y - sourceArea.y, 0);
1549*8975f5c5SAndroid Build Coastguard Worker             destBox = Box(clippedOffset.x, clippedOffset.y, clippedOffset.z, clippedArea.width,
1550*8975f5c5SAndroid Build Coastguard Worker                           clippedArea.height, 1);
1551*8975f5c5SAndroid Build Coastguard Worker         }
1552*8975f5c5SAndroid Build Coastguard Worker     }
1553*8975f5c5SAndroid Build Coastguard Worker 
1554*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(ensureSubImageInitialized(context, index, destBox));
1555*8975f5c5SAndroid Build Coastguard Worker 
1556*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(mTexture->copySubImage(context, index, destOffset, sourceArea, source));
1557*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(handleMipmapGenerationHint(context, index.getLevelIndex()));
1558*8975f5c5SAndroid Build Coastguard Worker 
1559*8975f5c5SAndroid Build Coastguard Worker     onStateChange(angle::SubjectMessage::ContentsChanged);
1560*8975f5c5SAndroid Build Coastguard Worker 
1561*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
1562*8975f5c5SAndroid Build Coastguard Worker }
1563*8975f5c5SAndroid Build Coastguard Worker 
copyRenderbufferSubData(Context * context,const gl::Renderbuffer * srcBuffer,GLint srcLevel,GLint srcX,GLint srcY,GLint srcZ,GLint dstLevel,GLint dstX,GLint dstY,GLint dstZ,GLsizei srcWidth,GLsizei srcHeight,GLsizei srcDepth)1564*8975f5c5SAndroid Build Coastguard Worker angle::Result Texture::copyRenderbufferSubData(Context *context,
1565*8975f5c5SAndroid Build Coastguard Worker                                                const gl::Renderbuffer *srcBuffer,
1566*8975f5c5SAndroid Build Coastguard Worker                                                GLint srcLevel,
1567*8975f5c5SAndroid Build Coastguard Worker                                                GLint srcX,
1568*8975f5c5SAndroid Build Coastguard Worker                                                GLint srcY,
1569*8975f5c5SAndroid Build Coastguard Worker                                                GLint srcZ,
1570*8975f5c5SAndroid Build Coastguard Worker                                                GLint dstLevel,
1571*8975f5c5SAndroid Build Coastguard Worker                                                GLint dstX,
1572*8975f5c5SAndroid Build Coastguard Worker                                                GLint dstY,
1573*8975f5c5SAndroid Build Coastguard Worker                                                GLint dstZ,
1574*8975f5c5SAndroid Build Coastguard Worker                                                GLsizei srcWidth,
1575*8975f5c5SAndroid Build Coastguard Worker                                                GLsizei srcHeight,
1576*8975f5c5SAndroid Build Coastguard Worker                                                GLsizei srcDepth)
1577*8975f5c5SAndroid Build Coastguard Worker {
1578*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(mTexture->copyRenderbufferSubData(context, srcBuffer, srcLevel, srcX, srcY, srcZ,
1579*8975f5c5SAndroid Build Coastguard Worker                                                 dstLevel, dstX, dstY, dstZ, srcWidth, srcHeight,
1580*8975f5c5SAndroid Build Coastguard Worker                                                 srcDepth));
1581*8975f5c5SAndroid Build Coastguard Worker 
1582*8975f5c5SAndroid Build Coastguard Worker     signalDirtyStorage(InitState::Initialized);
1583*8975f5c5SAndroid Build Coastguard Worker 
1584*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
1585*8975f5c5SAndroid Build Coastguard Worker }
1586*8975f5c5SAndroid Build Coastguard Worker 
copyTextureSubData(Context * context,const gl::Texture * srcTexture,GLint srcLevel,GLint srcX,GLint srcY,GLint srcZ,GLint dstLevel,GLint dstX,GLint dstY,GLint dstZ,GLsizei srcWidth,GLsizei srcHeight,GLsizei srcDepth)1587*8975f5c5SAndroid Build Coastguard Worker angle::Result Texture::copyTextureSubData(Context *context,
1588*8975f5c5SAndroid Build Coastguard Worker                                           const gl::Texture *srcTexture,
1589*8975f5c5SAndroid Build Coastguard Worker                                           GLint srcLevel,
1590*8975f5c5SAndroid Build Coastguard Worker                                           GLint srcX,
1591*8975f5c5SAndroid Build Coastguard Worker                                           GLint srcY,
1592*8975f5c5SAndroid Build Coastguard Worker                                           GLint srcZ,
1593*8975f5c5SAndroid Build Coastguard Worker                                           GLint dstLevel,
1594*8975f5c5SAndroid Build Coastguard Worker                                           GLint dstX,
1595*8975f5c5SAndroid Build Coastguard Worker                                           GLint dstY,
1596*8975f5c5SAndroid Build Coastguard Worker                                           GLint dstZ,
1597*8975f5c5SAndroid Build Coastguard Worker                                           GLsizei srcWidth,
1598*8975f5c5SAndroid Build Coastguard Worker                                           GLsizei srcHeight,
1599*8975f5c5SAndroid Build Coastguard Worker                                           GLsizei srcDepth)
1600*8975f5c5SAndroid Build Coastguard Worker {
1601*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(mTexture->copyTextureSubData(context, srcTexture, srcLevel, srcX, srcY, srcZ,
1602*8975f5c5SAndroid Build Coastguard Worker                                            dstLevel, dstX, dstY, dstZ, srcWidth, srcHeight,
1603*8975f5c5SAndroid Build Coastguard Worker                                            srcDepth));
1604*8975f5c5SAndroid Build Coastguard Worker 
1605*8975f5c5SAndroid Build Coastguard Worker     signalDirtyStorage(InitState::Initialized);
1606*8975f5c5SAndroid Build Coastguard Worker 
1607*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
1608*8975f5c5SAndroid Build Coastguard Worker }
1609*8975f5c5SAndroid Build Coastguard Worker 
copyTexture(Context * context,TextureTarget target,GLint level,GLenum internalFormat,GLenum type,GLint sourceLevel,bool unpackFlipY,bool unpackPremultiplyAlpha,bool unpackUnmultiplyAlpha,Texture * source)1610*8975f5c5SAndroid Build Coastguard Worker angle::Result Texture::copyTexture(Context *context,
1611*8975f5c5SAndroid Build Coastguard Worker                                    TextureTarget target,
1612*8975f5c5SAndroid Build Coastguard Worker                                    GLint level,
1613*8975f5c5SAndroid Build Coastguard Worker                                    GLenum internalFormat,
1614*8975f5c5SAndroid Build Coastguard Worker                                    GLenum type,
1615*8975f5c5SAndroid Build Coastguard Worker                                    GLint sourceLevel,
1616*8975f5c5SAndroid Build Coastguard Worker                                    bool unpackFlipY,
1617*8975f5c5SAndroid Build Coastguard Worker                                    bool unpackPremultiplyAlpha,
1618*8975f5c5SAndroid Build Coastguard Worker                                    bool unpackUnmultiplyAlpha,
1619*8975f5c5SAndroid Build Coastguard Worker                                    Texture *source)
1620*8975f5c5SAndroid Build Coastguard Worker {
1621*8975f5c5SAndroid Build Coastguard Worker     ASSERT(TextureTargetToType(target) == mState.mType);
1622*8975f5c5SAndroid Build Coastguard Worker     ASSERT(source->getType() != TextureType::CubeMap);
1623*8975f5c5SAndroid Build Coastguard Worker 
1624*8975f5c5SAndroid Build Coastguard Worker     // Release from previous calls to eglBindTexImage, to avoid calling the Impl after
1625*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(releaseTexImageInternal(context));
1626*8975f5c5SAndroid Build Coastguard Worker 
1627*8975f5c5SAndroid Build Coastguard Worker     egl::RefCountObjectReleaser<egl::Image> releaseImage;
1628*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(orphanImages(context, &releaseImage));
1629*8975f5c5SAndroid Build Coastguard Worker 
1630*8975f5c5SAndroid Build Coastguard Worker     // Initialize source texture.
1631*8975f5c5SAndroid Build Coastguard Worker     // Note: we don't have a way to notify which portions of the image changed currently.
1632*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(source->ensureInitialized(context));
1633*8975f5c5SAndroid Build Coastguard Worker 
1634*8975f5c5SAndroid Build Coastguard Worker     ImageIndex index = ImageIndex::MakeFromTarget(target, level, ImageIndex::kEntireLevel);
1635*8975f5c5SAndroid Build Coastguard Worker 
1636*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(mTexture->copyTexture(context, index, internalFormat, type, sourceLevel, unpackFlipY,
1637*8975f5c5SAndroid Build Coastguard Worker                                     unpackPremultiplyAlpha, unpackUnmultiplyAlpha, source));
1638*8975f5c5SAndroid Build Coastguard Worker 
1639*8975f5c5SAndroid Build Coastguard Worker     const auto &sourceDesc =
1640*8975f5c5SAndroid Build Coastguard Worker         source->mState.getImageDesc(NonCubeTextureTypeToTarget(source->getType()), sourceLevel);
1641*8975f5c5SAndroid Build Coastguard Worker     const InternalFormat &internalFormatInfo = GetInternalFormatInfo(internalFormat, type);
1642*8975f5c5SAndroid Build Coastguard Worker     mState.setImageDesc(
1643*8975f5c5SAndroid Build Coastguard Worker         target, level,
1644*8975f5c5SAndroid Build Coastguard Worker         ImageDesc(sourceDesc.size, Format(internalFormatInfo), InitState::Initialized));
1645*8975f5c5SAndroid Build Coastguard Worker 
1646*8975f5c5SAndroid Build Coastguard Worker     signalDirtyStorage(InitState::Initialized);
1647*8975f5c5SAndroid Build Coastguard Worker 
1648*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
1649*8975f5c5SAndroid Build Coastguard Worker }
1650*8975f5c5SAndroid Build Coastguard Worker 
copySubTexture(const Context * context,TextureTarget target,GLint level,const Offset & destOffset,GLint sourceLevel,const Box & sourceBox,bool unpackFlipY,bool unpackPremultiplyAlpha,bool unpackUnmultiplyAlpha,Texture * source)1651*8975f5c5SAndroid Build Coastguard Worker angle::Result Texture::copySubTexture(const Context *context,
1652*8975f5c5SAndroid Build Coastguard Worker                                       TextureTarget target,
1653*8975f5c5SAndroid Build Coastguard Worker                                       GLint level,
1654*8975f5c5SAndroid Build Coastguard Worker                                       const Offset &destOffset,
1655*8975f5c5SAndroid Build Coastguard Worker                                       GLint sourceLevel,
1656*8975f5c5SAndroid Build Coastguard Worker                                       const Box &sourceBox,
1657*8975f5c5SAndroid Build Coastguard Worker                                       bool unpackFlipY,
1658*8975f5c5SAndroid Build Coastguard Worker                                       bool unpackPremultiplyAlpha,
1659*8975f5c5SAndroid Build Coastguard Worker                                       bool unpackUnmultiplyAlpha,
1660*8975f5c5SAndroid Build Coastguard Worker                                       Texture *source)
1661*8975f5c5SAndroid Build Coastguard Worker {
1662*8975f5c5SAndroid Build Coastguard Worker     ASSERT(TextureTargetToType(target) == mState.mType);
1663*8975f5c5SAndroid Build Coastguard Worker 
1664*8975f5c5SAndroid Build Coastguard Worker     // Ensure source is initialized.
1665*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(source->ensureInitialized(context));
1666*8975f5c5SAndroid Build Coastguard Worker 
1667*8975f5c5SAndroid Build Coastguard Worker     Box destBox(destOffset.x, destOffset.y, destOffset.z, sourceBox.width, sourceBox.height,
1668*8975f5c5SAndroid Build Coastguard Worker                 sourceBox.depth);
1669*8975f5c5SAndroid Build Coastguard Worker     ImageIndex index = ImageIndex::MakeFromTarget(target, level, sourceBox.depth);
1670*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(ensureSubImageInitialized(context, index, destBox));
1671*8975f5c5SAndroid Build Coastguard Worker 
1672*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(mTexture->copySubTexture(context, index, destOffset, sourceLevel, sourceBox,
1673*8975f5c5SAndroid Build Coastguard Worker                                        unpackFlipY, unpackPremultiplyAlpha, unpackUnmultiplyAlpha,
1674*8975f5c5SAndroid Build Coastguard Worker                                        source));
1675*8975f5c5SAndroid Build Coastguard Worker 
1676*8975f5c5SAndroid Build Coastguard Worker     onStateChange(angle::SubjectMessage::ContentsChanged);
1677*8975f5c5SAndroid Build Coastguard Worker 
1678*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
1679*8975f5c5SAndroid Build Coastguard Worker }
1680*8975f5c5SAndroid Build Coastguard Worker 
copyCompressedTexture(Context * context,const Texture * source)1681*8975f5c5SAndroid Build Coastguard Worker angle::Result Texture::copyCompressedTexture(Context *context, const Texture *source)
1682*8975f5c5SAndroid Build Coastguard Worker {
1683*8975f5c5SAndroid Build Coastguard Worker     // Release from previous calls to eglBindTexImage, to avoid calling the Impl after
1684*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(releaseTexImageInternal(context));
1685*8975f5c5SAndroid Build Coastguard Worker 
1686*8975f5c5SAndroid Build Coastguard Worker     egl::RefCountObjectReleaser<egl::Image> releaseImage;
1687*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(orphanImages(context, &releaseImage));
1688*8975f5c5SAndroid Build Coastguard Worker 
1689*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(mTexture->copyCompressedTexture(context, source));
1690*8975f5c5SAndroid Build Coastguard Worker 
1691*8975f5c5SAndroid Build Coastguard Worker     ASSERT(source->getType() != TextureType::CubeMap && getType() != TextureType::CubeMap);
1692*8975f5c5SAndroid Build Coastguard Worker     const auto &sourceDesc =
1693*8975f5c5SAndroid Build Coastguard Worker         source->mState.getImageDesc(NonCubeTextureTypeToTarget(source->getType()), 0);
1694*8975f5c5SAndroid Build Coastguard Worker     mState.setImageDesc(NonCubeTextureTypeToTarget(getType()), 0, sourceDesc);
1695*8975f5c5SAndroid Build Coastguard Worker 
1696*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
1697*8975f5c5SAndroid Build Coastguard Worker }
1698*8975f5c5SAndroid Build Coastguard Worker 
setStorage(Context * context,TextureType type,GLsizei levels,GLenum internalFormat,const Extents & size)1699*8975f5c5SAndroid Build Coastguard Worker angle::Result Texture::setStorage(Context *context,
1700*8975f5c5SAndroid Build Coastguard Worker                                   TextureType type,
1701*8975f5c5SAndroid Build Coastguard Worker                                   GLsizei levels,
1702*8975f5c5SAndroid Build Coastguard Worker                                   GLenum internalFormat,
1703*8975f5c5SAndroid Build Coastguard Worker                                   const Extents &size)
1704*8975f5c5SAndroid Build Coastguard Worker {
1705*8975f5c5SAndroid Build Coastguard Worker     ASSERT(type == mState.mType);
1706*8975f5c5SAndroid Build Coastguard Worker 
1707*8975f5c5SAndroid Build Coastguard Worker     // Release from previous calls to eglBindTexImage, to avoid calling the Impl after
1708*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(releaseTexImageInternal(context));
1709*8975f5c5SAndroid Build Coastguard Worker 
1710*8975f5c5SAndroid Build Coastguard Worker     egl::RefCountObjectReleaser<egl::Image> releaseImage;
1711*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(orphanImages(context, &releaseImage));
1712*8975f5c5SAndroid Build Coastguard Worker 
1713*8975f5c5SAndroid Build Coastguard Worker     mState.mImmutableFormat = true;
1714*8975f5c5SAndroid Build Coastguard Worker     mState.mImmutableLevels = static_cast<GLuint>(levels);
1715*8975f5c5SAndroid Build Coastguard Worker     mState.clearImageDescs();
1716*8975f5c5SAndroid Build Coastguard Worker     InitState initState = DetermineInitState(context, nullptr, nullptr);
1717*8975f5c5SAndroid Build Coastguard Worker     mState.setImageDescChain(0, static_cast<GLuint>(levels - 1), size, Format(internalFormat),
1718*8975f5c5SAndroid Build Coastguard Worker                              initState);
1719*8975f5c5SAndroid Build Coastguard Worker 
1720*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(mTexture->setStorage(context, type, levels, internalFormat, size));
1721*8975f5c5SAndroid Build Coastguard Worker 
1722*8975f5c5SAndroid Build Coastguard Worker     // Changing the texture to immutable can trigger a change in the base and max levels:
1723*8975f5c5SAndroid Build Coastguard Worker     // GLES 3.0.4 section 3.8.10 pg 158:
1724*8975f5c5SAndroid Build Coastguard Worker     // "For immutable-format textures, levelbase is clamped to the range[0;levels],levelmax is then
1725*8975f5c5SAndroid Build Coastguard Worker     // clamped to the range[levelbase;levels].
1726*8975f5c5SAndroid Build Coastguard Worker     mDirtyBits.set(DIRTY_BIT_BASE_LEVEL);
1727*8975f5c5SAndroid Build Coastguard Worker     mDirtyBits.set(DIRTY_BIT_MAX_LEVEL);
1728*8975f5c5SAndroid Build Coastguard Worker 
1729*8975f5c5SAndroid Build Coastguard Worker     signalDirtyStorage(initState);
1730*8975f5c5SAndroid Build Coastguard Worker 
1731*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
1732*8975f5c5SAndroid Build Coastguard Worker }
1733*8975f5c5SAndroid Build Coastguard Worker 
setImageExternal(Context * context,TextureTarget target,GLint level,GLenum internalFormat,const Extents & size,GLenum format,GLenum type)1734*8975f5c5SAndroid Build Coastguard Worker angle::Result Texture::setImageExternal(Context *context,
1735*8975f5c5SAndroid Build Coastguard Worker                                         TextureTarget target,
1736*8975f5c5SAndroid Build Coastguard Worker                                         GLint level,
1737*8975f5c5SAndroid Build Coastguard Worker                                         GLenum internalFormat,
1738*8975f5c5SAndroid Build Coastguard Worker                                         const Extents &size,
1739*8975f5c5SAndroid Build Coastguard Worker                                         GLenum format,
1740*8975f5c5SAndroid Build Coastguard Worker                                         GLenum type)
1741*8975f5c5SAndroid Build Coastguard Worker {
1742*8975f5c5SAndroid Build Coastguard Worker     ASSERT(TextureTargetToType(target) == mState.mType);
1743*8975f5c5SAndroid Build Coastguard Worker 
1744*8975f5c5SAndroid Build Coastguard Worker     // Release from previous calls to eglBindTexImage, to avoid calling the Impl after
1745*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(releaseTexImageInternal(context));
1746*8975f5c5SAndroid Build Coastguard Worker 
1747*8975f5c5SAndroid Build Coastguard Worker     egl::RefCountObjectReleaser<egl::Image> releaseImage;
1748*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(orphanImages(context, &releaseImage));
1749*8975f5c5SAndroid Build Coastguard Worker 
1750*8975f5c5SAndroid Build Coastguard Worker     ImageIndex index = ImageIndex::MakeFromTarget(target, level, size.depth);
1751*8975f5c5SAndroid Build Coastguard Worker 
1752*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(mTexture->setImageExternal(context, index, internalFormat, size, format, type));
1753*8975f5c5SAndroid Build Coastguard Worker 
1754*8975f5c5SAndroid Build Coastguard Worker     InitState initState = InitState::Initialized;
1755*8975f5c5SAndroid Build Coastguard Worker     mState.setImageDesc(target, level, ImageDesc(size, Format(internalFormat, type), initState));
1756*8975f5c5SAndroid Build Coastguard Worker 
1757*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(handleMipmapGenerationHint(context, level));
1758*8975f5c5SAndroid Build Coastguard Worker 
1759*8975f5c5SAndroid Build Coastguard Worker     signalDirtyStorage(initState);
1760*8975f5c5SAndroid Build Coastguard Worker 
1761*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
1762*8975f5c5SAndroid Build Coastguard Worker }
1763*8975f5c5SAndroid Build Coastguard Worker 
setStorageMultisample(Context * context,TextureType type,GLsizei samplesIn,GLint internalFormat,const Extents & size,bool fixedSampleLocations)1764*8975f5c5SAndroid Build Coastguard Worker angle::Result Texture::setStorageMultisample(Context *context,
1765*8975f5c5SAndroid Build Coastguard Worker                                              TextureType type,
1766*8975f5c5SAndroid Build Coastguard Worker                                              GLsizei samplesIn,
1767*8975f5c5SAndroid Build Coastguard Worker                                              GLint internalFormat,
1768*8975f5c5SAndroid Build Coastguard Worker                                              const Extents &size,
1769*8975f5c5SAndroid Build Coastguard Worker                                              bool fixedSampleLocations)
1770*8975f5c5SAndroid Build Coastguard Worker {
1771*8975f5c5SAndroid Build Coastguard Worker     ASSERT(type == mState.mType);
1772*8975f5c5SAndroid Build Coastguard Worker 
1773*8975f5c5SAndroid Build Coastguard Worker     // Release from previous calls to eglBindTexImage, to avoid calling the Impl after
1774*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(releaseTexImageInternal(context));
1775*8975f5c5SAndroid Build Coastguard Worker 
1776*8975f5c5SAndroid Build Coastguard Worker     egl::RefCountObjectReleaser<egl::Image> releaseImage;
1777*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(orphanImages(context, &releaseImage));
1778*8975f5c5SAndroid Build Coastguard Worker 
1779*8975f5c5SAndroid Build Coastguard Worker     // Potentially adjust "samples" to a supported value
1780*8975f5c5SAndroid Build Coastguard Worker     const TextureCaps &formatCaps = context->getTextureCaps().get(internalFormat);
1781*8975f5c5SAndroid Build Coastguard Worker     GLsizei samples               = formatCaps.getNearestSamples(samplesIn);
1782*8975f5c5SAndroid Build Coastguard Worker 
1783*8975f5c5SAndroid Build Coastguard Worker     mState.mImmutableFormat = true;
1784*8975f5c5SAndroid Build Coastguard Worker     mState.mImmutableLevels = static_cast<GLuint>(1);
1785*8975f5c5SAndroid Build Coastguard Worker     mState.clearImageDescs();
1786*8975f5c5SAndroid Build Coastguard Worker     InitState initState = DetermineInitState(context, nullptr, nullptr);
1787*8975f5c5SAndroid Build Coastguard Worker     mState.setImageDescChainMultisample(size, Format(internalFormat), samples, fixedSampleLocations,
1788*8975f5c5SAndroid Build Coastguard Worker                                         initState);
1789*8975f5c5SAndroid Build Coastguard Worker 
1790*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(mTexture->setStorageMultisample(context, type, samples, internalFormat, size,
1791*8975f5c5SAndroid Build Coastguard Worker                                               fixedSampleLocations));
1792*8975f5c5SAndroid Build Coastguard Worker     signalDirtyStorage(initState);
1793*8975f5c5SAndroid Build Coastguard Worker 
1794*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
1795*8975f5c5SAndroid Build Coastguard Worker }
1796*8975f5c5SAndroid Build Coastguard Worker 
setStorageExternalMemory(Context * context,TextureType type,GLsizei levels,GLenum internalFormat,const Extents & size,MemoryObject * memoryObject,GLuint64 offset,GLbitfield createFlags,GLbitfield usageFlags,const void * imageCreateInfoPNext)1797*8975f5c5SAndroid Build Coastguard Worker angle::Result Texture::setStorageExternalMemory(Context *context,
1798*8975f5c5SAndroid Build Coastguard Worker                                                 TextureType type,
1799*8975f5c5SAndroid Build Coastguard Worker                                                 GLsizei levels,
1800*8975f5c5SAndroid Build Coastguard Worker                                                 GLenum internalFormat,
1801*8975f5c5SAndroid Build Coastguard Worker                                                 const Extents &size,
1802*8975f5c5SAndroid Build Coastguard Worker                                                 MemoryObject *memoryObject,
1803*8975f5c5SAndroid Build Coastguard Worker                                                 GLuint64 offset,
1804*8975f5c5SAndroid Build Coastguard Worker                                                 GLbitfield createFlags,
1805*8975f5c5SAndroid Build Coastguard Worker                                                 GLbitfield usageFlags,
1806*8975f5c5SAndroid Build Coastguard Worker                                                 const void *imageCreateInfoPNext)
1807*8975f5c5SAndroid Build Coastguard Worker {
1808*8975f5c5SAndroid Build Coastguard Worker     ASSERT(type == mState.mType);
1809*8975f5c5SAndroid Build Coastguard Worker 
1810*8975f5c5SAndroid Build Coastguard Worker     // Release from previous calls to eglBindTexImage, to avoid calling the Impl after
1811*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(releaseTexImageInternal(context));
1812*8975f5c5SAndroid Build Coastguard Worker 
1813*8975f5c5SAndroid Build Coastguard Worker     egl::RefCountObjectReleaser<egl::Image> releaseImage;
1814*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(orphanImages(context, &releaseImage));
1815*8975f5c5SAndroid Build Coastguard Worker 
1816*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(mTexture->setStorageExternalMemory(context, type, levels, internalFormat, size,
1817*8975f5c5SAndroid Build Coastguard Worker                                                  memoryObject, offset, createFlags, usageFlags,
1818*8975f5c5SAndroid Build Coastguard Worker                                                  imageCreateInfoPNext));
1819*8975f5c5SAndroid Build Coastguard Worker 
1820*8975f5c5SAndroid Build Coastguard Worker     mState.mImmutableFormat = true;
1821*8975f5c5SAndroid Build Coastguard Worker     mState.mImmutableLevels = static_cast<GLuint>(levels);
1822*8975f5c5SAndroid Build Coastguard Worker     mState.clearImageDescs();
1823*8975f5c5SAndroid Build Coastguard Worker     mState.setImageDescChain(0, static_cast<GLuint>(levels - 1), size, Format(internalFormat),
1824*8975f5c5SAndroid Build Coastguard Worker                              InitState::Initialized);
1825*8975f5c5SAndroid Build Coastguard Worker 
1826*8975f5c5SAndroid Build Coastguard Worker     // Changing the texture to immutable can trigger a change in the base and max levels:
1827*8975f5c5SAndroid Build Coastguard Worker     // GLES 3.0.4 section 3.8.10 pg 158:
1828*8975f5c5SAndroid Build Coastguard Worker     // "For immutable-format textures, levelbase is clamped to the range[0;levels],levelmax is then
1829*8975f5c5SAndroid Build Coastguard Worker     // clamped to the range[levelbase;levels].
1830*8975f5c5SAndroid Build Coastguard Worker     mDirtyBits.set(DIRTY_BIT_BASE_LEVEL);
1831*8975f5c5SAndroid Build Coastguard Worker     mDirtyBits.set(DIRTY_BIT_MAX_LEVEL);
1832*8975f5c5SAndroid Build Coastguard Worker 
1833*8975f5c5SAndroid Build Coastguard Worker     signalDirtyStorage(InitState::Initialized);
1834*8975f5c5SAndroid Build Coastguard Worker 
1835*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
1836*8975f5c5SAndroid Build Coastguard Worker }
1837*8975f5c5SAndroid Build Coastguard Worker 
setStorageAttribs(Context * context,TextureType type,GLsizei levels,GLenum internalFormat,const Extents & size,const GLint * attribList)1838*8975f5c5SAndroid Build Coastguard Worker angle::Result Texture::setStorageAttribs(Context *context,
1839*8975f5c5SAndroid Build Coastguard Worker                                          TextureType type,
1840*8975f5c5SAndroid Build Coastguard Worker                                          GLsizei levels,
1841*8975f5c5SAndroid Build Coastguard Worker                                          GLenum internalFormat,
1842*8975f5c5SAndroid Build Coastguard Worker                                          const Extents &size,
1843*8975f5c5SAndroid Build Coastguard Worker                                          const GLint *attribList)
1844*8975f5c5SAndroid Build Coastguard Worker {
1845*8975f5c5SAndroid Build Coastguard Worker     ASSERT(type == mState.mType);
1846*8975f5c5SAndroid Build Coastguard Worker 
1847*8975f5c5SAndroid Build Coastguard Worker     // Release from previous calls to eglBindTexImage, to avoid calling the Impl after
1848*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(releaseTexImageInternal(context));
1849*8975f5c5SAndroid Build Coastguard Worker 
1850*8975f5c5SAndroid Build Coastguard Worker     egl::RefCountObjectReleaser<egl::Image> releaseImage;
1851*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(orphanImages(context, &releaseImage));
1852*8975f5c5SAndroid Build Coastguard Worker 
1853*8975f5c5SAndroid Build Coastguard Worker     mState.mImmutableFormat = true;
1854*8975f5c5SAndroid Build Coastguard Worker     mState.mImmutableLevels = static_cast<GLuint>(levels);
1855*8975f5c5SAndroid Build Coastguard Worker     mState.clearImageDescs();
1856*8975f5c5SAndroid Build Coastguard Worker     InitState initState = DetermineInitState(context, nullptr, nullptr);
1857*8975f5c5SAndroid Build Coastguard Worker     mState.setImageDescChain(0, static_cast<GLuint>(levels - 1), size, Format(internalFormat),
1858*8975f5c5SAndroid Build Coastguard Worker                              initState);
1859*8975f5c5SAndroid Build Coastguard Worker 
1860*8975f5c5SAndroid Build Coastguard Worker     if (nullptr != attribList && GL_SURFACE_COMPRESSION_EXT == *attribList)
1861*8975f5c5SAndroid Build Coastguard Worker     {
1862*8975f5c5SAndroid Build Coastguard Worker         attribList++;
1863*8975f5c5SAndroid Build Coastguard Worker         if (nullptr != attribList && GL_NONE != *attribList)
1864*8975f5c5SAndroid Build Coastguard Worker         {
1865*8975f5c5SAndroid Build Coastguard Worker             mState.mCompressionFixedRate = *attribList;
1866*8975f5c5SAndroid Build Coastguard Worker         }
1867*8975f5c5SAndroid Build Coastguard Worker     }
1868*8975f5c5SAndroid Build Coastguard Worker 
1869*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(mTexture->setStorageAttribs(context, type, levels, internalFormat, size, attribList));
1870*8975f5c5SAndroid Build Coastguard Worker 
1871*8975f5c5SAndroid Build Coastguard Worker     // Changing the texture to immutable can trigger a change in the base and max levels:
1872*8975f5c5SAndroid Build Coastguard Worker     // GLES 3.0.4 section 3.8.10 pg 158:
1873*8975f5c5SAndroid Build Coastguard Worker     // "For immutable-format textures, levelbase is clamped to the range[0;levels],levelmax is then
1874*8975f5c5SAndroid Build Coastguard Worker     // clamped to the range[levelbase;levels].
1875*8975f5c5SAndroid Build Coastguard Worker     mDirtyBits.set(DIRTY_BIT_BASE_LEVEL);
1876*8975f5c5SAndroid Build Coastguard Worker     mDirtyBits.set(DIRTY_BIT_MAX_LEVEL);
1877*8975f5c5SAndroid Build Coastguard Worker 
1878*8975f5c5SAndroid Build Coastguard Worker     signalDirtyStorage(initState);
1879*8975f5c5SAndroid Build Coastguard Worker 
1880*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
1881*8975f5c5SAndroid Build Coastguard Worker }
1882*8975f5c5SAndroid Build Coastguard Worker 
getImageCompressionRate(const Context * context) const1883*8975f5c5SAndroid Build Coastguard Worker GLint Texture::getImageCompressionRate(const Context *context) const
1884*8975f5c5SAndroid Build Coastguard Worker {
1885*8975f5c5SAndroid Build Coastguard Worker     return mTexture->getImageCompressionRate(context);
1886*8975f5c5SAndroid Build Coastguard Worker }
1887*8975f5c5SAndroid Build Coastguard Worker 
getFormatSupportedCompressionRates(const Context * context,GLenum internalformat,GLsizei bufSize,GLint * rates) const1888*8975f5c5SAndroid Build Coastguard Worker GLint Texture::getFormatSupportedCompressionRates(const Context *context,
1889*8975f5c5SAndroid Build Coastguard Worker                                                   GLenum internalformat,
1890*8975f5c5SAndroid Build Coastguard Worker                                                   GLsizei bufSize,
1891*8975f5c5SAndroid Build Coastguard Worker                                                   GLint *rates) const
1892*8975f5c5SAndroid Build Coastguard Worker {
1893*8975f5c5SAndroid Build Coastguard Worker     return mTexture->getFormatSupportedCompressionRates(context, internalformat, bufSize, rates);
1894*8975f5c5SAndroid Build Coastguard Worker }
1895*8975f5c5SAndroid Build Coastguard Worker 
generateMipmap(Context * context)1896*8975f5c5SAndroid Build Coastguard Worker angle::Result Texture::generateMipmap(Context *context)
1897*8975f5c5SAndroid Build Coastguard Worker {
1898*8975f5c5SAndroid Build Coastguard Worker     // Release from previous calls to eglBindTexImage, to avoid calling the Impl after
1899*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(releaseTexImageInternal(context));
1900*8975f5c5SAndroid Build Coastguard Worker 
1901*8975f5c5SAndroid Build Coastguard Worker     // EGL_KHR_gl_image states that images are only orphaned when generating mipmaps if the texture
1902*8975f5c5SAndroid Build Coastguard Worker     // is not mip complete.
1903*8975f5c5SAndroid Build Coastguard Worker     egl::RefCountObjectReleaser<egl::Image> releaseImage;
1904*8975f5c5SAndroid Build Coastguard Worker     if (!isMipmapComplete())
1905*8975f5c5SAndroid Build Coastguard Worker     {
1906*8975f5c5SAndroid Build Coastguard Worker         ANGLE_TRY(orphanImages(context, &releaseImage));
1907*8975f5c5SAndroid Build Coastguard Worker     }
1908*8975f5c5SAndroid Build Coastguard Worker 
1909*8975f5c5SAndroid Build Coastguard Worker     const GLuint baseLevel = mState.getEffectiveBaseLevel();
1910*8975f5c5SAndroid Build Coastguard Worker     const GLuint maxLevel  = mState.getMipmapMaxLevel();
1911*8975f5c5SAndroid Build Coastguard Worker 
1912*8975f5c5SAndroid Build Coastguard Worker     if (maxLevel <= baseLevel)
1913*8975f5c5SAndroid Build Coastguard Worker     {
1914*8975f5c5SAndroid Build Coastguard Worker         return angle::Result::Continue;
1915*8975f5c5SAndroid Build Coastguard Worker     }
1916*8975f5c5SAndroid Build Coastguard Worker 
1917*8975f5c5SAndroid Build Coastguard Worker     // If any dimension is zero, this is a no-op:
1918*8975f5c5SAndroid Build Coastguard Worker     //
1919*8975f5c5SAndroid Build Coastguard Worker     // > Otherwise, if level_base is not defined, or if any dimension is zero, all mipmap levels are
1920*8975f5c5SAndroid Build Coastguard Worker     // > left unchanged. This is not an error.
1921*8975f5c5SAndroid Build Coastguard Worker     const ImageDesc &baseImageInfo = mState.getImageDesc(mState.getBaseImageTarget(), baseLevel);
1922*8975f5c5SAndroid Build Coastguard Worker     if (baseImageInfo.size.empty())
1923*8975f5c5SAndroid Build Coastguard Worker     {
1924*8975f5c5SAndroid Build Coastguard Worker         return angle::Result::Continue;
1925*8975f5c5SAndroid Build Coastguard Worker     }
1926*8975f5c5SAndroid Build Coastguard Worker 
1927*8975f5c5SAndroid Build Coastguard Worker     // Clear the base image(s) immediately if needed
1928*8975f5c5SAndroid Build Coastguard Worker     if (context->isRobustResourceInitEnabled())
1929*8975f5c5SAndroid Build Coastguard Worker     {
1930*8975f5c5SAndroid Build Coastguard Worker         ImageIndexIterator it =
1931*8975f5c5SAndroid Build Coastguard Worker             ImageIndexIterator::MakeGeneric(mState.mType, baseLevel, baseLevel + 1,
1932*8975f5c5SAndroid Build Coastguard Worker                                             ImageIndex::kEntireLevel, ImageIndex::kEntireLevel);
1933*8975f5c5SAndroid Build Coastguard Worker         while (it.hasNext())
1934*8975f5c5SAndroid Build Coastguard Worker         {
1935*8975f5c5SAndroid Build Coastguard Worker             const ImageIndex index = it.next();
1936*8975f5c5SAndroid Build Coastguard Worker             const ImageDesc &desc  = mState.getImageDesc(index.getTarget(), index.getLevelIndex());
1937*8975f5c5SAndroid Build Coastguard Worker 
1938*8975f5c5SAndroid Build Coastguard Worker             if (desc.initState == InitState::MayNeedInit)
1939*8975f5c5SAndroid Build Coastguard Worker             {
1940*8975f5c5SAndroid Build Coastguard Worker                 ANGLE_TRY(initializeContents(context, GL_NONE, index));
1941*8975f5c5SAndroid Build Coastguard Worker             }
1942*8975f5c5SAndroid Build Coastguard Worker         }
1943*8975f5c5SAndroid Build Coastguard Worker     }
1944*8975f5c5SAndroid Build Coastguard Worker 
1945*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(syncState(context, Command::GenerateMipmap));
1946*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(mTexture->generateMipmap(context));
1947*8975f5c5SAndroid Build Coastguard Worker 
1948*8975f5c5SAndroid Build Coastguard Worker     // Propagate the format and size of the base mip to the smaller ones. Cube maps are guaranteed
1949*8975f5c5SAndroid Build Coastguard Worker     // to have faces of the same size and format so any faces can be picked.
1950*8975f5c5SAndroid Build Coastguard Worker     mState.setImageDescChain(baseLevel, maxLevel, baseImageInfo.size, baseImageInfo.format,
1951*8975f5c5SAndroid Build Coastguard Worker                              InitState::Initialized);
1952*8975f5c5SAndroid Build Coastguard Worker 
1953*8975f5c5SAndroid Build Coastguard Worker     signalDirtyStorage(InitState::Initialized);
1954*8975f5c5SAndroid Build Coastguard Worker 
1955*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
1956*8975f5c5SAndroid Build Coastguard Worker }
1957*8975f5c5SAndroid Build Coastguard Worker 
clearImage(Context * context,GLint level,GLenum format,GLenum type,const uint8_t * data)1958*8975f5c5SAndroid Build Coastguard Worker angle::Result Texture::clearImage(Context *context,
1959*8975f5c5SAndroid Build Coastguard Worker                                   GLint level,
1960*8975f5c5SAndroid Build Coastguard Worker                                   GLenum format,
1961*8975f5c5SAndroid Build Coastguard Worker                                   GLenum type,
1962*8975f5c5SAndroid Build Coastguard Worker                                   const uint8_t *data)
1963*8975f5c5SAndroid Build Coastguard Worker {
1964*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(mTexture->clearImage(context, level, format, type, data));
1965*8975f5c5SAndroid Build Coastguard Worker 
1966*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(handleMipmapGenerationHint(context, level));
1967*8975f5c5SAndroid Build Coastguard Worker 
1968*8975f5c5SAndroid Build Coastguard Worker     ImageIndexIterator it = ImageIndexIterator::MakeGeneric(
1969*8975f5c5SAndroid Build Coastguard Worker         mState.mType, level, level + 1, ImageIndex::kEntireLevel, ImageIndex::kEntireLevel);
1970*8975f5c5SAndroid Build Coastguard Worker     while (it.hasNext())
1971*8975f5c5SAndroid Build Coastguard Worker     {
1972*8975f5c5SAndroid Build Coastguard Worker         const ImageIndex index = it.next();
1973*8975f5c5SAndroid Build Coastguard Worker         setInitState(GL_NONE, index, InitState::Initialized);
1974*8975f5c5SAndroid Build Coastguard Worker     }
1975*8975f5c5SAndroid Build Coastguard Worker 
1976*8975f5c5SAndroid Build Coastguard Worker     onStateChange(angle::SubjectMessage::ContentsChanged);
1977*8975f5c5SAndroid Build Coastguard Worker 
1978*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
1979*8975f5c5SAndroid Build Coastguard Worker }
1980*8975f5c5SAndroid Build Coastguard Worker 
clearSubImage(Context * context,GLint level,const Box & area,GLenum format,GLenum type,const uint8_t * data)1981*8975f5c5SAndroid Build Coastguard Worker angle::Result Texture::clearSubImage(Context *context,
1982*8975f5c5SAndroid Build Coastguard Worker                                      GLint level,
1983*8975f5c5SAndroid Build Coastguard Worker                                      const Box &area,
1984*8975f5c5SAndroid Build Coastguard Worker                                      GLenum format,
1985*8975f5c5SAndroid Build Coastguard Worker                                      GLenum type,
1986*8975f5c5SAndroid Build Coastguard Worker                                      const uint8_t *data)
1987*8975f5c5SAndroid Build Coastguard Worker {
1988*8975f5c5SAndroid Build Coastguard Worker     const ImageIndexIterator allImagesIterator = ImageIndexIterator::MakeGeneric(
1989*8975f5c5SAndroid Build Coastguard Worker         mState.mType, level, level + 1, area.z, area.z + area.depth);
1990*8975f5c5SAndroid Build Coastguard Worker 
1991*8975f5c5SAndroid Build Coastguard Worker     ImageIndexIterator initImagesIterator = allImagesIterator;
1992*8975f5c5SAndroid Build Coastguard Worker     while (initImagesIterator.hasNext())
1993*8975f5c5SAndroid Build Coastguard Worker     {
1994*8975f5c5SAndroid Build Coastguard Worker         const ImageIndex index     = initImagesIterator.next();
1995*8975f5c5SAndroid Build Coastguard Worker         const Box cubeFlattenedBox = index.getType() == TextureType::CubeMap
1996*8975f5c5SAndroid Build Coastguard Worker                                          ? Box(area.x, area.y, 0, area.width, area.height, 1)
1997*8975f5c5SAndroid Build Coastguard Worker                                          : area;
1998*8975f5c5SAndroid Build Coastguard Worker         ANGLE_TRY(ensureSubImageInitialized(context, index, cubeFlattenedBox));
1999*8975f5c5SAndroid Build Coastguard Worker     }
2000*8975f5c5SAndroid Build Coastguard Worker 
2001*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(mTexture->clearSubImage(context, level, area, format, type, data));
2002*8975f5c5SAndroid Build Coastguard Worker 
2003*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(handleMipmapGenerationHint(context, level));
2004*8975f5c5SAndroid Build Coastguard Worker 
2005*8975f5c5SAndroid Build Coastguard Worker     onStateChange(angle::SubjectMessage::ContentsChanged);
2006*8975f5c5SAndroid Build Coastguard Worker 
2007*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
2008*8975f5c5SAndroid Build Coastguard Worker }
2009*8975f5c5SAndroid Build Coastguard Worker 
bindTexImageFromSurface(Context * context,egl::Surface * surface)2010*8975f5c5SAndroid Build Coastguard Worker angle::Result Texture::bindTexImageFromSurface(Context *context, egl::Surface *surface)
2011*8975f5c5SAndroid Build Coastguard Worker {
2012*8975f5c5SAndroid Build Coastguard Worker     ASSERT(surface);
2013*8975f5c5SAndroid Build Coastguard Worker     ASSERT(!mBoundSurface);
2014*8975f5c5SAndroid Build Coastguard Worker     mBoundSurface = surface;
2015*8975f5c5SAndroid Build Coastguard Worker 
2016*8975f5c5SAndroid Build Coastguard Worker     // Set the image info to the size and format of the surface
2017*8975f5c5SAndroid Build Coastguard Worker     ASSERT(mState.mType == TextureType::_2D || mState.mType == TextureType::Rectangle);
2018*8975f5c5SAndroid Build Coastguard Worker     Extents size(surface->getWidth(), surface->getHeight(), 1);
2019*8975f5c5SAndroid Build Coastguard Worker     ImageDesc desc(size, surface->getBindTexImageFormat(), InitState::Initialized);
2020*8975f5c5SAndroid Build Coastguard Worker     mState.setImageDesc(NonCubeTextureTypeToTarget(mState.mType), 0, desc);
2021*8975f5c5SAndroid Build Coastguard Worker     mState.mHasProtectedContent = surface->hasProtectedContent();
2022*8975f5c5SAndroid Build Coastguard Worker 
2023*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(mTexture->bindTexImage(context, surface));
2024*8975f5c5SAndroid Build Coastguard Worker 
2025*8975f5c5SAndroid Build Coastguard Worker     signalDirtyStorage(InitState::Initialized);
2026*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
2027*8975f5c5SAndroid Build Coastguard Worker }
2028*8975f5c5SAndroid Build Coastguard Worker 
releaseTexImageFromSurface(const Context * context)2029*8975f5c5SAndroid Build Coastguard Worker angle::Result Texture::releaseTexImageFromSurface(const Context *context)
2030*8975f5c5SAndroid Build Coastguard Worker {
2031*8975f5c5SAndroid Build Coastguard Worker     ASSERT(mBoundSurface);
2032*8975f5c5SAndroid Build Coastguard Worker     mBoundSurface = nullptr;
2033*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(mTexture->releaseTexImage(context));
2034*8975f5c5SAndroid Build Coastguard Worker 
2035*8975f5c5SAndroid Build Coastguard Worker     // Erase the image info for level 0
2036*8975f5c5SAndroid Build Coastguard Worker     ASSERT(mState.mType == TextureType::_2D || mState.mType == TextureType::Rectangle);
2037*8975f5c5SAndroid Build Coastguard Worker     mState.clearImageDesc(NonCubeTextureTypeToTarget(mState.mType), 0);
2038*8975f5c5SAndroid Build Coastguard Worker     mState.mHasProtectedContent = false;
2039*8975f5c5SAndroid Build Coastguard Worker     signalDirtyStorage(InitState::Initialized);
2040*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
2041*8975f5c5SAndroid Build Coastguard Worker }
2042*8975f5c5SAndroid Build Coastguard Worker 
bindStream(egl::Stream * stream)2043*8975f5c5SAndroid Build Coastguard Worker void Texture::bindStream(egl::Stream *stream)
2044*8975f5c5SAndroid Build Coastguard Worker {
2045*8975f5c5SAndroid Build Coastguard Worker     ASSERT(stream);
2046*8975f5c5SAndroid Build Coastguard Worker 
2047*8975f5c5SAndroid Build Coastguard Worker     // It should not be possible to bind a texture already bound to another stream
2048*8975f5c5SAndroid Build Coastguard Worker     ASSERT(mBoundStream == nullptr);
2049*8975f5c5SAndroid Build Coastguard Worker 
2050*8975f5c5SAndroid Build Coastguard Worker     mBoundStream = stream;
2051*8975f5c5SAndroid Build Coastguard Worker 
2052*8975f5c5SAndroid Build Coastguard Worker     ASSERT(mState.mType == TextureType::External);
2053*8975f5c5SAndroid Build Coastguard Worker }
2054*8975f5c5SAndroid Build Coastguard Worker 
releaseStream()2055*8975f5c5SAndroid Build Coastguard Worker void Texture::releaseStream()
2056*8975f5c5SAndroid Build Coastguard Worker {
2057*8975f5c5SAndroid Build Coastguard Worker     ASSERT(mBoundStream);
2058*8975f5c5SAndroid Build Coastguard Worker     mBoundStream = nullptr;
2059*8975f5c5SAndroid Build Coastguard Worker }
2060*8975f5c5SAndroid Build Coastguard Worker 
acquireImageFromStream(const Context * context,const egl::Stream::GLTextureDescription & desc)2061*8975f5c5SAndroid Build Coastguard Worker angle::Result Texture::acquireImageFromStream(const Context *context,
2062*8975f5c5SAndroid Build Coastguard Worker                                               const egl::Stream::GLTextureDescription &desc)
2063*8975f5c5SAndroid Build Coastguard Worker {
2064*8975f5c5SAndroid Build Coastguard Worker     ASSERT(mBoundStream != nullptr);
2065*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(mTexture->setImageExternal(context, mState.mType, mBoundStream, desc));
2066*8975f5c5SAndroid Build Coastguard Worker 
2067*8975f5c5SAndroid Build Coastguard Worker     Extents size(desc.width, desc.height, 1);
2068*8975f5c5SAndroid Build Coastguard Worker     mState.setImageDesc(NonCubeTextureTypeToTarget(mState.mType), 0,
2069*8975f5c5SAndroid Build Coastguard Worker                         ImageDesc(size, Format(desc.internalFormat), InitState::Initialized));
2070*8975f5c5SAndroid Build Coastguard Worker     signalDirtyStorage(InitState::Initialized);
2071*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
2072*8975f5c5SAndroid Build Coastguard Worker }
2073*8975f5c5SAndroid Build Coastguard Worker 
releaseImageFromStream(const Context * context)2074*8975f5c5SAndroid Build Coastguard Worker angle::Result Texture::releaseImageFromStream(const Context *context)
2075*8975f5c5SAndroid Build Coastguard Worker {
2076*8975f5c5SAndroid Build Coastguard Worker     ASSERT(mBoundStream != nullptr);
2077*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(mTexture->setImageExternal(context, mState.mType, nullptr,
2078*8975f5c5SAndroid Build Coastguard Worker                                          egl::Stream::GLTextureDescription()));
2079*8975f5c5SAndroid Build Coastguard Worker 
2080*8975f5c5SAndroid Build Coastguard Worker     // Set to incomplete
2081*8975f5c5SAndroid Build Coastguard Worker     mState.clearImageDesc(NonCubeTextureTypeToTarget(mState.mType), 0);
2082*8975f5c5SAndroid Build Coastguard Worker     signalDirtyStorage(InitState::Initialized);
2083*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
2084*8975f5c5SAndroid Build Coastguard Worker }
2085*8975f5c5SAndroid Build Coastguard Worker 
releaseTexImageInternal(Context * context)2086*8975f5c5SAndroid Build Coastguard Worker angle::Result Texture::releaseTexImageInternal(Context *context)
2087*8975f5c5SAndroid Build Coastguard Worker {
2088*8975f5c5SAndroid Build Coastguard Worker     if (mBoundSurface)
2089*8975f5c5SAndroid Build Coastguard Worker     {
2090*8975f5c5SAndroid Build Coastguard Worker         // Notify the surface
2091*8975f5c5SAndroid Build Coastguard Worker         egl::Error eglErr = mBoundSurface->releaseTexImageFromTexture(context);
2092*8975f5c5SAndroid Build Coastguard Worker         // TODO(jmadill): Remove this once refactor is complete. http://anglebug.com/42261727
2093*8975f5c5SAndroid Build Coastguard Worker         if (eglErr.isError())
2094*8975f5c5SAndroid Build Coastguard Worker         {
2095*8975f5c5SAndroid Build Coastguard Worker             context->handleError(GL_INVALID_OPERATION, "Error releasing tex image from texture",
2096*8975f5c5SAndroid Build Coastguard Worker                                  __FILE__, ANGLE_FUNCTION, __LINE__);
2097*8975f5c5SAndroid Build Coastguard Worker         }
2098*8975f5c5SAndroid Build Coastguard Worker 
2099*8975f5c5SAndroid Build Coastguard Worker         // Then, call the same method as from the surface
2100*8975f5c5SAndroid Build Coastguard Worker         ANGLE_TRY(releaseTexImageFromSurface(context));
2101*8975f5c5SAndroid Build Coastguard Worker     }
2102*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
2103*8975f5c5SAndroid Build Coastguard Worker }
2104*8975f5c5SAndroid Build Coastguard Worker 
setEGLImageTargetImpl(Context * context,TextureType type,GLuint levels,egl::Image * imageTarget)2105*8975f5c5SAndroid Build Coastguard Worker angle::Result Texture::setEGLImageTargetImpl(Context *context,
2106*8975f5c5SAndroid Build Coastguard Worker                                              TextureType type,
2107*8975f5c5SAndroid Build Coastguard Worker                                              GLuint levels,
2108*8975f5c5SAndroid Build Coastguard Worker                                              egl::Image *imageTarget)
2109*8975f5c5SAndroid Build Coastguard Worker {
2110*8975f5c5SAndroid Build Coastguard Worker     ASSERT(type == mState.mType);
2111*8975f5c5SAndroid Build Coastguard Worker 
2112*8975f5c5SAndroid Build Coastguard Worker     // Release from previous calls to eglBindTexImage, to avoid calling the Impl after
2113*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(releaseTexImageInternal(context));
2114*8975f5c5SAndroid Build Coastguard Worker 
2115*8975f5c5SAndroid Build Coastguard Worker     egl::RefCountObjectReleaser<egl::Image> releaseImage;
2116*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(orphanImages(context, &releaseImage));
2117*8975f5c5SAndroid Build Coastguard Worker 
2118*8975f5c5SAndroid Build Coastguard Worker     setTargetImage(context, imageTarget);
2119*8975f5c5SAndroid Build Coastguard Worker 
2120*8975f5c5SAndroid Build Coastguard Worker     auto initState = imageTarget->sourceInitState();
2121*8975f5c5SAndroid Build Coastguard Worker 
2122*8975f5c5SAndroid Build Coastguard Worker     mState.clearImageDescs();
2123*8975f5c5SAndroid Build Coastguard Worker     mState.setImageDescChain(0, levels - 1, imageTarget->getExtents(), imageTarget->getFormat(),
2124*8975f5c5SAndroid Build Coastguard Worker                              initState);
2125*8975f5c5SAndroid Build Coastguard Worker     mState.mHasProtectedContent = imageTarget->hasProtectedContent();
2126*8975f5c5SAndroid Build Coastguard Worker 
2127*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(mTexture->setEGLImageTarget(context, type, imageTarget));
2128*8975f5c5SAndroid Build Coastguard Worker 
2129*8975f5c5SAndroid Build Coastguard Worker     signalDirtyStorage(initState);
2130*8975f5c5SAndroid Build Coastguard Worker 
2131*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
2132*8975f5c5SAndroid Build Coastguard Worker }
2133*8975f5c5SAndroid Build Coastguard Worker 
setEGLImageTarget(Context * context,TextureType type,egl::Image * imageTarget)2134*8975f5c5SAndroid Build Coastguard Worker angle::Result Texture::setEGLImageTarget(Context *context,
2135*8975f5c5SAndroid Build Coastguard Worker                                          TextureType type,
2136*8975f5c5SAndroid Build Coastguard Worker                                          egl::Image *imageTarget)
2137*8975f5c5SAndroid Build Coastguard Worker {
2138*8975f5c5SAndroid Build Coastguard Worker     ASSERT(type == TextureType::_2D || type == TextureType::External ||
2139*8975f5c5SAndroid Build Coastguard Worker            type == TextureType::_2DArray);
2140*8975f5c5SAndroid Build Coastguard Worker 
2141*8975f5c5SAndroid Build Coastguard Worker     return setEGLImageTargetImpl(context, type, 1u, imageTarget);
2142*8975f5c5SAndroid Build Coastguard Worker }
2143*8975f5c5SAndroid Build Coastguard Worker 
setStorageEGLImageTarget(Context * context,TextureType type,egl::Image * imageTarget,const GLint * attrib_list)2144*8975f5c5SAndroid Build Coastguard Worker angle::Result Texture::setStorageEGLImageTarget(Context *context,
2145*8975f5c5SAndroid Build Coastguard Worker                                                 TextureType type,
2146*8975f5c5SAndroid Build Coastguard Worker                                                 egl::Image *imageTarget,
2147*8975f5c5SAndroid Build Coastguard Worker                                                 const GLint *attrib_list)
2148*8975f5c5SAndroid Build Coastguard Worker {
2149*8975f5c5SAndroid Build Coastguard Worker     ASSERT(type == TextureType::External || type == TextureType::_3D || type == TextureType::_2D ||
2150*8975f5c5SAndroid Build Coastguard Worker            type == TextureType::_2DArray || type == TextureType::CubeMap ||
2151*8975f5c5SAndroid Build Coastguard Worker            type == TextureType::CubeMapArray);
2152*8975f5c5SAndroid Build Coastguard Worker 
2153*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(setEGLImageTargetImpl(context, type, imageTarget->getLevelCount(), imageTarget));
2154*8975f5c5SAndroid Build Coastguard Worker 
2155*8975f5c5SAndroid Build Coastguard Worker     mState.mImmutableLevels = imageTarget->getLevelCount();
2156*8975f5c5SAndroid Build Coastguard Worker     mState.mImmutableFormat = true;
2157*8975f5c5SAndroid Build Coastguard Worker 
2158*8975f5c5SAndroid Build Coastguard Worker     // Changing the texture to immutable can trigger a change in the base and max levels:
2159*8975f5c5SAndroid Build Coastguard Worker     // GLES 3.0.4 section 3.8.10 pg 158:
2160*8975f5c5SAndroid Build Coastguard Worker     // "For immutable-format textures, levelbase is clamped to the range[0;levels],levelmax is then
2161*8975f5c5SAndroid Build Coastguard Worker     // clamped to the range[levelbase;levels].
2162*8975f5c5SAndroid Build Coastguard Worker     mDirtyBits.set(DIRTY_BIT_BASE_LEVEL);
2163*8975f5c5SAndroid Build Coastguard Worker     mDirtyBits.set(DIRTY_BIT_MAX_LEVEL);
2164*8975f5c5SAndroid Build Coastguard Worker 
2165*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
2166*8975f5c5SAndroid Build Coastguard Worker }
2167*8975f5c5SAndroid Build Coastguard Worker 
getAttachmentSize(const ImageIndex & imageIndex) const2168*8975f5c5SAndroid Build Coastguard Worker Extents Texture::getAttachmentSize(const ImageIndex &imageIndex) const
2169*8975f5c5SAndroid Build Coastguard Worker {
2170*8975f5c5SAndroid Build Coastguard Worker     // As an ImageIndex that represents an entire level of a cube map corresponds to 6 ImageDescs,
2171*8975f5c5SAndroid Build Coastguard Worker     // we only allow querying ImageDesc on a complete cube map, and this ImageDesc is exactly the
2172*8975f5c5SAndroid Build Coastguard Worker     // one that belongs to the first face of the cube map.
2173*8975f5c5SAndroid Build Coastguard Worker     if (imageIndex.isEntireLevelCubeMap())
2174*8975f5c5SAndroid Build Coastguard Worker     {
2175*8975f5c5SAndroid Build Coastguard Worker         // A cube map texture is cube complete if the following conditions all hold true:
2176*8975f5c5SAndroid Build Coastguard Worker         // - The levelbase arrays of each of the six texture images making up the cube map have
2177*8975f5c5SAndroid Build Coastguard Worker         //   identical, positive, and square dimensions.
2178*8975f5c5SAndroid Build Coastguard Worker         if (!mState.isCubeComplete())
2179*8975f5c5SAndroid Build Coastguard Worker         {
2180*8975f5c5SAndroid Build Coastguard Worker             return Extents();
2181*8975f5c5SAndroid Build Coastguard Worker         }
2182*8975f5c5SAndroid Build Coastguard Worker     }
2183*8975f5c5SAndroid Build Coastguard Worker 
2184*8975f5c5SAndroid Build Coastguard Worker     return mState.getImageDesc(imageIndex).size;
2185*8975f5c5SAndroid Build Coastguard Worker }
2186*8975f5c5SAndroid Build Coastguard Worker 
getAttachmentFormat(GLenum,const ImageIndex & imageIndex) const2187*8975f5c5SAndroid Build Coastguard Worker Format Texture::getAttachmentFormat(GLenum /*binding*/, const ImageIndex &imageIndex) const
2188*8975f5c5SAndroid Build Coastguard Worker {
2189*8975f5c5SAndroid Build Coastguard Worker     // As an ImageIndex that represents an entire level of a cube map corresponds to 6 ImageDescs,
2190*8975f5c5SAndroid Build Coastguard Worker     // we only allow querying ImageDesc on a complete cube map, and this ImageDesc is exactly the
2191*8975f5c5SAndroid Build Coastguard Worker     // one that belongs to the first face of the cube map.
2192*8975f5c5SAndroid Build Coastguard Worker     if (imageIndex.isEntireLevelCubeMap())
2193*8975f5c5SAndroid Build Coastguard Worker     {
2194*8975f5c5SAndroid Build Coastguard Worker         // A cube map texture is cube complete if the following conditions all hold true:
2195*8975f5c5SAndroid Build Coastguard Worker         // - The levelbase arrays were each specified with the same effective internal format.
2196*8975f5c5SAndroid Build Coastguard Worker         if (!mState.isCubeComplete())
2197*8975f5c5SAndroid Build Coastguard Worker         {
2198*8975f5c5SAndroid Build Coastguard Worker             return Format::Invalid();
2199*8975f5c5SAndroid Build Coastguard Worker         }
2200*8975f5c5SAndroid Build Coastguard Worker     }
2201*8975f5c5SAndroid Build Coastguard Worker     return mState.getImageDesc(imageIndex).format;
2202*8975f5c5SAndroid Build Coastguard Worker }
2203*8975f5c5SAndroid Build Coastguard Worker 
getAttachmentSamples(const ImageIndex & imageIndex) const2204*8975f5c5SAndroid Build Coastguard Worker GLsizei Texture::getAttachmentSamples(const ImageIndex &imageIndex) const
2205*8975f5c5SAndroid Build Coastguard Worker {
2206*8975f5c5SAndroid Build Coastguard Worker     // We do not allow querying TextureTarget by an ImageIndex that represents an entire level of a
2207*8975f5c5SAndroid Build Coastguard Worker     // cube map (See comments in function TextureTypeToTarget() in ImageIndex.cpp).
2208*8975f5c5SAndroid Build Coastguard Worker     if (imageIndex.isEntireLevelCubeMap())
2209*8975f5c5SAndroid Build Coastguard Worker     {
2210*8975f5c5SAndroid Build Coastguard Worker         return 0;
2211*8975f5c5SAndroid Build Coastguard Worker     }
2212*8975f5c5SAndroid Build Coastguard Worker 
2213*8975f5c5SAndroid Build Coastguard Worker     return getSamples(imageIndex.getTarget(), imageIndex.getLevelIndex());
2214*8975f5c5SAndroid Build Coastguard Worker }
2215*8975f5c5SAndroid Build Coastguard Worker 
isRenderable(const Context * context,GLenum binding,const ImageIndex & imageIndex) const2216*8975f5c5SAndroid Build Coastguard Worker bool Texture::isRenderable(const Context *context,
2217*8975f5c5SAndroid Build Coastguard Worker                            GLenum binding,
2218*8975f5c5SAndroid Build Coastguard Worker                            const ImageIndex &imageIndex) const
2219*8975f5c5SAndroid Build Coastguard Worker {
2220*8975f5c5SAndroid Build Coastguard Worker     if (isEGLImageTarget())
2221*8975f5c5SAndroid Build Coastguard Worker     {
2222*8975f5c5SAndroid Build Coastguard Worker         return ImageSibling::isRenderable(context, binding, imageIndex);
2223*8975f5c5SAndroid Build Coastguard Worker     }
2224*8975f5c5SAndroid Build Coastguard Worker 
2225*8975f5c5SAndroid Build Coastguard Worker     // Surfaces bound to textures are always renderable. This avoids issues with surfaces with ES3+
2226*8975f5c5SAndroid Build Coastguard Worker     // formats not being renderable when bound to textures in ES2 contexts.
2227*8975f5c5SAndroid Build Coastguard Worker     if (mBoundSurface)
2228*8975f5c5SAndroid Build Coastguard Worker     {
2229*8975f5c5SAndroid Build Coastguard Worker         return true;
2230*8975f5c5SAndroid Build Coastguard Worker     }
2231*8975f5c5SAndroid Build Coastguard Worker 
2232*8975f5c5SAndroid Build Coastguard Worker     // Skip the renderability checks if it is set via glTexParameteri and current
2233*8975f5c5SAndroid Build Coastguard Worker     // context is less than GLES3. Note that we should not skip the check if the
2234*8975f5c5SAndroid Build Coastguard Worker     // texture is not renderable at all. Otherwise we would end up rendering to
2235*8975f5c5SAndroid Build Coastguard Worker     // textures like compressed textures that are not really renderable.
2236*8975f5c5SAndroid Build Coastguard Worker     if (context->getImplementation()
2237*8975f5c5SAndroid Build Coastguard Worker             ->getNativeTextureCaps()
2238*8975f5c5SAndroid Build Coastguard Worker             .get(getAttachmentFormat(binding, imageIndex).info->sizedInternalFormat)
2239*8975f5c5SAndroid Build Coastguard Worker             .textureAttachment &&
2240*8975f5c5SAndroid Build Coastguard Worker         !mState.renderabilityValidation() && context->getClientMajorVersion() < 3)
2241*8975f5c5SAndroid Build Coastguard Worker     {
2242*8975f5c5SAndroid Build Coastguard Worker         return true;
2243*8975f5c5SAndroid Build Coastguard Worker     }
2244*8975f5c5SAndroid Build Coastguard Worker 
2245*8975f5c5SAndroid Build Coastguard Worker     return getAttachmentFormat(binding, imageIndex)
2246*8975f5c5SAndroid Build Coastguard Worker         .info->textureAttachmentSupport(context->getClientVersion(), context->getExtensions());
2247*8975f5c5SAndroid Build Coastguard Worker }
2248*8975f5c5SAndroid Build Coastguard Worker 
getAttachmentFixedSampleLocations(const ImageIndex & imageIndex) const2249*8975f5c5SAndroid Build Coastguard Worker bool Texture::getAttachmentFixedSampleLocations(const ImageIndex &imageIndex) const
2250*8975f5c5SAndroid Build Coastguard Worker {
2251*8975f5c5SAndroid Build Coastguard Worker     // We do not allow querying TextureTarget by an ImageIndex that represents an entire level of a
2252*8975f5c5SAndroid Build Coastguard Worker     // cube map (See comments in function TextureTypeToTarget() in ImageIndex.cpp).
2253*8975f5c5SAndroid Build Coastguard Worker     if (imageIndex.isEntireLevelCubeMap())
2254*8975f5c5SAndroid Build Coastguard Worker     {
2255*8975f5c5SAndroid Build Coastguard Worker         return true;
2256*8975f5c5SAndroid Build Coastguard Worker     }
2257*8975f5c5SAndroid Build Coastguard Worker 
2258*8975f5c5SAndroid Build Coastguard Worker     // ES3.1 (section 9.4) requires that the value of TEXTURE_FIXED_SAMPLE_LOCATIONS should be
2259*8975f5c5SAndroid Build Coastguard Worker     // the same for all attached textures.
2260*8975f5c5SAndroid Build Coastguard Worker     return getFixedSampleLocations(imageIndex.getTarget(), imageIndex.getLevelIndex());
2261*8975f5c5SAndroid Build Coastguard Worker }
2262*8975f5c5SAndroid Build Coastguard Worker 
setBorderColor(const Context * context,const ColorGeneric & color)2263*8975f5c5SAndroid Build Coastguard Worker void Texture::setBorderColor(const Context *context, const ColorGeneric &color)
2264*8975f5c5SAndroid Build Coastguard Worker {
2265*8975f5c5SAndroid Build Coastguard Worker     mState.mSamplerState.setBorderColor(color);
2266*8975f5c5SAndroid Build Coastguard Worker     signalDirtyState(DIRTY_BIT_BORDER_COLOR);
2267*8975f5c5SAndroid Build Coastguard Worker }
2268*8975f5c5SAndroid Build Coastguard Worker 
getBorderColor() const2269*8975f5c5SAndroid Build Coastguard Worker const ColorGeneric &Texture::getBorderColor() const
2270*8975f5c5SAndroid Build Coastguard Worker {
2271*8975f5c5SAndroid Build Coastguard Worker     return mState.mSamplerState.getBorderColor();
2272*8975f5c5SAndroid Build Coastguard Worker }
2273*8975f5c5SAndroid Build Coastguard Worker 
getRequiredTextureImageUnits(const Context * context) const2274*8975f5c5SAndroid Build Coastguard Worker GLint Texture::getRequiredTextureImageUnits(const Context *context) const
2275*8975f5c5SAndroid Build Coastguard Worker {
2276*8975f5c5SAndroid Build Coastguard Worker     // Only external texture types can return non-1.
2277*8975f5c5SAndroid Build Coastguard Worker     if (mState.mType != TextureType::External)
2278*8975f5c5SAndroid Build Coastguard Worker     {
2279*8975f5c5SAndroid Build Coastguard Worker         return 1;
2280*8975f5c5SAndroid Build Coastguard Worker     }
2281*8975f5c5SAndroid Build Coastguard Worker 
2282*8975f5c5SAndroid Build Coastguard Worker     return mTexture->getRequiredExternalTextureImageUnits(context);
2283*8975f5c5SAndroid Build Coastguard Worker }
2284*8975f5c5SAndroid Build Coastguard Worker 
setCrop(const Rectangle & rect)2285*8975f5c5SAndroid Build Coastguard Worker void Texture::setCrop(const Rectangle &rect)
2286*8975f5c5SAndroid Build Coastguard Worker {
2287*8975f5c5SAndroid Build Coastguard Worker     mState.setCrop(rect);
2288*8975f5c5SAndroid Build Coastguard Worker }
2289*8975f5c5SAndroid Build Coastguard Worker 
getCrop() const2290*8975f5c5SAndroid Build Coastguard Worker const Rectangle &Texture::getCrop() const
2291*8975f5c5SAndroid Build Coastguard Worker {
2292*8975f5c5SAndroid Build Coastguard Worker     return mState.getCrop();
2293*8975f5c5SAndroid Build Coastguard Worker }
2294*8975f5c5SAndroid Build Coastguard Worker 
setGenerateMipmapHint(GLenum hint)2295*8975f5c5SAndroid Build Coastguard Worker void Texture::setGenerateMipmapHint(GLenum hint)
2296*8975f5c5SAndroid Build Coastguard Worker {
2297*8975f5c5SAndroid Build Coastguard Worker     mState.setGenerateMipmapHint(hint);
2298*8975f5c5SAndroid Build Coastguard Worker }
2299*8975f5c5SAndroid Build Coastguard Worker 
getGenerateMipmapHint() const2300*8975f5c5SAndroid Build Coastguard Worker GLenum Texture::getGenerateMipmapHint() const
2301*8975f5c5SAndroid Build Coastguard Worker {
2302*8975f5c5SAndroid Build Coastguard Worker     return mState.getGenerateMipmapHint();
2303*8975f5c5SAndroid Build Coastguard Worker }
2304*8975f5c5SAndroid Build Coastguard Worker 
setBuffer(const gl::Context * context,gl::Buffer * buffer,GLenum internalFormat)2305*8975f5c5SAndroid Build Coastguard Worker angle::Result Texture::setBuffer(const gl::Context *context,
2306*8975f5c5SAndroid Build Coastguard Worker                                  gl::Buffer *buffer,
2307*8975f5c5SAndroid Build Coastguard Worker                                  GLenum internalFormat)
2308*8975f5c5SAndroid Build Coastguard Worker {
2309*8975f5c5SAndroid Build Coastguard Worker     // Use 0 to indicate that the size is taken from whatever size the buffer has when the texture
2310*8975f5c5SAndroid Build Coastguard Worker     // buffer is used.
2311*8975f5c5SAndroid Build Coastguard Worker     return setBufferRange(context, buffer, internalFormat, 0, 0);
2312*8975f5c5SAndroid Build Coastguard Worker }
2313*8975f5c5SAndroid Build Coastguard Worker 
setBufferRange(const gl::Context * context,gl::Buffer * buffer,GLenum internalFormat,GLintptr offset,GLsizeiptr size)2314*8975f5c5SAndroid Build Coastguard Worker angle::Result Texture::setBufferRange(const gl::Context *context,
2315*8975f5c5SAndroid Build Coastguard Worker                                       gl::Buffer *buffer,
2316*8975f5c5SAndroid Build Coastguard Worker                                       GLenum internalFormat,
2317*8975f5c5SAndroid Build Coastguard Worker                                       GLintptr offset,
2318*8975f5c5SAndroid Build Coastguard Worker                                       GLsizeiptr size)
2319*8975f5c5SAndroid Build Coastguard Worker {
2320*8975f5c5SAndroid Build Coastguard Worker     mState.mImmutableFormat = true;
2321*8975f5c5SAndroid Build Coastguard Worker     mState.mBuffer.set(context, buffer, offset, size);
2322*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(mTexture->setBuffer(context, internalFormat));
2323*8975f5c5SAndroid Build Coastguard Worker 
2324*8975f5c5SAndroid Build Coastguard Worker     mState.clearImageDescs();
2325*8975f5c5SAndroid Build Coastguard Worker     if (buffer == nullptr)
2326*8975f5c5SAndroid Build Coastguard Worker     {
2327*8975f5c5SAndroid Build Coastguard Worker         mBufferObserver.reset();
2328*8975f5c5SAndroid Build Coastguard Worker         InitState initState = DetermineInitState(context, nullptr, nullptr);
2329*8975f5c5SAndroid Build Coastguard Worker         signalDirtyStorage(initState);
2330*8975f5c5SAndroid Build Coastguard Worker         return angle::Result::Continue;
2331*8975f5c5SAndroid Build Coastguard Worker     }
2332*8975f5c5SAndroid Build Coastguard Worker 
2333*8975f5c5SAndroid Build Coastguard Worker     size = GetBoundBufferAvailableSize(mState.mBuffer);
2334*8975f5c5SAndroid Build Coastguard Worker 
2335*8975f5c5SAndroid Build Coastguard Worker     mState.mImmutableLevels           = static_cast<GLuint>(1);
2336*8975f5c5SAndroid Build Coastguard Worker     InternalFormat internalFormatInfo = GetSizedInternalFormatInfo(internalFormat);
2337*8975f5c5SAndroid Build Coastguard Worker     Format format(internalFormat);
2338*8975f5c5SAndroid Build Coastguard Worker     Extents extents(static_cast<GLuint>(size / internalFormatInfo.pixelBytes), 1, 1);
2339*8975f5c5SAndroid Build Coastguard Worker     InitState initState = buffer->initState();
2340*8975f5c5SAndroid Build Coastguard Worker     mState.setImageDesc(TextureTarget::Buffer, 0, ImageDesc(extents, format, initState));
2341*8975f5c5SAndroid Build Coastguard Worker 
2342*8975f5c5SAndroid Build Coastguard Worker     signalDirtyStorage(initState);
2343*8975f5c5SAndroid Build Coastguard Worker 
2344*8975f5c5SAndroid Build Coastguard Worker     // Observe modifications to the buffer, so that extents can be updated.
2345*8975f5c5SAndroid Build Coastguard Worker     mBufferObserver.bind(buffer);
2346*8975f5c5SAndroid Build Coastguard Worker 
2347*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
2348*8975f5c5SAndroid Build Coastguard Worker }
2349*8975f5c5SAndroid Build Coastguard Worker 
getBuffer() const2350*8975f5c5SAndroid Build Coastguard Worker const OffsetBindingPointer<Buffer> &Texture::getBuffer() const
2351*8975f5c5SAndroid Build Coastguard Worker {
2352*8975f5c5SAndroid Build Coastguard Worker     return mState.mBuffer;
2353*8975f5c5SAndroid Build Coastguard Worker }
2354*8975f5c5SAndroid Build Coastguard Worker 
onAttach(const Context * context,rx::UniqueSerial framebufferSerial)2355*8975f5c5SAndroid Build Coastguard Worker void Texture::onAttach(const Context *context, rx::UniqueSerial framebufferSerial)
2356*8975f5c5SAndroid Build Coastguard Worker {
2357*8975f5c5SAndroid Build Coastguard Worker     addRef();
2358*8975f5c5SAndroid Build Coastguard Worker 
2359*8975f5c5SAndroid Build Coastguard Worker     // Duplicates allowed for multiple attachment points. See the comment in the header.
2360*8975f5c5SAndroid Build Coastguard Worker     mBoundFramebufferSerials.push_back(framebufferSerial);
2361*8975f5c5SAndroid Build Coastguard Worker 
2362*8975f5c5SAndroid Build Coastguard Worker     if (!mState.mHasBeenBoundAsAttachment)
2363*8975f5c5SAndroid Build Coastguard Worker     {
2364*8975f5c5SAndroid Build Coastguard Worker         mDirtyBits.set(DIRTY_BIT_BOUND_AS_ATTACHMENT);
2365*8975f5c5SAndroid Build Coastguard Worker         mState.mHasBeenBoundAsAttachment = true;
2366*8975f5c5SAndroid Build Coastguard Worker     }
2367*8975f5c5SAndroid Build Coastguard Worker }
2368*8975f5c5SAndroid Build Coastguard Worker 
onDetach(const Context * context,rx::UniqueSerial framebufferSerial)2369*8975f5c5SAndroid Build Coastguard Worker void Texture::onDetach(const Context *context, rx::UniqueSerial framebufferSerial)
2370*8975f5c5SAndroid Build Coastguard Worker {
2371*8975f5c5SAndroid Build Coastguard Worker     // Erase first instance. If there are multiple bindings, leave the others.
2372*8975f5c5SAndroid Build Coastguard Worker     ASSERT(isBoundToFramebuffer(framebufferSerial));
2373*8975f5c5SAndroid Build Coastguard Worker     mBoundFramebufferSerials.remove_and_permute(framebufferSerial);
2374*8975f5c5SAndroid Build Coastguard Worker 
2375*8975f5c5SAndroid Build Coastguard Worker     release(context);
2376*8975f5c5SAndroid Build Coastguard Worker }
2377*8975f5c5SAndroid Build Coastguard Worker 
getId() const2378*8975f5c5SAndroid Build Coastguard Worker GLuint Texture::getId() const
2379*8975f5c5SAndroid Build Coastguard Worker {
2380*8975f5c5SAndroid Build Coastguard Worker     return id().value;
2381*8975f5c5SAndroid Build Coastguard Worker }
2382*8975f5c5SAndroid Build Coastguard Worker 
getNativeID() const2383*8975f5c5SAndroid Build Coastguard Worker GLuint Texture::getNativeID() const
2384*8975f5c5SAndroid Build Coastguard Worker {
2385*8975f5c5SAndroid Build Coastguard Worker     return mTexture->getNativeID();
2386*8975f5c5SAndroid Build Coastguard Worker }
2387*8975f5c5SAndroid Build Coastguard Worker 
syncState(const Context * context,Command source)2388*8975f5c5SAndroid Build Coastguard Worker angle::Result Texture::syncState(const Context *context, Command source)
2389*8975f5c5SAndroid Build Coastguard Worker {
2390*8975f5c5SAndroid Build Coastguard Worker     ASSERT(hasAnyDirtyBit() || source == Command::GenerateMipmap);
2391*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(mTexture->syncState(context, mDirtyBits, source));
2392*8975f5c5SAndroid Build Coastguard Worker     mDirtyBits.reset();
2393*8975f5c5SAndroid Build Coastguard Worker     mState.mInitState = InitState::Initialized;
2394*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
2395*8975f5c5SAndroid Build Coastguard Worker }
2396*8975f5c5SAndroid Build Coastguard Worker 
getAttachmentImpl() const2397*8975f5c5SAndroid Build Coastguard Worker rx::FramebufferAttachmentObjectImpl *Texture::getAttachmentImpl() const
2398*8975f5c5SAndroid Build Coastguard Worker {
2399*8975f5c5SAndroid Build Coastguard Worker     return mTexture;
2400*8975f5c5SAndroid Build Coastguard Worker }
2401*8975f5c5SAndroid Build Coastguard Worker 
isSamplerComplete(const Context * context,const Sampler * optionalSampler)2402*8975f5c5SAndroid Build Coastguard Worker bool Texture::isSamplerComplete(const Context *context, const Sampler *optionalSampler)
2403*8975f5c5SAndroid Build Coastguard Worker {
2404*8975f5c5SAndroid Build Coastguard Worker     const auto &samplerState =
2405*8975f5c5SAndroid Build Coastguard Worker         optionalSampler ? optionalSampler->getSamplerState() : mState.mSamplerState;
2406*8975f5c5SAndroid Build Coastguard Worker     const auto &contextState = context->getState();
2407*8975f5c5SAndroid Build Coastguard Worker 
2408*8975f5c5SAndroid Build Coastguard Worker     if (contextState.getContextID() != mCompletenessCache.context ||
2409*8975f5c5SAndroid Build Coastguard Worker         !mCompletenessCache.samplerState.sameCompleteness(samplerState))
2410*8975f5c5SAndroid Build Coastguard Worker     {
2411*8975f5c5SAndroid Build Coastguard Worker         mCompletenessCache.context      = context->getState().getContextID();
2412*8975f5c5SAndroid Build Coastguard Worker         mCompletenessCache.samplerState = samplerState;
2413*8975f5c5SAndroid Build Coastguard Worker         mCompletenessCache.samplerComplete =
2414*8975f5c5SAndroid Build Coastguard Worker             mState.computeSamplerCompleteness(samplerState, contextState);
2415*8975f5c5SAndroid Build Coastguard Worker     }
2416*8975f5c5SAndroid Build Coastguard Worker 
2417*8975f5c5SAndroid Build Coastguard Worker     return mCompletenessCache.samplerComplete;
2418*8975f5c5SAndroid Build Coastguard Worker }
2419*8975f5c5SAndroid Build Coastguard Worker 
2420*8975f5c5SAndroid Build Coastguard Worker // CopyImageSubData requires that we ignore format-based completeness rules
isSamplerCompleteForCopyImage(const Context * context,const Sampler * optionalSampler) const2421*8975f5c5SAndroid Build Coastguard Worker bool Texture::isSamplerCompleteForCopyImage(const Context *context,
2422*8975f5c5SAndroid Build Coastguard Worker                                             const Sampler *optionalSampler) const
2423*8975f5c5SAndroid Build Coastguard Worker {
2424*8975f5c5SAndroid Build Coastguard Worker     const gl::SamplerState &samplerState =
2425*8975f5c5SAndroid Build Coastguard Worker         optionalSampler ? optionalSampler->getSamplerState() : mState.mSamplerState;
2426*8975f5c5SAndroid Build Coastguard Worker     const gl::State &contextState = context->getState();
2427*8975f5c5SAndroid Build Coastguard Worker     return mState.computeSamplerCompletenessForCopyImage(samplerState, contextState);
2428*8975f5c5SAndroid Build Coastguard Worker }
2429*8975f5c5SAndroid Build Coastguard Worker 
SamplerCompletenessCache()2430*8975f5c5SAndroid Build Coastguard Worker Texture::SamplerCompletenessCache::SamplerCompletenessCache()
2431*8975f5c5SAndroid Build Coastguard Worker     : context({0}), samplerState(), samplerComplete(false)
2432*8975f5c5SAndroid Build Coastguard Worker {}
2433*8975f5c5SAndroid Build Coastguard Worker 
invalidateCompletenessCache() const2434*8975f5c5SAndroid Build Coastguard Worker void Texture::invalidateCompletenessCache() const
2435*8975f5c5SAndroid Build Coastguard Worker {
2436*8975f5c5SAndroid Build Coastguard Worker     mCompletenessCache.context = {0};
2437*8975f5c5SAndroid Build Coastguard Worker }
2438*8975f5c5SAndroid Build Coastguard Worker 
ensureInitialized(const Context * context)2439*8975f5c5SAndroid Build Coastguard Worker angle::Result Texture::ensureInitialized(const Context *context)
2440*8975f5c5SAndroid Build Coastguard Worker {
2441*8975f5c5SAndroid Build Coastguard Worker     if (!context->isRobustResourceInitEnabled() || mState.mInitState == InitState::Initialized)
2442*8975f5c5SAndroid Build Coastguard Worker     {
2443*8975f5c5SAndroid Build Coastguard Worker         return angle::Result::Continue;
2444*8975f5c5SAndroid Build Coastguard Worker     }
2445*8975f5c5SAndroid Build Coastguard Worker 
2446*8975f5c5SAndroid Build Coastguard Worker     bool anyDirty = false;
2447*8975f5c5SAndroid Build Coastguard Worker 
2448*8975f5c5SAndroid Build Coastguard Worker     ImageIndexIterator it =
2449*8975f5c5SAndroid Build Coastguard Worker         ImageIndexIterator::MakeGeneric(mState.mType, 0, IMPLEMENTATION_MAX_TEXTURE_LEVELS + 1,
2450*8975f5c5SAndroid Build Coastguard Worker                                         ImageIndex::kEntireLevel, ImageIndex::kEntireLevel);
2451*8975f5c5SAndroid Build Coastguard Worker     while (it.hasNext())
2452*8975f5c5SAndroid Build Coastguard Worker     {
2453*8975f5c5SAndroid Build Coastguard Worker         const ImageIndex index = it.next();
2454*8975f5c5SAndroid Build Coastguard Worker         ImageDesc &desc =
2455*8975f5c5SAndroid Build Coastguard Worker             mState.mImageDescs[GetImageDescIndex(index.getTarget(), index.getLevelIndex())];
2456*8975f5c5SAndroid Build Coastguard Worker         if (desc.initState == InitState::MayNeedInit && !desc.size.empty())
2457*8975f5c5SAndroid Build Coastguard Worker         {
2458*8975f5c5SAndroid Build Coastguard Worker             ASSERT(mState.mInitState == InitState::MayNeedInit);
2459*8975f5c5SAndroid Build Coastguard Worker             ANGLE_TRY(initializeContents(context, GL_NONE, index));
2460*8975f5c5SAndroid Build Coastguard Worker             desc.initState = InitState::Initialized;
2461*8975f5c5SAndroid Build Coastguard Worker             anyDirty       = true;
2462*8975f5c5SAndroid Build Coastguard Worker         }
2463*8975f5c5SAndroid Build Coastguard Worker     }
2464*8975f5c5SAndroid Build Coastguard Worker     if (anyDirty)
2465*8975f5c5SAndroid Build Coastguard Worker     {
2466*8975f5c5SAndroid Build Coastguard Worker         signalDirtyStorage(InitState::Initialized);
2467*8975f5c5SAndroid Build Coastguard Worker     }
2468*8975f5c5SAndroid Build Coastguard Worker     mState.mInitState = InitState::Initialized;
2469*8975f5c5SAndroid Build Coastguard Worker 
2470*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
2471*8975f5c5SAndroid Build Coastguard Worker }
2472*8975f5c5SAndroid Build Coastguard Worker 
initState(GLenum,const ImageIndex & imageIndex) const2473*8975f5c5SAndroid Build Coastguard Worker InitState Texture::initState(GLenum /*binding*/, const ImageIndex &imageIndex) const
2474*8975f5c5SAndroid Build Coastguard Worker {
2475*8975f5c5SAndroid Build Coastguard Worker     // As an ImageIndex that represents an entire level of a cube map corresponds to 6 ImageDescs,
2476*8975f5c5SAndroid Build Coastguard Worker     // we need to check all the related ImageDescs.
2477*8975f5c5SAndroid Build Coastguard Worker     if (imageIndex.isEntireLevelCubeMap())
2478*8975f5c5SAndroid Build Coastguard Worker     {
2479*8975f5c5SAndroid Build Coastguard Worker         const GLint levelIndex = imageIndex.getLevelIndex();
2480*8975f5c5SAndroid Build Coastguard Worker         for (TextureTarget cubeFaceTarget : AllCubeFaceTextureTargets())
2481*8975f5c5SAndroid Build Coastguard Worker         {
2482*8975f5c5SAndroid Build Coastguard Worker             if (mState.getImageDesc(cubeFaceTarget, levelIndex).initState == InitState::MayNeedInit)
2483*8975f5c5SAndroid Build Coastguard Worker             {
2484*8975f5c5SAndroid Build Coastguard Worker                 return InitState::MayNeedInit;
2485*8975f5c5SAndroid Build Coastguard Worker             }
2486*8975f5c5SAndroid Build Coastguard Worker         }
2487*8975f5c5SAndroid Build Coastguard Worker         return InitState::Initialized;
2488*8975f5c5SAndroid Build Coastguard Worker     }
2489*8975f5c5SAndroid Build Coastguard Worker 
2490*8975f5c5SAndroid Build Coastguard Worker     return mState.getImageDesc(imageIndex).initState;
2491*8975f5c5SAndroid Build Coastguard Worker }
2492*8975f5c5SAndroid Build Coastguard Worker 
setInitState(GLenum binding,const ImageIndex & imageIndex,InitState initState)2493*8975f5c5SAndroid Build Coastguard Worker void Texture::setInitState(GLenum binding, const ImageIndex &imageIndex, InitState initState)
2494*8975f5c5SAndroid Build Coastguard Worker {
2495*8975f5c5SAndroid Build Coastguard Worker     // As an ImageIndex that represents an entire level of a cube map corresponds to 6 ImageDescs,
2496*8975f5c5SAndroid Build Coastguard Worker     // we need to update all the related ImageDescs.
2497*8975f5c5SAndroid Build Coastguard Worker     if (imageIndex.isEntireLevelCubeMap())
2498*8975f5c5SAndroid Build Coastguard Worker     {
2499*8975f5c5SAndroid Build Coastguard Worker         const GLint levelIndex = imageIndex.getLevelIndex();
2500*8975f5c5SAndroid Build Coastguard Worker         for (TextureTarget cubeFaceTarget : AllCubeFaceTextureTargets())
2501*8975f5c5SAndroid Build Coastguard Worker         {
2502*8975f5c5SAndroid Build Coastguard Worker             setInitState(binding, ImageIndex::MakeCubeMapFace(cubeFaceTarget, levelIndex),
2503*8975f5c5SAndroid Build Coastguard Worker                          initState);
2504*8975f5c5SAndroid Build Coastguard Worker         }
2505*8975f5c5SAndroid Build Coastguard Worker     }
2506*8975f5c5SAndroid Build Coastguard Worker     else
2507*8975f5c5SAndroid Build Coastguard Worker     {
2508*8975f5c5SAndroid Build Coastguard Worker         ImageDesc newDesc = mState.getImageDesc(imageIndex);
2509*8975f5c5SAndroid Build Coastguard Worker         newDesc.initState = initState;
2510*8975f5c5SAndroid Build Coastguard Worker         mState.setImageDesc(imageIndex.getTarget(), imageIndex.getLevelIndex(), newDesc);
2511*8975f5c5SAndroid Build Coastguard Worker     }
2512*8975f5c5SAndroid Build Coastguard Worker }
2513*8975f5c5SAndroid Build Coastguard Worker 
setInitState(InitState initState)2514*8975f5c5SAndroid Build Coastguard Worker void Texture::setInitState(InitState initState)
2515*8975f5c5SAndroid Build Coastguard Worker {
2516*8975f5c5SAndroid Build Coastguard Worker     for (ImageDesc &imageDesc : mState.mImageDescs)
2517*8975f5c5SAndroid Build Coastguard Worker     {
2518*8975f5c5SAndroid Build Coastguard Worker         // Only modify defined images, undefined images will remain in the initialized state
2519*8975f5c5SAndroid Build Coastguard Worker         if (!imageDesc.size.empty())
2520*8975f5c5SAndroid Build Coastguard Worker         {
2521*8975f5c5SAndroid Build Coastguard Worker             imageDesc.initState = initState;
2522*8975f5c5SAndroid Build Coastguard Worker         }
2523*8975f5c5SAndroid Build Coastguard Worker     }
2524*8975f5c5SAndroid Build Coastguard Worker     mState.mInitState = initState;
2525*8975f5c5SAndroid Build Coastguard Worker }
2526*8975f5c5SAndroid Build Coastguard Worker 
doesSubImageNeedInit(const Context * context,const ImageIndex & imageIndex,const Box & area) const2527*8975f5c5SAndroid Build Coastguard Worker bool Texture::doesSubImageNeedInit(const Context *context,
2528*8975f5c5SAndroid Build Coastguard Worker                                    const ImageIndex &imageIndex,
2529*8975f5c5SAndroid Build Coastguard Worker                                    const Box &area) const
2530*8975f5c5SAndroid Build Coastguard Worker {
2531*8975f5c5SAndroid Build Coastguard Worker     if (!context->isRobustResourceInitEnabled() || mState.mInitState == InitState::Initialized)
2532*8975f5c5SAndroid Build Coastguard Worker     {
2533*8975f5c5SAndroid Build Coastguard Worker         return false;
2534*8975f5c5SAndroid Build Coastguard Worker     }
2535*8975f5c5SAndroid Build Coastguard Worker 
2536*8975f5c5SAndroid Build Coastguard Worker     // Pre-initialize the texture contents if necessary.
2537*8975f5c5SAndroid Build Coastguard Worker     const ImageDesc &desc = mState.getImageDesc(imageIndex);
2538*8975f5c5SAndroid Build Coastguard Worker     if (desc.initState != InitState::MayNeedInit)
2539*8975f5c5SAndroid Build Coastguard Worker     {
2540*8975f5c5SAndroid Build Coastguard Worker         return false;
2541*8975f5c5SAndroid Build Coastguard Worker     }
2542*8975f5c5SAndroid Build Coastguard Worker 
2543*8975f5c5SAndroid Build Coastguard Worker     ASSERT(mState.mInitState == InitState::MayNeedInit);
2544*8975f5c5SAndroid Build Coastguard Worker     return !area.coversSameExtent(desc.size);
2545*8975f5c5SAndroid Build Coastguard Worker }
2546*8975f5c5SAndroid Build Coastguard Worker 
ensureSubImageInitialized(const Context * context,const ImageIndex & imageIndex,const Box & area)2547*8975f5c5SAndroid Build Coastguard Worker angle::Result Texture::ensureSubImageInitialized(const Context *context,
2548*8975f5c5SAndroid Build Coastguard Worker                                                  const ImageIndex &imageIndex,
2549*8975f5c5SAndroid Build Coastguard Worker                                                  const Box &area)
2550*8975f5c5SAndroid Build Coastguard Worker {
2551*8975f5c5SAndroid Build Coastguard Worker     if (doesSubImageNeedInit(context, imageIndex, area))
2552*8975f5c5SAndroid Build Coastguard Worker     {
2553*8975f5c5SAndroid Build Coastguard Worker         // NOTE: do not optimize this to only initialize the passed area of the texture, or the
2554*8975f5c5SAndroid Build Coastguard Worker         // initialization logic in copySubImage will be incorrect.
2555*8975f5c5SAndroid Build Coastguard Worker         ANGLE_TRY(initializeContents(context, GL_NONE, imageIndex));
2556*8975f5c5SAndroid Build Coastguard Worker     }
2557*8975f5c5SAndroid Build Coastguard Worker     // Note: binding is ignored for textures.
2558*8975f5c5SAndroid Build Coastguard Worker     setInitState(GL_NONE, imageIndex, InitState::Initialized);
2559*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
2560*8975f5c5SAndroid Build Coastguard Worker }
2561*8975f5c5SAndroid Build Coastguard Worker 
handleMipmapGenerationHint(Context * context,int level)2562*8975f5c5SAndroid Build Coastguard Worker angle::Result Texture::handleMipmapGenerationHint(Context *context, int level)
2563*8975f5c5SAndroid Build Coastguard Worker {
2564*8975f5c5SAndroid Build Coastguard Worker     if (getGenerateMipmapHint() == GL_TRUE && level == 0)
2565*8975f5c5SAndroid Build Coastguard Worker     {
2566*8975f5c5SAndroid Build Coastguard Worker         ANGLE_TRY(generateMipmap(context));
2567*8975f5c5SAndroid Build Coastguard Worker     }
2568*8975f5c5SAndroid Build Coastguard Worker 
2569*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
2570*8975f5c5SAndroid Build Coastguard Worker }
2571*8975f5c5SAndroid Build Coastguard Worker 
onSubjectStateChange(angle::SubjectIndex index,angle::SubjectMessage message)2572*8975f5c5SAndroid Build Coastguard Worker void Texture::onSubjectStateChange(angle::SubjectIndex index, angle::SubjectMessage message)
2573*8975f5c5SAndroid Build Coastguard Worker {
2574*8975f5c5SAndroid Build Coastguard Worker     switch (message)
2575*8975f5c5SAndroid Build Coastguard Worker     {
2576*8975f5c5SAndroid Build Coastguard Worker         case angle::SubjectMessage::ContentsChanged:
2577*8975f5c5SAndroid Build Coastguard Worker             if (index != kBufferSubjectIndex)
2578*8975f5c5SAndroid Build Coastguard Worker             {
2579*8975f5c5SAndroid Build Coastguard Worker                 // ContentsChange originates from TextureStorage11::resolveAndReleaseTexture
2580*8975f5c5SAndroid Build Coastguard Worker                 // which resolves the underlying multisampled texture if it exists and so
2581*8975f5c5SAndroid Build Coastguard Worker                 // Texture will signal dirty storage to invalidate its own cache and the
2582*8975f5c5SAndroid Build Coastguard Worker                 // attached framebuffer's cache.
2583*8975f5c5SAndroid Build Coastguard Worker                 signalDirtyStorage(InitState::Initialized);
2584*8975f5c5SAndroid Build Coastguard Worker             }
2585*8975f5c5SAndroid Build Coastguard Worker             break;
2586*8975f5c5SAndroid Build Coastguard Worker         case angle::SubjectMessage::DirtyBitsFlagged:
2587*8975f5c5SAndroid Build Coastguard Worker             signalDirtyState(DIRTY_BIT_IMPLEMENTATION);
2588*8975f5c5SAndroid Build Coastguard Worker 
2589*8975f5c5SAndroid Build Coastguard Worker             // Notify siblings that we are dirty.
2590*8975f5c5SAndroid Build Coastguard Worker             if (index == rx::kTextureImageImplObserverMessageIndex)
2591*8975f5c5SAndroid Build Coastguard Worker             {
2592*8975f5c5SAndroid Build Coastguard Worker                 notifySiblings(message);
2593*8975f5c5SAndroid Build Coastguard Worker             }
2594*8975f5c5SAndroid Build Coastguard Worker             break;
2595*8975f5c5SAndroid Build Coastguard Worker         case angle::SubjectMessage::SubjectChanged:
2596*8975f5c5SAndroid Build Coastguard Worker             mState.mInitState = InitState::MayNeedInit;
2597*8975f5c5SAndroid Build Coastguard Worker             signalDirtyState(DIRTY_BIT_IMPLEMENTATION);
2598*8975f5c5SAndroid Build Coastguard Worker             onStateChange(angle::SubjectMessage::ContentsChanged);
2599*8975f5c5SAndroid Build Coastguard Worker 
2600*8975f5c5SAndroid Build Coastguard Worker             // Notify siblings that we are dirty.
2601*8975f5c5SAndroid Build Coastguard Worker             if (index == rx::kTextureImageImplObserverMessageIndex)
2602*8975f5c5SAndroid Build Coastguard Worker             {
2603*8975f5c5SAndroid Build Coastguard Worker                 notifySiblings(message);
2604*8975f5c5SAndroid Build Coastguard Worker             }
2605*8975f5c5SAndroid Build Coastguard Worker             else if (index == kBufferSubjectIndex)
2606*8975f5c5SAndroid Build Coastguard Worker             {
2607*8975f5c5SAndroid Build Coastguard Worker                 const gl::Buffer *buffer = mState.mBuffer.get();
2608*8975f5c5SAndroid Build Coastguard Worker                 ASSERT(buffer != nullptr);
2609*8975f5c5SAndroid Build Coastguard Worker 
2610*8975f5c5SAndroid Build Coastguard Worker                 // Update cached image desc based on buffer size.
2611*8975f5c5SAndroid Build Coastguard Worker                 GLsizeiptr size = GetBoundBufferAvailableSize(mState.mBuffer);
2612*8975f5c5SAndroid Build Coastguard Worker 
2613*8975f5c5SAndroid Build Coastguard Worker                 ImageDesc desc          = mState.getImageDesc(TextureTarget::Buffer, 0);
2614*8975f5c5SAndroid Build Coastguard Worker                 const GLuint pixelBytes = desc.format.info->pixelBytes;
2615*8975f5c5SAndroid Build Coastguard Worker                 desc.size.width         = static_cast<GLuint>(size / pixelBytes);
2616*8975f5c5SAndroid Build Coastguard Worker 
2617*8975f5c5SAndroid Build Coastguard Worker                 mState.setImageDesc(TextureTarget::Buffer, 0, desc);
2618*8975f5c5SAndroid Build Coastguard Worker             }
2619*8975f5c5SAndroid Build Coastguard Worker             break;
2620*8975f5c5SAndroid Build Coastguard Worker         case angle::SubjectMessage::StorageReleased:
2621*8975f5c5SAndroid Build Coastguard Worker             // When the TextureStorage is released, it needs to update the
2622*8975f5c5SAndroid Build Coastguard Worker             // RenderTargetCache of the Framebuffer attaching this Texture.
2623*8975f5c5SAndroid Build Coastguard Worker             // This is currently only for D3D back-end. See http://crbug.com/1234829
2624*8975f5c5SAndroid Build Coastguard Worker             if (index == rx::kTextureImageImplObserverMessageIndex)
2625*8975f5c5SAndroid Build Coastguard Worker             {
2626*8975f5c5SAndroid Build Coastguard Worker                 onStateChange(angle::SubjectMessage::StorageReleased);
2627*8975f5c5SAndroid Build Coastguard Worker             }
2628*8975f5c5SAndroid Build Coastguard Worker             break;
2629*8975f5c5SAndroid Build Coastguard Worker         case angle::SubjectMessage::SubjectMapped:
2630*8975f5c5SAndroid Build Coastguard Worker         case angle::SubjectMessage::SubjectUnmapped:
2631*8975f5c5SAndroid Build Coastguard Worker         case angle::SubjectMessage::BindingChanged:
2632*8975f5c5SAndroid Build Coastguard Worker         {
2633*8975f5c5SAndroid Build Coastguard Worker             ASSERT(index == kBufferSubjectIndex);
2634*8975f5c5SAndroid Build Coastguard Worker             gl::Buffer *buffer = mState.mBuffer.get();
2635*8975f5c5SAndroid Build Coastguard Worker             ASSERT(buffer != nullptr);
2636*8975f5c5SAndroid Build Coastguard Worker             if (buffer->hasContentsObserver(this))
2637*8975f5c5SAndroid Build Coastguard Worker             {
2638*8975f5c5SAndroid Build Coastguard Worker                 onBufferContentsChange();
2639*8975f5c5SAndroid Build Coastguard Worker             }
2640*8975f5c5SAndroid Build Coastguard Worker         }
2641*8975f5c5SAndroid Build Coastguard Worker         break;
2642*8975f5c5SAndroid Build Coastguard Worker         case angle::SubjectMessage::InitializationComplete:
2643*8975f5c5SAndroid Build Coastguard Worker             ASSERT(index == rx::kTextureImageImplObserverMessageIndex);
2644*8975f5c5SAndroid Build Coastguard Worker             setInitState(InitState::Initialized);
2645*8975f5c5SAndroid Build Coastguard Worker             break;
2646*8975f5c5SAndroid Build Coastguard Worker         case angle::SubjectMessage::InternalMemoryAllocationChanged:
2647*8975f5c5SAndroid Build Coastguard Worker             // Need to mark the texture dirty to give the back end a chance to handle the new
2648*8975f5c5SAndroid Build Coastguard Worker             // buffer. For example, the Vulkan back end needs to create a new buffer view that
2649*8975f5c5SAndroid Build Coastguard Worker             // points to the newly allocated buffer and update the texture descriptor set.
2650*8975f5c5SAndroid Build Coastguard Worker             signalDirtyState(DIRTY_BIT_IMPLEMENTATION);
2651*8975f5c5SAndroid Build Coastguard Worker             break;
2652*8975f5c5SAndroid Build Coastguard Worker         default:
2653*8975f5c5SAndroid Build Coastguard Worker             UNREACHABLE();
2654*8975f5c5SAndroid Build Coastguard Worker             break;
2655*8975f5c5SAndroid Build Coastguard Worker     }
2656*8975f5c5SAndroid Build Coastguard Worker }
2657*8975f5c5SAndroid Build Coastguard Worker 
onBufferContentsChange()2658*8975f5c5SAndroid Build Coastguard Worker void Texture::onBufferContentsChange()
2659*8975f5c5SAndroid Build Coastguard Worker {
2660*8975f5c5SAndroid Build Coastguard Worker     mState.mInitState = InitState::MayNeedInit;
2661*8975f5c5SAndroid Build Coastguard Worker     signalDirtyState(DIRTY_BIT_IMPLEMENTATION);
2662*8975f5c5SAndroid Build Coastguard Worker     onStateChange(angle::SubjectMessage::ContentsChanged);
2663*8975f5c5SAndroid Build Coastguard Worker }
2664*8975f5c5SAndroid Build Coastguard Worker 
onBindToMSRTTFramebuffer()2665*8975f5c5SAndroid Build Coastguard Worker void Texture::onBindToMSRTTFramebuffer()
2666*8975f5c5SAndroid Build Coastguard Worker {
2667*8975f5c5SAndroid Build Coastguard Worker     if (!mState.mHasBeenBoundToMSRTTFramebuffer)
2668*8975f5c5SAndroid Build Coastguard Worker     {
2669*8975f5c5SAndroid Build Coastguard Worker         mDirtyBits.set(DIRTY_BIT_BOUND_TO_MSRTT_FRAMEBUFFER);
2670*8975f5c5SAndroid Build Coastguard Worker         mState.mHasBeenBoundToMSRTTFramebuffer = true;
2671*8975f5c5SAndroid Build Coastguard Worker     }
2672*8975f5c5SAndroid Build Coastguard Worker }
2673*8975f5c5SAndroid Build Coastguard Worker 
getImplementationColorReadFormat(const Context * context) const2674*8975f5c5SAndroid Build Coastguard Worker GLenum Texture::getImplementationColorReadFormat(const Context *context) const
2675*8975f5c5SAndroid Build Coastguard Worker {
2676*8975f5c5SAndroid Build Coastguard Worker     return mTexture->getColorReadFormat(context);
2677*8975f5c5SAndroid Build Coastguard Worker }
2678*8975f5c5SAndroid Build Coastguard Worker 
getImplementationColorReadType(const Context * context) const2679*8975f5c5SAndroid Build Coastguard Worker GLenum Texture::getImplementationColorReadType(const Context *context) const
2680*8975f5c5SAndroid Build Coastguard Worker {
2681*8975f5c5SAndroid Build Coastguard Worker     return mTexture->getColorReadType(context);
2682*8975f5c5SAndroid Build Coastguard Worker }
2683*8975f5c5SAndroid Build Coastguard Worker 
getTexImage(const Context * context,const PixelPackState & packState,Buffer * packBuffer,TextureTarget target,GLint level,GLenum format,GLenum type,void * pixels)2684*8975f5c5SAndroid Build Coastguard Worker angle::Result Texture::getTexImage(const Context *context,
2685*8975f5c5SAndroid Build Coastguard Worker                                    const PixelPackState &packState,
2686*8975f5c5SAndroid Build Coastguard Worker                                    Buffer *packBuffer,
2687*8975f5c5SAndroid Build Coastguard Worker                                    TextureTarget target,
2688*8975f5c5SAndroid Build Coastguard Worker                                    GLint level,
2689*8975f5c5SAndroid Build Coastguard Worker                                    GLenum format,
2690*8975f5c5SAndroid Build Coastguard Worker                                    GLenum type,
2691*8975f5c5SAndroid Build Coastguard Worker                                    void *pixels)
2692*8975f5c5SAndroid Build Coastguard Worker {
2693*8975f5c5SAndroid Build Coastguard Worker     // No-op if the image level is empty.
2694*8975f5c5SAndroid Build Coastguard Worker     if (getExtents(target, level).empty())
2695*8975f5c5SAndroid Build Coastguard Worker     {
2696*8975f5c5SAndroid Build Coastguard Worker         return angle::Result::Continue;
2697*8975f5c5SAndroid Build Coastguard Worker     }
2698*8975f5c5SAndroid Build Coastguard Worker 
2699*8975f5c5SAndroid Build Coastguard Worker     return mTexture->getTexImage(context, packState, packBuffer, target, level, format, type,
2700*8975f5c5SAndroid Build Coastguard Worker                                  pixels);
2701*8975f5c5SAndroid Build Coastguard Worker }
2702*8975f5c5SAndroid Build Coastguard Worker 
getCompressedTexImage(const Context * context,const PixelPackState & packState,Buffer * packBuffer,TextureTarget target,GLint level,void * pixels)2703*8975f5c5SAndroid Build Coastguard Worker angle::Result Texture::getCompressedTexImage(const Context *context,
2704*8975f5c5SAndroid Build Coastguard Worker                                              const PixelPackState &packState,
2705*8975f5c5SAndroid Build Coastguard Worker                                              Buffer *packBuffer,
2706*8975f5c5SAndroid Build Coastguard Worker                                              TextureTarget target,
2707*8975f5c5SAndroid Build Coastguard Worker                                              GLint level,
2708*8975f5c5SAndroid Build Coastguard Worker                                              void *pixels)
2709*8975f5c5SAndroid Build Coastguard Worker {
2710*8975f5c5SAndroid Build Coastguard Worker     // No-op if the image level is empty.
2711*8975f5c5SAndroid Build Coastguard Worker     if (getExtents(target, level).empty())
2712*8975f5c5SAndroid Build Coastguard Worker     {
2713*8975f5c5SAndroid Build Coastguard Worker         return angle::Result::Continue;
2714*8975f5c5SAndroid Build Coastguard Worker     }
2715*8975f5c5SAndroid Build Coastguard Worker 
2716*8975f5c5SAndroid Build Coastguard Worker     return mTexture->getCompressedTexImage(context, packState, packBuffer, target, level, pixels);
2717*8975f5c5SAndroid Build Coastguard Worker }
2718*8975f5c5SAndroid Build Coastguard Worker 
onBindAsImageTexture()2719*8975f5c5SAndroid Build Coastguard Worker void Texture::onBindAsImageTexture()
2720*8975f5c5SAndroid Build Coastguard Worker {
2721*8975f5c5SAndroid Build Coastguard Worker     if (!mState.mHasBeenBoundAsImage)
2722*8975f5c5SAndroid Build Coastguard Worker     {
2723*8975f5c5SAndroid Build Coastguard Worker         mDirtyBits.set(DIRTY_BIT_BOUND_AS_IMAGE);
2724*8975f5c5SAndroid Build Coastguard Worker         mState.mHasBeenBoundAsImage = true;
2725*8975f5c5SAndroid Build Coastguard Worker     }
2726*8975f5c5SAndroid Build Coastguard Worker }
2727*8975f5c5SAndroid Build Coastguard Worker 
2728*8975f5c5SAndroid Build Coastguard Worker }  // namespace gl
2729