blob: cb85708bf552f1cbf0a87384000c629fe3645865 [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
mtklein59c12e32016-05-02 07:19:41 -07008#include "SkAtomics.h"
reed@google.com9ea5a3b2012-07-30 21:03:46 +00009#include "SkSurface_Base.h"
reed@google.com889b09e2012-07-27 21:10:42 +000010#include "SkImagePriv.h"
11#include "SkCanvas.h"
12
reed4a8126e2014-09-22 07:29:03 -070013#include "SkFontLCDConfig.h"
14static SkPixelGeometry compute_default_geometry() {
15 SkFontLCDConfig::LCDOrder order = SkFontLCDConfig::GetSubpixelOrder();
16 if (SkFontLCDConfig::kNONE_LCDOrder == order) {
17 return kUnknown_SkPixelGeometry;
18 } else {
19 // Bit0 is RGB(0), BGR(1)
20 // Bit1 is H(0), V(1)
21 const SkPixelGeometry gGeo[] = {
22 kRGB_H_SkPixelGeometry,
23 kBGR_H_SkPixelGeometry,
24 kRGB_V_SkPixelGeometry,
25 kBGR_V_SkPixelGeometry,
26 };
27 int index = 0;
28 if (SkFontLCDConfig::kBGR_LCDOrder == order) {
29 index |= 1;
30 }
31 if (SkFontLCDConfig::kVertical_LCDOrientation == SkFontLCDConfig::GetSubpixelOrientation()){
32 index |= 2;
33 }
34 return gGeo[index];
35 }
36}
37
38SkSurfaceProps::SkSurfaceProps() : fFlags(0), fPixelGeometry(kUnknown_SkPixelGeometry) {}
39
40SkSurfaceProps::SkSurfaceProps(InitType) : fFlags(0), fPixelGeometry(compute_default_geometry()) {}
41
42SkSurfaceProps::SkSurfaceProps(uint32_t flags, InitType)
43 : fFlags(flags)
44 , fPixelGeometry(compute_default_geometry())
45{}
46
47SkSurfaceProps::SkSurfaceProps(uint32_t flags, SkPixelGeometry pg)
48 : fFlags(flags), fPixelGeometry(pg)
49{}
50
reed4af267b2014-11-21 08:46:37 -080051SkSurfaceProps::SkSurfaceProps(const SkSurfaceProps& other)
52 : fFlags(other.fFlags)
53 , fPixelGeometry(other.fPixelGeometry)
54{}
55
reed@google.com889b09e2012-07-27 21:10:42 +000056///////////////////////////////////////////////////////////////////////////////
57
reed4a8126e2014-09-22 07:29:03 -070058SkSurface_Base::SkSurface_Base(int width, int height, const SkSurfaceProps* props)
59 : INHERITED(width, height, props)
60{
halcanary96fcdcc2015-08-27 07:41:13 -070061 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 fCachedImage = nullptr;
reed@google.com1360c522014-01-08 21:25:26 +000068}
69
reed@google.com9ea5a3b2012-07-30 21:03:46 +000070SkSurface_Base::~SkSurface_Base() {
reed@google.com97af1a62012-08-28 12:19:02 +000071 // in case the canvas outsurvives us, we null the callback
72 if (fCachedCanvas) {
halcanary96fcdcc2015-08-27 07:41:13 -070073 fCachedCanvas->setSurfaceBase(nullptr);
reed@google.com97af1a62012-08-28 12:19:02 +000074 }
75
76 SkSafeUnref(fCachedImage);
reed@google.com9ea5a3b2012-07-30 21:03:46 +000077}
reed@google.com889b09e2012-07-27 21:10:42 +000078
reed4a8126e2014-09-22 07:29:03 -070079void SkSurface_Base::onDraw(SkCanvas* canvas, SkScalar x, SkScalar y, const SkPaint* paint) {
reed9ce9d672016-03-17 10:51:11 -070080 auto image = this->makeImageSnapshot(SkBudgeted::kYes);
reed@google.com889b09e2012-07-27 21:10:42 +000081 if (image) {
piotaixrb5fae932014-09-24 13:03:30 -070082 canvas->drawImage(image, x, y, paint);
reed@google.com889b09e2012-07-27 21:10:42 +000083 }
84}
85
reedc83a2972015-07-16 07:40:45 -070086bool SkSurface_Base::outstandingImageSnapshot() const {
87 return fCachedImage && !fCachedImage->unique();
88}
89
commit-bot@chromium.orgc4c98702013-04-22 14:28:01 +000090void SkSurface_Base::aboutToDraw(ContentChangeMode mode) {
reed@google.com97af1a62012-08-28 12:19:02 +000091 this->dirtyGenerationID();
92
commit-bot@chromium.org28361fa2014-03-28 16:08:05 +000093 SkASSERT(!fCachedCanvas || fCachedCanvas->getSurfaceBase() == this);
reed@google.com97af1a62012-08-28 12:19:02 +000094
bsalomon49f085d2014-09-05 13:34:00 -070095 if (fCachedImage) {
reed@google.com97af1a62012-08-28 12:19:02 +000096 // the surface may need to fork its backend, if its sharing it with
97 // the cached image. Note: we only call if there is an outstanding owner
98 // on the image (besides us).
reed26e0e582015-07-29 11:44:52 -070099 bool unique = fCachedImage->unique();
100 if (!unique) {
commit-bot@chromium.orgc4c98702013-04-22 14:28:01 +0000101 this->onCopyOnWrite(mode);
reed@google.com97af1a62012-08-28 12:19:02 +0000102 }
103
104 // regardless of copy-on-write, we must drop our cached image now, so
105 // that the next request will get our new contents.
106 fCachedImage->unref();
halcanary96fcdcc2015-08-27 07:41:13 -0700107 fCachedImage = nullptr;
reed26e0e582015-07-29 11:44:52 -0700108
109 if (unique) {
110 // Our content isn't held by any image now, so we can consider that content mutable.
111 // Raster surfaces need to be told it's safe to consider its pixels mutable again.
112 // We make this call after the ->unref() so the subclass can assert there are no images.
113 this->onRestoreBackingMutability();
114 }
commit-bot@chromium.org28361fa2014-03-28 16:08:05 +0000115 } else if (kDiscard_ContentChangeMode == mode) {
116 this->onDiscard();
reed@google.com97af1a62012-08-28 12:19:02 +0000117 }
118}
119
120uint32_t SkSurface_Base::newGenerationID() {
commit-bot@chromium.org28361fa2014-03-28 16:08:05 +0000121 SkASSERT(!fCachedCanvas || fCachedCanvas->getSurfaceBase() == this);
reed@google.com97af1a62012-08-28 12:19:02 +0000122 static int32_t gID;
123 return sk_atomic_inc(&gID) + 1;
124}
125
reed@google.com889b09e2012-07-27 21:10:42 +0000126static SkSurface_Base* asSB(SkSurface* surface) {
127 return static_cast<SkSurface_Base*>(surface);
128}
129
130///////////////////////////////////////////////////////////////////////////////
131
reed4a8126e2014-09-22 07:29:03 -0700132SkSurface::SkSurface(int width, int height, const SkSurfaceProps* props)
133 : fProps(SkSurfacePropsCopyOrDefault(props)), fWidth(width), fHeight(height)
134{
reedb2497c22014-12-31 12:31:43 -0800135 SkASSERT(fWidth > 0);
136 SkASSERT(fHeight > 0);
reed@google.com1360c522014-01-08 21:25:26 +0000137 fGenerationID = 0;
138}
139
reed4a8126e2014-09-22 07:29:03 -0700140SkSurface::SkSurface(const SkImageInfo& info, const SkSurfaceProps* props)
141 : fProps(SkSurfacePropsCopyOrDefault(props)), fWidth(info.width()), fHeight(info.height())
142{
reedb2497c22014-12-31 12:31:43 -0800143 SkASSERT(fWidth > 0);
144 SkASSERT(fHeight > 0);
reed@google.com889b09e2012-07-27 21:10:42 +0000145 fGenerationID = 0;
146}
147
reed@google.com97af1a62012-08-28 12:19:02 +0000148uint32_t SkSurface::generationID() {
149 if (0 == fGenerationID) {
150 fGenerationID = asSB(this)->newGenerationID();
151 }
152 return fGenerationID;
153}
154
commit-bot@chromium.orgc4c98702013-04-22 14:28:01 +0000155void SkSurface::notifyContentWillChange(ContentChangeMode mode) {
156 asSB(this)->aboutToDraw(mode);
reed@google.com97af1a62012-08-28 12:19:02 +0000157}
158
reed@google.com9ea5a3b2012-07-30 21:03:46 +0000159SkCanvas* SkSurface::getCanvas() {
160 return asSB(this)->getCachedCanvas();
reed@google.com889b09e2012-07-27 21:10:42 +0000161}
162
reed9ce9d672016-03-17 10:51:11 -0700163sk_sp<SkImage> SkSurface::makeImageSnapshot(SkBudgeted budgeted) {
Mike Reed85ff8482016-12-29 09:36:20 -0500164 return asSB(this)->refCachedImage(budgeted);
reed@google.com889b09e2012-07-27 21:10:42 +0000165}
166
reede8f30622016-03-23 18:59:25 -0700167sk_sp<SkSurface> SkSurface::makeSurface(const SkImageInfo& info) {
mike@reedtribe.orgb9476252012-11-15 02:37:45 +0000168 return asSB(this)->onNewSurface(info);
reed@google.com889b09e2012-07-27 21:10:42 +0000169}
170
171void SkSurface::draw(SkCanvas* canvas, SkScalar x, SkScalar y,
172 const SkPaint* paint) {
173 return asSB(this)->onDraw(canvas, x, y, paint);
174}
commit-bot@chromium.orgc3bd8af2014-02-13 17:14:46 +0000175
reed6ceeebd2016-03-09 14:26:26 -0800176bool SkSurface::peekPixels(SkPixmap* pmap) {
177 return this->getCanvas()->peekPixels(pmap);
commit-bot@chromium.orgc3bd8af2014-02-13 17:14:46 +0000178}
reed4a8126e2014-09-22 07:29:03 -0700179
reed7543aa22014-12-09 14:39:44 -0800180bool SkSurface::readPixels(const SkImageInfo& dstInfo, void* dstPixels, size_t dstRowBytes,
181 int srcX, int srcY) {
182 return this->getCanvas()->readPixels(dstInfo, dstPixels, dstRowBytes, srcX, srcY);
183}
184
joshualitt81793412015-07-08 12:54:04 -0700185GrBackendObject SkSurface::getTextureHandle(BackendHandleAccess access) {
reedfa5e68e2015-06-29 07:37:01 -0700186 return asSB(this)->onGetTextureHandle(access);
187}
188
joshualitt81793412015-07-08 12:54:04 -0700189bool SkSurface::getRenderTargetHandle(GrBackendObject* obj, BackendHandleAccess access) {
190 return asSB(this)->onGetRenderTargetHandle(obj, access);
191}
192
ericrkf7b8b8a2016-02-24 14:49:51 -0800193void SkSurface::prepareForExternalIO() {
194 asSB(this)->onPrepareForExternalIO();
195}
196
reed4a8126e2014-09-22 07:29:03 -0700197//////////////////////////////////////////////////////////////////////////////////////
reed4a8126e2014-09-22 07:29:03 -0700198
199#if !SK_SUPPORT_GPU
200
robertphillips7e922762016-07-26 11:38:17 -0700201sk_sp<SkSurface> SkSurface::MakeRenderTarget(GrContext*, SkBudgeted, const SkImageInfo&,
202 int, GrSurfaceOrigin, const SkSurfaceProps*) {
halcanary96fcdcc2015-08-27 07:41:13 -0700203 return nullptr;
reed4a8126e2014-09-22 07:29:03 -0700204}
205
reede8f30622016-03-23 18:59:25 -0700206sk_sp<SkSurface> SkSurface::MakeFromBackendTexture(GrContext*, const GrBackendTextureDesc&,
brianosmandfe4f2e2016-07-21 13:28:36 -0700207 sk_sp<SkColorSpace>, const SkSurfaceProps*) {
halcanary96fcdcc2015-08-27 07:41:13 -0700208 return nullptr;
bsalomone4579ad2015-04-08 08:38:40 -0700209}
reed4a8126e2014-09-22 07:29:03 -0700210
reede8f30622016-03-23 18:59:25 -0700211sk_sp<SkSurface> SkSurface::MakeFromBackendRenderTarget(GrContext*,
212 const GrBackendRenderTargetDesc&,
brianosmandfe4f2e2016-07-21 13:28:36 -0700213 sk_sp<SkColorSpace>,
reede8f30622016-03-23 18:59:25 -0700214 const SkSurfaceProps*) {
halcanary96fcdcc2015-08-27 07:41:13 -0700215 return nullptr;
bsalomond3e259a2015-06-30 12:04:40 -0700216}
217
reede8f30622016-03-23 18:59:25 -0700218sk_sp<SkSurface> MakeFromBackendTextureAsRenderTarget(GrContext*, const GrBackendTextureDesc&,
brianosmandfe4f2e2016-07-21 13:28:36 -0700219 sk_sp<SkColorSpace>, const SkSurfaceProps*) {
ericrkf7b8b8a2016-02-24 14:49:51 -0800220 return nullptr;
221}
222
reed4a8126e2014-09-22 07:29:03 -0700223#endif