michael@0: /* michael@0: * Copyright 2012 Google Inc. michael@0: * michael@0: * Use of this source code is governed by a BSD-style license that can be michael@0: * found in the LICENSE file. michael@0: */ michael@0: michael@0: #include "SkSurface_Base.h" michael@0: #include "SkImagePriv.h" michael@0: #include "SkCanvas.h" michael@0: #include "SkGpuDevice.h" michael@0: michael@0: class SkSurface_Gpu : public SkSurface_Base { michael@0: public: michael@0: SK_DECLARE_INST_COUNT(SkSurface_Gpu) michael@0: michael@0: SkSurface_Gpu(GrRenderTarget*); michael@0: virtual ~SkSurface_Gpu(); michael@0: michael@0: virtual SkCanvas* onNewCanvas() SK_OVERRIDE; michael@0: virtual SkSurface* onNewSurface(const SkImageInfo&) SK_OVERRIDE; michael@0: virtual SkImage* onNewImageSnapshot() SK_OVERRIDE; michael@0: virtual void onDraw(SkCanvas*, SkScalar x, SkScalar y, michael@0: const SkPaint*) SK_OVERRIDE; michael@0: virtual void onCopyOnWrite(ContentChangeMode) SK_OVERRIDE; michael@0: michael@0: private: michael@0: SkGpuDevice* fDevice; michael@0: michael@0: typedef SkSurface_Base INHERITED; michael@0: }; michael@0: michael@0: /////////////////////////////////////////////////////////////////////////////// michael@0: michael@0: SkSurface_Gpu::SkSurface_Gpu(GrRenderTarget* renderTarget) michael@0: : INHERITED(renderTarget->width(), renderTarget->height()) { michael@0: fDevice = SkNEW_ARGS(SkGpuDevice, (renderTarget->getContext(), renderTarget)); michael@0: michael@0: if (kRGB_565_GrPixelConfig != renderTarget->config()) { michael@0: fDevice->clear(0x0); michael@0: } michael@0: } michael@0: michael@0: SkSurface_Gpu::~SkSurface_Gpu() { michael@0: SkSafeUnref(fDevice); michael@0: } michael@0: michael@0: SkCanvas* SkSurface_Gpu::onNewCanvas() { michael@0: return SkNEW_ARGS(SkCanvas, (fDevice)); michael@0: } michael@0: michael@0: SkSurface* SkSurface_Gpu::onNewSurface(const SkImageInfo& info) { michael@0: GrRenderTarget* rt = fDevice->accessRenderTarget(); michael@0: int sampleCount = rt->numSamples(); michael@0: return SkSurface::NewRenderTarget(fDevice->context(), info, sampleCount); michael@0: } michael@0: michael@0: SkImage* SkSurface_Gpu::onNewImageSnapshot() { michael@0: return SkImage::NewTexture(fDevice->accessBitmap(false)); michael@0: } michael@0: michael@0: void SkSurface_Gpu::onDraw(SkCanvas* canvas, SkScalar x, SkScalar y, michael@0: const SkPaint* paint) { michael@0: canvas->drawBitmap(fDevice->accessBitmap(false), x, y, paint); michael@0: } michael@0: michael@0: // Create a new SkGpuDevice and, if necessary, copy the contents of the old michael@0: // device into it. Note that this flushes the SkGpuDevice but michael@0: // doesn't force an OpenGL flush. michael@0: void SkSurface_Gpu::onCopyOnWrite(ContentChangeMode mode) { michael@0: GrRenderTarget* rt = fDevice->accessRenderTarget(); michael@0: // are we sharing our render target with the image? michael@0: SkASSERT(NULL != this->getCachedImage()); michael@0: if (rt->asTexture() == SkTextureImageGetTexture(this->getCachedImage())) { michael@0: // We call createCompatibleDevice because it uses the texture cache. This isn't michael@0: // necessarily correct (http://skbug.com/2252), but never using the cache causes michael@0: // a Chromium regression. (http://crbug.com/344020) michael@0: SkGpuDevice* newDevice = static_cast( michael@0: fDevice->createCompatibleDevice(fDevice->imageInfo())); michael@0: SkAutoTUnref aurd(newDevice); michael@0: if (kRetain_ContentChangeMode == mode) { michael@0: fDevice->context()->copyTexture(rt->asTexture(), newDevice->accessRenderTarget()); michael@0: } michael@0: SkASSERT(NULL != this->getCachedCanvas()); michael@0: SkASSERT(this->getCachedCanvas()->getDevice() == fDevice); michael@0: michael@0: this->getCachedCanvas()->setRootDevice(newDevice); michael@0: SkRefCnt_SafeAssign(fDevice, newDevice); michael@0: } michael@0: } michael@0: michael@0: /////////////////////////////////////////////////////////////////////////////// michael@0: michael@0: SkSurface* SkSurface::NewRenderTargetDirect(GrRenderTarget* target) { michael@0: if (NULL == target) { michael@0: return NULL; michael@0: } michael@0: return SkNEW_ARGS(SkSurface_Gpu, (target)); michael@0: } michael@0: michael@0: SkSurface* SkSurface::NewRenderTarget(GrContext* ctx, const SkImageInfo& info, int sampleCount) { michael@0: if (NULL == ctx) { michael@0: return NULL; michael@0: } michael@0: michael@0: SkBitmap::Config config = SkImageInfoToBitmapConfig(info); michael@0: michael@0: GrTextureDesc desc; michael@0: desc.fFlags = kRenderTarget_GrTextureFlagBit | kCheckAllocation_GrTextureFlagBit; michael@0: desc.fWidth = info.fWidth; michael@0: desc.fHeight = info.fHeight; michael@0: desc.fConfig = SkBitmapConfig2GrPixelConfig(config); michael@0: desc.fSampleCnt = sampleCount; michael@0: michael@0: SkAutoTUnref tex(ctx->createUncachedTexture(desc, NULL, 0)); michael@0: if (NULL == tex) { michael@0: return NULL; michael@0: } michael@0: michael@0: return SkNEW_ARGS(SkSurface_Gpu, (tex->asRenderTarget())); michael@0: }