• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 // Copyright 2015 The ANGLE Project Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
5 //
6 
7 // TextureGL.cpp: Implements the class methods for TextureGL.
8 
9 #include "libANGLE/renderer/gl/TextureGL.h"
10 
11 #include "common/bitset_utils.h"
12 #include "common/debug.h"
13 #include "common/utilities.h"
14 #include "libANGLE/Context.h"
15 #include "libANGLE/MemoryObject.h"
16 #include "libANGLE/State.h"
17 #include "libANGLE/Surface.h"
18 #include "libANGLE/angletypes.h"
19 #include "libANGLE/formatutils.h"
20 #include "libANGLE/queryconversions.h"
21 #include "libANGLE/renderer/gl/BlitGL.h"
22 #include "libANGLE/renderer/gl/BufferGL.h"
23 #include "libANGLE/renderer/gl/ContextGL.h"
24 #include "libANGLE/renderer/gl/FramebufferGL.h"
25 #include "libANGLE/renderer/gl/FunctionsGL.h"
26 #include "libANGLE/renderer/gl/ImageGL.h"
27 #include "libANGLE/renderer/gl/MemoryObjectGL.h"
28 #include "libANGLE/renderer/gl/StateManagerGL.h"
29 #include "libANGLE/renderer/gl/SurfaceGL.h"
30 #include "libANGLE/renderer/gl/formatutilsgl.h"
31 #include "libANGLE/renderer/gl/renderergl_utils.h"
32 #include "platform/FeaturesGL.h"
33 
34 using angle::CheckedNumeric;
35 
36 namespace rx
37 {
38 
39 namespace
40 {
41 
GetLevelInfoIndex(gl::TextureTarget target,size_t level)42 size_t GetLevelInfoIndex(gl::TextureTarget target, size_t level)
43 {
44     return gl::IsCubeMapFaceTarget(target)
45                ? ((level * gl::kCubeFaceCount) + gl::CubeMapTextureTargetToFaceIndex(target))
46                : level;
47 }
48 
IsLUMAFormat(GLenum format)49 bool IsLUMAFormat(GLenum format)
50 {
51     return format == GL_LUMINANCE || format == GL_ALPHA || format == GL_LUMINANCE_ALPHA;
52 }
53 
GetLUMAWorkaroundInfo(GLenum originalFormat,GLenum destinationFormat)54 LUMAWorkaroundGL GetLUMAWorkaroundInfo(GLenum originalFormat, GLenum destinationFormat)
55 {
56     if (IsLUMAFormat(originalFormat))
57     {
58         return LUMAWorkaroundGL(!IsLUMAFormat(destinationFormat), destinationFormat);
59     }
60     else
61     {
62         return LUMAWorkaroundGL(false, GL_NONE);
63     }
64 }
65 
GetDepthStencilWorkaround(GLenum format)66 bool GetDepthStencilWorkaround(GLenum format)
67 {
68     return format == GL_DEPTH_COMPONENT || format == GL_DEPTH_STENCIL;
69 }
70 
GetEmulatedAlphaChannel(const angle::FeaturesGL & features,GLenum internalFormat)71 bool GetEmulatedAlphaChannel(const angle::FeaturesGL &features, GLenum internalFormat)
72 {
73     return features.rgbDXT1TexturesSampleZeroAlpha.enabled &&
74            internalFormat == GL_COMPRESSED_RGB_S3TC_DXT1_EXT;
75 }
76 
GetLevelInfo(const angle::FeaturesGL & features,GLenum originalInternalFormat,GLenum destinationInternalFormat)77 LevelInfoGL GetLevelInfo(const angle::FeaturesGL &features,
78                          GLenum originalInternalFormat,
79                          GLenum destinationInternalFormat)
80 {
81     GLenum originalFormat    = gl::GetUnsizedFormat(originalInternalFormat);
82     GLenum destinationFormat = gl::GetUnsizedFormat(destinationInternalFormat);
83     return LevelInfoGL(originalFormat, destinationInternalFormat,
84                        GetDepthStencilWorkaround(originalFormat),
85                        GetLUMAWorkaroundInfo(originalFormat, destinationFormat),
86                        GetEmulatedAlphaChannel(features, originalFormat));
87 }
88 
GetLevelWorkaroundDirtyBits()89 gl::Texture::DirtyBits GetLevelWorkaroundDirtyBits()
90 {
91     gl::Texture::DirtyBits bits;
92     bits.set(gl::Texture::DIRTY_BIT_SWIZZLE_RED);
93     bits.set(gl::Texture::DIRTY_BIT_SWIZZLE_GREEN);
94     bits.set(gl::Texture::DIRTY_BIT_SWIZZLE_BLUE);
95     bits.set(gl::Texture::DIRTY_BIT_SWIZZLE_ALPHA);
96     return bits;
97 }
98 
GetMaxLevelInfoCountForTextureType(gl::TextureType type)99 size_t GetMaxLevelInfoCountForTextureType(gl::TextureType type)
100 {
101     switch (type)
102     {
103         case gl::TextureType::CubeMap:
104             return (gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS + 1) * gl::kCubeFaceCount;
105 
106         case gl::TextureType::External:
107             return 1;
108 
109         default:
110             return gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS + 1;
111     }
112 }
113 
114 }  // anonymous namespace
115 
LUMAWorkaroundGL()116 LUMAWorkaroundGL::LUMAWorkaroundGL() : LUMAWorkaroundGL(false, GL_NONE) {}
117 
LUMAWorkaroundGL(bool enabled_,GLenum workaroundFormat_)118 LUMAWorkaroundGL::LUMAWorkaroundGL(bool enabled_, GLenum workaroundFormat_)
119     : enabled(enabled_), workaroundFormat(workaroundFormat_)
120 {}
121 
LevelInfoGL()122 LevelInfoGL::LevelInfoGL() : LevelInfoGL(GL_NONE, GL_NONE, false, LUMAWorkaroundGL(), false) {}
123 
LevelInfoGL(GLenum sourceFormat_,GLenum nativeInternalFormat_,bool depthStencilWorkaround_,const LUMAWorkaroundGL & lumaWorkaround_,bool emulatedAlphaChannel_)124 LevelInfoGL::LevelInfoGL(GLenum sourceFormat_,
125                          GLenum nativeInternalFormat_,
126                          bool depthStencilWorkaround_,
127                          const LUMAWorkaroundGL &lumaWorkaround_,
128                          bool emulatedAlphaChannel_)
129     : sourceFormat(sourceFormat_),
130       nativeInternalFormat(nativeInternalFormat_),
131       depthStencilWorkaround(depthStencilWorkaround_),
132       lumaWorkaround(lumaWorkaround_),
133       emulatedAlphaChannel(emulatedAlphaChannel_)
134 {}
135 
TextureGL(const gl::TextureState & state,GLuint id)136 TextureGL::TextureGL(const gl::TextureState &state, GLuint id)
137     : TextureImpl(state),
138       mAppliedSwizzle(state.getSwizzleState()),
139       mAppliedSampler(state.getSamplerState()),
140       mAppliedBaseLevel(state.getEffectiveBaseLevel()),
141       mAppliedMaxLevel(state.getEffectiveMaxLevel()),
142       mTextureID(id)
143 {
144     mLevelInfo.resize(GetMaxLevelInfoCountForTextureType(getType()));
145 }
146 
~TextureGL()147 TextureGL::~TextureGL()
148 {
149     ASSERT(mTextureID == 0);
150 }
151 
onDestroy(const gl::Context * context)152 void TextureGL::onDestroy(const gl::Context *context)
153 {
154     GetImplAs<ContextGL>(context)->flushIfNecessaryBeforeDeleteTextures();
155     StateManagerGL *stateManager = GetStateManagerGL(context);
156     stateManager->deleteTexture(mTextureID);
157     mTextureID = 0;
158 }
159 
setImage(const gl::Context * context,const gl::ImageIndex & index,GLenum internalFormat,const gl::Extents & size,GLenum format,GLenum type,const gl::PixelUnpackState & unpack,gl::Buffer * unpackBuffer,const uint8_t * pixels)160 angle::Result TextureGL::setImage(const gl::Context *context,
161                                   const gl::ImageIndex &index,
162                                   GLenum internalFormat,
163                                   const gl::Extents &size,
164                                   GLenum format,
165                                   GLenum type,
166                                   const gl::PixelUnpackState &unpack,
167                                   gl::Buffer *unpackBuffer,
168                                   const uint8_t *pixels)
169 {
170     const angle::FeaturesGL &features = GetFeaturesGL(context);
171 
172     gl::TextureTarget target = index.getTarget();
173     size_t level             = static_cast<size_t>(index.getLevelIndex());
174 
175     if (features.unpackOverlappingRowsSeparatelyUnpackBuffer.enabled && unpackBuffer &&
176         unpack.rowLength != 0 && unpack.rowLength < size.width)
177     {
178         // The rows overlap in unpack memory. Upload the texture row by row to work around
179         // driver bug.
180         ANGLE_TRY(
181             reserveTexImageToBeFilled(context, target, level, internalFormat, size, format, type));
182 
183         if (size.width == 0 || size.height == 0 || size.depth == 0)
184         {
185             return angle::Result::Continue;
186         }
187 
188         gl::Box area(0, 0, 0, size.width, size.height, size.depth);
189         return setSubImageRowByRowWorkaround(context, target, level, area, format, type, unpack,
190                                              unpackBuffer, pixels);
191     }
192 
193     if (features.unpackLastRowSeparatelyForPaddingInclusion.enabled)
194     {
195         bool apply = false;
196         ANGLE_TRY(ShouldApplyLastRowPaddingWorkaround(
197             GetImplAs<ContextGL>(context), size, unpack, unpackBuffer, format, type,
198             nativegl::UseTexImage3D(getType()), pixels, &apply));
199 
200         // The driver will think the pixel buffer doesn't have enough data, work around this bug
201         // by uploading the last row (and last level if 3D) separately.
202         if (apply)
203         {
204             ANGLE_TRY(reserveTexImageToBeFilled(context, target, level, internalFormat, size,
205                                                 format, type));
206 
207             if (size.width == 0 || size.height == 0 || size.depth == 0)
208             {
209                 return angle::Result::Continue;
210             }
211 
212             gl::Box area(0, 0, 0, size.width, size.height, size.depth);
213             return setSubImagePaddingWorkaround(context, target, level, area, format, type, unpack,
214                                                 unpackBuffer, pixels);
215         }
216     }
217 
218     ANGLE_TRY(setImageHelper(context, target, level, internalFormat, size, format, type, pixels));
219 
220     return angle::Result::Continue;
221 }
222 
setImageHelper(const gl::Context * context,gl::TextureTarget target,size_t level,GLenum internalFormat,const gl::Extents & size,GLenum format,GLenum type,const uint8_t * pixels)223 angle::Result TextureGL::setImageHelper(const gl::Context *context,
224                                         gl::TextureTarget target,
225                                         size_t level,
226                                         GLenum internalFormat,
227                                         const gl::Extents &size,
228                                         GLenum format,
229                                         GLenum type,
230                                         const uint8_t *pixels)
231 {
232     ASSERT(TextureTargetToType(target) == getType());
233 
234     const FunctionsGL *functions      = GetFunctionsGL(context);
235     StateManagerGL *stateManager      = GetStateManagerGL(context);
236     const angle::FeaturesGL &features = GetFeaturesGL(context);
237 
238     nativegl::TexImageFormat texImageFormat =
239         nativegl::GetTexImageFormat(functions, features, internalFormat, format, type);
240 
241     stateManager->bindTexture(getType(), mTextureID);
242 
243     if (features.resetTexImage2DBaseLevel.enabled)
244     {
245         // setBaseLevel doesn't ever generate errors.
246         (void)setBaseLevel(context, 0);
247     }
248 
249     if (nativegl::UseTexImage2D(getType()))
250     {
251         ASSERT(size.depth == 1);
252         ANGLE_GL_TRY_ALWAYS_CHECK(
253             context, functions->texImage2D(nativegl::GetTextureBindingTarget(target),
254                                            static_cast<GLint>(level), texImageFormat.internalFormat,
255                                            size.width, size.height, 0, texImageFormat.format,
256                                            texImageFormat.type, pixels));
257     }
258     else
259     {
260         ASSERT(nativegl::UseTexImage3D(getType()));
261         ANGLE_GL_TRY_ALWAYS_CHECK(
262             context, functions->texImage3D(ToGLenum(target), static_cast<GLint>(level),
263                                            texImageFormat.internalFormat, size.width, size.height,
264                                            size.depth, 0, texImageFormat.format,
265                                            texImageFormat.type, pixels));
266     }
267 
268     setLevelInfo(context, target, level, 1,
269                  GetLevelInfo(features, internalFormat, texImageFormat.internalFormat));
270 
271     return angle::Result::Continue;
272 }
273 
reserveTexImageToBeFilled(const gl::Context * context,gl::TextureTarget target,size_t level,GLenum internalFormat,const gl::Extents & size,GLenum format,GLenum type)274 angle::Result TextureGL::reserveTexImageToBeFilled(const gl::Context *context,
275                                                    gl::TextureTarget target,
276                                                    size_t level,
277                                                    GLenum internalFormat,
278                                                    const gl::Extents &size,
279                                                    GLenum format,
280                                                    GLenum type)
281 {
282     StateManagerGL *stateManager = GetStateManagerGL(context);
283     stateManager->setPixelUnpackBuffer(nullptr);
284     ANGLE_TRY(setImageHelper(context, target, level, internalFormat, size, format, type, nullptr));
285     return angle::Result::Continue;
286 }
287 
setSubImage(const gl::Context * context,const gl::ImageIndex & index,const gl::Box & area,GLenum format,GLenum type,const gl::PixelUnpackState & unpack,gl::Buffer * unpackBuffer,const uint8_t * pixels)288 angle::Result TextureGL::setSubImage(const gl::Context *context,
289                                      const gl::ImageIndex &index,
290                                      const gl::Box &area,
291                                      GLenum format,
292                                      GLenum type,
293                                      const gl::PixelUnpackState &unpack,
294                                      gl::Buffer *unpackBuffer,
295                                      const uint8_t *pixels)
296 {
297     ASSERT(TextureTargetToType(index.getTarget()) == getType());
298 
299     const FunctionsGL *functions      = GetFunctionsGL(context);
300     StateManagerGL *stateManager      = GetStateManagerGL(context);
301     const angle::FeaturesGL &features = GetFeaturesGL(context);
302 
303     nativegl::TexSubImageFormat texSubImageFormat =
304         nativegl::GetTexSubImageFormat(functions, features, format, type);
305 
306     gl::TextureTarget target = index.getTarget();
307     size_t level             = static_cast<size_t>(index.getLevelIndex());
308 
309     ASSERT(getLevelInfo(target, level).lumaWorkaround.enabled ==
310            GetLevelInfo(features, format, texSubImageFormat.format).lumaWorkaround.enabled);
311 
312     stateManager->bindTexture(getType(), mTextureID);
313     if (features.unpackOverlappingRowsSeparatelyUnpackBuffer.enabled && unpackBuffer &&
314         unpack.rowLength != 0 && unpack.rowLength < area.width)
315     {
316         return setSubImageRowByRowWorkaround(context, target, level, area, format, type, unpack,
317                                              unpackBuffer, pixels);
318     }
319 
320     if (features.unpackLastRowSeparatelyForPaddingInclusion.enabled)
321     {
322         gl::Extents size(area.width, area.height, area.depth);
323 
324         bool apply = false;
325         ANGLE_TRY(ShouldApplyLastRowPaddingWorkaround(
326             GetImplAs<ContextGL>(context), size, unpack, unpackBuffer, format, type,
327             nativegl::UseTexImage3D(getType()), pixels, &apply));
328 
329         // The driver will think the pixel buffer doesn't have enough data, work around this bug
330         // by uploading the last row (and last level if 3D) separately.
331         if (apply)
332         {
333             return setSubImagePaddingWorkaround(context, target, level, area, format, type, unpack,
334                                                 unpackBuffer, pixels);
335         }
336     }
337 
338     if (nativegl::UseTexImage2D(getType()))
339     {
340         ASSERT(area.z == 0 && area.depth == 1);
341         ANGLE_GL_TRY(context,
342                      functions->texSubImage2D(nativegl::GetTextureBindingTarget(target),
343                                               static_cast<GLint>(level), area.x, area.y, area.width,
344                                               area.height, texSubImageFormat.format,
345                                               texSubImageFormat.type, pixels));
346     }
347     else
348     {
349         ASSERT(nativegl::UseTexImage3D(getType()));
350         ANGLE_GL_TRY(context, functions->texSubImage3D(
351                                   ToGLenum(target), static_cast<GLint>(level), area.x, area.y,
352                                   area.z, area.width, area.height, area.depth,
353                                   texSubImageFormat.format, texSubImageFormat.type, pixels));
354     }
355 
356     return angle::Result::Continue;
357 }
358 
setSubImageRowByRowWorkaround(const gl::Context * context,gl::TextureTarget target,size_t level,const gl::Box & area,GLenum format,GLenum type,const gl::PixelUnpackState & unpack,const gl::Buffer * unpackBuffer,const uint8_t * pixels)359 angle::Result TextureGL::setSubImageRowByRowWorkaround(const gl::Context *context,
360                                                        gl::TextureTarget target,
361                                                        size_t level,
362                                                        const gl::Box &area,
363                                                        GLenum format,
364                                                        GLenum type,
365                                                        const gl::PixelUnpackState &unpack,
366                                                        const gl::Buffer *unpackBuffer,
367                                                        const uint8_t *pixels)
368 {
369     ContextGL *contextGL         = GetImplAs<ContextGL>(context);
370     const FunctionsGL *functions = GetFunctionsGL(context);
371     StateManagerGL *stateManager = GetStateManagerGL(context);
372 
373     gl::PixelUnpackState directUnpack;
374     directUnpack.alignment = 1;
375     stateManager->setPixelUnpackState(directUnpack);
376     stateManager->setPixelUnpackBuffer(unpackBuffer);
377 
378     const gl::InternalFormat &glFormat = gl::GetInternalFormatInfo(format, type);
379     GLuint rowBytes                    = 0;
380     ANGLE_CHECK_GL_MATH(contextGL, glFormat.computeRowPitch(type, area.width, unpack.alignment,
381                                                             unpack.rowLength, &rowBytes));
382     GLuint imageBytes = 0;
383     ANGLE_CHECK_GL_MATH(contextGL, glFormat.computeDepthPitch(area.height, unpack.imageHeight,
384                                                               rowBytes, &imageBytes));
385 
386     bool useTexImage3D = nativegl::UseTexImage3D(getType());
387     GLuint skipBytes   = 0;
388     ANGLE_CHECK_GL_MATH(contextGL, glFormat.computeSkipBytes(type, rowBytes, imageBytes, unpack,
389                                                              useTexImage3D, &skipBytes));
390 
391     const uint8_t *pixelsWithSkip = pixels + skipBytes;
392     if (useTexImage3D)
393     {
394         for (GLint image = 0; image < area.depth; ++image)
395         {
396             GLint imageByteOffset = image * imageBytes;
397             for (GLint row = 0; row < area.height; ++row)
398             {
399                 GLint byteOffset         = imageByteOffset + row * rowBytes;
400                 const GLubyte *rowPixels = pixelsWithSkip + byteOffset;
401                 ANGLE_GL_TRY(context,
402                              functions->texSubImage3D(ToGLenum(target), static_cast<GLint>(level),
403                                                       area.x, row + area.y, image + area.z,
404                                                       area.width, 1, 1, format, type, rowPixels));
405             }
406         }
407     }
408     else
409     {
410         ASSERT(nativegl::UseTexImage2D(getType()));
411         for (GLint row = 0; row < area.height; ++row)
412         {
413             GLint byteOffset         = row * rowBytes;
414             const GLubyte *rowPixels = pixelsWithSkip + byteOffset;
415             ANGLE_GL_TRY(context, functions->texSubImage2D(
416                                       ToGLenum(target), static_cast<GLint>(level), area.x,
417                                       row + area.y, area.width, 1, format, type, rowPixels));
418         }
419     }
420     return angle::Result::Continue;
421 }
422 
setSubImagePaddingWorkaround(const gl::Context * context,gl::TextureTarget target,size_t level,const gl::Box & area,GLenum format,GLenum type,const gl::PixelUnpackState & unpack,const gl::Buffer * unpackBuffer,const uint8_t * pixels)423 angle::Result TextureGL::setSubImagePaddingWorkaround(const gl::Context *context,
424                                                       gl::TextureTarget target,
425                                                       size_t level,
426                                                       const gl::Box &area,
427                                                       GLenum format,
428                                                       GLenum type,
429                                                       const gl::PixelUnpackState &unpack,
430                                                       const gl::Buffer *unpackBuffer,
431                                                       const uint8_t *pixels)
432 {
433     ContextGL *contextGL         = GetImplAs<ContextGL>(context);
434     const FunctionsGL *functions = GetFunctionsGL(context);
435     StateManagerGL *stateManager = GetStateManagerGL(context);
436 
437     const gl::InternalFormat &glFormat = gl::GetInternalFormatInfo(format, type);
438     GLuint rowBytes                    = 0;
439     ANGLE_CHECK_GL_MATH(contextGL, glFormat.computeRowPitch(type, area.width, unpack.alignment,
440                                                             unpack.rowLength, &rowBytes));
441     GLuint imageBytes = 0;
442     ANGLE_CHECK_GL_MATH(contextGL, glFormat.computeDepthPitch(area.height, unpack.imageHeight,
443                                                               rowBytes, &imageBytes));
444     bool useTexImage3D = nativegl::UseTexImage3D(getType());
445     GLuint skipBytes   = 0;
446     ANGLE_CHECK_GL_MATH(contextGL, glFormat.computeSkipBytes(type, rowBytes, imageBytes, unpack,
447                                                              useTexImage3D, &skipBytes));
448 
449     stateManager->setPixelUnpackState(unpack);
450     stateManager->setPixelUnpackBuffer(unpackBuffer);
451 
452     gl::PixelUnpackState directUnpack;
453     directUnpack.alignment = 1;
454 
455     if (useTexImage3D)
456     {
457         // Upload all but the last slice
458         if (area.depth > 1)
459         {
460             ANGLE_GL_TRY(context,
461                          functions->texSubImage3D(ToGLenum(target), static_cast<GLint>(level),
462                                                   area.x, area.y, area.z, area.width, area.height,
463                                                   area.depth - 1, format, type, pixels));
464         }
465 
466         // Upload the last slice but its last row
467         if (area.height > 1)
468         {
469             // Do not include skipBytes in the last image pixel start offset as it will be done by
470             // the driver
471             GLint lastImageOffset          = (area.depth - 1) * imageBytes;
472             const GLubyte *lastImagePixels = pixels + lastImageOffset;
473             ANGLE_GL_TRY(context, functions->texSubImage3D(
474                                       ToGLenum(target), static_cast<GLint>(level), area.x, area.y,
475                                       area.z + area.depth - 1, area.width, area.height - 1, 1,
476                                       format, type, lastImagePixels));
477         }
478 
479         // Upload the last row of the last slice "manually"
480         stateManager->setPixelUnpackState(directUnpack);
481 
482         GLint lastRowOffset =
483             skipBytes + (area.depth - 1) * imageBytes + (area.height - 1) * rowBytes;
484         const GLubyte *lastRowPixels = pixels + lastRowOffset;
485         ANGLE_GL_TRY(context,
486                      functions->texSubImage3D(ToGLenum(target), static_cast<GLint>(level), area.x,
487                                               area.y + area.height - 1, area.z + area.depth - 1,
488                                               area.width, 1, 1, format, type, lastRowPixels));
489     }
490     else
491     {
492         ASSERT(nativegl::UseTexImage2D(getType()));
493 
494         // Upload all but the last row
495         if (area.height > 1)
496         {
497             ANGLE_GL_TRY(context, functions->texSubImage2D(
498                                       ToGLenum(target), static_cast<GLint>(level), area.x, area.y,
499                                       area.width, area.height - 1, format, type, pixels));
500         }
501 
502         // Upload the last row "manually"
503         stateManager->setPixelUnpackState(directUnpack);
504 
505         GLint lastRowOffset          = skipBytes + (area.height - 1) * rowBytes;
506         const GLubyte *lastRowPixels = pixels + lastRowOffset;
507         ANGLE_GL_TRY(context, functions->texSubImage2D(ToGLenum(target), static_cast<GLint>(level),
508                                                        area.x, area.y + area.height - 1, area.width,
509                                                        1, format, type, lastRowPixels));
510     }
511 
512     return angle::Result::Continue;
513 }
514 
setCompressedImage(const gl::Context * context,const gl::ImageIndex & index,GLenum internalFormat,const gl::Extents & size,const gl::PixelUnpackState & unpack,size_t imageSize,const uint8_t * pixels)515 angle::Result TextureGL::setCompressedImage(const gl::Context *context,
516                                             const gl::ImageIndex &index,
517                                             GLenum internalFormat,
518                                             const gl::Extents &size,
519                                             const gl::PixelUnpackState &unpack,
520                                             size_t imageSize,
521                                             const uint8_t *pixels)
522 {
523     const FunctionsGL *functions      = GetFunctionsGL(context);
524     StateManagerGL *stateManager      = GetStateManagerGL(context);
525     const angle::FeaturesGL &features = GetFeaturesGL(context);
526 
527     gl::TextureTarget target = index.getTarget();
528     size_t level             = static_cast<size_t>(index.getLevelIndex());
529     ASSERT(TextureTargetToType(target) == getType());
530 
531     nativegl::CompressedTexImageFormat compressedTexImageFormat =
532         nativegl::GetCompressedTexImageFormat(functions, features, internalFormat);
533 
534     stateManager->bindTexture(getType(), mTextureID);
535     if (nativegl::UseTexImage2D(getType()))
536     {
537         ASSERT(size.depth == 1);
538         ANGLE_GL_TRY_ALWAYS_CHECK(
539             context, functions->compressedTexImage2D(ToGLenum(target), static_cast<GLint>(level),
540                                                      compressedTexImageFormat.internalFormat,
541                                                      size.width, size.height, 0,
542                                                      static_cast<GLsizei>(imageSize), pixels));
543     }
544     else
545     {
546         ASSERT(nativegl::UseTexImage3D(getType()));
547         ANGLE_GL_TRY_ALWAYS_CHECK(
548             context, functions->compressedTexImage3D(ToGLenum(target), static_cast<GLint>(level),
549                                                      compressedTexImageFormat.internalFormat,
550                                                      size.width, size.height, size.depth, 0,
551                                                      static_cast<GLsizei>(imageSize), pixels));
552     }
553 
554     LevelInfoGL levelInfo =
555         GetLevelInfo(features, internalFormat, compressedTexImageFormat.internalFormat);
556     ASSERT(!levelInfo.lumaWorkaround.enabled);
557     setLevelInfo(context, target, level, 1, levelInfo);
558 
559     return angle::Result::Continue;
560 }
561 
setCompressedSubImage(const gl::Context * context,const gl::ImageIndex & index,const gl::Box & area,GLenum format,const gl::PixelUnpackState & unpack,size_t imageSize,const uint8_t * pixels)562 angle::Result TextureGL::setCompressedSubImage(const gl::Context *context,
563                                                const gl::ImageIndex &index,
564                                                const gl::Box &area,
565                                                GLenum format,
566                                                const gl::PixelUnpackState &unpack,
567                                                size_t imageSize,
568                                                const uint8_t *pixels)
569 {
570     const FunctionsGL *functions      = GetFunctionsGL(context);
571     StateManagerGL *stateManager      = GetStateManagerGL(context);
572     const angle::FeaturesGL &features = GetFeaturesGL(context);
573 
574     gl::TextureTarget target = index.getTarget();
575     size_t level             = static_cast<size_t>(index.getLevelIndex());
576     ASSERT(TextureTargetToType(target) == getType());
577 
578     nativegl::CompressedTexSubImageFormat compressedTexSubImageFormat =
579         nativegl::GetCompressedSubTexImageFormat(functions, features, format);
580 
581     stateManager->bindTexture(getType(), mTextureID);
582     if (nativegl::UseTexImage2D(getType()))
583     {
584         ASSERT(area.z == 0 && area.depth == 1);
585         ANGLE_GL_TRY(context, functions->compressedTexSubImage2D(
586                                   ToGLenum(target), static_cast<GLint>(level), area.x, area.y,
587                                   area.width, area.height, compressedTexSubImageFormat.format,
588                                   static_cast<GLsizei>(imageSize), pixels));
589     }
590     else
591     {
592         ASSERT(nativegl::UseTexImage3D(getType()));
593         ANGLE_GL_TRY(context,
594                      functions->compressedTexSubImage3D(
595                          ToGLenum(target), static_cast<GLint>(level), area.x, area.y, area.z,
596                          area.width, area.height, area.depth, compressedTexSubImageFormat.format,
597                          static_cast<GLsizei>(imageSize), pixels));
598     }
599 
600     ASSERT(
601         !getLevelInfo(target, level).lumaWorkaround.enabled &&
602         !GetLevelInfo(features, format, compressedTexSubImageFormat.format).lumaWorkaround.enabled);
603 
604     return angle::Result::Continue;
605 }
606 
copyImage(const gl::Context * context,const gl::ImageIndex & index,const gl::Rectangle & sourceArea,GLenum internalFormat,gl::Framebuffer * source)607 angle::Result TextureGL::copyImage(const gl::Context *context,
608                                    const gl::ImageIndex &index,
609                                    const gl::Rectangle &sourceArea,
610                                    GLenum internalFormat,
611                                    gl::Framebuffer *source)
612 {
613     ContextGL *contextGL              = GetImplAs<ContextGL>(context);
614     const FunctionsGL *functions      = GetFunctionsGL(context);
615     StateManagerGL *stateManager      = GetStateManagerGL(context);
616     const angle::FeaturesGL &features = GetFeaturesGL(context);
617 
618     gl::TextureTarget target = index.getTarget();
619     size_t level             = static_cast<size_t>(index.getLevelIndex());
620     GLenum type              = source->getImplementationColorReadType(context);
621     nativegl::CopyTexImageImageFormat copyTexImageFormat =
622         nativegl::GetCopyTexImageImageFormat(functions, features, internalFormat, type);
623 
624     stateManager->bindTexture(getType(), mTextureID);
625 
626     const FramebufferGL *sourceFramebufferGL = GetImplAs<FramebufferGL>(source);
627     gl::Extents fbSize = sourceFramebufferGL->getState().getReadAttachment()->getSize();
628 
629     // Did the read area go outside the framebuffer?
630     bool outside = sourceArea.x < 0 || sourceArea.y < 0 ||
631                    sourceArea.x + sourceArea.width > fbSize.width ||
632                    sourceArea.y + sourceArea.height > fbSize.height;
633 
634     // TODO: Find a way to initialize the texture entirely in the gl level with ensureInitialized.
635     // Right now there is no easy way to pre-fill the texture when it is being redefined with
636     // partially uninitialized data.
637     bool requiresInitialization =
638         outside && (context->isRobustResourceInitEnabled() || context->isWebGL());
639 
640     // When robust resource initialization is enabled, the area outside the framebuffer must be
641     // zeroed. We just zero the whole thing before copying into the area that overlaps the
642     // framebuffer.
643     if (requiresInitialization)
644     {
645         GLuint pixelBytes =
646             gl::GetInternalFormatInfo(copyTexImageFormat.internalFormat, type).pixelBytes;
647         angle::MemoryBuffer *zero;
648         ANGLE_CHECK_GL_ALLOC(
649             contextGL,
650             context->getZeroFilledBuffer(sourceArea.width * sourceArea.height * pixelBytes, &zero));
651 
652         gl::PixelUnpackState unpack;
653         unpack.alignment = 1;
654         stateManager->setPixelUnpackState(unpack);
655         stateManager->setPixelUnpackBuffer(nullptr);
656 
657         ANGLE_GL_TRY_ALWAYS_CHECK(
658             context, functions->texImage2D(ToGLenum(target), static_cast<GLint>(level),
659                                            copyTexImageFormat.internalFormat, sourceArea.width,
660                                            sourceArea.height, 0,
661                                            gl::GetUnsizedFormat(copyTexImageFormat.internalFormat),
662                                            type, zero->data()));
663     }
664 
665     // Clip source area to framebuffer and copy if remaining area is not empty.
666     gl::Rectangle clippedArea;
667     if (ClipRectangle(sourceArea, gl::Rectangle(0, 0, fbSize.width, fbSize.height), &clippedArea))
668     {
669         // If fbo's read buffer and the target texture are the same texture but different levels,
670         // and if the read buffer is a non-base texture level, then implementations glTexImage2D
671         // may change the target texture and make the original texture mipmap incomplete, which in
672         // turn makes the fbo incomplete.
673         // To avoid that, we clamp BASE_LEVEL and MAX_LEVEL to the same texture level as the fbo's
674         // read buffer attachment. See http://crbug.com/797235
675         const gl::FramebufferAttachment *readBuffer = source->getReadColorAttachment();
676         if (readBuffer && readBuffer->type() == GL_TEXTURE)
677         {
678             TextureGL *sourceTexture = GetImplAs<TextureGL>(readBuffer->getTexture());
679             if (sourceTexture && sourceTexture->mTextureID == mTextureID)
680             {
681                 GLuint attachedTextureLevel = readBuffer->mipLevel();
682                 if (attachedTextureLevel != mState.getEffectiveBaseLevel())
683                 {
684                     ANGLE_TRY(setBaseLevel(context, attachedTextureLevel));
685                     ANGLE_TRY(setMaxLevel(context, attachedTextureLevel));
686                 }
687             }
688         }
689 
690         LevelInfoGL levelInfo =
691             GetLevelInfo(features, internalFormat, copyTexImageFormat.internalFormat);
692         gl::Offset destOffset(clippedArea.x - sourceArea.x, clippedArea.y - sourceArea.y, 0);
693 
694         if (levelInfo.lumaWorkaround.enabled)
695         {
696             BlitGL *blitter = GetBlitGL(context);
697 
698             if (requiresInitialization)
699             {
700                 ANGLE_TRY(blitter->copySubImageToLUMAWorkaroundTexture(
701                     context, mTextureID, getType(), target, levelInfo.sourceFormat, level,
702                     destOffset, clippedArea, source));
703             }
704             else
705             {
706                 ANGLE_TRY(blitter->copyImageToLUMAWorkaroundTexture(
707                     context, mTextureID, getType(), target, levelInfo.sourceFormat, level,
708                     clippedArea, copyTexImageFormat.internalFormat, source));
709             }
710         }
711         else
712         {
713             ASSERT(nativegl::UseTexImage2D(getType()));
714             stateManager->bindFramebuffer(GL_READ_FRAMEBUFFER,
715                                           sourceFramebufferGL->getFramebufferID());
716             if (features.emulateCopyTexImage2DFromRenderbuffers.enabled && readBuffer &&
717                 readBuffer->type() == GL_RENDERBUFFER)
718             {
719                 BlitGL *blitter = GetBlitGL(context);
720                 ANGLE_TRY(blitter->blitColorBufferWithShader(
721                     context, source, mTextureID, target, level, clippedArea,
722                     gl::Rectangle(destOffset.x, destOffset.y, clippedArea.width,
723                                   clippedArea.height),
724                     GL_NEAREST, true));
725             }
726             else if (requiresInitialization)
727             {
728                 ANGLE_GL_TRY(context, functions->copyTexSubImage2D(
729                                           ToGLenum(target), static_cast<GLint>(level), destOffset.x,
730                                           destOffset.y, clippedArea.x, clippedArea.y,
731                                           clippedArea.width, clippedArea.height));
732             }
733             else
734             {
735                 ANGLE_GL_TRY_ALWAYS_CHECK(
736                     context, functions->copyTexImage2D(ToGLenum(target), static_cast<GLint>(level),
737                                                        copyTexImageFormat.internalFormat,
738                                                        clippedArea.x, clippedArea.y,
739                                                        clippedArea.width, clippedArea.height, 0));
740             }
741         }
742         setLevelInfo(context, target, level, 1, levelInfo);
743     }
744 
745     if (features.flushBeforeDeleteTextureIfCopiedTo.enabled)
746     {
747         contextGL->setNeedsFlushBeforeDeleteTextures();
748     }
749 
750     return angle::Result::Continue;
751 }
752 
copySubImage(const gl::Context * context,const gl::ImageIndex & index,const gl::Offset & destOffset,const gl::Rectangle & sourceArea,gl::Framebuffer * source)753 angle::Result TextureGL::copySubImage(const gl::Context *context,
754                                       const gl::ImageIndex &index,
755                                       const gl::Offset &destOffset,
756                                       const gl::Rectangle &sourceArea,
757                                       gl::Framebuffer *source)
758 {
759     const FunctionsGL *functions      = GetFunctionsGL(context);
760     StateManagerGL *stateManager      = GetStateManagerGL(context);
761     const angle::FeaturesGL &features = GetFeaturesGL(context);
762 
763     gl::TextureTarget target                 = index.getTarget();
764     size_t level                             = static_cast<size_t>(index.getLevelIndex());
765     const FramebufferGL *sourceFramebufferGL = GetImplAs<FramebufferGL>(source);
766 
767     // Clip source area to framebuffer.
768     const gl::Extents fbSize = sourceFramebufferGL->getState().getReadAttachment()->getSize();
769     gl::Rectangle clippedArea;
770     if (!ClipRectangle(sourceArea, gl::Rectangle(0, 0, fbSize.width, fbSize.height), &clippedArea))
771     {
772         // nothing to do
773         return angle::Result::Continue;
774     }
775     gl::Offset clippedOffset(destOffset.x + clippedArea.x - sourceArea.x,
776                              destOffset.y + clippedArea.y - sourceArea.y, destOffset.z);
777 
778     stateManager->bindTexture(getType(), mTextureID);
779     stateManager->bindFramebuffer(GL_READ_FRAMEBUFFER, sourceFramebufferGL->getFramebufferID());
780 
781     const LevelInfoGL &levelInfo = getLevelInfo(target, level);
782     if (levelInfo.lumaWorkaround.enabled)
783     {
784         BlitGL *blitter = GetBlitGL(context);
785         ANGLE_TRY(blitter->copySubImageToLUMAWorkaroundTexture(
786             context, mTextureID, getType(), target, levelInfo.sourceFormat, level, clippedOffset,
787             clippedArea, source));
788     }
789     else
790     {
791         if (nativegl::UseTexImage2D(getType()))
792         {
793             ASSERT(clippedOffset.z == 0);
794             if (features.emulateCopyTexImage2DFromRenderbuffers.enabled &&
795                 source->getReadColorAttachment() &&
796                 source->getReadColorAttachment()->type() == GL_RENDERBUFFER)
797             {
798                 BlitGL *blitter = GetBlitGL(context);
799                 ANGLE_TRY(blitter->blitColorBufferWithShader(
800                     context, source, mTextureID, target, level, clippedArea,
801                     gl::Rectangle(clippedOffset.x, clippedOffset.y, clippedArea.width,
802                                   clippedArea.height),
803                     GL_NEAREST, true));
804             }
805             else
806             {
807                 ANGLE_GL_TRY(context, functions->copyTexSubImage2D(
808                                           ToGLenum(target), static_cast<GLint>(level),
809                                           clippedOffset.x, clippedOffset.y, clippedArea.x,
810                                           clippedArea.y, clippedArea.width, clippedArea.height));
811             }
812         }
813         else
814         {
815             ASSERT(nativegl::UseTexImage3D(getType()));
816             ANGLE_GL_TRY(context, functions->copyTexSubImage3D(
817                                       ToGLenum(target), static_cast<GLint>(level), clippedOffset.x,
818                                       clippedOffset.y, clippedOffset.z, clippedArea.x,
819                                       clippedArea.y, clippedArea.width, clippedArea.height));
820         }
821     }
822 
823     if (features.flushBeforeDeleteTextureIfCopiedTo.enabled)
824     {
825         ContextGL *contextGL = GetImplAs<ContextGL>(context);
826         contextGL->setNeedsFlushBeforeDeleteTextures();
827     }
828 
829     return angle::Result::Continue;
830 }
831 
copyTexture(const gl::Context * context,const gl::ImageIndex & index,GLenum internalFormat,GLenum type,size_t sourceLevel,bool unpackFlipY,bool unpackPremultiplyAlpha,bool unpackUnmultiplyAlpha,const gl::Texture * source)832 angle::Result TextureGL::copyTexture(const gl::Context *context,
833                                      const gl::ImageIndex &index,
834                                      GLenum internalFormat,
835                                      GLenum type,
836                                      size_t sourceLevel,
837                                      bool unpackFlipY,
838                                      bool unpackPremultiplyAlpha,
839                                      bool unpackUnmultiplyAlpha,
840                                      const gl::Texture *source)
841 {
842     gl::TextureTarget target  = index.getTarget();
843     size_t level              = static_cast<size_t>(index.getLevelIndex());
844     const TextureGL *sourceGL = GetImplAs<TextureGL>(source);
845     const gl::ImageDesc &sourceImageDesc =
846         sourceGL->mState.getImageDesc(NonCubeTextureTypeToTarget(source->getType()), sourceLevel);
847     gl::Rectangle sourceArea(0, 0, sourceImageDesc.size.width, sourceImageDesc.size.height);
848 
849     ANGLE_TRY(reserveTexImageToBeFilled(context, target, level, internalFormat,
850                                         sourceImageDesc.size, gl::GetUnsizedFormat(internalFormat),
851                                         type));
852 
853     const gl::InternalFormat &destFormatInfo = gl::GetInternalFormatInfo(internalFormat, type);
854     return copySubTextureHelper(context, target, level, gl::Offset(0, 0, 0), sourceLevel,
855                                 sourceArea, destFormatInfo, unpackFlipY, unpackPremultiplyAlpha,
856                                 unpackUnmultiplyAlpha, source);
857 }
858 
copySubTexture(const gl::Context * context,const gl::ImageIndex & index,const gl::Offset & destOffset,size_t sourceLevel,const gl::Box & sourceBox,bool unpackFlipY,bool unpackPremultiplyAlpha,bool unpackUnmultiplyAlpha,const gl::Texture * source)859 angle::Result TextureGL::copySubTexture(const gl::Context *context,
860                                         const gl::ImageIndex &index,
861                                         const gl::Offset &destOffset,
862                                         size_t sourceLevel,
863                                         const gl::Box &sourceBox,
864                                         bool unpackFlipY,
865                                         bool unpackPremultiplyAlpha,
866                                         bool unpackUnmultiplyAlpha,
867                                         const gl::Texture *source)
868 {
869     gl::TextureTarget target                 = index.getTarget();
870     size_t level                             = static_cast<size_t>(index.getLevelIndex());
871     const gl::InternalFormat &destFormatInfo = *mState.getImageDesc(target, level).format.info;
872     return copySubTextureHelper(context, target, level, destOffset, sourceLevel, sourceBox.toRect(),
873                                 destFormatInfo, unpackFlipY, unpackPremultiplyAlpha,
874                                 unpackUnmultiplyAlpha, source);
875 }
876 
copySubTextureHelper(const gl::Context * context,gl::TextureTarget target,size_t level,const gl::Offset & destOffset,size_t sourceLevel,const gl::Rectangle & sourceArea,const gl::InternalFormat & destFormat,bool unpackFlipY,bool unpackPremultiplyAlpha,bool unpackUnmultiplyAlpha,const gl::Texture * source)877 angle::Result TextureGL::copySubTextureHelper(const gl::Context *context,
878                                               gl::TextureTarget target,
879                                               size_t level,
880                                               const gl::Offset &destOffset,
881                                               size_t sourceLevel,
882                                               const gl::Rectangle &sourceArea,
883                                               const gl::InternalFormat &destFormat,
884                                               bool unpackFlipY,
885                                               bool unpackPremultiplyAlpha,
886                                               bool unpackUnmultiplyAlpha,
887                                               const gl::Texture *source)
888 {
889     const FunctionsGL *functions      = GetFunctionsGL(context);
890     const angle::FeaturesGL &features = GetFeaturesGL(context);
891     BlitGL *blitter                   = GetBlitGL(context);
892 
893     TextureGL *sourceGL = GetImplAs<TextureGL>(source);
894     const gl::ImageDesc &sourceImageDesc =
895         sourceGL->mState.getImageDesc(NonCubeTextureTypeToTarget(source->getType()), sourceLevel);
896 
897     if (features.flushBeforeDeleteTextureIfCopiedTo.enabled)
898     {
899         // Conservatively indicate that this workaround is necessary. Not clear
900         // if it is on this code path, but added for symmetry.
901         ContextGL *contextGL = GetImplAs<ContextGL>(context);
902         contextGL->setNeedsFlushBeforeDeleteTextures();
903     }
904 
905     // Check is this is a simple copySubTexture that can be done with a copyTexSubImage
906     ASSERT(sourceGL->getType() == gl::TextureType::_2D ||
907            source->getType() == gl::TextureType::External ||
908            source->getType() == gl::TextureType::Rectangle);
909     const LevelInfoGL &sourceLevelInfo =
910         sourceGL->getLevelInfo(NonCubeTextureTypeToTarget(source->getType()), sourceLevel);
911     bool needsLumaWorkaround = sourceLevelInfo.lumaWorkaround.enabled;
912 
913     const gl::InternalFormat &sourceFormatInfo = *sourceImageDesc.format.info;
914     GLenum sourceFormat                        = sourceFormatInfo.format;
915     bool sourceFormatContainSupersetOfDestFormat =
916         (sourceFormat == destFormat.format && sourceFormat != GL_BGRA_EXT) ||
917         (sourceFormat == GL_RGBA && destFormat.format == GL_RGB);
918 
919     GLenum sourceComponentType = sourceFormatInfo.componentType;
920     GLenum destComponentType   = destFormat.componentType;
921     bool destSRGB              = destFormat.colorEncoding == GL_SRGB;
922     if (!unpackFlipY && unpackPremultiplyAlpha == unpackUnmultiplyAlpha && !needsLumaWorkaround &&
923         sourceFormatContainSupersetOfDestFormat && sourceComponentType == destComponentType &&
924         !destSRGB && sourceGL->getType() == gl::TextureType::_2D)
925     {
926         bool copySucceeded = false;
927         ANGLE_TRY(blitter->copyTexSubImage(context, sourceGL, sourceLevel, this, target, level,
928                                            sourceArea, destOffset, &copySucceeded));
929         if (copySucceeded)
930         {
931             return angle::Result::Continue;
932         }
933     }
934 
935     // Check if the destination is renderable and copy on the GPU
936     const LevelInfoGL &destLevelInfo = getLevelInfo(target, level);
937     // todo(jonahr): http://crbug.com/773861
938     // Behavior for now is to fallback to CPU readback implementation if the destination texture
939     // is a luminance format. The correct solution is to handle both source and destination in the
940     // luma workaround.
941     if (!destSRGB && !destLevelInfo.lumaWorkaround.enabled &&
942         nativegl::SupportsNativeRendering(functions, getType(), destLevelInfo.nativeInternalFormat))
943     {
944         bool copySucceeded = false;
945         ANGLE_TRY(blitter->copySubTexture(
946             context, sourceGL, sourceLevel, sourceComponentType, mTextureID, target, level,
947             destComponentType, sourceImageDesc.size, sourceArea, destOffset, needsLumaWorkaround,
948             sourceLevelInfo.sourceFormat, unpackFlipY, unpackPremultiplyAlpha,
949             unpackUnmultiplyAlpha, &copySucceeded));
950         if (copySucceeded)
951         {
952             return angle::Result::Continue;
953         }
954     }
955 
956     // Fall back to CPU-readback
957     return blitter->copySubTextureCPUReadback(
958         context, sourceGL, sourceLevel, sourceFormatInfo.sizedInternalFormat, this, target, level,
959         destFormat.format, destFormat.type, sourceImageDesc.size, sourceArea, destOffset,
960         needsLumaWorkaround, sourceLevelInfo.sourceFormat, unpackFlipY, unpackPremultiplyAlpha,
961         unpackUnmultiplyAlpha);
962 }
963 
setStorage(const gl::Context * context,gl::TextureType type,size_t levels,GLenum internalFormat,const gl::Extents & size)964 angle::Result TextureGL::setStorage(const gl::Context *context,
965                                     gl::TextureType type,
966                                     size_t levels,
967                                     GLenum internalFormat,
968                                     const gl::Extents &size)
969 {
970     ContextGL *contextGL              = GetImplAs<ContextGL>(context);
971     const FunctionsGL *functions      = GetFunctionsGL(context);
972     StateManagerGL *stateManager      = GetStateManagerGL(context);
973     const angle::FeaturesGL &features = GetFeaturesGL(context);
974 
975     nativegl::TexStorageFormat texStorageFormat =
976         nativegl::GetTexStorageFormat(functions, features, internalFormat);
977 
978     stateManager->bindTexture(getType(), mTextureID);
979     if (nativegl::UseTexImage2D(getType()))
980     {
981         ASSERT(size.depth == 1);
982         if (functions->texStorage2D)
983         {
984             ANGLE_GL_TRY_ALWAYS_CHECK(
985                 context,
986                 functions->texStorage2D(ToGLenum(type), static_cast<GLsizei>(levels),
987                                         texStorageFormat.internalFormat, size.width, size.height));
988         }
989         else
990         {
991             // Make sure no pixel unpack buffer is bound
992             stateManager->bindBuffer(gl::BufferBinding::PixelUnpack, 0);
993 
994             const gl::InternalFormat &internalFormatInfo =
995                 gl::GetSizedInternalFormatInfo(internalFormat);
996 
997             // Internal format must be sized
998             ASSERT(internalFormatInfo.sized);
999 
1000             for (size_t level = 0; level < levels; level++)
1001             {
1002                 gl::Extents levelSize(std::max(size.width >> level, 1),
1003                                       std::max(size.height >> level, 1), 1);
1004 
1005                 if (getType() == gl::TextureType::_2D || getType() == gl::TextureType::Rectangle)
1006                 {
1007                     if (internalFormatInfo.compressed)
1008                     {
1009                         nativegl::CompressedTexSubImageFormat compressedTexImageFormat =
1010                             nativegl::GetCompressedSubTexImageFormat(functions, features,
1011                                                                      internalFormat);
1012 
1013                         GLuint dataSize = 0;
1014                         ANGLE_CHECK_GL_MATH(
1015                             contextGL,
1016                             internalFormatInfo.computeCompressedImageSize(levelSize, &dataSize));
1017                         ANGLE_GL_TRY_ALWAYS_CHECK(
1018                             context,
1019                             functions->compressedTexImage2D(
1020                                 ToGLenum(type), static_cast<GLint>(level),
1021                                 compressedTexImageFormat.format, levelSize.width, levelSize.height,
1022                                 0, static_cast<GLsizei>(dataSize), nullptr));
1023                     }
1024                     else
1025                     {
1026                         nativegl::TexImageFormat texImageFormat = nativegl::GetTexImageFormat(
1027                             functions, features, internalFormat, internalFormatInfo.format,
1028                             internalFormatInfo.type);
1029 
1030                         ANGLE_GL_TRY_ALWAYS_CHECK(
1031                             context,
1032                             functions->texImage2D(ToGLenum(type), static_cast<GLint>(level),
1033                                                   texImageFormat.internalFormat, levelSize.width,
1034                                                   levelSize.height, 0, texImageFormat.format,
1035                                                   texImageFormat.type, nullptr));
1036                     }
1037                 }
1038                 else
1039                 {
1040                     ASSERT(getType() == gl::TextureType::CubeMap);
1041                     for (gl::TextureTarget face : gl::AllCubeFaceTextureTargets())
1042                     {
1043                         if (internalFormatInfo.compressed)
1044                         {
1045                             nativegl::CompressedTexSubImageFormat compressedTexImageFormat =
1046                                 nativegl::GetCompressedSubTexImageFormat(functions, features,
1047                                                                          internalFormat);
1048 
1049                             GLuint dataSize = 0;
1050                             ANGLE_CHECK_GL_MATH(contextGL,
1051                                                 internalFormatInfo.computeCompressedImageSize(
1052                                                     levelSize, &dataSize));
1053                             ANGLE_GL_TRY_ALWAYS_CHECK(
1054                                 context,
1055                                 functions->compressedTexImage2D(
1056                                     ToGLenum(face), static_cast<GLint>(level),
1057                                     compressedTexImageFormat.format, levelSize.width,
1058                                     levelSize.height, 0, static_cast<GLsizei>(dataSize), nullptr));
1059                         }
1060                         else
1061                         {
1062                             nativegl::TexImageFormat texImageFormat = nativegl::GetTexImageFormat(
1063                                 functions, features, internalFormat, internalFormatInfo.format,
1064                                 internalFormatInfo.type);
1065 
1066                             ANGLE_GL_TRY_ALWAYS_CHECK(
1067                                 context, functions->texImage2D(
1068                                              ToGLenum(face), static_cast<GLint>(level),
1069                                              texImageFormat.internalFormat, levelSize.width,
1070                                              levelSize.height, 0, texImageFormat.format,
1071                                              texImageFormat.type, nullptr));
1072                         }
1073                     }
1074                 }
1075             }
1076         }
1077     }
1078     else
1079     {
1080         ASSERT(nativegl::UseTexImage3D(getType()));
1081         if (functions->texStorage3D)
1082         {
1083             ANGLE_GL_TRY_ALWAYS_CHECK(
1084                 context, functions->texStorage3D(ToGLenum(type), static_cast<GLsizei>(levels),
1085                                                  texStorageFormat.internalFormat, size.width,
1086                                                  size.height, size.depth));
1087         }
1088         else
1089         {
1090             // Make sure no pixel unpack buffer is bound
1091             stateManager->bindBuffer(gl::BufferBinding::PixelUnpack, 0);
1092 
1093             const gl::InternalFormat &internalFormatInfo =
1094                 gl::GetSizedInternalFormatInfo(internalFormat);
1095 
1096             // Internal format must be sized
1097             ASSERT(internalFormatInfo.sized);
1098 
1099             for (GLsizei i = 0; i < static_cast<GLsizei>(levels); i++)
1100             {
1101                 gl::Extents levelSize(
1102                     std::max(size.width >> i, 1), std::max(size.height >> i, 1),
1103                     getType() == gl::TextureType::_3D ? std::max(size.depth >> i, 1) : size.depth);
1104 
1105                 if (internalFormatInfo.compressed)
1106                 {
1107                     nativegl::CompressedTexSubImageFormat compressedTexImageFormat =
1108                         nativegl::GetCompressedSubTexImageFormat(functions, features,
1109                                                                  internalFormat);
1110 
1111                     GLuint dataSize = 0;
1112                     ANGLE_CHECK_GL_MATH(contextGL, internalFormatInfo.computeCompressedImageSize(
1113                                                        levelSize, &dataSize));
1114                     ANGLE_GL_TRY_ALWAYS_CHECK(
1115                         context, functions->compressedTexImage3D(
1116                                      ToGLenum(type), i, compressedTexImageFormat.format,
1117                                      levelSize.width, levelSize.height, levelSize.depth, 0,
1118                                      static_cast<GLsizei>(dataSize), nullptr));
1119                 }
1120                 else
1121                 {
1122                     nativegl::TexImageFormat texImageFormat = nativegl::GetTexImageFormat(
1123                         functions, features, internalFormat, internalFormatInfo.format,
1124                         internalFormatInfo.type);
1125 
1126                     ANGLE_GL_TRY_ALWAYS_CHECK(
1127                         context,
1128                         functions->texImage3D(ToGLenum(type), i, texImageFormat.internalFormat,
1129                                               levelSize.width, levelSize.height, levelSize.depth, 0,
1130                                               texImageFormat.format, texImageFormat.type, nullptr));
1131                 }
1132             }
1133         }
1134     }
1135 
1136     setLevelInfo(context, type, 0, levels,
1137                  GetLevelInfo(features, internalFormat, texStorageFormat.internalFormat));
1138 
1139     return angle::Result::Continue;
1140 }
1141 
setImageExternal(const gl::Context * context,const gl::ImageIndex & index,GLenum internalFormat,const gl::Extents & size,GLenum format,GLenum type)1142 angle::Result TextureGL::setImageExternal(const gl::Context *context,
1143                                           const gl::ImageIndex &index,
1144                                           GLenum internalFormat,
1145                                           const gl::Extents &size,
1146                                           GLenum format,
1147                                           GLenum type)
1148 {
1149     const FunctionsGL *functions      = GetFunctionsGL(context);
1150     const angle::FeaturesGL &features = GetFeaturesGL(context);
1151 
1152     gl::TextureTarget target = index.getTarget();
1153     size_t level             = static_cast<size_t>(index.getLevelIndex());
1154     nativegl::TexImageFormat texImageFormat =
1155         nativegl::GetTexImageFormat(functions, features, internalFormat, format, type);
1156 
1157     setLevelInfo(context, target, level, 1,
1158                  GetLevelInfo(features, internalFormat, texImageFormat.internalFormat));
1159     return angle::Result::Continue;
1160 }
1161 
setStorageMultisample(const gl::Context * context,gl::TextureType type,GLsizei samples,GLint internalformat,const gl::Extents & size,bool fixedSampleLocations)1162 angle::Result TextureGL::setStorageMultisample(const gl::Context *context,
1163                                                gl::TextureType type,
1164                                                GLsizei samples,
1165                                                GLint internalformat,
1166                                                const gl::Extents &size,
1167                                                bool fixedSampleLocations)
1168 {
1169     const FunctionsGL *functions      = GetFunctionsGL(context);
1170     StateManagerGL *stateManager      = GetStateManagerGL(context);
1171     const angle::FeaturesGL &features = GetFeaturesGL(context);
1172 
1173     nativegl::TexStorageFormat texStorageFormat =
1174         nativegl::GetTexStorageFormat(functions, features, internalformat);
1175 
1176     stateManager->bindTexture(getType(), mTextureID);
1177 
1178     if (nativegl::UseTexImage2D(getType()))
1179     {
1180         ASSERT(size.depth == 1);
1181         if (functions->texStorage2DMultisample)
1182         {
1183             ANGLE_GL_TRY_ALWAYS_CHECK(
1184                 context, functions->texStorage2DMultisample(
1185                              ToGLenum(type), samples, texStorageFormat.internalFormat, size.width,
1186                              size.height, gl::ConvertToGLBoolean(fixedSampleLocations)));
1187         }
1188         else
1189         {
1190             // texImage2DMultisample is similar to texStorage2DMultisample of es 3.1 core feature,
1191             // On macos and some old drivers which doesn't support OpenGL ES 3.1, the function can
1192             // be supported by ARB_texture_multisample or OpenGL 3.2 core feature.
1193             ANGLE_GL_TRY_ALWAYS_CHECK(
1194                 context, functions->texImage2DMultisample(
1195                              ToGLenum(type), samples, texStorageFormat.internalFormat, size.width,
1196                              size.height, gl::ConvertToGLBoolean(fixedSampleLocations)));
1197         }
1198     }
1199     else
1200     {
1201         ASSERT(nativegl::UseTexImage3D(getType()));
1202         ANGLE_GL_TRY_ALWAYS_CHECK(
1203             context, functions->texStorage3DMultisample(
1204                          ToGLenum(type), samples, texStorageFormat.internalFormat, size.width,
1205                          size.height, size.depth, gl::ConvertToGLBoolean(fixedSampleLocations)));
1206     }
1207 
1208     setLevelInfo(context, type, 0, 1,
1209                  GetLevelInfo(features, internalformat, texStorageFormat.internalFormat));
1210 
1211     return angle::Result::Continue;
1212 }
1213 
setStorageExternalMemory(const gl::Context * context,gl::TextureType type,size_t levels,GLenum internalFormat,const gl::Extents & size,gl::MemoryObject * memoryObject,GLuint64 offset)1214 angle::Result TextureGL::setStorageExternalMemory(const gl::Context *context,
1215                                                   gl::TextureType type,
1216                                                   size_t levels,
1217                                                   GLenum internalFormat,
1218                                                   const gl::Extents &size,
1219                                                   gl::MemoryObject *memoryObject,
1220                                                   GLuint64 offset)
1221 {
1222     const FunctionsGL *functions      = GetFunctionsGL(context);
1223     StateManagerGL *stateManager      = GetStateManagerGL(context);
1224     const angle::FeaturesGL &features = GetFeaturesGL(context);
1225 
1226     MemoryObjectGL *memoryObjectGL = GetImplAs<MemoryObjectGL>(memoryObject);
1227 
1228     nativegl::TexStorageFormat texStorageFormat =
1229         nativegl::GetTexStorageFormat(functions, features, internalFormat);
1230 
1231     stateManager->bindTexture(getType(), mTextureID);
1232     if (nativegl::UseTexImage2D(getType()))
1233     {
1234         ANGLE_GL_TRY_ALWAYS_CHECK(
1235             context,
1236             functions->texStorageMem2DEXT(ToGLenum(type), static_cast<GLsizei>(levels),
1237                                           texStorageFormat.internalFormat, size.width, size.height,
1238                                           memoryObjectGL->getMemoryObjectID(), offset));
1239     }
1240     else
1241     {
1242         ASSERT(nativegl::UseTexImage3D(getType()));
1243         ANGLE_GL_TRY_ALWAYS_CHECK(
1244             context,
1245             functions->texStorageMem3DEXT(ToGLenum(type), static_cast<GLsizei>(levels),
1246                                           texStorageFormat.internalFormat, size.width, size.height,
1247                                           size.depth, memoryObjectGL->getMemoryObjectID(), offset));
1248     }
1249 
1250     setLevelInfo(context, type, 0, levels,
1251                  GetLevelInfo(features, internalFormat, texStorageFormat.internalFormat));
1252 
1253     return angle::Result::Continue;
1254 }
1255 
setImageExternal(const gl::Context * context,gl::TextureType type,egl::Stream * stream,const egl::Stream::GLTextureDescription & desc)1256 angle::Result TextureGL::setImageExternal(const gl::Context *context,
1257                                           gl::TextureType type,
1258                                           egl::Stream *stream,
1259                                           const egl::Stream::GLTextureDescription &desc)
1260 {
1261     ANGLE_GL_UNREACHABLE(GetImplAs<ContextGL>(context));
1262     return angle::Result::Stop;
1263 }
1264 
generateMipmap(const gl::Context * context)1265 angle::Result TextureGL::generateMipmap(const gl::Context *context)
1266 {
1267     const FunctionsGL *functions      = GetFunctionsGL(context);
1268     StateManagerGL *stateManager      = GetStateManagerGL(context);
1269     const angle::FeaturesGL &features = GetFeaturesGL(context);
1270 
1271     const GLuint effectiveBaseLevel = mState.getEffectiveBaseLevel();
1272     const GLuint maxLevel           = mState.getMipmapMaxLevel();
1273 
1274     const gl::ImageDesc &baseLevelDesc                = mState.getBaseLevelDesc();
1275     const gl::InternalFormat &baseLevelInternalFormat = *baseLevelDesc.format.info;
1276 
1277     stateManager->bindTexture(getType(), mTextureID);
1278     if (baseLevelInternalFormat.colorEncoding == GL_SRGB &&
1279         features.encodeAndDecodeSRGBForGenerateMipmap.enabled && getType() == gl::TextureType::_2D)
1280     {
1281         nativegl::TexImageFormat texImageFormat = nativegl::GetTexImageFormat(
1282             functions, features, baseLevelInternalFormat.internalFormat,
1283             baseLevelInternalFormat.format, baseLevelInternalFormat.type);
1284 
1285         // Manually allocate the mip levels of this texture if they don't exist
1286         GLuint levelCount = maxLevel - effectiveBaseLevel + 1;
1287         for (GLuint levelIdx = 1; levelIdx < levelCount; levelIdx++)
1288         {
1289             gl::Extents levelSize(std::max(baseLevelDesc.size.width >> levelIdx, 1),
1290                                   std::max(baseLevelDesc.size.height >> levelIdx, 1), 1);
1291 
1292             const gl::ImageDesc &levelDesc =
1293                 mState.getImageDesc(gl::TextureTarget::_2D, effectiveBaseLevel + levelIdx);
1294 
1295             // Make sure no pixel unpack buffer is bound
1296             stateManager->bindBuffer(gl::BufferBinding::PixelUnpack, 0);
1297 
1298             if (levelDesc.size != levelSize || *levelDesc.format.info != baseLevelInternalFormat)
1299             {
1300                 ANGLE_GL_TRY_ALWAYS_CHECK(
1301                     context, functions->texImage2D(
1302                                  ToGLenum(getType()), effectiveBaseLevel + levelIdx,
1303                                  texImageFormat.internalFormat, levelSize.width, levelSize.height,
1304                                  0, texImageFormat.format, texImageFormat.type, nullptr));
1305             }
1306         }
1307 
1308         // Use the blitter to generate the mips
1309         BlitGL *blitter = GetBlitGL(context);
1310         ANGLE_TRY(blitter->generateSRGBMipmap(context, this, effectiveBaseLevel, levelCount,
1311                                               baseLevelDesc.size));
1312     }
1313     else
1314     {
1315         ANGLE_GL_TRY_ALWAYS_CHECK(context, functions->generateMipmap(ToGLenum(getType())));
1316     }
1317 
1318     setLevelInfo(context, getType(), effectiveBaseLevel, maxLevel - effectiveBaseLevel,
1319                  getBaseLevelInfo());
1320 
1321     return angle::Result::Continue;
1322 }
1323 
bindTexImage(const gl::Context * context,egl::Surface * surface)1324 angle::Result TextureGL::bindTexImage(const gl::Context *context, egl::Surface *surface)
1325 {
1326     ASSERT(getType() == gl::TextureType::_2D || getType() == gl::TextureType::Rectangle);
1327 
1328     StateManagerGL *stateManager = GetStateManagerGL(context);
1329 
1330     // Make sure this texture is bound
1331     stateManager->bindTexture(getType(), mTextureID);
1332 
1333     SurfaceGL *surfaceGL = GetImplAs<SurfaceGL>(surface);
1334 
1335     setLevelInfo(context, getType(), 0, 1,
1336                  LevelInfoGL(GL_NONE, GL_NONE, false, LUMAWorkaroundGL(),
1337                              surfaceGL->hasEmulatedAlphaChannel()));
1338     return angle::Result::Continue;
1339 }
1340 
releaseTexImage(const gl::Context * context)1341 angle::Result TextureGL::releaseTexImage(const gl::Context *context)
1342 {
1343     ASSERT(getType() == gl::TextureType::_2D || getType() == gl::TextureType::Rectangle);
1344 
1345     const angle::FeaturesGL &features = GetFeaturesGL(context);
1346     if (!features.resettingTexturesGeneratesErrors.enabled)
1347     {
1348         // Not all Surface implementations reset the size of mip 0 when releasing, do it manually
1349         const FunctionsGL *functions = GetFunctionsGL(context);
1350         StateManagerGL *stateManager = GetStateManagerGL(context);
1351 
1352         stateManager->bindTexture(getType(), mTextureID);
1353         ASSERT(nativegl::UseTexImage2D(getType()));
1354         ANGLE_GL_TRY(context, functions->texImage2D(ToGLenum(getType()), 0, GL_RGBA, 0, 0, 0,
1355                                                     GL_RGBA, GL_UNSIGNED_BYTE, nullptr));
1356     }
1357 
1358     return angle::Result::Continue;
1359 }
1360 
setEGLImageTarget(const gl::Context * context,gl::TextureType type,egl::Image * image)1361 angle::Result TextureGL::setEGLImageTarget(const gl::Context *context,
1362                                            gl::TextureType type,
1363                                            egl::Image *image)
1364 {
1365     const angle::FeaturesGL &features = GetFeaturesGL(context);
1366 
1367     ImageGL *imageGL = GetImplAs<ImageGL>(image);
1368 
1369     GLenum imageNativeInternalFormat = GL_NONE;
1370     ANGLE_TRY(imageGL->setTexture2D(context, type, this, &imageNativeInternalFormat));
1371 
1372     setLevelInfo(
1373         context, type, 0, 1,
1374         GetLevelInfo(features, image->getFormat().info->internalFormat, imageNativeInternalFormat));
1375 
1376     return angle::Result::Continue;
1377 }
1378 
getNativeID() const1379 GLint TextureGL::getNativeID() const
1380 {
1381     return mTextureID;
1382 }
1383 
syncState(const gl::Context * context,const gl::Texture::DirtyBits & dirtyBits)1384 angle::Result TextureGL::syncState(const gl::Context *context,
1385                                    const gl::Texture::DirtyBits &dirtyBits)
1386 {
1387     if (dirtyBits.none() && mLocalDirtyBits.none())
1388     {
1389         return angle::Result::Continue;
1390     }
1391 
1392     const FunctionsGL *functions = GetFunctionsGL(context);
1393     StateManagerGL *stateManager = GetStateManagerGL(context);
1394 
1395     stateManager->bindTexture(getType(), mTextureID);
1396 
1397     if (dirtyBits[gl::Texture::DIRTY_BIT_BASE_LEVEL] || dirtyBits[gl::Texture::DIRTY_BIT_MAX_LEVEL])
1398     {
1399         // Don't know if the previous base level was using any workarounds, always re-sync the
1400         // workaround dirty bits
1401         mLocalDirtyBits |= GetLevelWorkaroundDirtyBits();
1402     }
1403     for (auto dirtyBit : (dirtyBits | mLocalDirtyBits))
1404     {
1405 
1406         switch (dirtyBit)
1407         {
1408             case gl::Texture::DIRTY_BIT_MIN_FILTER:
1409                 mAppliedSampler.setMinFilter(mState.getSamplerState().getMinFilter());
1410                 ANGLE_GL_TRY(context, functions->texParameteri(
1411                                           nativegl::GetTextureBindingTarget(getType()),
1412                                           GL_TEXTURE_MIN_FILTER, mAppliedSampler.getMinFilter()));
1413                 break;
1414             case gl::Texture::DIRTY_BIT_MAG_FILTER:
1415                 mAppliedSampler.setMagFilter(mState.getSamplerState().getMagFilter());
1416                 ANGLE_GL_TRY(context, functions->texParameteri(
1417                                           nativegl::GetTextureBindingTarget(getType()),
1418                                           GL_TEXTURE_MAG_FILTER, mAppliedSampler.getMagFilter()));
1419                 break;
1420             case gl::Texture::DIRTY_BIT_WRAP_S:
1421                 mAppliedSampler.setWrapS(mState.getSamplerState().getWrapS());
1422                 ANGLE_GL_TRY(context, functions->texParameteri(
1423                                           nativegl::GetTextureBindingTarget(getType()),
1424                                           GL_TEXTURE_WRAP_S, mAppliedSampler.getWrapS()));
1425                 break;
1426             case gl::Texture::DIRTY_BIT_WRAP_T:
1427                 mAppliedSampler.setWrapT(mState.getSamplerState().getWrapT());
1428                 ANGLE_GL_TRY(context, functions->texParameteri(
1429                                           nativegl::GetTextureBindingTarget(getType()),
1430                                           GL_TEXTURE_WRAP_T, mAppliedSampler.getWrapT()));
1431                 break;
1432             case gl::Texture::DIRTY_BIT_WRAP_R:
1433                 mAppliedSampler.setWrapR(mState.getSamplerState().getWrapR());
1434                 ANGLE_GL_TRY(context, functions->texParameteri(
1435                                           nativegl::GetTextureBindingTarget(getType()),
1436                                           GL_TEXTURE_WRAP_R, mAppliedSampler.getWrapR()));
1437                 break;
1438             case gl::Texture::DIRTY_BIT_MAX_ANISOTROPY:
1439                 mAppliedSampler.setMaxAnisotropy(mState.getSamplerState().getMaxAnisotropy());
1440                 ANGLE_GL_TRY(context,
1441                              functions->texParameterf(nativegl::GetTextureBindingTarget(getType()),
1442                                                       GL_TEXTURE_MAX_ANISOTROPY_EXT,
1443                                                       mAppliedSampler.getMaxAnisotropy()));
1444                 break;
1445             case gl::Texture::DIRTY_BIT_MIN_LOD:
1446                 mAppliedSampler.setMinLod(mState.getSamplerState().getMinLod());
1447                 ANGLE_GL_TRY(context, functions->texParameterf(
1448                                           nativegl::GetTextureBindingTarget(getType()),
1449                                           GL_TEXTURE_MIN_LOD, mAppliedSampler.getMinLod()));
1450                 break;
1451             case gl::Texture::DIRTY_BIT_MAX_LOD:
1452                 mAppliedSampler.setMaxLod(mState.getSamplerState().getMaxLod());
1453                 ANGLE_GL_TRY(context, functions->texParameterf(
1454                                           nativegl::GetTextureBindingTarget(getType()),
1455                                           GL_TEXTURE_MAX_LOD, mAppliedSampler.getMaxLod()));
1456                 break;
1457             case gl::Texture::DIRTY_BIT_COMPARE_MODE:
1458                 mAppliedSampler.setCompareMode(mState.getSamplerState().getCompareMode());
1459                 ANGLE_GL_TRY(context,
1460                              functions->texParameteri(nativegl::GetTextureBindingTarget(getType()),
1461                                                       GL_TEXTURE_COMPARE_MODE,
1462                                                       mAppliedSampler.getCompareMode()));
1463                 break;
1464             case gl::Texture::DIRTY_BIT_COMPARE_FUNC:
1465                 mAppliedSampler.setCompareFunc(mState.getSamplerState().getCompareFunc());
1466                 ANGLE_GL_TRY(context,
1467                              functions->texParameteri(nativegl::GetTextureBindingTarget(getType()),
1468                                                       GL_TEXTURE_COMPARE_FUNC,
1469                                                       mAppliedSampler.getCompareFunc()));
1470                 break;
1471             case gl::Texture::DIRTY_BIT_SRGB_DECODE:
1472                 mAppliedSampler.setSRGBDecode(mState.getSamplerState().getSRGBDecode());
1473                 ANGLE_GL_TRY(context,
1474                              functions->texParameteri(nativegl::GetTextureBindingTarget(getType()),
1475                                                       GL_TEXTURE_SRGB_DECODE_EXT,
1476                                                       mAppliedSampler.getSRGBDecode()));
1477                 break;
1478             case gl::Texture::DIRTY_BIT_BORDER_COLOR:
1479             {
1480                 const angle::ColorGeneric &borderColor(mState.getSamplerState().getBorderColor());
1481                 mAppliedSampler.setBorderColor(borderColor);
1482                 switch (borderColor.type)
1483                 {
1484                     case angle::ColorGeneric::Type::Float:
1485                         ANGLE_GL_TRY(context,
1486                                      functions->texParameterfv(
1487                                          nativegl::GetTextureBindingTarget(getType()),
1488                                          GL_TEXTURE_BORDER_COLOR, &borderColor.colorF.red));
1489                         break;
1490                     case angle::ColorGeneric::Type::Int:
1491                         ANGLE_GL_TRY(context,
1492                                      functions->texParameterIiv(
1493                                          nativegl::GetTextureBindingTarget(getType()),
1494                                          GL_TEXTURE_BORDER_COLOR, &borderColor.colorI.red));
1495                         break;
1496                     case angle::ColorGeneric::Type::UInt:
1497                         ANGLE_GL_TRY(context,
1498                                      functions->texParameterIuiv(
1499                                          nativegl::GetTextureBindingTarget(getType()),
1500                                          GL_TEXTURE_BORDER_COLOR, &borderColor.colorUI.red));
1501                         break;
1502                     default:
1503                         UNREACHABLE();
1504                         break;
1505                 }
1506                 break;
1507             }
1508 
1509             // Texture state
1510             case gl::Texture::DIRTY_BIT_SWIZZLE_RED:
1511                 ANGLE_TRY(syncTextureStateSwizzle(context, functions, GL_TEXTURE_SWIZZLE_R,
1512                                                   mState.getSwizzleState().swizzleRed,
1513                                                   &mAppliedSwizzle.swizzleRed));
1514                 break;
1515             case gl::Texture::DIRTY_BIT_SWIZZLE_GREEN:
1516                 ANGLE_TRY(syncTextureStateSwizzle(context, functions, GL_TEXTURE_SWIZZLE_G,
1517                                                   mState.getSwizzleState().swizzleGreen,
1518                                                   &mAppliedSwizzle.swizzleGreen));
1519                 break;
1520             case gl::Texture::DIRTY_BIT_SWIZZLE_BLUE:
1521                 ANGLE_TRY(syncTextureStateSwizzle(context, functions, GL_TEXTURE_SWIZZLE_B,
1522                                                   mState.getSwizzleState().swizzleBlue,
1523                                                   &mAppliedSwizzle.swizzleBlue));
1524                 break;
1525             case gl::Texture::DIRTY_BIT_SWIZZLE_ALPHA:
1526                 ANGLE_TRY(syncTextureStateSwizzle(context, functions, GL_TEXTURE_SWIZZLE_A,
1527                                                   mState.getSwizzleState().swizzleAlpha,
1528                                                   &mAppliedSwizzle.swizzleAlpha));
1529                 break;
1530             case gl::Texture::DIRTY_BIT_BASE_LEVEL:
1531                 mAppliedBaseLevel = mState.getEffectiveBaseLevel();
1532                 ANGLE_GL_TRY(context,
1533                              functions->texParameteri(nativegl::GetTextureBindingTarget(getType()),
1534                                                       GL_TEXTURE_BASE_LEVEL, mAppliedBaseLevel));
1535                 break;
1536             case gl::Texture::DIRTY_BIT_MAX_LEVEL:
1537                 mAppliedMaxLevel = mState.getEffectiveMaxLevel();
1538                 ANGLE_GL_TRY(context,
1539                              functions->texParameteri(nativegl::GetTextureBindingTarget(getType()),
1540                                                       GL_TEXTURE_MAX_LEVEL, mAppliedMaxLevel));
1541                 break;
1542             case gl::Texture::DIRTY_BIT_DEPTH_STENCIL_TEXTURE_MODE:
1543             {
1544                 GLenum mDepthStencilTextureMode = mState.getDepthStencilTextureMode();
1545                 ANGLE_GL_TRY(context, functions->texParameteri(
1546                                           nativegl::GetTextureBindingTarget(getType()),
1547                                           GL_DEPTH_STENCIL_TEXTURE_MODE, mDepthStencilTextureMode));
1548                 break;
1549             }
1550             case gl::Texture::DIRTY_BIT_USAGE:
1551                 break;
1552             case gl::Texture::DIRTY_BIT_LABEL:
1553                 break;
1554 
1555             case gl::Texture::DIRTY_BIT_IMPLEMENTATION:
1556                 // This special dirty bit is used to signal the front-end that the implementation
1557                 // has local dirty bits. The real dirty bits are in mLocalDirty bits.
1558                 break;
1559             case gl::Texture::DIRTY_BIT_BOUND_AS_IMAGE:
1560                 // Only used for Vulkan.
1561                 break;
1562 
1563             default:
1564                 UNREACHABLE();
1565         }
1566     }
1567 
1568     mLocalDirtyBits.reset();
1569     return angle::Result::Continue;
1570 }
1571 
hasAnyDirtyBit() const1572 bool TextureGL::hasAnyDirtyBit() const
1573 {
1574     return mLocalDirtyBits.any();
1575 }
1576 
setBaseLevel(const gl::Context * context,GLuint baseLevel)1577 angle::Result TextureGL::setBaseLevel(const gl::Context *context, GLuint baseLevel)
1578 {
1579     if (baseLevel != mAppliedBaseLevel)
1580     {
1581         const FunctionsGL *functions = GetFunctionsGL(context);
1582         StateManagerGL *stateManager = GetStateManagerGL(context);
1583 
1584         mAppliedBaseLevel = baseLevel;
1585         mLocalDirtyBits.set(gl::Texture::DIRTY_BIT_BASE_LEVEL);
1586 
1587         // Signal to the GL layer that the Impl has dirty bits.
1588         onStateChange(angle::SubjectMessage::DirtyBitsFlagged);
1589 
1590         stateManager->bindTexture(getType(), mTextureID);
1591         ANGLE_GL_TRY(context, functions->texParameteri(ToGLenum(getType()), GL_TEXTURE_BASE_LEVEL,
1592                                                        baseLevel));
1593     }
1594     return angle::Result::Continue;
1595 }
1596 
setMaxLevel(const gl::Context * context,GLuint maxLevel)1597 angle::Result TextureGL::setMaxLevel(const gl::Context *context, GLuint maxLevel)
1598 {
1599     if (maxLevel != mAppliedMaxLevel)
1600     {
1601         const FunctionsGL *functions = GetFunctionsGL(context);
1602         StateManagerGL *stateManager = GetStateManagerGL(context);
1603 
1604         mAppliedMaxLevel = maxLevel;
1605         mLocalDirtyBits.set(gl::Texture::DIRTY_BIT_MAX_LEVEL);
1606 
1607         // Signal to the GL layer that the Impl has dirty bits.
1608         onStateChange(angle::SubjectMessage::DirtyBitsFlagged);
1609 
1610         stateManager->bindTexture(getType(), mTextureID);
1611         ANGLE_GL_TRY(context,
1612                      functions->texParameteri(ToGLenum(getType()), GL_TEXTURE_MAX_LEVEL, maxLevel));
1613     }
1614     return angle::Result::Continue;
1615 }
1616 
setMinFilter(const gl::Context * context,GLenum filter)1617 angle::Result TextureGL::setMinFilter(const gl::Context *context, GLenum filter)
1618 {
1619     if (filter != mAppliedSampler.getMinFilter())
1620     {
1621         const FunctionsGL *functions = GetFunctionsGL(context);
1622         StateManagerGL *stateManager = GetStateManagerGL(context);
1623 
1624         mAppliedSampler.setMinFilter(filter);
1625         mLocalDirtyBits.set(gl::Texture::DIRTY_BIT_MIN_FILTER);
1626 
1627         // Signal to the GL layer that the Impl has dirty bits.
1628         onStateChange(angle::SubjectMessage::DirtyBitsFlagged);
1629 
1630         stateManager->bindTexture(getType(), mTextureID);
1631         ANGLE_GL_TRY(context,
1632                      functions->texParameteri(ToGLenum(getType()), GL_TEXTURE_MIN_FILTER, filter));
1633     }
1634     return angle::Result::Continue;
1635 }
setMagFilter(const gl::Context * context,GLenum filter)1636 angle::Result TextureGL::setMagFilter(const gl::Context *context, GLenum filter)
1637 {
1638     if (filter != mAppliedSampler.getMagFilter())
1639     {
1640         const FunctionsGL *functions = GetFunctionsGL(context);
1641         StateManagerGL *stateManager = GetStateManagerGL(context);
1642 
1643         mAppliedSampler.setMagFilter(filter);
1644         mLocalDirtyBits.set(gl::Texture::DIRTY_BIT_MAG_FILTER);
1645 
1646         // Signal to the GL layer that the Impl has dirty bits.
1647         onStateChange(angle::SubjectMessage::DirtyBitsFlagged);
1648 
1649         stateManager->bindTexture(getType(), mTextureID);
1650         ANGLE_GL_TRY(context,
1651                      functions->texParameteri(ToGLenum(getType()), GL_TEXTURE_MAG_FILTER, filter));
1652     }
1653     return angle::Result::Continue;
1654 }
1655 
setSwizzle(const gl::Context * context,GLint swizzle[4])1656 angle::Result TextureGL::setSwizzle(const gl::Context *context, GLint swizzle[4])
1657 {
1658     gl::SwizzleState resultingSwizzle =
1659         gl::SwizzleState(swizzle[0], swizzle[1], swizzle[2], swizzle[3]);
1660 
1661     if (resultingSwizzle != mAppliedSwizzle)
1662     {
1663         const FunctionsGL *functions = GetFunctionsGL(context);
1664         StateManagerGL *stateManager = GetStateManagerGL(context);
1665 
1666         mAppliedSwizzle = resultingSwizzle;
1667         mLocalDirtyBits.set(gl::Texture::DIRTY_BIT_SWIZZLE_RED);
1668         mLocalDirtyBits.set(gl::Texture::DIRTY_BIT_SWIZZLE_GREEN);
1669         mLocalDirtyBits.set(gl::Texture::DIRTY_BIT_SWIZZLE_BLUE);
1670         mLocalDirtyBits.set(gl::Texture::DIRTY_BIT_SWIZZLE_ALPHA);
1671 
1672         // Signal to the GL layer that the Impl has dirty bits.
1673         onStateChange(angle::SubjectMessage::DirtyBitsFlagged);
1674 
1675         stateManager->bindTexture(getType(), mTextureID);
1676         if (functions->standard == STANDARD_GL_ES)
1677         {
1678             ANGLE_GL_TRY(context, functions->texParameteri(ToGLenum(getType()),
1679                                                            GL_TEXTURE_SWIZZLE_R, swizzle[0]));
1680             ANGLE_GL_TRY(context, functions->texParameteri(ToGLenum(getType()),
1681                                                            GL_TEXTURE_SWIZZLE_G, swizzle[1]));
1682             ANGLE_GL_TRY(context, functions->texParameteri(ToGLenum(getType()),
1683                                                            GL_TEXTURE_SWIZZLE_B, swizzle[2]));
1684             ANGLE_GL_TRY(context, functions->texParameteri(ToGLenum(getType()),
1685                                                            GL_TEXTURE_SWIZZLE_A, swizzle[3]));
1686         }
1687         else
1688         {
1689             ANGLE_GL_TRY(context, functions->texParameteriv(ToGLenum(getType()),
1690                                                             GL_TEXTURE_SWIZZLE_RGBA, swizzle));
1691         }
1692     }
1693     return angle::Result::Continue;
1694 }
1695 
getNativeInternalFormat(const gl::ImageIndex & index) const1696 GLenum TextureGL::getNativeInternalFormat(const gl::ImageIndex &index) const
1697 {
1698     return getLevelInfo(index.getTarget(), index.getLevelIndex()).nativeInternalFormat;
1699 }
1700 
hasEmulatedAlphaChannel(const gl::ImageIndex & index) const1701 bool TextureGL::hasEmulatedAlphaChannel(const gl::ImageIndex &index) const
1702 {
1703     return getLevelInfo(index.getTargetOrFirstCubeFace(), index.getLevelIndex())
1704         .emulatedAlphaChannel;
1705 }
1706 
syncTextureStateSwizzle(const gl::Context * context,const FunctionsGL * functions,GLenum name,GLenum value,GLenum * outValue)1707 angle::Result TextureGL::syncTextureStateSwizzle(const gl::Context *context,
1708                                                  const FunctionsGL *functions,
1709                                                  GLenum name,
1710                                                  GLenum value,
1711                                                  GLenum *outValue)
1712 {
1713     const LevelInfoGL &levelInfo = getBaseLevelInfo();
1714     GLenum resultSwizzle         = value;
1715     if (levelInfo.lumaWorkaround.enabled)
1716     {
1717         switch (value)
1718         {
1719             case GL_RED:
1720             case GL_GREEN:
1721             case GL_BLUE:
1722                 if (levelInfo.sourceFormat == GL_LUMINANCE ||
1723                     levelInfo.sourceFormat == GL_LUMINANCE_ALPHA)
1724                 {
1725                     // Texture is backed by a RED or RG texture, point all color channels at the
1726                     // red channel.
1727                     ASSERT(levelInfo.lumaWorkaround.workaroundFormat == GL_RED ||
1728                            levelInfo.lumaWorkaround.workaroundFormat == GL_RG);
1729                     resultSwizzle = GL_RED;
1730                 }
1731                 else
1732                 {
1733                     ASSERT(levelInfo.sourceFormat == GL_ALPHA);
1734                     // Color channels are not supposed to exist, make them always sample 0.
1735                     resultSwizzle = GL_ZERO;
1736                 }
1737                 break;
1738 
1739             case GL_ALPHA:
1740                 if (levelInfo.sourceFormat == GL_LUMINANCE)
1741                 {
1742                     // Alpha channel is not supposed to exist, make it always sample 1.
1743                     resultSwizzle = GL_ONE;
1744                 }
1745                 else if (levelInfo.sourceFormat == GL_ALPHA)
1746                 {
1747                     // Texture is backed by a RED texture, point the alpha channel at the red
1748                     // channel.
1749                     ASSERT(levelInfo.lumaWorkaround.workaroundFormat == GL_RED);
1750                     resultSwizzle = GL_RED;
1751                 }
1752                 else
1753                 {
1754                     ASSERT(levelInfo.sourceFormat == GL_LUMINANCE_ALPHA);
1755                     // Texture is backed by an RG texture, point the alpha channel at the green
1756                     // channel.
1757                     ASSERT(levelInfo.lumaWorkaround.workaroundFormat == GL_RG);
1758                     resultSwizzle = GL_GREEN;
1759                 }
1760                 break;
1761 
1762             case GL_ZERO:
1763             case GL_ONE:
1764                 // Don't modify the swizzle state when requesting ZERO or ONE.
1765                 resultSwizzle = value;
1766                 break;
1767 
1768             default:
1769                 UNREACHABLE();
1770                 break;
1771         }
1772     }
1773     else if (levelInfo.depthStencilWorkaround)
1774     {
1775         switch (value)
1776         {
1777             case GL_RED:
1778                 // Don't modify the swizzle state when requesting the red channel.
1779                 resultSwizzle = value;
1780                 break;
1781 
1782             case GL_GREEN:
1783             case GL_BLUE:
1784                 if (context->getClientMajorVersion() <= 2)
1785                 {
1786                     // In OES_depth_texture/ARB_depth_texture, depth
1787                     // textures are treated as luminance.
1788                     resultSwizzle = GL_RED;
1789                 }
1790                 else
1791                 {
1792                     // In GLES 3.0, depth textures are treated as RED
1793                     // textures, so green and blue should be 0.
1794                     resultSwizzle = GL_ZERO;
1795                 }
1796                 break;
1797 
1798             case GL_ALPHA:
1799                 // Depth textures should sample 1 from the alpha channel.
1800                 resultSwizzle = GL_ONE;
1801                 break;
1802 
1803             case GL_ZERO:
1804             case GL_ONE:
1805                 // Don't modify the swizzle state when requesting ZERO or ONE.
1806                 resultSwizzle = value;
1807                 break;
1808 
1809             default:
1810                 UNREACHABLE();
1811                 break;
1812         }
1813     }
1814     else if (levelInfo.emulatedAlphaChannel)
1815     {
1816         if (value == GL_ALPHA)
1817         {
1818             resultSwizzle = GL_ONE;
1819         }
1820     }
1821 
1822     *outValue = resultSwizzle;
1823     ANGLE_GL_TRY(context, functions->texParameteri(ToGLenum(getType()), name, resultSwizzle));
1824 
1825     return angle::Result::Continue;
1826 }
1827 
setLevelInfo(const gl::Context * context,gl::TextureTarget target,size_t level,size_t levelCount,const LevelInfoGL & levelInfo)1828 void TextureGL::setLevelInfo(const gl::Context *context,
1829                              gl::TextureTarget target,
1830                              size_t level,
1831                              size_t levelCount,
1832                              const LevelInfoGL &levelInfo)
1833 {
1834     ASSERT(levelCount > 0);
1835 
1836     bool updateWorkarounds = levelInfo.depthStencilWorkaround || levelInfo.lumaWorkaround.enabled ||
1837                              levelInfo.emulatedAlphaChannel;
1838 
1839     for (size_t i = level; i < level + levelCount; i++)
1840     {
1841         size_t index = GetLevelInfoIndex(target, i);
1842         ASSERT(index < mLevelInfo.size());
1843         auto &curLevelInfo = mLevelInfo[index];
1844 
1845         updateWorkarounds |= curLevelInfo.depthStencilWorkaround;
1846         updateWorkarounds |= curLevelInfo.lumaWorkaround.enabled;
1847         updateWorkarounds |= curLevelInfo.emulatedAlphaChannel;
1848 
1849         curLevelInfo = levelInfo;
1850     }
1851 
1852     if (updateWorkarounds)
1853     {
1854         mLocalDirtyBits |= GetLevelWorkaroundDirtyBits();
1855         onStateChange(angle::SubjectMessage::DirtyBitsFlagged);
1856     }
1857 }
1858 
setLevelInfo(const gl::Context * context,gl::TextureType type,size_t level,size_t levelCount,const LevelInfoGL & levelInfo)1859 void TextureGL::setLevelInfo(const gl::Context *context,
1860                              gl::TextureType type,
1861                              size_t level,
1862                              size_t levelCount,
1863                              const LevelInfoGL &levelInfo)
1864 {
1865     if (type == gl::TextureType::CubeMap)
1866     {
1867         for (gl::TextureTarget target : gl::AllCubeFaceTextureTargets())
1868         {
1869             setLevelInfo(context, target, level, levelCount, levelInfo);
1870         }
1871     }
1872     else
1873     {
1874         setLevelInfo(context, NonCubeTextureTypeToTarget(type), level, levelCount, levelInfo);
1875     }
1876 }
1877 
getLevelInfo(gl::TextureTarget target,size_t level) const1878 const LevelInfoGL &TextureGL::getLevelInfo(gl::TextureTarget target, size_t level) const
1879 {
1880     return mLevelInfo[GetLevelInfoIndex(target, level)];
1881 }
1882 
getBaseLevelInfo() const1883 const LevelInfoGL &TextureGL::getBaseLevelInfo() const
1884 {
1885     GLint effectiveBaseLevel = mState.getEffectiveBaseLevel();
1886     gl::TextureTarget target = getType() == gl::TextureType::CubeMap
1887                                    ? gl::kCubeMapTextureTargetMin
1888                                    : gl::NonCubeTextureTypeToTarget(getType());
1889     return getLevelInfo(target, effectiveBaseLevel);
1890 }
1891 
getType() const1892 gl::TextureType TextureGL::getType() const
1893 {
1894     return mState.mType;
1895 }
1896 
initializeContents(const gl::Context * context,const gl::ImageIndex & imageIndex)1897 angle::Result TextureGL::initializeContents(const gl::Context *context,
1898                                             const gl::ImageIndex &imageIndex)
1899 {
1900     ContextGL *contextGL              = GetImplAs<ContextGL>(context);
1901     const FunctionsGL *functions      = GetFunctionsGL(context);
1902     StateManagerGL *stateManager      = GetStateManagerGL(context);
1903     const angle::FeaturesGL &features = GetFeaturesGL(context);
1904 
1905     bool shouldUseClear = !nativegl::SupportsTexImage(getType());
1906     GLenum nativeInternalFormat =
1907         getLevelInfo(imageIndex.getTarget(), imageIndex.getLevelIndex()).nativeInternalFormat;
1908     if ((features.allowClearForRobustResourceInit.enabled || shouldUseClear) &&
1909         nativegl::SupportsNativeRendering(functions, mState.getType(), nativeInternalFormat))
1910     {
1911         BlitGL *blitter = GetBlitGL(context);
1912 
1913         int levelDepth = mState.getImageDesc(imageIndex).size.depth;
1914 
1915         bool clearSucceeded = false;
1916         ANGLE_TRY(blitter->clearRenderableTexture(context, this, nativeInternalFormat, levelDepth,
1917                                                   imageIndex, &clearSucceeded));
1918         if (clearSucceeded)
1919         {
1920             return angle::Result::Continue;
1921         }
1922     }
1923 
1924     // Either the texture is not renderable or was incomplete when clearing, fall back to a data
1925     // upload
1926     ASSERT(nativegl::SupportsTexImage(getType()));
1927     const gl::ImageDesc &desc                    = mState.getImageDesc(imageIndex);
1928     const gl::InternalFormat &internalFormatInfo = *desc.format.info;
1929 
1930     gl::PixelUnpackState unpackState;
1931     unpackState.alignment = 1;
1932     stateManager->setPixelUnpackState(unpackState);
1933 
1934     GLuint prevUnpackBuffer = stateManager->getBufferID(gl::BufferBinding::PixelUnpack);
1935     stateManager->bindBuffer(gl::BufferBinding::PixelUnpack, 0);
1936 
1937     stateManager->bindTexture(getType(), mTextureID);
1938     if (internalFormatInfo.compressed)
1939     {
1940         nativegl::CompressedTexSubImageFormat nativeSubImageFormat =
1941             nativegl::GetCompressedSubTexImageFormat(functions, features,
1942                                                      internalFormatInfo.internalFormat);
1943 
1944         GLuint imageSize = 0;
1945         ANGLE_CHECK_GL_MATH(contextGL,
1946                             internalFormatInfo.computeCompressedImageSize(desc.size, &imageSize));
1947 
1948         angle::MemoryBuffer *zero;
1949         ANGLE_CHECK_GL_ALLOC(contextGL, context->getZeroFilledBuffer(imageSize, &zero));
1950 
1951         // WebGL spec requires that zero data is uploaded to compressed textures even if it might
1952         // not result in zero color data.
1953         if (nativegl::UseTexImage2D(getType()))
1954         {
1955             ANGLE_GL_TRY(context, functions->compressedTexSubImage2D(
1956                                       ToGLenum(imageIndex.getTarget()), imageIndex.getLevelIndex(),
1957                                       0, 0, desc.size.width, desc.size.height,
1958                                       nativeSubImageFormat.format, imageSize, zero->data()));
1959         }
1960         else
1961         {
1962             ASSERT(nativegl::UseTexImage3D(getType()));
1963             ANGLE_GL_TRY(context, functions->compressedTexSubImage3D(
1964                                       ToGLenum(imageIndex.getTarget()), imageIndex.getLevelIndex(),
1965                                       0, 0, 0, desc.size.width, desc.size.height, desc.size.depth,
1966                                       nativeSubImageFormat.format, imageSize, zero->data()));
1967         }
1968     }
1969     else
1970     {
1971         nativegl::TexSubImageFormat nativeSubImageFormat = nativegl::GetTexSubImageFormat(
1972             functions, features, internalFormatInfo.format, internalFormatInfo.type);
1973 
1974         GLuint imageSize = 0;
1975         ANGLE_CHECK_GL_MATH(contextGL, internalFormatInfo.computePackUnpackEndByte(
1976                                            nativeSubImageFormat.type, desc.size, unpackState,
1977                                            nativegl::UseTexImage3D(getType()), &imageSize));
1978 
1979         angle::MemoryBuffer *zero;
1980         ANGLE_CHECK_GL_ALLOC(contextGL, context->getZeroFilledBuffer(imageSize, &zero));
1981 
1982         if (nativegl::UseTexImage2D(getType()))
1983         {
1984             ANGLE_GL_TRY(context,
1985                          functions->texSubImage2D(ToGLenum(imageIndex.getTarget()),
1986                                                   imageIndex.getLevelIndex(), 0, 0, desc.size.width,
1987                                                   desc.size.height, nativeSubImageFormat.format,
1988                                                   nativeSubImageFormat.type, zero->data()));
1989         }
1990         else
1991         {
1992             ASSERT(nativegl::UseTexImage3D(getType()));
1993             ANGLE_GL_TRY(context,
1994                          functions->texSubImage3D(
1995                              ToGLenum(imageIndex.getTarget()), imageIndex.getLevelIndex(), 0, 0, 0,
1996                              desc.size.width, desc.size.height, desc.size.depth,
1997                              nativeSubImageFormat.format, nativeSubImageFormat.type, zero->data()));
1998         }
1999     }
2000 
2001     // Reset the pixel unpack state.  Because this call is made after synchronizing dirty bits in a
2002     // glTexImage call, we need to make sure that the texture data to be uploaded later has the
2003     // expected unpack state.
2004     stateManager->setPixelUnpackState(context->getState().getUnpackState());
2005     stateManager->bindBuffer(gl::BufferBinding::PixelUnpack, prevUnpackBuffer);
2006 
2007     return angle::Result::Continue;
2008 }
2009 
2010 }  // namespace rx
2011