Add Gr*Proxy classes
authorrobertphillips <robertphillips@google.com>
Tue, 3 May 2016 12:06:29 +0000 (05:06 -0700)
committerCommit bot <commit-bot@chromium.org>
Tue, 3 May 2016 12:06:29 +0000 (05:06 -0700)
This isn't wired in anywhere yet.

GOLD_TRYBOT_URL= https://gold.skia.org/search2?unt=true&query=source_type%3Dgm&master=false&issue=1937553002

Review-Url: https://codereview.chromium.org/1937553002

25 files changed:
gyp/gpu.gypi
include/core/SkTypes.h
include/gpu/GrContext.h
include/gpu/GrRenderTarget.h
include/private/GrRenderTargetProxy.h [new file with mode: 0644]
include/private/GrSurfaceProxy.h [new file with mode: 0644]
include/private/GrTextureProxy.h [new file with mode: 0644]
src/core/SkImageFilter.cpp
src/effects/SkAlphaThresholdFilter.cpp
src/effects/SkDisplacementMapEffect.cpp
src/effects/SkLightingImageFilter.cpp
src/effects/SkMorphologyImageFilter.cpp
src/effects/SkXfermodeImageFilter.cpp
src/gpu/GrBlurUtils.cpp
src/gpu/GrContext.cpp
src/gpu/GrRenderTarget.cpp
src/gpu/GrRenderTargetPriv.h
src/gpu/GrRenderTargetProxy.cpp [new file with mode: 0644]
src/gpu/GrSurfaceProxy.cpp [new file with mode: 0644]
src/gpu/GrTextureProxy.cpp [new file with mode: 0644]
src/gpu/gl/GrGLGpu.cpp
src/image/SkImage_Gpu.cpp
tests/ClearTest.cpp
tests/PrimitiveProcessorTest.cpp
tests/ProxyTest.cpp [new file with mode: 0644]

index 69f286d..5919e24 100644 (file)
@@ -61,6 +61,9 @@
       # Private includes
       '<(skia_include_path)/private/GrAuditTrail.h',
       '<(skia_include_path)/private/GrSingleOwner.h',
+      '<(skia_include_path)/private/GrRenderTargetProxy.h',
+      '<(skia_include_path)/private/GrSurfaceProxy.h',
+      '<(skia_include_path)/private/GrTextureProxy.h',
 
       '<(skia_src_path)/gpu/GrAuditTrail.cpp',
       '<(skia_src_path)/gpu/GrAutoLocaleSetter.h',
       '<(skia_src_path)/gpu/GrRectanizer_skyline.h',
       '<(skia_src_path)/gpu/GrRenderTarget.cpp',
       '<(skia_src_path)/gpu/GrRenderTargetPriv.h',
+      '<(skia_src_path)/gpu/GrRenderTargetProxy.cpp',
       '<(skia_src_path)/gpu/GrReducedClip.cpp',
       '<(skia_src_path)/gpu/GrReducedClip.h',
       '<(skia_src_path)/gpu/GrResourceCache.cpp',
       '<(skia_src_path)/gpu/GrSoftwarePathRenderer.h',
       '<(skia_src_path)/gpu/GrSurfacePriv.h',
       '<(skia_src_path)/gpu/GrSurface.cpp',
+      '<(skia_src_path)/gpu/GrSurfaceProxy.cpp',
       '<(skia_src_path)/gpu/GrSwizzle.h',
       '<(skia_src_path)/gpu/GrTexture.cpp',
       '<(skia_src_path)/gpu/GrTextureParamsAdjuster.h',
       '<(skia_src_path)/gpu/GrTextureParamsAdjuster.cpp',
-      '<(skia_src_path)/gpu/GrTextureProvider.cpp',
       '<(skia_src_path)/gpu/GrTexturePriv.h',
+      '<(skia_src_path)/gpu/GrTextureProvider.cpp',
+      '<(skia_src_path)/gpu/GrTextureProxy.cpp',
       '<(skia_src_path)/gpu/GrTextureToYUVPlanes.cpp',
       '<(skia_src_path)/gpu/GrTextureToYUVPlanes.h',
       '<(skia_src_path)/gpu/GrTextureAccess.cpp',
index f9d0c53..f99bb01 100644 (file)
@@ -442,6 +442,15 @@ enum class SkBudgeted : bool {
     kYes = true
 };
 
+/**
+ * Indicates whether a backing store needs to be an exact match or can be larger
+ * than is strictly necessary
+ */
+enum class SkBackingFit {
+    kApprox,
+    kExact
+};
+
 ///////////////////////////////////////////////////////////////////////////////
 
 /** Use to combine multiple bits in a bitmask in a type safe way.
index cb407aa..6f5ca98 100644 (file)
@@ -194,16 +194,11 @@ public:
      */
     sk_sp<GrDrawContext> drawContext(sk_sp<GrRenderTarget> rt, const SkSurfaceProps* = nullptr);
 
