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 12 /////////////////////////////////////////////////////////////////////////////// 13 14 SkSurface_Base::SkSurface_Base(int width, int height) : INHERITED(width, height) { 15 fCachedCanvas = NULL; 16 fCachedImage = NULL; 17 } 18 19 SkSurface_Base::SkSurface_Base(const SkImageInfo& info) : INHERITED(info) { 20 fCachedCanvas = NULL; 21 fCachedImage = NULL; 22 } 23 24 SkSurface_Base::~SkSurface_Base() { 25 // in case the canvas outsurvives us, we null the callback 26 if (fCachedCanvas) { 27 fCachedCanvas->setSurfaceBase(NULL); 28 } 29 30 SkSafeUnref(fCachedImage); 31 SkSafeUnref(fCachedCanvas); 32 } 33 34 void SkSurface_Base::onDraw(SkCanvas* canvas, SkScalar x, SkScalar y, 35 const SkPaint* paint) { 36 SkImage* image = this->newImageSnapshot(); 37 if (image) { 38 image->draw(canvas, x, y, paint); 39 image->unref(); 40 } 41 } 42 43 void SkSurface_Base::aboutToDraw(ContentChangeMode mode) { 44 this->dirtyGenerationID(); 45 46 SkASSERT(!fCachedCanvas || fCachedCanvas->getSurfaceBase() == this); 47 48 if (NULL != fCachedImage) { 49 // the surface may need to fork its backend, if its sharing it with 50 // the cached image. Note: we only call if there is an outstanding owner 51 // on the image (besides us). 52 if (!fCachedImage->unique()) { 53 this->onCopyOnWrite(mode); 54 } 55 56 // regardless of copy-on-write, we must drop our cached image now, so 57 // that the next request will get our new contents. 58 fCachedImage->unref(); 59 fCachedImage = NULL; 60 } else if (kDiscard_ContentChangeMode == mode) { 61 this->onDiscard(); 62 } 63 } 64 65 uint32_t SkSurface_Base::newGenerationID() { 66 SkASSERT(!fCachedCanvas || fCachedCanvas->getSurfaceBase() == this); 67 static int32_t gID; 68 return sk_atomic_inc(&gID) + 1; 69 } 70 71 static SkSurface_Base* asSB(SkSurface* surface) { 72 return static_cast<SkSurface_Base*>(surface); 73 } 74 75 /////////////////////////////////////////////////////////////////////////////// 76 77 SkSurface::SkSurface(int width, int height) : fWidth(width), fHeight(height) { 78 SkASSERT(fWidth >= 0); 79 SkASSERT(fHeight >= 0); 80 fGenerationID = 0; 81 } 82 83 SkSurface::SkSurface(const SkImageInfo& info) 84 : fWidth(info.fWidth) 85 , fHeight(info.fHeight) 86 { 87 SkASSERT(fWidth >= 0); 88 SkASSERT(fHeight >= 0); 89 fGenerationID = 0; 90 } 91 92 uint32_t SkSurface::generationID() { 93 if (0 == fGenerationID) { 94 fGenerationID = asSB(this)->newGenerationID(); 95 } 96 return fGenerationID; 97 } 98 99 void SkSurface::notifyContentWillChange(ContentChangeMode mode) { 100 asSB(this)->aboutToDraw(mode); 101 } 102 103 SkCanvas* SkSurface::getCanvas() { 104 return asSB(this)->getCachedCanvas(); 105 } 106 107 SkImage* SkSurface::newImageSnapshot() { 108 SkImage* image = asSB(this)->getCachedImage(); 109 SkSafeRef(image); // the caller will call unref() to balance this 110 return image; 111 } 112 113 SkSurface* SkSurface::newSurface(const SkImageInfo& info) { 114 return asSB(this)->onNewSurface(info); 115 } 116 117 void SkSurface::draw(SkCanvas* canvas, SkScalar x, SkScalar y, 118 const SkPaint* paint) { 119 return asSB(this)->onDraw(canvas, x, y, paint); 120 } 121 122 const void* SkSurface::peekPixels(SkImageInfo* info, size_t* rowBytes) { 123 return this->getCanvas()->peekPixels(info, rowBytes); 124 } 125