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