Reland "Separate texture creation from uploading in GrGpu subclasses."
This is a reland of a7398246cb
TBR:egdaniel@google.com
Original change's description:
> Separate texture creation from uploading in GrGpu subclasses.
>
> GrGpu base class still allows creation with initial data, but separated
> at subclass level into create and then write pixels.
>
> GrGpu handles determining which levels need clearing and GrGpu
> subclasses take a mask and clear levels with mask bit set.
>
> GrGLGpu uses three pronged clear strategy:
> glClearTexImage() if supported, glClear() if format is FBO bindable, and
> lastly glTexSubImage2D with zero'ed buffer.
>
> Change-Id: I65fb1e60eed8f9d0896d686d3baeb10b57ff8f39
> Reviewed-on: https://skia-review.googlesource.com/c/skia/+/236676
> Commit-Queue: Brian Salomon <bsalomon@google.com>
> Reviewed-by: Greg Daniel <egdaniel@google.com>
Change-Id: I54cda3b6a4b017a94ef1f50bb3748c45a24d8936
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/240558
Commit-Queue: Brian Salomon <bsalomon@google.com>
Reviewed-by: Brian Salomon <bsalomon@google.com>
This commit is contained in:
parent
c0c05047c2
commit
d2a8ae2b71
@ -289,17 +289,6 @@ public:
|
||||
*/
|
||||
bool shouldInitializeTextures() const { return fShouldInitializeTextures; }
|
||||
|
||||
/**
|
||||
* When this is true it is required that all textures are initially cleared. However, the
|
||||
* clearing must be implemented by passing level data to GrGpu::createTexture() rather than
|
||||
* be implemeted by GrGpu::createTexture().
|
||||
*
|
||||
* TODO: Make this take GrBacknedFormat when canClearTextureOnCreation() does as well.
|
||||
*/
|
||||
bool createTextureMustSpecifyAllLevels() const {
|
||||
return this->shouldInitializeTextures() && !this->canClearTextureOnCreation();
|
||||
}
|
||||
|
||||
/** Returns true if the given backend supports importing AHardwareBuffers via the
|
||||
* GrAHardwarebufferImageGenerator. This will only ever be supported on Android devices with API
|
||||
* level >= 26.
|
||||
@ -403,17 +392,6 @@ public:
|
||||
|
||||
virtual GrBackendFormat getBackendFormatFromCompressionType(SkImage::CompressionType) const = 0;
|
||||
|
||||
/**
|
||||
* Used by implementation of shouldInitializeTextures(). Indicates whether GrGpu implements the
|
||||
* clear in GrGpu::createTexture() or if false then the caller must provide cleared MIP level
|
||||
* data or GrGpu::createTexture() will fail.
|
||||
*
|
||||
* TODO: Make this take a GrBackendFormat so that GL can make this faster for cases
|
||||
* when the format is renderable and glTexClearImage is not available. Doing this
|
||||
* is overly complicated until the GrPixelConfig/format mess is straightened out..
|
||||
*/
|
||||
virtual bool canClearTextureOnCreation() const = 0;
|
||||
|
||||
/**
|
||||
* The CLAMP_TO_BORDER wrap mode for texture coordinates was added to desktop GL in 1.3, and
|
||||
* GLES 3.2, but is also available in extensions. Vulkan and Metal always have support.
|
||||
|
@ -99,8 +99,8 @@ bool GrGpu::IsACopyNeededForMips(const GrCaps* caps, const GrTextureProxy* texPr
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool validate_levels(int w, int h, const GrMipLevel texels[], int mipLevelCount, int bpp,
|
||||
const GrCaps* caps, bool mustHaveDataForAllLevels = false) {
|
||||
static bool validate_texel_levels(int w, int h, const GrMipLevel* texels, int mipLevelCount,
|
||||
int bpp, const GrCaps* caps) {
|
||||
SkASSERT(mipLevelCount > 0);
|
||||
bool hasBasePixels = texels[0].fPixels;
|
||||
int levelsWithPixelsCnt = 0;
|
||||
@ -138,10 +138,7 @@ static bool validate_levels(int w, int h, const GrMipLevel texels[], int mipLeve
|
||||
if (!hasBasePixels) {
|
||||
return levelsWithPixelsCnt == 0;
|
||||
}
|
||||
if (levelsWithPixelsCnt == 1 && !mustHaveDataForAllLevels) {
|
||||
return true;
|
||||
}
|
||||
return levelsWithPixelsCnt == mipLevelCount;
|
||||
return levelsWithPixelsCnt == 1 || levelsWithPixelsCnt == mipLevelCount;
|
||||
}
|
||||
|
||||
sk_sp<GrTexture> GrGpu::createTexture(const GrSurfaceDesc& desc,
|
||||
@ -151,14 +148,14 @@ sk_sp<GrTexture> GrGpu::createTexture(const GrSurfaceDesc& desc,
|
||||
SkBudgeted budgeted,
|
||||
GrProtected isProtected,
|
||||
const GrMipLevel texels[],
|
||||
int mipLevelCount) {
|
||||
int texelLevelCount) {
|
||||
TRACE_EVENT0("skia.gpu", TRACE_FUNC);
|
||||
if (this->caps()->isFormatCompressed(format)) {
|
||||
// Call GrGpu::createCompressedTexture.
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
GrMipMapped mipMapped = mipLevelCount > 1 ? GrMipMapped::kYes : GrMipMapped::kNo;
|
||||
GrMipMapped mipMapped = texelLevelCount > 1 ? GrMipMapped::kYes : GrMipMapped::kNo;
|
||||
if (!this->caps()->validateSurfaceParams({desc.fWidth, desc.fHeight}, format, desc.fConfig,
|
||||
renderable, renderTargetSampleCnt, mipMapped)) {
|
||||
return nullptr;
|
||||
@ -170,16 +167,26 @@ sk_sp<GrTexture> GrGpu::createTexture(const GrSurfaceDesc& desc,
|
||||
}
|
||||
// Attempt to catch un- or wrongly initialized sample counts.
|
||||
SkASSERT(renderTargetSampleCnt > 0 && renderTargetSampleCnt <= 64);
|
||||
|
||||
bool mustHaveDataForAllLevels = this->caps()->createTextureMustSpecifyAllLevels();
|
||||
if (mipLevelCount) {
|
||||
if (texelLevelCount) {
|
||||
int bpp = GrBytesPerPixel(desc.fConfig);
|
||||
if (!validate_levels(desc.fWidth, desc.fHeight, texels, mipLevelCount, bpp, this->caps(),
|
||||
mustHaveDataForAllLevels)) {
|
||||
if (!validate_texel_levels(desc.fWidth, desc.fHeight, texels, texelLevelCount, bpp,
|
||||
this->caps())) {
|
||||
return nullptr;
|
||||
}
|
||||
} else if (mustHaveDataForAllLevels) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
int mipLevelCount = SkTMax(1, texelLevelCount);
|
||||
uint32_t levelClearMask = 0;
|
||||
if (this->caps()->shouldInitializeTextures()) {
|
||||
if (texelLevelCount) {
|
||||
for (int i = 0; i < mipLevelCount; ++i) {
|
||||
if (!texels->fPixels) {
|
||||
levelClearMask |= static_cast<uint32_t>(1 << i);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
levelClearMask = static_cast<uint32_t>((1 << mipLevelCount) - 1);
|
||||
}
|
||||
}
|
||||
|
||||
this->handleDirtyContext();
|
||||
@ -189,20 +196,36 @@ sk_sp<GrTexture> GrGpu::createTexture(const GrSurfaceDesc& desc,
|
||||
renderTargetSampleCnt,
|
||||
budgeted,
|
||||
isProtected,
|
||||
texels,
|
||||
mipLevelCount);
|
||||
mipLevelCount,
|
||||
levelClearMask);
|
||||
|
||||
if (tex) {
|
||||
SkASSERT(tex->backendFormat() == format);
|
||||
SkASSERT(GrRenderable::kNo == renderable || tex->asRenderTarget());
|
||||
if (!this->caps()->reuseScratchTextures() && renderable == GrRenderable::kNo) {
|
||||
tex->resourcePriv().removeScratchKey();
|
||||
}
|
||||
fStats.incTextureCreates();
|
||||
if (mipLevelCount) {
|
||||
if (texels[0].fPixels) {
|
||||
fStats.incTextureUploads();
|
||||
bool markMipLevelsClean = false;
|
||||
// Currently if level 0 does not have pixels then no other level may, as enforced by
|
||||
// validate_texel_levels.
|
||||
if (texelLevelCount && texels[0].fPixels) {
|
||||
auto textureColorType = GrPixelConfigToColorType(desc.fConfig);
|
||||
auto dataColorType = textureColorType;
|
||||
if (!this->writePixels(tex.get(), 0, 0, desc.fWidth, desc.fHeight, textureColorType,
|
||||
dataColorType, texels, texelLevelCount)) {
|
||||
return nullptr;
|
||||
}
|
||||
// Currently if level[1] of mip map has pixel data then so must all other levels.
|
||||
// as enforced by validate_texel_levels.
|
||||
markMipLevelsClean = (texelLevelCount > 1 && !levelClearMask && texels[1].fPixels);
|
||||
fStats.incTextureUploads();
|
||||
} else if (levelClearMask && mipLevelCount > 1) {
|
||||
markMipLevelsClean = true;
|
||||
}
|
||||
if (markMipLevelsClean) {
|
||||
tex->texturePriv().markMipMapsClean();
|
||||
}
|
||||
SkASSERT(tex->backendFormat() == format);
|
||||
SkASSERT(!tex || GrRenderable::kNo == renderable || tex->asRenderTarget());
|
||||
if (renderTargetSampleCnt > 1 && !this->caps()->msaaResolvesAutomatically()) {
|
||||
SkASSERT(GrRenderable::kYes == renderable);
|
||||
tex->asRenderTarget()->setRequiresManualMSAAResolve();
|
||||
@ -432,7 +455,7 @@ bool GrGpu::writePixels(GrSurface* surface, int left, int top, int width, int he
|
||||
}
|
||||
|
||||
size_t bpp = GrColorTypeBytesPerPixel(srcColorType);
|
||||
if (!validate_levels(width, height, texels, mipLevelCount, bpp, this->caps())) {
|
||||
if (!validate_texel_levels(width, height, texels, mipLevelCount, bpp, this->caps())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -103,7 +103,7 @@ public:
|
||||
* If mipLevelCount > 1 and texels[i].fPixels != nullptr for any i > 0
|
||||
* then all levels must have non-null pixels. All levels must have
|
||||
* non-null pixels if GrCaps::createTextureMustSpecifyAllLevels() is true.
|
||||
* @param mipLevelCount the number of levels in 'texels'. May be 0, 1, or
|
||||
* @param texelLevelCount the number of levels in 'texels'. May be 0, 1, or
|
||||
* floor(max((log2(desc.fWidth), log2(desc.fHeight)))). It must be the
|
||||
* latter if GrCaps::createTextureMustSpecifyAllLevels() is true.
|
||||
* @return The texture object if successful, otherwise nullptr.
|
||||
@ -111,7 +111,7 @@ public:
|
||||
sk_sp<GrTexture> createTexture(const GrSurfaceDesc& desc, const GrBackendFormat& format,
|
||||
GrRenderable renderable, int renderTargetSampleCnt, SkBudgeted,
|
||||
GrProtected isProtected, const GrMipLevel texels[],
|
||||
int mipLevelCount);
|
||||
int texelLevelCount);
|
||||
|
||||
/**
|
||||
* Simplified createTexture() interface for when there is no initial texel data to upload.
|
||||
@ -546,15 +546,17 @@ private:
|
||||
virtual void xferBarrier(GrRenderTarget*, GrXferBarrierType) = 0;
|
||||
|
||||
// overridden by backend-specific derived class to create objects.
|
||||
// Texture size and sample size will have already been validated in base class before
|
||||
// onCreateTexture is called.
|
||||
// Texture size, renderablility, format support, sample count will have already been validated
|
||||
// in base class before onCreateTexture is called.
|
||||
// If the ith bit is set in levelClearMask then the ith MIP level should be cleared.
|
||||
virtual sk_sp<GrTexture> onCreateTexture(const GrSurfaceDesc&,
|
||||
const GrBackendFormat&,
|
||||
GrRenderable,
|
||||
int renderTargetSampleCnt,
|
||||
SkBudgeted, GrProtected,
|
||||
const GrMipLevel[],
|
||||
int mipLevelCount) = 0;
|
||||
SkBudgeted,
|
||||
GrProtected,
|
||||
int mipLevelCoont,
|
||||
uint32_t levelClearMask) = 0;
|
||||
virtual sk_sp<GrTexture> onCreateCompressedTexture(int width, int height,
|
||||
const GrBackendFormat&,
|
||||
SkImage::CompressionType, SkBudgeted,
|
||||
|
@ -45,18 +45,11 @@ GrResourceProvider::GrResourceProvider(GrGpu* gpu, GrResourceCache* cache, GrSin
|
||||
// Ensures the row bytes are populated (not 0) and makes a copy to a temporary
|
||||
// to make the row bytes tight if necessary. Returns false if the input row bytes are invalid.
|
||||
static bool prepare_level(const GrMipLevel& inLevel, size_t bpp, int w, int h, bool rowBytesSupport,
|
||||
bool mustInitializeAllLevels, GrMipLevel* outLevel,
|
||||
std::unique_ptr<char[]>* data) {
|
||||
GrMipLevel* outLevel, std::unique_ptr<char[]>* data) {
|
||||
size_t minRB = w * bpp;
|
||||
if (!inLevel.fPixels) {
|
||||
if (mustInitializeAllLevels) {
|
||||
data->reset(new char[minRB * h]());
|
||||
outLevel->fPixels = data->get();
|
||||
outLevel->fRowBytes = minRB;
|
||||
} else {
|
||||
outLevel->fPixels = nullptr;
|
||||
outLevel->fRowBytes = 0;
|
||||
}
|
||||
outLevel->fPixels = nullptr;
|
||||
outLevel->fRowBytes = 0;
|
||||
return true;
|
||||
}
|
||||
size_t actualRB = inLevel.fRowBytes ? inLevel.fRowBytes : minRB;
|
||||
@ -97,7 +90,6 @@ sk_sp<GrTexture> GrResourceProvider::createTexture(const GrSurfaceDesc& desc,
|
||||
renderTargetSampleCnt, mipMapped)) {
|
||||
return nullptr;
|
||||
}
|
||||
bool mustInitializeAllLevels = this->caps()->createTextureMustSpecifyAllLevels();
|
||||
bool rowBytesSupport = this->caps()->writePixelsRowBytesSupport();
|
||||
SkAutoSTMalloc<14, GrMipLevel> tmpTexels;
|
||||
SkAutoSTArray<14, std::unique_ptr<char[]>> tmpDatas;
|
||||
@ -108,8 +100,8 @@ sk_sp<GrTexture> GrResourceProvider::createTexture(const GrSurfaceDesc& desc,
|
||||
int h = desc.fHeight;
|
||||
size_t bpp = GrBytesPerPixel(desc.fConfig);
|
||||
for (int i = 0; i < mipLevelCount; ++i) {
|
||||
if (!prepare_level(texels[i], bpp, w, h, rowBytesSupport, mustInitializeAllLevels,
|
||||
&tmpTexels[i], &tmpDatas[i])) {
|
||||
if (!prepare_level(texels[i], bpp, w, h, rowBytesSupport, &tmpTexels[i],
|
||||
&tmpDatas[i])) {
|
||||
return nullptr;
|
||||
}
|
||||
w = std::max(w / 2, 1);
|
||||
@ -162,14 +154,13 @@ sk_sp<GrTexture> GrResourceProvider::createTexture(const GrSurfaceDesc& desc,
|
||||
GrContext* context = fGpu->getContext();
|
||||
GrProxyProvider* proxyProvider = context->priv().proxyProvider();
|
||||
|
||||
bool mustInitialize = this->caps()->createTextureMustSpecifyAllLevels();
|
||||
bool rowBytesSupport = this->caps()->writePixelsRowBytesSupport();
|
||||
|
||||
size_t bpp = GrBytesPerPixel(desc.fConfig);
|
||||
std::unique_ptr<char[]> tmpData;
|
||||
GrMipLevel tmpLevel;
|
||||
if (!prepare_level(mipLevel, bpp, desc.fWidth, desc.fHeight, rowBytesSupport, mustInitialize,
|
||||
&tmpLevel, &tmpData)) {
|
||||
if (!prepare_level(mipLevel, bpp, desc.fWidth, desc.fHeight, rowBytesSupport, &tmpLevel,
|
||||
&tmpData)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@ -239,17 +230,6 @@ sk_sp<GrTexture> GrResourceProvider::createTexture(const GrSurfaceDesc& desc,
|
||||
}
|
||||
}
|
||||
|
||||
if (fCaps->createTextureMustSpecifyAllLevels()) {
|
||||
size_t rowBytes = GrBytesPerPixel(desc.fConfig) * desc.fWidth;
|
||||
size_t size = rowBytes * desc.fHeight;
|
||||
std::unique_ptr<char[]> zeros(new char[size]());
|
||||
GrMipLevel level;
|
||||
level.fRowBytes = rowBytes;
|
||||
level.fPixels = zeros.get();
|
||||
return fGpu->createTexture(desc, format, renderable, renderTargetSampleCnt, budgeted,
|
||||
isProtected, &level, 1);
|
||||
}
|
||||
|
||||
return fGpu->createTexture(desc, format, renderable, renderTargetSampleCnt, budgeted,
|
||||
isProtected);
|
||||
}
|
||||
@ -320,16 +300,6 @@ sk_sp<GrTexture> GrResourceProvider::createApproxTexture(const GrSurfaceDesc& de
|
||||
return tex;
|
||||
}
|
||||
|
||||
if (this->caps()->createTextureMustSpecifyAllLevels()) {
|
||||
size_t rowBytes = GrBytesPerPixel(copyDesc->fConfig) * copyDesc->fWidth;
|
||||
size_t size = rowBytes * copyDesc->fHeight;
|
||||
std::unique_ptr<char[]> zeros(new char[size]());
|
||||
GrMipLevel level;
|
||||
level.fRowBytes = rowBytes;
|
||||
level.fPixels = zeros.get();
|
||||
return fGpu->createTexture(*copyDesc, format, renderable, renderTargetSampleCnt,
|
||||
SkBudgeted::kYes, isProtected, &level, 1);
|
||||
}
|
||||
return fGpu->createTexture(*copyDesc, format, renderable, renderTargetSampleCnt,
|
||||
SkBudgeted::kYes, isProtected);
|
||||
}
|
||||
|
@ -175,10 +175,6 @@ GrSwizzle GrDawnCaps::getTextureSwizzle(const GrBackendFormat& format, GrColorTy
|
||||
return get_swizzle(format, colorType, false);
|
||||
}
|
||||
|
||||
bool GrDawnCaps::canClearTextureOnCreation() const {
|
||||
return true;
|
||||
}
|
||||
|
||||
GrSwizzle GrDawnCaps::getOutputSwizzle(const GrBackendFormat& format, GrColorType colorType) const
|
||||
{
|
||||
return get_swizzle(format, colorType, true);
|
||||
|
@ -48,8 +48,6 @@ public:
|
||||
|
||||
GrBackendFormat getBackendFormatFromCompressionType(SkImage::CompressionType) const override;
|
||||
|
||||
bool canClearTextureOnCreation() const override;
|
||||
|
||||
GrSwizzle getTextureSwizzle(const GrBackendFormat&, GrColorType) const override;
|
||||
|
||||
GrSwizzle getOutputSwizzle(const GrBackendFormat&, GrColorType) const override;
|
||||
|
@ -1195,12 +1195,12 @@ void GrGLCaps::onDumpJSON(SkJSONWriter* writer) const {
|
||||
writer->beginObject(nullptr, false);
|
||||
writer->appendHexU32("flags", fFormatTable[i].fFlags);
|
||||
writer->appendHexU32("f_type", (uint32_t)fFormatTable[i].fFormatType);
|
||||
writer->appendHexU32("b_internal", fFormatTable[i].fBaseInternalFormat);
|
||||
writer->appendHexU32("s_internal", fFormatTable[i].fSizedInternalFormat);
|
||||
writer->appendHexU32("c_internal", fFormatTable[i].fCompressedInternalFormat);
|
||||
writer->appendHexU32("i_for_teximage", fFormatTable[i].fInternalFormatForTexImage);
|
||||
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->appendHexU64("z_bpp", fFormatTable[i].fTexSubImageZeroDataBpp);
|
||||
|
||||
writer->beginArray("surface color types");
|
||||
for (int j = 0; j < fFormatTable[i].fColorTypeInfoCount; ++j) {
|
||||
@ -1233,12 +1233,28 @@ void GrGLCaps::onDumpJSON(SkJSONWriter* writer) const {
|
||||
void GrGLCaps::onDumpJSON(SkJSONWriter* writer) const { }
|
||||
#endif
|
||||
|
||||
void GrGLCaps::getTexImageFormats(GrGLFormat surfaceFormat, GrColorType surfaceColorType,
|
||||
GrColorType memoryColorType, GrGLenum* internalFormat,
|
||||
GrGLenum* externalFormat, GrGLenum* externalType) const {
|
||||
void GrGLCaps::getTexImageExternalFormatAndType(GrGLFormat surfaceFormat, GrGLenum* externalFormat,
|
||||
GrGLenum* externalType) const {
|
||||
const auto& info = this->getFormatInfo(surfaceFormat);
|
||||
*externalType = info.fDefaultExternalType;
|
||||
*externalFormat = info.fDefaultExternalFormat;
|
||||
}
|
||||
|
||||
void GrGLCaps::getTexSubImageZeroFormatTypeAndBpp(GrGLFormat format, GrGLenum* externalFormat,
|
||||
GrGLenum* externalType, size_t* bpp) const {
|
||||
const auto& info = this->getFormatInfo(format);
|
||||
*externalType = info.fDefaultExternalType;
|
||||
*externalFormat = info.fDefaultExternalFormat;
|
||||
*bpp = info.fTexSubImageZeroDataBpp;
|
||||
}
|
||||
|
||||
void GrGLCaps::getTexSubImageExternalFormatAndType(GrGLFormat surfaceFormat,
|
||||
GrColorType surfaceColorType,
|
||||
GrColorType memoryColorType,
|
||||
GrGLenum* externalFormat,
|
||||
GrGLenum* externalType) const {
|
||||
this->getExternalFormat(surfaceFormat, surfaceColorType, memoryColorType,
|
||||
kTexImage_ExternalFormatUsage, externalFormat, externalType);
|
||||
*internalFormat = this->getTexImageInternalFormat(surfaceFormat);
|
||||
}
|
||||
|
||||
void GrGLCaps::getReadPixelsFormat(GrGLFormat surfaceFormat, GrColorType surfaceColorType,
|
||||
@ -1417,12 +1433,10 @@ void GrGLCaps::initFormatTable(const GrGLContextInfo& ctxInfo, const GrGLInterfa
|
||||
{
|
||||
FormatInfo& info = this->getFormatInfo(GrGLFormat::kRGBA8);
|
||||
info.fFormatType = FormatType::kNormalizedFixedPoint;
|
||||
info.fBaseInternalFormat = GR_GL_RGBA;
|
||||
info.fSizedInternalFormat = GR_GL_RGBA8;
|
||||
info.fInternalFormatForTexImage =
|
||||
texImageSupportsSizedInternalFormat ? GR_GL_RGBA8 : GR_GL_RGBA;
|
||||
info.fInternalFormatForRenderbuffer = GR_GL_RGBA8;
|
||||
info.fDefaultExternalFormat = GR_GL_RGBA;
|
||||
info.fDefaultExternalType = GR_GL_UNSIGNED_BYTE;
|
||||
info.fTexSubImageZeroDataBpp = 4;
|
||||
info.fFlags = FormatInfo::kTexturable_Flag;
|
||||
if (GR_IS_GR_GL(standard)) {
|
||||
info.fFlags |= msaaRenderFlags;
|
||||
@ -1436,7 +1450,11 @@ void GrGLCaps::initFormatTable(const GrGLContextInfo& ctxInfo, const GrGLInterfa
|
||||
}
|
||||
|
||||
if (texStorageSupported) {
|
||||
info.fFlags |= FormatInfo::kCanUseTexStorage_Flag;
|
||||
info.fFlags |= FormatInfo::kUseTexStorage_Flag;
|
||||
info.fInternalFormatForTexImageOrStorage = GR_GL_RGBA8;
|
||||
} else {
|
||||
info.fInternalFormatForTexImageOrStorage =
|
||||
texImageSupportsSizedInternalFormat ? GR_GL_RGBA8 : GR_GL_RGBA;
|
||||
}
|
||||
|
||||
bool supportsBGRAColorType = GR_IS_GR_GL(standard) &&
|
||||
@ -1524,19 +1542,21 @@ void GrGLCaps::initFormatTable(const GrGLContextInfo& ctxInfo, const GrGLInterfa
|
||||
{
|
||||
FormatInfo& info = this->getFormatInfo(GrGLFormat::kR8);
|
||||
info.fFormatType = FormatType::kNormalizedFixedPoint;
|
||||
info.fBaseInternalFormat = GR_GL_RED;
|
||||
info.fSizedInternalFormat = GR_GL_R8;
|
||||
info.fInternalFormatForTexImage =
|
||||
texImageSupportsSizedInternalFormat ? GR_GL_R8 : GR_GL_RED;
|
||||
info.fInternalFormatForRenderbuffer = GR_GL_R8;
|
||||
info.fDefaultExternalFormat = GR_GL_RED;
|
||||
info.fDefaultExternalType = GR_GL_UNSIGNED_BYTE;
|
||||
info.fTexSubImageZeroDataBpp = 1;
|
||||
if (textureRedSupport) {
|
||||
info.fFlags |= FormatInfo::kTexturable_Flag | msaaRenderFlags;
|
||||
}
|
||||
|
||||
if (texStorageSupported &&
|
||||
!formatWorkarounds.fDisablePerFormatTextureStorageForCommandBufferES2) {
|
||||
info.fFlags |= FormatInfo::kCanUseTexStorage_Flag;
|
||||
info.fFlags |= FormatInfo::kUseTexStorage_Flag;
|
||||
info.fInternalFormatForTexImageOrStorage = GR_GL_R8;
|
||||
} else {
|
||||
info.fInternalFormatForTexImageOrStorage =
|
||||
texImageSupportsSizedInternalFormat ? GR_GL_R8 : GR_GL_RED;
|
||||
}
|
||||
|
||||
if (textureRedSupport) {
|
||||
@ -1619,8 +1639,6 @@ void GrGLCaps::initFormatTable(const GrGLContextInfo& ctxInfo, const GrGLInterfa
|
||||
|
||||
FormatInfo& info = this->getFormatInfo(GrGLFormat::kALPHA8);
|
||||
info.fFormatType = FormatType::kNormalizedFixedPoint;
|
||||
info.fBaseInternalFormat = GR_GL_ALPHA;
|
||||
info.fSizedInternalFormat = GR_GL_ALPHA8;
|
||||
// GL_EXT_texture_storage adds GL_ALPHA8 for texture storage. However, ES3 has glTexStorage
|
||||
// but does not have GL_ALPHA8 (and requires a sized internal format for glTexStorage).
|
||||
// WebGL never has GL_ALPHA8.
|
||||
@ -1628,14 +1646,6 @@ void GrGLCaps::initFormatTable(const GrGLContextInfo& ctxInfo, const GrGLInterfa
|
||||
alpha8IsValidForGL ||
|
||||
(alpha8IsValidForGLES && ctxInfo.hasExtension("GL_EXT_texture_storage"));
|
||||
bool alpha8TexStorageSupported = alpha8SizedEnumSupported && texStorageSupported;
|
||||
// Even if GL_ALPHA8 is added by GL_EXT_texture_storage it doesn't become legal for
|
||||
// glTexImage2D.
|
||||
if (!GR_IS_GR_GL_ES(standard) && texImageSupportsSizedInternalFormat &&
|
||||
alpha8SizedEnumSupported) {
|
||||
info.fInternalFormatForTexImage = GR_GL_ALPHA8;
|
||||
} else {
|
||||
info.fInternalFormatForTexImage = GR_GL_ALPHA;
|
||||
}
|
||||
|
||||
bool alpha8IsRenderable = false;
|
||||
if (!formatWorkarounds.fDisableAlpha8Renderable) {
|
||||
@ -1647,8 +1657,9 @@ void GrGLCaps::initFormatTable(const GrGLContextInfo& ctxInfo, const GrGLInterfa
|
||||
}
|
||||
}
|
||||
info.fInternalFormatForRenderbuffer = GR_GL_ALPHA8;
|
||||
|
||||
info.fDefaultExternalFormat = GR_GL_ALPHA;
|
||||
info.fDefaultExternalType = GR_GL_UNSIGNED_BYTE;
|
||||
info.fTexSubImageZeroDataBpp = 1;
|
||||
if (alpha8IsValidForGL || alpha8IsValidForGLES || alpha8IsValidForWebGL) {
|
||||
info.fFlags = FormatInfo::kTexturable_Flag;
|
||||
}
|
||||
@ -1658,7 +1669,17 @@ void GrGLCaps::initFormatTable(const GrGLContextInfo& ctxInfo, const GrGLInterfa
|
||||
info.fFlags |= msaaRenderFlags;
|
||||
}
|
||||
if (alpha8TexStorageSupported) {
|
||||
info.fFlags |= FormatInfo::kCanUseTexStorage_Flag;
|
||||
info.fFlags |= FormatInfo::kUseTexStorage_Flag;
|
||||
info.fInternalFormatForTexImageOrStorage = GR_GL_ALPHA8;
|
||||
} else {
|
||||
// Even if GL_ALPHA8 is added to ES by GL_EXT_texture_storage it doesn't become legal
|
||||
// for glTexImage2D.
|
||||
if (!GR_IS_GR_GL_ES(standard) && texImageSupportsSizedInternalFormat &&
|
||||
alpha8SizedEnumSupported) {
|
||||
info.fInternalFormatForTexImageOrStorage = GR_GL_ALPHA8;
|
||||
} else {
|
||||
info.fInternalFormatForTexImageOrStorage = GR_GL_ALPHA;
|
||||
}
|
||||
}
|
||||
|
||||
if (alpha8IsValidForGL || alpha8IsValidForGLES || alpha8IsValidForWebGL) {
|
||||
@ -1709,12 +1730,10 @@ void GrGLCaps::initFormatTable(const GrGLContextInfo& ctxInfo, const GrGLInterfa
|
||||
{
|
||||
FormatInfo& info = this->getFormatInfo(GrGLFormat::kLUMINANCE8);
|
||||
info.fFormatType = FormatType::kNormalizedFixedPoint;
|
||||
info.fBaseInternalFormat = GR_GL_LUMINANCE;
|
||||
info.fSizedInternalFormat = GR_GL_LUMINANCE8;
|
||||
info.fInternalFormatForTexImage =
|
||||
texImageSupportsSizedInternalFormat ? GR_GL_LUMINANCE8 : GR_GL_LUMINANCE;
|
||||
info.fInternalFormatForRenderbuffer = GR_GL_LUMINANCE8;
|
||||
info.fDefaultExternalFormat = GR_GL_LUMINANCE;
|
||||
info.fDefaultExternalType = GR_GL_UNSIGNED_BYTE;
|
||||
info.fTexSubImageZeroDataBpp = 1;
|
||||
bool supportsLum = (GR_IS_GR_GL(standard) && version <= GR_GL_VER(3, 0)) ||
|
||||
(GR_IS_GR_GL_ES(standard) && version < GR_GL_VER(3, 0)) ||
|
||||
(GR_IS_GR_WEBGL(standard));
|
||||
@ -1724,7 +1743,11 @@ void GrGLCaps::initFormatTable(const GrGLContextInfo& ctxInfo, const GrGLInterfa
|
||||
if (texStorageSupported &&
|
||||
!formatWorkarounds.fDisablePerFormatTextureStorageForCommandBufferES2 &&
|
||||
!formatWorkarounds.fDisableNonRedSingleChannelTexStorageForANGLEGL) {
|
||||
info.fFlags |= FormatInfo::kCanUseTexStorage_Flag;
|
||||
info.fFlags |= FormatInfo::kUseTexStorage_Flag;
|
||||
info.fInternalFormatForTexImageOrStorage = GR_GL_LUMINANCE8;
|
||||
} else {
|
||||
info.fInternalFormatForTexImageOrStorage =
|
||||
texImageSupportsSizedInternalFormat ? GR_GL_LUMINANCE8 : GR_GL_LUMINANCE;
|
||||
}
|
||||
// We are not enabling attaching to an FBO for LUMINANCE8 mostly because of confusion in the
|
||||
// spec. For GLES it does not seem to ever support LUMINANCE8 being color-renderable. For GL
|
||||
@ -1780,23 +1803,6 @@ void GrGLCaps::initFormatTable(const GrGLContextInfo& ctxInfo, const GrGLInterfa
|
||||
{
|
||||
FormatInfo& info = this->getFormatInfo(GrGLFormat::kBGRA8);
|
||||
info.fFormatType = FormatType::kNormalizedFixedPoint;
|
||||
info.fBaseInternalFormat = GR_GL_BGRA;
|
||||
info.fSizedInternalFormat = GR_GL_BGRA8;
|
||||
// If BGRA is supported as an internal format it must always be specified to glTex[Sub]Image
|
||||
// as a base format. Which base format depends on which extension is used.
|
||||
if (ctxInfo.hasExtension("GL_APPLE_texture_format_BGRA8888")) {
|
||||
// GL_APPLE_texture_format_BGRA8888:
|
||||
// ES 2.0: the extension makes BGRA an external format but not an internal format.
|
||||
// ES 3.0: the extension explicitly states GL_BGRA8 is not a valid internal format
|
||||
// for glTexImage (just for glTexStorage).
|
||||
info.fInternalFormatForTexImage = GR_GL_RGBA;
|
||||
} else {
|
||||
// GL_EXT_texture_format_BGRA8888:
|
||||
// This extension adds GL_BGRA as an unsized internal format. However, it is
|
||||
// written against ES 2.0 and therefore doesn't define a GL_BGRA8 as ES 2.0 doesn't
|
||||
// have sized internal formats.
|
||||
info.fInternalFormatForTexImage = GR_GL_BGRA;
|
||||
}
|
||||
|
||||
// We currently only use the renderbuffer format when allocating msaa renderbuffers, so we
|
||||
// are making decisions here based on that use case. The GL_EXT_texture_format_BGRA8888
|
||||
@ -1819,7 +1825,28 @@ void GrGLCaps::initFormatTable(const GrGLContextInfo& ctxInfo, const GrGLInterfa
|
||||
info.fInternalFormatForRenderbuffer = GR_GL_BGRA8;
|
||||
}
|
||||
|
||||
info.fDefaultExternalFormat = GR_GL_BGRA;
|
||||
info.fDefaultExternalType = GR_GL_UNSIGNED_BYTE;
|
||||
info.fTexSubImageZeroDataBpp = 4;
|
||||
|
||||
GrGLenum bgraTexImageFormat;
|
||||
// If BGRA is supported as an internal format it must always be specified to glTex[Sub]Image
|
||||
// as a base format. Which base format depends on which extension is used.
|
||||
if (ctxInfo.hasExtension("GL_APPLE_texture_format_BGRA8888")) {
|
||||
// GL_APPLE_texture_format_BGRA8888:
|
||||
// ES 2.0: the extension makes BGRA an external format but not an internal format.
|
||||
// ES 3.0: the extension explicitly states GL_BGRA8 is not a valid internal format
|
||||
// for glTexImage (just for glTexStorage).
|
||||
bgraTexImageFormat = GR_GL_RGBA;
|
||||
} else {
|
||||
// GL_EXT_texture_format_BGRA8888:
|
||||
// This extension adds GL_BGRA as an unsized internal format. However, it is
|
||||
// written against ES 2.0 and therefore doesn't define a GL_BGRA8 as ES 2.0 doesn't
|
||||
// have sized internal formats. See later where we check for tex storage BGRA8
|
||||
// support.
|
||||
bgraTexImageFormat = GR_GL_BGRA;
|
||||
}
|
||||
|
||||
// TexStorage requires using a sized internal format and BGRA8 is only supported if we have
|
||||
// the GL_APPLE_texture_format_BGRA8888 extension or if we have GL_EXT_texture_storage and
|
||||
// GL_EXT_texture_format_BGRA8888.
|
||||
@ -1829,7 +1856,8 @@ void GrGLCaps::initFormatTable(const GrGLContextInfo& ctxInfo, const GrGLInterfa
|
||||
if (ctxInfo.hasExtension("GL_EXT_texture_format_BGRA8888")) {
|
||||
info.fFlags = FormatInfo::kTexturable_Flag | nonMSAARenderFlags;
|
||||
// GL_EXT_texture storage has defined interactions with
|
||||
// GL_EXT_texture_format_BGRA8888.
|
||||
// GL_EXT_texture_format_BGRA8888. However, ES3 supports glTexStorage but
|
||||
// without GL_EXT_texture_storage it does not allow the BGRA8 sized internal format.
|
||||
if (ctxInfo.hasExtension("GL_EXT_texture_storage") &&
|
||||
!formatWorkarounds.fDisableBGRATextureStorageForIntelWindowsES) {
|
||||
supportsBGRATexStorage = true;
|
||||
@ -1852,7 +1880,10 @@ void GrGLCaps::initFormatTable(const GrGLContextInfo& ctxInfo, const GrGLInterfa
|
||||
}
|
||||
}
|
||||
if (texStorageSupported && supportsBGRATexStorage) {
|
||||
info.fFlags |= FormatInfo::kCanUseTexStorage_Flag;
|
||||
info.fFlags |= FormatInfo::kUseTexStorage_Flag;
|
||||
info.fInternalFormatForTexImageOrStorage = GR_GL_BGRA8;
|
||||
} else {
|
||||
info.fInternalFormatForTexImageOrStorage = bgraTexImageFormat;
|
||||
}
|
||||
|
||||
if (SkToBool(info.fFlags &FormatInfo::kTexturable_Flag)) {
|
||||
@ -1896,12 +1927,10 @@ void GrGLCaps::initFormatTable(const GrGLContextInfo& ctxInfo, const GrGLInterfa
|
||||
{
|
||||
FormatInfo& info = this->getFormatInfo(GrGLFormat::kRGB565);
|
||||
info.fFormatType = FormatType::kNormalizedFixedPoint;
|
||||
info.fBaseInternalFormat = GR_GL_RGB;
|
||||
info.fSizedInternalFormat = GR_GL_RGB565;
|
||||
info.fInternalFormatForTexImage =
|
||||
texImageSupportsSizedInternalFormat ? GR_GL_RGB565 : GR_GL_RGB;
|
||||
info.fInternalFormatForRenderbuffer = GR_GL_RGB565;
|
||||
info.fDefaultExternalFormat = GR_GL_RGB;
|
||||
info.fDefaultExternalType = GR_GL_UNSIGNED_SHORT_5_6_5;
|
||||
info.fTexSubImageZeroDataBpp = 2;
|
||||
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;
|
||||
@ -1919,7 +1948,11 @@ void GrGLCaps::initFormatTable(const GrGLContextInfo& ctxInfo, const GrGLInterfa
|
||||
// TODO: As of 4.2, regular GL supports 565. This logic is due for an
|
||||
// update.
|
||||
if (texStorageSupported && GR_IS_GR_GL_ES(standard)) {
|
||||
info.fFlags |= FormatInfo::kCanUseTexStorage_Flag;
|
||||
info.fFlags |= FormatInfo::kUseTexStorage_Flag;
|
||||
info.fInternalFormatForTexImageOrStorage = GR_GL_RGB565;
|
||||
} else {
|
||||
info.fInternalFormatForTexImageOrStorage =
|
||||
texImageSupportsSizedInternalFormat ? GR_GL_RGB565 : GR_GL_RGB;
|
||||
}
|
||||
|
||||
if (SkToBool(info.fFlags &FormatInfo::kTexturable_Flag)) {
|
||||
@ -1963,12 +1996,10 @@ void GrGLCaps::initFormatTable(const GrGLContextInfo& ctxInfo, const GrGLInterfa
|
||||
{
|
||||
FormatInfo& info = this->getFormatInfo(GrGLFormat::kRGBA16F);
|
||||
info.fFormatType = FormatType::kFloat;
|
||||
info.fBaseInternalFormat = GR_GL_RGBA;
|
||||
info.fSizedInternalFormat = GR_GL_RGBA16F;
|
||||
info.fInternalFormatForTexImage =
|
||||
texImageSupportsSizedInternalFormat ? GR_GL_RGBA16F : GR_GL_RGBA;
|
||||
info.fInternalFormatForRenderbuffer = GR_GL_RGBA16F;
|
||||
info.fDefaultExternalFormat = GR_GL_RGBA;
|
||||
info.fDefaultExternalType = halfFloatType;
|
||||
info.fTexSubImageZeroDataBpp = 8;
|
||||
if (hasFP16Textures) {
|
||||
info.fFlags = FormatInfo::kTexturable_Flag;
|
||||
// ES requires 3.2 or EXT_color_buffer_half_float.
|
||||
@ -1978,7 +2009,11 @@ void GrGLCaps::initFormatTable(const GrGLContextInfo& ctxInfo, const GrGLInterfa
|
||||
}
|
||||
if (texStorageSupported &&
|
||||
!formatWorkarounds.fDisablePerFormatTextureStorageForCommandBufferES2) {
|
||||
info.fFlags |= FormatInfo::kCanUseTexStorage_Flag;
|
||||
info.fFlags |= FormatInfo::kUseTexStorage_Flag;
|
||||
info.fInternalFormatForTexImageOrStorage = GR_GL_RGBA16F;
|
||||
} else {
|
||||
info.fInternalFormatForTexImageOrStorage =
|
||||
texImageSupportsSizedInternalFormat ? GR_GL_RGBA16F : GR_GL_RGBA;
|
||||
}
|
||||
|
||||
if (hasFP16Textures) {
|
||||
@ -2055,12 +2090,10 @@ void GrGLCaps::initFormatTable(const GrGLContextInfo& ctxInfo, const GrGLInterfa
|
||||
{
|
||||
FormatInfo& info = this->getFormatInfo(GrGLFormat::kR16F);
|
||||
info.fFormatType = FormatType::kFloat;
|
||||
info.fBaseInternalFormat = GR_GL_RED;
|
||||
info.fSizedInternalFormat = GR_GL_R16F;
|
||||
info.fInternalFormatForTexImage =
|
||||
texImageSupportsSizedInternalFormat ? GR_GL_R16F : GR_GL_RED;
|
||||
info.fInternalFormatForRenderbuffer = GR_GL_R16F;
|
||||
info.fDefaultExternalFormat = GR_GL_RED;
|
||||
info.fDefaultExternalType = halfFloatType;
|
||||
info.fTexSubImageZeroDataBpp = 2;
|
||||
if (textureRedSupport && hasFP16Textures) {
|
||||
info.fFlags = FormatInfo::kTexturable_Flag;
|
||||
if (halfFPRenderTargetSupport == HalfFPRenderTargetSupport::kAll) {
|
||||
@ -2069,7 +2102,11 @@ void GrGLCaps::initFormatTable(const GrGLContextInfo& ctxInfo, const GrGLInterfa
|
||||
}
|
||||
if (texStorageSupported &&
|
||||
!formatWorkarounds.fDisablePerFormatTextureStorageForCommandBufferES2) {
|
||||
info.fFlags |= FormatInfo::kCanUseTexStorage_Flag;
|
||||
info.fFlags |= FormatInfo::kUseTexStorage_Flag;
|
||||
info.fInternalFormatForTexImageOrStorage = GR_GL_R16F;
|
||||
} else {
|
||||
info.fInternalFormatForTexImageOrStorage =
|
||||
texImageSupportsSizedInternalFormat ? GR_GL_R16F : GR_GL_RED;
|
||||
}
|
||||
|
||||
if (textureRedSupport && hasFP16Textures) {
|
||||
@ -2137,19 +2174,21 @@ void GrGLCaps::initFormatTable(const GrGLContextInfo& ctxInfo, const GrGLInterfa
|
||||
|
||||
FormatInfo& info = this->getFormatInfo(GrGLFormat::kLUMINANCE16F);
|
||||
info.fFormatType = FormatType::kFloat;
|
||||
info.fBaseInternalFormat = GR_GL_LUMINANCE;
|
||||
info.fSizedInternalFormat = GR_GL_LUMINANCE16F;
|
||||
info.fInternalFormatForTexImage =
|
||||
texImageSupportsSizedInternalFormat ? GR_GL_LUMINANCE16F : GR_GL_LUMINANCE;
|
||||
info.fInternalFormatForRenderbuffer = GR_GL_LUMINANCE16F;
|
||||
info.fDefaultExternalFormat = GR_GL_LUMINANCE;
|
||||
info.fDefaultExternalType = halfFloatType;
|
||||
info.fTexSubImageZeroDataBpp = 2;
|
||||
|
||||
if (lum16FSupported) {
|
||||
info.fFlags = FormatInfo::kTexturable_Flag;
|
||||
|
||||
if (texStorageSupported &&
|
||||
!formatWorkarounds.fDisablePerFormatTextureStorageForCommandBufferES2) {
|
||||
info.fFlags |= FormatInfo::kCanUseTexStorage_Flag;
|
||||
info.fFlags |= FormatInfo::kUseTexStorage_Flag;
|
||||
info.fInternalFormatForTexImageOrStorage = GR_GL_LUMINANCE16F;
|
||||
} else {
|
||||
info.fInternalFormatForTexImageOrStorage =
|
||||
texImageSupportsSizedInternalFormat ? GR_GL_LUMINANCE16F : GR_GL_LUMINANCE;
|
||||
}
|
||||
|
||||
info.fColorTypeInfoCount = 1;
|
||||
@ -2198,12 +2237,10 @@ void GrGLCaps::initFormatTable(const GrGLContextInfo& ctxInfo, const GrGLInterfa
|
||||
{
|
||||
FormatInfo& info = this->getFormatInfo(GrGLFormat::kRGB8);
|
||||
info.fFormatType = FormatType::kNormalizedFixedPoint;
|
||||
info.fBaseInternalFormat = GR_GL_RGB;
|
||||
info.fSizedInternalFormat = GR_GL_RGB8;
|
||||
info.fInternalFormatForTexImage =
|
||||
texImageSupportsSizedInternalFormat ? GR_GL_RGB8 : GR_GL_RGB;
|
||||
info.fInternalFormatForRenderbuffer = GR_GL_RGB8;
|
||||
info.fDefaultExternalFormat = GR_GL_RGB;
|
||||
info.fDefaultExternalType = GR_GL_UNSIGNED_BYTE;
|
||||
info.fTexSubImageZeroDataBpp = 3;
|
||||
info.fFlags = FormatInfo::kTexturable_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
|
||||
@ -2224,7 +2261,11 @@ void GrGLCaps::initFormatTable(const GrGLContextInfo& ctxInfo, const GrGLInterfa
|
||||
info.fFlags |= msaaRenderFlags;
|
||||
}
|
||||
if (texStorageSupported) {
|
||||
info.fFlags |= FormatInfo::kCanUseTexStorage_Flag;
|
||||
info.fFlags |= FormatInfo::kUseTexStorage_Flag;
|
||||
info.fInternalFormatForTexImageOrStorage = GR_GL_RGB8;
|
||||
} else {
|
||||
info.fInternalFormatForTexImageOrStorage =
|
||||
texImageSupportsSizedInternalFormat ? GR_GL_RGB8 : GR_GL_RGB;
|
||||
}
|
||||
if (formatWorkarounds.fDisableRGB8ForMali400) {
|
||||
info.fFlags = 0;
|
||||
@ -2275,20 +2316,22 @@ void GrGLCaps::initFormatTable(const GrGLContextInfo& ctxInfo, const GrGLInterfa
|
||||
{
|
||||
FormatInfo& info = this->getFormatInfo(GrGLFormat::kRG8);
|
||||
info.fFormatType = FormatType::kNormalizedFixedPoint;
|
||||
info.fBaseInternalFormat = GR_GL_RG;
|
||||
info.fSizedInternalFormat = GR_GL_RG8;
|
||||
info.fInternalFormatForTexImage =
|
||||
texImageSupportsSizedInternalFormat ? GR_GL_RG8 : GR_GL_RG;
|
||||
info.fInternalFormatForRenderbuffer = GR_GL_RG8;
|
||||
info.fDefaultExternalFormat = GR_GL_RG;
|
||||
info.fDefaultExternalType = GR_GL_UNSIGNED_BYTE;
|
||||
info.fTexSubImageZeroDataBpp = 2;
|
||||
if (textureRedSupport) {
|
||||
info.fFlags |= FormatInfo::kTexturable_Flag | msaaRenderFlags;
|
||||
if (texStorageSupported &&
|
||||
!formatWorkarounds.fDisablePerFormatTextureStorageForCommandBufferES2) {
|
||||
info.fFlags |= FormatInfo::kCanUseTexStorage_Flag;
|
||||
info.fFlags |= FormatInfo::kUseTexStorage_Flag;
|
||||
info.fInternalFormatForTexImageOrStorage = GR_GL_RG8;
|
||||
}
|
||||
}
|
||||
|
||||
if (!(info.fFlags & FormatInfo::kUseTexStorage_Flag)) {
|
||||
info.fInternalFormatForTexImageOrStorage =
|
||||
texImageSupportsSizedInternalFormat ? GR_GL_RG8 : GR_GL_RG;
|
||||
}
|
||||
if (textureRedSupport) {
|
||||
info.fColorTypeInfoCount = 1;
|
||||
info.fColorTypeInfos.reset(new ColorTypeInfo[info.fColorTypeInfoCount]());
|
||||
@ -2330,12 +2373,10 @@ void GrGLCaps::initFormatTable(const GrGLContextInfo& ctxInfo, const GrGLInterfa
|
||||
{
|
||||
FormatInfo& info = this->getFormatInfo(GrGLFormat::kRGB10_A2);
|
||||
info.fFormatType = FormatType::kNormalizedFixedPoint;
|
||||
info.fBaseInternalFormat = GR_GL_RGBA;
|
||||
info.fSizedInternalFormat = GR_GL_RGB10_A2;
|
||||
info.fInternalFormatForTexImage =
|
||||
texImageSupportsSizedInternalFormat ? GR_GL_RGB10_A2 : GR_GL_RGBA;
|
||||
info.fInternalFormatForRenderbuffer = GR_GL_RGB10_A2;
|
||||
info.fDefaultExternalFormat = GR_GL_RGBA;
|
||||
info.fDefaultExternalType = GR_GL_UNSIGNED_INT_2_10_10_10_REV;
|
||||
info.fTexSubImageZeroDataBpp = 4;
|
||||
if (GR_IS_GR_GL(standard) ||
|
||||
(GR_IS_GR_GL_ES(standard) && version >= GR_GL_VER(3, 0))) {
|
||||
info.fFlags = FormatInfo::kTexturable_Flag | msaaRenderFlags;
|
||||
@ -2344,7 +2385,11 @@ void GrGLCaps::initFormatTable(const GrGLContextInfo& ctxInfo, const GrGLInterfa
|
||||
info.fFlags = FormatInfo::kTexturable_Flag;
|
||||
} // No WebGL support
|
||||
if (texStorageSupported) {
|
||||
info.fFlags |= FormatInfo::kCanUseTexStorage_Flag;
|
||||
info.fFlags |= FormatInfo::kUseTexStorage_Flag;
|
||||
info.fInternalFormatForTexImageOrStorage = GR_GL_RGB10_A2;
|
||||
} else {
|
||||
info.fInternalFormatForTexImageOrStorage =
|
||||
texImageSupportsSizedInternalFormat ? GR_GL_RGB10_A2 : GR_GL_RGBA;
|
||||
}
|
||||
|
||||
if (SkToBool(info.fFlags &FormatInfo::kTexturable_Flag)) {
|
||||
@ -2388,12 +2433,10 @@ void GrGLCaps::initFormatTable(const GrGLContextInfo& ctxInfo, const GrGLInterfa
|
||||
{
|
||||
FormatInfo& info = this->getFormatInfo(GrGLFormat::kRGBA4);
|
||||
info.fFormatType = FormatType::kNormalizedFixedPoint;
|
||||
info.fBaseInternalFormat = GR_GL_RGBA;
|
||||
info.fSizedInternalFormat = GR_GL_RGBA4;
|
||||
info.fInternalFormatForTexImage =
|
||||
texImageSupportsSizedInternalFormat ? GR_GL_RGBA4 : GR_GL_RGBA;
|
||||
info.fInternalFormatForRenderbuffer = GR_GL_RGBA4;
|
||||
info.fDefaultExternalFormat = GR_GL_RGBA;
|
||||
info.fDefaultExternalType = GR_GL_UNSIGNED_SHORT_4_4_4_4;
|
||||
info.fTexSubImageZeroDataBpp = 2;
|
||||
info.fFlags = FormatInfo::kTexturable_Flag;
|
||||
if (GR_IS_GR_GL(standard)) {
|
||||
if (version >= GR_GL_VER(4, 2)) {
|
||||
@ -2405,7 +2448,11 @@ void GrGLCaps::initFormatTable(const GrGLContextInfo& ctxInfo, const GrGLInterfa
|
||||
info.fFlags |= msaaRenderFlags;
|
||||
}
|
||||
if (texStorageSupported) {
|
||||
info.fFlags |= FormatInfo::kCanUseTexStorage_Flag;
|
||||
info.fFlags |= FormatInfo::kUseTexStorage_Flag;
|
||||
info.fInternalFormatForTexImageOrStorage = GR_GL_RGBA4;
|
||||
} else {
|
||||
info.fInternalFormatForTexImageOrStorage =
|
||||
texImageSupportsSizedInternalFormat ? GR_GL_RGBA4 : GR_GL_RGBA;
|
||||
}
|
||||
|
||||
info.fColorTypeInfoCount = 1;
|
||||
@ -2447,9 +2494,7 @@ void GrGLCaps::initFormatTable(const GrGLContextInfo& ctxInfo, const GrGLInterfa
|
||||
{
|
||||
FormatInfo& info = this->getFormatInfo(GrGLFormat::kRGBA32F);
|
||||
info.fFormatType = FormatType::kFloat;
|
||||
info.fBaseInternalFormat = GR_GL_RGBA;
|
||||
info.fSizedInternalFormat = GR_GL_RGBA32F;
|
||||
info.fInternalFormatForTexImage =
|
||||
info.fInternalFormatForTexImageOrStorage =
|
||||
texImageSupportsSizedInternalFormat ? GR_GL_RGBA32F : GR_GL_RGBA;
|
||||
info.fInternalFormatForRenderbuffer = GR_GL_RGBA32F;
|
||||
// We don't allow texturing or rendering to this format
|
||||
@ -2459,12 +2504,18 @@ void GrGLCaps::initFormatTable(const GrGLContextInfo& ctxInfo, const GrGLInterfa
|
||||
{
|
||||
FormatInfo& info = this->getFormatInfo(GrGLFormat::kSRGB8_ALPHA8);
|
||||
info.fFormatType = FormatType::kNormalizedFixedPoint;
|
||||
info.fBaseInternalFormat = GR_GL_RGBA;
|
||||
info.fSizedInternalFormat = GR_GL_SRGB8_ALPHA8;
|
||||
info.fInternalFormatForTexImage =
|
||||
texImageSupportsSizedInternalFormat ? GR_GL_SRGB8_ALPHA8 : GR_GL_SRGB_ALPHA;
|
||||
info.fInternalFormatForRenderbuffer = GR_GL_SRGB8_ALPHA8;
|
||||
// See comment below about ES 2.0 + GL_EXT_sRGB.
|
||||
if (GR_IS_GR_GL_ES(standard) && version == GR_GL_VER(2,0)) {
|
||||
// ES 2.0 requires that the external format matches the internal format.
|
||||
info.fDefaultExternalFormat = GR_GL_SRGB_ALPHA;
|
||||
} else {
|
||||
// On other GLs the expected external format is GL_RGBA, assuming this format
|
||||
// is supported at all.
|
||||
info.fDefaultExternalFormat = GR_GL_RGBA;
|
||||
}
|
||||
info.fDefaultExternalType = GR_GL_UNSIGNED_BYTE;
|
||||
info.fTexSubImageZeroDataBpp = 4;
|
||||
if (fSRGBSupport) {
|
||||
uint32_t srgbRenderFlags =
|
||||
formatWorkarounds.fDisableSRGBRenderWithMSAAForMacAMD ? nonMSAARenderFlags
|
||||
@ -2474,7 +2525,11 @@ void GrGLCaps::initFormatTable(const GrGLContextInfo& ctxInfo, const GrGLInterfa
|
||||
}
|
||||
if (texStorageSupported &&
|
||||
!formatWorkarounds.fDisablePerFormatTextureStorageForCommandBufferES2) {
|
||||
info.fFlags |= FormatInfo::kCanUseTexStorage_Flag;
|
||||
info.fFlags |= FormatInfo::kUseTexStorage_Flag;
|
||||
info.fInternalFormatForTexImageOrStorage = GR_GL_SRGB8_ALPHA8;
|
||||
} else {
|
||||
info.fInternalFormatForTexImageOrStorage =
|
||||
texImageSupportsSizedInternalFormat ? GR_GL_SRGB8_ALPHA8 : GR_GL_SRGB_ALPHA;
|
||||
}
|
||||
|
||||
if (fSRGBSupport) {
|
||||
@ -2499,7 +2554,7 @@ void GrGLCaps::initFormatTable(const GrGLContextInfo& ctxInfo, const GrGLInterfa
|
||||
// GL does not do srgb<->rgb conversions when transferring between cpu and gpu.
|
||||
// Thus, the external format is GL_RGBA. See below for note about ES2.0 and
|
||||
// glTex[Sub]Image.
|
||||
GrGLenum texImageFormat = GR_GL_RGBA;
|
||||
GrGLenum texImageExternalFormat = GR_GL_RGBA;
|
||||
|
||||
// OpenGL ES 2.0 + GL_EXT_sRGB allows GL_SRGB_ALPHA to be specified as the
|
||||
// <format> param to Tex(Sub)Image. ES 2.0 requires the <internalFormat> and
|
||||
@ -2507,12 +2562,12 @@ void GrGLCaps::initFormatTable(const GrGLContextInfo& ctxInfo, const GrGLInterfa
|
||||
// <format> param. On OpenGL and ES 3.0+ GL_SRGB_ALPHA does not work for the
|
||||
// <format> param to glTexImage.
|
||||
if (GR_IS_GR_GL_ES(standard) && version == GR_GL_VER(2,0)) {
|
||||
texImageFormat = GR_GL_SRGB_ALPHA;
|
||||
texImageExternalFormat = GR_GL_SRGB_ALPHA;
|
||||
}
|
||||
auto& ioFormat = ctInfo.fExternalIOFormats[ioIdx++];
|
||||
ioFormat.fColorType = GrColorType::kRGBA_8888_SRGB;
|
||||
ioFormat.fExternalType = GR_GL_UNSIGNED_BYTE;
|
||||
ioFormat.fExternalTexImageFormat = texImageFormat;
|
||||
ioFormat.fExternalTexImageFormat = texImageExternalFormat;
|
||||
ioFormat.fExternalReadFormat = GR_GL_RGBA;
|
||||
}
|
||||
}
|
||||
@ -2523,8 +2578,7 @@ void GrGLCaps::initFormatTable(const GrGLContextInfo& ctxInfo, const GrGLInterfa
|
||||
{
|
||||
FormatInfo& info = this->getFormatInfo(GrGLFormat::kCOMPRESSED_RGB8_ETC2);
|
||||
info.fFormatType = FormatType::kNormalizedFixedPoint;
|
||||
info.fBaseInternalFormat = GR_GL_RGB;
|
||||
info.fInternalFormatForTexImage = GR_GL_COMPRESSED_RGB8_ETC2;
|
||||
info.fInternalFormatForTexImageOrStorage = GR_GL_COMPRESSED_RGB8_ETC2;
|
||||
if (GR_IS_GR_GL(standard)) {
|
||||
if (version >= GR_GL_VER(4, 3) || ctxInfo.hasExtension("GL_ARB_ES3_compatibility")) {
|
||||
info.fFlags = FormatInfo::kTexturable_Flag;
|
||||
@ -2543,8 +2597,7 @@ void GrGLCaps::initFormatTable(const GrGLContextInfo& ctxInfo, const GrGLInterfa
|
||||
{
|
||||
FormatInfo& info = this->getFormatInfo(GrGLFormat::kCOMPRESSED_ETC1_RGB8);
|
||||
info.fFormatType = FormatType::kNormalizedFixedPoint;
|
||||
info.fBaseInternalFormat = GR_GL_RGB;
|
||||
info.fInternalFormatForTexImage = GR_GL_COMPRESSED_ETC1_RGB8;
|
||||
info.fInternalFormatForTexImageOrStorage = GR_GL_COMPRESSED_ETC1_RGB8;
|
||||
if (GR_IS_GR_GL_ES(standard)) {
|
||||
if (ctxInfo.hasExtension("GL_OES_compressed_ETC1_RGB8_texture")) {
|
||||
info.fFlags = FormatInfo::kTexturable_Flag;
|
||||
@ -2558,12 +2611,12 @@ void GrGLCaps::initFormatTable(const GrGLContextInfo& ctxInfo, const GrGLInterfa
|
||||
{
|
||||
FormatInfo& info = this->getFormatInfo(GrGLFormat::kR16);
|
||||
info.fFormatType = FormatType::kNormalizedFixedPoint;
|
||||
info.fBaseInternalFormat = GR_GL_RED;
|
||||
info.fSizedInternalFormat = GR_GL_R16;
|
||||
info.fInternalFormatForTexImage =
|
||||
info.fInternalFormatForTexImageOrStorage =
|
||||
texImageSupportsSizedInternalFormat ? GR_GL_R16 : GR_GL_RED;
|
||||
info.fInternalFormatForRenderbuffer = GR_GL_R16;
|
||||
info.fDefaultExternalFormat = GR_GL_RED;
|
||||
info.fDefaultExternalType = GR_GL_UNSIGNED_SHORT;
|
||||
info.fTexSubImageZeroDataBpp = 2;
|
||||
if (r16AndRG1616Supported) {
|
||||
info.fFlags = FormatInfo::kTexturable_Flag | msaaRenderFlags;
|
||||
}
|
||||
@ -2609,12 +2662,12 @@ void GrGLCaps::initFormatTable(const GrGLContextInfo& ctxInfo, const GrGLInterfa
|
||||
{
|
||||
FormatInfo& info = this->getFormatInfo(GrGLFormat::kRG16);
|
||||
info.fFormatType = FormatType::kNormalizedFixedPoint;
|
||||
info.fBaseInternalFormat = GR_GL_RG;
|
||||
info.fSizedInternalFormat = GR_GL_RG16;
|
||||
info.fInternalFormatForTexImage =
|
||||
info.fInternalFormatForTexImageOrStorage =
|
||||
texImageSupportsSizedInternalFormat ? GR_GL_RG16 : GR_GL_RG;
|
||||
info.fInternalFormatForRenderbuffer = GR_GL_RG16;
|
||||
info.fDefaultExternalFormat = GR_GL_RG;
|
||||
info.fDefaultExternalType = GR_GL_UNSIGNED_SHORT;
|
||||
info.fTexSubImageZeroDataBpp = 4;
|
||||
if (r16AndRG1616Supported) {
|
||||
info.fFlags = FormatInfo::kTexturable_Flag | msaaRenderFlags;
|
||||
}
|
||||
@ -2679,12 +2732,12 @@ void GrGLCaps::initFormatTable(const GrGLContextInfo& ctxInfo, const GrGLInterfa
|
||||
|
||||
FormatInfo& info = this->getFormatInfo(GrGLFormat::kRGBA16);
|
||||
info.fFormatType = FormatType::kNormalizedFixedPoint;
|
||||
info.fBaseInternalFormat = GR_GL_RGBA;
|
||||
info.fSizedInternalFormat = GR_GL_RGBA16;
|
||||
info.fInternalFormatForTexImage =
|
||||
info.fInternalFormatForTexImageOrStorage =
|
||||
texImageSupportsSizedInternalFormat ? GR_GL_RGBA16 : GR_GL_RGBA;
|
||||
info.fInternalFormatForRenderbuffer = GR_GL_RGBA16;
|
||||
info.fDefaultExternalFormat = GR_GL_RGBA;
|
||||
info.fDefaultExternalType = GR_GL_UNSIGNED_SHORT;
|
||||
info.fTexSubImageZeroDataBpp = 8;
|
||||
if (rgba16161616Supported) {
|
||||
info.fFlags = FormatInfo::kTexturable_Flag | msaaRenderFlags;
|
||||
}
|
||||
@ -2753,12 +2806,12 @@ void GrGLCaps::initFormatTable(const GrGLContextInfo& ctxInfo, const GrGLInterfa
|
||||
|
||||
FormatInfo& info = this->getFormatInfo(GrGLFormat::kRG16F);
|
||||
info.fFormatType = FormatType::kFloat;
|
||||
info.fBaseInternalFormat = GR_GL_RG;
|
||||
info.fSizedInternalFormat = GR_GL_RG16F;
|
||||
info.fInternalFormatForTexImage =
|
||||
info.fInternalFormatForTexImageOrStorage =
|
||||
texImageSupportsSizedInternalFormat ? GR_GL_RG16F : GR_GL_RG;
|
||||
info.fInternalFormatForRenderbuffer = GR_GL_RG16F;
|
||||
info.fDefaultExternalFormat = GR_GL_RG;
|
||||
info.fDefaultExternalType = halfFloatType;
|
||||
info.fTexSubImageZeroDataBpp = 4;
|
||||
if (rg16fTexturesSupported) {
|
||||
info.fFlags |= FormatInfo::kTexturable_Flag;
|
||||
}
|
||||
@ -3616,7 +3669,8 @@ bool GrGLCaps::onSurfaceSupportsWritePixels(const GrSurface* surface) const {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
} if (auto rt = surface->asRenderTarget()) {
|
||||
}
|
||||
if (auto rt = surface->asRenderTarget()) {
|
||||
if (fUseDrawInsteadOfAllRenderTargetWrites) {
|
||||
return false;
|
||||
}
|
||||
@ -3837,7 +3891,7 @@ bool GrGLCaps::isFormatCopyable(const GrBackendFormat& format) const {
|
||||
}
|
||||
|
||||
bool GrGLCaps::formatSupportsTexStorage(GrGLFormat format) const {
|
||||
return SkToBool(this->getFormatInfo(format).fFlags & FormatInfo::kCanUseTexStorage_Flag);
|
||||
return SkToBool(this->getFormatInfo(format).fFlags & FormatInfo::kUseTexStorage_Flag);
|
||||
}
|
||||
|
||||
static GrPixelConfig validate_sized_format(GrGLFormat format,
|
||||
@ -4010,12 +4064,12 @@ GrColorType GrGLCaps::getYUVAColorTypeFromBackendFormat(const GrBackendFormat& f
|
||||
|
||||
GrBackendFormat GrGLCaps::onGetDefaultBackendFormat(GrColorType ct,
|
||||
GrRenderable renderable) const {
|
||||
// TODO: make use of renderable.
|
||||
auto format = this->getFormatFromColorType(ct);
|
||||
if (format == GrGLFormat::kUnknown) {
|
||||
return GrBackendFormat();
|
||||
}
|
||||
// TODO: plumb 'renderable' into getSizedInternalFormat (or, at least, make use of it)
|
||||
return GrBackendFormat::MakeGL(this->getSizedInternalFormat(format), GR_GL_TEXTURE_2D);
|
||||
return GrBackendFormat::MakeGL(GrGLFormatToEnum(format), GR_GL_TEXTURE_2D);
|
||||
}
|
||||
|
||||
GrBackendFormat GrGLCaps::getBackendFormatFromCompressionType(
|
||||
@ -4027,8 +4081,6 @@ GrBackendFormat GrGLCaps::getBackendFormatFromCompressionType(
|
||||
SK_ABORT("Invalid compression type");
|
||||
}
|
||||
|
||||
bool GrGLCaps::canClearTextureOnCreation() const { return fClearTextureSupport; }
|
||||
|
||||
GrSwizzle GrGLCaps::getTextureSwizzle(const GrBackendFormat& format, GrColorType colorType) const {
|
||||
const auto& info = this->getFormatInfo(format.asGLFormat());
|
||||
for (int i = 0; i < info.fColorTypeInfoCount; ++i) {
|
||||
|
@ -142,13 +142,36 @@ public:
|
||||
return fColorTypeToFormatTable[idx];
|
||||
}
|
||||
|
||||
GrGLenum formatSizedInternalFormat(GrGLFormat format) const {
|
||||
return this->getFormatInfo(format).fSizedInternalFormat;
|
||||
/**
|
||||
* Gets the internal format to use with glTexImage...() and glTexStorage...(). May be sized or
|
||||
* base depending upon the GL. Not applicable to compressed textures.
|
||||
*/
|
||||
GrGLenum getTexImageOrStorageInternalFormat(GrGLFormat format) const {
|
||||
return this->getFormatInfo(format).fInternalFormatForTexImageOrStorage;
|
||||
}
|
||||
|
||||
void getTexImageFormats(GrGLFormat surfaceFormat, GrColorType surfaceColorType,
|
||||
GrColorType memoryColorType, GrGLenum* internalFormat,
|
||||
GrGLenum* externalFormat, GrGLenum* externalType) const;
|
||||
/**
|
||||
* Gets the external format and type to pass to glTexImage2D with nullptr to create an
|
||||
* uninitialized texture. See getTexImageOrStorageInternalFormat() for the internal format.
|
||||
*/
|
||||
void getTexImageExternalFormatAndType(GrGLFormat surfaceFormat, GrGLenum* externalFormat,
|
||||
GrGLenum* externalType) const;
|
||||
|
||||
/**
|
||||
* Given a src data color type and a color type interpretation for a texture of a given format
|
||||
* this provides the external GL format and type to use with glTexSubImage2d. The color types
|
||||
* should originate from supportedWritePixelsColorType().
|
||||
*/
|
||||
void getTexSubImageExternalFormatAndType(GrGLFormat surfaceFormat, GrColorType surfaceColorType,
|
||||
GrColorType memoryColorType, GrGLenum* externalFormat,
|
||||
GrGLenum* externalType) const;
|
||||
|
||||
/**
|
||||
* Gets the external format, type, and bytes per pixel to use when uploading zeros via
|
||||
* glTexSubImage...() to clear the texture at creation.
|
||||
*/
|
||||
void getTexSubImageZeroFormatTypeAndBpp(GrGLFormat format, GrGLenum* externalFormat,
|
||||
GrGLenum* externalType, size_t* bpp) const;
|
||||
|
||||
void getReadPixelsFormat(GrGLFormat surfaceFormat, GrColorType surfaceColorType,
|
||||
GrColorType memoryColorType, GrGLenum* externalFormat,
|
||||
@ -165,14 +188,6 @@ public:
|
||||
|
||||
bool formatSupportsTexStorage(GrGLFormat) const;
|
||||
|
||||
/**
|
||||
* Gets the internal format to use with glTexImage...() and glTexStorage...(). May be sized or
|
||||
* base depending upon the GL. Not applicable to compressed textures.
|
||||
*/
|
||||
GrGLenum getTexImageInternalFormat(GrGLFormat format) const {
|
||||
return this->getFormatInfo(format).fInternalFormatForTexImage;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the internal format to use with glRenderbufferStorageMultisample...(). May be sized or
|
||||
* base depending upon the GL. Not applicable to compressed textures.
|
||||
@ -181,14 +196,6 @@ public:
|
||||
return this->getFormatInfo(format).fInternalFormatForRenderbuffer;
|
||||
}
|
||||
|
||||
GrGLenum getSizedInternalFormat(GrGLFormat format) const {
|
||||
return this->getFormatInfo(format).fSizedInternalFormat;
|
||||
}
|
||||
|
||||
GrGLenum getBaseInternalFormat(GrGLFormat format) const {
|
||||
return this->getFormatInfo(format).fBaseInternalFormat;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the default external type to use with glTex[Sub]Image... when the data pointer is null.
|
||||
*/
|
||||
@ -404,8 +411,6 @@ public:
|
||||
|
||||
GrBackendFormat getBackendFormatFromCompressionType(SkImage::CompressionType) const override;
|
||||
|
||||
bool canClearTextureOnCreation() const override;
|
||||
|
||||
GrSwizzle getTextureSwizzle(const GrBackendFormat&, GrColorType) const override;
|
||||
GrSwizzle getOutputSwizzle(const GrBackendFormat&, GrColorType) const override;
|
||||
|
||||
@ -618,34 +623,30 @@ private:
|
||||
still attach it to a FBO for blitting or reading pixels. */
|
||||
kFBOColorAttachment_Flag = 0x2,
|
||||
kFBOColorAttachmentWithMSAA_Flag = 0x4,
|
||||
kCanUseTexStorage_Flag = 0x8,
|
||||
kUseTexStorage_Flag = 0x8,
|
||||
};
|
||||
uint32_t fFlags = 0;
|
||||
|
||||
FormatType fFormatType = FormatType::kUnknown;
|
||||
|
||||
// Both compressed and uncompressed formats have base internal formats.
|
||||
GrGLenum fBaseInternalFormat = 0;
|
||||
|
||||
// Not defined for compressed formats.
|
||||
GrGLenum fSizedInternalFormat = 0;
|
||||
|
||||
// Not defined for uncompressed formats. Passed to glCompressedTexImage...
|
||||
GrGLenum fCompressedInternalFormat = 0;
|
||||
|
||||
// Value to uses as the "internalformat" argument to glTexImage and glCompressedTexImage...
|
||||
// Usually one of fBaseInternalFormat or fSizedInternalFormat but may vary depending on the
|
||||
// particular format, GL version, extensions.
|
||||
GrGLenum fInternalFormatForTexImage = 0;
|
||||
// Value to uses as the "internalformat" argument to glTexImage or glTexStorage. It is
|
||||
// initialized in coordination with the presence/absence of the kUseTexStorage flag. In
|
||||
// other words, it is only guaranteed to be compatible with glTexImage if the flag is not
|
||||
// set and or with glTexStorage if the flag is set.
|
||||
GrGLenum fInternalFormatForTexImageOrStorage = 0;
|
||||
|
||||
// Value to uses as the "internalformat" argument to glRenderbufferStorageMultisample...
|
||||
// Usually one of fBaseInternalFormat or fSizedInternalFormat but may vary depending on the
|
||||
// particular format, GL version, extensions.
|
||||
GrGLenum fInternalFormatForRenderbuffer = 0;
|
||||
|
||||
// Default value to use along with fBaseInternalFormat for functions such as glTexImage2D
|
||||
// when not input providing data (passing nullptr). Not defined for compressed formats.
|
||||
// Default values to use along with fInternalFormatForTexImageOrStorage for function
|
||||
// glTexImage2D when not input providing data (passing nullptr). Not defined for compressed
|
||||
// formats. Also used to upload zeros to initially clear a texture.
|
||||
GrGLenum fDefaultExternalFormat = 0;
|
||||
GrGLenum fDefaultExternalType = 0;
|
||||
GrGLenum fTexSubImageZeroDataBpp = 0;
|
||||
|
||||
enum {
|
||||
// This indicates that a stencil format has not yet been determined for the config.
|
||||
|
@ -719,22 +719,20 @@ sk_sp<GrTexture> GrGLGpu::onWrapRenderableBackendTexture(const GrBackendTexture&
|
||||
GrColorType colorType,
|
||||
GrWrapOwnership ownership,
|
||||
GrWrapCacheable cacheable) {
|
||||
const GrGLCaps& caps = this->glCaps();
|
||||
|
||||
GrGLTexture::Desc desc;
|
||||
if (!check_backend_texture(backendTex, colorType, this->glCaps(), &desc)) {
|
||||
return nullptr;
|
||||
}
|
||||
SkASSERT(caps.isFormatRenderable(desc.fFormat, sampleCnt));
|
||||
SkASSERT(caps.isFormatTexturable(desc.fFormat));
|
||||
|
||||
// We don't support rendering to a EXTERNAL texture.
|
||||
if (GR_GL_TEXTURE_EXTERNAL == desc.fTarget) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const GrGLCaps& caps = this->glCaps();
|
||||
|
||||
if (!caps.isFormatRenderable(desc.fFormat, sampleCnt)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (kBorrow_GrWrapOwnership == ownership) {
|
||||
desc.fOwnership = GrBackendObjectOwnership::kBorrowed;
|
||||
} else {
|
||||
@ -846,8 +844,8 @@ bool GrGLGpu::onWritePixels(GrSurface* surface, int left, int top, int width, in
|
||||
|
||||
SkASSERT(!GrGLFormatIsCompressed(glTex->format()));
|
||||
return this->uploadTexData(glTex->format(), surfaceColorType, glTex->width(), glTex->height(),
|
||||
glTex->target(), kWrite_UploadType, left, top,width,
|
||||
height, srcColorType, texels, mipLevelCount);
|
||||
glTex->target(), left, top, width, height, srcColorType, texels,
|
||||
mipLevelCount);
|
||||
}
|
||||
|
||||
bool GrGLGpu::onTransferPixelsTo(GrTexture* texture, int left, int top, int width, int height,
|
||||
@ -896,13 +894,11 @@ bool GrGLGpu::onTransferPixelsTo(GrTexture* texture, int left, int top, int widt
|
||||
}
|
||||
|
||||
GrGLFormat textureFormat = glTex->format();
|
||||
// Internal format comes from the texture desc.
|
||||
GrGLenum internalFormat;
|
||||
// External format and type come from the upload data.
|
||||
GrGLenum externalFormat = 0;
|
||||
GrGLenum externalType = 0;
|
||||
this->glCaps().getTexImageFormats(textureFormat, textureColorType, bufferColorType,
|
||||
&internalFormat, &externalFormat, &externalType);
|
||||
this->glCaps().getTexSubImageExternalFormatAndType(
|
||||
textureFormat, textureColorType, bufferColorType, &externalFormat, &externalType);
|
||||
if (!externalFormat || !externalType) {
|
||||
return false;
|
||||
}
|
||||
@ -933,178 +929,6 @@ bool GrGLGpu::onTransferPixelsFrom(GrSurface* surface, int left, int top, int wi
|
||||
dstColorType, offsetAsPtr, width);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates storage space for the texture and fills it with texels.
|
||||
*
|
||||
* @param format The format of the texture.
|
||||
* @param interface The GL interface in use.
|
||||
* @param caps The capabilities of the GL device.
|
||||
* @param target Which bound texture to target (GR_GL_TEXTURE_2D, e.g.)
|
||||
* @param internalFormat The data format used for the internal storage of the texture. May be sized.
|
||||
* @param internalFormatForTexStorage The data format used for the TexStorage API. Must be sized.
|
||||
* @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.
|
||||
* @param dataBpp The bytes per pixel of the data in texels.
|
||||
* @param texels The texel data of the texture being created.
|
||||
* @param mipLevelCount Number of mipmap levels
|
||||
* @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_texture(GrGLFormat format,
|
||||
const GrGLInterface& interface,
|
||||
const GrGLCaps& caps,
|
||||
GrGLenum target,
|
||||
GrGLenum internalFormat,
|
||||
GrGLenum internalFormatForTexStorage,
|
||||
GrGLenum externalFormat,
|
||||
GrGLenum externalType,
|
||||
size_t dataBpp,
|
||||
const GrMipLevel texels[],
|
||||
int mipLevelCount,
|
||||
int baseWidth,
|
||||
int baseHeight,
|
||||
bool* changedUnpackRowLength,
|
||||
GrMipMapsStatus* mipMapsStatus) {
|
||||
CLEAR_ERROR_BEFORE_ALLOC(&interface);
|
||||
|
||||
if (caps.formatSupportsTexStorage(format)) {
|
||||
// We never resize or change formats of textures.
|
||||
GL_ALLOC_CALL(&interface,
|
||||
TexStorage2D(target, SkTMax(mipLevelCount, 1), internalFormatForTexStorage,
|
||||
baseWidth, baseHeight));
|
||||
GrGLenum error = CHECK_ALLOC_ERROR(&interface);
|
||||
if (error != GR_GL_NO_ERROR) {
|
||||
return false;
|
||||
} else {
|
||||
for (int currentMipLevel = 0; currentMipLevel < mipLevelCount; currentMipLevel++) {
|
||||
const void* currentMipData = texels[currentMipLevel].fPixels;
|
||||
if (currentMipData == nullptr) {
|
||||
if (mipMapsStatus) {
|
||||
*mipMapsStatus = GrMipMapsStatus::kDirty;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
int twoToTheMipLevel = 1 << currentMipLevel;
|
||||
const int currentWidth = SkTMax(1, baseWidth / twoToTheMipLevel);
|
||||
const int currentHeight = SkTMax(1, baseHeight / twoToTheMipLevel);
|
||||
|
||||
if (texels[currentMipLevel].fPixels) {
|
||||
const size_t trimRowBytes = currentWidth * dataBpp;
|
||||
const size_t rowBytes = texels[currentMipLevel].fRowBytes;
|
||||
if (rowBytes != trimRowBytes) {
|
||||
SkASSERT(caps.writePixelsRowBytesSupport());
|
||||
GrGLint rowLength = static_cast<GrGLint>(rowBytes / dataBpp);
|
||||
GR_GL_CALL(&interface, PixelStorei(GR_GL_UNPACK_ROW_LENGTH, rowLength));
|
||||
*changedUnpackRowLength = true;
|
||||
} else if (*changedUnpackRowLength) {
|
||||
SkASSERT(caps.writePixelsRowBytesSupport());
|
||||
GR_GL_CALL(&interface, PixelStorei(GR_GL_UNPACK_ROW_LENGTH, 0));
|
||||
*changedUnpackRowLength = false;
|
||||
}
|
||||
}
|
||||
|
||||
GR_GL_CALL(&interface,
|
||||
TexSubImage2D(target,
|
||||
currentMipLevel,
|
||||
0, // left
|
||||
0, // top
|
||||
currentWidth,
|
||||
currentHeight,
|
||||
externalFormat, externalType,
|
||||
currentMipData));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
if (!mipLevelCount) {
|
||||
GL_ALLOC_CALL(&interface,
|
||||
TexImage2D(target,
|
||||
0,
|
||||
internalFormat,
|
||||
baseWidth,
|
||||
baseHeight,
|
||||
0, // border
|
||||
externalFormat, externalType,
|
||||
nullptr));
|
||||
GrGLenum error = CHECK_ALLOC_ERROR(&interface);
|
||||
if (error != GR_GL_NO_ERROR) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
for (int currentMipLevel = 0; currentMipLevel < mipLevelCount; currentMipLevel++) {
|
||||
int twoToTheMipLevel = 1 << currentMipLevel;
|
||||
const int currentWidth = SkTMax(1, baseWidth / twoToTheMipLevel);
|
||||
const int currentHeight = SkTMax(1, baseHeight / twoToTheMipLevel);
|
||||
|
||||
const void* currentMipData = texels[currentMipLevel].fPixels;
|
||||
if (currentMipData) {
|
||||
const size_t trimRowBytes = currentWidth * dataBpp;
|
||||
const size_t rowBytes = texels[currentMipLevel].fRowBytes;
|
||||
if (rowBytes != trimRowBytes) {
|
||||
SkASSERT(caps.writePixelsRowBytesSupport());
|
||||
GrGLint rowLength = static_cast<GrGLint>(rowBytes / dataBpp);
|
||||
GR_GL_CALL(&interface, PixelStorei(GR_GL_UNPACK_ROW_LENGTH, rowLength));
|
||||
*changedUnpackRowLength = true;
|
||||
} else if (*changedUnpackRowLength) {
|
||||
SkASSERT(caps.writePixelsRowBytesSupport());
|
||||
GR_GL_CALL(&interface, PixelStorei(GR_GL_UNPACK_ROW_LENGTH, 0));
|
||||
*changedUnpackRowLength = false;
|
||||
}
|
||||
} else if (mipMapsStatus) {
|
||||
*mipMapsStatus = GrMipMapsStatus::kDirty;
|
||||
}
|
||||
|
||||
// We are considering modifying the interface to GrGpu to no longer allow data to
|
||||
// be provided when creating a texture. To test whether that is feasible for
|
||||
// performance on ES2 GPUs without tex storage we're calling glTexImage2D and then
|
||||
// glTexSubImage2D and hoping we don't get any performance regressions.
|
||||
GL_ALLOC_CALL(&interface,
|
||||
TexImage2D(target,
|
||||
currentMipLevel,
|
||||
internalFormat,
|
||||
currentWidth,
|
||||
currentHeight,
|
||||
0, // border
|
||||
externalFormat, externalType,
|
||||
nullptr));
|
||||
if (currentMipData) {
|
||||
GR_GL_CALL(&interface,
|
||||
TexSubImage2D(target,
|
||||
currentMipLevel,
|
||||
0, 0,
|
||||
currentWidth,
|
||||
currentHeight,
|
||||
externalFormat,
|
||||
externalType,
|
||||
currentMipData));
|
||||
}
|
||||
GrGLenum error = CHECK_ALLOC_ERROR(&interface);
|
||||
if (error != GR_GL_NO_ERROR) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* After a texture is created, any state which was altered during its creation
|
||||
* needs to be restored.
|
||||
*
|
||||
* @param interface The GL interface to use.
|
||||
* @param caps The capabilities of the GL device.
|
||||
* @param restoreGLRowLength Should the row length unpacking be restored?
|
||||
* @param glFlipY Did GL flip the texture vertically?
|
||||
*/
|
||||
static void restore_pixelstore_state(const GrGLInterface& interface, const GrGLCaps& caps,
|
||||
bool restoreGLRowLength) {
|
||||
if (restoreGLRowLength) {
|
||||
SkASSERT(caps.writePixelsRowBytesSupport());
|
||||
GR_GL_CALL(&interface, PixelStorei(GR_GL_UNPACK_ROW_LENGTH, 0));
|
||||
}
|
||||
}
|
||||
|
||||
void GrGLGpu::unbindCpuToGpuXferBuffer() {
|
||||
auto* xferBufferState = this->hwBufferState(GrGpuBufferType::kXferCpuToGpu);
|
||||
if (!xferBufferState->fBoundBufferUniqueID.isInvalid()) {
|
||||
@ -1113,11 +937,10 @@ void GrGLGpu::unbindCpuToGpuXferBuffer() {
|
||||
}
|
||||
}
|
||||
|
||||
bool GrGLGpu::uploadTexData(GrGLFormat textureFormat, GrColorType textureColorType,
|
||||
int texWidth, int texHeight, GrGLenum target, UploadType uploadType,
|
||||
int left, int top, int width, int height, GrColorType srcColorType,
|
||||
const GrMipLevel texels[],int mipLevelCount,
|
||||
GrMipMapsStatus* mipMapsStatus) {
|
||||
bool GrGLGpu::uploadTexData(GrGLFormat textureFormat, GrColorType textureColorType, int texWidth,
|
||||
int texHeight, GrGLenum target, int left, int top, int width,
|
||||
int height, GrColorType srcColorType, const GrMipLevel texels[],
|
||||
int mipLevelCount, GrMipMapsStatus* mipMapsStatus) {
|
||||
// If we're uploading compressed data then we should be using uploadCompressedTexData
|
||||
SkASSERT(!GrGLFormatIsCompressed(textureFormat));
|
||||
|
||||
@ -1141,19 +964,15 @@ bool GrGLGpu::uploadTexData(GrGLFormat textureFormat, GrColorType textureColorTy
|
||||
return false;
|
||||
}
|
||||
|
||||
// Internal format comes from the texture desc.
|
||||
GrGLenum internalFormat;
|
||||
// External format and type come from the upload data.
|
||||
GrGLenum externalFormat;
|
||||
GrGLenum externalType;
|
||||
this->glCaps().getTexImageFormats(textureFormat, textureColorType, srcColorType,
|
||||
&internalFormat, &externalFormat, &externalType);
|
||||
this->glCaps().getTexSubImageExternalFormatAndType(
|
||||
textureFormat, textureColorType, srcColorType, &externalFormat, &externalType);
|
||||
if (!externalFormat || !externalType) {
|
||||
return false;
|
||||
}
|
||||
|
||||
GrGLenum internalFormatForTexStorage = this->glCaps().getSizedInternalFormat(textureFormat);
|
||||
|
||||
/*
|
||||
* Check whether to allocate a temporary buffer for flipping y or
|
||||
* because our srcData has extra bytes past each row. If so, we need
|
||||
@ -1162,61 +981,40 @@ bool GrGLGpu::uploadTexData(GrGLFormat textureFormat, GrColorType textureColorTy
|
||||
*/
|
||||
bool restoreGLRowLength = false;
|
||||
|
||||
// in case we need a temporary, trimmed copy of the src pixels
|
||||
SkAutoSMalloc<128 * 128> tempStorage;
|
||||
|
||||
if (mipMapsStatus) {
|
||||
*mipMapsStatus = (mipLevelCount > 1) ?
|
||||
GrMipMapsStatus::kValid : GrMipMapsStatus::kNotAllocated;
|
||||
}
|
||||
|
||||
if (mipLevelCount) {
|
||||
GR_GL_CALL(interface, PixelStorei(GR_GL_UNPACK_ALIGNMENT, 1));
|
||||
}
|
||||
GR_GL_CALL(interface, PixelStorei(GR_GL_UNPACK_ALIGNMENT, 1));
|
||||
|
||||
bool succeeded = true;
|
||||
if (kNewTexture_UploadType == uploadType) {
|
||||
if (0 == left && 0 == top && texWidth == width && texHeight == height) {
|
||||
succeeded = allocate_and_populate_texture(
|
||||
textureFormat, *interface, caps, target, internalFormat,
|
||||
internalFormatForTexStorage, externalFormat, externalType, bpp, texels,
|
||||
mipLevelCount, width, height, &restoreGLRowLength, mipMapsStatus);
|
||||
} else {
|
||||
succeeded = false;
|
||||
}
|
||||
} else {
|
||||
for (int currentMipLevel = 0; currentMipLevel < mipLevelCount; currentMipLevel++) {
|
||||
if (!texels[currentMipLevel].fPixels) {
|
||||
if (mipMapsStatus) {
|
||||
*mipMapsStatus = GrMipMapsStatus::kDirty;
|
||||
}
|
||||
continue;
|
||||
for (int currentMipLevel = 0; currentMipLevel < mipLevelCount; currentMipLevel++) {
|
||||
if (!texels[currentMipLevel].fPixels) {
|
||||
if (mipMapsStatus) {
|
||||
*mipMapsStatus = GrMipMapsStatus::kDirty;
|
||||
}
|
||||
int twoToTheMipLevel = 1 << currentMipLevel;
|
||||
const int currentWidth = SkTMax(1, width / twoToTheMipLevel);
|
||||
const int currentHeight = SkTMax(1, height / twoToTheMipLevel);
|
||||
const size_t trimRowBytes = currentWidth * bpp;
|
||||
const size_t rowBytes = texels[currentMipLevel].fRowBytes;
|
||||
|
||||
if (caps.writePixelsRowBytesSupport() && rowBytes != trimRowBytes) {
|
||||
GrGLint rowLength = static_cast<GrGLint>(rowBytes / bpp);
|
||||
GR_GL_CALL(interface, PixelStorei(GR_GL_UNPACK_ROW_LENGTH, rowLength));
|
||||
restoreGLRowLength = true;
|
||||
}
|
||||
|
||||
GL_CALL(TexSubImage2D(target,
|
||||
currentMipLevel,
|
||||
left, top,
|
||||
currentWidth,
|
||||
currentHeight,
|
||||
externalFormat, externalType,
|
||||
texels[currentMipLevel].fPixels));
|
||||
continue;
|
||||
}
|
||||
int twoToTheMipLevel = 1 << currentMipLevel;
|
||||
const int currentWidth = SkTMax(1, width / twoToTheMipLevel);
|
||||
const int currentHeight = SkTMax(1, height / twoToTheMipLevel);
|
||||
const size_t trimRowBytes = currentWidth * bpp;
|
||||
const size_t rowBytes = texels[currentMipLevel].fRowBytes;
|
||||
|
||||
if (caps.writePixelsRowBytesSupport() && (rowBytes != trimRowBytes || restoreGLRowLength)) {
|
||||
GrGLint rowLength = static_cast<GrGLint>(rowBytes / bpp);
|
||||
GR_GL_CALL(interface, PixelStorei(GR_GL_UNPACK_ROW_LENGTH, rowLength));
|
||||
restoreGLRowLength = true;
|
||||
}
|
||||
|
||||
GL_CALL(TexSubImage2D(target, currentMipLevel, left, top, currentWidth, currentHeight,
|
||||
externalFormat, externalType, texels[currentMipLevel].fPixels));
|
||||
}
|
||||
|
||||
restore_pixelstore_state(*interface, caps, restoreGLRowLength);
|
||||
|
||||
return succeeded;
|
||||
if (restoreGLRowLength) {
|
||||
SkASSERT(caps.writePixelsRowBytesSupport());
|
||||
GL_CALL(PixelStorei(GR_GL_UNPACK_ROW_LENGTH, 0));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool GrGLGpu::uploadCompressedTexData(GrGLFormat format,
|
||||
@ -1228,7 +1026,7 @@ bool GrGLGpu::uploadCompressedTexData(GrGLFormat format,
|
||||
const GrGLCaps& caps = this->glCaps();
|
||||
|
||||
// We only need the internal format for compressed 2D textures.
|
||||
GrGLenum internalFormat = caps.getTexImageInternalFormat(format);
|
||||
GrGLenum internalFormat = caps.getTexImageOrStorageInternalFormat(format);
|
||||
if (!internalFormat) {
|
||||
return 0;
|
||||
}
|
||||
@ -1427,16 +1225,17 @@ sk_sp<GrTexture> GrGLGpu::onCreateTexture(const GrSurfaceDesc& desc,
|
||||
int renderTargetSampleCnt,
|
||||
SkBudgeted budgeted,
|
||||
GrProtected isProtected,
|
||||
const GrMipLevel texels[],
|
||||
int mipLevelCount) {
|
||||
int mipLevelCount,
|
||||
uint32_t levelClearMask) {
|
||||
// We don't support protected textures in GL.
|
||||
if (isProtected == GrProtected::kYes) {
|
||||
return nullptr;
|
||||
}
|
||||
SkASSERT(GrGLCaps::kNone_MSFBOType != this->glCaps().msFBOType() || renderTargetSampleCnt == 1);
|
||||
|
||||
|
||||
GrMipMapsStatus mipMapsStatus;
|
||||
SkASSERT(mipLevelCount > 0);
|
||||
GrMipMapsStatus mipMapsStatus =
|
||||
mipLevelCount > 1 ? GrMipMapsStatus::kDirty : GrMipMapsStatus::kNotAllocated;
|
||||
GrGLTextureParameters::SamplerOverriddenState initialState;
|
||||
GrGLTexture::Desc texDesc;
|
||||
texDesc.fSize = {desc.fWidth, desc.fHeight};
|
||||
@ -1447,18 +1246,8 @@ sk_sp<GrTexture> GrGLGpu::onCreateTexture(const GrSurfaceDesc& desc,
|
||||
SkASSERT(texDesc.fFormat != GrGLFormat::kUnknown);
|
||||
SkASSERT(!GrGLFormatIsCompressed(texDesc.fFormat));
|
||||
|
||||
// TODO: Take these as parameters.
|
||||
auto textureColorType = GrPixelConfigToColorType(desc.fConfig);
|
||||
auto srcColorType = GrPixelConfigToColorType(desc.fConfig);
|
||||
texDesc.fID = this->createTexture2D({desc.fWidth, desc.fHeight},
|
||||
texDesc.fFormat,
|
||||
renderable,
|
||||
&initialState,
|
||||
textureColorType,
|
||||
srcColorType,
|
||||
texels,
|
||||
mipLevelCount,
|
||||
&mipMapsStatus);
|
||||
texDesc.fID = this->createTexture2D({desc.fWidth, desc.fHeight}, texDesc.fFormat, renderable,
|
||||
&initialState, mipLevelCount);
|
||||
|
||||
if (!texDesc.fID) {
|
||||
return return_null_texture();
|
||||
@ -1483,16 +1272,49 @@ sk_sp<GrTexture> GrGLGpu::onCreateTexture(const GrSurfaceDesc& desc,
|
||||
// The non-sampler params are still at their default values.
|
||||
tex->parameters()->set(&initialState, GrGLTextureParameters::NonsamplerState(),
|
||||
fResetTimestampForTextureParameters);
|
||||
bool clearLevelsWithoutData =
|
||||
this->caps()->shouldInitializeTextures() && this->glCaps().clearTextureSupport();
|
||||
|
||||
if (clearLevelsWithoutData) {
|
||||
static constexpr uint32_t kZero = 0;
|
||||
int levelCnt = SkTMax(1, tex->texturePriv().maxMipMapLevel());
|
||||
for (int i = 0; i < levelCnt; ++i) {
|
||||
if (i >= mipLevelCount || !texels[i].fPixels) {
|
||||
GL_CALL(ClearTexImage(tex->textureID(), i, GR_GL_RGBA, GR_GL_UNSIGNED_BYTE,
|
||||
&kZero));
|
||||
if (levelClearMask) {
|
||||
GrGLenum externalFormat, externalType;
|
||||
size_t bpp;
|
||||
this->glCaps().getTexSubImageZeroFormatTypeAndBpp(texDesc.fFormat, &externalFormat,
|
||||
&externalType, &bpp);
|
||||
if (this->glCaps().clearTextureSupport()) {
|
||||
for (int i = 0; i < mipLevelCount; ++i) {
|
||||
if (levelClearMask & (1U << i)) {
|
||||
GL_CALL(ClearTexImage(tex->textureID(), i, externalFormat, externalType,
|
||||
nullptr));
|
||||
}
|
||||
}
|
||||
} else if (this->glCaps().canFormatBeFBOColorAttachment(format.asGLFormat()) &&
|
||||
!this->glCaps().performColorClearsAsDraws()) {
|
||||
this->disableScissor();
|
||||
this->disableWindowRectangles();
|
||||
this->flushColorWrite(true);
|
||||
this->flushClearColor(0, 0, 0, 0);
|
||||
for (int i = 0; i < mipLevelCount; ++i) {
|
||||
if (levelClearMask & (1U << i)) {
|
||||
this->bindSurfaceFBOForPixelOps(tex.get(), i, GR_GL_FRAMEBUFFER,
|
||||
kDst_TempFBOTarget);
|
||||
GL_CALL(Clear(GR_GL_COLOR_BUFFER_BIT));
|
||||
this->unbindSurfaceFBOForPixelOps(tex.get(), i, GR_GL_FRAMEBUFFER);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
std::unique_ptr<char[]> zeros;
|
||||
GL_CALL(PixelStorei(GR_GL_UNPACK_ALIGNMENT, 1));
|
||||
for (int i = 0; i < mipLevelCount; ++i) {
|
||||
if (levelClearMask & (1U << i)) {
|
||||
int levelWidth = SkTMax(1, texDesc.fSize.width() >> i);
|
||||
int levelHeight = SkTMax(1, texDesc.fSize.height() >> i);
|
||||
// Levels only get smaller as we proceed. Once we create a zeros use it for all
|
||||
// smaller levels that need clearing.
|
||||
if (!zeros) {
|
||||
size_t size = levelWidth * levelHeight * bpp;
|
||||
zeros.reset(new char[size]());
|
||||
}
|
||||
this->bindTextureToScratchUnit(GR_GL_TEXTURE_2D, tex->textureID());
|
||||
GL_CALL(TexSubImage2D(GR_GL_TEXTURE_2D, i, 0, 0, levelWidth, levelHeight,
|
||||
externalFormat, externalType, zeros.get()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1556,46 +1378,11 @@ int GrGLGpu::getCompatibleStencilIndex(GrGLFormat format) {
|
||||
// Default to unsupported, set this if we find a stencil format that works.
|
||||
int firstWorkingStencilFormatIndex = -1;
|
||||
|
||||
// Create color texture
|
||||
GrGLuint colorID = 0;
|
||||
GL_CALL(GenTextures(1, &colorID));
|
||||
this->bindTextureToScratchUnit(GR_GL_TEXTURE_2D, colorID);
|
||||
GL_CALL(TexParameteri(GR_GL_TEXTURE_2D,
|
||||
GR_GL_TEXTURE_MAG_FILTER,
|
||||
GR_GL_NEAREST));
|
||||
GL_CALL(TexParameteri(GR_GL_TEXTURE_2D,
|
||||
GR_GL_TEXTURE_MIN_FILTER,
|
||||
GR_GL_NEAREST));
|
||||
GL_CALL(TexParameteri(GR_GL_TEXTURE_2D,
|
||||
GR_GL_TEXTURE_WRAP_S,
|
||||
GR_GL_CLAMP_TO_EDGE));
|
||||
GL_CALL(TexParameteri(GR_GL_TEXTURE_2D,
|
||||
GR_GL_TEXTURE_WRAP_T,
|
||||
GR_GL_CLAMP_TO_EDGE));
|
||||
|
||||
GrGLenum internalFormat = this->glCaps().getTexImageInternalFormat(format);
|
||||
GrGLenum externalFormat = this->glCaps().getBaseInternalFormat(format);
|
||||
GrGLenum externalType = this->glCaps().getFormatDefaultExternalType(format);
|
||||
if (!internalFormat || !externalFormat || !externalType) {
|
||||
GrGLuint colorID =
|
||||
this->createTexture2D({kSize, kSize}, format, GrRenderable::kYes, nullptr, 1);
|
||||
if (!colorID) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
this->unbindCpuToGpuXferBuffer();
|
||||
CLEAR_ERROR_BEFORE_ALLOC(this->glInterface());
|
||||
GL_ALLOC_CALL(this->glInterface(), TexImage2D(GR_GL_TEXTURE_2D,
|
||||
0,
|
||||
internalFormat,
|
||||
kSize,
|
||||
kSize,
|
||||
0,
|
||||
externalFormat,
|
||||
externalType,
|
||||
nullptr));
|
||||
if (GR_GL_NO_ERROR != CHECK_ALLOC_ERROR(this->glInterface())) {
|
||||
GL_CALL(DeleteTextures(1, &colorID));
|
||||
return -1;
|
||||
}
|
||||
|
||||
// unbind the texture from the texture unit before binding it to the frame buffer
|
||||
GL_CALL(BindTexture(GR_GL_TEXTURE_2D, 0));
|
||||
|
||||
@ -1691,11 +1478,7 @@ GrGLuint GrGLGpu::createTexture2D(const SkISize& size,
|
||||
GrGLFormat format,
|
||||
GrRenderable renderable,
|
||||
GrGLTextureParameters::SamplerOverriddenState* initialState,
|
||||
GrColorType textureColorType,
|
||||
GrColorType srcColorType,
|
||||
const GrMipLevel texels[],
|
||||
int mipLevelCount,
|
||||
GrMipMapsStatus* mipMapsStatus) {
|
||||
int mipLevelCount) {
|
||||
SkASSERT(format != GrGLFormat::kUnknown);
|
||||
SkASSERT(!GrGLFormatIsCompressed(format));
|
||||
|
||||
@ -1713,25 +1496,46 @@ GrGLuint GrGLGpu::createTexture2D(const SkISize& size,
|
||||
GL_CALL(TexParameteri(GR_GL_TEXTURE_2D, GR_GL_TEXTURE_USAGE, GR_GL_FRAMEBUFFER_ATTACHMENT));
|
||||
}
|
||||
|
||||
*initialState = set_initial_texture_params(this->glInterface(), GR_GL_TEXTURE_2D);
|
||||
|
||||
if (!this->uploadTexData(format,
|
||||
textureColorType,
|
||||
size.width(), size.height(),
|
||||
GR_GL_TEXTURE_2D,
|
||||
kNewTexture_UploadType,
|
||||
0,
|
||||
0,
|
||||
size.width(),
|
||||
size.height(),
|
||||
srcColorType,
|
||||
texels,
|
||||
mipLevelCount,
|
||||
mipMapsStatus)) {
|
||||
GL_CALL(DeleteTextures(1, &id));
|
||||
return 0;
|
||||
if (initialState) {
|
||||
*initialState = set_initial_texture_params(this->glInterface(), GR_GL_TEXTURE_2D);
|
||||
} else {
|
||||
set_initial_texture_params(this->glInterface(), GR_GL_TEXTURE_2D);
|
||||
}
|
||||
return id;
|
||||
|
||||
GrGLenum internalFormat = this->glCaps().getTexImageOrStorageInternalFormat(format);
|
||||
|
||||
bool success = false;
|
||||
if (internalFormat) {
|
||||
CLEAR_ERROR_BEFORE_ALLOC(this->glInterface());
|
||||
if (this->glCaps().formatSupportsTexStorage(format)) {
|
||||
GL_ALLOC_CALL(this->glInterface(),
|
||||
TexStorage2D(GR_GL_TEXTURE_2D, SkTMax(mipLevelCount, 1), internalFormat,
|
||||
size.width(), size.height()));
|
||||
success = (GR_GL_NO_ERROR == CHECK_ALLOC_ERROR(this->glInterface()));
|
||||
} else {
|
||||
GrGLenum externalFormat, externalType;
|
||||
this->glCaps().getTexImageExternalFormatAndType(format, &externalFormat, &externalType);
|
||||
GrGLenum error = GR_GL_NO_ERROR;
|
||||
if (externalFormat && externalType) {
|
||||
for (int level = 0; level < mipLevelCount && error == GR_GL_NO_ERROR; level++) {
|
||||
const int twoToTheMipLevel = 1 << level;
|
||||
const int currentWidth = SkTMax(1, size.width() / twoToTheMipLevel);
|
||||
const int currentHeight = SkTMax(1, size.height() / twoToTheMipLevel);
|
||||
GL_ALLOC_CALL(
|
||||
this->glInterface(),
|
||||
TexImage2D(GR_GL_TEXTURE_2D, level, internalFormat, currentWidth,
|
||||
currentHeight, 0, externalFormat, externalType, nullptr));
|
||||
error = CHECK_ALLOC_ERROR(this->glInterface());
|
||||
}
|
||||
success = (GR_GL_NO_ERROR == error);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (success) {
|
||||
return id;
|
||||
}
|
||||
GL_CALL(DeleteTextures(1, &id));
|
||||
return 0;
|
||||
}
|
||||
|
||||
GrStencilAttachment* GrGLGpu::createStencilAttachmentForRenderTarget(
|
||||
@ -2161,7 +1965,7 @@ bool GrGLGpu::readOrTransferPixelsFrom(GrSurface* surface, int left, int top, in
|
||||
}
|
||||
} else {
|
||||
// Use a temporary FBO.
|
||||
this->bindSurfaceFBOForPixelOps(surface, GR_GL_FRAMEBUFFER, kSrc_TempFBOTarget);
|
||||
this->bindSurfaceFBOForPixelOps(surface, 0, GR_GL_FRAMEBUFFER, kSrc_TempFBOTarget);
|
||||
fHWBoundRenderTargetUniqueID.makeInvalid();
|
||||
}
|
||||
|
||||
@ -2202,7 +2006,7 @@ bool GrGLGpu::readOrTransferPixelsFrom(GrSurface* surface, int left, int top, in
|
||||
}
|
||||
|
||||
if (!renderTarget) {
|
||||
this->unbindTextureFBOForPixelOps(GR_GL_FRAMEBUFFER, surface);
|
||||
this->unbindSurfaceFBOForPixelOps(surface, 0, GR_GL_FRAMEBUFFER);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@ -3015,10 +2819,10 @@ static inline bool can_copy_texsubimage(const GrSurface* dst, const GrSurface* s
|
||||
}
|
||||
|
||||
// If a temporary FBO was created, its non-zero ID is returned.
|
||||
void GrGLGpu::bindSurfaceFBOForPixelOps(GrSurface* surface, GrGLenum fboTarget,
|
||||
void GrGLGpu::bindSurfaceFBOForPixelOps(GrSurface* surface, int mipLevel, GrGLenum fboTarget,
|
||||
TempFBOTarget tempFBOTarget) {
|
||||
GrGLRenderTarget* rt = static_cast<GrGLRenderTarget*>(surface->asRenderTarget());
|
||||
if (!rt) {
|
||||
if (!rt || mipLevel > 0) {
|
||||
SkASSERT(surface->asTexture());
|
||||
GrGLTexture* texture = static_cast<GrGLTexture*>(surface->asTexture());
|
||||
GrGLuint texID = texture->textureID();
|
||||
@ -3031,20 +2835,20 @@ void GrGLGpu::bindSurfaceFBOForPixelOps(GrSurface* surface, GrGLenum fboTarget,
|
||||
}
|
||||
|
||||
this->bindFramebuffer(fboTarget, *tempFBOID);
|
||||
GR_GL_CALL(this->glInterface(), FramebufferTexture2D(fboTarget,
|
||||
GR_GL_COLOR_ATTACHMENT0,
|
||||
target,
|
||||
texID,
|
||||
0));
|
||||
texture->baseLevelWasBoundToFBO();
|
||||
GR_GL_CALL(
|
||||
this->glInterface(),
|
||||
FramebufferTexture2D(fboTarget, GR_GL_COLOR_ATTACHMENT0, target, texID, mipLevel));
|
||||
if (mipLevel == 0) {
|
||||
texture->baseLevelWasBoundToFBO();
|
||||
}
|
||||
} else {
|
||||
this->bindFramebuffer(fboTarget, rt->renderFBOID());
|
||||
}
|
||||
}
|
||||
|
||||
void GrGLGpu::unbindTextureFBOForPixelOps(GrGLenum fboTarget, GrSurface* surface) {
|
||||
void GrGLGpu::unbindSurfaceFBOForPixelOps(GrSurface* surface, int mipLevel, GrGLenum fboTarget) {
|
||||
// bindSurfaceFBOForPixelOps temporarily binds textures that are not render targets to
|
||||
if (!surface->asRenderTarget()) {
|
||||
if (mipLevel > 0 || !surface->asRenderTarget()) {
|
||||
SkASSERT(surface->asTexture());
|
||||
GrGLenum textureTarget = static_cast<GrGLTexture*>(surface->asTexture())->target();
|
||||
GR_GL_CALL(this->glInterface(), FramebufferTexture2D(fboTarget,
|
||||
@ -3426,7 +3230,7 @@ bool GrGLGpu::copySurfaceAsDraw(GrSurface* dst, GrSurface* src, const SkIRect& s
|
||||
int h = srcRect.height();
|
||||
// We don't swizzle at all in our copies.
|
||||
this->bindTexture(0, GrSamplerState::ClampNearest(), GrSwizzle::RGBA(), srcTex);
|
||||
this->bindSurfaceFBOForPixelOps(dst, GR_GL_FRAMEBUFFER, kDst_TempFBOTarget);
|
||||
this->bindSurfaceFBOForPixelOps(dst, 0, GR_GL_FRAMEBUFFER, kDst_TempFBOTarget);
|
||||
this->flushViewport(dst->width(), dst->height());
|
||||
fHWBoundRenderTargetUniqueID.makeInvalid();
|
||||
SkIRect dstRect = SkIRect::MakeXYWH(dstPoint.fX, dstPoint.fY, w, h);
|
||||
@ -3469,7 +3273,7 @@ bool GrGLGpu::copySurfaceAsDraw(GrSurface* dst, GrSurface* src, const SkIRect& s
|
||||
this->flushFramebufferSRGB(true);
|
||||
}
|
||||
GL_CALL(DrawArrays(GR_GL_TRIANGLE_STRIP, 0, 4));
|
||||
this->unbindTextureFBOForPixelOps(GR_GL_FRAMEBUFFER, dst);
|
||||
this->unbindSurfaceFBOForPixelOps(dst, 0, GR_GL_FRAMEBUFFER);
|
||||
// The rect is already in device space so we pass in kTopLeft so no flip is done.
|
||||
this->didWriteToSurface(dst, kTopLeft_GrSurfaceOrigin, &dstRect);
|
||||
return true;
|
||||
@ -3478,7 +3282,7 @@ bool GrGLGpu::copySurfaceAsDraw(GrSurface* dst, GrSurface* src, const SkIRect& s
|
||||
void GrGLGpu::copySurfaceAsCopyTexSubImage(GrSurface* dst, GrSurface* src, const SkIRect& srcRect,
|
||||
const SkIPoint& dstPoint) {
|
||||
SkASSERT(can_copy_texsubimage(dst, src, this->glCaps()));
|
||||
this->bindSurfaceFBOForPixelOps(src, GR_GL_FRAMEBUFFER, kSrc_TempFBOTarget);
|
||||
this->bindSurfaceFBOForPixelOps(src, 0, GR_GL_FRAMEBUFFER, kSrc_TempFBOTarget);
|
||||
GrGLTexture* dstTex = static_cast<GrGLTexture *>(dst->asTexture());
|
||||
SkASSERT(dstTex);
|
||||
// We modified the bound FBO
|
||||
@ -3489,7 +3293,7 @@ void GrGLGpu::copySurfaceAsCopyTexSubImage(GrSurface* dst, GrSurface* src, const
|
||||
dstPoint.fX, dstPoint.fY,
|
||||
srcRect.fLeft, srcRect.fTop,
|
||||
srcRect.width(), srcRect.height()));
|
||||
this->unbindTextureFBOForPixelOps(GR_GL_FRAMEBUFFER, src);
|
||||
this->unbindSurfaceFBOForPixelOps(src, 0, GR_GL_FRAMEBUFFER);
|
||||
SkIRect dstRect = SkIRect::MakeXYWH(dstPoint.fX, dstPoint.fY,
|
||||
srcRect.width(), srcRect.height());
|
||||
// The rect is already in device space so we pass in kTopLeft so no flip is done.
|
||||
@ -3507,8 +3311,8 @@ bool GrGLGpu::copySurfaceAsBlitFramebuffer(GrSurface* dst, GrSurface* src, const
|
||||
}
|
||||
}
|
||||
|
||||
this->bindSurfaceFBOForPixelOps(dst, GR_GL_DRAW_FRAMEBUFFER, kDst_TempFBOTarget);
|
||||
this->bindSurfaceFBOForPixelOps(src, GR_GL_READ_FRAMEBUFFER, kSrc_TempFBOTarget);
|
||||
this->bindSurfaceFBOForPixelOps(dst, 0, GR_GL_DRAW_FRAMEBUFFER, kDst_TempFBOTarget);
|
||||
this->bindSurfaceFBOForPixelOps(src, 0, GR_GL_READ_FRAMEBUFFER, kSrc_TempFBOTarget);
|
||||
// We modified the bound FBO
|
||||
fHWBoundRenderTargetUniqueID.makeInvalid();
|
||||
|
||||
@ -3525,8 +3329,8 @@ bool GrGLGpu::copySurfaceAsBlitFramebuffer(GrSurface* dst, GrSurface* src, const
|
||||
dstRect.fRight,
|
||||
dstRect.fBottom,
|
||||
GR_GL_COLOR_BUFFER_BIT, GR_GL_NEAREST));
|
||||
this->unbindTextureFBOForPixelOps(GR_GL_DRAW_FRAMEBUFFER, dst);
|
||||
this->unbindTextureFBOForPixelOps(GR_GL_READ_FRAMEBUFFER, src);
|
||||
this->unbindSurfaceFBOForPixelOps(dst, 0, GR_GL_DRAW_FRAMEBUFFER);
|
||||
this->unbindSurfaceFBOForPixelOps(src, 0, GR_GL_READ_FRAMEBUFFER);
|
||||
|
||||
// The rect is already in device space so we pass in kTopLeft so no flip is done.
|
||||
this->didWriteToSurface(dst, kTopLeft_GrSurfaceOrigin, &dstRect);
|
||||
@ -3764,8 +3568,7 @@ GrBackendTexture GrGLGpu::createBackendTexture(int w, int h,
|
||||
GrGLTextureInfo info;
|
||||
GrGLTextureParameters::SamplerOverriddenState initialState;
|
||||
|
||||
int mipLevelCount = 0;
|
||||
SkAutoTMalloc<GrMipLevel> texels;
|
||||
SkTDArray<GrMipLevel> texels;
|
||||
SkAutoMalloc pixelStorage;
|
||||
SkImage::CompressionType compressionType;
|
||||
if (GrGLFormatToCompressionType(glFormat, &compressionType)) {
|
||||
@ -3791,16 +3594,15 @@ GrBackendTexture GrGLGpu::createBackendTexture(int w, int h,
|
||||
info.fTarget = GR_GL_TEXTURE_2D;
|
||||
} else {
|
||||
if (srcPixels) {
|
||||
mipLevelCount = 1;
|
||||
texels.reset(mipLevelCount);
|
||||
texels.get()[0] = {srcPixels, rowBytes};
|
||||
texels.append(1);
|
||||
texels[0] = {srcPixels, rowBytes};
|
||||
} else if (color) {
|
||||
mipLevelCount = 1;
|
||||
int mipLevelCount = 1;
|
||||
if (GrMipMapped::kYes == mipMapped) {
|
||||
mipLevelCount = SkMipMap::ComputeLevelCount(w, h) + 1;
|
||||
}
|
||||
|
||||
texels.reset(mipLevelCount);
|
||||
texels.append(mipLevelCount);
|
||||
SkTArray<size_t> individualMipOffsets(mipLevelCount);
|
||||
|
||||
size_t bytesPerPixel = GrBytesPerPixel(config);
|
||||
@ -3817,7 +3619,7 @@ GrBackendTexture GrGLGpu::createBackendTexture(int w, int h,
|
||||
int twoToTheMipLevel = 1 << i;
|
||||
int currentWidth = SkTMax(1, w / twoToTheMipLevel);
|
||||
|
||||
texels.get()[i] = {&(tmpPixels[offset]), currentWidth * bytesPerPixel};
|
||||
texels[i] = {&(tmpPixels[offset]), currentWidth * bytesPerPixel};
|
||||
}
|
||||
}
|
||||
GrSurfaceDesc desc;
|
||||
@ -3827,20 +3629,19 @@ GrBackendTexture GrGLGpu::createBackendTexture(int w, int h,
|
||||
|
||||
info.fTarget = GR_GL_TEXTURE_2D;
|
||||
info.fFormat = GrGLFormatToEnum(glFormat);
|
||||
// TODO: Take these as parameters.
|
||||
auto srcColorType = GrPixelConfigToColorType(desc.fConfig);
|
||||
info.fID = this->createTexture2D({desc.fWidth, desc.fHeight},
|
||||
glFormat,
|
||||
renderable,
|
||||
&initialState,
|
||||
textureColorType,
|
||||
srcColorType,
|
||||
texels,
|
||||
mipLevelCount,
|
||||
nullptr);
|
||||
info.fID = this->createTexture2D({desc.fWidth, desc.fHeight}, glFormat, renderable,
|
||||
&initialState, SkTMax(1, texels.count()));
|
||||
if (!info.fID) {
|
||||
return GrBackendTexture(); // invalid
|
||||
}
|
||||
auto srcColorType = GrPixelConfigToColorType(desc.fConfig);
|
||||
if (!texels.empty() &&
|
||||
!this->uploadTexData(glFormat, textureColorType, desc.fWidth, desc.fHeight,
|
||||
GR_GL_TEXTURE_2D, 0, 0, desc.fWidth, desc.fHeight, srcColorType,
|
||||
texels.begin(), texels.count())) {
|
||||
GL_CALL(DeleteTextures(1, &info.fID));
|
||||
return GrBackendTexture();
|
||||
}
|
||||
}
|
||||
|
||||
// unbind the texture from the texture unit to avoid asserts
|
||||
@ -3888,17 +3689,7 @@ GrBackendRenderTarget GrGLGpu::createTestingOnlyBackendRenderTarget(int w, int h
|
||||
if (!this->glCaps().isFormatRenderable(format, 1)) {
|
||||
return {};
|
||||
}
|
||||
bool useTexture = false;
|
||||
GrGLenum colorBufferFormat;
|
||||
GrGLenum externalFormat = 0, externalType = 0;
|
||||
if (format == GrGLFormat::kBGRA8) {
|
||||
// BGRA render buffers are not supported.
|
||||
this->glCaps().getTexImageFormats(format, colorType, colorType, &colorBufferFormat,
|
||||
&externalFormat, &externalType);
|
||||
useTexture = true;
|
||||
} else {
|
||||
colorBufferFormat = this->glCaps().getRenderbufferInternalFormat(format);
|
||||
}
|
||||
bool useTexture = format == GrGLFormat::kBGRA8;
|
||||
int sFormatIdx = this->getCompatibleStencilIndex(format);
|
||||
if (sFormatIdx < 0) {
|
||||
return {};
|
||||
@ -3931,7 +3722,7 @@ GrBackendRenderTarget GrGLGpu::createTestingOnlyBackendRenderTarget(int w, int h
|
||||
|
||||
GrGLFramebufferInfo info;
|
||||
info.fFBOID = 0;
|
||||
info.fFormat = this->glCaps().formatSizedInternalFormat(format);
|
||||
info.fFormat = GrGLFormatToEnum(format);
|
||||
GL_CALL(GenFramebuffers(1, &info.fFBOID));
|
||||
if (!info.fFBOID) {
|
||||
deleteIDs();
|
||||
@ -3942,15 +3733,19 @@ GrBackendRenderTarget GrGLGpu::createTestingOnlyBackendRenderTarget(int w, int h
|
||||
|
||||
this->bindFramebuffer(GR_GL_FRAMEBUFFER, info.fFBOID);
|
||||
if (useTexture) {
|
||||
this->bindTextureToScratchUnit(GR_GL_TEXTURE_2D, colorID);
|
||||
GL_CALL(TexImage2D(GR_GL_TEXTURE_2D, 0, colorBufferFormat, w, h, 0, externalFormat,
|
||||
externalType, nullptr));
|
||||
GrGLTextureParameters::SamplerOverriddenState initialState;
|
||||
colorID = this->createTexture2D({w, h}, format, GrRenderable::kYes, &initialState, 1);
|
||||
if (!colorID) {
|
||||
deleteIDs();
|
||||
return {};
|
||||
}
|
||||
GL_CALL(FramebufferTexture2D(GR_GL_FRAMEBUFFER, GR_GL_COLOR_ATTACHMENT0, GR_GL_TEXTURE_2D,
|
||||
colorID, 0));
|
||||
} else {
|
||||
GrGLenum renderBufferFormat = this->glCaps().getRenderbufferInternalFormat(format);
|
||||
GL_CALL(BindRenderbuffer(GR_GL_RENDERBUFFER, colorID));
|
||||
GL_ALLOC_CALL(this->glInterface(),
|
||||
RenderbufferStorage(GR_GL_RENDERBUFFER, colorBufferFormat, w, h));
|
||||
RenderbufferStorage(GR_GL_RENDERBUFFER, renderBufferFormat, w, h));
|
||||
GL_CALL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER, GR_GL_COLOR_ATTACHMENT0,
|
||||
GR_GL_RENDERBUFFER, colorID));
|
||||
}
|
||||
|
@ -195,8 +195,8 @@ private:
|
||||
int renderTargetSampleCnt,
|
||||
SkBudgeted,
|
||||
GrProtected,
|
||||
const GrMipLevel[],
|
||||
int mipLevelCount) override;
|
||||
int mipLevelCount,
|
||||
uint32_t levelClearMask) override;
|
||||
sk_sp<GrTexture> onCreateCompressedTexture(int width, int height, const GrBackendFormat&,
|
||||
SkImage::CompressionType compression, SkBudgeted,
|
||||
const void* data) override;
|
||||
@ -228,11 +228,7 @@ private:
|
||||
GrGLFormat format,
|
||||
GrRenderable,
|
||||
GrGLTextureParameters::SamplerOverriddenState* initialState,
|
||||
GrColorType textureColorType,
|
||||
GrColorType srcColorType,
|
||||
const GrMipLevel texels[],
|
||||
int mipLevelCount,
|
||||
GrMipMapsStatus* mipMapsStatus);
|
||||
int mipLevelCount);
|
||||
|
||||
GrGLuint createCompressedTexture2D(const SkISize& size, GrGLFormat format,
|
||||
SkImage::CompressionType compression,
|
||||
@ -377,15 +373,9 @@ private:
|
||||
|
||||
void flushFramebufferSRGB(bool enable);
|
||||
|
||||
// helper for onCreateTexture and writeTexturePixels
|
||||
enum UploadType {
|
||||
kNewTexture_UploadType, // we are creating a new texture
|
||||
kWrite_UploadType, // we are using TexSubImage2D to copy data to an existing texture
|
||||
};
|
||||
bool uploadTexData(GrGLFormat textureFormat, GrColorType textureColorType,
|
||||
int texWidth, int texHeight, GrGLenum target, UploadType uploadType,
|
||||
int left, int top, int width, int height, GrColorType srcColorType,
|
||||
const GrMipLevel texels[], int mipLevelCount,
|
||||
bool uploadTexData(GrGLFormat textureFormat, GrColorType textureColorType, int texWidth,
|
||||
int texHeight, GrGLenum target, int left, int top, int width, int height,
|
||||
GrColorType srcColorType, const GrMipLevel texels[], int mipLevelCount,
|
||||
GrMipMapsStatus* mipMapsStatus = nullptr);
|
||||
|
||||
// Helper for onCreateCompressedTexture. Compressed textures are read-only so we only use this
|
||||
@ -408,11 +398,11 @@ private:
|
||||
// Binds a surface as a FBO for copying, reading, or clearing. If the surface already owns an
|
||||
// FBO ID then that ID is bound. If not the surface is temporarily bound to a FBO and that FBO
|
||||
// is bound. This must be paired with a call to unbindSurfaceFBOForPixelOps().
|
||||
void bindSurfaceFBOForPixelOps(GrSurface* surface, GrGLenum fboTarget,
|
||||
void bindSurfaceFBOForPixelOps(GrSurface* surface, int mipLevel, GrGLenum fboTarget,
|
||||
TempFBOTarget tempFBOTarget);
|
||||
|
||||
// Must be called if bindSurfaceFBOForPixelOps was used to bind a surface for copying.
|
||||
void unbindTextureFBOForPixelOps(GrGLenum fboTarget, GrSurface* surface);
|
||||
void unbindSurfaceFBOForPixelOps(GrSurface* surface, int mipLevel, GrGLenum fboTarget);
|
||||
|
||||
#ifdef SK_ENABLE_DUMP_GPU
|
||||
void onDumpJSON(SkJSONWriter*) const override;
|
||||
|
@ -132,8 +132,6 @@ public:
|
||||
return {};
|
||||
}
|
||||
|
||||
bool canClearTextureOnCreation() const override { return true; }
|
||||
|
||||
GrSwizzle getTextureSwizzle(const GrBackendFormat&, GrColorType) const override {
|
||||
return GrSwizzle();
|
||||
}
|
||||
|
@ -137,8 +137,8 @@ sk_sp<GrTexture> GrMockGpu::onCreateTexture(const GrSurfaceDesc& desc,
|
||||
int renderTargetSampleCnt,
|
||||
SkBudgeted budgeted,
|
||||
GrProtected isProtected,
|
||||
const GrMipLevel texels[],
|
||||
int mipLevelCount) {
|
||||
int mipLevelCount,
|
||||
uint32_t levelClearMask) {
|
||||
if (fMockOptions.fFailTextureAllocations) {
|
||||
return nullptr;
|
||||
}
|
||||
@ -146,14 +146,8 @@ sk_sp<GrTexture> GrMockGpu::onCreateTexture(const GrSurfaceDesc& desc,
|
||||
GrColorType ct = format.asMockColorType();
|
||||
SkASSERT(ct != GrColorType::kUnknown);
|
||||
|
||||
GrMipMapsStatus mipMapsStatus = mipLevelCount > 1 ? GrMipMapsStatus::kValid
|
||||
: GrMipMapsStatus::kNotAllocated;
|
||||
for (int i = 0; i < mipLevelCount; ++i) {
|
||||
if (!texels[i].fPixels) {
|
||||
mipMapsStatus = GrMipMapsStatus::kDirty;
|
||||
break;
|
||||
}
|
||||
}
|
||||
GrMipMapsStatus mipMapsStatus =
|
||||
mipLevelCount > 1 ? GrMipMapsStatus::kDirty : GrMipMapsStatus::kNotAllocated;
|
||||
GrMockTextureInfo texInfo(ct, NextInternalTextureID());
|
||||
if (renderable == GrRenderable::kYes) {
|
||||
GrMockRenderTargetInfo rtInfo(ct, NextInternalRenderTargetID());
|
||||
|
@ -63,8 +63,8 @@ private:
|
||||
int renderTargetSampleCnt,
|
||||
SkBudgeted,
|
||||
GrProtected,
|
||||
const GrMipLevel[],
|
||||
int mipLevelCount) override;
|
||||
int mipLevelCount,
|
||||
uint32_t levelClearMask) override;
|
||||
|
||||
sk_sp<GrTexture> onCreateCompressedTexture(int width, int height, const GrBackendFormat&,
|
||||
SkImage::CompressionType, SkBudgeted,
|
||||
|
@ -78,8 +78,6 @@ public:
|
||||
return fColorTypeToFormatTable[idx];
|
||||
}
|
||||
|
||||
bool canClearTextureOnCreation() const override { return true; }
|
||||
|
||||
GrSwizzle getTextureSwizzle(const GrBackendFormat&, GrColorType) const override;
|
||||
GrSwizzle getOutputSwizzle(const GrBackendFormat&, GrColorType) const override;
|
||||
|
||||
|
@ -139,8 +139,8 @@ private:
|
||||
int renderTargetSampleCnt,
|
||||
SkBudgeted budgeted,
|
||||
GrProtected,
|
||||
const GrMipLevel texels[],
|
||||
int mipLevelCount) override;
|
||||
int mipLevelCount,
|
||||
uint32_t levelClearMask) override;
|
||||
sk_sp<GrTexture> onCreateCompressedTexture(int width, int height, const GrBackendFormat&,
|
||||
SkImage::CompressionType, SkBudgeted,
|
||||
const void* data) override {
|
||||
|
@ -402,13 +402,13 @@ sk_sp<GrTexture> GrMtlGpu::onCreateTexture(const GrSurfaceDesc& desc,
|
||||
int renderTargetSampleCnt,
|
||||
SkBudgeted budgeted,
|
||||
GrProtected isProtected,
|
||||
const GrMipLevel texels[],
|
||||
int mipLevelCount) {
|
||||
int mipLevelCount,
|
||||
uint32_t levelClearMask) {
|
||||
// We don't support protected textures in Metal.
|
||||
if (isProtected == GrProtected::kYes) {
|
||||
return nullptr;
|
||||
}
|
||||
int mipLevels = !mipLevelCount ? 1 : mipLevelCount;
|
||||
SkASSERT(mipLevelCount > 0);
|
||||
|
||||
MTLPixelFormat mtlPixelFormat = GrBackendFormatAsMTLPixelFormat(format);
|
||||
SkASSERT(mtlPixelFormat != MTLPixelFormatInvalid);
|
||||
@ -424,7 +424,7 @@ sk_sp<GrTexture> GrMtlGpu::onCreateTexture(const GrSurfaceDesc& desc,
|
||||
texDesc.width = desc.fWidth;
|
||||
texDesc.height = desc.fHeight;
|
||||
texDesc.depth = 1;
|
||||
texDesc.mipmapLevelCount = mipLevels;
|
||||
texDesc.mipmapLevelCount = mipLevelCount;
|
||||
texDesc.sampleCount = 1;
|
||||
texDesc.arrayLength = 1;
|
||||
// Make all textures have private gpu only access. We can use transfer buffers or textures
|
||||
@ -433,17 +433,8 @@ sk_sp<GrTexture> GrMtlGpu::onCreateTexture(const GrSurfaceDesc& desc,
|
||||
texDesc.usage = MTLTextureUsageShaderRead;
|
||||
texDesc.usage |= (renderable == GrRenderable::kYes) ? MTLTextureUsageRenderTarget : 0;
|
||||
|
||||
GrMipMapsStatus mipMapsStatus = GrMipMapsStatus::kNotAllocated;
|
||||
if (mipLevels > 1) {
|
||||
mipMapsStatus = GrMipMapsStatus::kValid;
|
||||
for (int i = 0; i < mipLevels; ++i) {
|
||||
if (!texels[i].fPixels) {
|
||||
mipMapsStatus = GrMipMapsStatus::kDirty;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
GrMipMapsStatus mipMapsStatus =
|
||||
mipLevelCount > 1 ? GrMipMapsStatus::kDirty : GrMipMapsStatus::kNotAllocated;
|
||||
if (renderable == GrRenderable::kYes) {
|
||||
tex = GrMtlTextureRenderTarget::MakeNewTextureRenderTarget(this, budgeted,
|
||||
desc, renderTargetSampleCnt,
|
||||
@ -456,24 +447,9 @@ sk_sp<GrTexture> GrMtlGpu::onCreateTexture(const GrSurfaceDesc& desc,
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
auto colorType = GrPixelConfigToColorType(desc.fConfig);
|
||||
if (mipLevelCount && texels[0].fPixels) {
|
||||
if (!this->uploadToTexture(tex.get(), 0, 0, desc.fWidth, desc.fHeight, colorType, texels,
|
||||
mipLevelCount)) {
|
||||
tex->unref();
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
if (this->caps()->shouldInitializeTextures()) {
|
||||
uint32_t levelMask = ~0;
|
||||
SkASSERT(mipLevelCount < 32);
|
||||
for (int i = 0; i < mipLevelCount; ++i) {
|
||||
if (!texels[i].fPixels) {
|
||||
levelMask &= ~(1 << i);
|
||||
}
|
||||
}
|
||||
this->clearTexture(tex.get(), colorType, levelMask);
|
||||
if (levelClearMask) {
|
||||
auto colorType = GrPixelConfigToColorType(desc.fConfig);
|
||||
this->clearTexture(tex.get(), colorType, levelClearMask);
|
||||
}
|
||||
|
||||
return tex;
|
||||
|
@ -1610,8 +1610,6 @@ GrBackendFormat GrVkCaps::getBackendFormatFromCompressionType(
|
||||
SK_ABORT("Invalid compression type");
|
||||
}
|
||||
|
||||
bool GrVkCaps::canClearTextureOnCreation() const { return true; }
|
||||
|
||||
GrSwizzle GrVkCaps::getTextureSwizzle(const GrBackendFormat& format, GrColorType colorType) const {
|
||||
VkFormat vkFormat;
|
||||
SkAssertResult(format.asVkFormat(&vkFormat));
|
||||
|
@ -171,8 +171,6 @@ public:
|
||||
return fColorTypeToFormatTable[idx];
|
||||
}
|
||||
|
||||
bool canClearTextureOnCreation() const override;
|
||||
|
||||
GrSwizzle getTextureSwizzle(const GrBackendFormat&, GrColorType) const override;
|
||||
GrSwizzle getOutputSwizzle(const GrBackendFormat&, GrColorType) const override;
|
||||
|
||||
|
@ -953,8 +953,8 @@ sk_sp<GrTexture> GrVkGpu::onCreateTexture(const GrSurfaceDesc& desc,
|
||||
int renderTargetSampleCnt,
|
||||
SkBudgeted budgeted,
|
||||
GrProtected isProtected,
|
||||
const GrMipLevel texels[],
|
||||
int mipLevelCount) {
|
||||
int mipLevelCount,
|
||||
uint32_t levelClearMask) {
|
||||
VkFormat pixelFormat;
|
||||
SkAssertResult(format.asVkFormat(&pixelFormat));
|
||||
SkASSERT(!GrVkFormatIsCompressed(pixelFormat));
|
||||
@ -975,28 +975,20 @@ sk_sp<GrTexture> GrVkGpu::onCreateTexture(const GrSurfaceDesc& desc,
|
||||
// This ImageDesc refers to the texture that will be read by the client. Thus even if msaa is
|
||||
// requested, this ImageDesc describes the resolved texture. Therefore we always have samples set
|
||||
// to 1.
|
||||
int mipLevels = !mipLevelCount ? 1 : mipLevelCount;
|
||||
SkASSERT(mipLevelCount > 0);
|
||||
GrVkImage::ImageDesc imageDesc;
|
||||
imageDesc.fImageType = VK_IMAGE_TYPE_2D;
|
||||
imageDesc.fFormat = pixelFormat;
|
||||
imageDesc.fWidth = desc.fWidth;
|
||||
imageDesc.fHeight = desc.fHeight;
|
||||
imageDesc.fLevels = mipLevels;
|
||||
imageDesc.fLevels = mipLevelCount;
|
||||
imageDesc.fSamples = 1;
|
||||
imageDesc.fImageTiling = VK_IMAGE_TILING_OPTIMAL;
|
||||
imageDesc.fUsageFlags = usageFlags;
|
||||
imageDesc.fIsProtected = isProtected;
|
||||
|
||||
GrMipMapsStatus mipMapsStatus = GrMipMapsStatus::kNotAllocated;
|
||||
if (mipLevels > 1) {
|
||||
mipMapsStatus = GrMipMapsStatus::kValid;
|
||||
for (int i = 0; i < mipLevels; ++i) {
|
||||
if (!texels[i].fPixels) {
|
||||
mipMapsStatus = GrMipMapsStatus::kDirty;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
GrMipMapsStatus mipMapsStatus =
|
||||
mipLevelCount > 1 ? GrMipMapsStatus::kDirty : GrMipMapsStatus::kNotAllocated;
|
||||
|
||||
sk_sp<GrVkTexture> tex;
|
||||
if (renderable == GrRenderable::kYes) {
|
||||
@ -1010,20 +1002,11 @@ sk_sp<GrTexture> GrVkGpu::onCreateTexture(const GrSurfaceDesc& desc,
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
auto colorType = GrPixelConfigToColorType(desc.fConfig);
|
||||
if (mipLevelCount) {
|
||||
if (!this->uploadTexDataOptimal(tex.get(), 0, 0, desc.fWidth, desc.fHeight, colorType,
|
||||
texels, mipLevelCount)) {
|
||||
tex->unref();
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
if (this->caps()->shouldInitializeTextures()) {
|
||||
if (levelClearMask) {
|
||||
SkSTArray<1, VkImageSubresourceRange> ranges;
|
||||
bool inRange = false;
|
||||
for (uint32_t i = 0; i < tex->mipLevels(); ++i) {
|
||||
if (i >= static_cast<uint32_t>(mipLevelCount) || !texels[i].fPixels) {
|
||||
if (levelClearMask & (1U << i)) {
|
||||
if (inRange) {
|
||||
ranges.back().levelCount++;
|
||||
} else {
|
||||
@ -1039,15 +1022,12 @@ sk_sp<GrTexture> GrVkGpu::onCreateTexture(const GrSurfaceDesc& desc,
|
||||
inRange = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!ranges.empty()) {
|
||||
static constexpr VkClearColorValue kZeroClearColor = {};
|
||||
tex->setImageLayout(this, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
|
||||
VK_ACCESS_TRANSFER_WRITE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT,
|
||||
false);
|
||||
this->currentCommandBuffer()->clearColorImage(this, tex.get(), &kZeroClearColor,
|
||||
ranges.count(), ranges.begin());
|
||||
}
|
||||
SkASSERT(!ranges.empty());
|
||||
static constexpr VkClearColorValue kZeroClearColor = {};
|
||||
tex->setImageLayout(this, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
|
||||
VK_ACCESS_TRANSFER_WRITE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, false);
|
||||
this->currentCommandBuffer()->clearColorImage(this, tex.get(), &kZeroClearColor,
|
||||
ranges.count(), ranges.begin());
|
||||
}
|
||||
return tex;
|
||||
}
|
||||
|
@ -196,8 +196,8 @@ private:
|
||||
int renderTargetSampleCnt,
|
||||
SkBudgeted,
|
||||
GrProtected,
|
||||
const GrMipLevel[],
|
||||
int mipLevelCount) override;
|
||||
int mipLevelCount,
|
||||
uint32_t levelClearMask) override;
|
||||
sk_sp<GrTexture> onCreateCompressedTexture(int width, int height, const GrBackendFormat&,
|
||||
SkImage::CompressionType, SkBudgeted,
|
||||
const void* data) override;
|
||||
|
@ -499,7 +499,7 @@ sk_sp<const GrGLInterface> CreateANGLEGLInterface() {
|
||||
}
|
||||
|
||||
std::unique_ptr<GLTestContext> MakeANGLETestContext(ANGLEBackend type, ANGLEContextVersion version,
|
||||
GLTestContext* shareContext, void* display){
|
||||
GLTestContext* shareContext, void* display) {
|
||||
#if defined(SK_BUILD_FOR_WIN) && defined(_M_ARM64)
|
||||
// Windows-on-ARM only has D3D11. This will fail correctly, but it produces huge amounts of
|
||||
// debug output for every unit test from both ANGLE and our context factory.
|
||||
|
Loading…
Reference in New Issue
Block a user