Make transferability a per-format flag in GrGLCaps
Add workaround for 16 bit unorm on freedreno
Make sure callsites are checking for transfer alignment
of 0 to indicate unsupported.
Bug: skia:11876
Change-Id: Ia1c22a430f675fc57724f220f5dee5b23f325f3c
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/421317
Commit-Queue: Brian Salomon <bsalomon@google.com>
Reviewed-by: Greg Daniel <egdaniel@google.com>
diff --git a/src/gpu/GrSurfaceContext.cpp b/src/gpu/GrSurfaceContext.cpp
index 6a6fd2d..c1ad2e8 100644
--- a/src/gpu/GrSurfaceContext.cpp
+++ b/src/gpu/GrSurfaceContext.cpp
@@ -967,7 +967,16 @@
auto texMatrix = SkMatrix::Translate(x, y);
- bool doSynchronousRead = !this->caps()->transferFromSurfaceToBufferSupport();
+ auto [readCT, offsetAlignment] =
+ this->caps()->supportedReadPixelsColorType(yFC->colorInfo().colorType(),
+ yFC->asSurfaceProxy()->backendFormat(),
+ GrColorType::kAlpha_8);
+ if (readCT == GrColorType::kUnknown) {
+ callback(callbackContext, nullptr);
+ return;
+ }
+ bool doSynchronousRead = !this->caps()->transferFromSurfaceToBufferSupport() ||
+ !offsetAlignment;
PixelTransferResult yTransfer, uTransfer, vTransfer;
// This matrix generates (r,g,b,a) = (0, 0, 0, y)
diff --git a/src/gpu/gl/GrGLCaps.cpp b/src/gpu/gl/GrGLCaps.cpp
index de85545..936cb17 100644
--- a/src/gpu/gl/GrGLCaps.cpp
+++ b/src/gpu/gl/GrGLCaps.cpp
@@ -1357,7 +1357,7 @@
info.fDefaultExternalFormat = GR_GL_RGBA;
info.fDefaultExternalType = GR_GL_UNSIGNED_BYTE;
info.fDefaultColorType = GrColorType::kRGBA_8888;
- info.fFlags = FormatInfo::kTexturable_Flag;
+ info.fFlags = FormatInfo::kTexturable_Flag | FormatInfo::kTransfers_Flag;
if (GR_IS_GR_GL(standard)) {
info.fFlags |= msaaRenderFlags;
} else if (GR_IS_GR_GL_ES(standard)) {
@@ -1493,7 +1493,9 @@
}
if (r8Support) {
- info.fFlags |= FormatInfo::kTexturable_Flag | msaaRenderFlags;
+ info.fFlags |= FormatInfo::kTexturable_Flag
+ | FormatInfo::kTransfers_Flag
+ | msaaRenderFlags;
}
if (texStorageSupported) {
@@ -1608,7 +1610,7 @@
info.fDefaultExternalType = GR_GL_UNSIGNED_BYTE;
info.fDefaultColorType = GrColorType::kAlpha_8;
if (alpha8IsValidForGL || alpha8IsValidForGLES || alpha8IsValidForWebGL) {
- info.fFlags = FormatInfo::kTexturable_Flag;
+ info.fFlags = FormatInfo::kTexturable_Flag | FormatInfo::kTransfers_Flag;
}
if (alpha8IsRenderable && alpha8IsValidForGL) {
// We will use ALPHA8 to create MSAA renderbuffers.
@@ -1695,7 +1697,7 @@
lum8Supported = true;
}
if (lum8Supported) {
- info.fFlags = FormatInfo::kTexturable_Flag;
+ info.fFlags = FormatInfo::kTexturable_Flag | FormatInfo::kTransfers_Flag;
}
if (texStorageSupported && lum8SizedFormatSupported) {
info.fFlags |= FormatInfo::kUseTexStorage_Flag;
@@ -1775,7 +1777,7 @@
la8Supported = true;
}
if (la8Supported) {
- info.fFlags = FormatInfo::kTexturable_Flag;
+ info.fFlags = FormatInfo::kTexturable_Flag | FormatInfo::kTransfers_Flag;
}
if (texStorageSupported && la8SizedFormatSupported) {
info.fFlags |= FormatInfo::kUseTexStorage_Flag;
@@ -1879,7 +1881,9 @@
if (GR_IS_GR_GL_ES(standard)) {
if (ctxInfo.hasExtension("GL_EXT_texture_format_BGRA8888")) {
- info.fFlags = FormatInfo::kTexturable_Flag | nonMSAARenderFlags;
+ info.fFlags = FormatInfo::kTexturable_Flag
+ | FormatInfo::kTransfers_Flag
+ | nonMSAARenderFlags;
// GL_EXT_texture storage has defined interactions with
// GL_EXT_texture_format_BGRA8888. However, ES3 supports glTexStorage but
// without GL_EXT_texture_storage it does not allow the BGRA8 sized internal format.
@@ -1899,7 +1903,9 @@
if (version >= GR_GL_VER(3,0)) {
// The APPLE extension doesn't explicitly make this renderable, but
// internally it appears to use RGBA8, which we'll patch up below.
- info.fFlags = FormatInfo::kTexturable_Flag | msaaRenderFlags;
+ info.fFlags = FormatInfo::kTexturable_Flag
+ | FormatInfo::kTransfers_Flag
+ | msaaRenderFlags;
supportsBGRATexStorage = true;
}
}
@@ -1962,12 +1968,18 @@
info.fDefaultColorType = GrColorType::kBGR_565;
if (GR_IS_GR_GL(standard)) {
if (version >= GR_GL_VER(4, 2) || ctxInfo.hasExtension("GL_ARB_ES2_compatibility")) {
- info.fFlags = FormatInfo::kTexturable_Flag | msaaRenderFlags;
+ info.fFlags = FormatInfo::kTexturable_Flag
+ | FormatInfo::kTransfers_Flag
+ | msaaRenderFlags;
}
} else if (GR_IS_GR_GL_ES(standard)) {
- info.fFlags = FormatInfo::kTexturable_Flag | msaaRenderFlags;
+ info.fFlags = FormatInfo::kTexturable_Flag
+ | FormatInfo::kTransfers_Flag
+ | msaaRenderFlags;
} else if (GR_IS_GR_WEBGL(standard)) {
- info.fFlags = FormatInfo::kTexturable_Flag | msaaRenderFlags;
+ info.fFlags = FormatInfo::kTexturable_Flag
+ | FormatInfo::kTransfers_Flag
+ | msaaRenderFlags;
}
// 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
@@ -2074,7 +2086,7 @@
}
if (rgba16FTextureSupport) {
- info.fFlags = FormatInfo::kTexturable_Flag;
+ info.fFlags = FormatInfo::kTexturable_Flag | FormatInfo::kTransfers_Flag;
if (rgba16FRenderTargetSupport) {
info.fFlags |= fpRenderFlags;
}
@@ -2198,7 +2210,7 @@
}
if (r16FTextureSupport) {
- info.fFlags = FormatInfo::kTexturable_Flag;
+ info.fFlags = FormatInfo::kTexturable_Flag | FormatInfo::kTransfers_Flag;
if (r16FRenderTargetSupport) {
info.fFlags |= fpRenderFlags;
}
@@ -2284,7 +2296,7 @@
info.fDefaultColorType = GrColorType::kGray_F16;
if (lum16FSupported) {
- info.fFlags = FormatInfo::kTexturable_Flag;
+ info.fFlags = FormatInfo::kTexturable_Flag | FormatInfo::kTransfers_Flag;
if (texStorageSupported && lum16FSizedFormatSupported) {
info.fFlags |= FormatInfo::kUseTexStorage_Flag;
@@ -2345,7 +2357,7 @@
info.fDefaultExternalFormat = GR_GL_RGB;
info.fDefaultExternalType = GR_GL_UNSIGNED_BYTE;
info.fDefaultColorType = GrColorType::kRGB_888;
- info.fFlags = FormatInfo::kTexturable_Flag;
+ info.fFlags = FormatInfo::kTexturable_Flag | FormatInfo::kTransfers_Flag;
if (GR_IS_GR_GL(standard)) {
// Even in OpenGL 4.6 GL_RGB8 is required to be color renderable but not required to be
// a supported render buffer format. Since we usually use render buffers for MSAA on
@@ -2422,7 +2434,9 @@
rg8Support = version >= GR_GL_VER(2, 0);
}
if (rg8Support) {
- info.fFlags |= FormatInfo::kTexturable_Flag | msaaRenderFlags;
+ info.fFlags |= FormatInfo::kTexturable_Flag
+ | FormatInfo::kTransfers_Flag
+ | msaaRenderFlags;
if (texStorageSupported) {
info.fFlags |= FormatInfo::kUseTexStorage_Flag;
info.fInternalFormatForTexImageOrStorage = GR_GL_RG8;
@@ -2482,10 +2496,12 @@
info.fDefaultColorType = GrColorType::kRGBA_1010102;
if (GR_IS_GR_GL(standard) ||
(GR_IS_GR_GL_ES(standard) && version >= GR_GL_VER(3, 0))) {
- info.fFlags = FormatInfo::kTexturable_Flag | msaaRenderFlags;
+ info.fFlags = FormatInfo::kTexturable_Flag
+ | FormatInfo::kTransfers_Flag
+ | msaaRenderFlags;
} else if (GR_IS_GR_GL_ES(standard) &&
ctxInfo.hasExtension("GL_EXT_texture_type_2_10_10_10_REV")) {
- info.fFlags = FormatInfo::kTexturable_Flag;
+ info.fFlags = FormatInfo::kTexturable_Flag | FormatInfo::kTransfers_Flag;
} // No WebGL support
if (texStorageSupported) {
@@ -2580,7 +2596,7 @@
info.fDefaultExternalFormat = GR_GL_RGBA;
info.fDefaultExternalType = GR_GL_UNSIGNED_SHORT_4_4_4_4;
info.fDefaultColorType = GrColorType::kABGR_4444;
- info.fFlags = FormatInfo::kTexturable_Flag;
+ info.fFlags = FormatInfo::kTexturable_Flag | FormatInfo::kTransfers_Flag;
if (GR_IS_GR_GL(standard)) {
if (version >= GR_GL_VER(4, 2)) {
info.fFlags |= msaaRenderFlags;
@@ -2687,7 +2703,7 @@
}
if (srgb8Alpha8TextureSupport) {
- info.fFlags = FormatInfo::kTexturable_Flag;
+ info.fFlags = FormatInfo::kTexturable_Flag | FormatInfo::kTransfers_Flag;
if (srgb8Alpha8RenderTargetSupport) {
info.fFlags |= formatWorkarounds.fDisableSRGBRenderWithMSAAForMacAMD
? nonMSAARenderFlags
@@ -2822,6 +2838,9 @@
if (r16Supported) {
info.fFlags = FormatInfo::kTexturable_Flag | msaaRenderFlags;
+ if (!formatWorkarounds.fDisallowUnorm16Transfers) {
+ info.fFlags |= FormatInfo::kTransfers_Flag;
+ }
}
if (texStorageSupported) {
@@ -2892,6 +2911,9 @@
if (rg16Supported) {
info.fFlags = FormatInfo::kTexturable_Flag | msaaRenderFlags;
+ if (!formatWorkarounds.fDisallowUnorm16Transfers) {
+ info.fFlags |= FormatInfo::kTransfers_Flag;
+ }
}
if (texStorageSupported) {
@@ -2959,6 +2981,9 @@
info.fDefaultColorType = GrColorType::kRGBA_16161616;
if (rgba16Support) {
info.fFlags = FormatInfo::kTexturable_Flag | msaaRenderFlags;
+ if (!formatWorkarounds.fDisallowUnorm16Transfers) {
+ info.fFlags |= FormatInfo::kTransfers_Flag;
+ }
}
if (texStorageSupported) {
@@ -3046,7 +3071,7 @@
info.fDefaultExternalType = halfFloatType;
info.fDefaultColorType = GrColorType::kRG_F16;
if (rg16FTextureSupport) {
- info.fFlags |= FormatInfo::kTexturable_Flag;
+ info.fFlags |= FormatInfo::kTexturable_Flag | FormatInfo::kTransfers_Flag;
if (rg16FRenderTargetSupport) {
info.fFlags |= fpRenderFlags;
}
@@ -4171,6 +4196,10 @@
// crbug.com/1203652
fAlwaysDrawQuadsIndexed = true;
}
+
+ if (ctxInfo.driver() == GrGLDriver::kFreedreno) {
+ formatWorkarounds->fDisallowUnorm16Transfers = true;
+ }
}
void GrGLCaps::onApplyOptionsOverrides(const GrContextOptions& options) {
@@ -4283,9 +4312,9 @@
SkImage::CompressionType compression = GrBackendFormatToCompressionType(srcBackendFormat);
if (compression != SkImage::CompressionType::kNone) {
- return { SkCompressionTypeIsOpaque(compression) ? GrColorType::kRGB_888x
- : GrColorType::kRGBA_8888,
- offset_alignment_for_transfer_buffer(GR_GL_UNSIGNED_BYTE) };
+ return {SkCompressionTypeIsOpaque(compression) ? GrColorType::kRGB_888x
+ : GrColorType::kRGBA_8888,
+ 0};
}
// We first try to find a supported read pixels GrColorType that matches the requested
@@ -4302,8 +4331,11 @@
if (ioInfo.fExternalReadFormat != 0) {
if (formatInfo.fHaveQueriedImplementationReadSupport ||
!ioInfo.fRequiresImplementationReadQuery) {
- GrGLenum transferOffsetAlignment =
- offset_alignment_for_transfer_buffer(ioInfo.fExternalType);
+ GrGLenum transferOffsetAlignment = 0;
+ if (formatInfo.fFlags & FormatInfo::kTransfers_Flag) {
+ transferOffsetAlignment =
+ offset_alignment_for_transfer_buffer(ioInfo.fExternalType);
+ }
if (ioInfo.fColorType == dstColorType) {
return {dstColorType, transferOffsetAlignment};
}
@@ -4328,6 +4360,10 @@
GrColorType fallbackCT = GrColorType::kUnknown;
const auto& formatInfo = this->getFormatInfo(surfaceFormat.asGLFormat());
bool foundSurfaceCT = false;
+ size_t transferOffsetAlignment = 0;
+ if (formatInfo.fFlags & FormatInfo::kTransfers_Flag) {
+ transferOffsetAlignment = 1;
+ }
for (int i = 0; !foundSurfaceCT && i < formatInfo.fColorTypeInfoCount; ++i) {
if (formatInfo.fColorTypeInfos[i].fColorType == surfaceColorType) {
const ColorTypeInfo& ctInfo = formatInfo.fColorTypeInfos[i];
@@ -4336,7 +4372,7 @@
const auto& ioInfo = ctInfo.fExternalIOFormats[j];
if (ioInfo.fExternalTexImageFormat != 0) {
if (ioInfo.fColorType == srcColorType) {
- return {srcColorType, 1};
+ return {srcColorType, transferOffsetAlignment};
}
// Currently we just pick the first supported format that we find as our
// fallback.
@@ -4347,7 +4383,7 @@
}
}
}
- return {fallbackCT, 1};
+ return {fallbackCT, transferOffsetAlignment};
}
bool GrGLCaps::onIsWindowRectanglesSupportedForRT(const GrBackendRenderTarget& backendRT) const {
diff --git a/src/gpu/gl/GrGLCaps.h b/src/gpu/gl/GrGLCaps.h
index 84cd3a5..7b11851 100644
--- a/src/gpu/gl/GrGLCaps.h
+++ b/src/gpu/gl/GrGLCaps.h
@@ -475,6 +475,7 @@
bool fDisallowDirectRG8ReadPixels = false;
bool fDisallowBGRA8ReadPixels = false;
bool fDisallowR8ForPowerVRSGX54x = false;
+ bool fDisallowUnorm16Transfers = false;
};
void applyDriverCorrectnessWorkarounds(const GrGLContextInfo&, const GrContextOptions&,
@@ -673,12 +674,17 @@
}
enum {
- kTexturable_Flag = 0x1,
+ kTexturable_Flag = 0x01,
/** kFBOColorAttachment means that even if the format cannot be a GrRenderTarget, we can
still attach it to a FBO for blitting or reading pixels. */
- kFBOColorAttachment_Flag = 0x2,
- kFBOColorAttachmentWithMSAA_Flag = 0x4,
- kUseTexStorage_Flag = 0x8,
+ kFBOColorAttachment_Flag = 0x02,
+ kFBOColorAttachmentWithMSAA_Flag = 0x04,
+ kUseTexStorage_Flag = 0x08,
+ /**
+ * Are pixel buffer objects supported in/out of this format? Ignored if PBOs are not
+ * supported at all.
+ */
+ kTransfers_Flag = 0x10,
};
uint32_t fFlags = 0;
diff --git a/src/gpu/gl/GrGLUtil.cpp b/src/gpu/gl/GrGLUtil.cpp
index 353a390..8d04068 100644
--- a/src/gpu/gl/GrGLUtil.cpp
+++ b/src/gpu/gl/GrGLUtil.cpp
@@ -369,6 +369,7 @@
static std::tuple<GrGLDriver, GrGLDriverVersion> get_driver_and_version(GrGLStandard standard,
GrGLVendor vendor,
+ const char* vendorString,
const char* rendererString,
const char* versionString) {
SkASSERT(rendererString);
@@ -378,7 +379,10 @@
GrGLDriverVersion driverVersion = GR_GL_DRIVER_UNKNOWN_VER;
int major, minor, rev, driverMajor, driverMinor, driverPoint;
- if (GR_IS_GR_GL(standard)) {
+ // This is the same on ES and regular GL.
+ if (!strcmp(vendorString, "freedreno")) {
+ driver = GrGLDriver::kFreedreno;
+ } else if (GR_IS_GR_GL(standard)) {
if (vendor == GrGLVendor::kNVIDIA) {
driver = GrGLDriver::kNVIDIA;
int n = sscanf(versionString,
@@ -554,6 +558,7 @@
auto [angleDriver, angleDriverVersion] = get_driver_and_version(kGLES_GrGLStandard,
angleVendor,
+ angleVendorString,
angleRendererString,
angleVersionString);
@@ -629,10 +634,10 @@
return reinterpret_cast<const char*>(bytes);
};
- const char* const version = getString(GR_GL_VERSION);
- const char* const slversion = getString(GR_GL_SHADING_LANGUAGE_VERSION);
- const char* const renderer = getString(GR_GL_RENDERER);
- const char* const vendor = getString(GR_GL_VENDOR);
+ const char* const version = getString(GR_GL_VERSION);
+ const char* const slversion = getString(GR_GL_SHADING_LANGUAGE_VERSION);
+ const char* const renderer = getString(GR_GL_RENDERER);
+ const char* const vendor = getString(GR_GL_VENDOR);
info.fVersion = GrGLGetVersionFromString(version);
info.fGLSLVersion = get_glsl_version(slversion);
@@ -641,6 +646,7 @@
std::tie(info.fDriver, info.fDriverVersion) = get_driver_and_version(interface->fStandard,
info.fVendor,
+ vendor,
renderer,
version);
diff --git a/src/gpu/gl/GrGLUtil.h b/src/gpu/gl/GrGLUtil.h
index b6f7e37..0f6bb78 100644
--- a/src/gpu/gl/GrGLUtil.h
+++ b/src/gpu/gl/GrGLUtil.h
@@ -209,6 +209,7 @@
kIntel,
kSwiftShader,
kQualcomm,
+ kFreedreno,
kAndroidEmulator,
kUnknown
};
diff --git a/tests/TransferPixelsTest.cpp b/tests/TransferPixelsTest.cpp
index 03b96be..269e483 100644
--- a/tests/TransferPixelsTest.cpp
+++ b/tests/TransferPixelsTest.cpp
@@ -152,6 +152,9 @@
// either of which may differ from 'colorType'.
GrCaps::SupportedWrite allowedSrc =
caps->supportedWritePixelsColorType(colorType, tex->backendFormat(), colorType);
+ if (!allowedSrc.fOffsetAlignmentForTransferBuffer) {
+ return;
+ }
size_t srcRowBytes = GrAlignTo(GrColorTypeBytesPerPixel(allowedSrc.fColorType) * srcBufferWidth,
caps->transferBufferAlignment());
@@ -331,6 +334,9 @@
// Create the transfer buffer.
auto allowedRead =
caps->supportedReadPixelsColorType(colorType, tex->backendFormat(), colorType);
+ if (!allowedRead.fOffsetAlignmentForTransferBuffer) {
+ return;
+ }
GrImageInfo readInfo(allowedRead.fColorType, kUnpremul_SkAlphaType, nullptr, kTexDims);
size_t bpp = GrColorTypeBytesPerPixel(allowedRead.fColorType);