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, TextRenderMode trm);
     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, TextRenderMode trm)
     37         : INHERITED(renderTarget->width(), renderTarget->height()) {
     38     int flags = 0;
     39     flags |= cached ? SkGpuDevice::kCached_Flag : 0;
     40     flags |= (kDistanceField_TextRenderMode == trm) ? SkGpuDevice::kDFFonts_Flag : 0;
     41     fDevice = SkGpuDevice::Create(renderTarget, flags);
     42 
     43     if (kRGB_565_GrPixelConfig != renderTarget->config()) {
     44         fDevice->clear(0x0);
     45     }
     46 }
     47 
     48 SkSurface_Gpu::~SkSurface_Gpu() {
     49     SkSafeUnref(fDevice);
     50 }
     51 
     52 SkCanvas* SkSurface_Gpu::onNewCanvas() {
     53     return SkNEW_ARGS(SkCanvas, (fDevice));
     54 }
     55 
     56 SkSurface* SkSurface_Gpu::onNewSurface(const SkImageInfo& info) {
     57     GrRenderTarget* rt = fDevice->accessRenderTarget();
     58     int sampleCount = rt->numSamples();
     59     return SkSurface::NewRenderTarget(fDevice->context(), info, sampleCount);
     60 }
     61 
     62 SkImage* SkSurface_Gpu::onNewImageSnapshot() {
     63     return SkImage::NewTexture(fDevice->accessBitmap(false));
     64 }
     65 
     66 void SkSurface_Gpu::onDraw(SkCanvas* canvas, SkScalar x, SkScalar y,
     67                               const SkPaint* paint) {
     68     canvas->drawBitmap(fDevice->accessBitmap(false), x, y, paint);
     69 }
     70 
     71 // Create a new SkGpuDevice and, if necessary, copy the contents of the old
     72 // device into it. Note that this flushes the SkGpuDevice but
     73 // doesn't force an OpenGL flush.
     74 void SkSurface_Gpu::onCopyOnWrite(ContentChangeMode mode) {
     75     GrRenderTarget* rt = fDevice->accessRenderTarget();
     76     // are we sharing our render target with the image?
     77     SkASSERT(NULL != this->getCachedImage());
     78     if (rt->asTexture() == SkTextureImageGetTexture(this->getCachedImage())) {
     79         // We call createCompatibleDevice because it uses the texture cache. This isn't
     80         // necessarily correct (http://skbug.com/2252), but never using the cache causes
     81         // a Chromium regression. (http://crbug.com/344020)
     82         SkGpuDevice* newDevice = static_cast<SkGpuDevice*>(
     83             fDevice->createCompatibleDevice(fDevice->imageInfo()));
     84         SkAutoTUnref<SkGpuDevice> aurd(newDevice);
     85         if (kRetain_ContentChangeMode == mode) {
     86             fDevice->context()->copyTexture(rt->asTexture(), newDevice->accessRenderTarget());
     87         }
     88         SkASSERT(NULL != this->getCachedCanvas());
     89         SkASSERT(this->getCachedCanvas()->getDevice() == fDevice);
     90 
     91         this->getCachedCanvas()->setRootDevice(newDevice);
     92         SkRefCnt_SafeAssign(fDevice, newDevice);
     93     } else if (kDiscard_ContentChangeMode == mode) {
     94         this->SkSurface_Gpu::onDiscard();
     95     }
     96 }
     97 
     98 void SkSurface_Gpu::onDiscard() {
     99     fDevice->accessRenderTarget()->discard();
    100 }
    101 
    102 ///////////////////////////////////////////////////////////////////////////////
    103 
    104 SkSurface* SkSurface::NewRenderTargetDirect(GrRenderTarget* target, TextRenderMode trm) {
    105     if (NULL == target) {
    106         return NULL;
    107     }
    108     return SkNEW_ARGS(SkSurface_Gpu, (target, false, trm));
    109 }
    110 
    111 SkSurface* SkSurface::NewRenderTarget(GrContext* ctx, const SkImageInfo& info, int sampleCount,
    112                                       TextRenderMode trm) {
    113     if (NULL == ctx) {
    114         return NULL;
    115     }
    116 
    117     GrTextureDesc desc;
    118     desc.fFlags = kRenderTarget_GrTextureFlagBit | kCheckAllocation_GrTextureFlagBit;
    119     desc.fWidth = info.width();
    120     desc.fHeight = info.height();
    121     desc.fConfig = SkImageInfo2GrPixelConfig(info);
    122     desc.fSampleCnt = sampleCount;
    123 
    124     SkAutoTUnref<GrTexture> tex(ctx->createUncachedTexture(desc, NULL, 0));
    125     if (NULL == tex) {
    126         return NULL;
    127     }
    128 
    129     return SkNEW_ARGS(SkSurface_Gpu, (tex->asRenderTarget(), false, trm));
    130 }
    131 
    132 SkSurface* SkSurface::NewScratchRenderTarget(GrContext* ctx, const SkImageInfo& info,
    133                                              int sampleCount, TextRenderMode trm) {
    134     if (NULL == ctx) {
    135         return NULL;
    136     }
    137 
    138     GrTextureDesc desc;
    139     desc.fFlags = kRenderTarget_GrTextureFlagBit | kCheckAllocation_GrTextureFlagBit;
    140     desc.fWidth = info.width();
    141     desc.fHeight = info.height();
    142     desc.fConfig = SkImageInfo2GrPixelConfig(info);
    143     desc.fSampleCnt = sampleCount;
    144 
    145     SkAutoTUnref<GrTexture> tex(ctx->lockAndRefScratchTexture(desc, GrContext::kExact_ScratchTexMatch));
    146 
    147     if (NULL == tex) {
    148         return NULL;
    149     }
    150 
    151     return SkNEW_ARGS(SkSurface_Gpu, (tex->asRenderTarget(), true, trm));
    152 }
    153