aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/gpu/gl
diff options
context:
space:
mode:
authorGravatar cblume <cblume@chromium.org>2016-02-29 11:13:29 -0800
committerGravatar Commit bot <commit-bot@chromium.org>2016-02-29 11:13:29 -0800
commit790d5132620d86813380d3df251e80dd2b41a409 (patch)
treed2d37a00140b9bf2b88a0d248e09bf67759c2fb9 /src/gpu/gl
parentc58487e088fb7803b7b5fc5348c99d4a717c72df (diff)
This CL adds glTexStorage support.
For us to take advantage of immutable texture storage, we would need to know in advance that the texture will not be changing allocated size. In some cases we cannot know this in advance: we will sometimes later need mipmaps to be allocated and generated. However, in the cases where we know in advance that we are allocating mipmaps we can take advantage of immutable storage. BUG=476416 GOLD_TRYBOT_URL= https://gold.skia.org/search2?unt=true&query=source_type%3Dgm&master=false&issue=1570173004 Review URL: https://codereview.chromium.org/1570173004
Diffstat (limited to 'src/gpu/gl')
-rw-r--r--src/gpu/gl/GrGLCaps.cpp68
-rw-r--r--src/gpu/gl/GrGLCaps.h10
-rw-r--r--src/gpu/gl/GrGLGpu.cpp170
3 files changed, 189 insertions, 59 deletions
diff --git a/src/gpu/gl/GrGLCaps.cpp b/src/gpu/gl/GrGLCaps.cpp
index 989c799a37..792f3ed5ba 100644
--- a/src/gpu/gl/GrGLCaps.cpp
+++ b/src/gpu/gl/GrGLCaps.cpp
@@ -33,7 +33,6 @@ GrGLCaps::GrGLCaps(const GrContextOptions& contextOptions,
fPackRowLengthSupport = false;
fPackFlipYSupport = false;
fTextureUsageSupport = false;
- fTexStorageSupport = false;
fTextureRedSupport = false;
fImagingSupport = false;
fVertexArrayObjectSupport = false;
@@ -107,18 +106,6 @@ void GrGLCaps::init(const GrContextOptions& contextOptions,
ctxInfo.hasExtension("GL_ANGLE_texture_usage");
if (kGL_GrGLStandard == standard) {
- // The EXT version can apply to either GL or GLES.
- fTexStorageSupport = version >= GR_GL_VER(4,2) ||
- ctxInfo.hasExtension("GL_ARB_texture_storage") ||
- ctxInfo.hasExtension("GL_EXT_texture_storage");
- } else {
- // Qualcomm Adreno drivers appear to have issues with texture storage.
- fTexStorageSupport = (version >= GR_GL_VER(3,0) &&
- kQualcomm_GrGLVendor != ctxInfo.vendor()) &&
- ctxInfo.hasExtension("GL_EXT_texture_storage");
- }
-
- if (kGL_GrGLStandard == standard) {
fTextureBarrierSupport = version >= GR_GL_VER(4,5) ||
ctxInfo.hasExtension("GL_ARB_texture_barrier") ||
ctxInfo.hasExtension("GL_NV_texture_barrier");
@@ -530,7 +517,6 @@ void GrGLCaps::init(const GrContextOptions& contextOptions,
// TODO: remove after command buffer supports full ES 3.0.
if (kGLES_GrGLStandard == standard && version >= GR_GL_VER(3, 0) &&
kChromium_GrGLDriver == ctxInfo.driver()) {
- fTexStorageSupport = false;
fSupportsInstancedDraws = false;
fTextureSwizzleSupport = false;
SkASSERT(ctxInfo.hasExtension("GL_CHROMIUM_map_sub"));
@@ -1036,7 +1022,6 @@ SkString GrGLCaps::dump() const {
r.appendf("Pack Flip Y support: %s\n", (fPackFlipYSupport ? "YES": "NO"));
r.appendf("Texture Usage support: %s\n", (fTextureUsageSupport ? "YES": "NO"));
- r.appendf("Texture Storage support: %s\n", (fTexStorageSupport ? "YES": "NO"));
r.appendf("GL_R support: %s\n", (fTextureRedSupport ? "YES": "NO"));
r.appendf("GL_ARB_imaging support: %s\n", (fImagingSupport ? "YES": "NO"));
r.appendf("Vertex array object support: %s\n", (fVertexArrayObjectSupport ? "YES": "NO"));
@@ -1313,6 +1298,25 @@ void GrGLCaps::initConfigTable(const GrGLContextInfo& ctxInfo, const GrGLInterfa
GrGLStandard standard = ctxInfo.standard();
GrGLVersion version = ctxInfo.version();
+ bool texStorageSupported = false;
+ if (kGL_GrGLStandard == standard) {
+ // The EXT version can apply to either GL or GLES.
+ texStorageSupported = version >= GR_GL_VER(4,2) ||
+ ctxInfo.hasExtension("GL_ARB_texture_storage") ||
+ ctxInfo.hasExtension("GL_EXT_texture_storage");
+ } else {
+ // Qualcomm Adreno drivers appear to have issues with texture storage.
+ texStorageSupported = (version >= GR_GL_VER(3,0) &&
+ kQualcomm_GrGLVendor != ctxInfo.vendor()) &&
+ ctxInfo.hasExtension("GL_EXT_texture_storage");
+ }
+
+ // TODO: remove after command buffer supports full ES 3.0
+ if (kGLES_GrGLStandard == standard && version >= GR_GL_VER(3,0) &&
+ kChromium_GrGLDriver == ctxInfo.driver()) {
+ texStorageSupported = false;
+ }
+
fConfigTable[kUnknown_GrPixelConfig].fFormats.fBaseInternalFormat = 0;
fConfigTable[kUnknown_GrPixelConfig].fFormats.fSizedInternalFormat = 0;
fConfigTable[kUnknown_GrPixelConfig].fFormats.fExternalFormat[kOther_ExternalFormatUsage] = 0;
@@ -1336,6 +1340,9 @@ void GrGLCaps::initConfigTable(const GrGLContextInfo& ctxInfo, const GrGLInterfa
fConfigTable[kRGBA_8888_GrPixelConfig].fFlags |= allRenderFlags;
}
}
+ if (texStorageSupported) {
+ fConfigTable[kRGBA_8888_GrPixelConfig].fFlags |= ConfigInfo::kCanUseTexStorage_Flag;
+ }
fConfigTable[kRGBA_8888_GrPixelConfig].fSwizzle = GrSwizzle::RGBA();
fConfigTable[kBGRA_8888_GrPixelConfig].fFormats.fExternalFormat[kOther_ExternalFormatUsage] =
@@ -1373,6 +1380,9 @@ void GrGLCaps::initConfigTable(const GrGLContextInfo& ctxInfo, const GrGLInterfa
}
}
}
+ if (texStorageSupported) {
+ fConfigTable[kBGRA_8888_GrPixelConfig].fFlags |= ConfigInfo::kCanUseTexStorage_Flag;
+ }
fConfigTable[kBGRA_8888_GrPixelConfig].fSwizzle = GrSwizzle::RGBA();
// We only enable srgb support if both textures and FBOs support srgb.
@@ -1408,6 +1418,9 @@ void GrGLCaps::initConfigTable(const GrGLContextInfo& ctxInfo, const GrGLInterfa
fConfigTable[kSRGBA_8888_GrPixelConfig].fFlags = ConfigInfo::kTextureable_Flag |
allRenderFlags;
}
+ if (texStorageSupported) {
+ fConfigTable[kSRGBA_8888_GrPixelConfig].fFlags |= ConfigInfo::kCanUseTexStorage_Flag;
+ }
fConfigTable[kSRGBA_8888_GrPixelConfig].fSwizzle = GrSwizzle::RGBA();
fConfigTable[kRGB_565_GrPixelConfig].fFormats.fBaseInternalFormat = GR_GL_RGB;
@@ -1428,6 +1441,16 @@ void GrGLCaps::initConfigTable(const GrGLContextInfo& ctxInfo, const GrGLInterfa
} else {
fConfigTable[kRGB_565_GrPixelConfig].fFlags |= allRenderFlags;
}
+ // 565 is not a sized internal format on desktop GL. So on desktop with
+ // 565 we always use an unsized internal format to let the system pick
+ // the best sized format to convert the 565 data to. Since TexStorage
+ // only allows sized internal formats we disallow it.
+ //
+ // TODO: As of 4.2, regular GL supports 565. This logic is due for an
+ // update.
+ if (texStorageSupported && kGL_GrGLStandard != standard) {
+ fConfigTable[kRGB_565_GrPixelConfig].fFlags |= ConfigInfo::kCanUseTexStorage_Flag;
+ }
fConfigTable[kRGB_565_GrPixelConfig].fSwizzle = GrSwizzle::RGBA();
fConfigTable[kRGBA_4444_GrPixelConfig].fFormats.fBaseInternalFormat = GR_GL_RGBA;
@@ -1444,6 +1467,9 @@ void GrGLCaps::initConfigTable(const GrGLContextInfo& ctxInfo, const GrGLInterfa
} else {
fConfigTable[kRGBA_4444_GrPixelConfig].fFlags |= allRenderFlags;
}
+ if (texStorageSupported) {
+ fConfigTable[kRGBA_4444_GrPixelConfig].fFlags |= ConfigInfo::kCanUseTexStorage_Flag;
+ }
fConfigTable[kRGBA_4444_GrPixelConfig].fSwizzle = GrSwizzle::RGBA();
if (this->textureRedSupport()) {
@@ -1467,6 +1493,9 @@ void GrGLCaps::initConfigTable(const GrGLContextInfo& ctxInfo, const GrGLInterfa
// Core profile removes ALPHA8 support, but we should have chosen R8 in that case.
fConfigTable[kAlpha_8_GrPixelConfig].fFlags |= allRenderFlags;
}
+ if (texStorageSupported) {
+ fConfigTable[kAlpha_8_GrPixelConfig].fFlags |= ConfigInfo::kCanUseTexStorage_Flag;
+ }
// Check for [half] floating point texture support
// NOTE: We disallow floating point textures on ES devices if linear filtering modes are not
@@ -1514,6 +1543,9 @@ void GrGLCaps::initConfigTable(const GrGLContextInfo& ctxInfo, const GrGLInterfa
fConfigTable[kRGBA_float_GrPixelConfig].fFlags |= fpRenderFlags;
}
}
+ if (texStorageSupported) {
+ fConfigTable[kRGBA_float_GrPixelConfig].fFlags |= ConfigInfo::kCanUseTexStorage_Flag;
+ }
fConfigTable[kRGBA_float_GrPixelConfig].fSwizzle = GrSwizzle::RGBA();
if (this->textureRedSupport()) {
@@ -1545,6 +1577,9 @@ void GrGLCaps::initConfigTable(const GrGLContextInfo& ctxInfo, const GrGLInterfa
fConfigTable[kAlpha_half_GrPixelConfig].fFlags |= fpRenderFlags;
}
}
+ if (texStorageSupported) {
+ fConfigTable[kAlpha_half_GrPixelConfig].fFlags |= ConfigInfo::kCanUseTexStorage_Flag;
+ }
fConfigTable[kRGBA_half_GrPixelConfig].fFormats.fBaseInternalFormat = GR_GL_RGBA;
fConfigTable[kRGBA_half_GrPixelConfig].fFormats.fSizedInternalFormat = GR_GL_RGBA16F;
@@ -1564,6 +1599,9 @@ void GrGLCaps::initConfigTable(const GrGLContextInfo& ctxInfo, const GrGLInterfa
fConfigTable[kRGBA_half_GrPixelConfig].fFlags |= fpRenderFlags;
}
}
+ if (texStorageSupported) {
+ fConfigTable[kRGBA_half_GrPixelConfig].fFlags |= ConfigInfo::kCanUseTexStorage_Flag;
+ }
fConfigTable[kRGBA_half_GrPixelConfig].fSwizzle = GrSwizzle::RGBA();
// Compressed texture support
diff --git a/src/gpu/gl/GrGLCaps.h b/src/gpu/gl/GrGLCaps.h
index fc29615cb5..724bab6258 100644
--- a/src/gpu/gl/GrGLCaps.h
+++ b/src/gpu/gl/GrGLCaps.h
@@ -133,6 +133,11 @@ public:
}
}
+ bool isConfigTexSupportEnabled(GrPixelConfig config) const {
+ SkASSERT(kGrPixelConfigCnt > config);
+ return SkToBool(fConfigTable[config].fFlags & ConfigInfo::kCanUseTexStorage_Flag);
+ }
+
/** Returns the mapping between GrPixelConfig components and GL internal format components. */
const GrSwizzle& configSwizzle(GrPixelConfig config) const {
return fConfigTable[config].fSwizzle;
@@ -274,9 +279,6 @@ public:
/// Is there support for texture parameter GL_TEXTURE_USAGE
bool textureUsageSupport() const { return fTextureUsageSupport; }
- /// Is there support for glTexStorage
- bool texStorageSupport() const { return fTexStorageSupport; }
-
/// Is there support for GL_RED and GL_R8
bool textureRedSupport() const { return fTextureRedSupport; }
@@ -396,7 +398,6 @@ private:
bool fPackRowLengthSupport : 1;
bool fPackFlipYSupport : 1;
bool fTextureUsageSupport : 1;
- bool fTexStorageSupport : 1;
bool fTextureRedSupport : 1;
bool fImagingSupport : 1;
bool fVertexArrayObjectSupport : 1;
@@ -482,6 +483,7 @@ private:
kTextureable_Flag = 0x2,
kRenderable_Flag = 0x4,
kRenderableWithMSAA_Flag = 0x8,
+ kCanUseTexStorage_Flag = 0x10,
};
uint32_t fFlags;
diff --git a/src/gpu/gl/GrGLGpu.cpp b/src/gpu/gl/GrGLGpu.cpp
index 071b11383d..29841331c0 100644
--- a/src/gpu/gl/GrGLGpu.cpp
+++ b/src/gpu/gl/GrGLGpu.cpp
@@ -916,7 +916,7 @@ static inline GrGLenum check_alloc_error(const GrSurfaceDesc& desc,
*
* @param desc The surface descriptor for the texture being created.
* @param interface The GL interface in use.
- * @param target The GL target to which the texture is bound
+ * @param caps The capabilities of the GL device.
* @param internalFormat The data format used for the internal storage of the texture.
* @param externalFormat The data format used for the external storage of the texture.
* @param externalType The type of the data used for the external storage of the texture.
@@ -928,6 +928,7 @@ static inline GrGLenum check_alloc_error(const GrSurfaceDesc& desc,
*/
static void allocate_and_populate_uncompressed_texture(const GrSurfaceDesc& desc,
const GrGLInterface& interface,
+ const GrGLCaps& caps,
GrGLenum target,
GrGLenum internalFormat,
GrGLenum externalFormat,
@@ -936,27 +937,70 @@ static void allocate_and_populate_uncompressed_texture(const GrSurfaceDesc& desc
int baseWidth, int baseHeight,
bool* succeeded) {
CLEAR_ERROR_BEFORE_ALLOC(&interface);
- *succeeded = true;
- for (int currentMipLevel = 0; currentMipLevel < texels.count(); currentMipLevel++) {
- int twoToTheMipLevel = 1 << currentMipLevel;
- int currentWidth = SkTMax(1, baseWidth / twoToTheMipLevel);
- int currentHeight = SkTMax(1, baseHeight / twoToTheMipLevel);
- const void* currentMipData = texels[currentMipLevel].fPixels;
- // Even if curremtMipData is nullptr, continue to call TexImage2D.
- // This will allocate texture memory which we can later populate.
+
+ bool useTexStorage = caps.isConfigTexSupportEnabled(desc.fConfig);
+ // We can only use TexStorage if we know we will not later change the storage requirements.
+ // This means if we may later want to add mipmaps, we cannot use TexStorage.
+ // Right now, we cannot know if we will later add mipmaps or not.
+ // The only time we can use TexStorage is when we already have the
+ // mipmaps.
+ useTexStorage &= texels.count() > 1;
+
+ if (useTexStorage) {
+ // We never resize or change formats of textures.
GL_ALLOC_CALL(&interface,
- TexImage2D(target,
- currentMipLevel,
- internalFormat,
- currentWidth,
- currentHeight,
- 0, // border
- externalFormat, externalType,
- currentMipData));
+ TexStorage2D(target,
+ texels.count(),
+ internalFormat,
+ desc.fWidth, desc.fHeight));
GrGLenum error = check_alloc_error(desc, &interface);
if (error != GR_GL_NO_ERROR) {
*succeeded = false;
- break;
+ } else {
+ for (int currentMipLevel = 0; currentMipLevel < texels.count(); currentMipLevel++) {
+ const void* currentMipData = texels[currentMipLevel].fPixels;
+ if (currentMipData == nullptr) {
+ continue;
+ }
+ int twoToTheMipLevel = 1 << currentMipLevel;
+ int currentWidth = SkTMax(1, desc.fWidth / twoToTheMipLevel);
+ int currentHeight = SkTMax(1, desc.fHeight / twoToTheMipLevel);
+
+ GR_GL_CALL(&interface,
+ TexSubImage2D(target,
+ currentMipLevel,
+ 0, // left
+ 0, // top
+ currentWidth,
+ currentHeight,
+ externalFormat, externalType,
+ currentMipData));
+ }
+ *succeeded = true;
+ }
+ } else {
+ *succeeded = true;
+ for (int currentMipLevel = 0; currentMipLevel < texels.count(); currentMipLevel++) {
+ int twoToTheMipLevel = 1 << currentMipLevel;
+ int currentWidth = SkTMax(1, baseWidth / twoToTheMipLevel);
+ int currentHeight = SkTMax(1, baseHeight / twoToTheMipLevel);
+ const void* currentMipData = texels[currentMipLevel].fPixels;
+ // Even if curremtMipData is nullptr, continue to call TexImage2D.
+ // This will allocate texture memory which we can later populate.
+ GL_ALLOC_CALL(&interface,
+ TexImage2D(target,
+ currentMipLevel,
+ internalFormat,
+ currentWidth,
+ currentHeight,
+ 0, // border
+ externalFormat, externalType,
+ currentMipData));
+ GrGLenum error = check_alloc_error(desc, &interface);
+ if (error != GR_GL_NO_ERROR) {
+ *succeeded = false;
+ break;
+ }
}
}
}
@@ -966,40 +1010,86 @@ static void allocate_and_populate_uncompressed_texture(const GrSurfaceDesc& desc
*
* @param desc The surface descriptor for the texture being created.
* @param interface The GL interface in use.
- * @param target The GL target to which the texture is bound
+ * @param caps The capabilities of the GL device.
* @param internalFormat The data format used for the internal storage of the texture.
* @param texels The texel data of the texture being created.
- * @param baseWidth The width of the texture's base mipmap level
- * @param baseHeight The height of the texture's base mipmap level
*/
static bool allocate_and_populate_compressed_texture(const GrSurfaceDesc& desc,
const GrGLInterface& interface,
+ const GrGLCaps& caps,
GrGLenum target, GrGLenum internalFormat,
const SkTArray<GrMipLevel>& texels,
int baseWidth, int baseHeight) {
CLEAR_ERROR_BEFORE_ALLOC(&interface);
- for (int currentMipLevel = 0; currentMipLevel < texels.count(); currentMipLevel++) {
- int twoToTheMipLevel = 1 << currentMipLevel;
- int currentWidth = SkTMax(1, baseWidth / twoToTheMipLevel);
- int currentHeight = SkTMax(1, baseHeight / twoToTheMipLevel);
- // Make sure that the width and height that we pass to OpenGL
- // is a multiple of the block size.
- size_t dataSize = GrCompressedFormatDataSize(desc.fConfig, baseWidth, baseHeight);
+ bool useTexStorage = caps.isConfigTexSupportEnabled(desc.fConfig);
+ // We can only use TexStorage if we know we will not later change the storage requirements.
+ // This means if we may later want to add mipmaps, we cannot use TexStorage.
+ // Right now, we cannot know if we will later add mipmaps or not.
+ // The only time we can use TexStorage is when we already have the
+ // mipmaps.
+ useTexStorage &= texels.count() > 1;
+ if (useTexStorage) {
+ // We never resize or change formats of textures.
GL_ALLOC_CALL(&interface,
- CompressedTexImage2D(target,
- currentMipLevel,
- internalFormat,
- currentWidth,
- currentHeight,
- 0, // border
- SkToInt(dataSize),
- texels[currentMipLevel].fPixels));
-
+ TexStorage2D(target,
+ texels.count(),
+ internalFormat,
+ baseWidth, baseHeight));
GrGLenum error = check_alloc_error(desc, &interface);
if (error != GR_GL_NO_ERROR) {
return false;
+ } else {
+ for (int currentMipLevel = 0; currentMipLevel < texels.count(); currentMipLevel++) {
+ const void* currentMipData = texels[currentMipLevel].fPixels;
+ if (currentMipData == nullptr) {
+ continue;
+ }
+
+ int twoToTheMipLevel = 1 << currentMipLevel;
+ int currentWidth = SkTMax(1, baseWidth / twoToTheMipLevel);
+ int currentHeight = SkTMax(1, baseHeight / twoToTheMipLevel);
+
+ // Make sure that the width and height that we pass to OpenGL
+ // is a multiple of the block size.
+ size_t dataSize = GrCompressedFormatDataSize(desc.fConfig, currentWidth,
+ currentHeight);
+ GR_GL_CALL(&interface, CompressedTexSubImage2D(target,
+ currentMipLevel,
+ 0, // left
+ 0, // top
+ currentWidth,
+ currentHeight,
+ internalFormat,
+ SkToInt(dataSize),
+ currentMipData));
+ }
+ }
+ } else {
+ for (int currentMipLevel = 0; currentMipLevel < texels.count(); currentMipLevel++) {
+ int twoToTheMipLevel = 1 << currentMipLevel;
+ int currentWidth = SkTMax(1, baseWidth / twoToTheMipLevel);
+ int currentHeight = SkTMax(1, baseHeight / twoToTheMipLevel);
+
+ // Make sure that the width and height that we pass to OpenGL
+ // is a multiple of the block size.
+ size_t dataSize = GrCompressedFormatDataSize(desc.fConfig, baseWidth, baseHeight);
+
+ GL_ALLOC_CALL(&interface,
+ CompressedTexImage2D(target,
+ currentMipLevel,
+ internalFormat,
+ currentWidth,
+ currentHeight,
+ 0, // border
+ SkToInt(dataSize),
+ texels[currentMipLevel].fPixels));
+
+ GrGLenum error = check_alloc_error(desc, &interface);
+ if (error != GR_GL_NO_ERROR) {
+ return false;
+ }
}
}
@@ -1191,7 +1281,7 @@ bool GrGLGpu::uploadTexData(const GrSurfaceDesc& desc,
0 == left && 0 == top &&
desc.fWidth == width && desc.fHeight == height &&
!desc.fTextureStorageAllocator.fAllocateTextureStorage) {
- allocate_and_populate_uncompressed_texture(desc, *interface, target,
+ allocate_and_populate_uncompressed_texture(desc, *interface, caps, target,
internalFormat, externalFormat,
externalType, texelsShallowCopy,
width, height, &succeeded);
@@ -1268,8 +1358,8 @@ bool GrGLGpu::uploadCompressedTexData(const GrSurfaceDesc& desc,
}
if (kNewTexture_UploadType == uploadType) {
- return allocate_and_populate_compressed_texture(desc, *interface, target, internalFormat,
- texels, width, height);
+ return allocate_and_populate_compressed_texture(desc, *interface, caps, target,
+ internalFormat, texels, width, height);
} else {
// Paletted textures can't be updated.
if (GR_GL_PALETTE8_RGBA8 == internalFormat) {