blob: 7b82a340da19173fbd9fc3273fdc7e66ca58b781 [file] [log] [blame]
reed@google.comc9062042012-07-30 18:06:00 +00001/*
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
reed@google.com9ea5a3b2012-07-30 21:03:46 +00008#include "SkSurface_Base.h"
reed@google.com889b09e2012-07-27 21:10:42 +00009#include "SkImagePriv.h"
10#include "SkCanvas.h"
11
reed@google.com97af1a62012-08-28 12:19:02 +000012//SK_DEFINE_INST_COUNT(SkSurface)
robertphillips@google.coma22e2112012-08-16 14:58:06 +000013
reed@google.com889b09e2012-07-27 21:10:42 +000014///////////////////////////////////////////////////////////////////////////////
15
reed@google.com97af1a62012-08-28 12:19:02 +000016void SkSurface_Base::installIntoCanvasForDirtyNotification() {
17 if (fCachedCanvas) {
18 fCachedCanvas->setSurfaceBase(this);
19 }
20}
21
reed@google.com9ea5a3b2012-07-30 21:03:46 +000022SkSurface_Base::SkSurface_Base(int width, int height) : INHERITED(width, height) {
23 fCachedCanvas = NULL;
reed@google.com97af1a62012-08-28 12:19:02 +000024 fCachedImage = NULL;
reed@google.com9ea5a3b2012-07-30 21:03:46 +000025}
reed@google.com889b09e2012-07-27 21:10:42 +000026
reed@google.com9ea5a3b2012-07-30 21:03:46 +000027SkSurface_Base::~SkSurface_Base() {
reed@google.com97af1a62012-08-28 12:19:02 +000028 // in case the canvas outsurvives us, we null the callback
29 if (fCachedCanvas) {
30 fCachedCanvas->setSurfaceBase(NULL);
31 }
32
33 SkSafeUnref(fCachedImage);
reed@google.com9ea5a3b2012-07-30 21:03:46 +000034 SkSafeUnref(fCachedCanvas);
35}
reed@google.com889b09e2012-07-27 21:10:42 +000036
37void SkSurface_Base::onDraw(SkCanvas* canvas, SkScalar x, SkScalar y,
38 const SkPaint* paint) {
39 SkImage* image = this->newImageShapshot();
40 if (image) {
41 image->draw(canvas, x, y, paint);
42 image->unref();
43 }
44}
45
reed@google.com97af1a62012-08-28 12:19:02 +000046void SkSurface_Base::onCopyOnWrite(SkImage*, SkCanvas*) {}
47
48SkCanvas* SkSurface_Base::getCachedCanvas() {
49 if (NULL == fCachedCanvas) {
50 fCachedCanvas = this->onNewCanvas();
51 this->installIntoCanvasForDirtyNotification();
52 }
53 return fCachedCanvas;
54}
55
56SkImage* SkSurface_Base::getCachedImage() {
57 if (NULL == fCachedImage) {
58 fCachedImage = this->onNewImageShapshot();
59 this->installIntoCanvasForDirtyNotification();
60 }
61 return fCachedImage;
62}
63
64void SkSurface_Base::aboutToDraw(SkCanvas* canvas) {
65 this->dirtyGenerationID();
66
67 if (canvas) {
68 SkASSERT(canvas == fCachedCanvas);
69 SkASSERT(canvas->getSurfaceBase() == this);
70 canvas->setSurfaceBase(NULL);
71 }
72
73 if (fCachedImage) {
74 // the surface may need to fork its backend, if its sharing it with
75 // the cached image. Note: we only call if there is an outstanding owner
76 // on the image (besides us).
77 if (fCachedImage->getRefCnt() > 1) {
78 this->onCopyOnWrite(fCachedImage, canvas);
79 }
80
81 // regardless of copy-on-write, we must drop our cached image now, so
82 // that the next request will get our new contents.
83 fCachedImage->unref();
84 fCachedImage = NULL;
85 }
86}
87
88uint32_t SkSurface_Base::newGenerationID() {
89 this->installIntoCanvasForDirtyNotification();
90
91 static int32_t gID;
92 return sk_atomic_inc(&gID) + 1;
93}
94
reed@google.com889b09e2012-07-27 21:10:42 +000095static SkSurface_Base* asSB(SkSurface* surface) {
96 return static_cast<SkSurface_Base*>(surface);
97}
98
99///////////////////////////////////////////////////////////////////////////////
100
101SkSurface::SkSurface(int width, int height) : fWidth(width), fHeight(height) {
102 SkASSERT(width >= 0);
103 SkASSERT(height >= 0);
104 fGenerationID = 0;
105}
106
reed@google.com97af1a62012-08-28 12:19:02 +0000107uint32_t SkSurface::generationID() {
108 if (0 == fGenerationID) {
109 fGenerationID = asSB(this)->newGenerationID();
110 }
111 return fGenerationID;
112}
113
114void SkSurface::notifyContentChanged() {
115 asSB(this)->aboutToDraw(NULL);
116}
117
reed@google.com9ea5a3b2012-07-30 21:03:46 +0000118SkCanvas* SkSurface::getCanvas() {
119 return asSB(this)->getCachedCanvas();
reed@google.com889b09e2012-07-27 21:10:42 +0000120}
121
reed@google.com97af1a62012-08-28 12:19:02 +0000122SkImage* SkSurface::newImageShapshot() {
123 SkImage* image = asSB(this)->getCachedImage();
124 SkSafeRef(image); // the caller will call unref() to balance this
125 return image;
reed@google.com889b09e2012-07-27 21:10:42 +0000126}
127
reed@google.com97af1a62012-08-28 12:19:02 +0000128SkSurface* SkSurface::newSurface(const SkImage::Info& info, SkColorSpace* cs) {
129 return asSB(this)->onNewSurface(info, cs);
reed@google.com889b09e2012-07-27 21:10:42 +0000130}
131
132void SkSurface::draw(SkCanvas* canvas, SkScalar x, SkScalar y,
133 const SkPaint* paint) {
134 return asSB(this)->onDraw(canvas, x, y, paint);
135}
136