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" 14 static 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 38 SkSurfaceProps::SkSurfaceProps() : fFlags(0), fPixelGeometry(kUnknown_SkPixelGeometry) {} 39 40 SkSurfaceProps::SkSurfaceProps(InitType) : fFlags(0), fPixelGeometry(compute_default_geometry()) {} 41 42 SkSurfaceProps::SkSurfaceProps(uint32_t flags, InitType) 43 : fFlags(flags) 44 , fPixelGeometry(compute_default_geometry()) 45 {} 46 47 SkSurfaceProps::SkSurfaceProps(uint32_t flags, SkPixelGeometry pg) 48 : fFlags(flags), fPixelGeometry(pg) 49 {} 50 51 SkSurfaceProps::SkSurfaceProps(const SkSurfaceProps& other) 52 : fFlags(other.fFlags) 53 , fPixelGeometry(other.fPixelGeometry) 54 {} 55 56 /////////////////////////////////////////////////////////////////////////////// 57 58 SkSurface_Base::SkSurface_Base(int width, int height, const SkSurfaceProps* props) 59 : INHERITED(width, height, props) { 60 } 61 62 SkSurface_Base::SkSurface_Base(const SkImageInfo& info, const SkSurfaceProps* props) 63 : INHERITED(info, props) { 64 } 65 66 SkSurface_Base::~SkSurface_Base() { 67 // in case the canvas outsurvives us, we null the callback 68 if (fCachedCanvas) { 69 fCachedCanvas->setSurfaceBase(nullptr); 70 } 71 } 72 73 void 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 80 bool SkSurface_Base::outstandingImageSnapshot() const { 81 return fCachedImage && !fCachedImage->unique(); 82 } 83 84 void 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 113 uint32_t SkSurface_Base::newGenerationID() { 114 SkASSERT(!fCachedCanvas || fCachedCanvas->getSurfaceBase() == this); 115 static int32_t gID; 116 return sk_atomic_inc(&gID) + 1; 117 } 118 119 static SkSurface_Base* asSB(SkSurface* surface) { 120 return static_cast<SkSurface_Base*>(surface); 121 } 122 123 /////////////////////////////////////////////////////////////////////////////// 124 125 SkSurface::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 133 SkSurface::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 141 uint32_t SkSurface::generationID() { 142 if (0 == fGenerationID) { 143 fGenerationID = asSB(this)->newGenerationID(); 144 } 145 return fGenerationID; 146 } 147 148 void SkSurface::notifyContentWillChange(ContentChangeMode mode) { 149 asSB(this)->aboutToDraw(mode); 150 } 151 152 SkCanvas* SkSurface::getCanvas() { 153 return asSB(this)->getCachedCanvas(); 154 } 155 156 sk_sp<SkImage> SkSurface::makeImageSnapshot() { 157 return asSB(this)->refCachedImage(); 158 } 159 160 sk_sp<SkSurface> SkSurface::makeSurface(const SkImageInfo& info) { 161 return asSB(this)->onNewSurface(info); 162 } 163 164 void SkSurface::draw(SkCanvas* canvas, SkScalar x, SkScalar y, 165 const SkPaint* paint) { 166 return asSB(this)->onDraw(canvas, x, y, paint); 167 } 168 169 bool SkSurface::peekPixels(SkPixmap* pmap) { 170 return this->getCanvas()->peekPixels(pmap); 171 } 172 173 bool 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 178 GrBackendObject SkSurface::getTextureHandle(BackendHandleAccess access) { 179 return asSB(this)->onGetTextureHandle(access); 180 } 181 182 bool SkSurface::getRenderTargetHandle(GrBackendObject* obj, BackendHandleAccess access) { 183 return asSB(this)->onGetRenderTargetHandle(obj, access); 184 } 185 186 void SkSurface::prepareForExternalIO() { 187 this->flush(); 188 } 189 190 void SkSurface::flush() { 191 asSB(this)->onFlush(0, nullptr); 192 } 193 194 bool SkSurface::flushAndSignalSemaphores(int numSemaphores, GrBackendSemaphore* signalSemaphores) { 195 return asSB(this)->onFlush(numSemaphores, signalSemaphores); 196 } 197 198 bool SkSurface::wait(int numSemaphores, const GrBackendSemaphore* waitSemaphores) { 199 return asSB(this)->onWait(numSemaphores, waitSemaphores); 200 } 201 202 ////////////////////////////////////////////////////////////////////////////////////// 203 #include "SkNoDrawCanvas.h" 204 205 class SkNullSurface : public SkSurface_Base { 206 public: 207 SkNullSurface(int width, int height) : SkSurface_Base(width, height, nullptr) {} 208 209 protected: 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 221 sk_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 232 sk_sp<SkSurface> SkSurface::MakeRenderTarget(GrContext*, SkBudgeted, const SkImageInfo&, 233 int, GrSurfaceOrigin, const SkSurfaceProps*) { 234 return nullptr; 235 } 236 237 sk_sp<SkSurface> SkSurface::MakeFromBackendTexture(GrContext*, const GrBackendTextureDesc&, 238 sk_sp<SkColorSpace>, const SkSurfaceProps*) { 239 return nullptr; 240 } 241 242 sk_sp<SkSurface> SkSurface::MakeFromBackendTexture(GrContext*, const GrBackendTexture&, 243 GrSurfaceOrigin origin, int sampleCnt, 244 sk_sp<SkColorSpace>, const SkSurfaceProps*) { 245 return nullptr; 246 } 247 248 sk_sp<SkSurface> SkSurface::MakeFromBackendRenderTarget(GrContext*, 249 const GrBackendRenderTargetDesc&, 250 sk_sp<SkColorSpace>, 251 const SkSurfaceProps*) { 252 return nullptr; 253 } 254 255 sk_sp<SkSurface> SkSurface::MakeFromBackendRenderTarget(GrContext*, 256 const GrBackendRenderTarget&, 257 GrSurfaceOrigin origin, 258 sk_sp<SkColorSpace>, 259 const SkSurfaceProps*) { 260 return nullptr; 261 } 262 263 sk_sp<SkSurface> SkSurface::MakeFromBackendTextureAsRenderTarget(GrContext*, 264 const GrBackendTextureDesc&, 265 sk_sp<SkColorSpace>, 266 const SkSurfaceProps*) { 267 return nullptr; 268 } 269 270 sk_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