/*
* Copyright 2016 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "GrTextureContext.h"
#include "GrDrawingManager.h"
#include "GrResourceProvider.h"
#include "GrTextureOpList.h"
#include "../private/GrAuditTrail.h"
#define ASSERT_SINGLE_OWNER \
SkDEBUGCODE(GrSingleOwner::AutoEnforce debug_SingleOwner(fSingleOwner);)
#define RETURN_FALSE_IF_ABANDONED if (this->drawingManager()->wasAbandoned()) { return false; }
GrTextureContext::GrTextureContext(GrContext* context,
GrDrawingManager* drawingMgr,
sk_sp<GrTextureProxy> textureProxy,
sk_sp<SkColorSpace> colorSpace,
GrAuditTrail* auditTrail,
GrSingleOwner* singleOwner)
: GrSurfaceContext(context, drawingMgr, std::move(colorSpace), auditTrail, singleOwner)
, fTextureProxy(std::move(textureProxy))
, fOpList(SkSafeRef(fTextureProxy->getLastTextureOpList())) {
SkDEBUGCODE(this->validate();)
}
#ifdef SK_DEBUG
void GrTextureContext::validate() const {
SkASSERT(fTextureProxy);
fTextureProxy->validate(fContext);
if (fOpList && !fOpList->isClosed()) {
SkASSERT(fTextureProxy->getLastOpList() == fOpList);
}
}
#endif
GrTextureContext::~GrTextureContext() {
ASSERT_SINGLE_OWNER
SkSafeUnref(fOpList);
}
GrRenderTargetProxy* GrTextureContext::asRenderTargetProxy() {
// If the proxy can return an RTProxy it should've been wrapped in a RTContext
SkASSERT(!fTextureProxy->asRenderTargetProxy());
return nullptr;
}
sk_sp<GrRenderTargetProxy> GrTextureContext::asRenderTargetProxyRef() {
// If the proxy can return an RTProxy it should've been wrapped in a RTContext
SkASSERT(!fTextureProxy->asRenderTargetProxy());
return nullptr;
}
GrTextureOpList* GrTextureContext::getOpList() {
ASSERT_SINGLE_OWNER
SkDEBUGCODE(this->validate();)
if (!fOpList || fOpList->isClosed()) {
fOpList = this->drawingManager()->newOpList(fTextureProxy.get());
}
return fOpList;
}
// TODO: move this (and GrRenderTargetContext::copy) to GrSurfaceContext?
bool GrTextureContext::onCopy(GrSurfaceProxy* srcProxy,
const SkIRect& srcRect,
const SkIPoint& dstPoint) {
ASSERT_SINGLE_OWNER
RETURN_FALSE_IF_ABANDONED
SkDEBUGCODE(this->validate();)
GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrTextureContext::copy");
// TODO: defer instantiation until flush time
sk_sp<GrSurface> src(sk_ref_sp(srcProxy->instantiate(fContext->resourceProvider())));
if (!src) {
return false;
}
#ifndef ENABLE_MDB
// We can't yet fully defer copies to textures, so GrTextureContext::copySurface will
// execute the copy immediately. Ensure the data is ready.
src->flushWrites();
#endif
// TODO: this needs to be fixed up since it ends the deferrable of the GrTexture
sk_sp<GrTexture> tex(sk_ref_sp(fTextureProxy->instantiate(fContext->resourceProvider())));
if (!tex) {
return false;
}
GrTextureOpList* opList = this->getOpList();
bool result = opList->copySurface(tex.get(), src.get(), srcRect, dstPoint);
#ifndef ENABLE_MDB
GrOpFlushState flushState(fContext->getGpu(), nullptr);
opList->prepareOps(&flushState);
opList->executeOps(&flushState);
opList->reset();
#endif
return result;
}
// TODO: move this (and GrRenderTargetContext::onReadPixels) to GrSurfaceContext?
bool GrTextureContext::onReadPixels(const SkImageInfo& dstInfo, void* dstBuffer,
size_t dstRowBytes, int x, int y, uint32_t flags) {
// TODO: teach GrTexture to take ImageInfo directly to specify the src pixels
GrPixelConfig config = SkImageInfo2GrPixelConfig(dstInfo, *fContext->caps());
if (kUnknown_GrPixelConfig == config) {
return false;
}
// TODO: this seems to duplicate code in SkImage_Gpu::onReadPixels
if (kUnpremul_SkAlphaType == dstInfo.alphaType()) {
flags |= GrContext::kUnpremul_PixelOpsFlag;
}
// Deferral of the VRAM resources must end in this instance anyway
sk_sp<GrTexture> tex(sk_ref_sp(fTextureProxy->instantiate(fContext->resourceProvider())));
if (!tex) {
return false;
}
return tex->readPixels(this->getColorSpace(), x, y, dstInfo.width(), dstInfo.height(),
config, dstInfo.colorSpace(), dstBuffer, dstRowBytes, flags);
}
// TODO: move this (and GrRenderTargetContext::onReadPixels) to GrSurfaceContext?
bool GrTextureContext::onWritePixels(const SkImageInfo& srcInfo, const void* srcBuffer,
size_t srcRowBytes, int x, int y,
uint32_t flags) {
// TODO: teach GrTexture to take ImageInfo directly to specify the src pixels
GrPixelConfig config = SkImageInfo2GrPixelConfig(srcInfo, *fContext->caps());
if (kUnknown_GrPixelConfig == config) {
return false;
}
if (kUnpremul_SkAlphaType == srcInfo.alphaType()) {
flags |= GrContext::kUnpremul_PixelOpsFlag;
}
// Deferral of the VRAM resources must end in this instance anyway
sk_sp<GrTexture> tex(sk_ref_sp(fTextureProxy->instantiate(fContext->resourceProvider())));
if (!tex) {
return false;
}
return tex->writePixels(this->getColorSpace(), x, y, srcInfo.width(), srcInfo.height(),
config, srcInfo.colorSpace(), srcBuffer, srcRowBytes, flags);
}