Implement refPinnedTextureProxy for SkImage_Lazy.

Creating a cross-context texture exposed a hole in our lazyproxy
texture generation. Despite having a wrapped texture we were falling
back to drawing in tiled mode, which is incorrect. Filling in these
methods allows us to draw with the wrapped texture.

Bug: skia:9562
Change-Id: Ia26c5d75b202aefdf720e6d1f7a201af23e40676
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/251214
Reviewed-by: Robert Phillips <robertphillips@google.com>
Commit-Queue: Jim Van Verth <jvanverth@google.com>
This commit is contained in:
Jim Van Verth 2019-10-28 14:37:49 -04:00 committed by Skia Commit-Bot
parent 9ead6c7400
commit 1e0f2f389f
3 changed files with 65 additions and 0 deletions

View File

@ -237,6 +237,15 @@ bool SkImage_Lazy::onIsValid(GrContext* context) const {
///////////////////////////////////////////////////////////////////////////////////////////////////
#if SK_SUPPORT_GPU
sk_sp<GrTextureProxy> SkImage_Lazy::asTextureProxyRef(GrRecordingContext* context) const {
if (!context) {
return nullptr;
}
GrImageTextureMaker textureMaker(context, this, kAllow_CachingHint);
return textureMaker.refTextureProxy(GrMipMapped::kNo);
}
sk_sp<GrTextureProxy> SkImage_Lazy::asTextureProxyRef(GrRecordingContext* context,
const GrSamplerState& params,
SkScalar scaleAdjust[2]) const {

View File

@ -42,11 +42,17 @@ public:
bool onReadPixels(const SkImageInfo&, void*, size_t, int srcX, int srcY,
CachingHint) const override;
#if SK_SUPPORT_GPU
sk_sp<GrTextureProxy> asTextureProxyRef(GrRecordingContext*) const override;
sk_sp<GrTextureProxy> asTextureProxyRef(GrRecordingContext*,
const GrSamplerState&,
SkScalar scaleAdjust[2]) const override;
sk_sp<SkCachedData> getPlanes(SkYUVASizeInfo*, SkYUVAIndex[4],
SkYUVColorSpace*, const void* planes[4]) override;
sk_sp<GrTextureProxy> refPinnedTextureProxy(GrRecordingContext* context,
uint32_t* uniqueID) const final {
*uniqueID = fUniqueID;
return this->asTextureProxyRef(context);
}
#endif
sk_sp<SkData> onRefEncoded() const override;
sk_sp<SkImage> onMakeSubset(GrRecordingContext*, const SkIRect&) const override;

View File

@ -1052,6 +1052,56 @@ DEF_GPUTEST(SkImage_CrossContextGrayAlphaConfigs, reporter, options) {
}
}
DEF_GPUTEST(SkImage_CrossContextLarge, reporter, options) {
SkAutoPixmapStorage srcPixmap;
srcPixmap.alloc(SkImageInfo::Make(5400, 3915, kRGBA_8888_SkColorType, kPremul_SkAlphaType));
srcPixmap.erase(0xdeadbeef);
// We need to draw into a rendertarget smaller than the original image to trigger the bug.
// Hence this will be the expected result.
SkAutoPixmapStorage clippedPixmap;
clippedPixmap.alloc(SkImageInfo::Make(2048, 2048, kRGBA_8888_SkColorType, kPremul_SkAlphaType));
srcPixmap.readPixels(clippedPixmap, 0, 0);
for (int i = 0; i < GrContextFactory::kContextTypeCnt; ++i) {
GrContextFactory testFactory(options);
GrContextFactory::ContextType ctxType = static_cast<GrContextFactory::ContextType>(i);
ContextInfo ctxInfo = testFactory.getContextInfo(ctxType);
GrContext* ctx = ctxInfo.grContext();
if (!ctx || !ctx->priv().caps()->crossContextTextureSupport()) {
continue;
}
sk_sp<SkImage> image = SkImage::MakeCrossContextFromPixmap(ctx, srcPixmap, false);
REPORTER_ASSERT(reporter, image);
auto surf = SkSurface::MakeRenderTarget(ctx, SkBudgeted::kYes, clippedPixmap.info(),
0, kTopLeft_GrSurfaceOrigin, nullptr);
if (surf) {
auto canvas = surf->getCanvas();
canvas->drawImage(image, 0, 0);
SkAutoPixmapStorage readPixmap;
readPixmap.alloc(clippedPixmap.info());
bool result = canvas->readPixels(readPixmap, 0, 0);
if (!result) {
continue;
}
const float tols[4] = {0, 0, 0, 0};
auto error = std::function<ComparePixmapsErrorReporter>([&](int x, int y,
const float diffs[4]) {
SkASSERT(x >= 0 && y >= 0);
ERRORF(reporter,
"Error at %d, %d. Diff in floats: (%f, %f, %f %f)",
x, y,
diffs[0], diffs[1], diffs[2], diffs[3]);
});
ComparePixels(clippedPixmap, readPixmap, tols, error);
}
}
}
DEF_GPUTEST_FOR_GL_RENDERING_CONTEXTS(makeBackendTexture, reporter, ctxInfo) {
GrContext* context = ctxInfo.grContext();
sk_gpu_test::TestContext* testContext = ctxInfo.testContext();