Take origin when creating/updating backend texture using pixmaps.

Bug: skia:11042

Change-Id: I511c7556f97f19d7f162031c245019d2da33c129
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/341005
Commit-Queue: Brian Salomon <bsalomon@google.com>
Reviewed-by: Greg Daniel <egdaniel@google.com>
This commit is contained in:
Brian Salomon 2020-12-07 11:30:16 -05:00 committed by Skia Commit-Bot
parent 011a77357e
commit b5f880a3f6
13 changed files with 205 additions and 74 deletions

View File

@ -6,6 +6,11 @@ This file includes a list of high level updates for each milestone release.
Milestone 89
------------
* Add versions of GrDirectContext::createBackendTexture and updateBackendTexture
that take a GrSurfaceOrigin. The previous versions are deprecated.
https://review.skia.org/341005
* Remove support for deprecated kDontClipToLayer_SaveLayerFlag in SkCanvas::SaveLayerRec
https://review.skia.org/339988

View File

@ -103,20 +103,7 @@ private:
if (!bet.isValid()) {
return nullptr;
}
const SkPixmap* pm = &content.pixmap();
SkAutoPixmapStorage tempPM;
if (origin == kBottomLeft_GrSurfaceOrigin) {
tempPM.alloc(pm->info());
const uint32_t* src = pm->addr32();
uint32_t* dst = tempPM.writable_addr32(0, content.height() - 1);
for (int y = 0; y < content.height(); ++y,
src += pm->rowBytesAsPixels(),
dst -= tempPM.rowBytesAsPixels()) {
std::copy_n(src, content.width(), dst);
}
pm = &tempPM;
}
if (!dContext->updateBackendTexture(bet, pm, 1, nullptr, nullptr)) {
if (!dContext->updateBackendTexture(bet, content.pixmap(), origin, nullptr, nullptr)) {
dContext->deleteBackendTexture(bet);
}
return SkImage::MakeFromAdoptedTexture(dContext, bet, origin, kRGBA_8888_SkColorType);

View File

@ -506,26 +506,61 @@ public:
* If numLevels is 1 a non-mipMapped texture will result. If a mipMapped texture is desired
* the data for all the mipmap levels must be provided. In the mipmapped case all the
* colortypes of the provided pixmaps must be the same. Additionally, all the miplevels
* must be sized correctly (please see SkMipmap::ComputeLevelSize and ComputeLevelCount).
* must be sized correctly (please see SkMipmap::ComputeLevelSize and ComputeLevelCount). The
* GrSurfaceOrigin controls whether the pixmap data is vertically flipped in the texture.
* Note: the pixmap's alphatypes and colorspaces are ignored.
* For the Vulkan backend the layout of the created VkImage will be:
* VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL
*/
GrBackendTexture createBackendTexture(const SkPixmap srcData[], int numLevels,
GrRenderable, GrProtected,
GrBackendTexture createBackendTexture(const SkPixmap srcData[],
int numLevels,
GrSurfaceOrigin,
GrRenderable,
GrProtected,
GrGpuFinishedProc finishedProc = nullptr,
GrGpuFinishedContext finishedContext = nullptr);
// Helper version of above for a single level.
/**
* Convenience version createBackendTexture() that takes just a base level pixmap.
*/
GrBackendTexture createBackendTexture(const SkPixmap& srcData,
GrSurfaceOrigin textureOrigin,
GrRenderable renderable,
GrProtected isProtected,
GrGpuFinishedProc finishedProc = nullptr,
GrGpuFinishedContext finishedContext = nullptr) {
return this->createBackendTexture(&srcData, 1, renderable, isProtected, finishedProc,
finishedContext);
return this->createBackendTexture(&srcData, 1, textureOrigin, renderable, isProtected,
finishedProc, finishedContext);
}
// Deprecated versions that do not take origin and assume top-left.
GrBackendTexture createBackendTexture(const SkPixmap srcData[],
int numLevels,
GrRenderable renderable,
GrProtected isProtected,
GrGpuFinishedProc finishedProc = nullptr,
GrGpuFinishedContext finishedContext = nullptr) {
return this->createBackendTexture(srcData,
numLevels,
kTopLeft_GrSurfaceOrigin,
renderable,
isProtected,
finishedProc,
finishedContext);
}
GrBackendTexture createBackendTexture(const SkPixmap& srcData,
GrRenderable renderable,
GrProtected isProtected,
GrGpuFinishedProc finishedProc = nullptr,
GrGpuFinishedContext finishedContext = nullptr) {
return this->createBackendTexture(&srcData,
1,
renderable,
isProtected,
finishedProc,
finishedContext);
}
/**
* If possible, updates a backend texture to be filled to a particular color. The client should
* check the return value to see if the update was successful. The client can pass in a
@ -569,7 +604,8 @@ public:
* If the backend texture is mip mapped, the data for all the mipmap levels must be provided.
* In the mipmapped case all the colortypes of the provided pixmaps must be the same.
* Additionally, all the miplevels must be sized correctly (please see
* SkMipmap::ComputeLevelSize and ComputeLevelCount).
* SkMipmap::ComputeLevelSize and ComputeLevelCount). The GrSurfaceOrigin controls whether the
* pixmap data is vertically flipped in the texture.
* Note: the pixmap's alphatypes and colorspaces are ignored.
* For the Vulkan backend after a successful update the layout of the created VkImage will be:
* VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL
@ -577,8 +613,39 @@ public:
bool updateBackendTexture(const GrBackendTexture&,
const SkPixmap srcData[],
int numLevels,
GrGpuFinishedProc finishedProc,
GrGpuFinishedContext finishedContext);
GrSurfaceOrigin = kTopLeft_GrSurfaceOrigin,
GrGpuFinishedProc finishedProc = nullptr,
GrGpuFinishedContext finishedContext = nullptr);
/**
* Convenience version of updateBackendTexture that takes just a base level pixmap.
*/
bool updateBackendTexture(const GrBackendTexture& texture,
const SkPixmap& srcData,
GrSurfaceOrigin textureOrigin = kTopLeft_GrSurfaceOrigin,
GrGpuFinishedProc finishedProc = nullptr,
GrGpuFinishedContext finishedContext = nullptr) {
return this->updateBackendTexture(texture,
&srcData,
1,
textureOrigin,
finishedProc,
finishedContext);
}
// Deprecated version that does not take origin and assumes top-left.
bool updateBackendTexture(const GrBackendTexture& texture,
const SkPixmap srcData[],
int numLevels,
GrGpuFinishedProc finishedProc,
GrGpuFinishedContext finishedContext) {
return this->updateBackendTexture(texture,
srcData,
numLevels,
kTopLeft_GrSurfaceOrigin,
finishedProc,
finishedContext);
}
/**
* Retrieve the GrBackendFormat for a given SkImage::CompressionType. This is

View File

@ -10,11 +10,9 @@
#include "include/core/SkColor.h"
#include "include/private/GrTypesPriv.h"
#include "src/gpu/GrColorInfo.h"
#include "src/gpu/GrImageInfo.h"
#include "src/gpu/GrSwizzle.h"
class GrImageInfo;
size_t GrNumBlocks(SkImage::CompressionType, SkISize baseDimensions);
// Returns a value that can be used to set rowBytes for a transfer function.
@ -39,6 +37,13 @@ bool GrConvertPixels(const GrImageInfo& dstInfo, void* dst, size_t dstRB,
const GrImageInfo& srcInfo, const void* src, size_t srcRB,
bool flipY = false);
// Convenience version for src/dst pixmaps.
inline bool GrConvertPixels(const SkPixmap& dst, const SkPixmap& src, bool flipY = false) {
return GrConvertPixels(dst.info(), dst.writable_addr(), dst.rowBytes(),
src.info(), src.addr(), src.rowBytes(),
flipY);
}
/** Clears the dst image to a constant color. */
bool GrClearImage(const GrImageInfo& dstInfo, void* dst, size_t dstRB, SkColor4f color);

View File

@ -484,6 +484,34 @@ static GrBackendTexture create_and_update_backend_texture(
return beTex;
}
static bool update_texture_with_pixmaps(GrGpu* gpu,
const SkPixmap* srcData,
int numLevels,
const GrBackendTexture& backendTexture,
GrSurfaceOrigin textureOrigin,
sk_sp<GrRefCntedCallback> finishedCallback) {
std::unique_ptr<char[]> tempStorage;
SkAutoSTArray<15, SkPixmap> tempPixmaps;
if (textureOrigin == kBottomLeft_GrSurfaceOrigin) {
size_t size = 0;
for (int i = 0; i < numLevels; ++i) {
size += srcData[i].info().minRowBytes()*srcData[i].height();
}
tempStorage.reset(new char[size]);
tempPixmaps.reset(numLevels);
size = 0;
for (int i = 0; i < numLevels; ++i) {
size_t tempRB = srcData[i].info().minRowBytes();
tempPixmaps[i].reset(srcData[i].info(), tempStorage.get() + size, tempRB);
SkAssertResult(GrConvertPixels(tempPixmaps[i], srcData[i], /*flip*/ true));
size += tempRB*srcData[i].height();
}
srcData = tempPixmaps.get();
}
GrGpu::BackendTextureData data(srcData);
return gpu->updateBackendTexture(backendTexture, std::move(finishedCallback), &data);
}
GrBackendTexture GrDirectContext::createBackendTexture(int width, int height,
const GrBackendFormat& backendFormat,
const SkColor4f& color,
@ -535,6 +563,7 @@ GrBackendTexture GrDirectContext::createBackendTexture(int width, int height,
GrBackendTexture GrDirectContext::createBackendTexture(const SkPixmap srcData[],
int numProvidedLevels,
GrSurfaceOrigin textureOrigin,
GrRenderable renderable,
GrProtected isProtected,
GrGpuFinishedProc finishedProc,
@ -567,11 +596,25 @@ GrBackendTexture GrDirectContext::createBackendTexture(const SkPixmap srcData[],
}
GrBackendFormat backendFormat = this->defaultBackendFormat(colorType, renderable);
GrGpu::BackendTextureData data(srcData);
return create_and_update_backend_texture(this, {baseWidth, baseHeight},
backendFormat, mipMapped, renderable, isProtected,
std::move(finishedCallback), &data);
GrBackendTexture beTex = this->createBackendTexture(srcData[0].width(),
srcData[0].height(),
backendFormat,
mipMapped,
renderable,
isProtected);
if (!beTex.isValid()) {
return {};
}
if (!update_texture_with_pixmaps(this->priv().getGpu(),
srcData,
numProvidedLevels,
beTex,
textureOrigin,
std::move(finishedCallback))) {
this->deleteBackendTexture(beTex);
return {};
}
return beTex;
}
bool GrDirectContext::updateBackendTexture(const GrBackendTexture& backendTexture,
@ -615,6 +658,7 @@ bool GrDirectContext::updateBackendTexture(const GrBackendTexture& backendTextur
bool GrDirectContext::updateBackendTexture(const GrBackendTexture& backendTexture,
const SkPixmap srcData[],
int numLevels,
GrSurfaceOrigin textureOrigin,
GrGpuFinishedProc finishedProc,
GrGpuFinishedContext finishedContext) {
auto finishedCallback = GrRefCntedCallback::Make(finishedProc, finishedContext);
@ -635,9 +679,12 @@ bool GrDirectContext::updateBackendTexture(const GrBackendTexture& backendTextur
if (numLevels != numExpectedLevels) {
return false;
}
GrGpu::BackendTextureData data(srcData);
return fGpu->updateBackendTexture(backendTexture, std::move(finishedCallback), &data);
return update_texture_with_pixmaps(fGpu.get(),
srcData,
numLevels,
backendTexture,
textureOrigin,
std::move(finishedCallback));
}
//////////////////////////////////////////////////////////////////////////////

View File

@ -464,11 +464,13 @@ static int make_pixmaps(SkColorType skColorType, GrMipmapped mipMapped,
// Test initialization of GrBackendObjects using SkPixmaps
static void test_pixmap_init(GrDirectContext* dContext,
skiatest::Reporter* reporter,
std::function<GrBackendTexture (GrDirectContext*,
const SkPixmap srcData[],
int numLevels,
GrRenderable)> create,
std::function<GrBackendTexture(GrDirectContext*,
const SkPixmap srcData[],
int numLevels,
GrSurfaceOrigin,
GrRenderable)> create,
SkColorType skColorType,
GrSurfaceOrigin origin,
GrMipmapped mipMapped,
GrRenderable renderable,
bool* finishedBECreate) {
@ -491,7 +493,7 @@ static void test_pixmap_init(GrDirectContext* dContext,
pixmaps[i].reset(pixmapMem[i].info(), pixmapMem[i].addr(), pixmapMem[i].rowBytes());
}
GrBackendTexture backendTex = create(dContext, pixmaps, numMipLevels, renderable);
GrBackendTexture backendTex = create(dContext, pixmaps, numMipLevels, origin, renderable);
if (!backendTex.isValid()) {
// errors here should be reported by the test_wrapping test
return;
@ -541,7 +543,7 @@ static void test_pixmap_init(GrDirectContext* dContext,
}
// Upload new data and make sure everything still works
dContext->updateBackendTexture(backendTex, pixmaps, numMipLevels, mark_signaled,
dContext->updateBackendTexture(backendTex, pixmaps, numMipLevels, origin, mark_signaled,
finishedBECreate);
checkBackendTexture(colorsNew);
@ -712,14 +714,19 @@ DEF_GPUTEST_FOR_RENDERING_CONTEXTS(ColorTypeBackendAllocationTest, reporter, ctx
renderable, finishedPtr);
}
{
for (auto origin : {kTopLeft_GrSurfaceOrigin, kBottomLeft_GrSurfaceOrigin}) {
auto createWithSrcDataMtd = [finishedPtr](GrDirectContext* dContext,
const SkPixmap srcData[],
int numLevels,
GrSurfaceOrigin origin,
GrRenderable renderable) {
SkASSERT(srcData && numLevels);
auto result = dContext->createBackendTexture(srcData, numLevels, renderable,
GrProtected::kNo, mark_signaled,
auto result = dContext->createBackendTexture(srcData,
numLevels,
origin,
renderable,
GrProtected::kNo,
mark_signaled,
finishedPtr);
check_vk_layout(result, VkLayout::kReadOnlyOptimal);
#ifdef SK_DEBUG
@ -732,8 +739,14 @@ DEF_GPUTEST_FOR_RENDERING_CONTEXTS(ColorTypeBackendAllocationTest, reporter, ctx
return result;
};
test_pixmap_init(context, reporter, createWithSrcDataMtd, colorType, mipMapped,
renderable, finishedPtr);
test_pixmap_init(context,
reporter,
createWithSrcDataMtd,
colorType,
origin,
mipMapped,
renderable,
finishedPtr);
}
}
}

View File

@ -201,7 +201,7 @@ static void gpu_tests(GrDirectContext* dContext,
*(bool*)context = true;
};
if (fullInit) {
backendTex = dContext->createBackendTexture(&nativeExpected, 1,
backendTex = dContext->createBackendTexture(nativeExpected, kTopLeft_GrSurfaceOrigin,
GrRenderable::kNo, GrProtected::kNo,
markFinished, &finishedBECreate);
} else {

View File

@ -360,7 +360,7 @@ DEF_GPUTEST_FOR_RENDERING_CONTEXTS(ReadOnlyTexture, reporter, context_info) {
// kRead for the right reason.
for (auto ioType : {kRead_GrIOType, kRW_GrIOType}) {
auto mbet = sk_gpu_test::ManagedBackendTexture::MakeWithData(
dContext, srcPixmap, GrRenderable::kNo, GrProtected::kNo);
dContext, srcPixmap, kTopLeft_GrSurfaceOrigin, GrRenderable::kNo, GrProtected::kNo);
if (!mbet) {
ERRORF(reporter, "Could not make texture.");
return;

View File

@ -131,7 +131,6 @@ DEF_GPUTEST_FOR_GL_RENDERING_CONTEXTS(RectangleTexture, reporter, ctxInfo) {
SkPixmap pm(ii, pixels, sizeof(uint32_t)*kWidth);
for (auto origin : { kBottomLeft_GrSurfaceOrigin, kTopLeft_GrSurfaceOrigin }) {
bool useBLOrigin = kBottomLeft_GrSurfaceOrigin == origin;
auto format = GrBackendFormat::MakeGL(GR_GL_RGBA8, GR_GL_TEXTURE_RECTANGLE);
GrBackendTexture rectangleTex = dContext->createBackendTexture(kWidth,
@ -143,15 +142,14 @@ DEF_GPUTEST_FOR_GL_RENDERING_CONTEXTS(RectangleTexture, reporter, ctxInfo) {
continue;
}
if (!dContext->updateBackendTexture(rectangleTex, &pm, 1, nullptr, nullptr)) {
if (!dContext->updateBackendTexture(rectangleTex, &pm, 1, origin, nullptr, nullptr)) {
continue;
}
GrColor refPixels[kWidth * kHeight];
for (int y = 0; y < kHeight; ++y) {
for (int x = 0; x < kWidth; ++x) {
int y0 = useBLOrigin ? kHeight - y - 1 : y;
refPixels[y * kWidth + x] = pixels[y0 * kWidth + x];
refPixels[y * kWidth + x] = pixels[y * kWidth + x];
}
}

View File

@ -121,8 +121,12 @@ static GrBackendTexture create_yuva_texture(GrDirectContext* direct,
auto markFinished = [](void* context) {
*(bool*)context = true;
};
auto beTex = direct->createBackendTexture(&pm, 1, GrRenderable::kNo, GrProtected::kNo,
markFinished, &finishedBECreate);
auto beTex = direct->createBackendTexture(pm,
kTopLeft_GrSurfaceOrigin,
GrRenderable::kNo,
GrProtected::kNo,
markFinished,
&finishedBECreate);
if (beTex.isValid()) {
direct->submit();
while (!finishedBECreate) {
@ -164,9 +168,13 @@ void DDLPromiseImageHelper::CreateBETexturesForPromiseImage(GrDirectContext* dir
auto markFinished = [](void* context) {
*(bool*)context = true;
};
auto backendTex = direct->createBackendTexture(mipLevels.get(), info->numMipLevels(),
GrRenderable::kNo, GrProtected::kNo,
markFinished, &finishedBECreate);
auto backendTex = direct->createBackendTexture(mipLevels.get(),
info->numMipLevels(),
kTopLeft_GrSurfaceOrigin,
GrRenderable::kNo,
GrProtected::kNo,
markFinished,
&finishedBECreate);
SkASSERT(backendTex.isValid());
direct->submit();
while (!finishedBECreate) {

View File

@ -19,27 +19,20 @@ sk_sp<SkImage> MakeBackendTextureImage(GrDirectContext* dContext,
const SkPixmap& pixmap,
GrRenderable renderable,
GrSurfaceOrigin origin) {
const SkPixmap* src = &pixmap;
SkAutoPixmapStorage temp;
if (origin == kBottomLeft_GrSurfaceOrigin) {
temp.alloc(src->info());
auto s = static_cast<const char*>(src->addr(0, pixmap.height() - 1));
auto d = static_cast<char*>(temp.writable_addr(0, 0));
for (int y = 0; y < temp.height(); ++y, s -= pixmap.rowBytes(), d += temp.rowBytes()) {
std::copy_n(s, temp.info().minRowBytes(), d);
}
src = &temp;
}
auto mbet = ManagedBackendTexture::MakeWithData(dContext, src, 1, renderable, GrProtected::kNo);
auto mbet = ManagedBackendTexture::MakeWithData(dContext,
pixmap,
origin,
renderable,
GrProtected::kNo);
if (!mbet) {
return nullptr;
}
return SkImage::MakeFromTexture(dContext,
mbet->texture(),
origin,
src->colorType(),
src->alphaType(),
src->refColorSpace(),
pixmap.colorType(),
pixmap.alphaType(),
pixmap.refColorSpace(),
ManagedBackendTexture::ReleaseProc,
mbet->releaseContext());
}

View File

@ -86,8 +86,12 @@ sk_sp<ManagedBackendTexture> ManagedBackendTexture::MakeFromBitmap(GrDirectConte
levels.push_back(level.fPixmap);
}
}
return MakeWithData(
dContext, levels.data(), static_cast<int>(levels.size()), renderable, isProtected);
return MakeWithData(dContext,
levels.data(),
static_cast<int>(levels.size()),
kTopLeft_GrSurfaceOrigin,
renderable,
isProtected);
}
} // namespace sk_gpu_test

View File

@ -236,7 +236,11 @@ bool LazyYUVImage::ensureYUVImage(GrRecordingContext* rContext, Type type) {
GrBackendTexture textures[SkYUVAInfo::kMaxPlanes];
for (int i = 0; i < fPixmaps.numPlanes(); ++i) {
mbets[i] = sk_gpu_test::ManagedBackendTexture::MakeWithData(
direct, fPixmaps.plane(i), GrRenderable::kNo, GrProtected::kNo);
direct,
fPixmaps.plane(i),
kTopLeft_GrSurfaceOrigin,
GrRenderable::kNo,
GrProtected::kNo);
if (mbets[i]) {
textures[i] = mbets[i]->texture();
} else {