Start removal of tool usage of SkSurface::MakeFromBackendTextureAsRenderTarget.
Adds a new helper that creates a GrBackendRenderTarget using GrGpu and then wraps it in a SkSurface. Uses the SkSurface release proc to delete the BERT using GrGpu. Upgrades GrGpu::createTestingOnlyBackendRenderTarget to create MSAA buffers. Updates many tests/tool to call sites to use the helper instead of SkSurface::MakeFromBackendTextureAsRenderTarget. Adds syncToCpu bool to SkSurface:: and GrContext::flushAndSubmit. Bug: skia:9832 Change-Id: I73a8f0ce09dc6523729af0814464c6b6657fda06 Reviewed-on: https://skia-review.googlesource.com/c/skia/+/293683 Commit-Queue: Brian Salomon <bsalomon@google.com> Reviewed-by: Greg Daniel <egdaniel@google.com> Reviewed-by: Jim Van Verth <jvanverth@google.com> Reviewed-by: Kevin Lubick <kjlubick@google.com>
This commit is contained in:
parent
2e09693964
commit
72c7b98ae3
2
BUILD.gn
2
BUILD.gn
@ -1605,6 +1605,8 @@ if (skia_enable_tools) {
|
||||
deps = []
|
||||
public_deps = []
|
||||
sources = [
|
||||
"tools/gpu/BackendSurfaceFactory.cpp",
|
||||
"tools/gpu/BackendSurfaceFactory.h",
|
||||
"tools/gpu/BackendTextureImageFactory.cpp",
|
||||
"tools/gpu/BackendTextureImageFactory.h",
|
||||
"tools/gpu/FlushFinishTracker.cpp",
|
||||
|
@ -9,6 +9,8 @@ Milestone 88
|
||||
|
||||
* <insert new release notes here>
|
||||
|
||||
* CPU sync bool added to SkSurface::flushAndSubmit() and GrContext::flushAndSubmit()
|
||||
|
||||
* Removed legacy variant of SkImage::MakeFromYUVAPixmaps. Use the version that
|
||||
takes SkYUVAPixmaps instead. It has a more structured description of the
|
||||
planar configuration.
|
||||
|
@ -51,6 +51,7 @@
|
||||
#include "tools/DDLTileHelper.h"
|
||||
#include "tools/Resources.h"
|
||||
#include "tools/debugger/DebugCanvas.h"
|
||||
#include "tools/gpu/BackendSurfaceFactory.h"
|
||||
#include "tools/gpu/MemoryCache.h"
|
||||
#if defined(SK_BUILD_FOR_WIN)
|
||||
#include "include/docs/SkXPSDocument.h"
|
||||
@ -1467,9 +1468,9 @@ Result GPUSink::draw(const Src& src, SkBitmap* dst, SkWStream* dstStream, SkStri
|
||||
return this->onDraw(src, dst, dstStream, log, fBaseContextOptions);
|
||||
}
|
||||
|
||||
sk_sp<SkSurface> GPUSink::createDstSurface(GrDirectContext* context, SkISize size,
|
||||
GrBackendTexture* backendTexture,
|
||||
GrBackendRenderTarget* backendRT) const {
|
||||
sk_sp<SkSurface> GPUSink::createDstSurface(GrDirectContext* context,
|
||||
SkISize size,
|
||||
GrBackendTexture* backendTexture) const {
|
||||
sk_sp<SkSurface> surface;
|
||||
|
||||
SkImageInfo info = SkImageInfo::Make(size, fColorType, fAlphaType, fColorSpace);
|
||||
@ -1490,14 +1491,13 @@ sk_sp<SkSurface> GPUSink::createDstSurface(GrDirectContext* context, SkISize siz
|
||||
fColorType, info.refColorSpace(), &props);
|
||||
break;
|
||||
case SkCommandLineConfigGpu::SurfType::kBackendRenderTarget:
|
||||
if (1 == fSampleCount) {
|
||||
auto colorType = SkColorTypeToGrColorType(info.colorType());
|
||||
*backendRT = context->priv().getGpu()->createTestingOnlyBackendRenderTarget(
|
||||
info.width(), info.height(), colorType);
|
||||
surface = SkSurface::MakeFromBackendRenderTarget(
|
||||
context, *backendRT, kBottomLeft_GrSurfaceOrigin, info.colorType(),
|
||||
info.refColorSpace(), &props);
|
||||
}
|
||||
surface = MakeBackendRenderTargetSurface(context,
|
||||
info.dimensions(),
|
||||
fSampleCount,
|
||||
kBottomLeft_GrSurfaceOrigin,
|
||||
info.colorType(),
|
||||
info.refColorSpace(),
|
||||
&props);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -1537,9 +1537,7 @@ Result GPUSink::onDraw(const Src& src, SkBitmap* dst, SkWStream*, SkString* log,
|
||||
}
|
||||
|
||||
GrBackendTexture backendTexture;
|
||||
GrBackendRenderTarget backendRT;
|
||||
sk_sp<SkSurface> surface = this->createDstSurface(direct, src.size(),
|
||||
&backendTexture, &backendRT);
|
||||
sk_sp<SkSurface> surface = this->createDstSurface(direct, src.size(), &backendTexture);
|
||||
if (!surface) {
|
||||
return Result::Fatal("Could not create a surface.");
|
||||
}
|
||||
@ -1570,9 +1568,6 @@ Result GPUSink::onDraw(const Src& src, SkBitmap* dst, SkWStream*, SkString* log,
|
||||
if (backendTexture.isValid()) {
|
||||
direct->deleteBackendTexture(backendTexture);
|
||||
}
|
||||
if (backendRT.isValid()) {
|
||||
direct->priv().getGpu()->deleteTestingOnlyBackendRenderTarget(backendRT);
|
||||
}
|
||||
}
|
||||
if (grOptions.fPersistentCache) {
|
||||
direct->storeVkPipelineCacheData();
|
||||
@ -1749,9 +1744,7 @@ Result GPUOOPRSink::draw(const Src& src, SkBitmap* dst, SkWStream*, SkString* lo
|
||||
SkASSERT(context->priv().getGpu());
|
||||
|
||||
GrBackendTexture backendTexture;
|
||||
GrBackendRenderTarget backendRT;
|
||||
sk_sp<SkSurface> surface = this->createDstSurface(context, src.size(),
|
||||
&backendTexture, &backendRT);
|
||||
sk_sp<SkSurface> surface = this->createDstSurface(context, src.size(), &backendTexture);
|
||||
if (!surface) {
|
||||
return Result::Fatal("Could not create a surface.");
|
||||
}
|
||||
@ -1775,9 +1768,6 @@ Result GPUOOPRSink::draw(const Src& src, SkBitmap* dst, SkWStream*, SkString* lo
|
||||
if (backendTexture.isValid()) {
|
||||
context->deleteBackendTexture(backendTexture);
|
||||
}
|
||||
if (backendRT.isValid()) {
|
||||
context->priv().getGpu()->deleteTestingOnlyBackendRenderTarget(backendRT);
|
||||
}
|
||||
|
||||
return Result::Ok();
|
||||
}
|
||||
@ -1929,9 +1919,7 @@ Result GPUDDLSink::draw(const Src& src, SkBitmap* dst, SkWStream*, SkString* log
|
||||
mainTestCtx->makeCurrent();
|
||||
|
||||
GrBackendTexture backendTexture;
|
||||
GrBackendRenderTarget backendRT;
|
||||
sk_sp<SkSurface> surface = this->createDstSurface(mainCtx, src.size(),
|
||||
&backendTexture, &backendRT);
|
||||
sk_sp<SkSurface> surface = this->createDstSurface(mainCtx, src.size(), &backendTexture);
|
||||
if (!surface) {
|
||||
return Result::Fatal("Could not create a surface.");
|
||||
}
|
||||
@ -1965,9 +1953,6 @@ Result GPUDDLSink::draw(const Src& src, SkBitmap* dst, SkWStream*, SkString* log
|
||||
if (backendTexture.isValid()) {
|
||||
mainCtx->deleteBackendTexture(backendTexture);
|
||||
}
|
||||
if (backendRT.isValid()) {
|
||||
mainCtx->priv().getGpu()->deleteTestingOnlyBackendRenderTarget(backendRT);
|
||||
}
|
||||
|
||||
return Result::Ok();
|
||||
}
|
||||
|
@ -407,8 +407,7 @@ public:
|
||||
}
|
||||
|
||||
protected:
|
||||
sk_sp<SkSurface> createDstSurface(GrDirectContext*, SkISize size, GrBackendTexture*,
|
||||
GrBackendRenderTarget*) const;
|
||||
sk_sp<SkSurface> createDstSurface(GrDirectContext*, SkISize size, GrBackendTexture*) const;
|
||||
bool readBack(SkSurface*, SkBitmap* dst) const;
|
||||
|
||||
private:
|
||||
|
@ -900,9 +900,9 @@ public:
|
||||
correct ordering when the surface backing store is accessed outside Skia (e.g. direct use of
|
||||
the 3D API or a windowing system). GrContext has additional flush and submit methods that
|
||||
apply to all surfaces and images created from a GrContext. This is equivalent to calling
|
||||
SkSurface::flush with a default GrFlushInfo followed by GrContext::submit.
|
||||
SkSurface::flush with a default GrFlushInfo followed by GrContext::submit(syncCpu).
|
||||
*/
|
||||
void flushAndSubmit();
|
||||
void flushAndSubmit(bool syncCpu = false);
|
||||
|
||||
enum class BackendSurfaceAccess {
|
||||
kNoAccess, //!< back-end object will not be used by client
|
||||
|
@ -332,11 +332,11 @@ public:
|
||||
/**
|
||||
* Call to ensure all drawing to the context has been flushed and submitted to the underlying 3D
|
||||
* API. This is equivalent to calling GrContext::flush with a default GrFlushInfo followed by
|
||||
* GrContext::submit.
|
||||
* GrContext::submit(syncCpu).
|
||||
*/
|
||||
void flushAndSubmit() {
|
||||
void flushAndSubmit(bool syncCpu = false) {
|
||||
this->flush(GrFlushInfo());
|
||||
this->submit();
|
||||
this->submit(syncCpu);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1647,7 +1647,9 @@ EMSCRIPTEN_BINDINGS(Skia) {
|
||||
|
||||
class_<SkSurface>("SkSurface")
|
||||
.smart_ptr<sk_sp<SkSurface>>("sk_sp<SkSurface>")
|
||||
.function("_flush", select_overload<void()>(&SkSurface::flushAndSubmit))
|
||||
.function("_flush", optional_override([](SkSurface& self) {
|
||||
self.flushAndSubmit(false);
|
||||
}))
|
||||
.function("getCanvas", &SkSurface::getCanvas, allow_raw_pointers())
|
||||
.function("imageInfo", optional_override([](SkSurface& self)->SimpleImageInfo {
|
||||
const auto& ii = self.imageInfo();
|
||||
|
@ -666,9 +666,22 @@ public:
|
||||
/** Check a handle represents an actual texture in the backend API that has not been freed. */
|
||||
virtual bool isTestingOnlyBackendTexture(const GrBackendTexture&) const = 0;
|
||||
|
||||
virtual GrBackendRenderTarget createTestingOnlyBackendRenderTarget(int w, int h,
|
||||
GrColorType) = 0;
|
||||
/**
|
||||
* Creates a GrBackendRenderTarget that can be wrapped using
|
||||
* SkSurface::MakeFromBackendRenderTarget. Ideally this is a non-textureable allocation to
|
||||
* differentiate from testing with SkSurface::MakeFromBackendTexture. When sampleCnt > 1 this
|
||||
* is used to test client wrapped allocations with MSAA where Skia does not allocate a separate
|
||||
* buffer for resolving. If the color is non-null the backing store should be cleared to the
|
||||
* passed in color.
|
||||
*/
|
||||
virtual GrBackendRenderTarget createTestingOnlyBackendRenderTarget(SkISize,
|
||||
GrColorType,
|
||||
int sampleCount = 1) = 0;
|
||||
|
||||
/**
|
||||
* Deletes a GrBackendRenderTarget allocated with the above. Synchronization to make this safe
|
||||
* is up to the caller.
|
||||
*/
|
||||
virtual void deleteTestingOnlyBackendRenderTarget(const GrBackendRenderTarget&) = 0;
|
||||
|
||||
// This is only to be used in GL-specific tests.
|
||||
|
@ -207,45 +207,75 @@ bool GrSurfaceContext::readPixels(GrDirectContext* dContext, const GrImageInfo&
|
||||
}
|
||||
|
||||
if (readFlag == GrCaps::SurfaceReadPixelsSupport::kCopyToTexture2D || canvas2DFastPath) {
|
||||
GrColorType colorType = (canvas2DFastPath || srcIsCompressed)
|
||||
? GrColorType::kRGBA_8888 : this->colorInfo().colorType();
|
||||
sk_sp<SkColorSpace> cs = canvas2DFastPath ? nullptr : this->colorInfo().refColorSpace();
|
||||
std::unique_ptr<GrSurfaceContext> tempCtx;
|
||||
if (this->asTextureProxy()) {
|
||||
GrColorType colorType = (canvas2DFastPath || srcIsCompressed)
|
||||
? GrColorType::kRGBA_8888
|
||||
: this->colorInfo().colorType();
|
||||
sk_sp<SkColorSpace> cs = canvas2DFastPath ? nullptr : this->colorInfo().refColorSpace();
|
||||
|
||||
auto tempCtx = GrRenderTargetContext::Make(
|
||||
dContext, colorType, std::move(cs), SkBackingFit::kApprox, dstInfo.dimensions(),
|
||||
1, GrMipmapped::kNo, GrProtected::kNo, kTopLeft_GrSurfaceOrigin);
|
||||
if (!tempCtx) {
|
||||
return false;
|
||||
}
|
||||
|
||||
std::unique_ptr<GrFragmentProcessor> fp;
|
||||
if (canvas2DFastPath) {
|
||||
fp = dContext->priv().createPMToUPMEffect(
|
||||
GrTextureEffect::Make(this->readSurfaceView(), this->colorInfo().alphaType()));
|
||||
if (dstInfo.colorType() == GrColorType::kBGRA_8888) {
|
||||
fp = GrFragmentProcessor::SwizzleOutput(std::move(fp), GrSwizzle::BGRA());
|
||||
dstInfo = dstInfo.makeColorType(GrColorType::kRGBA_8888);
|
||||
tempCtx = GrRenderTargetContext::Make(
|
||||
dContext, colorType, std::move(cs), SkBackingFit::kApprox, dstInfo.dimensions(),
|
||||
1, GrMipMapped::kNo, GrProtected::kNo, kTopLeft_GrSurfaceOrigin);
|
||||
if (!tempCtx) {
|
||||
return false;
|
||||
}
|
||||
// The render target context is incorrectly tagged as kPremul even though we're writing
|
||||
// unpremul data thanks to the PMToUPM effect. Fake out the dst alpha type so we don't
|
||||
// double unpremul.
|
||||
dstInfo = dstInfo.makeAlphaType(kPremul_SkAlphaType);
|
||||
|
||||
std::unique_ptr<GrFragmentProcessor> fp;
|
||||
if (canvas2DFastPath) {
|
||||
fp = dContext->priv().createPMToUPMEffect(GrTextureEffect::Make(
|
||||
this->readSurfaceView(), this->colorInfo().alphaType()));
|
||||
if (dstInfo.colorType() == GrColorType::kBGRA_8888) {
|
||||
fp = GrFragmentProcessor::SwizzleOutput(std::move(fp), GrSwizzle::BGRA());
|
||||
dstInfo = dstInfo.makeColorType(GrColorType::kRGBA_8888);
|
||||
}
|
||||
// The render target context is incorrectly tagged as kPremul even though we're
|
||||
// writing unpremul data thanks to the PMToUPM effect. Fake out the dst alpha type
|
||||
// so we don't double unpremul.
|
||||
dstInfo = dstInfo.makeAlphaType(kPremul_SkAlphaType);
|
||||
} else {
|
||||
fp = GrTextureEffect::Make(this->readSurfaceView(), this->colorInfo().alphaType());
|
||||
}
|
||||
if (!fp) {
|
||||
return false;
|
||||
}
|
||||
GrPaint paint;
|
||||
paint.setPorterDuffXPFactory(SkBlendMode::kSrc);
|
||||
paint.setColorFragmentProcessor(std::move(fp));
|
||||
|
||||
tempCtx->asRenderTargetContext()->fillRectToRect(
|
||||
nullptr, std::move(paint), GrAA::kNo, SkMatrix::I(),
|
||||
SkRect::MakeWH(dstInfo.width(), dstInfo.height()),
|
||||
SkRect::MakeXYWH(pt.fX, pt.fY, dstInfo.width(), dstInfo.height()));
|
||||
pt = {0, 0};
|
||||
} else {
|
||||
fp = GrTextureEffect::Make(this->readSurfaceView(), this->colorInfo().alphaType());
|
||||
auto restrictions = this->caps()->getDstCopyRestrictions(this->asRenderTargetProxy(),
|
||||
this->colorInfo().colorType());
|
||||
sk_sp<GrSurfaceProxy> copy;
|
||||
static constexpr auto kFit = SkBackingFit::kExact;
|
||||
static constexpr auto kBudgeted = SkBudgeted::kYes;
|
||||
static constexpr auto kMipMapped = GrMipMapped::kNo;
|
||||
if (restrictions.fMustCopyWholeSrc) {
|
||||
copy = GrSurfaceProxy::Copy(fContext, srcProxy, this->origin(), kMipMapped, kFit,
|
||||
kBudgeted);
|
||||
} else {
|
||||
auto srcRect = SkIRect::MakeXYWH(pt.fX, pt.fY, dstInfo.width(), dstInfo.height());
|
||||
copy = GrSurfaceProxy::Copy(fContext, srcProxy, this->origin(), kMipMapped, srcRect,
|
||||
kFit, kBudgeted, restrictions.fRectsMustMatch);
|
||||
pt = {0, 0};
|
||||
}
|
||||
if (!copy) {
|
||||
return false;
|
||||
}
|
||||
GrSurfaceProxyView view{std::move(copy), this->origin(), this->readSwizzle()};
|
||||
tempCtx = GrSurfaceContext::Make(dContext,
|
||||
std::move(view),
|
||||
this->colorInfo().colorType(),
|
||||
this->colorInfo().alphaType(),
|
||||
this->colorInfo().refColorSpace());
|
||||
SkASSERT(tempCtx);
|
||||
}
|
||||
if (!fp) {
|
||||
return false;
|
||||
}
|
||||
GrPaint paint;
|
||||
paint.setPorterDuffXPFactory(SkBlendMode::kSrc);
|
||||
paint.setColorFragmentProcessor(std::move(fp));
|
||||
|
||||
tempCtx->asRenderTargetContext()->fillRectToRect(
|
||||
nullptr, std::move(paint), GrAA::kNo, SkMatrix::I(),
|
||||
SkRect::MakeWH(dstInfo.width(), dstInfo.height()),
|
||||
SkRect::MakeXYWH(pt.fX, pt.fY, dstInfo.width(), dstInfo.height()));
|
||||
|
||||
return tempCtx->readPixels(dContext, dstInfo, dst, rowBytes, {0, 0});
|
||||
return tempCtx->readPixels(dContext, dstInfo, dst, rowBytes, pt);
|
||||
}
|
||||
|
||||
bool flip = this->origin() == kBottomLeft_GrSurfaceOrigin;
|
||||
|
@ -911,8 +911,14 @@ GrCaps::SurfaceReadPixelsSupport GrD3DCaps::surfaceSupportsReadPixels(
|
||||
if (GrDxgiFormatIsCompressed(tex->dxgiFormat())) {
|
||||
return SurfaceReadPixelsSupport::kCopyToTexture2D;
|
||||
}
|
||||
return SurfaceReadPixelsSupport::kSupported;
|
||||
} else if (auto rt = static_cast<const GrD3DRenderTarget*>(surface->asRenderTarget())) {
|
||||
if (rt->numSamples() > 1) {
|
||||
return SurfaceReadPixelsSupport::kCopyToTexture2D;
|
||||
}
|
||||
return SurfaceReadPixelsSupport::kSupported;
|
||||
}
|
||||
return SurfaceReadPixelsSupport::kSupported;
|
||||
return SurfaceReadPixelsSupport::kUnsupported;
|
||||
}
|
||||
|
||||
bool GrD3DCaps::onSurfaceSupportsWritePixels(const GrSurface* surface) const {
|
||||
|
@ -395,8 +395,9 @@ void GrD3DDirectCommandList::clearRenderTargetView(const GrD3DRenderTarget* rend
|
||||
const D3D12_RECT* rect) {
|
||||
this->addingWork();
|
||||
this->addResource(renderTarget->resource());
|
||||
if (renderTarget->numSamples() > 1) {
|
||||
this->addResource(renderTarget->msaaTextureResource()->resource());
|
||||
const GrD3DTextureResource* msaaTextureResource = renderTarget->msaaTextureResource();
|
||||
if (msaaTextureResource && msaaTextureResource != renderTarget) {
|
||||
this->addResource(msaaTextureResource->resource());
|
||||
}
|
||||
unsigned int numRects = rect ? 1 : 0;
|
||||
fCommandList->ClearRenderTargetView(renderTarget->colorRenderTargetView(),
|
||||
@ -416,8 +417,9 @@ void GrD3DDirectCommandList::clearDepthStencilView(const GrD3DStencilAttachment*
|
||||
void GrD3DDirectCommandList::setRenderTarget(const GrD3DRenderTarget* renderTarget) {
|
||||
this->addingWork();
|
||||
this->addResource(renderTarget->resource());
|
||||
if (renderTarget->numSamples() > 1) {
|
||||
this->addResource(renderTarget->msaaTextureResource()->resource());
|
||||
const GrD3DTextureResource* msaaTextureResource = renderTarget->msaaTextureResource();
|
||||
if (msaaTextureResource && msaaTextureResource != renderTarget) {
|
||||
this->addResource(msaaTextureResource->resource());
|
||||
}
|
||||
D3D12_CPU_DESCRIPTOR_HANDLE rtvDescriptor = renderTarget->colorRenderTargetView();
|
||||
|
||||
|
@ -583,7 +583,7 @@ void GrD3DGpu::resolveTexture(GrSurface* dst, int32_t dstX, int32_t dstY,
|
||||
void GrD3DGpu::onResolveRenderTarget(GrRenderTarget* target, const SkIRect& resolveRect) {
|
||||
SkASSERT(target->numSamples() > 1);
|
||||
GrD3DRenderTarget* rt = static_cast<GrD3DRenderTarget*>(target);
|
||||
SkASSERT(rt->msaaTextureResource());
|
||||
SkASSERT(rt->msaaTextureResource() && rt != rt->msaaTextureResource());
|
||||
|
||||
this->resolveTexture(target, resolveRect.fLeft, resolveRect.fTop, rt, resolveRect);
|
||||
}
|
||||
@ -884,14 +884,6 @@ sk_sp<GrTexture> GrD3DGpu::onWrapRenderableBackendTexture(const GrBackendTexture
|
||||
}
|
||||
|
||||
sk_sp<GrRenderTarget> GrD3DGpu::onWrapBackendRenderTarget(const GrBackendRenderTarget& rt) {
|
||||
// Currently the Direct3D backend does not support wrapping of msaa render targets directly. In
|
||||
// general this is not an issue since swapchain images in D3D are never multisampled. Thus if
|
||||
// you want a multisampled RT it is best to wrap the swapchain images and then let Skia handle
|
||||
// creating and owning the MSAA images.
|
||||
if (rt.sampleCnt() > 1) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
GrD3DTextureResourceInfo info;
|
||||
if (!rt.getD3DTextureResourceInfo(&info)) {
|
||||
return nullptr;
|
||||
@ -913,7 +905,7 @@ sk_sp<GrRenderTarget> GrD3DGpu::onWrapBackendRenderTarget(const GrBackendRenderT
|
||||
sk_sp<GrD3DResourceState> state = rt.getGrD3DResourceState();
|
||||
|
||||
sk_sp<GrD3DRenderTarget> tgt = GrD3DRenderTarget::MakeWrappedRenderTarget(
|
||||
this, rt.dimensions(), 1, info, std::move(state));
|
||||
this, rt.dimensions(), rt.sampleCnt(), info, std::move(state));
|
||||
|
||||
// We don't allow the client to supply a premade stencil buffer. We always create one if needed.
|
||||
SkASSERT(!rt.stencilBits());
|
||||
@ -993,6 +985,7 @@ bool GrD3DGpu::createTextureResourceForBackendSurface(DXGI_FORMAT dxgiFormat,
|
||||
GrTexturable texturable,
|
||||
GrRenderable renderable,
|
||||
GrMipmapped mipMapped,
|
||||
int sampleCnt,
|
||||
GrD3DTextureResourceInfo* info,
|
||||
GrProtected isProtected) {
|
||||
SkASSERT(texturable == GrTexturable::kYes || renderable == GrRenderable::kYes);
|
||||
@ -1028,7 +1021,7 @@ bool GrD3DGpu::createTextureResourceForBackendSurface(DXGI_FORMAT dxgiFormat,
|
||||
resourceDesc.DepthOrArraySize = 1;
|
||||
resourceDesc.MipLevels = numMipLevels;
|
||||
resourceDesc.Format = dxgiFormat;
|
||||
resourceDesc.SampleDesc.Count = 1;
|
||||
resourceDesc.SampleDesc.Count = sampleCnt;
|
||||
resourceDesc.SampleDesc.Quality = DXGI_STANDARD_MULTISAMPLE_QUALITY_PATTERN;
|
||||
resourceDesc.Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN; // use driver-selected swizzle
|
||||
resourceDesc.Flags = usageFlags;
|
||||
@ -1082,8 +1075,8 @@ GrBackendTexture GrD3DGpu::onCreateBackendTexture(SkISize dimensions,
|
||||
|
||||
GrD3DTextureResourceInfo info;
|
||||
if (!this->createTextureResourceForBackendSurface(dxgiFormat, dimensions, GrTexturable::kYes,
|
||||
renderable, mipMapped,
|
||||
&info, isProtected)) {
|
||||
renderable, mipMapped, 1, &info,
|
||||
isProtected)) {
|
||||
return {};
|
||||
}
|
||||
|
||||
@ -1265,24 +1258,26 @@ bool GrD3DGpu::isTestingOnlyBackendTexture(const GrBackendTexture& tex) const {
|
||||
return !(textureResource->GetDesc().Flags & D3D12_RESOURCE_FLAG_DENY_SHADER_RESOURCE);
|
||||
}
|
||||
|
||||
GrBackendRenderTarget GrD3DGpu::createTestingOnlyBackendRenderTarget(int w, int h,
|
||||
GrColorType colorType) {
|
||||
GrBackendRenderTarget GrD3DGpu::createTestingOnlyBackendRenderTarget(SkISize dimensions,
|
||||
GrColorType colorType,
|
||||
int sampleCnt) {
|
||||
this->handleDirtyContext();
|
||||
|
||||
if (w > this->caps()->maxRenderTargetSize() || h > this->caps()->maxRenderTargetSize()) {
|
||||
if (dimensions.width() > this->caps()->maxRenderTargetSize() ||
|
||||
dimensions.height() > this->caps()->maxRenderTargetSize()) {
|
||||
return {};
|
||||
}
|
||||
|
||||
DXGI_FORMAT dxgiFormat = this->d3dCaps().getFormatFromColorType(colorType);
|
||||
|
||||
GrD3DTextureResourceInfo info;
|
||||
if (!this->createTextureResourceForBackendSurface(dxgiFormat, { w, h }, GrTexturable::kNo,
|
||||
if (!this->createTextureResourceForBackendSurface(dxgiFormat, dimensions, GrTexturable::kNo,
|
||||
GrRenderable::kYes, GrMipmapped::kNo,
|
||||
&info, GrProtected::kNo)) {
|
||||
sampleCnt, &info, GrProtected::kNo)) {
|
||||
return {};
|
||||
}
|
||||
|
||||
return GrBackendRenderTarget(w, h, info);
|
||||
return GrBackendRenderTarget(dimensions.width(), dimensions.height(), info);
|
||||
}
|
||||
|
||||
void GrD3DGpu::deleteTestingOnlyBackendRenderTarget(const GrBackendRenderTarget& rt) {
|
||||
|
@ -65,7 +65,9 @@ public:
|
||||
#if GR_TEST_UTILS
|
||||
bool isTestingOnlyBackendTexture(const GrBackendTexture&) const override;
|
||||
|
||||
GrBackendRenderTarget createTestingOnlyBackendRenderTarget(int w, int h, GrColorType) override;
|
||||
GrBackendRenderTarget createTestingOnlyBackendRenderTarget(SkISize,
|
||||
GrColorType,
|
||||
int sampleCnt) override;
|
||||
void deleteTestingOnlyBackendRenderTarget(const GrBackendRenderTarget&) override;
|
||||
|
||||
void testingOnly_flushGpuAndSync() override;
|
||||
@ -258,6 +260,7 @@ private:
|
||||
GrTexturable texturable,
|
||||
GrRenderable renderable,
|
||||
GrMipmapped mipMapped,
|
||||
int sampleCnt,
|
||||
GrD3DTextureResourceInfo* info,
|
||||
GrProtected isProtected);
|
||||
|
||||
|
@ -19,7 +19,6 @@
|
||||
// constructor must be explicitly called.
|
||||
GrD3DRenderTarget::GrD3DRenderTarget(GrD3DGpu* gpu,
|
||||
SkISize dimensions,
|
||||
int sampleCnt,
|
||||
const GrD3DTextureResourceInfo& info,
|
||||
sk_sp<GrD3DResourceState> state,
|
||||
const GrD3DTextureResourceInfo& msaaInfo,
|
||||
@ -30,12 +29,12 @@ GrD3DRenderTarget::GrD3DRenderTarget(GrD3DGpu* gpu,
|
||||
: GrSurface(gpu, dimensions, info.fProtected)
|
||||
, GrD3DTextureResource(info, std::move(state))
|
||||
// for the moment we only support 1:1 color to stencil
|
||||
, GrRenderTarget(gpu, dimensions, sampleCnt, info.fProtected)
|
||||
, GrRenderTarget(gpu, dimensions, msaaInfo.fSampleCount, info.fProtected)
|
||||
, fMSAATextureResource(new GrD3DTextureResource(msaaInfo, std::move(msaaState)))
|
||||
, fColorRenderTargetView(colorRenderTargetView)
|
||||
, fResolveRenderTargetView(resolveRenderTargetView) {
|
||||
SkASSERT(info.fProtected == msaaInfo.fProtected);
|
||||
SkASSERT(sampleCnt > 1);
|
||||
SkASSERT(msaaInfo.fSampleCount > 1);
|
||||
this->registerWithCacheWrapped(GrWrapCacheable::kNo);
|
||||
}
|
||||
|
||||
@ -43,7 +42,6 @@ GrD3DRenderTarget::GrD3DRenderTarget(GrD3DGpu* gpu,
|
||||
// constructor must be explicitly called.
|
||||
GrD3DRenderTarget::GrD3DRenderTarget(GrD3DGpu* gpu,
|
||||
SkISize dimensions,
|
||||
int sampleCnt,
|
||||
const GrD3DTextureResourceInfo& info,
|
||||
sk_sp<GrD3DResourceState> state,
|
||||
const GrD3DTextureResourceInfo& msaaInfo,
|
||||
@ -53,12 +51,12 @@ GrD3DRenderTarget::GrD3DRenderTarget(GrD3DGpu* gpu,
|
||||
: GrSurface(gpu, dimensions, info.fProtected)
|
||||
, GrD3DTextureResource(info, std::move(state))
|
||||
// for the moment we only support 1:1 color to stencil
|
||||
, GrRenderTarget(gpu, dimensions, sampleCnt, info.fProtected)
|
||||
, GrRenderTarget(gpu, dimensions, msaaInfo.fSampleCount, info.fProtected)
|
||||
, fMSAATextureResource(new GrD3DTextureResource(msaaInfo, std::move(msaaState)))
|
||||
, fColorRenderTargetView(colorRenderTargetView)
|
||||
, fResolveRenderTargetView(resolveRenderTargetView) {
|
||||
SkASSERT(info.fProtected == msaaInfo.fProtected);
|
||||
SkASSERT(sampleCnt > 1);
|
||||
SkASSERT(msaaInfo.fSampleCount > 1);
|
||||
}
|
||||
|
||||
// We're virtually derived from GrSurface (via GrRenderTarget) so its
|
||||
@ -71,7 +69,7 @@ GrD3DRenderTarget::GrD3DRenderTarget(GrD3DGpu* gpu,
|
||||
Wrapped)
|
||||
: GrSurface(gpu, dimensions, info.fProtected)
|
||||
, GrD3DTextureResource(info, std::move(state))
|
||||
, GrRenderTarget(gpu, dimensions, 1, info.fProtected)
|
||||
, GrRenderTarget(gpu, dimensions, info.fSampleCount, info.fProtected)
|
||||
, fMSAATextureResource(nullptr)
|
||||
, fColorRenderTargetView(renderTargetView) {
|
||||
this->registerWithCacheWrapped(GrWrapCacheable::kNo);
|
||||
@ -86,7 +84,7 @@ GrD3DRenderTarget::GrD3DRenderTarget(GrD3DGpu* gpu,
|
||||
const GrD3DDescriptorHeap::CPUHandle& renderTargetView)
|
||||
: GrSurface(gpu, dimensions, info.fProtected)
|
||||
, GrD3DTextureResource(info, std::move(state))
|
||||
, GrRenderTarget(gpu, dimensions, 1, info.fProtected)
|
||||
, GrRenderTarget(gpu, dimensions, info.fSampleCount, info.fProtected)
|
||||
, fMSAATextureResource(nullptr)
|
||||
, fColorRenderTargetView(renderTargetView) {}
|
||||
|
||||
@ -94,15 +92,20 @@ sk_sp<GrD3DRenderTarget> GrD3DRenderTarget::MakeWrappedRenderTarget(
|
||||
GrD3DGpu* gpu, SkISize dimensions, int sampleCnt, const GrD3DTextureResourceInfo& info,
|
||||
sk_sp<GrD3DResourceState> state) {
|
||||
SkASSERT(info.fResource.get());
|
||||
SkASSERT(info.fLevelCount == 1);
|
||||
SkASSERT(sampleCnt >= 1 && info.fSampleCount >= 1);
|
||||
|
||||
SkASSERT(1 == info.fLevelCount);
|
||||
int wrappedTextureSampleCnt = static_cast<int>(info.fSampleCount);
|
||||
if (sampleCnt != wrappedTextureSampleCnt && wrappedTextureSampleCnt != 1) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
GrD3DDescriptorHeap::CPUHandle renderTargetView =
|
||||
gpu->resourceProvider().createRenderTargetView(info.fResource.get());
|
||||
|
||||
// create msaa surface if necessary
|
||||
GrD3DRenderTarget* d3dRT;
|
||||
if (sampleCnt > 1) {
|
||||
if (sampleCnt != wrappedTextureSampleCnt) {
|
||||
GrD3DTextureResourceInfo msInfo;
|
||||
sk_sp<GrD3DResourceState> msState;
|
||||
// for wrapped MSAA surface we assume clear to white
|
||||
@ -113,9 +116,9 @@ sk_sp<GrD3DRenderTarget> GrD3DRenderTarget::MakeWrappedRenderTarget(
|
||||
GrD3DDescriptorHeap::CPUHandle msaaRenderTargetView =
|
||||
gpu->resourceProvider().createRenderTargetView(msInfo.fResource.get());
|
||||
|
||||
d3dRT = new GrD3DRenderTarget(gpu, dimensions, sampleCnt, info, std::move(state), msInfo,
|
||||
std::move(msState), msaaRenderTargetView,
|
||||
renderTargetView, kWrapped);
|
||||
d3dRT = new GrD3DRenderTarget(gpu, dimensions, info, std::move(state), msInfo,
|
||||
std::move(msState), msaaRenderTargetView, renderTargetView,
|
||||
kWrapped);
|
||||
} else {
|
||||
d3dRT = new GrD3DRenderTarget(gpu, dimensions, info, std::move(state), renderTargetView,
|
||||
kWrapped);
|
||||
@ -129,6 +132,23 @@ GrD3DRenderTarget::~GrD3DRenderTarget() {
|
||||
SkASSERT(!fMSAATextureResource);
|
||||
}
|
||||
|
||||
const GrD3DTextureResource* GrD3DRenderTarget::msaaTextureResource() const {
|
||||
if (this->numSamples() == 1) {
|
||||
SkASSERT(!fMSAATextureResource);
|
||||
return nullptr;
|
||||
}
|
||||
if (fMSAATextureResource) {
|
||||
return fMSAATextureResource.get();
|
||||
}
|
||||
SkASSERT(!fMSAATextureResource);
|
||||
return this;
|
||||
}
|
||||
|
||||
GrD3DTextureResource* GrD3DRenderTarget::msaaTextureResource() {
|
||||
auto* constThis = const_cast<const GrD3DRenderTarget*>(this);
|
||||
return const_cast<GrD3DTextureResource*>(constThis->msaaTextureResource());
|
||||
}
|
||||
|
||||
void GrD3DRenderTarget::releaseInternalObjects() {
|
||||
GrD3DGpu* gpu = this->getD3DGpu();
|
||||
|
||||
|
@ -31,7 +31,13 @@ public:
|
||||
|
||||
GrBackendFormat backendFormat() const override { return this->getBackendFormat(); }
|
||||
|
||||
GrD3DTextureResource* msaaTextureResource() const { return fMSAATextureResource.get(); }
|
||||
/**
|
||||
* If this render target is multisampled, this returns the MSAA texture for rendering. This
|
||||
* will be different than *this* when we have separate render/resolve images. If not
|
||||
* multisampled returns nullptr.
|
||||
*/
|
||||
const GrD3DTextureResource* msaaTextureResource() const;
|
||||
GrD3DTextureResource* msaaTextureResource();
|
||||
|
||||
bool canAttemptStencilAttachment() const override {
|
||||
return true;
|
||||
@ -51,7 +57,6 @@ public:
|
||||
protected:
|
||||
GrD3DRenderTarget(GrD3DGpu* gpu,
|
||||
SkISize dimensions,
|
||||
int sampleCnt,
|
||||
const GrD3DTextureResourceInfo& info,
|
||||
sk_sp<GrD3DResourceState> state,
|
||||
const GrD3DTextureResourceInfo& msaaInfo,
|
||||
@ -84,7 +89,6 @@ private:
|
||||
enum Wrapped { kWrapped };
|
||||
GrD3DRenderTarget(GrD3DGpu* gpu,
|
||||
SkISize dimensions,
|
||||
int sampleCnt,
|
||||
const GrD3DTextureResourceInfo& info,
|
||||
sk_sp<GrD3DResourceState> state,
|
||||
const GrD3DTextureResourceInfo& msaaInfo,
|
||||
|
@ -11,64 +11,88 @@
|
||||
#include "src/gpu/d3d/GrD3DGpu.h"
|
||||
|
||||
GrD3DTextureRenderTarget::GrD3DTextureRenderTarget(
|
||||
GrD3DGpu* gpu, SkBudgeted budgeted, SkISize dimensions, int sampleCnt,
|
||||
const GrD3DTextureResourceInfo& info, sk_sp<GrD3DResourceState> state,
|
||||
GrD3DGpu* gpu,
|
||||
SkBudgeted budgeted,
|
||||
SkISize dimensions,
|
||||
const GrD3DTextureResourceInfo& info,
|
||||
sk_sp<GrD3DResourceState> state,
|
||||
const GrD3DDescriptorHeap::CPUHandle& shaderResourceView,
|
||||
const GrD3DTextureResourceInfo& msaaInfo, sk_sp<GrD3DResourceState> msaaState,
|
||||
const GrD3DTextureResourceInfo& msaaInfo,
|
||||
sk_sp<GrD3DResourceState> msaaState,
|
||||
const GrD3DDescriptorHeap::CPUHandle& colorRenderTargetView,
|
||||
const GrD3DDescriptorHeap::CPUHandle& resolveRenderTargetView,
|
||||
GrMipmapStatus mipmapStatus)
|
||||
: GrSurface(gpu, dimensions, info.fProtected)
|
||||
, GrD3DTextureResource(info, state)
|
||||
, GrD3DTexture(gpu, dimensions, info, state, shaderResourceView, mipmapStatus)
|
||||
, GrD3DRenderTarget(gpu, dimensions, sampleCnt, info, state, msaaInfo,
|
||||
std::move(msaaState), colorRenderTargetView, resolveRenderTargetView) {
|
||||
: GrSurface(gpu, dimensions, info.fProtected)
|
||||
, GrD3DTextureResource(info, state)
|
||||
, GrD3DTexture(gpu, dimensions, info, state, shaderResourceView, mipmapStatus)
|
||||
, GrD3DRenderTarget(gpu,
|
||||
dimensions,
|
||||
info,
|
||||
state,
|
||||
msaaInfo,
|
||||
std::move(msaaState),
|
||||
colorRenderTargetView,
|
||||
resolveRenderTargetView) {
|
||||
SkASSERT(info.fProtected == msaaInfo.fProtected);
|
||||
this->registerWithCache(budgeted);
|
||||
}
|
||||
|
||||
GrD3DTextureRenderTarget::GrD3DTextureRenderTarget(
|
||||
GrD3DGpu* gpu, SkBudgeted budgeted, SkISize dimensions,
|
||||
const GrD3DTextureResourceInfo& info, sk_sp<GrD3DResourceState> state,
|
||||
GrD3DGpu* gpu,
|
||||
SkBudgeted budgeted,
|
||||
SkISize dimensions,
|
||||
const GrD3DTextureResourceInfo& info,
|
||||
sk_sp<GrD3DResourceState> state,
|
||||
const GrD3DDescriptorHeap::CPUHandle& shaderResourceView,
|
||||
const GrD3DDescriptorHeap::CPUHandle& renderTargetView,
|
||||
GrMipmapStatus mipmapStatus)
|
||||
: GrSurface(gpu, dimensions, info.fProtected)
|
||||
, GrD3DTextureResource(info, state)
|
||||
, GrD3DTexture(gpu, dimensions, info, state, shaderResourceView, mipmapStatus)
|
||||
, GrD3DRenderTarget(gpu, dimensions, info, state, renderTargetView) {
|
||||
: GrSurface(gpu, dimensions, info.fProtected)
|
||||
, GrD3DTextureResource(info, state)
|
||||
, GrD3DTexture(gpu, dimensions, info, state, shaderResourceView, mipmapStatus)
|
||||
, GrD3DRenderTarget(gpu, dimensions, info, state, renderTargetView) {
|
||||
this->registerWithCache(budgeted);
|
||||
}
|
||||
|
||||
GrD3DTextureRenderTarget::GrD3DTextureRenderTarget(
|
||||
GrD3DGpu* gpu, SkISize dimensions, int sampleCnt,
|
||||
const GrD3DTextureResourceInfo& info, sk_sp<GrD3DResourceState> state,
|
||||
GrD3DGpu* gpu,
|
||||
SkISize dimensions,
|
||||
const GrD3DTextureResourceInfo& info,
|
||||
sk_sp<GrD3DResourceState> state,
|
||||
const GrD3DDescriptorHeap::CPUHandle& shaderResourceView,
|
||||
const GrD3DTextureResourceInfo& msaaInfo, sk_sp<GrD3DResourceState> msaaState,
|
||||
const GrD3DTextureResourceInfo& msaaInfo,
|
||||
sk_sp<GrD3DResourceState> msaaState,
|
||||
const GrD3DDescriptorHeap::CPUHandle& colorRenderTargetView,
|
||||
const GrD3DDescriptorHeap::CPUHandle& resolveRenderTargetView,
|
||||
GrMipmapStatus mipmapStatus,
|
||||
GrWrapCacheable cacheable)
|
||||
: GrSurface(gpu, dimensions, info.fProtected)
|
||||
, GrD3DTextureResource(info, state)
|
||||
, GrD3DTexture(gpu, dimensions, info, state, shaderResourceView, mipmapStatus)
|
||||
, GrD3DRenderTarget(gpu, dimensions, sampleCnt, info, state, msaaInfo,
|
||||
std::move(msaaState), colorRenderTargetView, resolveRenderTargetView) {
|
||||
: GrSurface(gpu, dimensions, info.fProtected)
|
||||
, GrD3DTextureResource(info, state)
|
||||
, GrD3DTexture(gpu, dimensions, info, state, shaderResourceView, mipmapStatus)
|
||||
, GrD3DRenderTarget(gpu,
|
||||
dimensions,
|
||||
info,
|
||||
state,
|
||||
msaaInfo,
|
||||
std::move(msaaState),
|
||||
colorRenderTargetView,
|
||||
resolveRenderTargetView) {
|
||||
SkASSERT(info.fProtected == msaaInfo.fProtected);
|
||||
this->registerWithCacheWrapped(cacheable);
|
||||
}
|
||||
|
||||
GrD3DTextureRenderTarget::GrD3DTextureRenderTarget(
|
||||
GrD3DGpu* gpu, SkISize dimensions,
|
||||
const GrD3DTextureResourceInfo& info, sk_sp<GrD3DResourceState> state,
|
||||
GrD3DGpu* gpu,
|
||||
SkISize dimensions,
|
||||
const GrD3DTextureResourceInfo& info,
|
||||
sk_sp<GrD3DResourceState> state,
|
||||
const GrD3DDescriptorHeap::CPUHandle& shaderResourceView,
|
||||
const GrD3DDescriptorHeap::CPUHandle& renderTargetView,
|
||||
GrMipmapStatus mipmapStatus,
|
||||
GrWrapCacheable cacheable)
|
||||
: GrSurface(gpu, dimensions, info.fProtected)
|
||||
, GrD3DTextureResource(info, state)
|
||||
, GrD3DTexture(gpu, dimensions, info, state, shaderResourceView, mipmapStatus)
|
||||
, GrD3DRenderTarget(gpu, dimensions, info, state, renderTargetView) {
|
||||
: GrSurface(gpu, dimensions, info.fProtected)
|
||||
, GrD3DTextureResource(info, state)
|
||||
, GrD3DTexture(gpu, dimensions, info, state, shaderResourceView, mipmapStatus)
|
||||
, GrD3DRenderTarget(gpu, dimensions, info, state, renderTargetView) {
|
||||
this->registerWithCacheWrapped(cacheable);
|
||||
}
|
||||
|
||||
@ -117,8 +141,8 @@ sk_sp<GrD3DTextureRenderTarget> GrD3DTextureRenderTarget::MakeNewTextureRenderTa
|
||||
gpu->resourceProvider().createRenderTargetView(msInfo.fResource.get());
|
||||
|
||||
GrD3DTextureRenderTarget* trt = new GrD3DTextureRenderTarget(
|
||||
gpu, budgeted, dimensions, sampleCnt, info, std::move(state), shaderResourceView,
|
||||
msInfo, std::move(msState), msaaRenderTargetView, renderTargetView, mipmapStatus);
|
||||
gpu, budgeted, dimensions, info, std::move(state), shaderResourceView, msInfo,
|
||||
std::move(msState), msaaRenderTargetView, renderTargetView, mipmapStatus);
|
||||
return sk_sp<GrD3DTextureRenderTarget>(trt);
|
||||
} else {
|
||||
GrD3DTextureRenderTarget* trt = new GrD3DTextureRenderTarget(
|
||||
@ -161,8 +185,8 @@ sk_sp<GrD3DTextureRenderTarget> GrD3DTextureRenderTarget::MakeWrappedTextureRend
|
||||
gpu->resourceProvider().createRenderTargetView(msInfo.fResource.get());
|
||||
|
||||
GrD3DTextureRenderTarget* trt = new GrD3DTextureRenderTarget(
|
||||
gpu, dimensions, sampleCnt, info, std::move(state), shaderResourceView,
|
||||
msInfo, std::move(msState), msaaRenderTargetView, renderTargetView, mipmapStatus,
|
||||
gpu, dimensions, info, std::move(state), shaderResourceView, msInfo,
|
||||
std::move(msState), msaaRenderTargetView, renderTargetView, mipmapStatus,
|
||||
cacheable);
|
||||
return sk_sp<GrD3DTextureRenderTarget>(trt);
|
||||
} else {
|
||||
|
@ -56,7 +56,6 @@ private:
|
||||
GrD3DTextureRenderTarget(GrD3DGpu* gpu,
|
||||
SkBudgeted budgeted,
|
||||
SkISize dimensions,
|
||||
int sampleCnt,
|
||||
const GrD3DTextureResourceInfo& info,
|
||||
sk_sp<GrD3DResourceState> state,
|
||||
const GrD3DDescriptorHeap::CPUHandle& shaderResourceView,
|
||||
@ -79,7 +78,6 @@ private:
|
||||
// MSAA, wrapped
|
||||
GrD3DTextureRenderTarget(GrD3DGpu* gpu,
|
||||
SkISize dimensions,
|
||||
int sampleCnt,
|
||||
const GrD3DTextureResourceInfo& info,
|
||||
sk_sp<GrD3DResourceState> state,
|
||||
const GrD3DDescriptorHeap::CPUHandle& shaderResourceView,
|
||||
|
@ -52,6 +52,7 @@ bool GrD3DTextureResource::InitTextureResourceInfo(GrD3DGpu* gpu, const D3D12_RE
|
||||
info->fResourceState = initialState;
|
||||
info->fFormat = desc.Format;
|
||||
info->fLevelCount = desc.MipLevels;
|
||||
info->fSampleCount = desc.SampleDesc.Count;
|
||||
info->fSampleQualityPattern = desc.SampleDesc.Quality;
|
||||
info->fProtected = isProtected;
|
||||
|
||||
|
@ -431,15 +431,22 @@ bool GrDawnGpu::isTestingOnlyBackendTexture(const GrBackendTexture& tex) const {
|
||||
return info.fTexture.Get();
|
||||
}
|
||||
|
||||
GrBackendRenderTarget GrDawnGpu::createTestingOnlyBackendRenderTarget(int width, int height,
|
||||
GrColorType colorType) {
|
||||
if (width > this->caps()->maxTextureSize() || height > this->caps()->maxTextureSize()) {
|
||||
return GrBackendRenderTarget();
|
||||
GrBackendRenderTarget GrDawnGpu::createTestingOnlyBackendRenderTarget(SkISize dimensions,
|
||||
GrColorType colorType,
|
||||
int sampleCnt) {
|
||||
if (dimensions.width() > this->caps()->maxTextureSize() ||
|
||||
dimensions.height() > this->caps()->maxTextureSize()) {
|
||||
return {};
|
||||
}
|
||||
|
||||
// We don't support MSAA in this backend yet.
|
||||
if (sampleCnt != 1) {
|
||||
return {};
|
||||
}
|
||||
|
||||
wgpu::TextureFormat format;
|
||||
if (!GrColorTypeToDawnFormat(colorType, &format)) {
|
||||
return GrBackendRenderTarget();
|
||||
return {};
|
||||
}
|
||||
|
||||
wgpu::TextureDescriptor desc;
|
||||
@ -447,8 +454,8 @@ GrBackendRenderTarget GrDawnGpu::createTestingOnlyBackendRenderTarget(int width,
|
||||
wgpu::TextureUsage::CopySrc |
|
||||
wgpu::TextureUsage::OutputAttachment;
|
||||
|
||||
desc.size.width = width;
|
||||
desc.size.height = height;
|
||||
desc.size.width = dimensions.width();
|
||||
desc.size.height = dimensions.height();
|
||||
desc.size.depth = 1;
|
||||
desc.format = format;
|
||||
|
||||
@ -458,7 +465,8 @@ GrBackendRenderTarget GrDawnGpu::createTestingOnlyBackendRenderTarget(int width,
|
||||
info.fTextureView = tex.CreateView();
|
||||
info.fFormat = desc.format;
|
||||
info.fLevelCount = desc.mipLevelCount;
|
||||
return GrBackendRenderTarget(width, height, 1, 0, info);
|
||||
|
||||
return GrBackendRenderTarget(dimensions.width(), dimensions.height(), 1, 0, info);
|
||||
}
|
||||
|
||||
void GrDawnGpu::deleteTestingOnlyBackendRenderTarget(const GrBackendRenderTarget& rt) {
|
||||
|
@ -53,7 +53,9 @@ public:
|
||||
#if GR_TEST_UTILS
|
||||
bool isTestingOnlyBackendTexture(const GrBackendTexture&) const override;
|
||||
|
||||
GrBackendRenderTarget createTestingOnlyBackendRenderTarget(int w, int h, GrColorType) override;
|
||||
GrBackendRenderTarget createTestingOnlyBackendRenderTarget(SkISize,
|
||||
GrColorType,
|
||||
int sampleCnt) override;
|
||||
void deleteTestingOnlyBackendRenderTarget(const GrBackendRenderTarget&) override;
|
||||
|
||||
void testingOnly_flushGpuAndSync() override;
|
||||
|
@ -1805,13 +1805,10 @@ void GrGLCaps::initFormatTable(const GrGLContextInfo& ctxInfo, const GrGLInterfa
|
||||
// requires the src and dst be bindable to FBOs. However, we can't do this in the current
|
||||
// world since some devices (e.g. chromium & angle) require the formats in glBlitFramebuffer
|
||||
// to match. We don't have a way to really check this during resolve since we only actually
|
||||
// have GrBackendFormat that is shared by the GrGLRenderTarget.
|
||||
// have GrBackendFormat that is shared by the GrGLRenderTarget. We always set the
|
||||
// renderbuffer format to RGBA8 but disable MSAA unless we have the APPLE extension.
|
||||
// Once we break those up into different surface we can revisit doing this change.
|
||||
if (ctxInfo.hasExtension("GL_APPLE_texture_format_BGRA8888")) {
|
||||
info.fInternalFormatForRenderbuffer = GR_GL_RGBA8;
|
||||
} else {
|
||||
info.fInternalFormatForRenderbuffer = GR_GL_BGRA8;
|
||||
}
|
||||
info.fInternalFormatForRenderbuffer = GR_GL_RGBA8;
|
||||
|
||||
info.fDefaultExternalFormat = GR_GL_BGRA;
|
||||
info.fDefaultExternalType = GR_GL_UNSIGNED_BYTE;
|
||||
@ -4086,6 +4083,12 @@ GrCaps::SurfaceReadPixelsSupport GrGLCaps::surfaceSupportsReadPixels(
|
||||
if (tex->target() == GR_GL_TEXTURE_EXTERNAL || GrGLFormatIsCompressed(tex->format())) {
|
||||
return SurfaceReadPixelsSupport::kCopyToTexture2D;
|
||||
}
|
||||
} else if (auto rt = static_cast<const GrGLRenderTarget*>(surface->asRenderTarget())) {
|
||||
// glReadPixels does not allow reading back from a MSAA framebuffer. If the underlying
|
||||
// GrSurface doesn't have a second FBO to resolve to then we must make a copy.
|
||||
if (rt->numSamples() > 1 && rt->textureFBOID() == GrGLRenderTarget::kUnresolvableFBOID) {
|
||||
return SurfaceReadPixelsSupport::kCopyToTexture2D;
|
||||
}
|
||||
}
|
||||
return SurfaceReadPixelsSupport::kSupported;
|
||||
}
|
||||
|
@ -3702,24 +3702,46 @@ bool GrGLGpu::isTestingOnlyBackendTexture(const GrBackendTexture& tex) const {
|
||||
return (GR_GL_TRUE == result);
|
||||
}
|
||||
|
||||
GrBackendRenderTarget GrGLGpu::createTestingOnlyBackendRenderTarget(int w, int h,
|
||||
GrColorType colorType) {
|
||||
if (w > this->caps()->maxRenderTargetSize() || h > this->caps()->maxRenderTargetSize()) {
|
||||
return GrBackendRenderTarget(); // invalid
|
||||
GrBackendRenderTarget GrGLGpu::createTestingOnlyBackendRenderTarget(SkISize dimensions,
|
||||
GrColorType colorType,
|
||||
int sampleCnt) {
|
||||
if (dimensions.width() > this->caps()->maxRenderTargetSize() ||
|
||||
dimensions.height() > this->caps()->maxRenderTargetSize()) {
|
||||
return {};
|
||||
}
|
||||
this->handleDirtyContext();
|
||||
auto format = this->glCaps().getFormatFromColorType(colorType);
|
||||
if (!this->glCaps().isFormatRenderable(format, 1)) {
|
||||
sampleCnt = this->glCaps().getRenderTargetSampleCount(sampleCnt, format);
|
||||
if (!sampleCnt) {
|
||||
return {};
|
||||
}
|
||||
bool useTexture = format == GrGLFormat::kBGRA8;
|
||||
// We make a texture instead of a render target if we're using a
|
||||
// "multisampled_render_to_texture" style extension or have a BGRA format that
|
||||
// is allowed for textures but not render buffer internal formats.
|
||||
bool useTexture = false;
|
||||
if (sampleCnt > 1 && !this->glCaps().usesMSAARenderBuffers()) {
|
||||
useTexture = true;
|
||||
} else if (format == GrGLFormat::kBGRA8 &&
|
||||
this->glCaps().getRenderbufferInternalFormat(GrGLFormat::kBGRA8) != GR_GL_BGRA8) {
|
||||
// We have a BGRA extension that doesn't support BGRA render buffers. We can use a texture
|
||||
// unless we've been asked for MSAA. Note we already checked above for render-to-
|
||||
// multisampled-texture style extensions.
|
||||
if (sampleCnt > 1) {
|
||||
return {};
|
||||
}
|
||||
useTexture = true;
|
||||
}
|
||||
int sFormatIdx = this->getCompatibleStencilIndex(format);
|
||||
if (sFormatIdx < 0) {
|
||||
return {};
|
||||
}
|
||||
GrGLuint colorID = 0;
|
||||
GrGLuint stencilID = 0;
|
||||
auto deleteIDs = [&] {
|
||||
GrGLFramebufferInfo info;
|
||||
info.fFBOID = 0;
|
||||
info.fFormat = GrGLFormatToEnum(format);
|
||||
|
||||
auto deleteIDs = [&](bool saveFBO = false) {
|
||||
if (colorID) {
|
||||
if (useTexture) {
|
||||
GL_CALL(DeleteTextures(1, &colorID));
|
||||
@ -3730,6 +3752,9 @@ GrBackendRenderTarget GrGLGpu::createTestingOnlyBackendRenderTarget(int w, int h
|
||||
if (stencilID) {
|
||||
GL_CALL(DeleteRenderbuffers(1, &stencilID));
|
||||
}
|
||||
if (!saveFBO && info.fFBOID) {
|
||||
this->deleteFramebuffer(info.fFBOID);
|
||||
}
|
||||
};
|
||||
|
||||
if (useTexture) {
|
||||
@ -3743,9 +3768,6 @@ GrBackendRenderTarget GrGLGpu::createTestingOnlyBackendRenderTarget(int w, int h
|
||||
return {};
|
||||
}
|
||||
|
||||
GrGLFramebufferInfo info;
|
||||
info.fFBOID = 0;
|
||||
info.fFormat = GrGLFormatToEnum(format);
|
||||
GL_CALL(GenFramebuffers(1, &info.fFBOID));
|
||||
if (!info.fFBOID) {
|
||||
deleteIDs();
|
||||
@ -3757,24 +3779,47 @@ GrBackendRenderTarget GrGLGpu::createTestingOnlyBackendRenderTarget(int w, int h
|
||||
this->bindFramebuffer(GR_GL_FRAMEBUFFER, info.fFBOID);
|
||||
if (useTexture) {
|
||||
GrGLTextureParameters::SamplerOverriddenState initialState;
|
||||
colorID = this->createTexture({w, h}, format, GR_GL_TEXTURE_2D, GrRenderable::kYes,
|
||||
colorID = this->createTexture(dimensions, format, GR_GL_TEXTURE_2D, GrRenderable::kYes,
|
||||
&initialState, 1);
|
||||
if (!colorID) {
|
||||
deleteIDs();
|
||||
return {};
|
||||
}
|
||||
GL_CALL(FramebufferTexture2D(GR_GL_FRAMEBUFFER, GR_GL_COLOR_ATTACHMENT0, GR_GL_TEXTURE_2D,
|
||||
colorID, 0));
|
||||
if (sampleCnt == 1) {
|
||||
GL_CALL(FramebufferTexture2D(GR_GL_FRAMEBUFFER, GR_GL_COLOR_ATTACHMENT0,
|
||||
GR_GL_TEXTURE_2D, colorID, 0));
|
||||
} else {
|
||||
GL_CALL(FramebufferTexture2DMultisample(GR_GL_FRAMEBUFFER, GR_GL_COLOR_ATTACHMENT0,
|
||||
GR_GL_TEXTURE_2D, colorID, 0, sampleCnt));
|
||||
}
|
||||
} else {
|
||||
GrGLenum renderBufferFormat = this->glCaps().getRenderbufferInternalFormat(format);
|
||||
GL_CALL(BindRenderbuffer(GR_GL_RENDERBUFFER, colorID));
|
||||
GL_CALL(RenderbufferStorage(GR_GL_RENDERBUFFER, renderBufferFormat, w, h));
|
||||
if (sampleCnt == 1) {
|
||||
GL_CALL(RenderbufferStorage(GR_GL_RENDERBUFFER, renderBufferFormat, dimensions.width(),
|
||||
dimensions.height()));
|
||||
} else {
|
||||
if (!this->renderbufferStorageMSAA(this->glContext(), sampleCnt, renderBufferFormat,
|
||||
dimensions.width(), dimensions.height())) {
|
||||
deleteIDs();
|
||||
return {};
|
||||
}
|
||||
}
|
||||
GL_CALL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER, GR_GL_COLOR_ATTACHMENT0,
|
||||
GR_GL_RENDERBUFFER, colorID));
|
||||
}
|
||||
GL_CALL(BindRenderbuffer(GR_GL_RENDERBUFFER, stencilID));
|
||||
auto stencilBufferFormat = this->glCaps().stencilFormats()[sFormatIdx].fInternalFormat;
|
||||
GL_CALL(RenderbufferStorage(GR_GL_RENDERBUFFER, stencilBufferFormat, w, h));
|
||||
if (sampleCnt == 1) {
|
||||
GL_CALL(RenderbufferStorage(GR_GL_RENDERBUFFER, stencilBufferFormat, dimensions.width(),
|
||||
dimensions.height()));
|
||||
} else {
|
||||
if (!this->renderbufferStorageMSAA(this->glContext(), sampleCnt, stencilBufferFormat,
|
||||
dimensions.width(), dimensions.height())) {
|
||||
deleteIDs();
|
||||
return {};
|
||||
}
|
||||
}
|
||||
GL_CALL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER, GR_GL_STENCIL_ATTACHMENT, GR_GL_RENDERBUFFER,
|
||||
stencilID));
|
||||
if (this->glCaps().stencilFormats()[sFormatIdx].fPacked) {
|
||||
@ -3787,7 +3832,7 @@ GrBackendRenderTarget GrGLGpu::createTestingOnlyBackendRenderTarget(int w, int h
|
||||
// has the RB attached then deletion is delayed. So we unbind the FBO here and delete the
|
||||
// renderbuffers/texture.
|
||||
this->bindFramebuffer(GR_GL_FRAMEBUFFER, 0);
|
||||
deleteIDs();
|
||||
deleteIDs(/* saveFBO = */ true);
|
||||
|
||||
this->bindFramebuffer(GR_GL_FRAMEBUFFER, info.fFBOID);
|
||||
GrGLenum status;
|
||||
@ -3796,9 +3841,11 @@ GrBackendRenderTarget GrGLGpu::createTestingOnlyBackendRenderTarget(int w, int h
|
||||
this->deleteFramebuffer(info.fFBOID);
|
||||
return {};
|
||||
}
|
||||
|
||||
auto stencilBits = SkToInt(this->glCaps().stencilFormats()[sFormatIdx].fStencilBits);
|
||||
|
||||
GrBackendRenderTarget beRT = GrBackendRenderTarget(w, h, 1, stencilBits, info);
|
||||
GrBackendRenderTarget beRT = GrBackendRenderTarget(dimensions.width(), dimensions.height(),
|
||||
sampleCnt, stencilBits, info);
|
||||
SkASSERT(this->caps()->areColorTypeAndFormatCompatible(colorType, beRT.getBackendFormat()));
|
||||
return beRT;
|
||||
}
|
||||
|
@ -144,7 +144,9 @@ public:
|
||||
#if GR_TEST_UTILS
|
||||
bool isTestingOnlyBackendTexture(const GrBackendTexture&) const override;
|
||||
|
||||
GrBackendRenderTarget createTestingOnlyBackendRenderTarget(int w, int h, GrColorType) override;
|
||||
GrBackendRenderTarget createTestingOnlyBackendRenderTarget(SkISize,
|
||||
GrColorType,
|
||||
int sampleCnt) override;
|
||||
void deleteTestingOnlyBackendRenderTarget(const GrBackendRenderTarget&) override;
|
||||
|
||||
const GrGLContext* glContextForTesting() const override { return &this->glContext(); }
|
||||
|
@ -334,12 +334,13 @@ bool GrMockGpu::isTestingOnlyBackendTexture(const GrBackendTexture& tex) const {
|
||||
return fOutstandingTestingOnlyTextureIDs.contains(info.id());
|
||||
}
|
||||
|
||||
GrBackendRenderTarget GrMockGpu::createTestingOnlyBackendRenderTarget(int w, int h,
|
||||
GrColorType colorType) {
|
||||
GrBackendRenderTarget GrMockGpu::createTestingOnlyBackendRenderTarget(SkISize dimensions,
|
||||
GrColorType colorType,
|
||||
int sampleCnt) {
|
||||
GrMockRenderTargetInfo info(colorType, NextExternalRenderTargetID());
|
||||
static constexpr int kSampleCnt = 1;
|
||||
static constexpr int kStencilBits = 8;
|
||||
return GrBackendRenderTarget(w, h, kSampleCnt, kStencilBits, info);
|
||||
return GrBackendRenderTarget(dimensions.width(), dimensions.height(), sampleCnt, kStencilBits,
|
||||
info);
|
||||
}
|
||||
|
||||
void GrMockGpu::deleteTestingOnlyBackendRenderTarget(const GrBackendRenderTarget&) {}
|
||||
|
@ -177,7 +177,9 @@ private:
|
||||
#if GR_TEST_UTILS
|
||||
bool isTestingOnlyBackendTexture(const GrBackendTexture&) const override;
|
||||
|
||||
GrBackendRenderTarget createTestingOnlyBackendRenderTarget(int w, int h, GrColorType) override;
|
||||
GrBackendRenderTarget createTestingOnlyBackendRenderTarget(SkISize dimensions,
|
||||
GrColorType,
|
||||
int sampleCnt) override;
|
||||
void deleteTestingOnlyBackendRenderTarget(const GrBackendRenderTarget&) override;
|
||||
|
||||
void testingOnly_flushGpuAndSync() override {}
|
||||
|
@ -48,9 +48,10 @@ public:
|
||||
const GrBackendFormat& surfaceFormat,
|
||||
GrColorType srcColorType) const override;
|
||||
|
||||
SurfaceReadPixelsSupport surfaceSupportsReadPixels(const GrSurface*) const override {
|
||||
return SurfaceReadPixelsSupport::kSupported;
|
||||
}
|
||||
SurfaceReadPixelsSupport surfaceSupportsReadPixels(const GrSurface*) const override;
|
||||
|
||||
DstCopyRestrictions getDstCopyRestrictions(const GrRenderTargetProxy* src,
|
||||
GrColorType ct) const override;
|
||||
|
||||
/**
|
||||
* Returns both a supported and most prefered stencil format to use in draws.
|
||||
@ -59,17 +60,27 @@ public:
|
||||
return fPreferredStencilFormat;
|
||||
}
|
||||
|
||||
bool canCopyAsBlit(GrSurface* dst, int dstSampleCount, GrSurface* src, int srcSampleCount,
|
||||
const SkIRect& srcRect, const SkIPoint& dstPoint,
|
||||
bool areDstSrcSameObj) const;
|
||||
bool canCopyAsBlit(GrSurface* dst,
|
||||
GrSurface* src,
|
||||
const SkIRect& srcRect,
|
||||
const SkIPoint& dstPoint) const;
|
||||
|
||||
bool canCopyAsBlit(MTLPixelFormat dstFormat, int dstSampleCount,
|
||||
MTLPixelFormat srcFormat, int srcSampleCount,
|
||||
const SkIRect& srcRect, const SkIPoint& dstPoint,
|
||||
bool areDstSrcSameObj) const;
|
||||
|
||||
bool canCopyAsResolve(GrSurface* dst, int dstSampleCount, GrSurface* src, int srcSampleCount,
|
||||
const SkIRect& srcRect, const SkIPoint& dstPoint) const;
|
||||
bool canCopyAsResolve(GrSurface* dst,
|
||||
GrSurface* src,
|
||||
const SkIRect& srcRect,
|
||||
const SkIPoint& dstPoint) const;
|
||||
|
||||
bool canCopyAsResolve(MTLPixelFormat dstFormat, int dstSampleCount,
|
||||
MTLPixelFormat srcFormat, int srcSampleCount,
|
||||
bool srcIsRenderTarget, const SkISize srcDimensions,
|
||||
const SkIRect& srcRect,
|
||||
const SkIPoint& dstPoint,
|
||||
bool areDstSrcSameObj) const;
|
||||
|
||||
GrBackendFormat getBackendFormatFromCompressionType(SkImage::CompressionType) const override;
|
||||
|
||||
|
@ -18,6 +18,7 @@
|
||||
#include "src/gpu/GrRenderTargetProxy.h"
|
||||
#include "src/gpu/GrShaderCaps.h"
|
||||
#include "src/gpu/GrSurfaceProxy.h"
|
||||
#include "src/gpu/mtl/GrMtlRenderTarget.h"
|
||||
#include "src/gpu/mtl/GrMtlUtil.h"
|
||||
|
||||
#if !__has_feature(objc_arc)
|
||||
@ -128,10 +129,29 @@ void GrMtlCaps::initFeatureSet(MTLFeatureSet featureSet) {
|
||||
SK_ABORT("Requested an unsupported feature set");
|
||||
}
|
||||
|
||||
bool GrMtlCaps::canCopyAsBlit(GrSurface* dst, int dstSampleCount,
|
||||
GrSurface* src, int srcSampleCount,
|
||||
const SkIRect& srcRect, const SkIPoint& dstPoint,
|
||||
bool areDstSrcSameObj) const {
|
||||
static int get_surface_sample_cnt(GrSurface* surf) {
|
||||
if (const GrRenderTarget* rt = surf->asRenderTarget()) {
|
||||
return rt->numSamples();
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static bool is_resolving_msaa(GrSurface* surf) {
|
||||
auto rt = static_cast<GrMtlRenderTarget*>(surf->asRenderTarget());
|
||||
if (rt && rt->mtlResolveTexture()) {
|
||||
SkASSERT(rt->numSamples() > 1);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool GrMtlCaps::canCopyAsBlit(GrSurface* dst,
|
||||
GrSurface* src,
|
||||
const SkIRect& srcRect,
|
||||
const SkIPoint& dstPoint) const {
|
||||
if (is_resolving_msaa(src) || is_resolving_msaa(dst)) {
|
||||
return false;
|
||||
}
|
||||
id<MTLTexture> dstTex = GrGetMTLTextureFromSurface(dst);
|
||||
id<MTLTexture> srcTex = GrGetMTLTextureFromSurface(src);
|
||||
if (srcTex.framebufferOnly || dstTex.framebufferOnly) {
|
||||
@ -140,9 +160,11 @@ bool GrMtlCaps::canCopyAsBlit(GrSurface* dst, int dstSampleCount,
|
||||
|
||||
MTLPixelFormat dstFormat = dstTex.pixelFormat;
|
||||
MTLPixelFormat srcFormat = srcTex.pixelFormat;
|
||||
int srcSampleCount = get_surface_sample_cnt(src);
|
||||
int dstSampleCount = get_surface_sample_cnt(dst);
|
||||
|
||||
return this->canCopyAsBlit(dstFormat, dstSampleCount, srcFormat, srcSampleCount,
|
||||
srcRect, dstPoint, areDstSrcSameObj);
|
||||
return this->canCopyAsBlit(dstFormat, dstSampleCount, srcFormat, srcSampleCount, srcRect,
|
||||
dstPoint, src == dst);
|
||||
}
|
||||
|
||||
bool GrMtlCaps::canCopyAsBlit(MTLPixelFormat dstFormat, int dstSampleCount,
|
||||
@ -165,16 +187,35 @@ bool GrMtlCaps::canCopyAsBlit(MTLPixelFormat dstFormat, int dstSampleCount,
|
||||
return true;
|
||||
}
|
||||
|
||||
bool GrMtlCaps::canCopyAsResolve(GrSurface* dst, int dstSampleCount,
|
||||
GrSurface* src, int srcSampleCount,
|
||||
const SkIRect& srcRect, const SkIPoint& dstPoint) const {
|
||||
if (dst == src) {
|
||||
bool GrMtlCaps::canCopyAsResolve(GrSurface* dst,
|
||||
GrSurface* src,
|
||||
const SkIRect& srcRect,
|
||||
const SkIPoint& dstPoint) const {
|
||||
MTLPixelFormat dstFormat = GrBackendFormatAsMTLPixelFormat(dst->backendFormat());
|
||||
MTLPixelFormat srcFormat = GrBackendFormatAsMTLPixelFormat(src->backendFormat());
|
||||
|
||||
int srcSampleCount = get_surface_sample_cnt(src);
|
||||
int dstSampleCount = get_surface_sample_cnt(dst);
|
||||
|
||||
bool srcIsRenderTarget = src->asRenderTarget();
|
||||
SkISize srcSize = src->dimensions();
|
||||
return this->canCopyAsResolve(dstFormat, dstSampleCount, srcFormat, srcSampleCount,
|
||||
srcIsRenderTarget, srcSize, srcRect, dstPoint, src == dst);
|
||||
}
|
||||
|
||||
bool GrMtlCaps::canCopyAsResolve(MTLPixelFormat dstFormat, int dstSampleCount,
|
||||
MTLPixelFormat srcFormat, int srcSampleCount,
|
||||
bool srcIsRenderTarget, const SkISize srcDimensions,
|
||||
const SkIRect& srcRect,
|
||||
const SkIPoint& dstPoint,
|
||||
bool areDstSrcSameObj) const {
|
||||
if (areDstSrcSameObj) {
|
||||
return false;
|
||||
}
|
||||
if (dst->backendFormat() != src->backendFormat()) {
|
||||
if (dstFormat != srcFormat) {
|
||||
return false;
|
||||
}
|
||||
if (dstSampleCount > 1 || srcSampleCount == 1 || !src->asRenderTarget()) {
|
||||
if (dstSampleCount > 1 || srcSampleCount == 1 || !srcIsRenderTarget) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -182,7 +223,7 @@ bool GrMtlCaps::canCopyAsResolve(GrSurface* dst, int dstSampleCount,
|
||||
if (dstPoint != SkIPoint::Make(0, 0)) {
|
||||
return false;
|
||||
}
|
||||
if (srcRect != SkIRect::MakeXYWH(0, 0, src->width(), src->height())) {
|
||||
if (srcRect != SkIRect::MakeSize(srcDimensions)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -191,22 +232,30 @@ bool GrMtlCaps::canCopyAsResolve(GrSurface* dst, int dstSampleCount,
|
||||
|
||||
bool GrMtlCaps::onCanCopySurface(const GrSurfaceProxy* dst, const GrSurfaceProxy* src,
|
||||
const SkIRect& srcRect, const SkIPoint& dstPoint) const {
|
||||
int dstSampleCnt = 0;
|
||||
int srcSampleCnt = 0;
|
||||
int dstSampleCnt = 1;
|
||||
int srcSampleCnt = 1;
|
||||
if (const GrRenderTargetProxy* rtProxy = dst->asRenderTargetProxy()) {
|
||||
dstSampleCnt = rtProxy->numSamples();
|
||||
}
|
||||
if (const GrRenderTargetProxy* rtProxy = src->asRenderTargetProxy()) {
|
||||
srcSampleCnt = rtProxy->numSamples();
|
||||
}
|
||||
SkASSERT((dstSampleCnt > 0) == SkToBool(dst->asRenderTargetProxy()));
|
||||
SkASSERT((srcSampleCnt > 0) == SkToBool(src->asRenderTargetProxy()));
|
||||
|
||||
// TODO: need some way to detect whether the proxy is framebufferOnly
|
||||
|
||||
return this->canCopyAsBlit(GrBackendFormatAsMTLPixelFormat(dst->backendFormat()), dstSampleCnt,
|
||||
GrBackendFormatAsMTLPixelFormat(src->backendFormat()), srcSampleCnt,
|
||||
srcRect, dstPoint, dst == src);
|
||||
if (this->canCopyAsBlit(GrBackendFormatAsMTLPixelFormat(dst->backendFormat()), dstSampleCnt,
|
||||
GrBackendFormatAsMTLPixelFormat(src->backendFormat()), srcSampleCnt,
|
||||
srcRect, dstPoint, dst == src)) {
|
||||
return true;
|
||||
}
|
||||
bool srcIsRenderTarget = src->asRenderTargetProxy();
|
||||
MTLPixelFormat dstFormat = GrBackendFormatAsMTLPixelFormat(dst->backendFormat());
|
||||
MTLPixelFormat srcFormat = GrBackendFormatAsMTLPixelFormat(src->backendFormat());
|
||||
return this->canCopyAsResolve(dstFormat, dstSampleCnt,
|
||||
srcFormat, srcSampleCnt,
|
||||
srcIsRenderTarget, src->backingStoreDimensions(), srcRect,
|
||||
dstPoint,
|
||||
dst == src);
|
||||
}
|
||||
|
||||
void GrMtlCaps::initGrCaps(const id<MTLDevice> device) {
|
||||
@ -853,6 +902,31 @@ bool GrMtlCaps::onSurfaceSupportsWritePixels(const GrSurface* surface) const {
|
||||
return true;
|
||||
}
|
||||
|
||||
GrCaps::SurfaceReadPixelsSupport GrMtlCaps::surfaceSupportsReadPixels(
|
||||
const GrSurface* surface) const {
|
||||
if (auto mtlRT = static_cast<const GrMtlRenderTarget*>(surface->asRenderTarget())) {
|
||||
if (mtlRT->numSamples() > 1 && !mtlRT->mtlResolveTexture()) {
|
||||
return SurfaceReadPixelsSupport::kCopyToTexture2D;
|
||||
}
|
||||
}
|
||||
return SurfaceReadPixelsSupport::kSupported;
|
||||
}
|
||||
|
||||
GrCaps::DstCopyRestrictions GrMtlCaps::getDstCopyRestrictions(const GrRenderTargetProxy* src,
|
||||
GrColorType ct) const {
|
||||
// If the src is a MSAA RT then the only supported copy action (not considering falling back
|
||||
// to a draw) is to resolve from the MSAA src to the non-MSAA dst. Currently we only support
|
||||
// resolving the entire texture to a resolve buffer of the same size.
|
||||
DstCopyRestrictions restrictions = {};
|
||||
if (auto rtProxy = src->asRenderTargetProxy()) {
|
||||
if (rtProxy->numSamples() > 1) {
|
||||
restrictions.fMustCopyWholeSrc = true;
|
||||
restrictions.fRectsMustMatch = GrSurfaceProxy::RectsMustMatch::kYes;
|
||||
}
|
||||
}
|
||||
return restrictions;
|
||||
}
|
||||
|
||||
bool GrMtlCaps::onAreColorTypeAndFormatCompatible(GrColorType ct,
|
||||
const GrBackendFormat& format) const {
|
||||
MTLPixelFormat mtlFormat = GrBackendFormatAsMTLPixelFormat(format);
|
||||
|
@ -65,7 +65,9 @@ public:
|
||||
#if GR_TEST_UTILS
|
||||
bool isTestingOnlyBackendTexture(const GrBackendTexture&) const override;
|
||||
|
||||
GrBackendRenderTarget createTestingOnlyBackendRenderTarget(int w, int h, GrColorType) override;
|
||||
GrBackendRenderTarget createTestingOnlyBackendRenderTarget(SkISize,
|
||||
GrColorType,
|
||||
int sampleCnt) override;
|
||||
void deleteTestingOnlyBackendRenderTarget(const GrBackendRenderTarget&) override;
|
||||
|
||||
void testingOnly_flushGpuAndSync() override;
|
||||
@ -241,6 +243,7 @@ private:
|
||||
|
||||
bool createMtlTextureForBackendSurface(MTLPixelFormat,
|
||||
SkISize dimensions,
|
||||
int sampleCnt,
|
||||
GrTexturable,
|
||||
GrRenderable,
|
||||
GrMipmapped,
|
||||
|
@ -769,10 +769,10 @@ sk_sp<GrTexture> GrMtlGpu::onWrapRenderableBackendTexture(const GrBackendTexture
|
||||
}
|
||||
|
||||
sk_sp<GrRenderTarget> GrMtlGpu::onWrapBackendRenderTarget(const GrBackendRenderTarget& backendRT) {
|
||||
// TODO: Revisit this when the Metal backend is completed. It may support MSAA render targets.
|
||||
if (backendRT.sampleCnt() > 1) {
|
||||
if (!this->caps()->isFormatRenderable(backendRT.getBackendFormat(), backendRT.sampleCnt())) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
id<MTLTexture> mtlTexture = get_texture_from_backend(backendRT);
|
||||
if (!mtlTexture) {
|
||||
return nullptr;
|
||||
@ -875,6 +875,7 @@ void copy_src_data(char* dst, size_t bytesPerPixel, const SkTArray<size_t>& indi
|
||||
|
||||
bool GrMtlGpu::createMtlTextureForBackendSurface(MTLPixelFormat mtlFormat,
|
||||
SkISize dimensions,
|
||||
int sampleCnt,
|
||||
GrTexturable texturable,
|
||||
GrRenderable renderable,
|
||||
GrMipmapped mipMapped,
|
||||
@ -902,6 +903,10 @@ bool GrMtlGpu::createMtlTextureForBackendSurface(MTLPixelFormat mtlFormat,
|
||||
desc.usage = texturable == GrTexturable::kYes ? MTLTextureUsageShaderRead : 0;
|
||||
desc.usage |= renderable == GrRenderable::kYes ? MTLTextureUsageRenderTarget : 0;
|
||||
}
|
||||
if (sampleCnt != 1) {
|
||||
desc.sampleCount = sampleCnt;
|
||||
desc.textureType = MTLTextureType2DMultisample;
|
||||
}
|
||||
id<MTLTexture> testTexture = [fDevice newTextureWithDescriptor: desc];
|
||||
info->fTexture.reset(GrRetainPtrFromId(testTexture));
|
||||
return true;
|
||||
@ -915,7 +920,7 @@ GrBackendTexture GrMtlGpu::onCreateBackendTexture(SkISize dimensions,
|
||||
const MTLPixelFormat mtlFormat = GrBackendFormatAsMTLPixelFormat(format);
|
||||
|
||||
GrMtlTextureInfo info;
|
||||
if (!this->createMtlTextureForBackendSurface(mtlFormat, dimensions, GrTexturable::kYes,
|
||||
if (!this->createMtlTextureForBackendSurface(mtlFormat, dimensions, 1, GrTexturable::kYes,
|
||||
renderable, mipMapped, &info)) {
|
||||
return {};
|
||||
}
|
||||
@ -1056,7 +1061,7 @@ GrBackendTexture GrMtlGpu::onCreateCompressedBackendTexture(
|
||||
const MTLPixelFormat mtlFormat = GrBackendFormatAsMTLPixelFormat(format);
|
||||
|
||||
GrMtlTextureInfo info;
|
||||
if (!this->createMtlTextureForBackendSurface(mtlFormat, dimensions, GrTexturable::kYes,
|
||||
if (!this->createMtlTextureForBackendSurface(mtlFormat, dimensions, 1, GrTexturable::kYes,
|
||||
GrRenderable::kNo, mipMapped, &info)) {
|
||||
return {};
|
||||
}
|
||||
@ -1098,25 +1103,27 @@ bool GrMtlGpu::isTestingOnlyBackendTexture(const GrBackendTexture& tex) const {
|
||||
}
|
||||
}
|
||||
|
||||
GrBackendRenderTarget GrMtlGpu::createTestingOnlyBackendRenderTarget(int w, int h, GrColorType ct) {
|
||||
if (w > this->caps()->maxRenderTargetSize() || h > this->caps()->maxRenderTargetSize()) {
|
||||
return GrBackendRenderTarget();
|
||||
}
|
||||
|
||||
MTLPixelFormat format = this->mtlCaps().getFormatFromColorType(ct);
|
||||
if (format == MTLPixelFormatInvalid) {
|
||||
return GrBackendRenderTarget();
|
||||
}
|
||||
|
||||
GrMtlTextureInfo info;
|
||||
if (!this->createMtlTextureForBackendSurface(format, {w, h}, GrTexturable::kNo,
|
||||
GrRenderable::kYes,
|
||||
GrMipmapped::kNo, &info)) {
|
||||
GrBackendRenderTarget GrMtlGpu::createTestingOnlyBackendRenderTarget(SkISize dimensions,
|
||||
GrColorType ct,
|
||||
int sampleCnt) {
|
||||
if (dimensions.width() > this->caps()->maxRenderTargetSize() ||
|
||||
dimensions.height() > this->caps()->maxRenderTargetSize()) {
|
||||
return {};
|
||||
}
|
||||
|
||||
GrBackendRenderTarget backendRT(w, h, info);
|
||||
return backendRT;
|
||||
MTLPixelFormat format = this->mtlCaps().getFormatFromColorType(ct);
|
||||
sampleCnt = this->mtlCaps().getRenderTargetSampleCount(sampleCnt, format);
|
||||
if (sampleCnt == 0) {
|
||||
return {};
|
||||
}
|
||||
|
||||
GrMtlTextureInfo info;
|
||||
if (!this->createMtlTextureForBackendSurface(format, dimensions, sampleCnt, GrTexturable::kNo,
|
||||
GrRenderable::kYes, GrMipmapped::kNo, &info)) {
|
||||
return {};
|
||||
}
|
||||
|
||||
return GrBackendRenderTarget(dimensions.width(), dimensions.height(), info);
|
||||
}
|
||||
|
||||
void GrMtlGpu::deleteTestingOnlyBackendRenderTarget(const GrBackendRenderTarget& rt) {
|
||||
@ -1135,13 +1142,6 @@ void GrMtlGpu::testingOnly_flushGpuAndSync() {
|
||||
}
|
||||
#endif // GR_TEST_UTILS
|
||||
|
||||
static int get_surface_sample_cnt(GrSurface* surf) {
|
||||
if (const GrRenderTarget* rt = surf->asRenderTarget()) {
|
||||
return rt->numSamples();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void GrMtlGpu::copySurfaceAsResolve(GrSurface* dst, GrSurface* src) {
|
||||
// TODO: Add support for subrectangles
|
||||
GrMtlRenderTarget* srcRT = static_cast<GrMtlRenderTarget*>(src->asRenderTarget());
|
||||
@ -1161,10 +1161,7 @@ void GrMtlGpu::copySurfaceAsResolve(GrSurface* dst, GrSurface* src) {
|
||||
void GrMtlGpu::copySurfaceAsBlit(GrSurface* dst, GrSurface* src, const SkIRect& srcRect,
|
||||
const SkIPoint& dstPoint) {
|
||||
#ifdef SK_DEBUG
|
||||
int dstSampleCnt = get_surface_sample_cnt(dst);
|
||||
int srcSampleCnt = get_surface_sample_cnt(src);
|
||||
SkASSERT(this->mtlCaps().canCopyAsBlit(dst, dstSampleCnt, src, srcSampleCnt,
|
||||
srcRect, dstPoint, dst == src));
|
||||
SkASSERT(this->mtlCaps().canCopyAsBlit(dst, src, srcRect, dstPoint));
|
||||
#endif
|
||||
id<MTLTexture> dstTex = GrGetMTLTextureFromSurface(dst);
|
||||
id<MTLTexture> srcTex = GrGetMTLTextureFromSurface(src);
|
||||
@ -1185,17 +1182,13 @@ bool GrMtlGpu::onCopySurface(GrSurface* dst, GrSurface* src, const SkIRect& srcR
|
||||
const SkIPoint& dstPoint) {
|
||||
SkASSERT(!src->isProtected() && !dst->isProtected());
|
||||
|
||||
int dstSampleCnt = get_surface_sample_cnt(dst);
|
||||
int srcSampleCnt = get_surface_sample_cnt(src);
|
||||
|
||||
bool success = false;
|
||||
if (this->mtlCaps().canCopyAsResolve(dst, dstSampleCnt, src, srcSampleCnt, srcRect, dstPoint)) {
|
||||
if (this->mtlCaps().canCopyAsBlit(dst, src, srcRect, dstPoint)) {
|
||||
this->copySurfaceAsBlit(dst, src, srcRect, dstPoint);
|
||||
success = true;
|
||||
} else if (this->mtlCaps().canCopyAsResolve(dst, src, srcRect, dstPoint)) {
|
||||
this->copySurfaceAsResolve(dst, src);
|
||||
success = true;
|
||||
} else if (this->mtlCaps().canCopyAsBlit(dst, dstSampleCnt, src, srcSampleCnt, srcRect,
|
||||
dstPoint, dst == src)) {
|
||||
this->copySurfaceAsBlit(dst, src, srcRect, dstPoint);
|
||||
success = true;
|
||||
}
|
||||
if (success) {
|
||||
SkIRect dstRect = SkIRect::MakeXYWH(dstPoint.x(), dstPoint.y(),
|
||||
|
@ -19,6 +19,8 @@ class GrMtlGpu;
|
||||
|
||||
class GrMtlRenderTarget: public GrRenderTarget {
|
||||
public:
|
||||
// If sampleCnt is greater than 1 and the texture is single sampled, then a MSAA texture
|
||||
// is created that will resolve to the wrapped single sample texture.
|
||||
static sk_sp<GrMtlRenderTarget> MakeWrappedRenderTarget(GrMtlGpu*,
|
||||
SkISize,
|
||||
int sampleCnt,
|
||||
|
@ -71,32 +71,39 @@ sk_sp<GrMtlRenderTarget> GrMtlRenderTarget::MakeWrappedRenderTarget(GrMtlGpu* gp
|
||||
|
||||
GrMtlRenderTarget* mtlRT;
|
||||
if (sampleCnt > 1) {
|
||||
MTLPixelFormat format = texture.pixelFormat;
|
||||
if (!gpu->mtlCaps().isFormatRenderable(format, sampleCnt)) {
|
||||
return nullptr;
|
||||
}
|
||||
MTLTextureDescriptor* texDesc = [[MTLTextureDescriptor alloc] init];
|
||||
texDesc.textureType = MTLTextureType2DMultisample;
|
||||
texDesc.pixelFormat = format;
|
||||
texDesc.width = dimensions.fWidth;
|
||||
texDesc.height = dimensions.fHeight;
|
||||
texDesc.depth = 1;
|
||||
texDesc.mipmapLevelCount = 1;
|
||||
texDesc.sampleCount = sampleCnt;
|
||||
texDesc.arrayLength = 1;
|
||||
if (@available(macOS 10.11, iOS 9.0, *)) {
|
||||
texDesc.storageMode = MTLStorageModePrivate;
|
||||
texDesc.usage = MTLTextureUsageShaderRead | MTLTextureUsageRenderTarget;
|
||||
}
|
||||
if ([texture sampleCount] == 1) {
|
||||
MTLPixelFormat format = texture.pixelFormat;
|
||||
if (!gpu->mtlCaps().isFormatRenderable(format, sampleCnt)) {
|
||||
return nullptr;
|
||||
}
|
||||
MTLTextureDescriptor* texDesc = [[MTLTextureDescriptor alloc] init];
|
||||
texDesc.textureType = MTLTextureType2DMultisample;
|
||||
texDesc.pixelFormat = format;
|
||||
texDesc.width = dimensions.fWidth;
|
||||
texDesc.height = dimensions.fHeight;
|
||||
texDesc.depth = 1;
|
||||
texDesc.mipmapLevelCount = 1;
|
||||
texDesc.sampleCount = sampleCnt;
|
||||
texDesc.arrayLength = 1;
|
||||
if (@available(macOS 10.11, iOS 9.0, *)) {
|
||||
texDesc.storageMode = MTLStorageModePrivate;
|
||||
texDesc.usage = MTLTextureUsageShaderRead | MTLTextureUsageRenderTarget;
|
||||
}
|
||||
|
||||
id<MTLTexture> colorTexture = [gpu->device() newTextureWithDescriptor:texDesc];
|
||||
if (!colorTexture) {
|
||||
return nullptr;
|
||||
id<MTLTexture> colorTexture = [gpu->device() newTextureWithDescriptor:texDesc];
|
||||
if (!colorTexture) {
|
||||
return nullptr;
|
||||
}
|
||||
if (@available(macOS 10.11, iOS 9.0, *)) {
|
||||
SkASSERT((MTLTextureUsageShaderRead | MTLTextureUsageRenderTarget) &
|
||||
colorTexture.usage);
|
||||
}
|
||||
mtlRT = new GrMtlRenderTarget(
|
||||
gpu, dimensions, sampleCnt, colorTexture, texture, kWrapped);
|
||||
} else {
|
||||
SkASSERT(sampleCnt == static_cast<int>([texture sampleCount]));
|
||||
mtlRT = new GrMtlRenderTarget(gpu, dimensions, sampleCnt, texture, nil, kWrapped);
|
||||
}
|
||||
if (@available(macOS 10.11, iOS 9.0, *)) {
|
||||
SkASSERT((MTLTextureUsageShaderRead|MTLTextureUsageRenderTarget) & colorTexture.usage);
|
||||
}
|
||||
mtlRT = new GrMtlRenderTarget(gpu, dimensions, sampleCnt, colorTexture, texture, kWrapped);
|
||||
} else {
|
||||
mtlRT = new GrMtlRenderTarget(gpu, dimensions, texture, kWrapped);
|
||||
}
|
||||
|
@ -212,8 +212,10 @@ id<MTLTexture> GrGetMTLTextureFromSurface(GrSurface* surface) {
|
||||
GrMtlRenderTarget* renderTarget = static_cast<GrMtlRenderTarget*>(surface->asRenderTarget());
|
||||
GrMtlTexture* texture;
|
||||
if (renderTarget) {
|
||||
// We should not be using this for multisampled rendertargets
|
||||
if (renderTarget->numSamples() > 1) {
|
||||
// We should not be using this for multisampled rendertargets with a separate resolve
|
||||
// texture.
|
||||
if (renderTarget->mtlResolveTexture()) {
|
||||
SkASSERT(renderTarget->numSamples() > 1);
|
||||
SkASSERT(false);
|
||||
return nil;
|
||||
}
|
||||
|
@ -1489,8 +1489,14 @@ GrCaps::SurfaceReadPixelsSupport GrVkCaps::surfaceSupportsReadPixels(
|
||||
if (GrVkFormatIsCompressed(tex->imageFormat())) {
|
||||
return SurfaceReadPixelsSupport::kCopyToTexture2D;
|
||||
}
|
||||
return SurfaceReadPixelsSupport::kSupported;
|
||||
} else if (auto rt = surface->asRenderTarget()) {
|
||||
if (rt->numSamples() > 1) {
|
||||
return SurfaceReadPixelsSupport::kCopyToTexture2D;
|
||||
}
|
||||
return SurfaceReadPixelsSupport::kSupported;
|
||||
}
|
||||
return SurfaceReadPixelsSupport::kSupported;
|
||||
return SurfaceReadPixelsSupport::kUnsupported;
|
||||
}
|
||||
|
||||
bool GrVkCaps::onSurfaceSupportsWritePixels(const GrSurface* surface) const {
|
||||
|
@ -666,6 +666,7 @@ void GrVkGpu::onResolveRenderTarget(GrRenderTarget* target, const SkIRect& resol
|
||||
SkASSERT(target->numSamples() > 1);
|
||||
GrVkRenderTarget* rt = static_cast<GrVkRenderTarget*>(target);
|
||||
SkASSERT(rt->msaaImage());
|
||||
SkASSERT(rt->colorAttachmentView() && rt->resolveAttachmentView());
|
||||
|
||||
this->resolveImage(target, rt, resolveRect,
|
||||
SkIPoint::Make(resolveRect.x(), resolveRect.y()));
|
||||
@ -1356,14 +1357,6 @@ sk_sp<GrTexture> GrVkGpu::onWrapRenderableBackendTexture(const GrBackendTexture&
|
||||
}
|
||||
|
||||
sk_sp<GrRenderTarget> GrVkGpu::onWrapBackendRenderTarget(const GrBackendRenderTarget& backendRT) {
|
||||
// Currently the Vulkan backend does not support wrapping of msaa render targets directly. In
|
||||
// general this is not an issue since swapchain images in vulkan are never multisampled. Thus if
|
||||
// you want a multisampled RT it is best to wrap the swapchain images and then let Skia handle
|
||||
// creating and owning the MSAA images.
|
||||
if (backendRT.sampleCnt() > 1) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
GrVkImageInfo info;
|
||||
if (!backendRT.getVkImageInfo(&info)) {
|
||||
return nullptr;
|
||||
@ -1602,6 +1595,7 @@ bool generate_compressed_data(GrVkGpu* gpu, char* mapPtr,
|
||||
|
||||
bool GrVkGpu::createVkImageForBackendSurface(VkFormat vkFormat,
|
||||
SkISize dimensions,
|
||||
int sampleCnt,
|
||||
GrTexturable texturable,
|
||||
GrRenderable renderable,
|
||||
GrMipmapped mipMapped,
|
||||
@ -1617,10 +1611,19 @@ bool GrVkGpu::createVkImageForBackendSurface(VkFormat vkFormat,
|
||||
return false;
|
||||
}
|
||||
|
||||
if (renderable == GrRenderable::kYes && !fVkCaps->isFormatRenderable(vkFormat, 1)) {
|
||||
// MSAA images are only currently used by createTestingOnlyBackendRenderTarget.
|
||||
if (sampleCnt > 1 && (texturable == GrTexturable::kYes || renderable == GrRenderable::kNo)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (renderable == GrRenderable::kYes) {
|
||||
sampleCnt = fVkCaps->getRenderTargetSampleCount(sampleCnt, vkFormat);
|
||||
if (!sampleCnt) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int numMipLevels = 1;
|
||||
if (mipMapped == GrMipmapped::kYes) {
|
||||
numMipLevels = SkMipmap::ComputeLevelCount(dimensions.width(), dimensions.height()) + 1;
|
||||
@ -1643,7 +1646,7 @@ bool GrVkGpu::createVkImageForBackendSurface(VkFormat vkFormat,
|
||||
imageDesc.fWidth = dimensions.width();
|
||||
imageDesc.fHeight = dimensions.height();
|
||||
imageDesc.fLevels = numMipLevels;
|
||||
imageDesc.fSamples = 1;
|
||||
imageDesc.fSamples = sampleCnt;
|
||||
imageDesc.fImageTiling = VK_IMAGE_TILING_OPTIMAL;
|
||||
imageDesc.fUsageFlags = usageFlags;
|
||||
imageDesc.fMemProps = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
|
||||
@ -1777,9 +1780,8 @@ GrBackendTexture GrVkGpu::onCreateBackendTexture(SkISize dimensions,
|
||||
}
|
||||
|
||||
GrVkImageInfo info;
|
||||
if (!this->createVkImageForBackendSurface(vkFormat, dimensions, GrTexturable::kYes,
|
||||
renderable, mipMapped,
|
||||
&info, isProtected)) {
|
||||
if (!this->createVkImageForBackendSurface(vkFormat, dimensions, 1, GrTexturable::kYes,
|
||||
renderable, mipMapped, &info, isProtected)) {
|
||||
return {};
|
||||
}
|
||||
|
||||
@ -2022,23 +2024,25 @@ bool GrVkGpu::isTestingOnlyBackendTexture(const GrBackendTexture& tex) const {
|
||||
return false;
|
||||
}
|
||||
|
||||
GrBackendRenderTarget GrVkGpu::createTestingOnlyBackendRenderTarget(int w, int h, GrColorType ct) {
|
||||
GrBackendRenderTarget GrVkGpu::createTestingOnlyBackendRenderTarget(SkISize dimensions,
|
||||
GrColorType ct,
|
||||
int sampleCnt) {
|
||||
this->handleDirtyContext();
|
||||
|
||||
if (w > this->caps()->maxRenderTargetSize() || h > this->caps()->maxRenderTargetSize()) {
|
||||
return GrBackendRenderTarget();
|
||||
if (dimensions.width() > this->caps()->maxRenderTargetSize() ||
|
||||
dimensions.height() > this->caps()->maxRenderTargetSize()) {
|
||||
return {};
|
||||
}
|
||||
|
||||
VkFormat vkFormat = this->vkCaps().getFormatFromColorType(ct);
|
||||
|
||||
GrVkImageInfo info;
|
||||
if (!this->createVkImageForBackendSurface(vkFormat, {w, h}, GrTexturable::kNo,
|
||||
GrRenderable::kYes, GrMipmapped::kNo,
|
||||
&info, GrProtected::kNo)) {
|
||||
return {};
|
||||
if (!this->createVkImageForBackendSurface(vkFormat, dimensions, sampleCnt, GrTexturable::kNo,
|
||||
GrRenderable::kYes, GrMipmapped::kNo, &info,
|
||||
GrProtected::kNo)) {
|
||||
return {};
|
||||
}
|
||||
|
||||
return GrBackendRenderTarget(w, h, 1, info);
|
||||
return GrBackendRenderTarget(dimensions.width(), dimensions.height(), 0, info);
|
||||
}
|
||||
|
||||
void GrVkGpu::deleteTestingOnlyBackendRenderTarget(const GrBackendRenderTarget& rt) {
|
||||
|
@ -94,7 +94,9 @@ public:
|
||||
#if GR_TEST_UTILS
|
||||
bool isTestingOnlyBackendTexture(const GrBackendTexture&) const override;
|
||||
|
||||
GrBackendRenderTarget createTestingOnlyBackendRenderTarget(int w, int h, GrColorType) override;
|
||||
GrBackendRenderTarget createTestingOnlyBackendRenderTarget(SkISize,
|
||||
GrColorType,
|
||||
int sampleCnt) override;
|
||||
void deleteTestingOnlyBackendRenderTarget(const GrBackendRenderTarget&) override;
|
||||
|
||||
void testingOnly_flushGpuAndSync() override;
|
||||
@ -320,6 +322,7 @@ private:
|
||||
|
||||
bool createVkImageForBackendSurface(VkFormat,
|
||||
SkISize dimensions,
|
||||
int sampleCnt,
|
||||
GrTexturable,
|
||||
GrRenderable,
|
||||
GrMipmapped,
|
||||
|
@ -268,6 +268,7 @@ bool GrVkImage::InitImageInfo(GrVkGpu* gpu, const ImageDesc& imageDesc, GrVkImag
|
||||
info->fImageLayout = initialLayout;
|
||||
info->fFormat = imageDesc.fFormat;
|
||||
info->fImageUsageFlags = imageDesc.fUsageFlags;
|
||||
info->fSampleCount = imageDesc.fSamples;
|
||||
info->fLevelCount = imageDesc.fLevels;
|
||||
info->fCurrentQueueFamily = VK_QUEUE_FAMILY_IGNORED;
|
||||
info->fProtected =
|
||||
|
@ -97,7 +97,7 @@ GrVkRenderTarget::GrVkRenderTarget(GrVkGpu* gpu,
|
||||
sk_sp<const GrVkImageView> colorAttachmentView)
|
||||
: GrSurface(gpu, dimensions, info.fProtected)
|
||||
, GrVkImage(gpu, info, std::move(mutableState), GrBackendObjectOwnership::kBorrowed)
|
||||
, GrRenderTarget(gpu, dimensions, 1, info.fProtected)
|
||||
, GrRenderTarget(gpu, dimensions, info.fSampleCount, info.fProtected)
|
||||
, fColorAttachmentView(std::move(colorAttachmentView))
|
||||
, fMSAAImage(nullptr)
|
||||
, fCachedFramebuffers()
|
||||
@ -117,7 +117,7 @@ GrVkRenderTarget::GrVkRenderTarget(GrVkGpu* gpu,
|
||||
GrBackendObjectOwnership ownership)
|
||||
: GrSurface(gpu, dimensions, info.fProtected)
|
||||
, GrVkImage(gpu, info, std::move(mutableState), ownership)
|
||||
, GrRenderTarget(gpu, dimensions, 1, info.fProtected)
|
||||
, GrRenderTarget(gpu, dimensions, info.fSampleCount, info.fProtected)
|
||||
, fColorAttachmentView(std::move(colorAttachmentView))
|
||||
, fMSAAImage(nullptr)
|
||||
, fCachedFramebuffers()
|
||||
@ -139,6 +139,7 @@ GrVkRenderTarget::GrVkRenderTarget(GrVkGpu* gpu,
|
||||
, fCachedFramebuffers()
|
||||
, fCachedRenderPasses()
|
||||
, fSecondaryCommandBuffer(secondaryCommandBuffer) {
|
||||
SkASSERT(info.fSampleCount == 1);
|
||||
SkASSERT(fSecondaryCommandBuffer != VK_NULL_HANDLE);
|
||||
SkASSERT(SkToBool(info.fImageUsageFlags & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT));
|
||||
this->setFlags(info);
|
||||
@ -159,8 +160,14 @@ sk_sp<GrVkRenderTarget> GrVkRenderTarget::MakeWrappedRenderTarget(
|
||||
GrVkGpu* gpu, SkISize dimensions, int sampleCnt, const GrVkImageInfo& info,
|
||||
sk_sp<GrBackendSurfaceMutableStateImpl> mutableState) {
|
||||
SkASSERT(VK_NULL_HANDLE != info.fImage);
|
||||
|
||||
SkASSERT(1 == info.fLevelCount);
|
||||
SkASSERT(sampleCnt >= 1 && info.fSampleCount >= 1);
|
||||
|
||||
int wrappedImageSampleCnt = static_cast<int>(info.fSampleCount);
|
||||
if (sampleCnt != wrappedImageSampleCnt && wrappedImageSampleCnt != 1) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
VkFormat pixelFormat = info.fFormat;
|
||||
|
||||
VkImage colorImage;
|
||||
@ -169,7 +176,7 @@ sk_sp<GrVkRenderTarget> GrVkRenderTarget::MakeWrappedRenderTarget(
|
||||
GrVkImageInfo msInfo;
|
||||
sk_sp<GrBackendSurfaceMutableStateImpl> msMutableState;
|
||||
sk_sp<const GrVkImageView> resolveAttachmentView;
|
||||
if (sampleCnt > 1) {
|
||||
if (sampleCnt != wrappedImageSampleCnt) {
|
||||
GrVkImage::ImageDesc msImageDesc;
|
||||
msImageDesc.fImageType = VK_IMAGE_TYPE_2D;
|
||||
msImageDesc.fFormat = pixelFormat;
|
||||
@ -210,7 +217,7 @@ sk_sp<GrVkRenderTarget> GrVkRenderTarget::MakeWrappedRenderTarget(
|
||||
sk_sp<const GrVkImageView> colorAttachmentView = GrVkImageView::Make(
|
||||
gpu, colorImage, pixelFormat, GrVkImageView::kColor_Type, 1, GrVkYcbcrConversionInfo());
|
||||
if (!colorAttachmentView) {
|
||||
if (sampleCnt > 1) {
|
||||
if (resolveAttachmentView) {
|
||||
resolveAttachmentView.reset();
|
||||
GrVkImage::DestroyImageInfo(gpu, &msInfo);
|
||||
}
|
||||
@ -218,7 +225,7 @@ sk_sp<GrVkRenderTarget> GrVkRenderTarget::MakeWrappedRenderTarget(
|
||||
}
|
||||
|
||||
GrVkRenderTarget* vkRT;
|
||||
if (sampleCnt > 1) {
|
||||
if (resolveAttachmentView) {
|
||||
vkRT = new GrVkRenderTarget(gpu, dimensions, sampleCnt, info, std::move(mutableState),
|
||||
msInfo, std::move(msMutableState),
|
||||
std::move(colorAttachmentView),
|
||||
@ -531,6 +538,20 @@ GrBackendRenderTarget GrVkRenderTarget::getBackendRenderTarget() const {
|
||||
return GrBackendRenderTarget(this->width(), this->height(), fInfo, this->getMutableState());
|
||||
}
|
||||
|
||||
GrVkImage* GrVkRenderTarget::msaaImage() {
|
||||
if (this->numSamples() == 1) {
|
||||
SkASSERT(fColorAttachmentView && !fResolveAttachmentView);
|
||||
return nullptr;
|
||||
}
|
||||
if (!this->fResolveAttachmentView) {
|
||||
// In this case *this* object is MSAA (there is not a separate color and resolve buffer)
|
||||
SkASSERT(!fMSAAImage);
|
||||
return this;
|
||||
}
|
||||
SkASSERT(fMSAAImage);
|
||||
return fMSAAImage.get();
|
||||
}
|
||||
|
||||
const GrManagedResource* GrVkRenderTarget::stencilImageResource() const {
|
||||
SkASSERT(!this->wrapsSecondaryCommandBuffer());
|
||||
const GrStencilAttachment* stencil = this->getStencilAttachment();
|
||||
|
@ -47,7 +47,12 @@ public:
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
GrVkImage* msaaImage() { return fMSAAImage.get(); }
|
||||
/**
|
||||
* If this render target is multisampled, this returns the MSAA image for rendering. This
|
||||
* will be different than *this* when we have separate render/resolve images. If not
|
||||
* multisampled returns nullptr.
|
||||
*/
|
||||
GrVkImage* msaaImage();
|
||||
const GrVkImageView* resolveAttachmentView() const { return fResolveAttachmentView.get(); }
|
||||
const GrManagedResource* stencilImageResource() const;
|
||||
const GrVkImageView* stencilAttachmentView() const;
|
||||
@ -142,7 +147,7 @@ private:
|
||||
SkISize dimensions,
|
||||
const GrVkImageInfo& info,
|
||||
sk_sp<GrBackendSurfaceMutableStateImpl> mutableState,
|
||||
sk_sp < const GrVkImageView> colorAttachmentView);
|
||||
sk_sp<const GrVkImageView> colorAttachmentView);
|
||||
|
||||
GrVkRenderTarget(GrVkGpu* gpu,
|
||||
SkISize dimensions,
|
||||
|
@ -435,7 +435,7 @@ sk_sp<SkSurface> SkSurface::MakeFromBackendRenderTarget(GrContext*,
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void SkSurface::flushAndSubmit() {
|
||||
void SkSurface::flushAndSubmit(bool syncCpu) {
|
||||
this->flush(BackendSurfaceAccess::kNoAccess, GrFlushInfo());
|
||||
}
|
||||
|
||||
|
@ -767,12 +767,12 @@ sk_sp<SkSurface> SkSurface::MakeFromAHardwareBuffer(GrContext* context,
|
||||
}
|
||||
#endif
|
||||
|
||||
void SkSurface::flushAndSubmit() {
|
||||
void SkSurface::flushAndSubmit(bool syncCpu) {
|
||||
this->flush(BackendSurfaceAccess::kNoAccess, GrFlushInfo());
|
||||
|
||||
auto direct = GrAsDirectContext(this->recordingContext());
|
||||
if (direct) {
|
||||
direct->submit();
|
||||
direct->submit(syncCpu);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -9,7 +9,6 @@
|
||||
#include "include/core/SkBlendMode.h"
|
||||
#include "include/core/SkCanvas.h"
|
||||
#include "include/core/SkColor.h"
|
||||
#include "include/core/SkColorSpace.h"
|
||||
#include "include/core/SkImageInfo.h"
|
||||
#include "include/core/SkPaint.h"
|
||||
#include "include/core/SkPoint.h"
|
||||
@ -17,16 +16,10 @@
|
||||
#include "include/core/SkRefCnt.h"
|
||||
#include "include/core/SkSurface.h"
|
||||
#include "include/core/SkTypes.h"
|
||||
#include "include/gpu/GrBackendSurface.h"
|
||||
#include "include/gpu/GrDirectContext.h"
|
||||
#include "include/gpu/GrTypes.h"
|
||||
#include "include/private/GrTypesPriv.h"
|
||||
#include "src/gpu/GrCaps.h"
|
||||
#include "src/gpu/GrContextPriv.h"
|
||||
#include "src/gpu/GrResourceProvider.h"
|
||||
#include "src/gpu/GrTexture.h"
|
||||
#include "tests/Test.h"
|
||||
#include "tools/gpu/GrContextFactory.h"
|
||||
#include "tools/gpu/BackendSurfaceFactory.h"
|
||||
|
||||
#include <initializer_list>
|
||||
#include <vector>
|
||||
@ -87,32 +80,6 @@ DEF_TEST(Blend_byte_multiply, r) {
|
||||
for (auto multiply : perfect) { REPORTER_ASSERT(r, test(multiply).diffs == 0); }
|
||||
}
|
||||
|
||||
namespace {
|
||||
static sk_sp<SkSurface> create_gpu_surface_backend_texture_as_render_target(
|
||||
GrDirectContext* context, int sampleCnt, SkISize dimensions, SkColorType colorType,
|
||||
GrSurfaceOrigin origin, sk_sp<GrTexture>* backingSurface) {
|
||||
auto ct = SkColorTypeToGrColorType(colorType);
|
||||
auto format = context->priv().caps()->getDefaultBackendFormat(ct, GrRenderable::kYes);
|
||||
|
||||
auto resourceProvider = context->priv().resourceProvider();
|
||||
|
||||
*backingSurface =
|
||||
resourceProvider->createTexture(dimensions, format, GrRenderable::kYes, sampleCnt,
|
||||
GrMipmapped::kNo, SkBudgeted::kNo, GrProtected::kNo);
|
||||
if (!(*backingSurface)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
GrBackendTexture backendTex = (*backingSurface)->getBackendTexture();
|
||||
|
||||
sk_sp<SkSurface> surface =
|
||||
SkSurface::MakeFromBackendTextureAsRenderTarget(context, backendTex, origin,
|
||||
sampleCnt, colorType, nullptr, nullptr);
|
||||
|
||||
return surface;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
// Tests blending to a surface with no texture available.
|
||||
DEF_GPUTEST_FOR_GL_RENDERING_CONTEXTS(ES2BlendWithNoTexture, reporter, ctxInfo) {
|
||||
auto context = ctxInfo.directContext();
|
||||
@ -156,10 +123,9 @@ DEF_GPUTEST_FOR_GL_RENDERING_CONTEXTS(ES2BlendWithNoTexture, reporter, ctxInfo)
|
||||
SkIPoint inPoint = testCase.fRectAndPoints.inPoint;
|
||||
GrSurfaceOrigin origin = testCase.fOrigin;
|
||||
|
||||
sk_sp<GrTexture> backingSurface;
|
||||
// BGRA forces a framebuffer blit on ES2.
|
||||
sk_sp<SkSurface> surface = create_gpu_surface_backend_texture_as_render_target(
|
||||
context, sampleCnt, kDimensions, kColorType, origin, &backingSurface);
|
||||
sk_sp<SkSurface> surface =
|
||||
MakeBackendRenderTargetSurface(context, kDimensions, sampleCnt, origin, kColorType);
|
||||
|
||||
if (!surface && sampleCnt > 1) {
|
||||
// Some platforms don't support MSAA.
|
||||
@ -194,9 +160,5 @@ DEF_GPUTEST_FOR_GL_RENDERING_CONTEXTS(ES2BlendWithNoTexture, reporter, ctxInfo)
|
||||
SkColorSetRGB(0xFF, 0xFF, 0x80));
|
||||
REPORTER_ASSERT(reporter, bitmap.getColor(inPoint.x(), inPoint.y()) ==
|
||||
SkColorSetRGB(0x80, 0xFF, 0x80));
|
||||
|
||||
// Clean up - surface depends on backingSurface and must be released first.
|
||||
surface.reset();
|
||||
backingSurface.reset();
|
||||
}
|
||||
}
|
||||
|
@ -25,8 +25,7 @@ static sk_sp<GrSurfaceProxy> make_wrapped_rt(GrProxyProvider* provider,
|
||||
skiatest::Reporter* reporter,
|
||||
const SkISize& size,
|
||||
GrColorType colorType) {
|
||||
auto backendRT =
|
||||
gpu->createTestingOnlyBackendRenderTarget(size.width(), size.height(), colorType);
|
||||
auto backendRT = gpu->createTestingOnlyBackendRenderTarget(size, colorType);
|
||||
return provider->wrapBackendRenderTarget(backendRT, nullptr);
|
||||
}
|
||||
|
||||
|
@ -226,7 +226,7 @@ DEF_GPUTEST_FOR_RENDERING_CONTEXTS(WrappedProxyTest, reporter, ctxInfo) {
|
||||
// sample counts :(.
|
||||
if (direct->colorTypeSupportedAsSurface(colorType)) {
|
||||
GrBackendRenderTarget backendRT = gpu->createTestingOnlyBackendRenderTarget(
|
||||
kWidthHeight, kWidthHeight, grColorType);
|
||||
{kWidthHeight, kWidthHeight}, grColorType);
|
||||
sk_sp<GrSurfaceProxy> sProxy(
|
||||
proxyProvider->wrapBackendRenderTarget(backendRT, nullptr));
|
||||
check_surface(reporter, sProxy.get(), kWidthHeight, kWidthHeight, SkBudgeted::kNo);
|
||||
|
@ -30,6 +30,7 @@
|
||||
#include "src/image/SkSurface_Gpu.h"
|
||||
#include "tests/Test.h"
|
||||
#include "tests/TestUtils.h"
|
||||
#include "tools/gpu/BackendSurfaceFactory.h"
|
||||
|
||||
#include <functional>
|
||||
#include <initializer_list>
|
||||
@ -117,12 +118,6 @@ DEF_GPUTEST_FOR_RENDERING_CONTEXTS(GrContext_colorTypeSupportedAsSurface, report
|
||||
REPORTER_ASSERT(reporter, can == SkToBool(surf), "ct: %d, can: %d, surf: %d",
|
||||
colorType, can, SkToBool(surf));
|
||||
|
||||
surf = SkSurface::MakeFromBackendTextureAsRenderTarget(context, backendTex,
|
||||
kTopLeft_GrSurfaceOrigin, 1,
|
||||
colorType, nullptr, nullptr);
|
||||
REPORTER_ASSERT(reporter, can == SkToBool(surf), "ct: %d, can: %d, surf: %d",
|
||||
colorType, can, SkToBool(surf));
|
||||
|
||||
surf.reset();
|
||||
context->flushAndSubmit();
|
||||
context->deleteBackendTexture(backendTex);
|
||||
@ -158,44 +153,38 @@ DEF_GPUTEST_FOR_RENDERING_CONTEXTS(GrContext_colorTypeSupportedAsSurface, report
|
||||
"Should store an allowed sample count (%d vs %d)", allowedCnt,
|
||||
storedCnt);
|
||||
}
|
||||
|
||||
surf = SkSurface::MakeFromBackendTextureAsRenderTarget(context, backendTex,
|
||||
kTopLeft_GrSurfaceOrigin,
|
||||
kSampleCnt, colorType,
|
||||
nullptr, nullptr);
|
||||
REPORTER_ASSERT(reporter, can == SkToBool(surf),
|
||||
"colorTypeSupportedAsSurface:%d, surf:%d, ct:%d", can, SkToBool(surf),
|
||||
colorType);
|
||||
if (surf) {
|
||||
auto rtc = ((SkSurface_Gpu*)(surf.get()))->getDevice()->accessRenderTargetContext();
|
||||
int storedCnt = rtc->numSamples();
|
||||
int allowedCnt = context->priv().caps()->getRenderTargetSampleCount(
|
||||
storedCnt, backendTex.getBackendFormat());
|
||||
REPORTER_ASSERT(reporter, storedCnt == allowedCnt,
|
||||
"Should store an allowed sample count (%d vs %d)", allowedCnt,
|
||||
storedCnt);
|
||||
}
|
||||
|
||||
surf.reset();
|
||||
context->flushAndSubmit();
|
||||
context->deleteBackendTexture(backendTex);
|
||||
}
|
||||
|
||||
{
|
||||
auto* gpu = context->priv().getGpu();
|
||||
|
||||
GrBackendRenderTarget backendRenderTarget = gpu->createTestingOnlyBackendRenderTarget(
|
||||
16, 16, SkColorTypeToGrColorType(colorType));
|
||||
bool can = context->colorTypeSupportedAsSurface(colorType);
|
||||
auto surf = SkSurface::MakeFromBackendRenderTarget(context, backendRenderTarget,
|
||||
kTopLeft_GrSurfaceOrigin, colorType,
|
||||
nullptr, nullptr);
|
||||
REPORTER_ASSERT(reporter, can == SkToBool(surf), "ct: %d, can: %d, surf: %d", colorType,
|
||||
can, SkToBool(surf));
|
||||
surf.reset();
|
||||
context->flushAndSubmit();
|
||||
if (backendRenderTarget.isValid()) {
|
||||
gpu->deleteTestingOnlyBackendRenderTarget(backendRenderTarget);
|
||||
for (int sampleCnt : {1, 2}) {
|
||||
auto surf = MakeBackendRenderTargetSurface(context, {16, 16}, sampleCnt,
|
||||
kTopLeft_GrSurfaceOrigin, colorType);
|
||||
bool can = context->colorTypeSupportedAsSurface(colorType) &&
|
||||
context->maxSurfaceSampleCountForColorType(colorType) >= sampleCnt;
|
||||
if (!surf && can && colorType == kBGRA_8888_SkColorType && sampleCnt > 1 &&
|
||||
context->backend() == GrBackendApi::kOpenGL) {
|
||||
// This is an execeptional case. On iOS GLES we support MSAA BGRA for internally-
|
||||
// created render targets by using a MSAA RGBA8 renderbuffer that resolves to a
|
||||
// BGRA8 texture. However, the GL_APPLE_texture_format_BGRA8888 extension does not
|
||||
// allow creation of BGRA8 renderbuffers and we don't support multisampled textures.
|
||||
// So this is expected to fail. As of 10/5/2020 it actually seems to work to create
|
||||
// a MSAA BGRA8 renderbuffer (at least in the simulator) but we don't want to rely
|
||||
// on this undocumented behavior.
|
||||
continue;
|
||||
}
|
||||
REPORTER_ASSERT(reporter, can == SkToBool(surf), "ct: %d, sc: %d, can: %d, surf: %d",
|
||||
colorType, sampleCnt, can, SkToBool(surf));
|
||||
if (surf) {
|
||||
auto rtc = ((SkSurface_Gpu*)(surf.get()))->getDevice()->accessRenderTargetContext();
|
||||
auto backendFormat = rtc->asSurfaceProxy()->backendFormat();
|
||||
int storedCnt = rtc->numSamples();
|
||||
int allowedCnt = context->priv().caps()->getRenderTargetSampleCount(storedCnt,
|
||||
backendFormat);
|
||||
REPORTER_ASSERT(reporter, storedCnt == allowedCnt,
|
||||
"Should store an allowed sample count (%d vs %d)", allowedCnt,
|
||||
storedCnt);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -744,32 +733,21 @@ static bool supports_readpixels(const GrCaps* caps, SkSurface* surface) {
|
||||
return caps->surfaceSupportsReadPixels(rt) == GrCaps::SurfaceReadPixelsSupport::kSupported;
|
||||
}
|
||||
|
||||
static sk_sp<SkSurface> create_gpu_surface_backend_texture_as_render_target(
|
||||
GrDirectContext* dContext,
|
||||
int sampleCnt,
|
||||
const SkColor4f& color,
|
||||
GrBackendTexture* outTexture) {
|
||||
|
||||
static sk_sp<SkSurface> create_gpu_surface_backend_render_target(GrDirectContext* dContext,
|
||||
int sampleCnt,
|
||||
const SkColor4f& color,
|
||||
GrBackendTexture* outTexture) {
|
||||
const int kWidth = 10;
|
||||
const int kHeight = 10;
|
||||
|
||||
SkImageInfo ii = SkImageInfo::Make(kWidth, kHeight, SkColorType::kRGBA_8888_SkColorType,
|
||||
kPremul_SkAlphaType);
|
||||
|
||||
if (!CreateBackendTexture(dContext, outTexture, ii, color,
|
||||
GrMipmapped::kNo, GrRenderable::kYes)) {
|
||||
auto surf = MakeBackendRenderTargetSurface(dContext, {kWidth, kHeight}, sampleCnt,
|
||||
kTopLeft_GrSurfaceOrigin, kRGBA_8888_SkColorType,
|
||||
nullptr, nullptr);
|
||||
if (!surf) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
sk_sp<SkSurface> surface = SkSurface::MakeFromBackendTextureAsRenderTarget(
|
||||
dContext, *outTexture, kTopLeft_GrSurfaceOrigin, sampleCnt, kRGBA_8888_SkColorType,
|
||||
nullptr, nullptr);
|
||||
|
||||
if (!surface) {
|
||||
DeleteBackendTexture(dContext, *outTexture);
|
||||
return nullptr;
|
||||
}
|
||||
return surface;
|
||||
surf->getCanvas()->clear(color);
|
||||
return surf;
|
||||
}
|
||||
|
||||
static void test_surface_context_clear(skiatest::Reporter* reporter,
|
||||
@ -835,8 +813,8 @@ DEF_GPUTEST_FOR_GL_RENDERING_CONTEXTS(SurfaceClear_Gpu, reporter, ctxInfo) {
|
||||
|
||||
// Wrapped RTs are *not* supposed to clear (to allow client to partially update a surface).
|
||||
const SkColor4f kOrigColor{.67f, .67f, .67f, 1};
|
||||
for (auto& surfaceFunc : {&create_gpu_surface_backend_texture,
|
||||
&create_gpu_surface_backend_texture_as_render_target}) {
|
||||
for (auto& surfaceFunc :
|
||||
{&create_gpu_surface_backend_texture, &create_gpu_surface_backend_render_target}) {
|
||||
GrBackendTexture backendTex;
|
||||
auto surface = surfaceFunc(dContext, 1, kOrigColor, &backendTex);
|
||||
if (!surface) {
|
||||
@ -913,8 +891,8 @@ DEF_GPUTEST_FOR_RENDERING_CONTEXTS(SurfacePartialDraw_Gpu, reporter, ctxInfo) {
|
||||
|
||||
static const SkColor4f kOrigColor { 0.667f, 0.733f, 0.8f, 1 };
|
||||
|
||||
for (auto& surfaceFunc : {&create_gpu_surface_backend_texture,
|
||||
&create_gpu_surface_backend_texture_as_render_target}) {
|
||||
for (auto& surfaceFunc :
|
||||
{&create_gpu_surface_backend_texture, &create_gpu_surface_backend_render_target}) {
|
||||
// Validate that we can draw to the canvas and that the original texture color is
|
||||
// preserved in pixels that aren't rendered to via the surface.
|
||||
// This works only for non-multisampled case.
|
||||
@ -970,7 +948,7 @@ DEF_GPUTEST_FOR_RENDERING_CONTEXTS(SurfaceWrappedWithRelease_Gpu, reporter, ctxI
|
||||
ReleaseChecker::Release,
|
||||
&releaseChecker);
|
||||
} else {
|
||||
backendRT = gpu->createTestingOnlyBackendRenderTarget(kWidth, kHeight,
|
||||
backendRT = gpu->createTestingOnlyBackendRenderTarget({kWidth, kHeight},
|
||||
GrColorType::kRGBA_8888);
|
||||
if (!backendRT.isValid()) {
|
||||
continue;
|
||||
@ -1015,8 +993,8 @@ DEF_GPUTEST_FOR_GL_RENDERING_CONTEXTS(SurfaceAttachStencil_Gpu, reporter, ctxInf
|
||||
|
||||
auto resourceProvider = context->priv().resourceProvider();
|
||||
|
||||
for (auto& surfaceFunc : {&create_gpu_surface_backend_texture,
|
||||
&create_gpu_surface_backend_texture_as_render_target}) {
|
||||
for (auto& surfaceFunc :
|
||||
{&create_gpu_surface_backend_texture, &create_gpu_surface_backend_render_target}) {
|
||||
for (int sampleCnt : {1, 4, 8}) {
|
||||
GrBackendTexture backendTex;
|
||||
auto surface = surfaceFunc(context, sampleCnt, kOrigColor, &backendTex);
|
||||
@ -1031,7 +1009,9 @@ DEF_GPUTEST_FOR_GL_RENDERING_CONTEXTS(SurfaceAttachStencil_Gpu, reporter, ctxInf
|
||||
GrRenderTarget* rt = surface->getCanvas()
|
||||
->internal_private_accessTopLayerRenderTargetContext()->accessRenderTarget();
|
||||
REPORTER_ASSERT(reporter, resourceProvider->attachStencilAttachment(rt, sampleCnt));
|
||||
context->deleteBackendTexture(backendTex);
|
||||
if (backendTex.isValid()) {
|
||||
context->deleteBackendTexture(backendTex);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -5,6 +5,9 @@
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#ifndef TestUtils_DEFINED
|
||||
#define TestUtils_DEFINED
|
||||
|
||||
#include "include/core/SkBitmap.h"
|
||||
#include "src/gpu/GrDataUtils.h"
|
||||
#include "tests/Test.h"
|
||||
@ -110,3 +113,5 @@ void CheckSingleThreadedProxyRefs(skiatest::Reporter* reporter,
|
||||
GrSurfaceProxy* proxy,
|
||||
int32_t expectedProxyRefs,
|
||||
int32_t expectedBackingRefs);
|
||||
|
||||
#endif
|
||||
|
@ -134,11 +134,15 @@ void wrap_rt_test(skiatest::Reporter* reporter, GrDirectContext* dContext) {
|
||||
|
||||
// Image has MSAA
|
||||
{
|
||||
GrVkImageInfo backendCopy = imageInfo;
|
||||
backendCopy.fSampleCount = 4;
|
||||
GrBackendRenderTarget backendRT(kW, kH, backendCopy);
|
||||
rt = gpu->wrapBackendRenderTarget(backendRT);
|
||||
REPORTER_ASSERT(reporter, !rt);
|
||||
GrColorType ct = SkColorTypeToGrColorType(kColorType);
|
||||
GrGpu* gpu = dContext->priv().getGpu();
|
||||
GrBackendRenderTarget backendRT =
|
||||
gpu->createTestingOnlyBackendRenderTarget({kW, kW}, ct, 4);
|
||||
if (backendRT.isValid()) {
|
||||
rt = gpu->wrapBackendRenderTarget(backendRT);
|
||||
REPORTER_ASSERT(reporter, rt);
|
||||
dContext->priv().getGpu()->deleteTestingOnlyBackendRenderTarget(backendRT);
|
||||
}
|
||||
}
|
||||
|
||||
// When we wrapBackendRenderTarget it is always borrowed, so we must make sure to free the
|
||||
|
@ -7,18 +7,16 @@
|
||||
|
||||
#include "include/core/SkCanvas.h"
|
||||
#include "include/core/SkSurface.h"
|
||||
#include "include/gpu/GrBackendSurface.h"
|
||||
#include "include/gpu/GrDirectContext.h"
|
||||
#include "include/private/SkColorData.h"
|
||||
#include "include/private/SkImageInfoPriv.h"
|
||||
#include "src/core/SkMathPriv.h"
|
||||
#include "tests/Test.h"
|
||||
#include "tests/TestUtils.h"
|
||||
#include "tools/ToolUtils.h"
|
||||
|
||||
#include "include/gpu/GrBackendSurface.h"
|
||||
#include "include/gpu/GrDirectContext.h"
|
||||
#include "src/gpu/GrContextPriv.h"
|
||||
#include "src/gpu/GrGpu.h"
|
||||
#include "src/gpu/GrProxyProvider.h"
|
||||
#include "tests/Test.h"
|
||||
#include "tools/gpu/BackendSurfaceFactory.h"
|
||||
|
||||
#include <initializer_list>
|
||||
|
||||
@ -462,21 +460,13 @@ static void test_write_pixels_non_texture(skiatest::Reporter* reporter,
|
||||
return;
|
||||
}
|
||||
for (auto& origin : { kTopLeft_GrSurfaceOrigin, kBottomLeft_GrSurfaceOrigin }) {
|
||||
GrBackendTexture backendTex;
|
||||
CreateBackendTexture(dContext, &backendTex, DEV_W, DEV_H, kRGBA_8888_SkColorType,
|
||||
SkColors::kTransparent, GrMipmapped::kNo, GrRenderable::kYes,
|
||||
GrProtected::kNo);
|
||||
if (!backendTex.isValid()) {
|
||||
continue;
|
||||
}
|
||||
SkColorType colorType = kN32_SkColorType;
|
||||
sk_sp<SkSurface> surface(SkSurface::MakeFromBackendTextureAsRenderTarget(
|
||||
dContext, backendTex, origin, sampleCnt, colorType, nullptr, nullptr));
|
||||
auto surface = MakeBackendRenderTargetSurface(dContext, {DEV_W, DEV_H}, sampleCnt, origin,
|
||||
colorType);
|
||||
if (surface) {
|
||||
auto ii = SkImageInfo::MakeN32Premul(DEV_W, DEV_H);
|
||||
test_write_pixels(reporter, surface.get(), ii);
|
||||
}
|
||||
dContext->deleteBackendTexture(backendTex);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -26,9 +26,11 @@
|
||||
#include "tools/ToolUtils.h"
|
||||
#include "tools/flags/CommandLineFlags.h"
|
||||
#include "tools/flags/CommonFlags.h"
|
||||
#include "tools/gpu/BackendSurfaceFactory.h"
|
||||
#include "tools/gpu/GrContextFactory.h"
|
||||
#include "tools/gpu/MemoryCache.h"
|
||||
#include "tools/trace/EventTracingPriv.h"
|
||||
|
||||
#include <chrono>
|
||||
#include <functional>
|
||||
#include <stdio.h>
|
||||
@ -338,16 +340,13 @@ static sk_sp<SkImage> draw_with_gpu(std::function<bool(SkCanvas*)> draw,
|
||||
break;
|
||||
|
||||
case SurfaceType::kBackendRenderTarget:
|
||||
backendRT = context->priv().getGpu()
|
||||
->createTestingOnlyBackendRenderTarget(info.width(),
|
||||
info.height(),
|
||||
SkColorTypeToGrColorType(info.colorType()));
|
||||
surface = SkSurface::MakeFromBackendRenderTarget(context,
|
||||
backendRT,
|
||||
kBottomLeft_GrSurfaceOrigin,
|
||||
info.colorType(),
|
||||
info.refColorSpace(),
|
||||
&props);
|
||||
surface = MakeBackendRenderTargetSurface(context,
|
||||
info.dimensions(),
|
||||
FLAGS_samples,
|
||||
kBottomLeft_GrSurfaceOrigin,
|
||||
info.colorType(),
|
||||
info.refColorSpace(),
|
||||
&props);
|
||||
break;
|
||||
}
|
||||
|
||||
|
44
tools/gpu/BackendSurfaceFactory.cpp
Normal file
44
tools/gpu/BackendSurfaceFactory.cpp
Normal file
@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Copyright 2020 Google LLC
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#include "tools/gpu/BackendSurfaceFactory.h"
|
||||
|
||||
#include "include/core/SkSurface.h"
|
||||
#include "include/gpu/GrContext.h"
|
||||
#include "src/gpu/GrContextPriv.h"
|
||||
#include "src/gpu/GrGpu.h"
|
||||
|
||||
sk_sp<SkSurface> MakeBackendRenderTargetSurface(GrDirectContext* context,
|
||||
SkISize dimensions,
|
||||
int sampleCnt,
|
||||
GrSurfaceOrigin origin,
|
||||
SkColorType colorType,
|
||||
sk_sp<SkColorSpace> colorSpace,
|
||||
const SkSurfaceProps* props) {
|
||||
auto ct = SkColorTypeToGrColorType(colorType);
|
||||
|
||||
struct ReleaseContext {
|
||||
GrContext* fContext;
|
||||
GrBackendRenderTarget fRenderTarget;
|
||||
};
|
||||
|
||||
auto bert = context->priv().getGpu()->createTestingOnlyBackendRenderTarget(
|
||||
dimensions, ct, sampleCnt);
|
||||
auto rc = new ReleaseContext{context, bert};
|
||||
SkASSERT(!bert.isValid() || bert.sampleCnt() >= sampleCnt);
|
||||
|
||||
auto proc = [](void* c) {
|
||||
const auto* rc = static_cast<ReleaseContext*>(c);
|
||||
if (auto gpu = rc->fContext->priv().getGpu(); gpu && rc->fRenderTarget.isValid()) {
|
||||
gpu->deleteTestingOnlyBackendRenderTarget(rc->fRenderTarget);
|
||||
}
|
||||
delete rc;
|
||||
};
|
||||
|
||||
return SkSurface::MakeFromBackendRenderTarget(
|
||||
context, bert, origin, colorType, std::move(colorSpace), props, proc, rc);
|
||||
}
|
29
tools/gpu/BackendSurfaceFactory.h
Normal file
29
tools/gpu/BackendSurfaceFactory.h
Normal file
@ -0,0 +1,29 @@
|
||||
/*
|
||||
* Copyright 2020 Google LLC
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#ifndef TestSurface_DEFINED
|
||||
#define TestSurface_DEFINED
|
||||
|
||||
#include "include/core/SkImageInfo.h"
|
||||
#include "include/core/SkSize.h"
|
||||
#include "include/gpu/GrTypes.h"
|
||||
#include "include/private/SkColorData.h"
|
||||
|
||||
class GrDirectContext;
|
||||
class SkSurface;
|
||||
class SkSurfaceProps;
|
||||
|
||||
/** Creates an SkSurface backed by a non-textureable render target. */
|
||||
sk_sp<SkSurface> MakeBackendRenderTargetSurface(GrDirectContext*,
|
||||
SkISize,
|
||||
int sampleCnt,
|
||||
GrSurfaceOrigin,
|
||||
SkColorType,
|
||||
sk_sp<SkColorSpace> = nullptr,
|
||||
const SkSurfaceProps* = nullptr);
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue
Block a user