aboutsummaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
authorGravatar ericrk <ericrk@chromium.org>2016-02-24 14:49:51 -0800
committerGravatar Commit bot <commit-bot@chromium.org>2016-02-24 14:49:52 -0800
commitf7b8b8affec91fcfab0d79199e466c16c254fe56 (patch)
tree295ca66ae496d202d9005b40f08b1832ad476068 /src
parent0cc2f85a19d50b45573d71d8c9d6ee1292c9fd3a (diff)
Add wrapBackendTextureAsRenderTarget API
Skia's GrTextureProvider currently exposes two APIs for wrapping backend objects: * wrapBackendTexture - wraps a texture into a GrTexture. Depending on flags, this GrTexture can be converted to a GrRenderTarget. Skia manages the render target objects it may create to provide a render target for the texture. This allows Skia to create stencil buffers if needed and manager MSAA resolves. * wrapBackendRenderTarget - wraps a FBO into a GrRenderTarget. This object cannot be converted to a GrTexture. Skia does not manage the render target objects for such a GrRenderTarget, and as such cannot attach stencil buffers or perform MSAA resolves on the created GrRenderTarget. Given these two options, wrapBackendTexture provides more versatility and allows Skia more room for optimization. Chrome currently uses wrapBackendTexture for this reason. While these two functions cover most cases, they do not provide a way for Skia to wrap a texture into a render target (and gain the MSAA and stencil buffer management), without also creating a GrTexture. This is problematic in cases where a texture can be bound to a render target, but cannot be textured from, as is the case in Chrome's limited support for GL_TEXTURE_RECTANGLE. To address this, a new function is created: * wrapBackendTextureAsRenderTarget - wraps a texture into a GrRenderTarget. As with wrapBackendTexture, the created render target objects are fully managed by Skia. Unlike wrapBackendTexture no GrTexture is created, and the created object will never be textured from. BUG=skia: GOLD_TRYBOT_URL= https://gold.skia.org/search2?unt=true&query=source_type%3Dgm&master=false&issue=1709163003 Review URL: https://codereview.chromium.org/1709163003
Diffstat (limited to 'src')
-rw-r--r--src/gpu/GrGpu.cpp20
-rw-r--r--src/gpu/GrGpu.h11
-rw-r--r--src/gpu/GrResourceProvider.cpp7
-rw-r--r--src/gpu/GrResourceProvider.h9
-rw-r--r--src/gpu/GrTest.cpp5
-rw-r--r--src/gpu/gl/GrGLGpu.cpp73
-rw-r--r--src/gpu/gl/GrGLGpu.h2
-rw-r--r--src/image/SkSurface.cpp9
-rw-r--r--src/image/SkSurface_Base.h5
-rw-r--r--src/image/SkSurface_Gpu.cpp24
-rw-r--r--src/image/SkSurface_Gpu.h1
11 files changed, 156 insertions, 10 deletions
diff --git a/src/gpu/GrGpu.cpp b/src/gpu/GrGpu.cpp
index e7adf0b321..4fcd4d57af 100644
--- a/src/gpu/GrGpu.cpp
+++ b/src/gpu/GrGpu.cpp
@@ -166,6 +166,10 @@ GrTexture* GrGpu::wrapBackendTexture(const GrBackendTextureDesc& desc, GrWrapOwn
!this->caps()->isConfigRenderable(desc.fConfig, desc.fSampleCnt > 0)) {
return nullptr;
}
+ int maxSize = this->caps()->maxTextureSize();
+ if (desc.fWidth > maxSize || desc.fHeight > maxSize) {
+ return nullptr;
+ }
GrTexture* tex = this->onWrapBackendTexture(desc, ownership);
if (nullptr == tex) {
return nullptr;
@@ -189,6 +193,22 @@ GrRenderTarget* GrGpu::wrapBackendRenderTarget(const GrBackendRenderTargetDesc&
return this->onWrapBackendRenderTarget(desc, ownership);
}
+GrRenderTarget* GrGpu::wrapBackendTextureAsRenderTarget(const GrBackendTextureDesc& desc,
+ GrWrapOwnership ownership) {
+ this->handleDirtyContext();
+ if (!(desc.fFlags & kRenderTarget_GrBackendTextureFlag)) {
+ return nullptr;
+ }
+ if (!this->caps()->isConfigRenderable(desc.fConfig, desc.fSampleCnt > 0)) {
+ return nullptr;
+ }
+ int maxSize = this->caps()->maxTextureSize();
+ if (desc.fWidth > maxSize || desc.fHeight > maxSize) {
+ return nullptr;
+ }
+ return this->onWrapBackendTextureAsRenderTarget(desc, ownership);
+}
+
GrVertexBuffer* GrGpu::createVertexBuffer(size_t size, bool dynamic) {
this->handleDirtyContext();
GrVertexBuffer* vb = this->onCreateVertexBuffer(size, dynamic);
diff --git a/src/gpu/GrGpu.h b/src/gpu/GrGpu.h
index 147c481020..fd134eae2c 100644
--- a/src/gpu/GrGpu.h
+++ b/src/gpu/GrGpu.h
@@ -97,16 +97,21 @@ public:
const void* srcData, size_t rowBytes);
/**
- * Implements GrContext::wrapBackendTexture
+ * Implements GrTextureProvider::wrapBackendTexture
*/
GrTexture* wrapBackendTexture(const GrBackendTextureDesc&, GrWrapOwnership);
/**
- * Implements GrContext::wrapBackendTexture
+ * Implements GrTextureProvider::wrapBackendTexture
*/
GrRenderTarget* wrapBackendRenderTarget(const GrBackendRenderTargetDesc&, GrWrapOwnership);
/**
+ * Implements GrTextureProvider::wrapBackendTextureAsRenderTarget
+ */
+ GrRenderTarget* wrapBackendTextureAsRenderTarget(const GrBackendTextureDesc&, GrWrapOwnership);
+
+ /**
* Creates a vertex buffer.
*
* @param size size in bytes of the vertex buffer
@@ -512,6 +517,8 @@ private:
virtual GrTexture* onWrapBackendTexture(const GrBackendTextureDesc&, GrWrapOwnership) = 0;
virtual GrRenderTarget* onWrapBackendRenderTarget(const GrBackendRenderTargetDesc&,
GrWrapOwnership) = 0;
+ virtual GrRenderTarget* onWrapBackendTextureAsRenderTarget(const GrBackendTextureDesc&,
+ GrWrapOwnership) = 0;
virtual GrVertexBuffer* onCreateVertexBuffer(size_t size, bool dynamic) = 0;
virtual GrIndexBuffer* onCreateIndexBuffer(size_t size, bool dynamic) = 0;
virtual GrTransferBuffer* onCreateTransferBuffer(size_t size, TransferType type) = 0;
diff --git a/src/gpu/GrResourceProvider.cpp b/src/gpu/GrResourceProvider.cpp
index 19fa1cfbb6..79146d0911 100644
--- a/src/gpu/GrResourceProvider.cpp
+++ b/src/gpu/GrResourceProvider.cpp
@@ -227,4 +227,11 @@ GrStencilAttachment* GrResourceProvider::attachStencilAttachment(GrRenderTarget*
return rt->renderTargetPriv().getStencilAttachment();
}
+GrRenderTarget* GrResourceProvider::wrapBackendTextureAsRenderTarget(
+ const GrBackendTextureDesc& desc, GrWrapOwnership ownership) {
+ if (this->isAbandoned()) {
+ return nullptr;
+ }
+ return this->gpu()->wrapBackendTextureAsRenderTarget(desc, ownership);
+}
diff --git a/src/gpu/GrResourceProvider.h b/src/gpu/GrResourceProvider.h
index 783c7c743b..3dfc9ba863 100644
--- a/src/gpu/GrResourceProvider.h
+++ b/src/gpu/GrResourceProvider.h
@@ -147,6 +147,15 @@ public:
const GrCaps* caps() { return this->gpu()->caps(); }
+ /**
+ * Wraps an existing texture with a GrRenderTarget object. This is useful when the provided
+ * texture has a format that cannot be textured from by Skia, but we want to raster to it.
+ *
+ * @return GrRenderTarget object or NULL on failure.
+ */
+ GrRenderTarget* wrapBackendTextureAsRenderTarget(const GrBackendTextureDesc& desc,
+ GrWrapOwnership = kBorrow_GrWrapOwnership);
+
private:
const GrIndexBuffer* createInstancedIndexBuffer(const uint16_t* pattern,
int patternSize,
diff --git a/src/gpu/GrTest.cpp b/src/gpu/GrTest.cpp
index b4fb27bcc5..f082a8693a 100644
--- a/src/gpu/GrTest.cpp
+++ b/src/gpu/GrTest.cpp
@@ -345,6 +345,11 @@ private:
return nullptr;
}
+ GrRenderTarget* onWrapBackendTextureAsRenderTarget(const GrBackendTextureDesc&,
+ GrWrapOwnership) override {
+ return nullptr;
+ }
+
GrVertexBuffer* onCreateVertexBuffer(size_t size, bool dynamic) override { return nullptr; }
GrIndexBuffer* onCreateIndexBuffer(size_t size, bool dynamic) override { return nullptr; }
diff --git a/src/gpu/gl/GrGLGpu.cpp b/src/gpu/gl/GrGLGpu.cpp
index 73d219d033..1070f53c5c 100644
--- a/src/gpu/gl/GrGLGpu.cpp
+++ b/src/gpu/gl/GrGLGpu.cpp
@@ -547,11 +547,6 @@ GrTexture* GrGLGpu::onWrapBackendTexture(const GrBackendTextureDesc& desc,
}
#endif
- int maxSize = this->caps()->maxTextureSize();
- if (desc.fWidth > maxSize || desc.fHeight > maxSize) {
- return nullptr;
- }
-
// next line relies on GrBackendTextureDesc's flags matching GrTexture's
bool renderTarget = SkToBool(desc.fFlags & kRenderTarget_GrBackendTextureFlag);
@@ -657,7 +652,72 @@ GrRenderTarget* GrGLGpu::onWrapBackendRenderTarget(const GrBackendRenderTargetDe
return GrGLRenderTarget::CreateWrapped(this, desc, idDesc, wrapDesc.fStencilBits);
}
+GrRenderTarget* GrGLGpu::onWrapBackendTextureAsRenderTarget(const GrBackendTextureDesc& desc,
+ GrWrapOwnership ownership) {
+#ifdef SK_IGNORE_GL_TEXTURE_TARGET
+ if (!desc.fTextureHandle) {
+ return nullptr;
+ }
+#else
+ const GrGLTextureInfo* info = reinterpret_cast<const GrGLTextureInfo*>(desc.fTextureHandle);
+ if (!info || !info->fID) {
+ return nullptr;
+ }
+#endif
+
+ GrGLTexture::IDDesc idDesc;
+ GrSurfaceDesc surfDesc;
+
+#ifdef SK_IGNORE_GL_TEXTURE_TARGET
+ idDesc.fInfo.fID = static_cast<GrGLuint>(desc.fTextureHandle);
+ // We only support GL_TEXTURE_2D at the moment.
+ idDesc.fInfo.fTarget = GR_GL_TEXTURE_2D;
+#else
+ idDesc.fInfo = *info;
+#endif
+
+ if (GR_GL_TEXTURE_RECTANGLE != idDesc.fInfo.fTarget &&
+ GR_GL_TEXTURE_2D != idDesc.fInfo.fTarget) {
+ // Only texture rectangle and texture 2d are supported. We do not check whether texture
+ // rectangle is supported by Skia - if the caller provided us with a texture rectangle,
+ // we assume the necessary support exists.
+ return nullptr;
+ }
+
+ switch (ownership) {
+ case kAdopt_GrWrapOwnership:
+ idDesc.fLifeCycle = GrGpuResource::kAdopted_LifeCycle;
+ break;
+ case kBorrow_GrWrapOwnership:
+ idDesc.fLifeCycle = GrGpuResource::kBorrowed_LifeCycle;
+ break;
+ }
+
+ surfDesc.fFlags = (GrSurfaceFlags) desc.fFlags;
+ surfDesc.fWidth = desc.fWidth;
+ surfDesc.fHeight = desc.fHeight;
+ surfDesc.fConfig = desc.fConfig;
+ surfDesc.fSampleCnt = SkTMin(desc.fSampleCnt, this->caps()->maxSampleCount());
+ // FIXME: this should be calling resolve_origin(), but Chrome code is currently
+ // assuming the old behaviour, which is that backend textures are always
+ // BottomLeft, even for non-RT's. Once Chrome is fixed, change this to:
+ // glTexDesc.fOrigin = resolve_origin(desc.fOrigin, renderTarget);
+ if (kDefault_GrSurfaceOrigin == desc.fOrigin) {
+ surfDesc.fOrigin = kBottomLeft_GrSurfaceOrigin;
+ } else {
+ surfDesc.fOrigin = desc.fOrigin;
+ }
+
+ GrGLRenderTarget::IDDesc rtIDDesc;
+ if (!this->createRenderTargetObjects(surfDesc, GrGpuResource::kUncached_LifeCycle,
+ idDesc.fInfo, &rtIDDesc)) {
+ return nullptr;
+ }
+ return GrGLRenderTarget::CreateWrapped(this, surfDesc, rtIDDesc, 0);
+}
+
////////////////////////////////////////////////////////////////////////////////
+
bool GrGLGpu::onGetWritePixelsInfo(GrSurface* dstSurface, int width, int height,
GrPixelConfig srcConfig,
DrawPreference* drawPreference,
@@ -1534,9 +1594,6 @@ bool GrGLGpu::createTextureExternalAllocatorImpl(
GrStencilAttachment* GrGLGpu::createStencilAttachmentForRenderTarget(const GrRenderTarget* rt,
int width,
int height) {
- // All internally created RTs are also textures. We don't create
- // SBs for a client's standalone RT (that is a RT that isn't also a texture).
- SkASSERT(rt->asTexture());
SkASSERT(width >= rt->width());
SkASSERT(height >= rt->height());
diff --git a/src/gpu/gl/GrGLGpu.h b/src/gpu/gl/GrGLGpu.h
index 00acd34d9d..87c5c3db37 100644
--- a/src/gpu/gl/GrGLGpu.h
+++ b/src/gpu/gl/GrGLGpu.h
@@ -155,6 +155,8 @@ private:
GrTexture* onWrapBackendTexture(const GrBackendTextureDesc&, GrWrapOwnership) override;
GrRenderTarget* onWrapBackendRenderTarget(const GrBackendRenderTargetDesc&,
GrWrapOwnership) override;
+ GrRenderTarget* onWrapBackendTextureAsRenderTarget(const GrBackendTextureDesc&,
+ GrWrapOwnership) override;
// Given a GrPixelConfig return the index into the stencil format array on GrGLCaps to a
// compatible stencil format, or negative if there is no compatible stencil format.
int getCompatibleStencilIndex(GrPixelConfig config);
diff --git a/src/image/SkSurface.cpp b/src/image/SkSurface.cpp
index 711dfda6a4..4fc904539b 100644
--- a/src/image/SkSurface.cpp
+++ b/src/image/SkSurface.cpp
@@ -199,6 +199,10 @@ bool SkSurface::getRenderTargetHandle(GrBackendObject* obj, BackendHandleAccess
return asSB(this)->onGetRenderTargetHandle(obj, access);
}
+void SkSurface::prepareForExternalIO() {
+ asSB(this)->onPrepareForExternalIO();
+}
+
//////////////////////////////////////////////////////////////////////////////////////
#if !SK_SUPPORT_GPU
@@ -222,4 +226,9 @@ SkSurface* SkSurface::NewFromBackendRenderTarget(GrContext*, const GrBackendRend
return nullptr;
}
+SkSurface* NewFromBackendTextureAsRenderTarget(GrContext*, const GrBackendTextureDesc&,
+ const SkSurfaceProps*) {
+ return nullptr;
+}
+
#endif
diff --git a/src/image/SkSurface_Base.h b/src/image/SkSurface_Base.h
index aaa19cf592..159780b33a 100644
--- a/src/image/SkSurface_Base.h
+++ b/src/image/SkSurface_Base.h
@@ -75,6 +75,11 @@ public:
*/
virtual void onRestoreBackingMutability() {}
+ /**
+ * Issue any pending surface IO to the current backend 3D API and resolve any surface MSAA.
+ */
+ virtual void onPrepareForExternalIO() {}
+
inline SkCanvas* getCachedCanvas();
inline SkImage* refCachedImage(Budgeted, ForceUnique);
diff --git a/src/image/SkSurface_Gpu.cpp b/src/image/SkSurface_Gpu.cpp
index 03fdecef3a..5eca56e8fb 100644
--- a/src/image/SkSurface_Gpu.cpp
+++ b/src/image/SkSurface_Gpu.cpp
@@ -7,6 +7,7 @@
#include "SkSurface_Gpu.h"
+#include "GrResourceProvider.h"
#include "SkCanvas.h"
#include "SkGpuDevice.h"
#include "SkImage_Base.h"
@@ -125,6 +126,10 @@ void SkSurface_Gpu::onDiscard() {
fDevice->accessRenderTarget()->discard();
}
+void SkSurface_Gpu::onPrepareForExternalIO() {
+ fDevice->accessRenderTarget()->prepareForExternalIO();
+}
+
///////////////////////////////////////////////////////////////////////////////
SkSurface* SkSurface::NewRenderTargetDirect(GrRenderTarget* target, const SkSurfaceProps* props) {
@@ -187,4 +192,23 @@ SkSurface* SkSurface::NewFromBackendRenderTarget(GrContext* context,
return new SkSurface_Gpu(device);
}
+SkSurface* SkSurface::NewFromBackendTextureAsRenderTarget(GrContext* context,
+ const GrBackendTextureDesc& desc,
+ const SkSurfaceProps* props) {
+ if (nullptr == context) {
+ return nullptr;
+ }
+ SkAutoTUnref<GrRenderTarget> rt(
+ context->resourceProvider()->wrapBackendTextureAsRenderTarget(desc));
+ if (!rt) {
+ return nullptr;
+ }
+ SkAutoTUnref<SkGpuDevice> device(SkGpuDevice::Create(rt, props,
+ SkGpuDevice::kUninit_InitContents));
+ if (!device) {
+ return nullptr;
+ }
+ return new SkSurface_Gpu(device);
+}
+
#endif
diff --git a/src/image/SkSurface_Gpu.h b/src/image/SkSurface_Gpu.h
index 23aed2cd3c..dff7970d46 100644
--- a/src/image/SkSurface_Gpu.h
+++ b/src/image/SkSurface_Gpu.h
@@ -26,6 +26,7 @@ public:
SkImage* onNewImageSnapshot(Budgeted, ForceCopyMode) override;
void onCopyOnWrite(ContentChangeMode) override;
void onDiscard() override;
+ void onPrepareForExternalIO() override;
SkGpuDevice* getDevice() { return fDevice; }