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 "SkAtomics.h" 9#include "SkSurface_Base.h" 10#include "SkImagePriv.h" 11#include "SkCanvas.h" 12 13#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 51SkSurfaceProps::SkSurfaceProps(const SkSurfaceProps& other) 52 : fFlags(other.fFlags) 53 , fPixelGeometry(other.fPixelGeometry) 54{} 55 56/////////////////////////////////////////////////////////////////////////////// 57 58SkSurface_Base::SkSurface_Base(int width, int height, const SkSurfaceProps* props) 59 : INHERITED(width, height, props) { 60} 61 62SkSurface_Base::SkSurface_Base(const SkImageInfo& info, const SkSurfaceProps* props) 63 : INHERITED(info, props) { 64} 65 66SkSurface_Base::~SkSurface_Base() { 67 // in case the canvas outsurvives us, we null the callback 68 if (fCachedCanvas) { 69 fCachedCanvas->setSurfaceBase(nullptr); 70 } 71} 72 73void SkSurface_Base::onDraw(SkCanvas* canvas, SkScalar x, SkScalar y, const SkPaint* paint) { 74 auto image = this->makeImageSnapshot(); 75 if (image) { 76 canvas->drawImage(image, x, y, paint); 77 } 78} 79 80bool SkSurface_Base::outstandingImageSnapshot() const { 81 return fCachedImage && !fCachedImage->unique(); 82} 83 84void SkSurface_Base::aboutToDraw(ContentChangeMode mode) { 85 this->dirtyGenerationID(); 86 87 SkASSERT(!fCachedCanvas || fCachedCanvas->getSurfaceBase() == this); 88 89 if (fCachedImage) { 90 // 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). 93 bool unique = fCachedImage->unique(); 94 if (!unique) { 95 this->onCopyOnWrite(mode); 96 } 97 98 // regardless of copy-on-write, we must drop our cached image now, so 99 // that the next request will get our new contents. 100 fCachedImage.reset(); 101 102 if (unique) { 103 // Our content isn't held by any image now, so we can consider that content mutable. 104 // Raster surfaces need to be told it's safe to consider its pixels mutable again. 105 // We make this call after the ->unref() so the subclass can assert there are no images. 106 this->onRestoreBackingMutability(); 107 } 108 } else if (kDiscard_ContentChangeMode == mode) { 109 this->onDiscard(); 110 } 111} 112 113uint32_t SkSurface_Base::newGenerationID() { 114 SkASSERT(!fCachedCanvas || fCachedCanvas->getSurfaceBase() == this); 115 static int32_t gID; 116 return sk_atomic_inc(&gID) + 1; 117} 118 119static SkSurface_Base* asSB(SkSurface* surface) { 120 return static_cast<SkSurface_Base*>(surface); 121} 122 123/////////////////////////////////////////////////////////////////////////////// 124 125SkSurface::SkSurface(int width, int height, const SkSurfaceProps* props) 126 : fProps(SkSurfacePropsCopyOrDefault(props)), fWidth(width), fHeight(height) 127{ 128 SkASSERT(fWidth > 0); 129 SkASSERT(fHeight > 0); 130 fGenerationID = 0; 131} 132 133SkSurface::SkSurface(const SkImageInfo& info, const SkSurfaceProps* props) 134 : fProps(SkSurfacePropsCopyOrDefault(props)), fWidth(info.width()), fHeight(info.height()) 135{ 136 SkASSERT(fWidth > 0); 137 SkASSERT(fHeight > 0); 138 fGenerationID = 0; 139} 140 141uint32_t SkSurface::generationID() { 142 if (0 == fGenerationID) { 143 fGenerationID = asSB(this)->newGenerationID(); 144 } 145 return fGenerationID; 146} 147 148void SkSurface::notifyContentWillChange(ContentChangeMode mode) { 149 asSB(this)->aboutToDraw(mode); 150} 151 152SkCanvas* SkSurface::getCanvas() { 153 return asSB(this)->getCachedCanvas(); 154} 155 156sk_sp<SkImage> SkSurface::makeImageSnapshot() { 157 return asSB(this)->refCachedImage(); 158} 159 160sk_sp<SkSurface> SkSurface::makeSurface(const SkImageInfo& info) { 161 return asSB(this)->onNewSurface(info); 162} 163 164void SkSurface::draw(SkCanvas* canvas, SkScalar x, SkScalar y, 165 const SkPaint* paint) { 166 return asSB(this)->onDraw(canvas, x, y, paint); 167} 168 169bool SkSurface::peekPixels(SkPixmap* pmap) { 170 return this->getCanvas()->peekPixels(pmap); 171} 172 173bool SkSurface::readPixels(const SkPixmap& pm, int srcX, int srcY) { 174 return this->getCanvas()->readPixels(pm, srcX, srcY); 175} 176 177bool SkSurface::readPixels(const SkImageInfo& dstInfo, void* dstPixels, size_t dstRowBytes, 178 int srcX, int srcY) { 179 return this->readPixels({dstInfo, dstPixels, dstRowBytes}, srcX, srcY); 180} 181 182bool SkSurface::readPixels(const SkBitmap& bitmap, int srcX, int srcY) { 183 SkPixmap pm; 184 return bitmap.peekPixels(&pm) && this->readPixels(pm, srcX, srcY); 185} 186 187GrBackendObject SkSurface::getTextureHandle(BackendHandleAccess access) { 188 return asSB(this)->onGetTextureHandle(access); 189} 190 191bool SkSurface::getRenderTargetHandle(GrBackendObject* obj, BackendHandleAccess access) { 192 return asSB(this)->onGetRenderTargetHandle(obj, access); 193} 194 195void SkSurface::prepareForExternalIO() { 196 this->flush(); 197} 198 199void SkSurface::flush() { 200 asSB(this)->onFlush(0, nullptr); 201} 202 203GrSemaphoresSubmitted SkSurface::flushAndSignalSemaphores(int numSemaphores, 204 GrBackendSemaphore signalSemaphores[]) { 205 return asSB(this)->onFlush(numSemaphores, signalSemaphores); 206} 207 208bool SkSurface::wait(int numSemaphores, const GrBackendSemaphore* waitSemaphores) { 209 return asSB(this)->onWait(numSemaphores, waitSemaphores); 210} 211 212bool SkSurface::characterize(SkSurfaceCharacterization* characterization) const { 213 return asSB(const_cast<SkSurface*>(this))->onCharacterize(characterization); 214} 215 216bool SkSurface::draw(SkDeferredDisplayList* ddl) { 217 return asSB(this)->onDraw(ddl); 218} 219 220////////////////////////////////////////////////////////////////////////////////////// 221#include "SkNoDrawCanvas.h" 222 223class SkNullSurface : public SkSurface_Base { 224public: 225 SkNullSurface(int width, int height) : SkSurface_Base(width, height, nullptr) {} 226 227protected: 228 SkCanvas* onNewCanvas() override { 229 return new SkNoDrawCanvas(this->width(), this->height()); 230 } 231 sk_sp<SkSurface> onNewSurface(const SkImageInfo& info) override { 232 return MakeNull(info.width(), info.height()); 233 } 234 sk_sp<SkImage> onNewImageSnapshot() override { return nullptr; } 235 void onDraw(SkCanvas*, SkScalar x, SkScalar y, const SkPaint*) override {} 236 void onCopyOnWrite(ContentChangeMode) override {} 237}; 238 239sk_sp<SkSurface> SkSurface::MakeNull(int width, int height) { 240 if (width < 1 || height < 1) { 241 return nullptr; 242 } 243 return sk_sp<SkSurface>(new SkNullSurface(width, height)); 244} 245 246////////////////////////////////////////////////////////////////////////////////////// 247 248#if !SK_SUPPORT_GPU 249 250sk_sp<SkSurface> SkSurface::MakeRenderTarget(GrContext*, SkBudgeted, const SkImageInfo&, int, 251 GrSurfaceOrigin, const SkSurfaceProps*, bool) { 252 return nullptr; 253} 254 255sk_sp<SkSurface> SkSurface::MakeFromBackendTexture(GrContext*, const GrBackendTexture&, 256 GrSurfaceOrigin origin, int sampleCnt, 257 sk_sp<SkColorSpace>, const SkSurfaceProps*) { 258 return nullptr; 259} 260 261sk_sp<SkSurface> SkSurface::MakeFromBackendTexture(GrContext*, const GrBackendTexture&, 262 GrSurfaceOrigin origin, int sampleCnt, 263 SkColorType, sk_sp<SkColorSpace>, 264 const SkSurfaceProps*) { 265 return nullptr; 266} 267 268sk_sp<SkSurface> SkSurface::MakeFromBackendRenderTarget(GrContext*, 269 const GrBackendRenderTarget&, 270 GrSurfaceOrigin origin, 271 sk_sp<SkColorSpace>, 272 const SkSurfaceProps*) { 273 return nullptr; 274} 275 276sk_sp<SkSurface> SkSurface::MakeFromBackendRenderTarget(GrContext*, 277 const GrBackendRenderTarget&, 278 GrSurfaceOrigin origin, 279 SkColorType, 280 sk_sp<SkColorSpace>, 281 const SkSurfaceProps*) { 282 return nullptr; 283} 284 285sk_sp<SkSurface> SkSurface::MakeFromBackendTextureAsRenderTarget(GrContext*, 286 const GrBackendTexture&, 287 GrSurfaceOrigin origin, 288 int sampleCnt, 289 sk_sp<SkColorSpace>, 290 const SkSurfaceProps*) { 291 return nullptr; 292} 293 294sk_sp<SkSurface> SkSurface::MakeFromBackendTextureAsRenderTarget(GrContext*, 295 const GrBackendTexture&, 296 GrSurfaceOrigin origin, 297 int sampleCnt, 298 SkColorType, 299 sk_sp<SkColorSpace>, 300 const SkSurfaceProps*) { 301 return nullptr; 302} 303 304#endif 305