blob: 2d0ce7062fc0445bdd86820f57d2a243a55e1a35 [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
reed3716fd02014-09-21 09:39:55 -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
reed@google.com889b09e2012-07-27 21:10:42 +000050///////////////////////////////////////////////////////////////////////////////
51
reed3716fd02014-09-21 09:39:55 -070052SkSurface_Base::SkSurface_Base(int width, int height, const SkSurfaceProps* props)
53 : INHERITED(width, height, props)
54{
reed@google.com9ea5a3b2012-07-30 21:03:46 +000055 fCachedCanvas = NULL;
reed@google.com97af1a62012-08-28 12:19:02 +000056 fCachedImage = NULL;
reed@google.com9ea5a3b2012-07-30 21:03:46 +000057}
reed@google.com889b09e2012-07-27 21:10:42 +000058
reed3716fd02014-09-21 09:39:55 -070059SkSurface_Base::SkSurface_Base(const SkImageInfo& info, const SkSurfaceProps* props)
60 : INHERITED(info, props)
61{
reed@google.com1360c522014-01-08 21:25:26 +000062 fCachedCanvas = NULL;
63 fCachedImage = NULL;
64}
65
reed@google.com9ea5a3b2012-07-30 21:03:46 +000066SkSurface_Base::~SkSurface_Base() {
reed@google.com97af1a62012-08-28 12:19:02 +000067 // in case the canvas outsurvives us, we null the callback
68 if (fCachedCanvas) {
69 fCachedCanvas->setSurfaceBase(NULL);
70 }
71
72 SkSafeUnref(fCachedImage);
reed@google.com9ea5a3b2012-07-30 21:03:46 +000073 SkSafeUnref(fCachedCanvas);
74}
reed@google.com889b09e2012-07-27 21:10:42 +000075
reed3716fd02014-09-21 09:39:55 -070076void SkSurface_Base::onDraw(SkCanvas* canvas, SkScalar x, SkScalar y, const SkPaint* paint) {
junov@chromium.org5ee449a2013-04-12 20:20:50 +000077 SkImage* image = this->newImageSnapshot();
reed@google.com889b09e2012-07-27 21:10:42 +000078 if (image) {
79 image->draw(canvas, x, y, paint);
80 image->unref();
81 }
82}
83
commit-bot@chromium.orgc4c98702013-04-22 14:28:01 +000084void SkSurface_Base::aboutToDraw(ContentChangeMode mode) {
reed@google.com97af1a62012-08-28 12:19:02 +000085 this->dirtyGenerationID();
86
commit-bot@chromium.org28361fa2014-03-28 16:08:05 +000087 SkASSERT(!fCachedCanvas || fCachedCanvas->getSurfaceBase() == this);
reed@google.com97af1a62012-08-28 12:19:02 +000088
bsalomon49f085d2014-09-05 13:34:00 -070089 if (fCachedImage) {
reed@google.com97af1a62012-08-28 12:19:02 +000090 // the surface may need to fork its backend, if its sharing it with
91 // the cached image. Note: we only call if there is an outstanding owner
92 // on the image (besides us).
bungeman@google.comf64c6842013-07-19 23:18:52 +000093 if (!fCachedImage->unique()) {
commit-bot@chromium.orgc4c98702013-04-22 14:28:01 +000094 this->onCopyOnWrite(mode);
reed@google.com97af1a62012-08-28 12:19:02 +000095 }
96
97 // regardless of copy-on-write, we must drop our cached image now, so
98 // that the next request will get our new contents.
99 fCachedImage->unref();
100 fCachedImage = NULL;
commit-bot@chromium.org28361fa2014-03-28 16:08:05 +0000101 } else if (kDiscard_ContentChangeMode == mode) {
102 this->onDiscard();
reed@google.com97af1a62012-08-28 12:19:02 +0000103 }
104}
105
106uint32_t SkSurface_Base::newGenerationID() {
commit-bot@chromium.org28361fa2014-03-28 16:08:05 +0000107 SkASSERT(!fCachedCanvas || fCachedCanvas->getSurfaceBase() == this);
reed@google.com97af1a62012-08-28 12:19:02 +0000108 static int32_t gID;
109 return sk_atomic_inc(&gID) + 1;
110}
111
reed@google.com889b09e2012-07-27 21:10:42 +0000112static SkSurface_Base* asSB(SkSurface* surface) {
113 return static_cast<SkSurface_Base*>(surface);
114}
115
116///////////////////////////////////////////////////////////////////////////////
117
reed3716fd02014-09-21 09:39:55 -0700118SkSurface::SkSurface(int width, int height, const SkSurfaceProps* props)
119 : fProps(SkSurfacePropsCopyOrDefault(props)), fWidth(width), fHeight(height)
120{
reed@google.com1360c522014-01-08 21:25:26 +0000121 SkASSERT(fWidth >= 0);
122 SkASSERT(fHeight >= 0);
123 fGenerationID = 0;
124}
125
reed3716fd02014-09-21 09:39:55 -0700126SkSurface::SkSurface(const SkImageInfo& info, const SkSurfaceProps* props)
127 : fProps(SkSurfacePropsCopyOrDefault(props)), fWidth(info.width()), fHeight(info.height())
128{
reed@google.com1360c522014-01-08 21:25:26 +0000129 SkASSERT(fWidth >= 0);
130 SkASSERT(fHeight >= 0);
reed@google.com889b09e2012-07-27 21:10:42 +0000131 fGenerationID = 0;
132}
133
reed@google.com97af1a62012-08-28 12:19:02 +0000134uint32_t SkSurface::generationID() {
135 if (0 == fGenerationID) {
136 fGenerationID = asSB(this)->newGenerationID();
137 }
138 return fGenerationID;
139}
140
commit-bot@chromium.orgc4c98702013-04-22 14:28:01 +0000141void SkSurface::notifyContentWillChange(ContentChangeMode mode) {
142 asSB(this)->aboutToDraw(mode);
reed@google.com97af1a62012-08-28 12:19:02 +0000143}
144
reed@google.com9ea5a3b2012-07-30 21:03:46 +0000145SkCanvas* SkSurface::getCanvas() {
146 return asSB(this)->getCachedCanvas();
reed@google.com889b09e2012-07-27 21:10:42 +0000147}
148
junov@chromium.org5ee449a2013-04-12 20:20:50 +0000149SkImage* SkSurface::newImageSnapshot() {
reed@google.com97af1a62012-08-28 12:19:02 +0000150 SkImage* image = asSB(this)->getCachedImage();
151 SkSafeRef(image); // the caller will call unref() to balance this
152 return image;
reed@google.com889b09e2012-07-27 21:10:42 +0000153}
154
reed@google.com2bd8b812013-11-01 13:46:54 +0000155SkSurface* SkSurface::newSurface(const SkImageInfo& info) {
mike@reedtribe.orgb9476252012-11-15 02:37:45 +0000156 return asSB(this)->onNewSurface(info);
reed@google.com889b09e2012-07-27 21:10:42 +0000157}
158
159void SkSurface::draw(SkCanvas* canvas, SkScalar x, SkScalar y,
160 const SkPaint* paint) {
161 return asSB(this)->onDraw(canvas, x, y, paint);
162}
commit-bot@chromium.orgc3bd8af2014-02-13 17:14:46 +0000163
164const void* SkSurface::peekPixels(SkImageInfo* info, size_t* rowBytes) {
165 return this->getCanvas()->peekPixels(info, rowBytes);
166}
reed3716fd02014-09-21 09:39:55 -0700167
168//////////////////////////////////////////////////////////////////////////////////////
169#ifdef SK_SUPPORT_LEGACY_TEXTRENDERMODE
170
171static SkSurfaceProps make_props(SkSurface::TextRenderMode trm) {
172 uint32_t propsFlags = 0;
173 if (SkSurface::kDistanceField_TextRenderMode == trm) {
174 propsFlags |= SkSurfaceProps::kUseDistanceFieldFonts_Flag;
175 }
176 return SkSurfaceProps(propsFlags, SkSurfaceProps::kLegacyFontHost_InitType);
177}
178
179SkSurface* SkSurface::NewRenderTargetDirect(GrRenderTarget* target, TextRenderMode trm,
180 RenderTargetFlags flags) {
181 SkSurfaceProps props = make_props(trm);
182 return NewRenderTargetDirect(target, &props, flags);
183}
184
185SkSurface* SkSurface::NewRenderTarget(GrContext* gr, const SkImageInfo& info, int sampleCount,
186 TextRenderMode trm, RenderTargetFlags flags) {
187 SkSurfaceProps props = make_props(trm);
188 return NewRenderTarget(gr, info, sampleCount, &props, flags);
189}
190
191SkSurface* SkSurface::NewScratchRenderTarget(GrContext* gr, const SkImageInfo& info, int sampleCount,
192 TextRenderMode trm, RenderTargetFlags flags) {
193 SkSurfaceProps props = make_props(trm);
194 return NewScratchRenderTarget(gr, info, sampleCount, &props, flags);
195}
196
197#endif
198
199#if !SK_SUPPORT_GPU
200
201SkSurface* SkSurface::NewRenderTargetDirect(GrRenderTarget*, const SkSurfaceProps*) {
202 return NULL;
203}
204
205SkSurface* SkSurface::NewRenderTarget(GrContext*, const SkImageInfo&, int, const SkSurfaceProps*) {
206 return NULL;
207}
208
209SkSurface* SkSurface::NewScratchRenderTarget(GrContext*, const SkImageInfo&, int sampleCount,
210 const SkSurfaceProps*) {
211 return NULL;
212}
213
214#endif