blob: d6f69806ee8a365f0ab2112108b185930591a646 [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
reed4a8126e2014-09-22 07:29:03 -070012#include "SkFontLCDConfig.h"
13static SkPixelGeometry compute_default_geometry() {
14 SkFontLCDConfig::LCDOrder order = SkFontLCDConfig::GetSubpixelOrder();
15 if (SkFontLCDConfig::kNONE_LCDOrder == order) {
16 return kUnknown_SkPixelGeometry;
17 } else {
18 // Bit0 is RGB(0), BGR(1)
19 // Bit1 is H(0), V(1)
20 const SkPixelGeometry gGeo[] = {
21 kRGB_H_SkPixelGeometry,
22 kBGR_H_SkPixelGeometry,
23 kRGB_V_SkPixelGeometry,
24 kBGR_V_SkPixelGeometry,
25 };
26 int index = 0;
27 if (SkFontLCDConfig::kBGR_LCDOrder == order) {
28 index |= 1;
29 }
30 if (SkFontLCDConfig::kVertical_LCDOrientation == SkFontLCDConfig::GetSubpixelOrientation()){
31 index |= 2;
32 }
33 return gGeo[index];
34 }
35}
36
37SkSurfaceProps::SkSurfaceProps() : fFlags(0), fPixelGeometry(kUnknown_SkPixelGeometry) {}
38
39SkSurfaceProps::SkSurfaceProps(InitType) : fFlags(0), fPixelGeometry(compute_default_geometry()) {}
40
41SkSurfaceProps::SkSurfaceProps(uint32_t flags, InitType)
42 : fFlags(flags)
43 , fPixelGeometry(compute_default_geometry())
44{}
45
46SkSurfaceProps::SkSurfaceProps(uint32_t flags, SkPixelGeometry pg)
47 : fFlags(flags), fPixelGeometry(pg)
48{}
49
reed4af267b2014-11-21 08:46:37 -080050SkSurfaceProps::SkSurfaceProps(const SkSurfaceProps& other)
51 : fFlags(other.fFlags)
52 , fPixelGeometry(other.fPixelGeometry)
53{}
54
reed@google.com889b09e2012-07-27 21:10:42 +000055///////////////////////////////////////////////////////////////////////////////
56
reed4a8126e2014-09-22 07:29:03 -070057SkSurface_Base::SkSurface_Base(int width, int height, const SkSurfaceProps* props)
58 : INHERITED(width, height, props)
59{
halcanary96fcdcc2015-08-27 07:41:13 -070060 fCachedCanvas = nullptr;
61 fCachedImage = nullptr;
reed@google.com9ea5a3b2012-07-30 21:03:46 +000062}
reed@google.com889b09e2012-07-27 21:10:42 +000063
reed4a8126e2014-09-22 07:29:03 -070064SkSurface_Base::SkSurface_Base(const SkImageInfo& info, const SkSurfaceProps* props)
65 : INHERITED(info, props)
66{
halcanary96fcdcc2015-08-27 07:41:13 -070067 fCachedCanvas = nullptr;
68 fCachedImage = nullptr;
reed@google.com1360c522014-01-08 21:25:26 +000069}
70
reed@google.com9ea5a3b2012-07-30 21:03:46 +000071SkSurface_Base::~SkSurface_Base() {
reed@google.com97af1a62012-08-28 12:19:02 +000072 // in case the canvas outsurvives us, we null the callback
73 if (fCachedCanvas) {
halcanary96fcdcc2015-08-27 07:41:13 -070074 fCachedCanvas->setSurfaceBase(nullptr);
reed@google.com97af1a62012-08-28 12:19:02 +000075 }
76
77 SkSafeUnref(fCachedImage);
reed@google.com9ea5a3b2012-07-30 21:03:46 +000078 SkSafeUnref(fCachedCanvas);
79}
reed@google.com889b09e2012-07-27 21:10:42 +000080
reed4a8126e2014-09-22 07:29:03 -070081void SkSurface_Base::onDraw(SkCanvas* canvas, SkScalar x, SkScalar y, const SkPaint* paint) {
reed9ce9d672016-03-17 10:51:11 -070082 auto image = this->makeImageSnapshot(SkBudgeted::kYes);
reed@google.com889b09e2012-07-27 21:10:42 +000083 if (image) {
piotaixrb5fae932014-09-24 13:03:30 -070084 canvas->drawImage(image, x, y, paint);
reed@google.com889b09e2012-07-27 21:10:42 +000085 }
86}
87
reedc83a2972015-07-16 07:40:45 -070088bool SkSurface_Base::outstandingImageSnapshot() const {
89 return fCachedImage && !fCachedImage->unique();
90}
91
commit-bot@chromium.orgc4c98702013-04-22 14:28:01 +000092void SkSurface_Base::aboutToDraw(ContentChangeMode mode) {
reed@google.com97af1a62012-08-28 12:19:02 +000093 this->dirtyGenerationID();
94
commit-bot@chromium.org28361fa2014-03-28 16:08:05 +000095 SkASSERT(!fCachedCanvas || fCachedCanvas->getSurfaceBase() == this);
reed@google.com97af1a62012-08-28 12:19:02 +000096
bsalomon49f085d2014-09-05 13:34:00 -070097 if (fCachedImage) {
reed@google.com97af1a62012-08-28 12:19:02 +000098 // the surface may need to fork its backend, if its sharing it with
99 // the cached image. Note: we only call if there is an outstanding owner
100 // on the image (besides us).
reed26e0e582015-07-29 11:44:52 -0700101 bool unique = fCachedImage->unique();
102 if (!unique) {
commit-bot@chromium.orgc4c98702013-04-22 14:28:01 +0000103 this->onCopyOnWrite(mode);
reed@google.com97af1a62012-08-28 12:19:02 +0000104 }
105
106 // regardless of copy-on-write, we must drop our cached image now, so
107 // that the next request will get our new contents.
108 fCachedImage->unref();
halcanary96fcdcc2015-08-27 07:41:13 -0700109 fCachedImage = nullptr;
reed26e0e582015-07-29 11:44:52 -0700110
111 if (unique) {
112 // Our content isn't held by any image now, so we can consider that content mutable.
113 // Raster surfaces need to be told it's safe to consider its pixels mutable again.
114 // We make this call after the ->unref() so the subclass can assert there are no images.
115 this->onRestoreBackingMutability();
116 }
commit-bot@chromium.org28361fa2014-03-28 16:08:05 +0000117 } else if (kDiscard_ContentChangeMode == mode) {
118 this->onDiscard();
reed@google.com97af1a62012-08-28 12:19:02 +0000119 }
120}
121
122uint32_t SkSurface_Base::newGenerationID() {
commit-bot@chromium.org28361fa2014-03-28 16:08:05 +0000123 SkASSERT(!fCachedCanvas || fCachedCanvas->getSurfaceBase() == this);
reed@google.com97af1a62012-08-28 12:19:02 +0000124 static int32_t gID;
125 return sk_atomic_inc(&gID) + 1;
126}
127
reed@google.com889b09e2012-07-27 21:10:42 +0000128static SkSurface_Base* asSB(SkSurface* surface) {
129 return static_cast<SkSurface_Base*>(surface);
130}
131
132///////////////////////////////////////////////////////////////////////////////
133
reed4a8126e2014-09-22 07:29:03 -0700134SkSurface::SkSurface(int width, int height, const SkSurfaceProps* props)
135 : fProps(SkSurfacePropsCopyOrDefault(props)), fWidth(width), fHeight(height)
136{
reedb2497c22014-12-31 12:31:43 -0800137 SkASSERT(fWidth > 0);
138 SkASSERT(fHeight > 0);
reed@google.com1360c522014-01-08 21:25:26 +0000139 fGenerationID = 0;
140}
141
reed4a8126e2014-09-22 07:29:03 -0700142SkSurface::SkSurface(const SkImageInfo& info, const SkSurfaceProps* props)
143 : fProps(SkSurfacePropsCopyOrDefault(props)), fWidth(info.width()), fHeight(info.height())
144{
reedb2497c22014-12-31 12:31:43 -0800145 SkASSERT(fWidth > 0);
146 SkASSERT(fHeight > 0);
reed@google.com889b09e2012-07-27 21:10:42 +0000147 fGenerationID = 0;
148}
149
reed@google.com97af1a62012-08-28 12:19:02 +0000150uint32_t SkSurface::generationID() {
151 if (0 == fGenerationID) {
152 fGenerationID = asSB(this)->newGenerationID();
153 }
154 return fGenerationID;
155}
156
commit-bot@chromium.orgc4c98702013-04-22 14:28:01 +0000157void SkSurface::notifyContentWillChange(ContentChangeMode mode) {
158 asSB(this)->aboutToDraw(mode);
reed@google.com97af1a62012-08-28 12:19:02 +0000159}
160
reed@google.com9ea5a3b2012-07-30 21:03:46 +0000161SkCanvas* SkSurface::getCanvas() {
162 return asSB(this)->getCachedCanvas();
reed@google.com889b09e2012-07-27 21:10:42 +0000163}
164
reed9ce9d672016-03-17 10:51:11 -0700165sk_sp<SkImage> SkSurface::makeImageSnapshot(SkBudgeted budgeted) {
bsalomonf47b9a32016-02-22 11:02:58 -0800166 // the caller will call unref() to balance this
167 return asSB(this)->refCachedImage(budgeted, kNo_ForceUnique);
168}
169
reed9ce9d672016-03-17 10:51:11 -0700170sk_sp<SkImage> SkSurface::makeImageSnapshot(SkBudgeted budgeted, ForceUnique unique) {
bsalomonf47b9a32016-02-22 11:02:58 -0800171 // the caller will call unref() to balance this
172 return asSB(this)->refCachedImage(budgeted, unique);
reed@google.com889b09e2012-07-27 21:10:42 +0000173}
174
reede8f30622016-03-23 18:59:25 -0700175sk_sp<SkSurface> SkSurface::makeSurface(const SkImageInfo& info) {
mike@reedtribe.orgb9476252012-11-15 02:37:45 +0000176 return asSB(this)->onNewSurface(info);
reed@google.com889b09e2012-07-27 21:10:42 +0000177}
178
179void SkSurface::draw(SkCanvas* canvas, SkScalar x, SkScalar y,
180 const SkPaint* paint) {
181 return asSB(this)->onDraw(canvas, x, y, paint);
182}
commit-bot@chromium.orgc3bd8af2014-02-13 17:14:46 +0000183
reed6ceeebd2016-03-09 14:26:26 -0800184bool SkSurface::peekPixels(SkPixmap* pmap) {
185 return this->getCanvas()->peekPixels(pmap);
commit-bot@chromium.orgc3bd8af2014-02-13 17:14:46 +0000186}
reed4a8126e2014-09-22 07:29:03 -0700187
reed6ceeebd2016-03-09 14:26:26 -0800188#ifdef SK_SUPPORT_LEGACY_PEEKPIXELS_PARMS
189const void* SkSurface::peekPixels(SkImageInfo* info, size_t* rowBytes) {
190 SkPixmap pm;
191 if (this->peekPixels(&pm)) {
192 if (info) {
193 *info = pm.info();
194 }
195 if (rowBytes) {
196 *rowBytes = pm.rowBytes();
197 }
198 return pm.addr();
199 }
200 return nullptr;
201}
202#endif
203
reed7543aa22014-12-09 14:39:44 -0800204bool SkSurface::readPixels(const SkImageInfo& dstInfo, void* dstPixels, size_t dstRowBytes,
205 int srcX, int srcY) {
206 return this->getCanvas()->readPixels(dstInfo, dstPixels, dstRowBytes, srcX, srcY);
207}
208
joshualitt81793412015-07-08 12:54:04 -0700209GrBackendObject SkSurface::getTextureHandle(BackendHandleAccess access) {
reedfa5e68e2015-06-29 07:37:01 -0700210 return asSB(this)->onGetTextureHandle(access);
211}
212
joshualitt81793412015-07-08 12:54:04 -0700213bool SkSurface::getRenderTargetHandle(GrBackendObject* obj, BackendHandleAccess access) {
214 return asSB(this)->onGetRenderTargetHandle(obj, access);
215}
216
ericrkf7b8b8a2016-02-24 14:49:51 -0800217void SkSurface::prepareForExternalIO() {
218 asSB(this)->onPrepareForExternalIO();
219}
220
reed4a8126e2014-09-22 07:29:03 -0700221//////////////////////////////////////////////////////////////////////////////////////
reed4a8126e2014-09-22 07:29:03 -0700222
223#if !SK_SUPPORT_GPU
224
reede8f30622016-03-23 18:59:25 -0700225sk_sp<SkSurface> SkSurface::MakeRenderTargetDirect(GrRenderTarget*, const SkSurfaceProps*) {
halcanary96fcdcc2015-08-27 07:41:13 -0700226 return nullptr;
reed4a8126e2014-09-22 07:29:03 -0700227}
228
reede8f30622016-03-23 18:59:25 -0700229sk_sp<SkSurface> SkSurface::MakeRenderTarget(GrContext*, SkBudgeted, const SkImageInfo&, int,
bsalomon7e68ab72016-04-13 14:29:25 -0700230 const SkSurfaceProps*) {
halcanary96fcdcc2015-08-27 07:41:13 -0700231 return nullptr;
reed4a8126e2014-09-22 07:29:03 -0700232}
233
reede8f30622016-03-23 18:59:25 -0700234sk_sp<SkSurface> SkSurface::MakeFromBackendTexture(GrContext*, const GrBackendTextureDesc&,
235 const SkSurfaceProps*) {
halcanary96fcdcc2015-08-27 07:41:13 -0700236 return nullptr;
bsalomone4579ad2015-04-08 08:38:40 -0700237}
reed4a8126e2014-09-22 07:29:03 -0700238
reede8f30622016-03-23 18:59:25 -0700239sk_sp<SkSurface> SkSurface::MakeFromBackendRenderTarget(GrContext*,
240 const GrBackendRenderTargetDesc&,
241 const SkSurfaceProps*) {
halcanary96fcdcc2015-08-27 07:41:13 -0700242 return nullptr;
bsalomond3e259a2015-06-30 12:04:40 -0700243}
244
reede8f30622016-03-23 18:59:25 -0700245sk_sp<SkSurface> MakeFromBackendTextureAsRenderTarget(GrContext*, const GrBackendTextureDesc&,
246 const SkSurfaceProps*) {
ericrkf7b8b8a2016-02-24 14:49:51 -0800247 return nullptr;
248}
249
reed4a8126e2014-09-22 07:29:03 -0700250#endif