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: michael@0: /////////////////////////////////////////////////////////////////////////////// michael@0: michael@0: SkSurface_Base::SkSurface_Base(int width, int height) : INHERITED(width, height) { michael@0: fCachedCanvas = NULL; michael@0: fCachedImage = NULL; michael@0: } michael@0: michael@0: SkSurface_Base::SkSurface_Base(const SkImageInfo& info) : INHERITED(info) { michael@0: fCachedCanvas = NULL; michael@0: fCachedImage = NULL; michael@0: } michael@0: michael@0: SkSurface_Base::~SkSurface_Base() { michael@0: // in case the canvas outsurvives us, we null the callback michael@0: if (fCachedCanvas) { michael@0: fCachedCanvas->setSurfaceBase(NULL); michael@0: } michael@0: michael@0: SkSafeUnref(fCachedImage); michael@0: SkSafeUnref(fCachedCanvas); michael@0: } michael@0: michael@0: void SkSurface_Base::onDraw(SkCanvas* canvas, SkScalar x, SkScalar y, michael@0: const SkPaint* paint) { michael@0: SkImage* image = this->newImageSnapshot(); michael@0: if (image) { michael@0: image->draw(canvas, x, y, paint); michael@0: image->unref(); michael@0: } michael@0: } michael@0: michael@0: void SkSurface_Base::aboutToDraw(ContentChangeMode mode) { michael@0: this->dirtyGenerationID(); michael@0: michael@0: if (NULL != fCachedCanvas) { michael@0: SkASSERT(fCachedCanvas->getSurfaceBase() == this || \ michael@0: NULL == fCachedCanvas->getSurfaceBase()); michael@0: fCachedCanvas->setSurfaceBase(NULL); michael@0: } michael@0: michael@0: if (NULL != fCachedImage) { michael@0: // the surface may need to fork its backend, if its sharing it with michael@0: // the cached image. Note: we only call if there is an outstanding owner michael@0: // on the image (besides us). michael@0: if (!fCachedImage->unique()) { michael@0: this->onCopyOnWrite(mode); michael@0: } michael@0: michael@0: // regardless of copy-on-write, we must drop our cached image now, so michael@0: // that the next request will get our new contents. michael@0: fCachedImage->unref(); michael@0: fCachedImage = NULL; michael@0: } michael@0: } michael@0: michael@0: uint32_t SkSurface_Base::newGenerationID() { michael@0: this->installIntoCanvasForDirtyNotification(); michael@0: michael@0: static int32_t gID; michael@0: return sk_atomic_inc(&gID) + 1; michael@0: } michael@0: michael@0: static SkSurface_Base* asSB(SkSurface* surface) { michael@0: return static_cast(surface); michael@0: } michael@0: michael@0: /////////////////////////////////////////////////////////////////////////////// michael@0: michael@0: SkSurface::SkSurface(int width, int height) : fWidth(width), fHeight(height) { michael@0: SkASSERT(fWidth >= 0); michael@0: SkASSERT(fHeight >= 0); michael@0: fGenerationID = 0; michael@0: } michael@0: michael@0: SkSurface::SkSurface(const SkImageInfo& info) michael@0: : fWidth(info.fWidth) michael@0: , fHeight(info.fHeight) michael@0: { michael@0: SkASSERT(fWidth >= 0); michael@0: SkASSERT(fHeight >= 0); michael@0: fGenerationID = 0; michael@0: } michael@0: michael@0: uint32_t SkSurface::generationID() { michael@0: if (0 == fGenerationID) { michael@0: fGenerationID = asSB(this)->newGenerationID(); michael@0: } michael@0: return fGenerationID; michael@0: } michael@0: michael@0: void SkSurface::notifyContentWillChange(ContentChangeMode mode) { michael@0: asSB(this)->aboutToDraw(mode); michael@0: } michael@0: michael@0: SkCanvas* SkSurface::getCanvas() { michael@0: return asSB(this)->getCachedCanvas(); michael@0: } michael@0: michael@0: SkImage* SkSurface::newImageSnapshot() { michael@0: SkImage* image = asSB(this)->getCachedImage(); michael@0: SkSafeRef(image); // the caller will call unref() to balance this michael@0: return image; michael@0: } michael@0: michael@0: SkSurface* SkSurface::newSurface(const SkImageInfo& info) { michael@0: return asSB(this)->onNewSurface(info); michael@0: } michael@0: michael@0: void SkSurface::draw(SkCanvas* canvas, SkScalar x, SkScalar y, michael@0: const SkPaint* paint) { michael@0: return asSB(this)->onDraw(canvas, x, y, paint); michael@0: } michael@0: michael@0: const void* SkSurface::peekPixels(SkImageInfo* info, size_t* rowBytes) { michael@0: return this->getCanvas()->peekPixels(info, rowBytes); michael@0: }