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(GrContext*, const SkImageInfo&, int sampleCount);
     18     SkSurface_Gpu(GrContext*, GrRenderTarget*);
     19     virtual ~SkSurface_Gpu();
     20 
     21     virtual SkCanvas* onNewCanvas() SK_OVERRIDE;
     22     virtual SkSurface* onNewSurface(const SkImageInfo&) SK_OVERRIDE;
     23     virtual SkImage* onNewImageSnapshot() SK_OVERRIDE;
     24     virtual void onDraw(SkCanvas*, SkScalar x, SkScalar y,
     25                         const SkPaint*) SK_OVERRIDE;
     26     virtual void onCopyOnWrite(ContentChangeMode) SK_OVERRIDE;
     27 
     28 private:
     29     SkGpuDevice* fDevice;
     30 
     31     typedef SkSurface_Base INHERITED;
     32 };
     33 
     34 ///////////////////////////////////////////////////////////////////////////////
     35 
     36 SkSurface_Gpu::SkSurface_Gpu(GrContext* ctx, const SkImageInfo& info,
     37                              int sampleCount)
     38         : INHERITED(info.fWidth, info.fHeight) {
     39     SkBitmap::Config config = SkImageInfoToBitmapConfig(info);
     40 
     41     fDevice = SkNEW_ARGS(SkGpuDevice, (ctx, config, info.fWidth, info.fHeight, sampleCount));
     42 
     43     if (!SkAlphaTypeIsOpaque(info.fAlphaType)) {
     44         fDevice->clear(0x0);
     45     }
     46 }
     47 
     48 SkSurface_Gpu::SkSurface_Gpu(GrContext* ctx, GrRenderTarget* renderTarget)
     49         : INHERITED(renderTarget->width(), renderTarget->height()) {
     50     fDevice = SkNEW_ARGS(SkGpuDevice, (ctx, renderTarget));
     51 
     52     if (kRGB_565_GrPixelConfig != renderTarget->config()) {
     53         fDevice->clear(0x0);
     54     }
     55 }
     56 
     57 SkSurface_Gpu::~SkSurface_Gpu() {
     58     SkSafeUnref(fDevice);
     59 }
     60 
     61 SkCanvas* SkSurface_Gpu::onNewCanvas() {
     62     return SkNEW_ARGS(SkCanvas, (fDevice));
     63 }
     64 
     65 SkSurface* SkSurface_Gpu::onNewSurface(const SkImageInfo& info) {
     66     GrRenderTarget* rt = fDevice->accessRenderTarget();
     67     int sampleCount = rt->numSamples();
     68     return SkSurface::NewRenderTarget(fDevice->context(), info, sampleCount);
     69 }
     70 
     71 SkImage* SkSurface_Gpu::onNewImageSnapshot() {
     72     return SkImage::NewTexture(fDevice->accessBitmap(false));
     73 }
     74 
     75 void SkSurface_Gpu::onDraw(SkCanvas* canvas, SkScalar x, SkScalar y,
     76                               const SkPaint* paint) {
     77     canvas->drawBitmap(fDevice->accessBitmap(false), x, y, paint);
     78 }
     79 
     80 // Create a new SkGpuDevice and, if necessary, copy the contents of the old
     81 // device into it. Note that this flushes the SkGpuDevice but
     82 // doesn't force an OpenGL flush.
     83 void SkSurface_Gpu::onCopyOnWrite(ContentChangeMode mode) {
     84     GrRenderTarget* rt = fDevice->accessRenderTarget();
     85     // are we sharing our render target with the image?
     86     SkASSERT(NULL != this->getCachedImage());
     87     if (rt->asTexture() == SkTextureImageGetTexture(this->getCachedImage())) {
     88         SkGpuDevice* newDevice = static_cast<SkGpuDevice*>(
     89             fDevice->createCompatibleDevice(fDevice->config(), fDevice->width(),
     90             fDevice->height(), fDevice->isOpaque()));
     91         SkAutoTUnref<SkGpuDevice> aurd(newDevice);
     92         if (kRetain_ContentChangeMode == mode) {
     93             fDevice->context()->copyTexture(rt->asTexture(),
     94                 reinterpret_cast<GrRenderTarget*>(newDevice->accessRenderTarget()));
     95         }
     96         SkASSERT(NULL != this->getCachedCanvas());
     97         SkASSERT(this->getCachedCanvas()->getDevice() == fDevice);
     98         this->getCachedCanvas()->setDevice(newDevice);
     99         SkRefCnt_SafeAssign(fDevice, newDevice);
    100     }
    101 }
    102 
    103 ///////////////////////////////////////////////////////////////////////////////
    104 
    105 SkSurface* SkSurface::NewRenderTargetDirect(GrContext* ctx,
    106                                             GrRenderTarget* target) {
    107     if (NULL == ctx || NULL == target) {
    108         return NULL;
    109     }
    110 
    111     return SkNEW_ARGS(SkSurface_Gpu, (ctx, target));
    112 }
    113 
    114 SkSurface* SkSurface::NewRenderTarget(GrContext* ctx, const SkImageInfo& info, int sampleCount) {
    115     if (NULL == ctx) {
    116         return NULL;
    117     }
    118 
    119     SkBitmap::Config config = SkImageInfoToBitmapConfig(info);
    120 
    121     GrTextureDesc desc;
    122     desc.fFlags = kRenderTarget_GrTextureFlagBit | kCheckAllocation_GrTextureFlagBit;
    123     desc.fWidth = info.fWidth;
    124     desc.fHeight = info.fHeight;
    125     desc.fConfig = SkBitmapConfig2GrPixelConfig(config);
    126     desc.fSampleCnt = sampleCount;
    127 
    128     SkAutoTUnref<GrTexture> tex(ctx->createUncachedTexture(desc, NULL, 0));
    129     if (NULL == tex) {
    130         return NULL;
    131     }
    132 
    133     return SkNEW_ARGS(SkSurface_Gpu, (ctx, tex->asRenderTarget()));
    134 }
    135