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