Home | History | Annotate | Download | only in image
      1 /*
      2  * Copyright 2012 Google Inc.
      3  *
      4  * Use of this source code is governed by a BSD-style license that can be
      5  * found in the LICENSE file.
      6  */
      7 
      8 #include "SkSurface_Base.h"
      9 #include "SkImagePriv.h"
     10 #include "SkCanvas.h"
     11 #include "SkGpuDevice.h"
     12 
     13 class SkSurface_Gpu : public SkSurface_Base {
     14 public:
     15     SK_DECLARE_INST_COUNT(SkSurface_Gpu)
     16 
     17     SkSurface_Gpu(GrRenderTarget*, bool cached, const SkSurfaceProps*, bool doClear);
     18     virtual ~SkSurface_Gpu();
     19 
     20     virtual SkCanvas* onNewCanvas() SK_OVERRIDE;
     21     virtual SkSurface* onNewSurface(const SkImageInfo&) SK_OVERRIDE;
     22     virtual SkImage* onNewImageSnapshot() SK_OVERRIDE;
     23     virtual void onDraw(SkCanvas*, SkScalar x, SkScalar y,
     24                         const SkPaint*) SK_OVERRIDE;
     25     virtual void onCopyOnWrite(ContentChangeMode) SK_OVERRIDE;
     26     virtual void onDiscard() SK_OVERRIDE;
     27 
     28 private:
     29     SkGpuDevice* fDevice;
     30 
     31     typedef SkSurface_Base INHERITED;
     32 };
     33 
     34 ///////////////////////////////////////////////////////////////////////////////
     35 
     36 SkSurface_Gpu::SkSurface_Gpu(GrRenderTarget* renderTarget, bool cached, const SkSurfaceProps* props,
     37                              bool doClear)
     38         : INHERITED(renderTarget->width(), renderTarget->height(), props)
     39 {
     40     int deviceFlags = 0;
     41     deviceFlags |= cached ? SkGpuDevice::kCached_Flag : 0;
     42     deviceFlags |= this->props().isUseDistanceFieldFonts() ? SkGpuDevice::kDFFonts_Flag : 0;
     43     fDevice = SkGpuDevice::Create(renderTarget, this->props(), deviceFlags);
     44 
     45     if (kRGB_565_GrPixelConfig != renderTarget->config() && doClear) {
     46         fDevice->clear(0x0);
     47     }
     48 }
     49 
     50 SkSurface_Gpu::~SkSurface_Gpu() {
     51     SkSafeUnref(fDevice);
     52 }
     53 
     54 SkCanvas* SkSurface_Gpu::onNewCanvas() {
     55     SkCanvas::InitFlags flags = SkCanvas::kDefault_InitFlags;
     56     // When we think this works...
     57 //    flags |= SkCanvas::kConservativeRasterClip_InitFlag;
     58 
     59     return SkNEW_ARGS(SkCanvas, (fDevice, &this->props(), flags));
     60 }
     61 
     62 SkSurface* SkSurface_Gpu::onNewSurface(const SkImageInfo& info) {
     63     GrRenderTarget* rt = fDevice->accessRenderTarget();
     64     int sampleCount = rt->numSamples();
     65     return SkSurface::NewRenderTarget(fDevice->context(), info, sampleCount, &this->props());
     66 }
     67 
     68 SkImage* SkSurface_Gpu::onNewImageSnapshot() {
     69     return SkImage::NewTexture(fDevice->accessBitmap(false));
     70 }
     71 
     72 void SkSurface_Gpu::onDraw(SkCanvas* canvas, SkScalar x, SkScalar y,
     73                               const SkPaint* paint) {
     74     canvas->drawBitmap(fDevice->accessBitmap(false), x, y, paint);
     75 }
     76 
     77 // Create a new SkGpuDevice and, if necessary, copy the contents of the old
     78 // device into it. Note that this flushes the SkGpuDevice but
     79 // doesn't force an OpenGL flush.
     80 void SkSurface_Gpu::onCopyOnWrite(ContentChangeMode mode) {
     81     GrRenderTarget* rt = fDevice->accessRenderTarget();
     82     // are we sharing our render target with the image?
     83     SkASSERT(this->getCachedImage());
     84     if (rt->asTexture() == SkTextureImageGetTexture(this->getCachedImage())) {
     85         // We call createCompatibleDevice because it uses the texture cache. This isn't
     86         // necessarily correct (http://skbug.com/2252), but never using the cache causes
     87         // a Chromium regression. (http://crbug.com/344020)
     88         SkGpuDevice* newDevice = static_cast<SkGpuDevice*>(
     89             fDevice->createCompatibleDevice(fDevice->imageInfo()));
     90         SkAutoTUnref<SkGpuDevice> aurd(newDevice);
     91         if (kRetain_ContentChangeMode == mode) {
     92             fDevice->context()->copyTexture(rt->asTexture(), newDevice->accessRenderTarget());
     93         }
     94         SkASSERT(this->getCachedCanvas());
     95         SkASSERT(this->getCachedCanvas()->getDevice() == fDevice);
     96 
     97         this->getCachedCanvas()->setRootDevice(newDevice);
     98         SkRefCnt_SafeAssign(fDevice, newDevice);
     99     } else if (kDiscard_ContentChangeMode == mode) {
    100         this->SkSurface_Gpu::onDiscard();
    101     }
    102 }
    103 
    104 void SkSurface_Gpu::onDiscard() {
    105     fDevice->accessRenderTarget()->discard();
    106 }
    107 
    108 ///////////////////////////////////////////////////////////////////////////////
    109 
    110 SkSurface* SkSurface::NewRenderTargetDirect(GrRenderTarget* target, const SkSurfaceProps* props) {
    111     if (NULL == target) {
    112         return NULL;
    113     }
    114     return SkNEW_ARGS(SkSurface_Gpu, (target, false, props, false));
    115 }
    116 
    117 SkSurface* SkSurface::NewRenderTarget(GrContext* ctx, const SkImageInfo& info, int sampleCount,
    118                                       const SkSurfaceProps* props) {
    119     if (NULL == ctx) {
    120         return NULL;
    121     }
    122 
    123     GrTextureDesc desc;
    124     desc.fFlags = kRenderTarget_GrTextureFlagBit | kCheckAllocation_GrTextureFlagBit;
    125     desc.fWidth = info.width();
    126     desc.fHeight = info.height();
    127     desc.fConfig = SkImageInfo2GrPixelConfig(info);
    128     desc.fSampleCnt = sampleCount;
    129 
    130     SkAutoTUnref<GrTexture> tex(ctx->createUncachedTexture(desc, NULL, 0));
    131     if (NULL == tex) {
    132         return NULL;
    133     }
    134 
    135     return SkNEW_ARGS(SkSurface_Gpu, (tex->asRenderTarget(), false, props, true));
    136 }
    137 
    138 SkSurface* SkSurface::NewScratchRenderTarget(GrContext* ctx, const SkImageInfo& info,
    139                                              int sampleCount, const SkSurfaceProps* props) {
    140     if (NULL == ctx) {
    141         return NULL;
    142     }
    143 
    144     GrTextureDesc desc;
    145     desc.fFlags = kRenderTarget_GrTextureFlagBit | kCheckAllocation_GrTextureFlagBit;
    146     desc.fWidth = info.width();
    147     desc.fHeight = info.height();
    148     desc.fConfig = SkImageInfo2GrPixelConfig(info);
    149     desc.fSampleCnt = sampleCount;
    150 
    151     SkAutoTUnref<GrTexture> tex(ctx->lockAndRefScratchTexture(desc, GrContext::kExact_ScratchTexMatch));
    152 
    153     if (NULL == tex) {
    154         return NULL;
    155     }
    156 
    157     return SkNEW_ARGS(SkSurface_Gpu, (tex->asRenderTarget(), true, props, true));
    158 }
    159