More SkImage_GpuYUV updates
Bug: skia:7901
Change-Id: If5f747ff95c65ac95cfed8c1282cc08019d8006a
Reviewed-on: https://skia-review.googlesource.com/c/160024
Reviewed-by: Robert Phillips <robertphillips@google.com>
Commit-Queue: Jim Van Verth <jvanverth@google.com>
diff --git a/src/image/SkImage_GpuBase.cpp b/src/image/SkImage_GpuBase.cpp
index 63d65a4..b5105ab 100644
--- a/src/image/SkImage_GpuBase.cpp
+++ b/src/image/SkImage_GpuBase.cpp
@@ -15,6 +15,7 @@
#include "SkBitmapCache.h"
#include "SkImage_Gpu.h"
#include "SkImage_GpuBase.h"
+#include "SkReadPixelsRec.h"
SkImage_GpuBase::SkImage_GpuBase(sk_sp<GrContext> context, int width, int height, uint32_t uniqueID,
SkAlphaType at, SkBudgeted budgeted, sk_sp<SkColorSpace> cs)
@@ -121,6 +122,76 @@
fColorSpace, fBudgeted);
}
+static void apply_premul(const SkImageInfo& info, void* pixels, size_t rowBytes) {
+ switch (info.colorType()) {
+ case kRGBA_8888_SkColorType:
+ case kBGRA_8888_SkColorType:
+ break;
+ default:
+ return; // nothing to do
+ }
+
+ // SkColor is not necesarily RGBA or BGRA, but it is one of them on little-endian,
+ // and in either case, the alpha-byte is always in the same place, so we can safely call
+ // SkPreMultiplyColor()
+ //
+ SkColor* row = (SkColor*)pixels;
+ for (int y = 0; y < info.height(); ++y) {
+ for (int x = 0; x < info.width(); ++x) {
+ row[x] = SkPreMultiplyColor(row[x]);
+ }
+ row = (SkColor*)((char*)(row)+rowBytes);
+ }
+}
+
+bool SkImage_GpuBase::onReadPixels(const SkImageInfo& dstInfo, void* dstPixels, size_t dstRB,
+ int srcX, int srcY, CachingHint) const {
+ if (!fContext->contextPriv().resourceProvider()) {
+ // DDL TODO: buffer up the readback so it occurs when the DDL is drawn?
+ return false;
+ }
+
+ if (!SkImageInfoValidConversion(dstInfo, this->onImageInfo())) {
+ return false;
+ }
+
+ SkReadPixelsRec rec(dstInfo, dstPixels, dstRB, srcX, srcY);
+ if (!rec.trim(this->width(), this->height())) {
+ return false;
+ }
+
+ // TODO: this seems to duplicate code in GrTextureContext::onReadPixels and
+ // GrRenderTargetContext::onReadPixels
+ uint32_t flags = 0;
+ if (kUnpremul_SkAlphaType == rec.fInfo.alphaType() && kPremul_SkAlphaType == fAlphaType) {
+ // let the GPU perform this transformation for us
+ flags = GrContextPriv::kUnpremul_PixelOpsFlag;
+ }
+
+ sk_sp<GrSurfaceContext> sContext = fContext->contextPriv().makeWrappedSurfaceContext(
+ this->asTextureProxyRef(), fColorSpace);
+ if (!sContext) {
+ return false;
+ }
+
+ if (!sContext->readPixels(rec.fInfo, rec.fPixels, rec.fRowBytes, rec.fX, rec.fY, flags)) {
+ return false;
+ }
+
+ // do we have to manually fix-up the alpha channel?
+ // src dst
+ // unpremul premul fix manually
+ // premul unpremul done by kUnpremul_PixelOpsFlag
+ // all other combos need to change.
+ //
+ // Should this be handled by Ganesh? todo:?
+ //
+ if (kPremul_SkAlphaType == rec.fInfo.alphaType() && kUnpremul_SkAlphaType == fAlphaType) {
+ apply_premul(rec.fInfo, rec.fPixels, rec.fRowBytes);
+ }
+ return true;
+}
+
sk_sp<GrTextureProxy> SkImage_GpuBase::asTextureProxyRef(GrContext* context,
const GrSamplerState& params,
SkColorSpace* dstColorSpace,
@@ -235,3 +306,52 @@
return true;
}
+
+/////////////////////////////////////////////////////////////////////////////////////////////////
+sk_sp<GrTexture> SkPromiseImageHelper::getTexture(GrResourceProvider* resourceProvider,
+ GrPixelConfig config) {
+ // Releases the promise helper if there are no outstanding hard refs. This means that we
+ // don't have any ReleaseProcs waiting to be called so we will need to do a fulfill.
+ if (fReleaseHelper && fReleaseHelper->weak_expired()) {
+ this->resetReleaseHelper();
+ }
+
+ sk_sp<GrTexture> tex;
+ if (!fReleaseHelper) {
+ fFulfillProc(fContext, &fBackendTex);
+ fBackendTex.fConfig = config;
+ if (!fBackendTex.isValid()) {
+ // Even though the GrBackendTexture is not valid, we must call the release
+ // proc to keep our contract of always calling Fulfill and Release in pairs.
+ fReleaseProc(fContext);
+ return sk_sp<GrTexture>();
+ }
+
+ tex = resourceProvider->wrapBackendTexture(fBackendTex, kBorrow_GrWrapOwnership);
+ if (!tex) {
+ // Even though the GrBackendTexture is not valid, we must call the release
+ // proc to keep our contract of always calling Fulfill and Release in pairs.
+ fReleaseProc(fContext);
+ return sk_sp<GrTexture>();
+ }
+ fReleaseHelper = new SkPromiseReleaseProcHelper(fReleaseProc, fContext, fDoneHelper);
+ // Take a weak ref
+ fReleaseHelper->weak_ref();
+ } else {
+ SkASSERT(fBackendTex.isValid());
+ tex = resourceProvider->wrapBackendTexture(fBackendTex, kBorrow_GrWrapOwnership);
+ if (!tex) {
+ // We weren't able to make a texture here, but since we are in this branch
+ // of the calls (promiseHelper.fReleaseHelper is valid) there is already a
+ // texture out there which will call the release proc so we don't need to
+ // call it here.
+ return sk_sp<GrTexture>();
+ }
+
+ SkAssertResult(fReleaseHelper->try_ref());
+ }
+ SkASSERT(tex);
+ // Pass the hard ref off to the texture
+ tex->setRelease(sk_sp<GrReleaseProcHelper>(fReleaseHelper));
+ return tex;
+}