chromium/third_party/skia/src/gpu/ganesh/gl/GrGLCaps.cpp

/*
 * Copyright 2012 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#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 {

    // We are called by the base class, which has already called beginObject(). We choose to nest
    // all of our caps information in a named sub-object.
    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* /* rt */,
                                 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