66c4ffcf6880fba75582d5543257f3aecee429ec
[WebKit-https.git] / Source / ThirdParty / ANGLE / src / libANGLE / renderer / gl / TextureGL.cpp
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
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
49 bool IsLUMAFormat(GLenum format)
50 {
51     return format == GL_LUMINANCE || format == GL_ALPHA || format == GL_LUMINANCE_ALPHA;
52 }
53
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
66 bool GetDepthStencilWorkaround(GLenum format)
67 {
68     return format == GL_DEPTH_COMPONENT || format == GL_DEPTH_STENCIL;
69 }
70
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
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
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
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
116 LUMAWorkaroundGL::LUMAWorkaroundGL() : LUMAWorkaroundGL(false, GL_NONE) {}
117
118 LUMAWorkaroundGL::LUMAWorkaroundGL(bool enabled_, GLenum workaroundFormat_)
119     : enabled(enabled_), workaroundFormat(workaroundFormat_)
120 {}
121
122 LevelInfoGL::LevelInfoGL() : LevelInfoGL(GL_NONE, GL_NONE, false, LUMAWorkaroundGL(), false) {}
123
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
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
147 TextureGL::~TextureGL()
148 {
149     ASSERT(mTextureID == 0);
150 }
151
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
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
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
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
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
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
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
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
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
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 (requiresInitialization)
717             {
718                 ANGLE_GL_TRY(context, functions->copyTexSubImage2D(
719                                           ToGLenum(target), static_cast<GLint>(level), destOffset.x,
720                                           destOffset.y, clippedArea.x, clippedArea.y,
721                                           clippedArea.width, clippedArea.height));
722             }
723             else
724             {
725                 ANGLE_GL_TRY_ALWAYS_CHECK(
726                     context, functions->copyTexImage2D(ToGLenum(target), static_cast<GLint>(level),
727                                                        copyTexImageFormat.internalFormat,
728                                                        clippedArea.x, clippedArea.y,
729                                                        clippedArea.width, clippedArea.height, 0));
730             }
731         }
732         setLevelInfo(context, target, level, 1, levelInfo);
733     }
734
735     if (features.flushBeforeDeleteTextureIfCopiedTo.enabled)
736     {
737         contextGL->setNeedsFlushBeforeDeleteTextures();
738     }
739
740     return angle::Result::Continue;
741 }
742
743 angle::Result TextureGL::copySubImage(const gl::Context *context,
744                                       const gl::ImageIndex &index,
745                                       const gl::Offset &destOffset,
746                                       const gl::Rectangle &sourceArea,
747                                       gl::Framebuffer *source)
748 {
749     const FunctionsGL *functions      = GetFunctionsGL(context);
750     StateManagerGL *stateManager      = GetStateManagerGL(context);
751     const angle::FeaturesGL &features = GetFeaturesGL(context);
752
753     gl::TextureTarget target                 = index.getTarget();
754     size_t level                             = static_cast<size_t>(index.getLevelIndex());
755     const FramebufferGL *sourceFramebufferGL = GetImplAs<FramebufferGL>(source);
756
757     // Clip source area to framebuffer.
758     const gl::Extents fbSize = sourceFramebufferGL->getState().getReadAttachment()->getSize();
759     gl::Rectangle clippedArea;
760     if (!ClipRectangle(sourceArea, gl::Rectangle(0, 0, fbSize.width, fbSize.height), &clippedArea))
761     {
762         // nothing to do
763         return angle::Result::Continue;
764     }
765     gl::Offset clippedOffset(destOffset.x + clippedArea.x - sourceArea.x,
766                              destOffset.y + clippedArea.y - sourceArea.y, destOffset.z);
767
768     stateManager->bindTexture(getType(), mTextureID);
769     stateManager->bindFramebuffer(GL_READ_FRAMEBUFFER, sourceFramebufferGL->getFramebufferID());
770
771     const LevelInfoGL &levelInfo = getLevelInfo(target, level);
772     if (levelInfo.lumaWorkaround.enabled)
773     {
774         BlitGL *blitter = GetBlitGL(context);
775         ANGLE_TRY(blitter->copySubImageToLUMAWorkaroundTexture(
776             context, mTextureID, getType(), target, levelInfo.sourceFormat, level, clippedOffset,
777             clippedArea, source));
778     }
779     else
780     {
781         if (nativegl::UseTexImage2D(getType()))
782         {
783             ASSERT(clippedOffset.z == 0);
784             ANGLE_GL_TRY(context, functions->copyTexSubImage2D(
785                                       ToGLenum(target), static_cast<GLint>(level), clippedOffset.x,
786                                       clippedOffset.y, clippedArea.x, clippedArea.y,
787                                       clippedArea.width, clippedArea.height));
788         }
789         else
790         {
791             ASSERT(nativegl::UseTexImage3D(getType()));
792             ANGLE_GL_TRY(context, functions->copyTexSubImage3D(
793                                       ToGLenum(target), static_cast<GLint>(level), clippedOffset.x,
794                                       clippedOffset.y, clippedOffset.z, clippedArea.x,
795                                       clippedArea.y, clippedArea.width, clippedArea.height));
796         }
797     }
798
799     if (features.flushBeforeDeleteTextureIfCopiedTo.enabled)
800     {
801         ContextGL *contextGL = GetImplAs<ContextGL>(context);
802         contextGL->setNeedsFlushBeforeDeleteTextures();
803     }
804
805     return angle::Result::Continue;
806 }
807
808 angle::Result TextureGL::copyTexture(const gl::Context *context,
809                                      const gl::ImageIndex &index,
810                                      GLenum internalFormat,
811                                      GLenum type,
812                                      size_t sourceLevel,
813                                      bool unpackFlipY,
814                                      bool unpackPremultiplyAlpha,
815                                      bool unpackUnmultiplyAlpha,
816                                      const gl::Texture *source)
817 {
818     gl::TextureTarget target  = index.getTarget();
819     size_t level              = static_cast<size_t>(index.getLevelIndex());
820     const TextureGL *sourceGL = GetImplAs<TextureGL>(source);
821     const gl::ImageDesc &sourceImageDesc =
822         sourceGL->mState.getImageDesc(NonCubeTextureTypeToTarget(source->getType()), sourceLevel);
823     gl::Rectangle sourceArea(0, 0, sourceImageDesc.size.width, sourceImageDesc.size.height);
824
825     ANGLE_TRY(reserveTexImageToBeFilled(context, target, level, internalFormat,
826                                         sourceImageDesc.size, gl::GetUnsizedFormat(internalFormat),
827                                         type));
828
829     const gl::InternalFormat &destFormatInfo = gl::GetInternalFormatInfo(internalFormat, type);
830     return copySubTextureHelper(context, target, level, gl::Offset(0, 0, 0), sourceLevel,
831                                 sourceArea, destFormatInfo, unpackFlipY, unpackPremultiplyAlpha,
832                                 unpackUnmultiplyAlpha, source);
833 }
834
835 angle::Result TextureGL::copySubTexture(const gl::Context *context,
836                                         const gl::ImageIndex &index,
837                                         const gl::Offset &destOffset,
838                                         size_t sourceLevel,
839                                         const gl::Box &sourceBox,
840                                         bool unpackFlipY,
841                                         bool unpackPremultiplyAlpha,
842                                         bool unpackUnmultiplyAlpha,
843                                         const gl::Texture *source)
844 {
845     gl::TextureTarget target                 = index.getTarget();
846     size_t level                             = static_cast<size_t>(index.getLevelIndex());
847     const gl::InternalFormat &destFormatInfo = *mState.getImageDesc(target, level).format.info;
848     return copySubTextureHelper(context, target, level, destOffset, sourceLevel, sourceBox.toRect(),
849                                 destFormatInfo, unpackFlipY, unpackPremultiplyAlpha,
850                                 unpackUnmultiplyAlpha, source);
851 }
852
853 angle::Result TextureGL::copySubTextureHelper(const gl::Context *context,
854                                               gl::TextureTarget target,
855                                               size_t level,
856                                               const gl::Offset &destOffset,
857                                               size_t sourceLevel,
858                                               const gl::Rectangle &sourceArea,
859                                               const gl::InternalFormat &destFormat,
860                                               bool unpackFlipY,
861                                               bool unpackPremultiplyAlpha,
862                                               bool unpackUnmultiplyAlpha,
863                                               const gl::Texture *source)
864 {
865     const FunctionsGL *functions      = GetFunctionsGL(context);
866     const angle::FeaturesGL &features = GetFeaturesGL(context);
867     BlitGL *blitter                   = GetBlitGL(context);
868
869     TextureGL *sourceGL = GetImplAs<TextureGL>(source);
870     const gl::ImageDesc &sourceImageDesc =
871         sourceGL->mState.getImageDesc(NonCubeTextureTypeToTarget(source->getType()), sourceLevel);
872
873     if (features.flushBeforeDeleteTextureIfCopiedTo.enabled)
874     {
875         // Conservatively indicate that this workaround is necessary. Not clear
876         // if it is on this code path, but added for symmetry.
877         ContextGL *contextGL = GetImplAs<ContextGL>(context);
878         contextGL->setNeedsFlushBeforeDeleteTextures();
879     }
880
881     // Check is this is a simple copySubTexture that can be done with a copyTexSubImage
882     ASSERT(sourceGL->getType() == gl::TextureType::_2D ||
883            source->getType() == gl::TextureType::External ||
884            source->getType() == gl::TextureType::Rectangle);
885     const LevelInfoGL &sourceLevelInfo =
886         sourceGL->getLevelInfo(NonCubeTextureTypeToTarget(source->getType()), sourceLevel);
887     bool needsLumaWorkaround = sourceLevelInfo.lumaWorkaround.enabled;
888
889     const gl::InternalFormat &sourceFormatInfo = *sourceImageDesc.format.info;
890     GLenum sourceFormat                        = sourceFormatInfo.format;
891     bool sourceFormatContainSupersetOfDestFormat =
892         (sourceFormat == destFormat.format && sourceFormat != GL_BGRA_EXT) ||
893         (sourceFormat == GL_RGBA && destFormat.format == GL_RGB);
894
895     GLenum sourceComponentType = sourceFormatInfo.componentType;
896     GLenum destComponentType   = destFormat.componentType;
897     bool destSRGB              = destFormat.colorEncoding == GL_SRGB;
898     if (!unpackFlipY && unpackPremultiplyAlpha == unpackUnmultiplyAlpha && !needsLumaWorkaround &&
899         sourceFormatContainSupersetOfDestFormat && sourceComponentType == destComponentType &&
900         !destSRGB && sourceGL->getType() == gl::TextureType::_2D)
901     {
902         bool copySucceeded = false;
903         ANGLE_TRY(blitter->copyTexSubImage(context, sourceGL, sourceLevel, this, target, level,
904                                            sourceArea, destOffset, &copySucceeded));
905         if (copySucceeded)
906         {
907             return angle::Result::Continue;
908         }
909     }
910
911     // Check if the destination is renderable and copy on the GPU
912     const LevelInfoGL &destLevelInfo = getLevelInfo(target, level);
913     // todo(jonahr): http://crbug.com/773861
914     // Behavior for now is to fallback to CPU readback implementation if the destination texture
915     // is a luminance format. The correct solution is to handle both source and destination in the
916     // luma workaround.
917     if (!destSRGB && !destLevelInfo.lumaWorkaround.enabled &&
918         nativegl::SupportsNativeRendering(functions, getType(), destLevelInfo.nativeInternalFormat))
919     {
920         bool copySucceeded = false;
921         ANGLE_TRY(blitter->copySubTexture(
922             context, sourceGL, sourceLevel, sourceComponentType, mTextureID, target, level,
923             destComponentType, sourceImageDesc.size, sourceArea, destOffset, needsLumaWorkaround,
924             sourceLevelInfo.sourceFormat, unpackFlipY, unpackPremultiplyAlpha,
925             unpackUnmultiplyAlpha, &copySucceeded));
926         if (copySucceeded)
927         {
928             return angle::Result::Continue;
929         }
930     }
931
932     // Fall back to CPU-readback
933     return blitter->copySubTextureCPUReadback(
934         context, sourceGL, sourceLevel, sourceFormatInfo.sizedInternalFormat, this, target, level,
935         destFormat.format, destFormat.type, sourceImageDesc.size, sourceArea, destOffset,
936         needsLumaWorkaround, sourceLevelInfo.sourceFormat, unpackFlipY, unpackPremultiplyAlpha,
937         unpackUnmultiplyAlpha);
938 }
939
940 angle::Result TextureGL::setStorage(const gl::Context *context,
941                                     gl::TextureType type,
942                                     size_t levels,
943                                     GLenum internalFormat,
944                                     const gl::Extents &size)
945 {
946     ContextGL *contextGL              = GetImplAs<ContextGL>(context);
947     const FunctionsGL *functions      = GetFunctionsGL(context);
948     StateManagerGL *stateManager      = GetStateManagerGL(context);
949     const angle::FeaturesGL &features = GetFeaturesGL(context);
950
951     nativegl::TexStorageFormat texStorageFormat =
952         nativegl::GetTexStorageFormat(functions, features, internalFormat);
953
954     stateManager->bindTexture(getType(), mTextureID);
955     if (nativegl::UseTexImage2D(getType()))
956     {
957         ASSERT(size.depth == 1);
958         if (functions->texStorage2D)
959         {
960             ANGLE_GL_TRY_ALWAYS_CHECK(
961                 context,
962                 functions->texStorage2D(ToGLenum(type), static_cast<GLsizei>(levels),
963                                         texStorageFormat.internalFormat, size.width, size.height));
964         }
965         else
966         {
967             // Make sure no pixel unpack buffer is bound
968             stateManager->bindBuffer(gl::BufferBinding::PixelUnpack, 0);
969
970             const gl::InternalFormat &internalFormatInfo =
971                 gl::GetSizedInternalFormatInfo(internalFormat);
972
973             // Internal format must be sized
974             ASSERT(internalFormatInfo.sized);
975
976             for (size_t level = 0; level < levels; level++)
977             {
978                 gl::Extents levelSize(std::max(size.width >> level, 1),
979                                       std::max(size.height >> level, 1), 1);
980
981                 if (getType() == gl::TextureType::_2D || getType() == gl::TextureType::Rectangle)
982                 {
983                     if (internalFormatInfo.compressed)
984                     {
985                         nativegl::CompressedTexSubImageFormat compressedTexImageFormat =
986                             nativegl::GetCompressedSubTexImageFormat(functions, features,
987                                                                      internalFormat);
988
989                         GLuint dataSize = 0;
990                         ANGLE_CHECK_GL_MATH(
991                             contextGL,
992                             internalFormatInfo.computeCompressedImageSize(levelSize, &dataSize));
993                         ANGLE_GL_TRY_ALWAYS_CHECK(
994                             context,
995                             functions->compressedTexImage2D(
996                                 ToGLenum(type), static_cast<GLint>(level),
997                                 compressedTexImageFormat.format, levelSize.width, levelSize.height,
998                                 0, static_cast<GLsizei>(dataSize), nullptr));
999                     }
1000                     else
1001                     {
1002                         nativegl::TexImageFormat texImageFormat = nativegl::GetTexImageFormat(
1003                             functions, features, internalFormat, internalFormatInfo.format,
1004                             internalFormatInfo.type);
1005
1006                         ANGLE_GL_TRY_ALWAYS_CHECK(
1007                             context,
1008                             functions->texImage2D(ToGLenum(type), static_cast<GLint>(level),
1009                                                   texImageFormat.internalFormat, levelSize.width,
1010                                                   levelSize.height, 0, texImageFormat.format,
1011                                                   texImageFormat.type, nullptr));
1012                     }
1013                 }
1014                 else
1015                 {
1016                     ASSERT(getType() == gl::TextureType::CubeMap);
1017                     for (gl::TextureTarget face : gl::AllCubeFaceTextureTargets())
1018                     {
1019                         if (internalFormatInfo.compressed)
1020                         {
1021                             nativegl::CompressedTexSubImageFormat compressedTexImageFormat =
1022                                 nativegl::GetCompressedSubTexImageFormat(functions, features,
1023                                                                          internalFormat);
1024
1025                             GLuint dataSize = 0;
1026                             ANGLE_CHECK_GL_MATH(contextGL,
1027                                                 internalFormatInfo.computeCompressedImageSize(
1028                                                     levelSize, &dataSize));
1029                             ANGLE_GL_TRY_ALWAYS_CHECK(
1030                                 context,
1031                                 functions->compressedTexImage2D(
1032                                     ToGLenum(face), static_cast<GLint>(level),
1033                                     compressedTexImageFormat.format, levelSize.width,
1034                                     levelSize.height, 0, static_cast<GLsizei>(dataSize), nullptr));
1035                         }
1036                         else
1037                         {
1038                             nativegl::TexImageFormat texImageFormat = nativegl::GetTexImageFormat(
1039                                 functions, features, internalFormat, internalFormatInfo.format,
1040                                 internalFormatInfo.type);
1041
1042                             ANGLE_GL_TRY_ALWAYS_CHECK(
1043                                 context, functions->texImage2D(
1044                                              ToGLenum(face), static_cast<GLint>(level),
1045                                              texImageFormat.internalFormat, levelSize.width,
1046                                              levelSize.height, 0, texImageFormat.format,
1047                                              texImageFormat.type, nullptr));
1048                         }
1049                     }
1050                 }
1051             }
1052         }
1053     }
1054     else
1055     {
1056         ASSERT(nativegl::UseTexImage3D(getType()));
1057         if (functions->texStorage3D)
1058         {
1059             ANGLE_GL_TRY_ALWAYS_CHECK(
1060                 context, functions->texStorage3D(ToGLenum(type), static_cast<GLsizei>(levels),
1061                                                  texStorageFormat.internalFormat, size.width,
1062                                                  size.height, size.depth));
1063         }
1064         else
1065         {
1066             // Make sure no pixel unpack buffer is bound
1067             stateManager->bindBuffer(gl::BufferBinding::PixelUnpack, 0);
1068
1069             const gl::InternalFormat &internalFormatInfo =
1070                 gl::GetSizedInternalFormatInfo(internalFormat);
1071
1072             // Internal format must be sized
1073             ASSERT(internalFormatInfo.sized);
1074
1075             for (GLsizei i = 0; i < static_cast<GLsizei>(levels); i++)
1076             {
1077                 gl::Extents levelSize(
1078                     std::max(size.width >> i, 1), std::max(size.height >> i, 1),
1079                     getType() == gl::TextureType::_3D ? std::max(size.depth >> i, 1) : size.depth);
1080
1081                 if (internalFormatInfo.compressed)
1082                 {
1083                     nativegl::CompressedTexSubImageFormat compressedTexImageFormat =
1084                         nativegl::GetCompressedSubTexImageFormat(functions, features,
1085                                                                  internalFormat);
1086
1087                     GLuint dataSize = 0;
1088                     ANGLE_CHECK_GL_MATH(contextGL, internalFormatInfo.computeCompressedImageSize(
1089                                                        levelSize, &dataSize));
1090                     ANGLE_GL_TRY_ALWAYS_CHECK(
1091                         context, functions->compressedTexImage3D(
1092                                      ToGLenum(type), i, compressedTexImageFormat.format,
1093                                      levelSize.width, levelSize.height, levelSize.depth, 0,
1094                                      static_cast<GLsizei>(dataSize), nullptr));
1095                 }
1096                 else
1097                 {
1098                     nativegl::TexImageFormat texImageFormat = nativegl::GetTexImageFormat(
1099                         functions, features, internalFormat, internalFormatInfo.format,
1100                         internalFormatInfo.type);
1101
1102                     ANGLE_GL_TRY_ALWAYS_CHECK(
1103                         context,
1104                         functions->texImage3D(ToGLenum(type), i, texImageFormat.internalFormat,
1105                                               levelSize.width, levelSize.height, levelSize.depth, 0,
1106                                               texImageFormat.format, texImageFormat.type, nullptr));
1107                 }
1108             }
1109         }
1110     }
1111
1112     setLevelInfo(context, type, 0, levels,
1113                  GetLevelInfo(features, internalFormat, texStorageFormat.internalFormat));
1114
1115     return angle::Result::Continue;
1116 }
1117
1118 angle::Result TextureGL::setImageExternal(const gl::Context *context,
1119                                           const gl::ImageIndex &index,
1120                                           GLenum internalFormat,
1121                                           const gl::Extents &size,
1122                                           GLenum format,
1123                                           GLenum type)
1124 {
1125     const FunctionsGL *functions      = GetFunctionsGL(context);
1126     const angle::FeaturesGL &features = GetFeaturesGL(context);
1127
1128     gl::TextureTarget target = index.getTarget();
1129     size_t level             = static_cast<size_t>(index.getLevelIndex());
1130     nativegl::TexImageFormat texImageFormat =
1131         nativegl::GetTexImageFormat(functions, features, internalFormat, format, type);
1132
1133     setLevelInfo(context, target, level, 1,
1134                  GetLevelInfo(features, internalFormat, texImageFormat.internalFormat));
1135     return angle::Result::Continue;
1136 }
1137
1138 angle::Result TextureGL::setStorageMultisample(const gl::Context *context,
1139                                                gl::TextureType type,
1140                                                GLsizei samples,
1141                                                GLint internalformat,
1142                                                const gl::Extents &size,
1143                                                bool fixedSampleLocations)
1144 {
1145     const FunctionsGL *functions      = GetFunctionsGL(context);
1146     StateManagerGL *stateManager      = GetStateManagerGL(context);
1147     const angle::FeaturesGL &features = GetFeaturesGL(context);
1148
1149     nativegl::TexStorageFormat texStorageFormat =
1150         nativegl::GetTexStorageFormat(functions, features, internalformat);
1151
1152     stateManager->bindTexture(getType(), mTextureID);
1153
1154     if (nativegl::UseTexImage2D(getType()))
1155     {
1156         ASSERT(size.depth == 1);
1157         if (functions->texStorage2DMultisample)
1158         {
1159             ANGLE_GL_TRY_ALWAYS_CHECK(
1160                 context, functions->texStorage2DMultisample(
1161                              ToGLenum(type), samples, texStorageFormat.internalFormat, size.width,
1162                              size.height, gl::ConvertToGLBoolean(fixedSampleLocations)));
1163         }
1164         else
1165         {
1166             // texImage2DMultisample is similar to texStorage2DMultisample of es 3.1 core feature,
1167             // On macos and some old drivers which doesn't support OpenGL ES 3.1, the function can
1168             // be supported by ARB_texture_multisample or OpenGL 3.2 core feature.
1169             ANGLE_GL_TRY_ALWAYS_CHECK(
1170                 context, functions->texImage2DMultisample(
1171                              ToGLenum(type), samples, texStorageFormat.internalFormat, size.width,
1172                              size.height, gl::ConvertToGLBoolean(fixedSampleLocations)));
1173         }
1174     }
1175     else
1176     {
1177         ASSERT(nativegl::UseTexImage3D(getType()));
1178         ANGLE_GL_TRY_ALWAYS_CHECK(
1179             context, functions->texStorage3DMultisample(
1180                          ToGLenum(type), samples, texStorageFormat.internalFormat, size.width,
1181                          size.height, size.depth, gl::ConvertToGLBoolean(fixedSampleLocations)));
1182     }
1183
1184     setLevelInfo(context, type, 0, 1,
1185                  GetLevelInfo(features, internalformat, texStorageFormat.internalFormat));
1186
1187     return angle::Result::Continue;
1188 }
1189
1190 angle::Result TextureGL::setStorageExternalMemory(const gl::Context *context,
1191                                                   gl::TextureType type,
1192                                                   size_t levels,
1193                                                   GLenum internalFormat,
1194                                                   const gl::Extents &size,
1195                                                   gl::MemoryObject *memoryObject,
1196                                                   GLuint64 offset)
1197 {
1198     const FunctionsGL *functions      = GetFunctionsGL(context);
1199     StateManagerGL *stateManager      = GetStateManagerGL(context);
1200     const angle::FeaturesGL &features = GetFeaturesGL(context);
1201
1202     MemoryObjectGL *memoryObjectGL = GetImplAs<MemoryObjectGL>(memoryObject);
1203
1204     nativegl::TexStorageFormat texStorageFormat =
1205         nativegl::GetTexStorageFormat(functions, features, internalFormat);
1206
1207     stateManager->bindTexture(getType(), mTextureID);
1208     if (nativegl::UseTexImage2D(getType()))
1209     {
1210         ANGLE_GL_TRY_ALWAYS_CHECK(
1211             context,
1212             functions->texStorageMem2DEXT(ToGLenum(type), static_cast<GLsizei>(levels),
1213                                           texStorageFormat.internalFormat, size.width, size.height,
1214                                           memoryObjectGL->getMemoryObjectID(), offset));
1215     }
1216     else
1217     {
1218         ASSERT(nativegl::UseTexImage3D(getType()));
1219         ANGLE_GL_TRY_ALWAYS_CHECK(
1220             context,
1221             functions->texStorageMem3DEXT(ToGLenum(type), static_cast<GLsizei>(levels),
1222                                           texStorageFormat.internalFormat, size.width, size.height,
1223                                           size.depth, memoryObjectGL->getMemoryObjectID(), offset));
1224     }
1225
1226     setLevelInfo(context, type, 0, levels,
1227                  GetLevelInfo(features, internalFormat, texStorageFormat.internalFormat));
1228
1229     return angle::Result::Continue;
1230 }
1231
1232 angle::Result TextureGL::setImageExternal(const gl::Context *context,
1233                                           gl::TextureType type,
1234                                           egl::Stream *stream,
1235                                           const egl::Stream::GLTextureDescription &desc)
1236 {
1237     ANGLE_GL_UNREACHABLE(GetImplAs<ContextGL>(context));
1238     return angle::Result::Stop;
1239 }
1240
1241 angle::Result TextureGL::generateMipmap(const gl::Context *context)
1242 {
1243     const FunctionsGL *functions = GetFunctionsGL(context);
1244     StateManagerGL *stateManager = GetStateManagerGL(context);
1245
1246     stateManager->bindTexture(getType(), mTextureID);
1247     ANGLE_GL_TRY_ALWAYS_CHECK(context, functions->generateMipmap(ToGLenum(getType())));
1248
1249     const GLuint effectiveBaseLevel = mState.getEffectiveBaseLevel();
1250     const GLuint maxLevel           = mState.getMipmapMaxLevel();
1251
1252     setLevelInfo(context, getType(), effectiveBaseLevel, maxLevel - effectiveBaseLevel,
1253                  getBaseLevelInfo());
1254
1255     return angle::Result::Continue;
1256 }
1257
1258 angle::Result TextureGL::bindTexImage(const gl::Context *context, egl::Surface *surface)
1259 {
1260     ASSERT(getType() == gl::TextureType::_2D || getType() == gl::TextureType::Rectangle);
1261
1262     StateManagerGL *stateManager = GetStateManagerGL(context);
1263
1264     // Make sure this texture is bound
1265     stateManager->bindTexture(getType(), mTextureID);
1266
1267     SurfaceGL *surfaceGL = GetImplAs<SurfaceGL>(surface);
1268
1269     setLevelInfo(context, getType(), 0, 1,
1270                  LevelInfoGL(GL_NONE, GL_NONE, false, LUMAWorkaroundGL(),
1271                              surfaceGL->hasEmulatedAlphaChannel()));
1272     return angle::Result::Continue;
1273 }
1274
1275 angle::Result TextureGL::releaseTexImage(const gl::Context *context)
1276 {
1277     ASSERT(getType() == gl::TextureType::_2D || getType() == gl::TextureType::Rectangle);
1278
1279     const angle::FeaturesGL &features = GetFeaturesGL(context);
1280     if (!features.resettingTexturesGeneratesErrors.enabled)
1281     {
1282         // Not all Surface implementations reset the size of mip 0 when releasing, do it manually
1283         const FunctionsGL *functions = GetFunctionsGL(context);
1284         StateManagerGL *stateManager = GetStateManagerGL(context);
1285
1286         stateManager->bindTexture(getType(), mTextureID);
1287         ASSERT(nativegl::UseTexImage2D(getType()));
1288         ANGLE_GL_TRY(context, functions->texImage2D(ToGLenum(getType()), 0, GL_RGBA, 0, 0, 0,
1289                                                     GL_RGBA, GL_UNSIGNED_BYTE, nullptr));
1290     }
1291
1292     return angle::Result::Continue;
1293 }
1294
1295 angle::Result TextureGL::setEGLImageTarget(const gl::Context *context,
1296                                            gl::TextureType type,
1297                                            egl::Image *image)
1298 {
1299     const angle::FeaturesGL &features = GetFeaturesGL(context);
1300
1301     ImageGL *imageGL = GetImplAs<ImageGL>(image);
1302
1303     GLenum imageNativeInternalFormat = GL_NONE;
1304     ANGLE_TRY(imageGL->setTexture2D(context, type, this, &imageNativeInternalFormat));
1305
1306     setLevelInfo(
1307         context, type, 0, 1,
1308         GetLevelInfo(features, image->getFormat().info->internalFormat, imageNativeInternalFormat));
1309
1310     return angle::Result::Continue;
1311 }
1312
1313 GLint TextureGL::getNativeID() const
1314 {
1315     return mTextureID;
1316 }
1317
1318 angle::Result TextureGL::syncState(const gl::Context *context,
1319                                    const gl::Texture::DirtyBits &dirtyBits)
1320 {
1321     if (dirtyBits.none() && mLocalDirtyBits.none())
1322     {
1323         return angle::Result::Continue;
1324     }
1325
1326     const FunctionsGL *functions = GetFunctionsGL(context);
1327     StateManagerGL *stateManager = GetStateManagerGL(context);
1328
1329     stateManager->bindTexture(getType(), mTextureID);
1330
1331     if (dirtyBits[gl::Texture::DIRTY_BIT_BASE_LEVEL] || dirtyBits[gl::Texture::DIRTY_BIT_MAX_LEVEL])
1332     {
1333         // Don't know if the previous base level was using any workarounds, always re-sync the
1334         // workaround dirty bits
1335         mLocalDirtyBits |= GetLevelWorkaroundDirtyBits();
1336     }
1337     for (auto dirtyBit : (dirtyBits | mLocalDirtyBits))
1338     {
1339
1340         switch (dirtyBit)
1341         {
1342             case gl::Texture::DIRTY_BIT_MIN_FILTER:
1343                 mAppliedSampler.setMinFilter(mState.getSamplerState().getMinFilter());
1344                 ANGLE_GL_TRY(context, functions->texParameteri(
1345                                           nativegl::GetTextureBindingTarget(getType()),
1346                                           GL_TEXTURE_MIN_FILTER, mAppliedSampler.getMinFilter()));
1347                 break;
1348             case gl::Texture::DIRTY_BIT_MAG_FILTER:
1349                 mAppliedSampler.setMagFilter(mState.getSamplerState().getMagFilter());
1350                 ANGLE_GL_TRY(context, functions->texParameteri(
1351                                           nativegl::GetTextureBindingTarget(getType()),
1352                                           GL_TEXTURE_MAG_FILTER, mAppliedSampler.getMagFilter()));
1353                 break;
1354             case gl::Texture::DIRTY_BIT_WRAP_S:
1355                 mAppliedSampler.setWrapS(mState.getSamplerState().getWrapS());
1356                 ANGLE_GL_TRY(context, functions->texParameteri(
1357                                           nativegl::GetTextureBindingTarget(getType()),
1358                                           GL_TEXTURE_WRAP_S, mAppliedSampler.getWrapS()));
1359                 break;
1360             case gl::Texture::DIRTY_BIT_WRAP_T:
1361                 mAppliedSampler.setWrapT(mState.getSamplerState().getWrapT());
1362                 ANGLE_GL_TRY(context, functions->texParameteri(
1363                                           nativegl::GetTextureBindingTarget(getType()),
1364                                           GL_TEXTURE_WRAP_T, mAppliedSampler.getWrapT()));
1365                 break;
1366             case gl::Texture::DIRTY_BIT_WRAP_R:
1367                 mAppliedSampler.setWrapR(mState.getSamplerState().getWrapR());
1368                 ANGLE_GL_TRY(context, functions->texParameteri(
1369                                           nativegl::GetTextureBindingTarget(getType()),
1370                                           GL_TEXTURE_WRAP_R, mAppliedSampler.getWrapR()));
1371                 break;
1372             case gl::Texture::DIRTY_BIT_MAX_ANISOTROPY:
1373                 mAppliedSampler.setMaxAnisotropy(mState.getSamplerState().getMaxAnisotropy());
1374                 ANGLE_GL_TRY(context,
1375                              functions->texParameterf(nativegl::GetTextureBindingTarget(getType()),
1376                                                       GL_TEXTURE_MAX_ANISOTROPY_EXT,
1377                                                       mAppliedSampler.getMaxAnisotropy()));
1378                 break;
1379             case gl::Texture::DIRTY_BIT_MIN_LOD:
1380                 mAppliedSampler.setMinLod(mState.getSamplerState().getMinLod());
1381                 ANGLE_GL_TRY(context, functions->texParameterf(
1382                                           nativegl::GetTextureBindingTarget(getType()),
1383                                           GL_TEXTURE_MIN_LOD, mAppliedSampler.getMinLod()));
1384                 break;
1385             case gl::Texture::DIRTY_BIT_MAX_LOD:
1386                 mAppliedSampler.setMaxLod(mState.getSamplerState().getMaxLod());
1387                 ANGLE_GL_TRY(context, functions->texParameterf(
1388                                           nativegl::GetTextureBindingTarget(getType()),
1389                                           GL_TEXTURE_MAX_LOD, mAppliedSampler.getMaxLod()));
1390                 break;
1391             case gl::Texture::DIRTY_BIT_COMPARE_MODE:
1392                 mAppliedSampler.setCompareMode(mState.getSamplerState().getCompareMode());
1393                 ANGLE_GL_TRY(context,
1394                              functions->texParameteri(nativegl::GetTextureBindingTarget(getType()),
1395                                                       GL_TEXTURE_COMPARE_MODE,
1396                                                       mAppliedSampler.getCompareMode()));
1397                 break;
1398             case gl::Texture::DIRTY_BIT_COMPARE_FUNC:
1399                 mAppliedSampler.setCompareFunc(mState.getSamplerState().getCompareFunc());
1400                 ANGLE_GL_TRY(context,
1401                              functions->texParameteri(nativegl::GetTextureBindingTarget(getType()),
1402                                                       GL_TEXTURE_COMPARE_FUNC,
1403                                                       mAppliedSampler.getCompareFunc()));
1404                 break;
1405             case gl::Texture::DIRTY_BIT_SRGB_DECODE:
1406                 mAppliedSampler.setSRGBDecode(mState.getSamplerState().getSRGBDecode());
1407                 ANGLE_GL_TRY(context,
1408                              functions->texParameteri(nativegl::GetTextureBindingTarget(getType()),
1409                                                       GL_TEXTURE_SRGB_DECODE_EXT,
1410                                                       mAppliedSampler.getSRGBDecode()));
1411                 break;
1412             case gl::Texture::DIRTY_BIT_BORDER_COLOR:
1413             {
1414                 const angle::ColorGeneric &borderColor(mState.getSamplerState().getBorderColor());
1415                 mAppliedSampler.setBorderColor(borderColor);
1416                 switch (borderColor.type)
1417                 {
1418                     case angle::ColorGeneric::Type::Float:
1419                         ANGLE_GL_TRY(context,
1420                                      functions->texParameterfv(
1421                                          nativegl::GetTextureBindingTarget(getType()),
1422                                          GL_TEXTURE_BORDER_COLOR, &borderColor.colorF.red));
1423                         break;
1424                     case angle::ColorGeneric::Type::Int:
1425                         ANGLE_GL_TRY(context,
1426                                      functions->texParameterIiv(
1427                                          nativegl::GetTextureBindingTarget(getType()),
1428                                          GL_TEXTURE_BORDER_COLOR, &borderColor.colorI.red));
1429                         break;
1430                     case angle::ColorGeneric::Type::UInt:
1431                         ANGLE_GL_TRY(context,
1432                                      functions->texParameterIuiv(
1433                                          nativegl::GetTextureBindingTarget(getType()),
1434                                          GL_TEXTURE_BORDER_COLOR, &borderColor.colorUI.red));
1435                         break;
1436                     default:
1437                         UNREACHABLE();
1438                         break;
1439                 }
1440                 break;
1441             }
1442
1443             // Texture state
1444             case gl::Texture::DIRTY_BIT_SWIZZLE_RED:
1445                 ANGLE_TRY(syncTextureStateSwizzle(context, functions, GL_TEXTURE_SWIZZLE_R,
1446                                                   mState.getSwizzleState().swizzleRed,
1447                                                   &mAppliedSwizzle.swizzleRed));
1448                 break;
1449             case gl::Texture::DIRTY_BIT_SWIZZLE_GREEN:
1450                 ANGLE_TRY(syncTextureStateSwizzle(context, functions, GL_TEXTURE_SWIZZLE_G,
1451                                                   mState.getSwizzleState().swizzleGreen,
1452                                                   &mAppliedSwizzle.swizzleGreen));
1453                 break;
1454             case gl::Texture::DIRTY_BIT_SWIZZLE_BLUE:
1455                 ANGLE_TRY(syncTextureStateSwizzle(context, functions, GL_TEXTURE_SWIZZLE_B,
1456                                                   mState.getSwizzleState().swizzleBlue,
1457                                                   &mAppliedSwizzle.swizzleBlue));
1458                 break;
1459             case gl::Texture::DIRTY_BIT_SWIZZLE_ALPHA:
1460                 ANGLE_TRY(syncTextureStateSwizzle(context, functions, GL_TEXTURE_SWIZZLE_A,
1461                                                   mState.getSwizzleState().swizzleAlpha,
1462                                                   &mAppliedSwizzle.swizzleAlpha));
1463                 break;
1464             case gl::Texture::DIRTY_BIT_BASE_LEVEL:
1465                 mAppliedBaseLevel = mState.getEffectiveBaseLevel();
1466                 ANGLE_GL_TRY(context,
1467                              functions->texParameteri(nativegl::GetTextureBindingTarget(getType()),
1468                                                       GL_TEXTURE_BASE_LEVEL, mAppliedBaseLevel));
1469                 break;
1470             case gl::Texture::DIRTY_BIT_MAX_LEVEL:
1471                 mAppliedMaxLevel = mState.getEffectiveMaxLevel();
1472                 ANGLE_GL_TRY(context,
1473                              functions->texParameteri(nativegl::GetTextureBindingTarget(getType()),
1474                                                       GL_TEXTURE_MAX_LEVEL, mAppliedMaxLevel));
1475                 break;
1476             case gl::Texture::DIRTY_BIT_DEPTH_STENCIL_TEXTURE_MODE:
1477             {
1478                 GLenum mDepthStencilTextureMode = mState.getDepthStencilTextureMode();
1479                 ANGLE_GL_TRY(context, functions->texParameteri(
1480                                           nativegl::GetTextureBindingTarget(getType()),
1481                                           GL_DEPTH_STENCIL_TEXTURE_MODE, mDepthStencilTextureMode));
1482                 break;
1483             }
1484             case gl::Texture::DIRTY_BIT_USAGE:
1485                 break;
1486             case gl::Texture::DIRTY_BIT_LABEL:
1487                 break;
1488
1489             case gl::Texture::DIRTY_BIT_IMPLEMENTATION:
1490                 // This special dirty bit is used to signal the front-end that the implementation
1491                 // has local dirty bits. The real dirty bits are in mLocalDirty bits.
1492                 break;
1493             case gl::Texture::DIRTY_BIT_BOUND_AS_IMAGE:
1494                 // Only used for Vulkan.
1495                 break;
1496
1497             default:
1498                 UNREACHABLE();
1499         }
1500     }
1501
1502     mLocalDirtyBits.reset();
1503     return angle::Result::Continue;
1504 }
1505
1506 bool TextureGL::hasAnyDirtyBit() const
1507 {
1508     return mLocalDirtyBits.any();
1509 }
1510
1511 angle::Result TextureGL::setBaseLevel(const gl::Context *context, GLuint baseLevel)
1512 {
1513     if (baseLevel != mAppliedBaseLevel)
1514     {
1515         const FunctionsGL *functions = GetFunctionsGL(context);
1516         StateManagerGL *stateManager = GetStateManagerGL(context);
1517
1518         mAppliedBaseLevel = baseLevel;
1519         mLocalDirtyBits.set(gl::Texture::DIRTY_BIT_BASE_LEVEL);
1520
1521         // Signal to the GL layer that the Impl has dirty bits.
1522         onStateChange(angle::SubjectMessage::DirtyBitsFlagged);
1523
1524         stateManager->bindTexture(getType(), mTextureID);
1525         ANGLE_GL_TRY(context, functions->texParameteri(ToGLenum(getType()), GL_TEXTURE_BASE_LEVEL,
1526                                                        baseLevel));
1527     }
1528     return angle::Result::Continue;
1529 }
1530
1531 angle::Result TextureGL::setMaxLevel(const gl::Context *context, GLuint maxLevel)
1532 {
1533     if (maxLevel != mAppliedMaxLevel)
1534     {
1535         const FunctionsGL *functions = GetFunctionsGL(context);
1536         StateManagerGL *stateManager = GetStateManagerGL(context);
1537
1538         mAppliedMaxLevel = maxLevel;
1539         mLocalDirtyBits.set(gl::Texture::DIRTY_BIT_MAX_LEVEL);
1540
1541         // Signal to the GL layer that the Impl has dirty bits.
1542         onStateChange(angle::SubjectMessage::DirtyBitsFlagged);
1543
1544         stateManager->bindTexture(getType(), mTextureID);
1545         ANGLE_GL_TRY(context,
1546                      functions->texParameteri(ToGLenum(getType()), GL_TEXTURE_MAX_LEVEL, maxLevel));
1547     }
1548     return angle::Result::Continue;
1549 }
1550
1551 angle::Result TextureGL::setMinFilter(const gl::Context *context, GLenum filter)
1552 {
1553     if (filter != mAppliedSampler.getMinFilter())
1554     {
1555         const FunctionsGL *functions = GetFunctionsGL(context);
1556         StateManagerGL *stateManager = GetStateManagerGL(context);
1557
1558         mAppliedSampler.setMinFilter(filter);
1559         mLocalDirtyBits.set(gl::Texture::DIRTY_BIT_MIN_FILTER);
1560
1561         // Signal to the GL layer that the Impl has dirty bits.
1562         onStateChange(angle::SubjectMessage::DirtyBitsFlagged);
1563
1564         stateManager->bindTexture(getType(), mTextureID);
1565         ANGLE_GL_TRY(context,
1566                      functions->texParameteri(ToGLenum(getType()), GL_TEXTURE_MIN_FILTER, filter));
1567     }
1568     return angle::Result::Continue;
1569 }
1570 angle::Result TextureGL::setMagFilter(const gl::Context *context, GLenum filter)
1571 {
1572     if (filter != mAppliedSampler.getMagFilter())
1573     {
1574         const FunctionsGL *functions = GetFunctionsGL(context);
1575         StateManagerGL *stateManager = GetStateManagerGL(context);
1576
1577         mAppliedSampler.setMagFilter(filter);
1578         mLocalDirtyBits.set(gl::Texture::DIRTY_BIT_MAG_FILTER);
1579
1580         // Signal to the GL layer that the Impl has dirty bits.
1581         onStateChange(angle::SubjectMessage::DirtyBitsFlagged);
1582
1583         stateManager->bindTexture(getType(), mTextureID);
1584         ANGLE_GL_TRY(context,
1585                      functions->texParameteri(ToGLenum(getType()), GL_TEXTURE_MAG_FILTER, filter));
1586     }
1587     return angle::Result::Continue;
1588 }
1589
1590 angle::Result TextureGL::setSwizzle(const gl::Context *context, GLint swizzle[4])
1591 {
1592     gl::SwizzleState resultingSwizzle =
1593         gl::SwizzleState(swizzle[0], swizzle[1], swizzle[2], swizzle[3]);
1594
1595     if (resultingSwizzle != mAppliedSwizzle)
1596     {
1597         const FunctionsGL *functions = GetFunctionsGL(context);
1598         StateManagerGL *stateManager = GetStateManagerGL(context);
1599
1600         mAppliedSwizzle = resultingSwizzle;
1601         mLocalDirtyBits.set(gl::Texture::DIRTY_BIT_SWIZZLE_RED);
1602         mLocalDirtyBits.set(gl::Texture::DIRTY_BIT_SWIZZLE_GREEN);
1603         mLocalDirtyBits.set(gl::Texture::DIRTY_BIT_SWIZZLE_BLUE);
1604         mLocalDirtyBits.set(gl::Texture::DIRTY_BIT_SWIZZLE_ALPHA);
1605
1606         // Signal to the GL layer that the Impl has dirty bits.
1607         onStateChange(angle::SubjectMessage::DirtyBitsFlagged);
1608
1609         stateManager->bindTexture(getType(), mTextureID);
1610         if (functions->standard == STANDARD_GL_ES)
1611         {
1612             ANGLE_GL_TRY(context, functions->texParameteri(ToGLenum(getType()),
1613                                                            GL_TEXTURE_SWIZZLE_R, swizzle[0]));
1614             ANGLE_GL_TRY(context, functions->texParameteri(ToGLenum(getType()),
1615                                                            GL_TEXTURE_SWIZZLE_G, swizzle[1]));
1616             ANGLE_GL_TRY(context, functions->texParameteri(ToGLenum(getType()),
1617                                                            GL_TEXTURE_SWIZZLE_B, swizzle[2]));
1618             ANGLE_GL_TRY(context, functions->texParameteri(ToGLenum(getType()),
1619                                                            GL_TEXTURE_SWIZZLE_A, swizzle[3]));
1620         }
1621         else
1622         {
1623             ANGLE_GL_TRY(context, functions->texParameteriv(ToGLenum(getType()),
1624                                                             GL_TEXTURE_SWIZZLE_RGBA, swizzle));
1625         }
1626     }
1627     return angle::Result::Continue;
1628 }
1629
1630 GLenum TextureGL::getNativeInternalFormat(const gl::ImageIndex &index) const
1631 {
1632     return getLevelInfo(index.getTarget(), index.getLevelIndex()).nativeInternalFormat;
1633 }
1634
1635 bool TextureGL::hasEmulatedAlphaChannel(const gl::ImageIndex &index) const
1636 {
1637     return getLevelInfo(index.getTargetOrFirstCubeFace(), index.getLevelIndex())
1638         .emulatedAlphaChannel;
1639 }
1640
1641 angle::Result TextureGL::syncTextureStateSwizzle(const gl::Context *context,
1642                                                  const FunctionsGL *functions,
1643                                                  GLenum name,
1644                                                  GLenum value,
1645                                                  GLenum *outValue)
1646 {
1647     const LevelInfoGL &levelInfo = getBaseLevelInfo();
1648     GLenum resultSwizzle         = value;
1649     if (levelInfo.lumaWorkaround.enabled)
1650     {
1651         switch (value)
1652         {
1653             case GL_RED:
1654             case GL_GREEN:
1655             case GL_BLUE:
1656                 if (levelInfo.sourceFormat == GL_LUMINANCE ||
1657                     levelInfo.sourceFormat == GL_LUMINANCE_ALPHA)
1658                 {
1659                     // Texture is backed by a RED or RG texture, point all color channels at the
1660                     // red channel.
1661                     ASSERT(levelInfo.lumaWorkaround.workaroundFormat == GL_RED ||
1662                            levelInfo.lumaWorkaround.workaroundFormat == GL_RG);
1663                     resultSwizzle = GL_RED;
1664                 }
1665                 else
1666                 {
1667                     ASSERT(levelInfo.sourceFormat == GL_ALPHA);
1668                     // Color channels are not supposed to exist, make them always sample 0.
1669                     resultSwizzle = GL_ZERO;
1670                 }
1671                 break;
1672
1673             case GL_ALPHA:
1674                 if (levelInfo.sourceFormat == GL_LUMINANCE)
1675                 {
1676                     // Alpha channel is not supposed to exist, make it always sample 1.
1677                     resultSwizzle = GL_ONE;
1678                 }
1679                 else if (levelInfo.sourceFormat == GL_ALPHA)
1680                 {
1681                     // Texture is backed by a RED texture, point the alpha channel at the red
1682                     // channel.
1683                     ASSERT(levelInfo.lumaWorkaround.workaroundFormat == GL_RED);
1684                     resultSwizzle = GL_RED;
1685                 }
1686                 else
1687                 {
1688                     ASSERT(levelInfo.sourceFormat == GL_LUMINANCE_ALPHA);
1689                     // Texture is backed by an RG texture, point the alpha channel at the green
1690                     // channel.
1691                     ASSERT(levelInfo.lumaWorkaround.workaroundFormat == GL_RG);
1692                     resultSwizzle = GL_GREEN;
1693                 }
1694                 break;
1695
1696             case GL_ZERO:
1697             case GL_ONE:
1698                 // Don't modify the swizzle state when requesting ZERO or ONE.
1699                 resultSwizzle = value;
1700                 break;
1701
1702             default:
1703                 UNREACHABLE();
1704                 break;
1705         }
1706     }
1707     else if (levelInfo.depthStencilWorkaround)
1708     {
1709         switch (value)
1710         {
1711             case GL_RED:
1712                 // Don't modify the swizzle state when requesting the red channel.
1713                 resultSwizzle = value;
1714                 break;
1715
1716             case GL_GREEN:
1717             case GL_BLUE:
1718                 if (context->getClientMajorVersion() <= 2)
1719                 {
1720                     // In OES_depth_texture/ARB_depth_texture, depth
1721                     // textures are treated as luminance.
1722                     resultSwizzle = GL_RED;
1723                 }
1724                 else
1725                 {
1726                     // In GLES 3.0, depth textures are treated as RED
1727                     // textures, so green and blue should be 0.
1728                     resultSwizzle = GL_ZERO;
1729                 }
1730                 break;
1731
1732             case GL_ALPHA:
1733                 // Depth textures should sample 1 from the alpha channel.
1734                 resultSwizzle = GL_ONE;
1735                 break;
1736
1737             case GL_ZERO:
1738             case GL_ONE:
1739                 // Don't modify the swizzle state when requesting ZERO or ONE.
1740                 resultSwizzle = value;
1741                 break;
1742
1743             default:
1744                 UNREACHABLE();
1745                 break;
1746         }
1747     }
1748     else if (levelInfo.emulatedAlphaChannel)
1749     {
1750         if (value == GL_ALPHA)
1751         {
1752             resultSwizzle = GL_ONE;
1753         }
1754     }
1755
1756     *outValue = resultSwizzle;
1757     ANGLE_GL_TRY(context, functions->texParameteri(ToGLenum(getType()), name, resultSwizzle));
1758
1759     return angle::Result::Continue;
1760 }
1761
1762 void TextureGL::setLevelInfo(const gl::Context *context,
1763                              gl::TextureTarget target,
1764                              size_t level,
1765                              size_t levelCount,
1766                              const LevelInfoGL &levelInfo)
1767 {
1768     ASSERT(levelCount > 0);
1769
1770     bool updateWorkarounds = levelInfo.depthStencilWorkaround || levelInfo.lumaWorkaround.enabled ||
1771                              levelInfo.emulatedAlphaChannel;
1772
1773     for (size_t i = level; i < level + levelCount; i++)
1774     {
1775         size_t index = GetLevelInfoIndex(target, i);
1776         ASSERT(index < mLevelInfo.size());
1777         auto &curLevelInfo = mLevelInfo[index];
1778
1779         updateWorkarounds |= curLevelInfo.depthStencilWorkaround;
1780         updateWorkarounds |= curLevelInfo.lumaWorkaround.enabled;
1781         updateWorkarounds |= curLevelInfo.emulatedAlphaChannel;
1782
1783         curLevelInfo = levelInfo;
1784     }
1785
1786     if (updateWorkarounds)
1787     {
1788         mLocalDirtyBits |= GetLevelWorkaroundDirtyBits();
1789         onStateChange(angle::SubjectMessage::DirtyBitsFlagged);
1790     }
1791 }
1792
1793 void TextureGL::setLevelInfo(const gl::Context *context,
1794                              gl::TextureType type,
1795                              size_t level,
1796                              size_t levelCount,
1797                              const LevelInfoGL &levelInfo)
1798 {
1799     if (type == gl::TextureType::CubeMap)
1800     {
1801         for (gl::TextureTarget target : gl::AllCubeFaceTextureTargets())
1802         {
1803             setLevelInfo(context, target, level, levelCount, levelInfo);
1804         }
1805     }
1806     else
1807     {
1808         setLevelInfo(context, NonCubeTextureTypeToTarget(type), level, levelCount, levelInfo);
1809     }
1810 }
1811
1812 const LevelInfoGL &TextureGL::getLevelInfo(gl::TextureTarget target, size_t level) const
1813 {
1814     return mLevelInfo[GetLevelInfoIndex(target, level)];
1815 }
1816
1817 const LevelInfoGL &TextureGL::getBaseLevelInfo() const
1818 {
1819     GLint effectiveBaseLevel = mState.getEffectiveBaseLevel();
1820     gl::TextureTarget target = getType() == gl::TextureType::CubeMap
1821                                    ? gl::kCubeMapTextureTargetMin
1822                                    : gl::NonCubeTextureTypeToTarget(getType());
1823     return getLevelInfo(target, effectiveBaseLevel);
1824 }
1825
1826 gl::TextureType TextureGL::getType() const
1827 {
1828     return mState.mType;
1829 }
1830
1831 angle::Result TextureGL::initializeContents(const gl::Context *context,
1832                                             const gl::ImageIndex &imageIndex)
1833 {
1834     ContextGL *contextGL              = GetImplAs<ContextGL>(context);
1835     const FunctionsGL *functions      = GetFunctionsGL(context);
1836     StateManagerGL *stateManager      = GetStateManagerGL(context);
1837     const angle::FeaturesGL &features = GetFeaturesGL(context);
1838
1839     bool shouldUseClear = !nativegl::SupportsTexImage(getType());
1840     GLenum nativeInternalFormat =
1841         getLevelInfo(imageIndex.getTarget(), imageIndex.getLevelIndex()).nativeInternalFormat;
1842     if ((features.allowClearForRobustResourceInit.enabled || shouldUseClear) &&
1843         nativegl::SupportsNativeRendering(functions, mState.getType(), nativeInternalFormat))
1844     {
1845         BlitGL *blitter = GetBlitGL(context);
1846
1847         int levelDepth = mState.getImageDesc(imageIndex).size.depth;
1848
1849         bool clearSucceeded = false;
1850         ANGLE_TRY(blitter->clearRenderableTexture(context, this, nativeInternalFormat, levelDepth,
1851                                                   imageIndex, &clearSucceeded));
1852         if (clearSucceeded)
1853         {
1854             return angle::Result::Continue;
1855         }
1856     }
1857
1858     // Either the texture is not renderable or was incomplete when clearing, fall back to a data
1859     // upload
1860     ASSERT(nativegl::SupportsTexImage(getType()));
1861     const gl::ImageDesc &desc                    = mState.getImageDesc(imageIndex);
1862     const gl::InternalFormat &internalFormatInfo = *desc.format.info;
1863
1864     gl::PixelUnpackState unpackState;
1865     unpackState.alignment = 1;
1866     stateManager->setPixelUnpackState(unpackState);
1867
1868     GLuint prevUnpackBuffer = stateManager->getBufferID(gl::BufferBinding::PixelUnpack);
1869     stateManager->bindBuffer(gl::BufferBinding::PixelUnpack, 0);
1870
1871     stateManager->bindTexture(getType(), mTextureID);
1872     if (internalFormatInfo.compressed)
1873     {
1874         nativegl::CompressedTexSubImageFormat nativeSubImageFormat =
1875             nativegl::GetCompressedSubTexImageFormat(functions, features,
1876                                                      internalFormatInfo.internalFormat);
1877
1878         GLuint imageSize = 0;
1879         ANGLE_CHECK_GL_MATH(contextGL,
1880                             internalFormatInfo.computeCompressedImageSize(desc.size, &imageSize));
1881
1882         angle::MemoryBuffer *zero;
1883         ANGLE_CHECK_GL_ALLOC(contextGL, context->getZeroFilledBuffer(imageSize, &zero));
1884
1885         // WebGL spec requires that zero data is uploaded to compressed textures even if it might
1886         // not result in zero color data.
1887         if (nativegl::UseTexImage2D(getType()))
1888         {
1889             ANGLE_GL_TRY(context, functions->compressedTexSubImage2D(
1890                                       ToGLenum(imageIndex.getTarget()), imageIndex.getLevelIndex(),
1891                                       0, 0, desc.size.width, desc.size.height,
1892                                       nativeSubImageFormat.format, imageSize, zero->data()));
1893         }
1894         else
1895         {
1896             ASSERT(nativegl::UseTexImage3D(getType()));
1897             ANGLE_GL_TRY(context, functions->compressedTexSubImage3D(
1898                                       ToGLenum(imageIndex.getTarget()), imageIndex.getLevelIndex(),
1899                                       0, 0, 0, desc.size.width, desc.size.height, desc.size.depth,
1900                                       nativeSubImageFormat.format, imageSize, zero->data()));
1901         }
1902     }
1903     else
1904     {
1905         nativegl::TexSubImageFormat nativeSubImageFormat = nativegl::GetTexSubImageFormat(
1906             functions, features, internalFormatInfo.format, internalFormatInfo.type);
1907
1908         GLuint imageSize = 0;
1909         ANGLE_CHECK_GL_MATH(contextGL, internalFormatInfo.computePackUnpackEndByte(
1910                                            nativeSubImageFormat.type, desc.size, unpackState,
1911                                            nativegl::UseTexImage3D(getType()), &imageSize));
1912
1913         angle::MemoryBuffer *zero;
1914         ANGLE_CHECK_GL_ALLOC(contextGL, context->getZeroFilledBuffer(imageSize, &zero));
1915
1916         if (nativegl::UseTexImage2D(getType()))
1917         {
1918             ANGLE_GL_TRY(context,
1919                          functions->texSubImage2D(ToGLenum(imageIndex.getTarget()),
1920                                                   imageIndex.getLevelIndex(), 0, 0, desc.size.width,
1921                                                   desc.size.height, nativeSubImageFormat.format,
1922                                                   nativeSubImageFormat.type, zero->data()));
1923         }
1924         else
1925         {
1926             ASSERT(nativegl::UseTexImage3D(getType()));
1927             ANGLE_GL_TRY(context,
1928                          functions->texSubImage3D(
1929                              ToGLenum(imageIndex.getTarget()), imageIndex.getLevelIndex(), 0, 0, 0,
1930                              desc.size.width, desc.size.height, desc.size.depth,
1931                              nativeSubImageFormat.format, nativeSubImageFormat.type, zero->data()));
1932         }
1933     }
1934
1935     // Reset the pixel unpack state.  Because this call is made after synchronizing dirty bits in a
1936     // glTexImage call, we need to make sure that the texture data to be uploaded later has the
1937     // expected unpack state.
1938     stateManager->setPixelUnpackState(context->getState().getUnpackState());
1939     stateManager->bindBuffer(gl::BufferBinding::PixelUnpack, prevUnpackBuffer);
1940
1941     return angle::Result::Continue;
1942 }
1943
1944 }  // namespace rx