Split apart creating and updating GrBackendTextures internally.
This change does not any public APIs but just pulls apart the create and
update steps inside of createBackendTexture. A future CL will allow just
calling update from the public API with an already create texture.
This change only splits apart the work for non compressed textures.
Compressed support can be added at a future time, but for many backends
it should be fairly trivial since the update call handles compressed and
uncompressed already.
Change-Id: Iae99e9f140c347effe66b5d669c6f39bce023115
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/287856
Reviewed-by: Robert Phillips <robertphillips@google.com>
Commit-Queue: Greg Daniel <egdaniel@google.com>
diff --git a/src/gpu/GrContext.cpp b/src/gpu/GrContext.cpp
index 672d380..379e149 100644
--- a/src/gpu/GrContext.cpp
+++ b/src/gpu/GrContext.cpp
@@ -405,7 +405,7 @@
}
return fGpu->createBackendTexture({width, height}, backendFormat, renderable,
- mipMapped, isProtected, nullptr, nullptr, nullptr);
+ mipMapped, isProtected);
}
GrBackendTexture GrContext::createBackendTexture(int width, int height,
@@ -497,6 +497,31 @@
return result;
}
+static GrBackendTexture create_and_update_backend_texture(GrContext* context,
+ SkISize dimensions,
+ const GrBackendFormat& backendFormat,
+ GrMipMapped mipMapped,
+ GrRenderable renderable,
+ GrProtected isProtected,
+ GrGpuFinishedProc finishedProc,
+ GrGpuFinishedContext finishedContext,
+ const GrGpu::BackendTextureData* data) {
+ GrGpu* gpu = context->priv().getGpu();
+
+ GrBackendTexture beTex = gpu->createBackendTexture(dimensions, backendFormat, renderable,
+ mipMapped, isProtected);
+ if (!beTex.isValid()) {
+ return {};
+ }
+
+ if (!context->priv().getGpu()->updateBackendTexture(beTex, finishedProc, finishedContext,
+ data)) {
+ context->deleteBackendTexture(beTex);
+ return {};
+ }
+ return beTex;
+}
+
GrBackendTexture GrContext::createBackendTexture(int width, int height,
const GrBackendFormat& backendFormat,
const SkColor4f& color,
@@ -517,8 +542,9 @@
}
GrGpu::BackendTextureData data(color);
- return fGpu->createBackendTexture({width, height}, backendFormat, renderable,
- mipMapped, isProtected, finishedProc, finishedContext, &data);
+ return create_and_update_backend_texture(this, {width, height}, backendFormat, mipMapped,
+ renderable, isProtected, finishedProc, finishedContext,
+ &data);
}
GrBackendTexture GrContext::createBackendTexture(int width, int height,
@@ -592,8 +618,9 @@
GrBackendFormat backendFormat = this->defaultBackendFormat(colorType, renderable);
GrGpu::BackendTextureData data(srcData);
- return fGpu->createBackendTexture({baseWidth, baseHeight}, backendFormat, renderable,
- mipMapped, isProtected, finishedProc, finishedContext, &data);
+ return create_and_update_backend_texture(this, {baseWidth, baseHeight}, backendFormat,
+ mipMapped, renderable, isProtected, finishedProc,
+ finishedContext, &data);
}
//////////////////////////////////////////////////////////////////////////////
diff --git a/src/gpu/GrGpu.cpp b/src/gpu/GrGpu.cpp
index 0749246..e57e62c 100644
--- a/src/gpu/GrGpu.cpp
+++ b/src/gpu/GrGpu.cpp
@@ -844,16 +844,7 @@
const GrBackendFormat& format,
GrRenderable renderable,
GrMipMapped mipMapped,
- GrProtected isProtected,
- GrGpuFinishedProc finishedProc,
- GrGpuFinishedContext finishedContext,
- const BackendTextureData* data) {
-
- sk_sp<GrRefCntedCallback> callback;
- if (finishedProc) {
- callback.reset(new GrRefCntedCallback(finishedProc, finishedContext));
- }
-
+ GrProtected isProtected) {
const GrCaps* caps = this->caps();
if (!format.isValid()) {
@@ -865,13 +856,6 @@
return {};
}
- if (data && data->type() == BackendTextureData::Type::kPixmaps) {
- auto ct = SkColorTypeToGrColorType(data->pixmap(0).colorType());
- if (!caps->areColorTypeAndFormatCompatible(ct, format)) {
- return {};
- }
- }
-
if (dimensions.isEmpty() || dimensions.width() > caps->maxTextureSize() ||
dimensions.height() > caps->maxTextureSize()) {
return {};
@@ -881,12 +865,42 @@
return {};
}
- if (!MipMapsAreCorrect(dimensions, mipMapped, data)) {
- return {};
+ return this->onCreateBackendTexture(dimensions, format, renderable, mipMapped, isProtected);
+}
+
+bool GrGpu::updateBackendTexture(const GrBackendTexture& backendTexture,
+ GrGpuFinishedProc finishedProc,
+ GrGpuFinishedContext finishedContext,
+ const BackendTextureData* data) {
+ SkASSERT(data);
+ const GrCaps* caps = this->caps();
+
+ sk_sp<GrRefCntedCallback> callback;
+ if (finishedProc) {
+ callback.reset(new GrRefCntedCallback(finishedProc, finishedContext));
}
- return this->onCreateBackendTexture(dimensions, format, renderable, mipMapped,
- isProtected, std::move(callback), data);
+ if (!backendTexture.isValid()) {
+ return false;
+ }
+
+ if (data->type() == BackendTextureData::Type::kPixmaps) {
+ auto ct = SkColorTypeToGrColorType(data->pixmap(0).colorType());
+ if (!caps->areColorTypeAndFormatCompatible(ct, backendTexture.getBackendFormat())) {
+ return false;
+ }
+ }
+
+ if (backendTexture.hasMipMaps() && !this->caps()->mipMapSupport()) {
+ return false;
+ }
+
+ GrMipMapped mipMapped = backendTexture.hasMipMaps() ? GrMipMapped::kYes : GrMipMapped::kNo;
+ if (!MipMapsAreCorrect(backendTexture.dimensions(), mipMapped, data)) {
+ return false;
+ }
+
+ return this->onUpdateBackendTexture(backendTexture, std::move(callback), data);
}
GrBackendTexture GrGpu::createCompressedBackendTexture(SkISize dimensions,
diff --git a/src/gpu/GrGpu.h b/src/gpu/GrGpu.h
index 1405093..ea9f531 100644
--- a/src/gpu/GrGpu.h
+++ b/src/gpu/GrGpu.h
@@ -597,10 +597,12 @@
const GrBackendFormat&,
GrRenderable,
GrMipMapped,
- GrProtected,
- GrGpuFinishedProc finishedProc,
- GrGpuFinishedContext finishedContext,
- const BackendTextureData*);
+ GrProtected);
+
+ bool updateBackendTexture(const GrBackendTexture&,
+ GrGpuFinishedProc finishedProc,
+ GrGpuFinishedContext finishedContext,
+ const BackendTextureData*);
/**
* Same as the createBackendTexture case except compressed backend textures can
@@ -719,14 +721,16 @@
const GrBackendFormat&,
GrRenderable,
GrMipMapped,
- GrProtected,
- sk_sp<GrRefCntedCallback> finishedCallback,
- const BackendTextureData*) = 0;
+ GrProtected) = 0;
virtual GrBackendTexture onCreateCompressedBackendTexture(
SkISize dimensions, const GrBackendFormat&, GrMipMapped, GrProtected,
sk_sp<GrRefCntedCallback> finishedCallback, const BackendTextureData*) = 0;
+ virtual bool onUpdateBackendTexture(const GrBackendTexture&,
+ sk_sp<GrRefCntedCallback> finishedCallback,
+ const BackendTextureData*) = 0;
+
// called when the 3D context state is unknown. Subclass should emit any
// assumed 3D context state and dirty any state cache.
virtual void onResetContext(uint32_t resetBits) = 0;
diff --git a/src/gpu/d3d/GrD3DGpu.cpp b/src/gpu/d3d/GrD3DGpu.cpp
index 2725761..fb79434 100644
--- a/src/gpu/d3d/GrD3DGpu.cpp
+++ b/src/gpu/d3d/GrD3DGpu.cpp
@@ -787,13 +787,8 @@
GrRenderable renderable,
GrMipMapped mipMapped,
GrD3DTextureResourceInfo* info,
- GrProtected isProtected,
- sk_sp<GrRefCntedCallback> finishedCallback,
- const BackendTextureData* data) {
+ GrProtected isProtected) {
SkASSERT(texturable == GrTexturable::kYes || renderable == GrRenderable::kYes);
- if (texturable == GrTexturable::kNo) {
- SkASSERT(!data && mipMapped == GrMipMapped::kNo);
- }
if (this->protectedContext() != (isProtected == GrProtected::kYes)) {
return false;
@@ -820,7 +815,7 @@
D3D12_RESOURCE_DESC resourceDesc = {};
resourceDesc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D;
- resourceDesc.Alignment = 0; // use default alignment
+ resourceDesc.Alignment = 0; // use default alignment
resourceDesc.Width = dimensions.fWidth;
resourceDesc.Height = dimensions.fHeight;
resourceDesc.DepthOrArraySize = 1;
@@ -829,7 +824,7 @@
resourceDesc.SampleDesc.Count = 1;
// quality levels are only supported for tiled resources so ignore for now
resourceDesc.SampleDesc.Quality = GrD3DTextureResource::kDefaultQualityLevel;
- resourceDesc.Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN; // use driver-selected swizzle
+ resourceDesc.Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN; // use driver-selected swizzle
resourceDesc.Flags = usageFlags;
D3D12_CLEAR_VALUE* clearValuePtr = nullptr;
@@ -844,21 +839,15 @@
clearValuePtr = &clearValue;
}
- D3D12_RESOURCE_STATES initialState =
- (renderable == GrRenderable::kYes) && !data ? D3D12_RESOURCE_STATE_RENDER_TARGET :
- D3D12_RESOURCE_STATE_COPY_DEST;
+ D3D12_RESOURCE_STATES initialState = (renderable == GrRenderable::kYes)
+ ? D3D12_RESOURCE_STATE_RENDER_TARGET
+ : D3D12_RESOURCE_STATE_COPY_DEST;
if (!GrD3DTextureResource::InitTextureResourceInfo(this, resourceDesc, initialState,
isProtected, clearValuePtr, info)) {
SkDebugf("Failed to init texture resource info\n");
return false;
}
- if (!data) {
- return true;
- }
-
- // TODO: upload the data and handle finished callback
-
return true;
}
@@ -866,9 +855,7 @@
const GrBackendFormat& format,
GrRenderable renderable,
GrMipMapped mipMapped,
- GrProtected isProtected,
- sk_sp<GrRefCntedCallback> finishedCallback,
- const BackendTextureData* data) {
+ GrProtected isProtected) {
this->handleDirtyContext();
const GrD3DCaps& caps = this->d3dCaps();
@@ -890,14 +877,20 @@
GrD3DTextureResourceInfo info;
if (!this->createTextureResourceForBackendSurface(dxgiFormat, dimensions, GrTexturable::kYes,
renderable, mipMapped,
- &info, isProtected,
- std::move(finishedCallback), data)) {
+ &info, isProtected)) {
return {};
}
return GrBackendTexture(dimensions.width(), dimensions.height(), info);
}
+bool GrD3DGpu::onUpdateBackendTexture(const GrBackendTexture& backendTexture,
+ sk_sp<GrRefCntedCallback> finishedCallback,
+ const BackendTextureData* data) {
+ // TODO: handle finishedCallback and data upload
+ return true;
+}
+
GrBackendTexture GrD3DGpu::onCreateCompressedBackendTexture(
SkISize dimensions, const GrBackendFormat& format, GrMipMapped mipMapped,
GrProtected isProtected, sk_sp<GrRefCntedCallback> finishedCallback,
@@ -923,8 +916,7 @@
GrD3DTextureResourceInfo info;
if (!this->createTextureResourceForBackendSurface(dxgiFormat, dimensions, GrTexturable::kYes,
GrRenderable::kNo, mipMapped,
- &info, isProtected,
- std::move(finishedCallback), data)) {
+ &info, isProtected)) {
return {};
}
@@ -968,7 +960,7 @@
GrD3DTextureResourceInfo info;
if (!this->createTextureResourceForBackendSurface(dxgiFormat, { w, h }, GrTexturable::kNo,
GrRenderable::kYes, GrMipMapped::kNo,
- &info, GrProtected::kNo, nullptr, nullptr)) {
+ &info, GrProtected::kNo)) {
return {};
}
diff --git a/src/gpu/d3d/GrD3DGpu.h b/src/gpu/d3d/GrD3DGpu.h
index 405c148..3c1c973 100644
--- a/src/gpu/d3d/GrD3DGpu.h
+++ b/src/gpu/d3d/GrD3DGpu.h
@@ -196,9 +196,12 @@
const GrBackendFormat&,
GrRenderable,
GrMipMapped,
- GrProtected,
- sk_sp<GrRefCntedCallback> finishedCallback,
- const BackendTextureData*) override;
+ GrProtected) override;
+
+ bool onUpdateBackendTexture(const GrBackendTexture&,
+ sk_sp<GrRefCntedCallback> finishedCallback,
+ const BackendTextureData*) override;
+
GrBackendTexture onCreateCompressedBackendTexture(SkISize dimensions,
const GrBackendFormat&,
GrMipMapped,
@@ -227,9 +230,7 @@
GrRenderable renderable,
GrMipMapped mipMapped,
GrD3DTextureResourceInfo* info,
- GrProtected isProtected,
- sk_sp<GrRefCntedCallback> finishedCallback,
- const BackendTextureData* data);
+ GrProtected isProtected);
gr_cp<ID3D12Device> fDevice;
gr_cp<ID3D12CommandQueue> fQueue;
diff --git a/src/gpu/dawn/GrDawnGpu.cpp b/src/gpu/dawn/GrDawnGpu.cpp
index 0aba908..2722b40 100644
--- a/src/gpu/dawn/GrDawnGpu.cpp
+++ b/src/gpu/dawn/GrDawnGpu.cpp
@@ -302,9 +302,7 @@
const GrBackendFormat& backendFormat,
GrRenderable renderable,
GrMipMapped mipMapped,
- GrProtected isProtected,
- sk_sp<GrRefCntedCallback> finishedCallback,
- const BackendTextureData* data) {
+ GrProtected isProtected) {
wgpu::TextureFormat format;
if (!backendFormat.asDawnFormat(&format)) {
return GrBackendTexture();
@@ -338,8 +336,21 @@
wgpu::Texture tex = this->device().CreateTexture(&desc);
- size_t bpp = GrDawnBytesPerPixel(format);
- size_t baseLayerSize = bpp * dimensions.width() * dimensions.height();
+ GrDawnTextureInfo info;
+ info.fTexture = tex;
+ info.fFormat = desc.format;
+ info.fLevelCount = desc.mipLevelCount;
+ return GrBackendTexture(dimensions.width(), dimensions.height(), info);
+}
+
+bool GrDawnGpu::onUpdateBackendTexture(const GrBackendTexture& backendTexture,
+ sk_sp<GrRefCntedCallback> finishedCallback,
+ const BackendTextureData* data) {
+ GrDawnTextureInfo info;
+ SkAssertResult(backendTexture.getDawnTextureInfo(&info));
+
+ size_t bpp = GrDawnBytesPerPixel(info.fFormat);
+ size_t baseLayerSize = bpp * backendTexture.width() * backendTexture.height();
const void* pixels;
SkAutoMalloc defaultStorage(baseLayerSize);
if (data && data->type() == BackendTextureData::Type::kPixmaps) {
@@ -350,8 +361,8 @@
}
wgpu::Device device = this->device();
wgpu::CommandEncoder copyEncoder = this->getCopyEncoder();
- int w = dimensions.width(), h = dimensions.height();
- for (uint32_t i = 0; i < desc.mipLevelCount; i++) {
+ int w = backendTexture.width(), h = backendTexture.height();
+ for (uint32_t i = 0; i < info.fLevelCount; i++) {
size_t origRowBytes = bpp * w;
size_t rowBytes = GrDawnRoundRowBytes(origRowBytes);
size_t size = rowBytes * h;
@@ -373,19 +384,15 @@
srcBuffer.bytesPerRow = rowBytes;
srcBuffer.rowsPerImage = h;
wgpu::TextureCopyView dstTexture;
- dstTexture.texture = tex;
+ dstTexture.texture = info.fTexture;
dstTexture.mipLevel = i;
dstTexture.origin = {0, 0, 0};
- wgpu::Extent3D copySize = {(uint32_t) w, (uint32_t) h, 1};
+ wgpu::Extent3D copySize = {(uint32_t)w, (uint32_t)h, 1};
copyEncoder.CopyBufferToTexture(&srcBuffer, &dstTexture, ©Size);
w = std::max(1, w / 2);
h = std::max(1, h / 2);
}
- GrDawnTextureInfo info;
- info.fTexture = tex;
- info.fFormat = desc.format;
- info.fLevelCount = desc.mipLevelCount;
- return GrBackendTexture(dimensions.width(), dimensions.height(), info);
+ return true;
}
GrBackendTexture GrDawnGpu::onCreateCompressedBackendTexture(
diff --git a/src/gpu/dawn/GrDawnGpu.h b/src/gpu/dawn/GrDawnGpu.h
index 7745105..7b3a160 100644
--- a/src/gpu/dawn/GrDawnGpu.h
+++ b/src/gpu/dawn/GrDawnGpu.h
@@ -41,20 +41,6 @@
void xferBarrier(GrRenderTarget*, GrXferBarrierType) override {}
- GrBackendTexture onCreateBackendTexture(SkISize dimensions,
- const GrBackendFormat&,
- GrRenderable,
- GrMipMapped,
- GrProtected,
- sk_sp<GrRefCntedCallback> finishedCallback,
- const BackendTextureData*) override;
- GrBackendTexture onCreateCompressedBackendTexture(SkISize dimensions,
- const GrBackendFormat&,
- GrMipMapped,
- GrProtected,
- sk_sp<GrRefCntedCallback> finishedCallback,
- const BackendTextureData*) override;
-
void deleteBackendTexture(const GrBackendTexture&) override;
bool compile(const GrProgramDesc&, const GrProgramInfo&) override;
@@ -148,6 +134,23 @@
sk_sp<GrRenderTarget> onWrapBackendTextureAsRenderTarget(const GrBackendTexture&,
int sampleCnt) override;
+ GrBackendTexture onCreateBackendTexture(SkISize dimensions,
+ const GrBackendFormat&,
+ GrRenderable,
+ GrMipMapped,
+ GrProtected) override;
+
+ bool onUpdateBackendTexture(const GrBackendTexture&,
+ sk_sp<GrRefCntedCallback> finishedCallback,
+ const BackendTextureData*) override;
+
+ GrBackendTexture onCreateCompressedBackendTexture(SkISize dimensions,
+ const GrBackendFormat&,
+ GrMipMapped,
+ GrProtected,
+ sk_sp<GrRefCntedCallback> finishedCallback,
+ const BackendTextureData*) override;
+
sk_sp<GrGpuBuffer> onCreateBuffer(size_t size, GrGpuBufferType type, GrAccessPattern,
const void* data) override;
diff --git a/src/gpu/gl/GrGLGpu.cpp b/src/gpu/gl/GrGLGpu.cpp
index e3dcf10..a2328da 100644
--- a/src/gpu/gl/GrGLGpu.cpp
+++ b/src/gpu/gl/GrGLGpu.cpp
@@ -3506,9 +3506,7 @@
const GrBackendFormat& format,
GrRenderable renderable,
GrMipMapped mipMapped,
- GrProtected isProtected,
- sk_sp<GrRefCntedCallback> finishedCallback,
- const BackendTextureData* data) {
+ GrProtected isProtected) {
// We don't support protected textures in GL.
if (isProtected == GrProtected::kYes) {
return {};
@@ -3543,50 +3541,6 @@
return {};
}
- SkASSERT(!data || data->type() != BackendTextureData::Type::kCompressed);
- if (data && data->type() == BackendTextureData::Type::kPixmaps) {
- SkTDArray<GrMipLevel> texels;
- GrColorType colorType = SkColorTypeToGrColorType(data->pixmap(0).colorType());
- texels.append(numMipLevels);
- for (int i = 0; i < numMipLevels; ++i) {
- texels[i] = {data->pixmap(i).addr(), data->pixmap(i).rowBytes()};
- }
- if (!this->uploadTexData(glFormat, colorType, dimensions.width(), dimensions.height(),
- GR_GL_TEXTURE_2D, 0, 0, dimensions.width(), dimensions.height(),
- colorType, texels.begin(), texels.count())) {
- GL_CALL(DeleteTextures(1, &info.fID));
- return {};
- }
- } else if (data && data->type() == BackendTextureData::Type::kColor) {
- // TODO: Unify this with the clear texture code in onCreateTexture().
- GrColorType colorType;
- GrGLenum externalFormat, externalType;
- this->glCaps().getTexSubImageDefaultFormatTypeAndColorType(glFormat, &externalFormat,
- &externalType, &colorType);
- if (colorType == GrColorType::kUnknown) {
- GL_CALL(DeleteTextures(1, &info.fID));
- return {};
- }
-
- // Make one tight image at the base size and reuse it for smaller levels.
- GrImageInfo ii(colorType, kUnpremul_SkAlphaType, nullptr, dimensions);
- auto rb = ii.minRowBytes();
- std::unique_ptr<char[]> pixelStorage(new char[rb * dimensions.height()]);
- if (!GrClearImage(ii, pixelStorage.get(), rb, data->color())) {
- GL_CALL(DeleteTextures(1, &info.fID));
- return {};
- }
-
- GL_CALL(PixelStorei(GR_GL_UNPACK_ALIGNMENT, 1));
- SkISize levelDimensions = dimensions;
- for (int i = 0; i < numMipLevels; ++i) {
- GL_CALL(TexSubImage2D(GR_GL_TEXTURE_2D, i, 0, 0, levelDimensions.width(),
- levelDimensions.height(), externalFormat, externalType,
- pixelStorage.get()));
- levelDimensions = {std::max(1, levelDimensions.width() /2),
- std::max(1, levelDimensions.height()/2)};
- }
- }
// Unbind this texture from the scratch texture unit.
this->bindTextureToScratchUnit(GR_GL_TEXTURE_2D, 0);
@@ -3599,6 +3553,73 @@
std::move(parameters));
}
+bool GrGLGpu::onUpdateBackendTexture(const GrBackendTexture& backendTexture,
+ sk_sp<GrRefCntedCallback> finishedCallback,
+ const BackendTextureData* data) {
+ GrGLTextureInfo info;
+ SkAssertResult(backendTexture.getGLTextureInfo(&info));
+
+ int numMipLevels = 1;
+ if (backendTexture.hasMipMaps()) {
+ numMipLevels =
+ SkMipMap::ComputeLevelCount(backendTexture.width(), backendTexture.height()) + 1;
+ }
+
+ GrGLFormat glFormat = GrGLFormatFromGLEnum(info.fFormat);
+
+ this->bindTextureToScratchUnit(GR_GL_TEXTURE_2D, info.fID);
+
+ SkASSERT(data->type() != BackendTextureData::Type::kCompressed);
+ if (data->type() == BackendTextureData::Type::kPixmaps) {
+ SkTDArray<GrMipLevel> texels;
+ GrColorType colorType = SkColorTypeToGrColorType(data->pixmap(0).colorType());
+ texels.append(numMipLevels);
+ for (int i = 0; i < numMipLevels; ++i) {
+ texels[i] = {data->pixmap(i).addr(), data->pixmap(i).rowBytes()};
+ }
+ if (!this->uploadTexData(glFormat, colorType, backendTexture.width(),
+ backendTexture.height(), GR_GL_TEXTURE_2D, 0, 0,
+ backendTexture.width(), backendTexture.height(),
+ colorType, texels.begin(), texels.count())) {
+ GL_CALL(DeleteTextures(1, &info.fID));
+ return false;
+ }
+ } else if (data && data->type() == BackendTextureData::Type::kColor) {
+ // TODO: Unify this with the clear texture code in onCreateTexture().
+ GrColorType colorType;
+ GrGLenum externalFormat, externalType;
+ this->glCaps().getTexSubImageDefaultFormatTypeAndColorType(glFormat, &externalFormat,
+ &externalType, &colorType);
+ if (colorType == GrColorType::kUnknown) {
+ GL_CALL(DeleteTextures(1, &info.fID));
+ return false;
+ }
+
+ // Make one tight image at the base size and reuse it for smaller levels.
+ GrImageInfo ii(colorType, kUnpremul_SkAlphaType, nullptr, backendTexture.dimensions());
+ auto rb = ii.minRowBytes();
+ std::unique_ptr<char[]> pixelStorage(new char[rb * backendTexture.height()]);
+ if (!GrClearImage(ii, pixelStorage.get(), rb, data->color())) {
+ GL_CALL(DeleteTextures(1, &info.fID));
+ return false;
+ }
+
+ GL_CALL(PixelStorei(GR_GL_UNPACK_ALIGNMENT, 1));
+ SkISize levelDimensions = backendTexture.dimensions();
+ for (int i = 0; i < numMipLevels; ++i) {
+ GL_CALL(TexSubImage2D(GR_GL_TEXTURE_2D, i, 0, 0, levelDimensions.width(),
+ levelDimensions.height(), externalFormat, externalType,
+ pixelStorage.get()));
+ levelDimensions = {std::max(1, levelDimensions.width() / 2),
+ std::max(1, levelDimensions.height() / 2)};
+ }
+ }
+
+ // Unbind this texture from the scratch texture unit.
+ this->bindTextureToScratchUnit(GR_GL_TEXTURE_2D, 0);
+ return true;
+}
+
void GrGLGpu::deleteBackendTexture(const GrBackendTexture& tex) {
SkASSERT(GrBackendApi::kOpenGL == tex.backend());
diff --git a/src/gpu/gl/GrGLGpu.h b/src/gpu/gl/GrGLGpu.h
index 8b8b9eb..ca47061 100644
--- a/src/gpu/gl/GrGLGpu.h
+++ b/src/gpu/gl/GrGLGpu.h
@@ -97,7 +97,6 @@
attribState->enableVertexArrays(this, numAttribs, primitiveRestart);
return attribState;
}
- GrGLAttribArrayState* bindInternalVertexArray(const GrBuffer* indexBuffer, GrPrimitiveRestart);
// Applies any necessary workarounds and returns the GL primitive type to use in draw calls.
GrGLenum prepareToDraw(GrPrimitiveType primitiveType);
@@ -199,9 +198,7 @@
const GrBackendFormat&,
GrRenderable,
GrMipMapped,
- GrProtected,
- sk_sp<GrRefCntedCallback> finishedCallback,
- const BackendTextureData*) override;
+ GrProtected) override;
GrBackendTexture onCreateCompressedBackendTexture(SkISize dimensions,
const GrBackendFormat&,
@@ -210,6 +207,10 @@
sk_sp<GrRefCntedCallback> finishedCallback,
const BackendTextureData*) override;
+ bool onUpdateBackendTexture(const GrBackendTexture&,
+ sk_sp<GrRefCntedCallback> finishedCallback,
+ const BackendTextureData*) override;
+
void onResetContext(uint32_t resetBits) override;
void onResetTextureBindings() override;
@@ -328,8 +329,6 @@
bool copySurfaceAsBlitFramebuffer(GrSurface* dst, GrSurface* src, const SkIRect& srcRect,
const SkIPoint& dstPoint);
- static bool BlendCoeffReferencesConstant(GrBlendCoeff coeff);
-
class ProgramCache : public ::SkNoncopyable {
public:
ProgramCache(GrGLGpu* gpu);
diff --git a/src/gpu/mock/GrMockGpu.cpp b/src/gpu/mock/GrMockGpu.cpp
index ad62c4b..3348c4b 100644
--- a/src/gpu/mock/GrMockGpu.cpp
+++ b/src/gpu/mock/GrMockGpu.cpp
@@ -276,9 +276,7 @@
const GrBackendFormat& format,
GrRenderable,
GrMipMapped mipMapped,
- GrProtected,
- sk_sp<GrRefCntedCallback> finishedCallback,
- const BackendTextureData*) {
+ GrProtected) {
SkImage::CompressionType compression = format.asMockCompressionType();
if (compression != SkImage::CompressionType::kNone) {
return {}; // should go through onCreateCompressedBackendTexture
diff --git a/src/gpu/mock/GrMockGpu.h b/src/gpu/mock/GrMockGpu.h
index 8d6631f..05fdda7 100644
--- a/src/gpu/mock/GrMockGpu.h
+++ b/src/gpu/mock/GrMockGpu.h
@@ -147,9 +147,14 @@
const GrBackendFormat&,
GrRenderable,
GrMipMapped,
- GrProtected,
- sk_sp<GrRefCntedCallback> finishedCallback,
- const BackendTextureData*) override;
+ GrProtected) override;
+
+ bool onUpdateBackendTexture(const GrBackendTexture&,
+ sk_sp<GrRefCntedCallback> finishedCallback,
+ const BackendTextureData*) override {
+ return true;
+ }
+
GrBackendTexture onCreateCompressedBackendTexture(SkISize dimensions,
const GrBackendFormat&,
GrMipMapped,
diff --git a/src/gpu/mtl/GrMtlGpu.h b/src/gpu/mtl/GrMtlGpu.h
index d07e3aa..191c0ba 100644
--- a/src/gpu/mtl/GrMtlGpu.h
+++ b/src/gpu/mtl/GrMtlGpu.h
@@ -130,9 +130,11 @@
const GrBackendFormat&,
GrRenderable,
GrMipMapped,
- GrProtected,
- sk_sp<GrRefCntedCallback> finishedCallback,
- const BackendTextureData*) override;
+ GrProtected) override;
+
+ bool onUpdateBackendTexture(const GrBackendTexture&,
+ sk_sp<GrRefCntedCallback> finishedCallback,
+ const BackendTextureData*) override;
GrBackendTexture onCreateCompressedBackendTexture(SkISize dimensions,
const GrBackendFormat&,
@@ -223,8 +225,7 @@
GrTexturable,
GrRenderable,
GrMipMapped,
- GrMtlTextureInfo*,
- const BackendTextureData*);
+ GrMtlTextureInfo*);
#if GR_TEST_UTILS
void testingOnly_startCapture() override;
diff --git a/src/gpu/mtl/GrMtlGpu.mm b/src/gpu/mtl/GrMtlGpu.mm
index b99ba25..420bb89 100644
--- a/src/gpu/mtl/GrMtlGpu.mm
+++ b/src/gpu/mtl/GrMtlGpu.mm
@@ -775,12 +775,8 @@
GrTexturable texturable,
GrRenderable renderable,
GrMipMapped mipMapped,
- GrMtlTextureInfo* info,
- const BackendTextureData* data) {
+ GrMtlTextureInfo* info) {
SkASSERT(texturable == GrTexturable::kYes || renderable == GrRenderable::kYes);
- if (texturable == GrTexturable::kNo) {
- SkASSERT(!data && mipMapped == GrMipMapped::kNo);
- }
if (texturable == GrTexturable::kYes && !fMtlCaps->isFormatTexturable(mtlFormat)) {
return false;
@@ -804,13 +800,37 @@
desc.usage |= renderable == GrRenderable::kYes ? MTLTextureUsageRenderTarget : 0;
}
id<MTLTexture> testTexture = [fDevice newTextureWithDescriptor: desc];
+ info->fTexture.reset(GrRetainPtrFromId(testTexture));
+ return true;
+}
- if (!data) {
- info->fTexture.reset(GrRetainPtrFromId(testTexture));
+GrBackendTexture GrMtlGpu::onCreateBackendTexture(SkISize dimensions,
+ const GrBackendFormat& format,
+ GrRenderable renderable,
+ GrMipMapped mipMapped,
+ GrProtected isProtected) {
+ const MTLPixelFormat mtlFormat = GrBackendFormatAsMTLPixelFormat(format);
- return true;
+ GrMtlTextureInfo info;
+ if (!this->createMtlTextureForBackendSurface(mtlFormat, dimensions, GrTexturable::kYes,
+ renderable, mipMapped, &info)) {
+ return {};
}
+ GrBackendTexture backendTex(dimensions.width(), dimensions.height(), mipMapped, info);
+ return backendTex;
+}
+
+bool GrMtlGpu::onUpdateBackendTexture(const GrBackendTexture& backendTexture,
+ sk_sp<GrRefCntedCallback> finishedCallback,
+ const BackendTextureData* data) {
+ GrMtlTextureInfo info;
+ SkAssertResult(backendTexture.getMtlTextureInfo(&info));
+
+ id<MTLTexture> mtlTexture = GrGetMTLTexture(info.fTexture.get());
+
+ const MTLPixelFormat mtlFormat = mtlTexture.pixelFormat;
+
// Create the transfer buffer
NSUInteger options = 0; // TODO: consider other options here
if (@available(macOS 10.11, iOS 9.0, *)) {
@@ -821,10 +841,8 @@
#endif
}
- int numMipLevels = 1;
- if (mipMapped == GrMipMapped::kYes) {
- numMipLevels = SkMipMap::ComputeLevelCount(dimensions.width(), dimensions.height()) + 1;
- }
+ int numMipLevels = mtlTexture.mipmapLevelCount;
+ GrMipMapped mipMapped = numMipLevels > 1 ? GrMipMapped::kYes : GrMipMapped::kNo;
SkImage::CompressionType compression = GrMtlFormatToCompressionType(mtlFormat);
@@ -839,12 +857,13 @@
if (compression == SkImage::CompressionType::kNone) {
size_t bytesPerPixel = fMtlCaps->bytesPerPixel(mtlFormat);
- transferBufferSize = GrComputeTightCombinedBufferSize(bytesPerPixel, dimensions,
+ transferBufferSize = GrComputeTightCombinedBufferSize(bytesPerPixel,
+ backendTexture.dimensions(),
&individualMipOffsets,
numMipLevels);
} else {
- transferBufferSize = SkCompressedDataSize(compression, dimensions,
+ transferBufferSize = SkCompressedDataSize(compression, backendTexture.dimensions(),
&individualMipOffsets,
mipMapped == GrMipMapped::kYes);
}
@@ -875,9 +894,9 @@
if (colorType == GrColorType::kUnknown) {
return false;
}
- GrImageInfo ii(colorType, kUnpremul_SkAlphaType, nullptr, dimensions);
+ GrImageInfo ii(colorType, kUnpremul_SkAlphaType, nullptr, backendTexture.dimensions());
auto rb = ii.minRowBytes();
- transferBufferSize = rb*dimensions.height();
+ transferBufferSize = rb*backendTexture.height();
transferBuffer = [fDevice newBufferWithLength: transferBufferSize
options: options];
if (nil == transferBuffer) {
@@ -889,7 +908,7 @@
// Reuse the same buffer for all levels. Should be ok since we made the row bytes tight.
individualMipOffsets.push_back_n(numMipLevels, (size_t)0);
} else {
- transferBufferSize = SkCompressedDataSize(compression, dimensions,
+ transferBufferSize = SkCompressedDataSize(compression, backendTexture.dimensions(),
&individualMipOffsets,
mipMapped == GrMipMapped::kYes);
SkASSERT(individualMipOffsets.count() == numMipLevels);
@@ -901,7 +920,8 @@
}
char* buffer = (char*)transferBuffer.contents;
- GrFillInCompressedData(compression, dimensions, mipMapped, buffer, data->color());
+ GrFillInCompressedData(compression, backendTexture.dimensions(), mipMapped, buffer,
+ data->color());
}
}
@@ -911,7 +931,7 @@
id<MTLCommandBuffer> cmdBuffer = [fQueue commandBuffer];
id<MTLBlitCommandEncoder> blitCmdEncoder = [cmdBuffer blitCommandEncoder];
- SkISize levelDimensions(dimensions);
+ SkISize levelDimensions(backendTexture.dimensions());
for (int currentMipLevel = 0; currentMipLevel < numMipLevels; currentMipLevel++) {
size_t levelRowBytes;
size_t levelSize;
@@ -934,7 +954,7 @@
sourceBytesPerImage: levelSize
sourceSize: MTLSizeMake(levelDimensions.width(),
levelDimensions.height(), 1)
- toTexture: testTexture
+ toTexture: mtlTexture
destinationSlice: 0
destinationLevel: currentMipLevel
destinationOrigin: origin];
@@ -950,29 +970,9 @@
[cmdBuffer commit];
transferBuffer = nil;
- info->fTexture.reset(GrRetainPtrFromId(testTexture));
return true;
}
-GrBackendTexture GrMtlGpu::onCreateBackendTexture(SkISize dimensions,
- const GrBackendFormat& format,
- GrRenderable renderable,
- GrMipMapped mipMapped,
- GrProtected isProtected,
- sk_sp<GrRefCntedCallback> finishedCallback,
- const BackendTextureData* data) {
- const MTLPixelFormat mtlFormat = GrBackendFormatAsMTLPixelFormat(format);
-
- GrMtlTextureInfo info;
- if (!this->createMtlTextureForBackendSurface(mtlFormat, dimensions, GrTexturable::kYes,
- renderable, mipMapped, &info, data)) {
- return {};
- }
-
- GrBackendTexture backendTex(dimensions.width(), dimensions.height(), mipMapped, info);
- return backendTex;
-}
-
GrBackendTexture GrMtlGpu::onCreateCompressedBackendTexture(
SkISize dimensions, const GrBackendFormat& format, GrMipMapped mipMapped,
GrProtected isProtected, sk_sp<GrRefCntedCallback> finishedCallback,
@@ -981,11 +981,19 @@
GrMtlTextureInfo info;
if (!this->createMtlTextureForBackendSurface(mtlFormat, dimensions, GrTexturable::kYes,
- GrRenderable::kNo, mipMapped, &info, data)) {
+ GrRenderable::kNo, mipMapped, &info)) {
return {};
}
GrBackendTexture backendTex(dimensions.width(), dimensions.height(), mipMapped, info);
+
+ if (data) {
+ if (!this->onUpdateBackendTexture(backendTex, std::move(finishedCallback), data)) {
+ this->deleteBackendTexture(backendTex);
+ return {};
+ }
+ }
+
return backendTex;
}
@@ -1030,7 +1038,7 @@
GrMtlTextureInfo info;
if (!this->createMtlTextureForBackendSurface(format, {w, h}, GrTexturable::kNo,
GrRenderable::kYes,
- GrMipMapped::kNo, &info, nullptr)) {
+ GrMipMapped::kNo, &info)) {
return {};
}
diff --git a/src/gpu/vk/GrVkGpu.cpp b/src/gpu/vk/GrVkGpu.cpp
index 41a1b99..6b146d8 100644
--- a/src/gpu/vk/GrVkGpu.cpp
+++ b/src/gpu/vk/GrVkGpu.cpp
@@ -1570,13 +1570,8 @@
GrRenderable renderable,
GrMipMapped mipMapped,
GrVkImageInfo* info,
- GrProtected isProtected,
- sk_sp<GrRefCntedCallback> finishedCallback,
- const BackendTextureData* data) {
+ GrProtected isProtected) {
SkASSERT(texturable == GrTexturable::kYes || renderable == GrRenderable::kYes);
- if (texturable == GrTexturable::kNo) {
- SkASSERT(!data && mipMapped == GrMipMapped::kNo);
- }
if (fProtectedContext != isProtected) {
return false;
@@ -1622,39 +1617,36 @@
return false;
}
- if (!data) {
- return true;
- }
+ return true;
+}
- sk_sp<GrVkImageLayout> layout(new GrVkImageLayout(info->fImageLayout));
+bool GrVkGpu::onUpdateBackendTexture(const GrBackendTexture& backendTexture,
+ sk_sp<GrRefCntedCallback> finishedCallback,
+ const BackendTextureData* data) {
+ GrVkImageInfo info;
+ SkAssertResult(backendTexture.getVkImageInfo(&info));
- sk_sp<GrSurface> surface;
- GrVkImage* image = nullptr;
- if (texturable == GrTexturable::kYes) {
- surface = GrVkTexture::MakeWrappedTexture(this, dimensions, kBorrow_GrWrapOwnership,
- GrWrapCacheable::kNo, kRW_GrIOType, *info,
- layout);
- image = static_cast<GrVkTexture*>(surface->asTexture());
- } else {
- surface = GrVkRenderTarget::MakeWrappedRenderTarget(this, dimensions, 1, *info, layout);
- image = static_cast<GrVkRenderTarget*>(surface->asRenderTarget());
- }
- if (!surface) {
+ sk_sp<GrVkImageLayout> layout = backendTexture.getGrVkImageLayout();
+ SkASSERT(layout);
+ sk_sp<GrVkTexture> texture =
+ GrVkTexture::MakeWrappedTexture(this, backendTexture.dimensions(),
+ kBorrow_GrWrapOwnership, GrWrapCacheable::kNo,
+ kRW_GrIOType, info, layout);
+ if (!texture) {
return false;
}
- SkASSERT(image);
GrVkPrimaryCommandBuffer* cmdBuffer = this->getTempCommandBuffer();
if (!cmdBuffer) {
return false;
}
- image->setImageLayout(this, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_ACCESS_TRANSFER_WRITE_BIT,
- VK_PIPELINE_STAGE_TRANSFER_BIT, false);
+ texture->setImageLayout(this, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
+ VK_ACCESS_TRANSFER_WRITE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, false);
// Unfortunately, CmdClearColorImage doesn't work for compressed formats
bool fastPath = data->type() == BackendTextureData::Type::kColor &&
- !GrVkFormatIsCompressed(vkFormat);
+ !GrVkFormatIsCompressed(info.fFormat);
if (fastPath) {
SkASSERT(data->type() == BackendTextureData::Type::kColor);
@@ -1671,48 +1663,48 @@
range.baseArrayLayer = 0;
range.baseMipLevel = 0;
range.layerCount = 1;
- range.levelCount = numMipLevels;
- cmdBuffer->clearColorImage(this, image, &vkColor, 1, &range);
+ range.levelCount = info.fLevelCount;
+ cmdBuffer->clearColorImage(this, texture.get(), &vkColor, 1, &range);
} else {
SkTArray<VkBufferImageCopy> regions;
SkTArray<size_t> individualMipOffsets;
size_t combinedBufferSize = fill_in_regions(fVkCaps.get(), ®ions, &individualMipOffsets,
- vkFormat, dimensions, mipMapped, 0);
+ info.fFormat, backendTexture.dimensions(),
+ backendTexture.fMipMapped, 0);
sk_sp<GrVkTransferBuffer> transferBuffer =
- GrVkTransferBuffer::Make(this, combinedBufferSize, GrVkBuffer::kCopyRead_Type);
+ GrVkTransferBuffer::Make(this, combinedBufferSize, GrVkBuffer::kCopyRead_Type);
if (!transferBuffer) {
return false;
}
bool result;
if (data->type() == BackendTextureData::Type::kPixmaps) {
- result = copy_src_data(this, (char*)transferBuffer->map(), vkFormat,
- individualMipOffsets, data->pixmaps(), numMipLevels);
+ result = copy_src_data(this, (char*)transferBuffer->map(), info.fFormat,
+ individualMipOffsets, data->pixmaps(), info.fLevelCount);
} else if (data->type() == BackendTextureData::Type::kCompressed) {
result = copy_compressed_data(this, (char*)transferBuffer->map(),
data->compressedData(), data->compressedSize());
} else {
SkASSERT(data->type() == BackendTextureData::Type::kColor);
- SkImage::CompressionType compression = GrVkFormatToCompressionType(vkFormat);
+ SkImage::CompressionType compression = GrVkFormatToCompressionType(info.fFormat);
result = generate_compressed_data(this, (char*)transferBuffer->map(), compression,
- dimensions, mipMapped, data->color());
+ backendTexture.dimensions(),
+ backendTexture.fMipMapped, data->color());
}
transferBuffer->unmap();
- cmdBuffer->copyBufferToImage(this, transferBuffer.get(), image, image->currentLayout(),
- regions.count(), regions.begin());
+ cmdBuffer->copyBufferToImage(this, transferBuffer.get(), texture.get(),
+ texture->currentLayout(), regions.count(), regions.begin());
}
- if (texturable == GrTexturable::kYes) {
- // Change image layout to shader read since if we use this texture as a borrowed
- // texture within Ganesh we require that its layout be set to that
- image->setImageLayout(this, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
- VK_ACCESS_SHADER_READ_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,
- false);
- }
- info->fImageLayout = layout->getImageLayout();
+ // Change image layout to shader read since if we use this texture as a borrowed
+ // texture within Ganesh we require that its layout be set to that
+ texture->setImageLayout(this, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
+ VK_ACCESS_SHADER_READ_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,
+ false);
+
return this->submitTempCommandBuffer(kSkip_SyncQueue, std::move(finishedCallback));
}
@@ -1720,9 +1712,7 @@
const GrBackendFormat& format,
GrRenderable renderable,
GrMipMapped mipMapped,
- GrProtected isProtected,
- sk_sp<GrRefCntedCallback> finishedCallback,
- const BackendTextureData* data) {
+ GrProtected isProtected) {
this->handleDirtyContext();
const GrVkCaps& caps = this->vkCaps();
@@ -1748,8 +1738,7 @@
GrVkImageInfo info;
if (!this->createVkImageForBackendSurface(vkFormat, dimensions, GrTexturable::kYes,
renderable, mipMapped,
- &info, isProtected, std::move(finishedCallback),
- data)) {
+ &info, isProtected)) {
return {};
}
@@ -1785,12 +1774,19 @@
GrVkImageInfo info;
if (!this->createVkImageForBackendSurface(vkFormat, dimensions, GrTexturable::kYes,
GrRenderable::kNo, mipMapped,
- &info, isProtected, std::move(finishedCallback),
- data)) {
+ &info, isProtected)) {
return {};
}
- return GrBackendTexture(dimensions.width(), dimensions.height(), info);
+ GrBackendTexture beTex(dimensions.width(), dimensions.height(), info);
+
+ if (data) {
+ if (!this->onUpdateBackendTexture(beTex, std::move(finishedCallback), data)) {
+ this->deleteBackendTexture(beTex);
+ return {};
+ }
+ }
+ return beTex;
}
@@ -1895,7 +1891,7 @@
GrVkImageInfo info;
if (!this->createVkImageForBackendSurface(vkFormat, {w, h}, GrTexturable::kNo,
GrRenderable::kYes, GrMipMapped::kNo,
- &info, GrProtected::kNo, nullptr, nullptr)) {
+ &info, GrProtected::kNo)) {
return {};
}
diff --git a/src/gpu/vk/GrVkGpu.h b/src/gpu/vk/GrVkGpu.h
index 150cbb6..be7a03c 100644
--- a/src/gpu/vk/GrVkGpu.h
+++ b/src/gpu/vk/GrVkGpu.h
@@ -184,9 +184,7 @@
const GrBackendFormat&,
GrRenderable,
GrMipMapped,
- GrProtected,
- sk_sp<GrRefCntedCallback> finishedCallback,
- const BackendTextureData*) override;
+ GrProtected) override;
GrBackendTexture onCreateCompressedBackendTexture(SkISize dimensions,
const GrBackendFormat&,
GrMipMapped,
@@ -194,6 +192,10 @@
sk_sp<GrRefCntedCallback> finishedCallbacks,
const BackendTextureData*) override;
+ bool onUpdateBackendTexture(const GrBackendTexture&,
+ sk_sp<GrRefCntedCallback> finishedCallback,
+ const BackendTextureData*) override;
+
sk_sp<GrTexture> onCreateTexture(SkISize,
const GrBackendFormat&,
GrRenderable,
@@ -293,9 +295,7 @@
GrRenderable,
GrMipMapped,
GrVkImageInfo*,
- GrProtected,
- sk_sp<GrRefCntedCallback> finishedCallback,
- const BackendTextureData*);
+ GrProtected);
// Creates a new temporary primary command buffer that will be target of all subsequent commands
// until it is submitted via submitTempCommandBuffer. When the temp command buffer gets