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 SkPixmap& pm, int srcX, int srcY) { 174 return this->getCanvas()->readPixels(pm, srcX, srcY); 175 } 176 177 bool 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 182 bool SkSurface::readPixels(const SkBitmap& bitmap, int srcX, int srcY) { 183 SkPixmap pm; 184 return bitmap.peekPixels(&pm) && this->readPixels(pm, srcX, srcY); 185 } 186 187 void SkSurface::writePixels(const SkPixmap& pmap, int x, int y) { 188 if (pmap.addr() == nullptr || pmap.width() <= 0 || pmap.height() <= 0) { 189 return; 190 } 191 192 const SkIRect srcR = SkIRect::MakeXYWH(x, y, pmap.width(), pmap.height()); 193 const SkIRect dstR = SkIRect::MakeWH(this->width(), this->height()); 194 if (SkIRect::Intersects(srcR, dstR)) { 195 ContentChangeMode mode = kRetain_ContentChangeMode; 196 if (srcR.contains(dstR)) { 197 mode = kDiscard_ContentChangeMode; 198 } 199 asSB(this)->aboutToDraw(mode); 200 asSB(this)->onWritePixels(pmap, x, y); 201 } 202 } 203 204 void SkSurface::writePixels(const SkBitmap& src, int x, int y) { 205 SkPixmap pm; 206 if (src.peekPixels(&pm)) { 207 this->writePixels(pm, x, y); 208 } 209 } 210 211 GrBackendObject SkSurface::getTextureHandle(BackendHandleAccess access) { 212 return asSB(this)->onGetTextureHandle(access); 213 } 214 215 bool SkSurface::getRenderTargetHandle(GrBackendObject* obj, BackendHandleAccess access) { 216 return asSB(this)->onGetRenderTargetHandle(obj, access); 217 } 218 219 void SkSurface::prepareForExternalIO() { 220 this->flush(); 221 } 222 223 void SkSurface::flush() { 224 asSB(this)->onFlush(0, nullptr); 225 } 226 227 GrSemaphoresSubmitted SkSurface::flushAndSignalSemaphores(int numSemaphores, 228 GrBackendSemaphore signalSemaphores[]) { 229 return asSB(this)->onFlush(numSemaphores, signalSemaphores); 230 } 231 232 bool SkSurface::wait(int numSemaphores, const GrBackendSemaphore* waitSemaphores) { 233 return asSB(this)->onWait(numSemaphores, waitSemaphores); 234 } 235 236 bool SkSurface::characterize(SkSurfaceCharacterization* characterization) const { 237 return asSB(const_cast<SkSurface*>(this))->onCharacterize(characterization); 238 } 239 240 bool SkSurface::draw(SkDeferredDisplayList* ddl) { 241 return asSB(this)->onDraw(ddl); 242 } 243 244 ////////////////////////////////////////////////////////////////////////////////////// 245 #include "SkNoDrawCanvas.h" 246 247 class SkNullSurface : public SkSurface_Base { 248 public: 249 SkNullSurface(int width, int height) : SkSurface_Base(width, height, nullptr) {} 250 251 protected: 252 SkCanvas* onNewCanvas() override { 253 return new SkNoDrawCanvas(this->width(), this->height()); 254 } 255 sk_sp<SkSurface> onNewSurface(const SkImageInfo& info) override { 256 return MakeNull(info.width(), info.height()); 257 } 258 sk_sp<SkImage> onNewImageSnapshot() override { return nullptr; } 259 void onWritePixels(const SkPixmap&, int x, int y) override {} 260 void onDraw(SkCanvas*, SkScalar x, SkScalar y, const SkPaint*) override {} 261 void onCopyOnWrite(ContentChangeMode) override {} 262 }; 263 264 sk_sp<SkSurface> SkSurface::MakeNull(int width, int height) { 265 if (width < 1 || height < 1) { 266 return nullptr; 267 } 268 return sk_sp<SkSurface>(new SkNullSurface(width, height)); 269 } 270 271 ////////////////////////////////////////////////////////////////////////////////////// 272 273 #if !SK_SUPPORT_GPU 274 275 sk_sp<SkSurface> SkSurface::MakeRenderTarget(GrContext*, SkBudgeted, const SkImageInfo&, int, 276 GrSurfaceOrigin, const SkSurfaceProps*, bool) { 277 return nullptr; 278 } 279 280 sk_sp<SkSurface> SkSurface::MakeFromBackendTexture(GrContext*, const GrBackendTexture&, 281 GrSurfaceOrigin origin, int sampleCnt, 282 sk_sp<SkColorSpace>, const SkSurfaceProps*) { 283 return nullptr; 284 } 285 286 sk_sp<SkSurface> SkSurface::MakeFromBackendTexture(GrContext*, const GrBackendTexture&, 287 GrSurfaceOrigin origin, int sampleCnt, 288 SkColorType, sk_sp<SkColorSpace>, 289 const SkSurfaceProps*) { 290 return nullptr; 291 } 292 293 sk_sp<SkSurface> SkSurface::MakeFromBackendRenderTarget(GrContext*, 294 const GrBackendRenderTarget&, 295 GrSurfaceOrigin origin, 296 sk_sp<SkColorSpace>, 297 const SkSurfaceProps*) { 298 return nullptr; 299 } 300 301 sk_sp<SkSurface> SkSurface::MakeFromBackendRenderTarget(GrContext*, 302 const GrBackendRenderTarget&, 303 GrSurfaceOrigin origin, 304 SkColorType, 305 sk_sp<SkColorSpace>, 306 const SkSurfaceProps*) { 307 return nullptr; 308 } 309 310 sk_sp<SkSurface> SkSurface::MakeFromBackendTextureAsRenderTarget(GrContext*, 311 const GrBackendTexture&, 312 GrSurfaceOrigin origin, 313 int sampleCnt, 314 sk_sp<SkColorSpace>, 315 const SkSurfaceProps*) { 316 return nullptr; 317 } 318 319 sk_sp<SkSurface> SkSurface::MakeFromBackendTextureAsRenderTarget(GrContext*, 320 const GrBackendTexture&, 321 GrSurfaceOrigin origin, 322 int sampleCnt, 323 SkColorType, 324 sk_sp<SkColorSpace>, 325 const SkSurfaceProps*) { 326 return nullptr; 327 } 328 329 #endif 330