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 SkImageInfo& dstInfo, void* dstPixels, size_t dstRowBytes, 174 int srcX, int srcY) { 175 return this->getCanvas()->readPixels(dstInfo, dstPixels, dstRowBytes, srcX, srcY); 176} 177 178GrBackendObject SkSurface::getTextureHandle(BackendHandleAccess access) { 179 return asSB(this)->onGetTextureHandle(access); 180} 181 182bool SkSurface::getRenderTargetHandle(GrBackendObject* obj, BackendHandleAccess access) { 183 return asSB(this)->onGetRenderTargetHandle(obj, access); 184} 185 186void SkSurface::prepareForExternalIO() { 187 this->flush(); 188} 189 190void SkSurface::flush() { 191 asSB(this)->onFlush(0, nullptr); 192} 193 194bool SkSurface::flushAndSignalSemaphores(int numSemaphores, GrBackendSemaphore* signalSemaphores) { 195 return asSB(this)->onFlush(numSemaphores, signalSemaphores); 196} 197 198bool SkSurface::wait(int numSemaphores, const GrBackendSemaphore* waitSemaphores) { 199 return asSB(this)->onWait(numSemaphores, waitSemaphores); 200} 201 202////////////////////////////////////////////////////////////////////////////////////// 203#include "SkNoDrawCanvas.h" 204 205class SkNullSurface : public SkSurface_Base { 206public: 207 SkNullSurface(int width, int height) : SkSurface_Base(width, height, nullptr) {} 208 209protected: 210 SkCanvas* onNewCanvas() override { 211 return new SkNoDrawCanvas(this->width(), this->height()); 212 } 213 sk_sp<SkSurface> onNewSurface(const SkImageInfo& info) override { 214 return MakeNull(info.width(), info.height()); 215 } 216 sk_sp<SkImage> onNewImageSnapshot() override { return nullptr; } 217 void onDraw(SkCanvas*, SkScalar x, SkScalar y, const SkPaint*) override {} 218 void onCopyOnWrite(ContentChangeMode) override {} 219}; 220 221sk_sp<SkSurface> SkSurface::MakeNull(int width, int height) { 222 if (width < 1 || height < 1) { 223 return nullptr; 224 } 225 return sk_sp<SkSurface>(new SkNullSurface(width, height)); 226} 227 228////////////////////////////////////////////////////////////////////////////////////// 229 230#if !SK_SUPPORT_GPU 231 232sk_sp<SkSurface> SkSurface::MakeRenderTarget(GrContext*, SkBudgeted, const SkImageInfo&, 233 int, GrSurfaceOrigin, const SkSurfaceProps*) { 234 return nullptr; 235} 236 237sk_sp<SkSurface> SkSurface::MakeFromBackendTexture(GrContext*, const GrBackendTextureDesc&, 238 sk_sp<SkColorSpace>, const SkSurfaceProps*) { 239 return nullptr; 240} 241 242sk_sp<SkSurface> SkSurface::MakeFromBackendTexture(GrContext*, const GrBackendTexture&, 243 GrSurfaceOrigin origin, int sampleCnt, 244 sk_sp<SkColorSpace>, const SkSurfaceProps*) { 245 return nullptr; 246} 247 248sk_sp<SkSurface> SkSurface::MakeFromBackendRenderTarget(GrContext*, 249 const GrBackendRenderTargetDesc&, 250 sk_sp<SkColorSpace>, 251 const SkSurfaceProps*) { 252 return nullptr; 253} 254 255sk_sp<SkSurface> SkSurface::MakeFromBackendRenderTarget(GrContext*, 256 const GrBackendRenderTarget&, 257 GrSurfaceOrigin origin, 258 sk_sp<SkColorSpace>, 259 const SkSurfaceProps*) { 260 return nullptr; 261} 262 263sk_sp<SkSurface> SkSurface::MakeFromBackendTextureAsRenderTarget(GrContext*, 264 const GrBackendTextureDesc&, 265 sk_sp<SkColorSpace>, 266 const SkSurfaceProps*) { 267 return nullptr; 268} 269 270sk_sp<SkSurface> SkSurface::MakeFromBackendTextureAsRenderTarget(GrContext*, 271 const GrBackendTexture&, 272 GrSurfaceOrigin origin, 273 int sampleCnt, 274 sk_sp<SkColorSpace>, 275 const SkSurfaceProps*) { 276 return nullptr; 277} 278 279#endif 280