|
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 if (NULL != fCachedCanvas) { |
|
47 SkASSERT(fCachedCanvas->getSurfaceBase() == this || \ |
|
48 NULL == fCachedCanvas->getSurfaceBase()); |
|
49 fCachedCanvas->setSurfaceBase(NULL); |
|
50 } |
|
51 |
|
52 if (NULL != fCachedImage) { |
|
53 // the surface may need to fork its backend, if its sharing it with |
|
54 // the cached image. Note: we only call if there is an outstanding owner |
|
55 // on the image (besides us). |
|
56 if (!fCachedImage->unique()) { |
|
57 this->onCopyOnWrite(mode); |
|
58 } |
|
59 |
|
60 // regardless of copy-on-write, we must drop our cached image now, so |
|
61 // that the next request will get our new contents. |
|
62 fCachedImage->unref(); |
|
63 fCachedImage = NULL; |
|
64 } |
|
65 } |
|
66 |
|
67 uint32_t SkSurface_Base::newGenerationID() { |
|
68 this->installIntoCanvasForDirtyNotification(); |
|
69 |
|
70 static int32_t gID; |
|
71 return sk_atomic_inc(&gID) + 1; |
|
72 } |
|
73 |
|
74 static SkSurface_Base* asSB(SkSurface* surface) { |
|
75 return static_cast<SkSurface_Base*>(surface); |
|
76 } |
|
77 |
|
78 /////////////////////////////////////////////////////////////////////////////// |
|
79 |
|
80 SkSurface::SkSurface(int width, int height) : fWidth(width), fHeight(height) { |
|
81 SkASSERT(fWidth >= 0); |
|
82 SkASSERT(fHeight >= 0); |
|
83 fGenerationID = 0; |
|
84 } |
|
85 |
|
86 SkSurface::SkSurface(const SkImageInfo& info) |
|
87 : fWidth(info.fWidth) |
|
88 , fHeight(info.fHeight) |
|
89 { |
|
90 SkASSERT(fWidth >= 0); |
|
91 SkASSERT(fHeight >= 0); |
|
92 fGenerationID = 0; |
|
93 } |
|
94 |
|
95 uint32_t SkSurface::generationID() { |
|
96 if (0 == fGenerationID) { |
|
97 fGenerationID = asSB(this)->newGenerationID(); |
|
98 } |
|
99 return fGenerationID; |
|
100 } |
|
101 |
|
102 void SkSurface::notifyContentWillChange(ContentChangeMode mode) { |
|
103 asSB(this)->aboutToDraw(mode); |
|
104 } |
|
105 |
|
106 SkCanvas* SkSurface::getCanvas() { |
|
107 return asSB(this)->getCachedCanvas(); |
|
108 } |
|
109 |
|
110 SkImage* SkSurface::newImageSnapshot() { |
|
111 SkImage* image = asSB(this)->getCachedImage(); |
|
112 SkSafeRef(image); // the caller will call unref() to balance this |
|
113 return image; |
|
114 } |
|
115 |
|
116 SkSurface* SkSurface::newSurface(const SkImageInfo& info) { |
|
117 return asSB(this)->onNewSurface(info); |
|
118 } |
|
119 |
|
120 void SkSurface::draw(SkCanvas* canvas, SkScalar x, SkScalar y, |
|
121 const SkPaint* paint) { |
|
122 return asSB(this)->onDraw(canvas, x, y, paint); |
|
123 } |
|
124 |
|
125 const void* SkSurface::peekPixels(SkImageInfo* info, size_t* rowBytes) { |
|
126 return this->getCanvas()->peekPixels(info, rowBytes); |
|
127 } |