#include "src/gpu/ganesh/gl/GrGLCaps.h"
#include "include/core/SkColor.h"
#include "include/core/SkRect.h"
#include "include/core/SkSize.h"
#include "include/core/SkTextureCompressionType.h"
#include "include/gpu/GpuTypes.h"
#include "include/gpu/ganesh/GrContextOptions.h"
#include "include/gpu/ganesh/GrDriverBugWorkarounds.h"
#include "include/gpu/ganesh/GrTypes.h"
#include "include/gpu/ganesh/gl/GrGLBackendSurface.h"
#include "include/gpu/ganesh/gl/GrGLFunctions.h"
#include "include/gpu/ganesh/gl/GrGLInterface.h"
#include "include/private/base/SkDebug.h"
#include "include/private/base/SkMath.h"
#include "include/private/base/SkTemplates.h"
#include "include/private/base/SkTo.h"
#include "src/core/SkCompressedDataUtils.h"
#include "src/gpu/Blend.h"
#include "src/gpu/ganesh/GrBackendUtils.h"
#include "src/gpu/ganesh/GrProgramDesc.h"
#include "src/gpu/ganesh/GrRenderTarget.h"
#include "src/gpu/ganesh/GrRenderTargetProxy.h"
#include "src/gpu/ganesh/GrShaderCaps.h"
#include "src/gpu/ganesh/GrSurface.h"
#include "src/gpu/ganesh/GrSurfaceProxy.h"
#include "src/gpu/ganesh/GrSurfaceProxyPriv.h"
#include "src/gpu/ganesh/GrTextureProxy.h"
#include "src/gpu/ganesh/TestFormatColorTypeCombination.h"
#include "src/gpu/ganesh/gl/GrGLContext.h"
#include "src/gpu/ganesh/gl/GrGLDefines.h"
#include "src/gpu/ganesh/gl/GrGLRenderTarget.h"
#include "src/gpu/ganesh/gl/GrGLTexture.h"
#include "src/gpu/ganesh/gl/GrGLUtil.h"
#include "src/sksl/SkSLGLSL.h"
#include <algorithm>
#include <cstddef>
#include <initializer_list>
#include <memory>
class GrProgramInfo;
class SkJSONWriter;
#if defined(SK_BUILD_FOR_IOS)
#include <TargetConditionals.h>
#endif
GrGLCaps::GrGLCaps(const GrContextOptions& contextOptions,
const GrGLContextInfo& ctxInfo,
const GrGLInterface* glInterface) : … { … }
static bool angle_backend_is_d3d(GrGLANGLEBackend backend) { … }
static bool angle_backend_is_metal(GrGLANGLEBackend backend) { … }
void GrGLCaps::init(const GrContextOptions& contextOptions,
const GrGLContextInfo& ctxInfo,
const GrGLInterface* gli) { … }
const char* get_glsl_version_decl_string(GrGLStandard standard, SkSL::GLSLGeneration generation,
bool isCoreProfile) { … }
bool is_float_fp32(const GrGLContextInfo& ctxInfo, const GrGLInterface* gli, GrGLenum precision) { … }
void GrGLCaps::initGLSL(const GrGLContextInfo& ctxInfo, const GrGLInterface* gli) { … }
void GrGLCaps::initFSAASupport(const GrContextOptions& contextOptions,
const GrGLContextInfo& ctxInfo, const GrGLInterface* gli) { … }
void GrGLCaps::initBlendEqationSupport(const GrGLContextInfo& ctxInfo) { … }
void GrGLCaps::initStencilSupport(const GrGLContextInfo& ctxInfo) { … }
#ifdef SK_ENABLE_DUMP_GPU
#include "src/utils/SkJSONWriter.h"
static const char* multi_draw_type_name(GrGLCaps::MultiDrawType multiDrawType) {
switch (multiDrawType) {
case GrGLCaps::MultiDrawType::kNone : return "kNone";
case GrGLCaps::MultiDrawType::kMultiDrawIndirect : return "kMultiDrawIndirect";
case GrGLCaps::MultiDrawType::kANGLEOrWebGL : return "kMultiDrawIndirect";
}
SkUNREACHABLE;
}
void GrGLCaps::onDumpJSON(SkJSONWriter* writer) const {
writer->beginObject("GL caps");
writer->beginArray("Stencil Formats");
for (int i = 0; i < fStencilFormats.size(); ++i) {
writer->beginObject(nullptr, false);
writer->appendS32("stencil bits", GrGLFormatStencilBits(fStencilFormats[i]));
writer->appendS32("total bytes", GrGLFormatBytesPerBlock(fStencilFormats[i]));
writer->endObject();
}
writer->endArray();
auto msfboStr = [&] {
switch (fMSFBOType) {
case kNone_MSFBOType: return "None";
case kStandard_MSFBOType: return "Standard";
case kES_Apple_MSFBOType: return "Apple";
case kES_IMG_MsToTexture_MSFBOType: return "IMG MS To Texture";
case kES_EXT_MsToTexture_MSFBOType: return "EXT MS To Texture";
}
SkUNREACHABLE;
};
auto invalidateFBTypeStr = [&] {
switch (fInvalidateFBType) {
case kNone_InvalidateFBType: return "None";
case kDiscard_InvalidateFBType: return "Discard";
case kInvalidate_InvalidateFBType: return "Invalidate";
}
SkUNREACHABLE;
};
auto invalidateBufferTypeStr = [&] {
switch (fInvalidateBufferType) {
case InvalidateBufferType::kNone: return "None";
case InvalidateBufferType::kNullData: return "Null data hint";
case InvalidateBufferType::kInvalidate: return "Invalidate";
}
SkUNREACHABLE;
};
auto mapBufferTypeStr = [&] {
switch (fMapBufferType) {
case kNone_MapBufferType: return "None";
case kMapBuffer_MapBufferType: return "MapBuffer";
case kMapBufferRange_MapBufferType: return "MapBufferRange";
case kChromium_MapBufferType: return "Chromium";
}
SkUNREACHABLE;
};
writer->appendBool("Core Profile", fIsCoreProfile);
writer->appendCString("MSAA Type", msfboStr());
writer->appendCString("Invalidate FB Type", invalidateFBTypeStr());
writer->appendCString("Invalidate Buffer Type", invalidateBufferTypeStr());
writer->appendCString("Map Buffer Type", mapBufferTypeStr());
writer->appendCString("Multi Draw Type", multi_draw_type_name(fMultiDrawType));
writer->appendS32("Max FS Uniform Vectors", fMaxFragmentUniformVectors);
writer->appendBool("Pack Flip Y support", fPackFlipYSupport);
writer->appendBool("Texture Usage support", fTextureUsageSupport);
writer->appendBool("GL_ARB_imaging support", fImagingSupport);
writer->appendBool("Vertex array object support", fVertexArrayObjectSupport);
writer->appendBool("Debug support", fDebugSupport);
writer->appendBool("ES2 compatibility support", fES2CompatibilitySupport);
writer->appendBool("drawRangeElements support", fDrawRangeElementsSupport);
writer->appendBool("Base (vertex base) instance support", fBaseVertexBaseInstanceSupport);
writer->appendBool("Bind uniform location support", fBindUniformLocationSupport);
writer->appendBool("Rectangle texture support", fRectangleTextureSupport);
writer->appendBool("Mipmap LOD control support", fMipmapLodControlSupport);
writer->appendBool("Mipmap level control support", fMipmapLevelControlSupport);
writer->appendBool("Clear texture support", fClearTextureSupport);
writer->appendBool("Program binary support", fProgramBinarySupport);
writer->appendBool("Program parameters support", fProgramParameterSupport);
writer->appendBool("Sampler object support", fSamplerObjectSupport);
writer->appendBool("Using sampler objects", fUseSamplerObjects);
writer->appendBool("Texture swizzle support", fTextureSwizzleSupport);
writer->appendBool("Tiled rendering support", fTiledRenderingSupport);
writer->appendBool("Fence sync support", fFenceSyncSupport);
writer->appendBool("FB fetch requires enable per sample", fFBFetchRequiresEnablePerSample);
writer->appendBool("sRGB Write Control", fSRGBWriteControl);
writer->appendBool("Intermediate texture for partial updates of unorm textures ever bound to FBOs",
fDisallowTexSubImageForUnormConfigTexturesEverBoundToFBO);
writer->appendBool("Intermediate texture for all updates of textures bound to FBOs",
fUseDrawInsteadOfAllRenderTargetWrites);
writer->appendBool("Max instances per draw without crashing (or zero)",
fMaxInstancesPerDrawWithoutCrashing);
writer->beginArray("formats");
for (int i = 0; i < kGrGLColorFormatCount; ++i) {
writer->beginObject(nullptr, false);
writer->appendHexU32("flags", fFormatTable[i].fFlags);
writer->appendHexU32("f_type", (uint32_t)fFormatTable[i].fFormatType);
writer->appendHexU32("c_internal", fFormatTable[i].fCompressedInternalFormat);
writer->appendHexU32("i_for_teximage", fFormatTable[i].fInternalFormatForTexImageOrStorage);
writer->appendHexU32("i_for_renderbuffer", fFormatTable[i].fInternalFormatForRenderbuffer);
writer->appendHexU32("default_ex_format", fFormatTable[i].fDefaultExternalFormat);
writer->appendHexU32("default_ex_type", fFormatTable[i].fDefaultExternalType);
writer->appendHexU32("default_color_type", (uint32_t)fFormatTable[i].fDefaultColorType);
writer->beginArray("surface color types");
for (int j = 0; j < fFormatTable[i].fColorTypeInfoCount; ++j) {
const auto& ctInfo = fFormatTable[i].fColorTypeInfos[j];
writer->beginObject(nullptr, false);
writer->appendHexU32("colorType", (uint32_t)ctInfo.fColorType);
writer->appendHexU32("flags", ctInfo.fFlags);
writer->beginArray("data color types");
for (int k = 0; k < ctInfo.fExternalIOFormatCount; ++k) {
const auto& ioInfo = ctInfo.fExternalIOFormats[k];
writer->beginObject(nullptr, false);
writer->appendHexU32("colorType", (uint32_t)ioInfo.fColorType);
writer->appendHexU32("ex_type", ioInfo.fExternalType);
writer->appendHexU32("ex_teximage", ioInfo.fExternalTexImageFormat);
writer->appendHexU32("ex_read", ioInfo.fExternalReadFormat);
writer->endObject();
}
writer->endArray();
writer->endObject();
}
writer->endArray();
writer->endObject();
}
writer->endArray();
writer->endObject();
}
#else
void GrGLCaps::onDumpJSON(SkJSONWriter* writer) const { … }
#endif
void GrGLCaps::getTexImageExternalFormatAndType(GrGLFormat surfaceFormat, GrGLenum* externalFormat,
GrGLenum* externalType) const { … }
void GrGLCaps::getTexSubImageDefaultFormatTypeAndColorType(GrGLFormat format,
GrGLenum* externalFormat,
GrGLenum* externalType,
GrColorType* colorType) const { … }
void GrGLCaps::getTexSubImageExternalFormatAndType(GrGLFormat surfaceFormat,
GrColorType surfaceColorType,
GrColorType memoryColorType,
GrGLenum* externalFormat,
GrGLenum* externalType) const { … }
void GrGLCaps::getReadPixelsFormat(GrGLFormat surfaceFormat, GrColorType surfaceColorType,
GrColorType memoryColorType, GrGLenum* externalFormat,
GrGLenum* externalType) const { … }
void GrGLCaps::getExternalFormat(GrGLFormat surfaceFormat, GrColorType surfaceColorType,
GrColorType memoryColorType, ExternalFormatUsage usage,
GrGLenum* externalFormat, GrGLenum* externalType) const { … }
void GrGLCaps::setStencilFormatIndexForFormat(GrGLFormat format, int index) { … }
void GrGLCaps::setColorTypeFormat(GrColorType colorType, GrGLFormat format) { … }
void GrGLCaps::initFormatTable(const GrGLContextInfo& ctxInfo, const GrGLInterface* gli,
const FormatWorkarounds& formatWorkarounds) { … }
void GrGLCaps::setupSampleCounts(const GrGLContextInfo& ctxInfo, const GrGLInterface* gli) { … }
bool GrGLCaps::canCopyTexSubImage(GrGLFormat dstFormat, bool dstHasMSAARenderBuffer,
const GrTextureType* dstTypeIfTexture,
GrGLFormat srcFormat, bool srcHasMSAARenderBuffer,
const GrTextureType* srcTypeIfTexture) const { … }
bool GrGLCaps::canCopyAsBlit(GrGLFormat dstFormat, int dstSampleCnt,
const GrTextureType* dstTypeIfTexture,
GrGLFormat srcFormat, int srcSampleCnt,
const GrTextureType* srcTypeIfTexture,
const SkRect& srcBounds, bool srcBoundsExact,
const SkIRect& srcRect, const SkIRect& dstRect) const { … }
bool GrGLCaps::canCopyAsDraw(GrGLFormat dstFormat, bool srcIsTexturable, bool scalingCopy) const { … }
static bool has_msaa_render_buffer(const GrSurfaceProxy* surf, const GrGLCaps& glCaps) { … }
bool GrGLCaps::onCanCopySurface(const GrSurfaceProxy* dst, const SkIRect& dstRect,
const GrSurfaceProxy* src, const SkIRect& srcRect) const { … }
GrCaps::DstCopyRestrictions GrGLCaps::getDstCopyRestrictions(const GrRenderTargetProxy* src,
GrColorType colorType) const { … }
void GrGLCaps::applyDriverCorrectnessWorkarounds(const GrGLContextInfo& ctxInfo,
const GrContextOptions& contextOptions,
const GrGLInterface* glInterface,
GrShaderCaps* shaderCaps,
FormatWorkarounds* formatWorkarounds) { … }
void GrGLCaps::onApplyOptionsOverrides(const GrContextOptions& options) { … }
bool GrGLCaps::onSurfaceSupportsWritePixels(const GrSurface* surface) const { … }
GrCaps::SurfaceReadPixelsSupport GrGLCaps::surfaceSupportsReadPixels(
const GrSurface* surface) const { … }
size_t offset_alignment_for_transfer_buffer(GrGLenum externalType) { … }
GrCaps::SupportedRead GrGLCaps::onSupportedReadPixelsColorType(
GrColorType srcColorType, const GrBackendFormat& srcBackendFormat,
GrColorType dstColorType) const { … }
GrCaps::SupportedWrite GrGLCaps::supportedWritePixelsColorType(GrColorType surfaceColorType,
const GrBackendFormat& surfaceFormat,
GrColorType srcColorType) const { … }
bool GrGLCaps::programBinaryFormatIsValid(GrGLenum binaryFormat) const { … }
bool GrGLCaps::onIsWindowRectanglesSupportedForRT(const GrBackendRenderTarget& backendRT) const { … }
bool GrGLCaps::isFormatSRGB(const GrBackendFormat& format) const { … }
bool GrGLCaps::isFormatTexturable(const GrBackendFormat& format, GrTextureType textureType) const { … }
bool GrGLCaps::isFormatTexturable(GrGLFormat format) const { … }
bool GrGLCaps::isFormatAsColorTypeRenderable(GrColorType ct, const GrBackendFormat& format,
int sampleCount) const { … }
bool GrGLCaps::isFormatRenderable(const GrBackendFormat& format, int sampleCount) const { … }
int GrGLCaps::getRenderTargetSampleCount(int requestedCount, GrGLFormat format) const { … }
int GrGLCaps::maxRenderTargetSampleCount(GrGLFormat format) const { … }
bool GrGLCaps::canFormatBeFBOColorAttachment(GrGLFormat format) const { … }
bool GrGLCaps::isFormatCopyable(const GrBackendFormat& format) const { … }
bool GrGLCaps::formatSupportsTexStorage(GrGLFormat format) const { … }
bool GrGLCaps::shouldQueryImplementationReadSupport(GrGLFormat format) const { … }
void GrGLCaps::didQueryImplementationReadSupport(GrGLFormat format,
GrGLenum readFormat,
GrGLenum readType) const { … }
bool GrGLCaps::onAreColorTypeAndFormatCompatible(GrColorType ct,
const GrBackendFormat& format) const { … }
GrBackendFormat GrGLCaps::onGetDefaultBackendFormat(GrColorType ct) const { … }
GrBackendFormat GrGLCaps::getBackendFormatFromCompressionType(
SkTextureCompressionType compressionType) const { … }
skgpu::Swizzle GrGLCaps::onGetReadSwizzle(const GrBackendFormat& format,
GrColorType colorType) const { … }
skgpu::Swizzle GrGLCaps::getWriteSwizzle(const GrBackendFormat& format,
GrColorType colorType) const { … }
GrDstSampleFlags GrGLCaps::onGetDstSampleFlagsForProxy(const GrRenderTargetProxy* rt) const { … }
bool GrGLCaps::onSupportsDynamicMSAA(const GrRenderTargetProxy* rtProxy) const { … }
uint64_t GrGLCaps::computeFormatKey(const GrBackendFormat& format) const { … }
GrProgramDesc GrGLCaps::makeDesc(GrRenderTarget* ,
const GrProgramInfo& programInfo,
ProgramDescOverrideFlags overrideFlags) const { … }
#if defined(GPU_TEST_UTILS)
std::vector<GrTest::TestFormatColorTypeCombination> GrGLCaps::getTestingCombinations() const {
std::vector<GrTest::TestFormatColorTypeCombination> combos = {
{ GrColorType::kAlpha_8,
GrBackendFormats::MakeGL(GR_GL_ALPHA8, GR_GL_TEXTURE_2D) },
{ GrColorType::kAlpha_8,
GrBackendFormats::MakeGL(GR_GL_R8, GR_GL_TEXTURE_2D) },
{ GrColorType::kBGR_565,
GrBackendFormats::MakeGL(GR_GL_RGB565, GR_GL_TEXTURE_2D) },
{ GrColorType::kABGR_4444,
GrBackendFormats::MakeGL(GR_GL_RGBA4, GR_GL_TEXTURE_2D) },
{ GrColorType::kRGBA_8888,
GrBackendFormats::MakeGL(GR_GL_RGBA8, GR_GL_TEXTURE_2D) },
{ GrColorType::kRGBA_8888_SRGB,
GrBackendFormats::MakeGL(GR_GL_SRGB8_ALPHA8, GR_GL_TEXTURE_2D) },
{ GrColorType::kRGB_888x,
GrBackendFormats::MakeGL(GR_GL_RGBA8, GR_GL_TEXTURE_2D) },
{ GrColorType::kRGB_888x,
GrBackendFormats::MakeGL(GR_GL_BGRA8, GR_GL_TEXTURE_2D) },
{ GrColorType::kRGB_888x,
GrBackendFormats::MakeGL(GR_GL_RGB8, GR_GL_TEXTURE_2D) },
{ GrColorType::kRGB_888x,
GrBackendFormats::MakeGL(GR_GL_COMPRESSED_RGB8_ETC2, GR_GL_TEXTURE_2D) },
{ GrColorType::kRGB_888x,
GrBackendFormats::MakeGL(GR_GL_COMPRESSED_ETC1_RGB8, GR_GL_TEXTURE_2D) },
{ GrColorType::kRGB_888x,
GrBackendFormats::MakeGL(GR_GL_COMPRESSED_RGB_S3TC_DXT1_EXT, GR_GL_TEXTURE_2D) },
{ GrColorType::kRGBA_8888,
GrBackendFormats::MakeGL(GR_GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, GR_GL_TEXTURE_2D) },
{ GrColorType::kRG_88,
GrBackendFormats::MakeGL(GR_GL_RG8, GR_GL_TEXTURE_2D) },
{ GrColorType::kRGBA_1010102,
GrBackendFormats::MakeGL(GR_GL_RGB10_A2, GR_GL_TEXTURE_2D) },
{ GrColorType::kRGB_101010x,
GrBackendFormats::MakeGL(GR_GL_RGB10_A2, GR_GL_TEXTURE_2D) },
{ GrColorType::kGray_8,
GrBackendFormats::MakeGL(GR_GL_LUMINANCE8, GR_GL_TEXTURE_2D) },
{ GrColorType::kGray_8,
GrBackendFormats::MakeGL(GR_GL_R8, GR_GL_TEXTURE_2D) },
{ GrColorType::kGrayAlpha_88,
GrBackendFormats::MakeGL(GR_GL_LUMINANCE8_ALPHA8, GR_GL_TEXTURE_2D) },
{ GrColorType::kAlpha_F16,
GrBackendFormats::MakeGL(GR_GL_R16F, GR_GL_TEXTURE_2D) },
{ GrColorType::kAlpha_F16,
GrBackendFormats::MakeGL(GR_GL_LUMINANCE16F, GR_GL_TEXTURE_2D) },
{ GrColorType::kRGBA_F16,
GrBackendFormats::MakeGL(GR_GL_RGBA16F, GR_GL_TEXTURE_2D) },
{ GrColorType::kRGBA_F16_Clamped,
GrBackendFormats::MakeGL(GR_GL_RGBA16F, GR_GL_TEXTURE_2D) },
{ GrColorType::kRGB_F16F16F16x,
GrBackendFormats::MakeGL(GR_GL_RGBA16F, GR_GL_TEXTURE_2D) },
{ GrColorType::kAlpha_16,
GrBackendFormats::MakeGL(GR_GL_R16, GR_GL_TEXTURE_2D) },
{ GrColorType::kRG_1616,
GrBackendFormats::MakeGL(GR_GL_RG16, GR_GL_TEXTURE_2D) },
{ GrColorType::kRGBA_16161616,
GrBackendFormats::MakeGL(GR_GL_RGBA16, GR_GL_TEXTURE_2D) },
{ GrColorType::kRG_F16,
GrBackendFormats::MakeGL(GR_GL_RG16F, GR_GL_TEXTURE_2D) },
};
if (GR_IS_GR_GL(fStandard)) {
combos.push_back({ GrColorType::kBGRA_8888,
GrBackendFormats::MakeGL(GR_GL_RGBA8, GR_GL_TEXTURE_2D) });
combos.push_back({ GrColorType::kBGRA_1010102,
GrBackendFormats::MakeGL(GR_GL_RGB10_A2, GR_GL_TEXTURE_2D) });
} else {
SkASSERT(GR_IS_GR_GL_ES(fStandard) || GR_IS_GR_WEBGL(fStandard));
combos.push_back({ GrColorType::kBGRA_8888,
GrBackendFormats::MakeGL(GR_GL_BGRA8, GR_GL_TEXTURE_2D) });
}
if (this->rectangleTextureSupport()) {
size_t count2D = combos.size();
for (size_t i = 0; i < count2D; ++i) {
auto combo2D = combos[i];
GrGLenum formatEnum = GrBackendFormats::AsGLFormatEnum(combo2D.fFormat);
combos.push_back({combo2D.fColorType,
GrBackendFormats::MakeGL(formatEnum, GR_GL_TEXTURE_RECTANGLE)});
}
}
return combos;
}
#endif