-    enum BackingFit {
-        kTight_BackingFit,
-        kLoose_BackingFit
-    };
-
     /**
      * Create both a GrRenderTarget and a matching GrDrawContext to wrap it.
      * The created GrRenderTarget will always be budgeted.
      */
-    sk_sp<GrDrawContext> newDrawContext(BackingFit fit, 
+    sk_sp<GrDrawContext> newDrawContext(SkBackingFit fit, 
                                         int width, int height,
                                         GrPixelConfig config,
                                         int sampleCnt = 0,
index eb9f142..ff75af3 100644 (file)
@@ -11,6 +11,7 @@
 #include "GrSurface.h"
 #include "SkRect.h"
 
+class GrCaps;
 class GrDrawTarget;
 class GrStencilAttachment;
 class GrRenderTargetPriv;
@@ -155,6 +156,8 @@ public:
     void setLastDrawTarget(GrDrawTarget* dt);
     GrDrawTarget* getLastDrawTarget() { return fLastDrawTarget; }
 
+    static SampleConfig ComputeSampleConfig(const GrCaps& caps, int sampleCnt);
+
 protected:
     GrRenderTarget(GrGpu* gpu, const GrSurfaceDesc& desc,
                    SampleConfig sampleConfig, GrStencilAttachment* stencil = nullptr)
diff --git a/include/private/GrRenderTargetProxy.h b/include/private/GrRenderTargetProxy.h
new file mode 100644 (file)
index 0000000..287aa01
--- /dev/null
@@ -0,0 +1,123 @@
+/*
+ * Copyright 2016 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef GrRenderTargetProxy_DEFINED
+#define GrRenderTargetProxy_DEFINED
+
+#include "GrRenderTarget.h"
+#include "GrSurfaceProxy.h"
+#include "GrTypes.h"
+
+class GrTextureProvider;
+
+// This class delays the acquisition of RenderTargets until they are actually
+// required
+// Beware: the uniqueID of the RenderTargetProxy will usually be different than
+// the uniqueID of the RenderTarget it represents!
+class GrRenderTargetProxy : public GrSurfaceProxy {
+public:
+    /**
+     * The caller gets the creation ref.
+     */
+    static sk_sp<GrRenderTargetProxy> Make(const GrCaps&, const GrSurfaceDesc&,
+                                           SkBackingFit, SkBudgeted);
+    static sk_sp<GrRenderTargetProxy> Make(sk_sp<GrRenderTarget> rt);
+
+    ~GrRenderTargetProxy() override;
+
+    // TODO: add asTextureProxy variants
+    GrRenderTargetProxy* asRenderTargetProxy() override { return this; }
+    const GrRenderTargetProxy* asRenderTargetProxy() const override { return this; }
+
+    // Actually instantiate the backing rendertarget, if necessary.
+    GrRenderTarget* instantiate(GrTextureProvider* texProvider);
+
+    /**
+     * @return true  if the surface is multisampled in all buffers,
+     *         false otherwise
+     */
+    bool isUnifiedMultisampled() const {
+        if (fSampleConfig != GrRenderTarget::kUnified_SampleConfig) {
+            return false;
+        }
+        return 0 != fDesc.fSampleCnt;
+    }
+
+    /**
+     * @return true if the surface is multisampled in the stencil buffer,
+     *         false otherwise
+     */
+    bool isStencilBufferMultisampled() const {
+        return 0 != fDesc.fSampleCnt;
+    }
+
+    /**
+     * @return the number of color samples-per-pixel, or zero if non-MSAA or
+     *         multisampled in the stencil buffer only.
+     */
+    int numColorSamples() const {
+        if (fSampleConfig == GrRenderTarget::kUnified_SampleConfig) {
+            return fDesc.fSampleCnt;
+        }
+        return 0;
+    }
+
+    /**
+     * @return the number of stencil samples-per-pixel, or zero if non-MSAA.
+     */
+    int numStencilSamples() const {
+        return fDesc.fSampleCnt;
+    }
+
+    /**
+     * @return true if the surface is mixed sampled, false otherwise.
+     */
+    bool hasMixedSamples() const {
+        SkASSERT(GrRenderTarget::kStencil_SampleConfig != fSampleConfig ||
+                 this->isStencilBufferMultisampled());
+        return GrRenderTarget::kStencil_SampleConfig == fSampleConfig;
+    }
+
+    void setLastDrawTarget(GrDrawTarget* dt);
+    GrDrawTarget* getLastDrawTarget() { return fLastDrawTarget; }
+
+private:
+    // TODO: we can probably munge the 'desc' in both the wrapped and deferred 
+    // cases to make the sampleConfig/numSamples stuff more rational.
+    GrRenderTargetProxy(const GrCaps& caps, const GrSurfaceDesc& desc,
+                        SkBackingFit fit, SkBudgeted budgeted)
+        : INHERITED(desc, fit, budgeted)
+        , fTarget(nullptr)
+        , fSampleConfig(GrRenderTarget::ComputeSampleConfig(caps, desc.fSampleCnt))
+        , fLastDrawTarget(nullptr) {
+    }
+
+    // Wrapped version
+    GrRenderTargetProxy(sk_sp<GrRenderTarget> rt);
+
+    // For wrapped render targets we store it here.
+    // For deferred proxies we will fill this in when we need to instantiate the deferred resource
+    sk_sp<GrRenderTarget>        fTarget;
+
+    // The sample config doesn't usually get computed until the render target is instantiated but
+    // the render target proxy may need to answer queries about it before then. For this reason
+    // we precompute it in the deferred case. In the wrapped case we just copy the wrapped
+    // rendertarget's info here.
+    GrRenderTarget::SampleConfig fSampleConfig;
+
+    // The last drawTarget that wrote to or is currently going to write to this renderTarget
+    // The drawTarget can be closed (e.g., no draw context is currently bound
+    // to this renderTarget).
+    // This back-pointer is required so that we can add a dependancy between
+    // the drawTarget used to create the current contents of this renderTarget
+    // and the drawTarget of a destination renderTarget to which this one is being drawn.
+    GrDrawTarget* fLastDrawTarget;
+
+    typedef GrSurfaceProxy INHERITED;
+};
+
+#endif
diff --git a/include/private/GrSurfaceProxy.h b/include/private/GrSurfaceProxy.h
new file mode 100644 (file)
index 0000000..63e646b
--- /dev/null
@@ -0,0 +1,72 @@
+/*
+ * Copyright 2016 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef GrSurfaceProxy_DEFINED
+#define GrSurfaceProxy_DEFINED
+
+#include "GrGpuResource.h"
+
+class GrTextureProxy;
+class GrRenderTargetProxy;
+
+class GrSurfaceProxy : public GrIORef<GrSurfaceProxy> {
+public:
+    const GrSurfaceDesc& desc() const { return fDesc; }
+
+    GrSurfaceOrigin origin() const {
+        SkASSERT(kTopLeft_GrSurfaceOrigin == fDesc.fOrigin ||
+                 kBottomLeft_GrSurfaceOrigin == fDesc.fOrigin);
+        return fDesc.fOrigin;
+    }
+    int width() const { return fDesc.fWidth; }
+    int height() const { return fDesc.fWidth; }
+    GrPixelConfig config() const { return fDesc.fConfig; }
+
+    uint32_t uniqueID() const { return fUniqueID; }
+
+    /**
+     * @return the texture proxy associated with the surface proxy, may be NULL.
+     */
+    virtual GrTextureProxy* asTextureProxy() { return nullptr; }
+    virtual const GrTextureProxy* asTextureProxy() const { return nullptr; }
+
+    /**
+     * @return the render target proxy associated with the surface proxy, may be NULL.
+     */
+    virtual GrRenderTargetProxy* asRenderTargetProxy() { return nullptr; }
+    virtual const GrRenderTargetProxy* asRenderTargetProxy() const { return nullptr; }
+
+protected:
+    GrSurfaceProxy(const GrSurfaceDesc& desc, SkBackingFit fit, SkBudgeted budgeted)
+        : fDesc(desc)
+        , fFit(fit)
+        , fBudgeted(budgeted)
+        , fUniqueID(CreateUniqueID()) {
+    }
+
+    virtual ~GrSurfaceProxy() {}
+
+    // For wrapped resources, 'fDesc' will always be filled in from the wrapped resource.
+    const GrSurfaceDesc fDesc;
+    const SkBackingFit  fFit;      // always exact for wrapped resources
+    const SkBudgeted    fBudgeted; // set from the backing resource for wrapped resources
+    const uint32_t      fUniqueID;
+
+private:
+    static uint32_t CreateUniqueID();
+
+    // See comment in GrGpuResource.h.
+    void notifyAllCntsAreZero(CntType) const {}
+    bool notifyRefCountIsZero() const { return false; }
+
+    typedef GrIORef<GrSurfaceProxy> INHERITED;
+
+    // to access notifyAllCntsAreZero and notifyRefCntIsZero.
+    friend class GrIORef<GrSurfaceProxy>;
+};
+
+#endif
diff --git a/include/private/GrTextureProxy.h b/include/private/GrTextureProxy.h
new file mode 100644 (file)
index 0000000..eb82ca7
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2016 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef GrTextureProxy_DEFINED
+#define GrTextureProxy_DEFINED
+
+#include "GrSurfaceProxy.h"
+#include "GrTexture.h"
+
+class GrTextureProvider;
+
+// This class delays the acquisition of textures until they are actually required
+class GrTextureProxy : public GrSurfaceProxy {
+public:
+    // TODO: need to refine ownership semantics of 'srcData' if we're in completely
+    // deferred mode
+    static sk_sp<GrTextureProxy> Make(const GrSurfaceDesc&, SkBackingFit, SkBudgeted,
+                                      const void* srcData = nullptr, size_t rowBytes = 0);
+    static sk_sp<GrTextureProxy> Make(sk_sp<GrTexture>);
+
+    // TODO: add asRenderTargetProxy variants
+    GrTextureProxy* asTextureProxy() override { return this; }
+    const GrTextureProxy* asTextureProxy() const override { return this; }
+
+    // Actually instantiate the backing texture, if necessary
+    GrTexture* instantiate(GrTextureProvider* texProvider);
+
+private:
+    GrTextureProxy(const GrSurfaceDesc& desc, SkBackingFit fit, SkBudgeted budgeted,
+                   const void* /*srcData*/, size_t /*rowBytes*/)
+        : INHERITED(desc, fit, budgeted) {
+        // TODO: Handle 'srcData' here
+    }
+
+    // Wrapped version
+    GrTextureProxy(sk_sp<GrTexture> tex);
+
+    // For wrapped textures we store it here.
+    // For deferred proxies we will fill this in when we need to instantiate the deferred resource
+    sk_sp<GrTexture> fTexture;
+
+    typedef GrSurfaceProxy INHERITED;
+};
+
+#endif
index d004252..899083d 100644 (file)
@@ -280,7 +280,7 @@ sk_sp<SkSpecialImage> SkImageFilter::DrawWithFP(GrContext* context,
     paint.addColorFragmentProcessor(fp.get());
     paint.setPorterDuffXPFactory(SkXfermode::kSrc_Mode);
 
-    sk_sp<GrDrawContext> drawContext(context->newDrawContext(GrContext::kLoose_BackingFit,
+    sk_sp<GrDrawContext> drawContext(context->newDrawContext(SkBackingFit::kApprox,
                                                              bounds.width(), bounds.height(),
                                                              kRGBA_8888_GrPixelConfig));
     if (!drawContext) {
index cec45ba..a4876c8 100644 (file)
@@ -102,7 +102,7 @@ sk_sp<GrTexture> SkAlphaThresholdFilterImpl::createMaskTexture(GrContext* contex
         config = kRGBA_8888_GrPixelConfig;
     }
 
-    sk_sp<GrDrawContext> drawContext(context->newDrawContext(GrContext::kLoose_BackingFit,
+    sk_sp<GrDrawContext> drawContext(context->newDrawContext(SkBackingFit::kApprox,
                                                              bounds.width(), bounds.height(),
                                                              config));
     if (!drawContext) {
index cf9e2c3..befda79 100644 (file)
@@ -335,7 +335,7 @@ sk_sp<SkSpecialImage> SkDisplacementMapEffect::onFilterImage(SkSpecialImage* sou
         SkMatrix matrix;
         matrix.setTranslate(-SkIntToScalar(colorBounds.x()), -SkIntToScalar(colorBounds.y()));
 
-        sk_sp<GrDrawContext> drawContext(context->newDrawContext(GrContext::kLoose_BackingFit,
+        sk_sp<GrDrawContext> drawContext(context->newDrawContext(SkBackingFit::kApprox,
                                                                  bounds.width(), bounds.height(),
                                                                  kSkia8888_GrPixelConfig));
         if (!drawContext) {
index 6efb0f6..d9b2936 100644 (file)
@@ -407,7 +407,7 @@ sk_sp<SkSpecialImage> SkLightingImageFilterInternal::filterImageGPU(SkSpecialIma
     sk_sp<GrTexture> inputTexture(input->asTextureRef(context));
     SkASSERT(inputTexture);
 
-    sk_sp<GrDrawContext> drawContext(context->newDrawContext(GrContext::kLoose_BackingFit,
+    sk_sp<GrDrawContext> drawContext(context->newDrawContext(SkBackingFit::kApprox,
                                                              offsetBounds.width(),
                                                              offsetBounds.height(),
                                                              kRGBA_8888_GrPixelConfig));
index 2a0f078..121a7fd 100644 (file)
@@ -487,7 +487,7 @@ static sk_sp<SkSpecialImage> apply_morphology(GrContext* context,
     SkASSERT(radius.width() > 0 || radius.height() > 0);
 
     if (radius.fWidth > 0) {
-        sk_sp<GrDrawContext> dstDrawContext(context->newDrawContext(GrContext::kLoose_BackingFit,
+        sk_sp<GrDrawContext> dstDrawContext(context->newDrawContext(SkBackingFit::kApprox,
                                                                     rect.width(), rect.height(),
                                                                     kSkia8888_GrPixelConfig));
         if (!dstDrawContext) {
@@ -508,7 +508,7 @@ static sk_sp<SkSpecialImage> apply_morphology(GrContext* context,
         srcRect = dstRect;
     }
     if (radius.fHeight > 0) {
-        sk_sp<GrDrawContext> dstDrawContext(context->newDrawContext(GrContext::kLoose_BackingFit,
+        sk_sp<GrDrawContext> dstDrawContext(context->newDrawContext(SkBackingFit::kApprox,
                                                                     rect.width(), rect.height(),
                                                                     kSkia8888_GrPixelConfig));
         if (!dstDrawContext) {
index b1e19bb..99ce24f 100644 (file)
@@ -238,7 +238,7 @@ sk_sp<SkSpecialImage> SkXfermodeImageFilter::filterImageGPU(SkSpecialImage* sour
 
     paint.setPorterDuffXPFactory(SkXfermode::kSrc_Mode);
 
-    sk_sp<GrDrawContext> drawContext(context->newDrawContext(GrContext::kLoose_BackingFit,
+    sk_sp<GrDrawContext> drawContext(context->newDrawContext(SkBackingFit::kApprox,
                                                              bounds.width(), bounds.height(),
                                                              kSkia8888_GrPixelConfig));
     if (!drawContext) {
index f95bdff..59a3dfc 100644 (file)
@@ -116,7 +116,7 @@ static sk_sp<GrTexture> create_mask_GPU(GrContext* context,
         config = kAlpha_8_GrPixelConfig;
     }
 
-    sk_sp<GrDrawContext> drawContext(context->newDrawContext(GrContext::kLoose_BackingFit,
+    sk_sp<GrDrawContext> drawContext(context->newDrawContext(SkBackingFit::kApprox,
                                                              SkScalarCeilToInt(maskRect->width()), 
                                                              SkScalarCeilToInt(maskRect->height()),
                                                              config,
index a186bd8..31845f9 100644 (file)
@@ -615,7 +615,7 @@ sk_sp<GrDrawContext> GrContext::drawContext(sk_sp<GrRenderTarget> rt,
     return fDrawingManager->drawContext(std::move(rt), surfaceProps);
 }
 
-sk_sp<GrDrawContext> GrContext::newDrawContext(BackingFit fit,
+sk_sp<GrDrawContext> GrContext::newDrawContext(SkBackingFit fit,
                                                int width, int height,
                                                GrPixelConfig config,
                                                int sampleCnt,
@@ -629,7 +629,7 @@ sk_sp<GrDrawContext> GrContext::newDrawContext(BackingFit fit,
     desc.fSampleCnt = sampleCnt;
 
     sk_sp<GrTexture> tex;
-    if (kTight_BackingFit == fit) {
+    if (SkBackingFit::kExact == fit) {
         tex.reset(this->textureProvider()->createTexture(desc, SkBudgeted::kYes));
     } else {
         tex.reset(this->textureProvider()->createApproxTexture(desc));
index a673640..ebbfae9 100644 (file)
@@ -109,3 +109,11 @@ const GrGpu::MultisampleSpecs&
 GrRenderTargetPriv::getMultisampleSpecs(const GrStencilSettings& stencil) const {
     return fRenderTarget->getGpu()->getMultisampleSpecs(fRenderTarget, stencil);
 }
+
+GrRenderTarget::SampleConfig GrRenderTarget::ComputeSampleConfig(const GrCaps& caps,
+                                                                 int sampleCnt) {
+    return (caps.usesMixedSamples() && sampleCnt > 0)
+                        ? GrRenderTarget::kStencil_SampleConfig
+                        : GrRenderTarget::kUnified_SampleConfig;
+}
+
index e64ed57..24b7e88 100644 (file)
@@ -32,6 +32,8 @@ public:
 
     const GrGpu::MultisampleSpecs& getMultisampleSpecs(const GrStencilSettings& stencil) const;
 
+    GrRenderTarget::SampleConfig sampleConfig() const { return fRenderTarget->fSampleConfig; }
+
 private:
     explicit GrRenderTargetPriv(GrRenderTarget* renderTarget) : fRenderTarget(renderTarget) {}
     GrRenderTargetPriv(const GrRenderTargetPriv&) {} // unimpl
diff --git a/src/gpu/GrRenderTargetProxy.cpp b/src/gpu/GrRenderTargetProxy.cpp
new file mode 100644 (file)
index 0000000..8d821c3
--- /dev/null
@@ -0,0 +1,77 @@
+/*
+ * Copyright 2016 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "GrRenderTargetProxy.h"
+
+#include "GrDrawTarget.h"
+#include "GrGpuResourcePriv.h"
+#include "GrRenderTargetPriv.h"
+
+GrRenderTargetProxy::GrRenderTargetProxy(sk_sp<GrRenderTarget> rt)
+    : INHERITED(rt->desc(), SkBackingFit::kExact, rt->resourcePriv().isBudgeted())
+    , fTarget(std::move(rt))
+    , fSampleConfig(fTarget->renderTargetPriv().sampleConfig())
+    , fLastDrawTarget(nullptr) {
+}
+
+GrRenderTargetProxy::~GrRenderTargetProxy() {
+    if (fLastDrawTarget) {
+        fLastDrawTarget->clearRT();
+    }
+    SkSafeUnref(fLastDrawTarget);
+}
+
+GrRenderTarget* GrRenderTargetProxy::instantiate(GrTextureProvider* texProvider) {
+    if (fTarget) {
+        return fTarget.get();
+    }
+
+    // TODO: it would be nice to not have to copy the desc here
+    GrSurfaceDesc desc = fDesc;
+    desc.fFlags |= GrSurfaceFlags::kRenderTarget_GrSurfaceFlag;
+
+    sk_sp<GrTexture> tex;
+    if (SkBackingFit::kApprox == fFit) {
+        tex.reset(texProvider->createApproxTexture(desc));
+    } else {
+        tex.reset(texProvider->createTexture(desc, fBudgeted));
+    }
+    if (!tex || !tex->asRenderTarget()) {
+        return nullptr;
+    }
+
+    fTarget.reset(tex->asRenderTarget());
+
+    // Check that our a priori computation matched the ultimate reality
+    SkASSERT(fSampleConfig == fTarget->renderTargetPriv().sampleConfig());
+
+    return fTarget.get();
+}
+
+void GrRenderTargetProxy::setLastDrawTarget(GrDrawTarget* dt) {
+    if (fLastDrawTarget) {
+        // The non-MDB world never closes so we can't check this condition
+#ifdef ENABLE_MDB
+        SkASSERT(fLastDrawTarget->isClosed());
+#endif
+        fLastDrawTarget->clearRT();
+    }
+
+    SkRefCnt_SafeAssign(fLastDrawTarget, dt);
+}
+
+sk_sp<GrRenderTargetProxy> GrRenderTargetProxy::Make(const GrCaps& caps,
+                                                     const GrSurfaceDesc& desc,
+                                                     SkBackingFit fit,
+                                                     SkBudgeted budgeted) {
+    return sk_sp<GrRenderTargetProxy>(new GrRenderTargetProxy(caps, desc, fit, budgeted));
+}
+
+sk_sp<GrRenderTargetProxy> GrRenderTargetProxy::Make(sk_sp<GrRenderTarget> rt) {
+    return sk_sp<GrRenderTargetProxy>(new GrRenderTargetProxy(rt));
+}
+
diff --git a/src/gpu/GrSurfaceProxy.cpp b/src/gpu/GrSurfaceProxy.cpp
new file mode 100644 (file)
index 0000000..b8b5d75
--- /dev/null
@@ -0,0 +1,19 @@
+/*
+ * Copyright 2016 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "GrSurfaceProxy.h"
+
+#include "SkAtomics.h"
+
+uint32_t GrSurfaceProxy::CreateUniqueID() {
+    static int32_t gUniqueID = SK_InvalidUniqueID;
+    uint32_t id;
+    do {
+        id = static_cast<uint32_t>(sk_atomic_inc(&gUniqueID) + 1);
+    } while (id == SK_InvalidUniqueID);
+    return id;
+}
diff --git a/src/gpu/GrTextureProxy.cpp b/src/gpu/GrTextureProxy.cpp
new file mode 100644 (file)
index 0000000..09c22e3
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2016 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "GrTextureProxy.h"
+
+#include "GrTextureProvider.h"
+#include "GrGpuResourcePriv.h"
+
+GrTextureProxy::GrTextureProxy(sk_sp<GrTexture> tex)
+    : INHERITED(tex->desc(), SkBackingFit::kExact, tex->resourcePriv().isBudgeted())
+    , fTexture(std::move(tex)) {
+}
+
+GrTexture* GrTextureProxy::instantiate(GrTextureProvider* texProvider) {
+    if (fTexture) {
+        return fTexture.get();
+    }
+
+    if (SkBackingFit::kApprox == fFit) {
+        fTexture.reset(texProvider->createApproxTexture(fDesc));
+    } else {
+        fTexture.reset(texProvider->createTexture(fDesc, fBudgeted));
+    }
+
+    return fTexture.get();
+}
+
+sk_sp<GrTextureProxy> GrTextureProxy::Make(const GrSurfaceDesc& desc,
+                                           SkBackingFit fit,
+                                           SkBudgeted budgeted,
+                                           const void* srcData,
+                                           size_t rowBytes) {
+    // TODO: handle 'srcData' (we could use the wrapped version if there is data)
+    SkASSERT(!srcData && !rowBytes);
+    return sk_sp<GrTextureProxy>(new GrTextureProxy(desc, fit, budgeted, srcData, rowBytes));
+}
+
+sk_sp<GrTextureProxy> GrTextureProxy::Make(sk_sp<GrTexture> tex) {
+    return sk_sp<GrTextureProxy>(new GrTextureProxy(tex));
+}
index 3372d42..d24734f 100644 (file)
@@ -1475,9 +1475,9 @@ bool GrGLGpu::createRenderTargetObjects(const GrSurfaceDesc& desc,
     idDesc->fRTFBOID = 0;
     idDesc->fRTFBOOwnership = GrBackendObjectOwnership::kOwned;
     idDesc->fTexFBOID = 0;
-    idDesc->fSampleConfig = (GrGLCaps::kMixedSamples_MSFBOType == this->glCaps().msFBOType() &&
-                            desc.fSampleCnt > 0) ? GrRenderTarget::kStencil_SampleConfig :
-                                                   GrRenderTarget::kUnified_SampleConfig;
+    SkASSERT((GrGLCaps::kMixedSamples_MSFBOType == this->glCaps().msFBOType()) ==
+             this->caps()->usesMixedSamples());
+    idDesc->fSampleConfig = GrRenderTarget::ComputeSampleConfig(*this->caps(), desc.fSampleCnt);
 
     GrGLenum status;
 
index eea7e2c..339dee7 100644 (file)
@@ -253,7 +253,7 @@ sk_sp<SkImage> SkImage::MakeFromYUVTexturesCopy(GrContext* ctx , SkYUVColorSpace
     const int height = yuvSizes[0].fHeight;
 
     // Needs to be a render target in order to draw to it for the yuv->rgb conversion.
-    sk_sp<GrDrawContext> drawContext(ctx->newDrawContext(GrContext::kTight_BackingFit,
+    sk_sp<GrDrawContext> drawContext(ctx->newDrawContext(SkBackingFit::kExact,
                                                          width, height,
                                                          kRGBA_8888_GrPixelConfig,
                                                          0,
index 7a533ba..d227cb8 100644 (file)
@@ -45,7 +45,7 @@ static bool reset_dc(sk_sp<GrDrawContext>* dc, GrContext* context, int w, int h)
     }
     context->freeGpuResources();
 
-    *dc = context->newDrawContext(GrContext::kTight_BackingFit, w, h, kRGBA_8888_GrPixelConfig);
+    *dc = context->newDrawContext(SkBackingFit::kExact, w, h, kRGBA_8888_GrPixelConfig);
 
     SkASSERT((*dc)->accessRenderTarget()->getUniqueID() != oldID);
 
index b1157a3..a82237d 100644 (file)
@@ -104,7 +104,7 @@ private:
 DEF_GPUTEST_FOR_ALL_GL_CONTEXTS(VertexAttributeCount, reporter, ctxInfo) {
     GrContext* context = ctxInfo.fGrContext;
 
-    sk_sp<GrDrawContext> dc(context->newDrawContext(GrContext::kLoose_BackingFit,
+    sk_sp<GrDrawContext> dc(context->newDrawContext(SkBackingFit::kApprox,
                                                     1, 1, kRGBA_8888_GrPixelConfig));
     if (!dc) {
         ERRORF(reporter, "Could not create draw context.");
diff --git a/tests/ProxyTest.cpp b/tests/ProxyTest.cpp
new file mode 100644 (file)
index 0000000..45a438a
--- /dev/null
@@ -0,0 +1,154 @@
+/*
+ * Copyright 2016 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+// This is a GPU-backend specific test.
+
+#include "Test.h"
+
+#if SK_SUPPORT_GPU
+#include "GrSurfaceProxy.h"
+#include "GrTextureProxy.h"
+#include "GrRenderTargetProxy.h"
+
+static void check_surface(skiatest::Reporter* reporter,
+                          GrSurfaceProxy* proxy,
+                          GrSurfaceOrigin origin,
+                          int width, int height, 
+                          GrPixelConfig config) {
+    REPORTER_ASSERT(reporter, proxy->origin() == origin);
+    REPORTER_ASSERT(reporter, proxy->width() == width);
+    REPORTER_ASSERT(reporter, proxy->height() == height);
+    REPORTER_ASSERT(reporter, proxy->config() == config);
+}
+
+static void check_rendertarget(skiatest::Reporter* reporter,
+                               GrTextureProvider* provider,
+                               GrRenderTargetProxy* rtProxy,
+                               SkBackingFit fit) {
+    REPORTER_ASSERT(reporter, rtProxy->asTextureProxy() == nullptr); // for now
+    REPORTER_ASSERT(reporter, rtProxy->asRenderTargetProxy() == rtProxy);
+
+    GrRenderTarget* rt = rtProxy->instantiate(provider);
+    REPORTER_ASSERT(reporter, rt);
+
+    REPORTER_ASSERT(reporter, rt->origin() == rtProxy->origin());
+    if (SkBackingFit::kExact == fit) {
+        REPORTER_ASSERT(reporter, rt->width() == rtProxy->width());
+        REPORTER_ASSERT(reporter, rt->height() == rtProxy->height());
+    } else {
+        REPORTER_ASSERT(reporter, rt->width() >= rtProxy->width());
+        REPORTER_ASSERT(reporter, rt->height() >= rtProxy->height());    
+    }
+    REPORTER_ASSERT(reporter, rt->config() == rtProxy->config());
+
+    REPORTER_ASSERT(reporter, rt->isUnifiedMultisampled() == rtProxy->isUnifiedMultisampled());
+    REPORTER_ASSERT(reporter, rt->isStencilBufferMultisampled() ==
+                              rtProxy->isStencilBufferMultisampled());
+    REPORTER_ASSERT(reporter, rt->numColorSamples() == rtProxy->numColorSamples());
+    REPORTER_ASSERT(reporter, rt->numStencilSamples() == rtProxy->numStencilSamples());
+    REPORTER_ASSERT(reporter, rt->hasMixedSamples() == rtProxy->hasMixedSamples());
+}
+
+static void check_texture(skiatest::Reporter* reporter,
+                          GrTextureProvider* provider,
+                          GrTextureProxy* texProxy,
+                          SkBackingFit fit) {
+    REPORTER_ASSERT(reporter, texProxy->asTextureProxy() == texProxy);
+    REPORTER_ASSERT(reporter, texProxy->asRenderTargetProxy() == nullptr); // for now
+
+    GrTexture* tex = texProxy->instantiate(provider);
+    REPORTER_ASSERT(reporter, tex);
+
+    REPORTER_ASSERT(reporter, tex->origin() == texProxy->origin());
+    if (SkBackingFit::kExact == fit) {
+        REPORTER_ASSERT(reporter, tex->width() == texProxy->width());
+        REPORTER_ASSERT(reporter, tex->height() == texProxy->height());
+    } else {
+        REPORTER_ASSERT(reporter, tex->width() >= texProxy->width());
+        REPORTER_ASSERT(reporter, tex->height() >= texProxy->height());
+    }
+    REPORTER_ASSERT(reporter, tex->config() == texProxy->config());
+}
+
+
+DEF_GPUTEST_FOR_GL_RENDERING_CONTEXTS(AllocedProxyTest, reporter, ctxInfo) {
+    GrTextureProvider* provider = ctxInfo.fGrContext->textureProvider();
+
+    for (auto origin : { kBottomLeft_GrSurfaceOrigin, kTopLeft_GrSurfaceOrigin }) {
+        for (auto widthHeight : { 100, 128 }) {
+            for (auto config : { kAlpha_8_GrPixelConfig, kRGBA_8888_GrPixelConfig }) {
+                for (auto fit : { SkBackingFit::kExact, SkBackingFit::kApprox }) {
+                    for (auto budgeted : { SkBudgeted::kYes, SkBudgeted::kNo }) {
+                        for (auto numSamples : { 0, 4}) {
+                            GrSurfaceDesc desc;
+                            desc.fOrigin = origin;
+                            desc.fWidth = widthHeight;
+                            desc.fHeight = widthHeight;
+                            desc.fConfig = config;
+                            desc.fSampleCnt = numSamples;
+
+                            sk_sp<GrRenderTargetProxy> rtProxy(GrRenderTargetProxy::Make(
+                                                                    *ctxInfo.fGrContext->caps(),
+                                                                    desc, 
+                                                                    fit,
+                                                                    budgeted));
+                            check_surface(reporter, rtProxy.get(), origin,
+                                          widthHeight, widthHeight, config);
+                            check_rendertarget(reporter, provider, rtProxy.get(), fit);
+
+                            desc.fSampleCnt = 0;
+
+                            sk_sp<GrTextureProxy> texProxy(GrTextureProxy::Make(desc,
+                                                                                fit,
+                                                                                budgeted));
+                            check_surface(reporter, texProxy.get(), origin,
+                                          widthHeight, widthHeight, config);
+                            check_texture(reporter, provider, texProxy.get(), fit);
+                        }
+                    }
+                }
+            }
+        }
+    }
+}
+
+DEF_GPUTEST_FOR_GL_RENDERING_CONTEXTS(WrappedProxyTest, reporter, ctxInfo) {
+    GrTextureProvider* provider = ctxInfo.fGrContext->textureProvider();
+
+    static const int kWidthHeight = 100;
+
+    for (auto origin : { kBottomLeft_GrSurfaceOrigin, kTopLeft_GrSurfaceOrigin }) {
+        for (auto config : { kAlpha_8_GrPixelConfig, kRGBA_8888_GrPixelConfig }) {
+            for (auto budgeted : { SkBudgeted::kYes, SkBudgeted::kNo }) {
+                for (auto numSamples: { 0, 4}) {
+                    GrSurfaceDesc desc;
+                    desc.fFlags = kRenderTarget_GrSurfaceFlag;
+                    desc.fOrigin = origin;
+                    desc.fWidth = kWidthHeight;
+                    desc.fHeight = kWidthHeight;
+                    desc.fConfig = config;
+                    desc.fSampleCnt = numSamples;
+
+                    sk_sp<GrTexture> tex(provider->createTexture(desc, budgeted));
+                    sk_sp<GrRenderTarget> rt(sk_ref_sp(tex->asRenderTarget()));
+
+                    sk_sp<GrRenderTargetProxy> rtProxy(GrRenderTargetProxy::Make(rt));
+                    check_surface(reporter, rtProxy.get(), origin,
+                                  kWidthHeight, kWidthHeight, config);
+                    check_rendertarget(reporter, provider, rtProxy.get(), SkBackingFit::kExact);
+
+                    sk_sp<GrTextureProxy> texProxy(GrTextureProxy::Make(tex));
+                    check_surface(reporter, texProxy.get(), origin,
+                                  kWidthHeight, kWidthHeight, config);
+                    check_texture(reporter, provider, texProxy.get(), SkBackingFit::kExact);
+                }
+            }
+        }
+    }
+}
+
+#endif