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 "SkSurface_Base.h" 9 #include "SkImagePriv.h" 10 #include "SkCanvas.h" 11 12 #include "SkFontLCDConfig.h" 13 static 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 37 SkSurfaceProps::SkSurfaceProps() : fFlags(0), fPixelGeometry(kUnknown_SkPixelGeometry) {} 38 39 SkSurfaceProps::SkSurfaceProps(InitType) : fFlags(0), fPixelGeometry(compute_default_geometry()) {} 40 41 SkSurfaceProps::SkSurfaceProps(uint32_t flags, InitType) 42 : fFlags(flags) 43 , fPixelGeometry(compute_default_geometry()) 44 {} 45 46 SkSurfaceProps::SkSurfaceProps(uint32_t flags, SkPixelGeometry pg) 47 : fFlags(flags), fPixelGeometry(pg) 48 {} 49 50 SkSurfaceProps::SkSurfaceProps(const SkSurfaceProps& other) 51 : fFlags(other.fFlags) 52 , fPixelGeometry(other.fPixelGeometry) 53 {} 54 55 /////////////////////////////////////////////////////////////////////////////// 56 57 SkSurface_Base::SkSurface_Base(int width, int height, const SkSurfaceProps* props) 58 : INHERITED(width, height, props) 59 { 60 fCachedCanvas = nullptr; 61 fCachedImage = nullptr; 62 } 63 64 SkSurface_Base::SkSurface_Base(const SkImageInfo& info, const SkSurfaceProps* props) 65 : INHERITED(info, props) 66 { 67 fCachedCanvas = nullptr; 68 fCachedImage = nullptr; 69 } 70 71 SkSurface_Base::~SkSurface_Base() { 72 // in case the canvas outsurvives us, we null the callback 73 if (fCachedCanvas) { 74 fCachedCanvas->setSurfaceBase(nullptr); 75 } 76 77 SkSafeUnref(fCachedImage); 78 SkSafeUnref(fCachedCanvas); 79 } 80 81 void SkSurface_Base::onDraw(SkCanvas* canvas, SkScalar x, SkScalar y, const SkPaint* paint) { 82 SkImage* image = this->newImageSnapshot(SkBudgeted::kYes); 83 if (image) { 84 canvas->drawImage(image, x, y, paint); 85 image->unref(); 86 } 87 } 88 89 bool SkSurface_Base::outstandingImageSnapshot() const { 90 return fCachedImage && !fCachedImage->unique(); 91 } 92 93 void SkSurface_Base::aboutToDraw(ContentChangeMode mode) { 94 this->dirtyGenerationID(); 95 96 SkASSERT(!fCachedCanvas || fCachedCanvas->getSurfaceBase() == this); 97 98 if (fCachedImage) { 99 // the surface may need to fork its backend, if its sharing it with 100 // the cached image. Note: we only call if there is an outstanding owner 101 // on the image (besides us). 102 bool unique = fCachedImage->unique(); 103 if (!unique) { 104 this->onCopyOnWrite(mode); 105 } 106 107 // regardless of copy-on-write, we must drop our cached image now, so 108 // that the next request will get our new contents. 109 fCachedImage->unref(); 110 fCachedImage = nullptr; 111 112 if (unique) { 113 // Our content isn't held by any image now, so we can consider that content mutable. 114 // Raster surfaces need to be told it's safe to consider its pixels mutable again. 115 // We make this call after the ->unref() so the subclass can assert there are no images. 116 this->onRestoreBackingMutability(); 117 } 118 } else if (kDiscard_ContentChangeMode == mode) { 119 this->onDiscard(); 120 } 121 } 122 123 uint32_t SkSurface_Base::newGenerationID() { 124 SkASSERT(!fCachedCanvas || fCachedCanvas->getSurfaceBase() == this); 125 static int32_t gID; 126 return sk_atomic_inc(&gID) + 1; 127 } 128 129 static SkSurface_Base* asSB(SkSurface* surface) { 130 return static_cast<SkSurface_Base*>(surface); 131 } 132 133 /////////////////////////////////////////////////////////////////////////////// 134 135 SkSurface::SkSurface(int width, int height, const SkSurfaceProps* props) 136 : fProps(SkSurfacePropsCopyOrDefault(props)), fWidth(width), fHeight(height) 137 { 138 SkASSERT(fWidth > 0); 139 SkASSERT(fHeight > 0); 140 fGenerationID = 0; 141 } 142 143 SkSurface::SkSurface(const SkImageInfo& info, const SkSurfaceProps* props) 144 : fProps(SkSurfacePropsCopyOrDefault(props)), fWidth(info.width()), fHeight(info.height()) 145 { 146 SkASSERT(fWidth > 0); 147 SkASSERT(fHeight > 0); 148 fGenerationID = 0; 149 } 150 151 uint32_t SkSurface::generationID() { 152 if (0 == fGenerationID) { 153 fGenerationID = asSB(this)->newGenerationID(); 154 } 155 return fGenerationID; 156 } 157 158 void SkSurface::notifyContentWillChange(ContentChangeMode mode) { 159 asSB(this)->aboutToDraw(mode); 160 } 161 162 SkCanvas* SkSurface::getCanvas() { 163 return asSB(this)->getCachedCanvas(); 164 } 165 166 SkImage* SkSurface::newImageSnapshot(SkBudgeted budgeted) { 167 // the caller will call unref() to balance this 168 return asSB(this)->refCachedImage(budgeted, kNo_ForceUnique); 169 } 170 171 SkImage* SkSurface::newImageSnapshot(SkBudgeted budgeted, ForceUnique unique) { 172 // the caller will call unref() to balance this 173 return asSB(this)->refCachedImage(budgeted, unique); 174 } 175 176 SkSurface* SkSurface::newSurface(const SkImageInfo& info) { 177 return asSB(this)->onNewSurface(info); 178 } 179 180 void SkSurface::draw(SkCanvas* canvas, SkScalar x, SkScalar y, 181 const SkPaint* paint) { 182 return asSB(this)->onDraw(canvas, x, y, paint); 183 } 184 185 const void* SkSurface::peekPixels(SkImageInfo* info, size_t* rowBytes) { 186 return this->getCanvas()->peekPixels(info, rowBytes); 187 } 188 189 bool SkSurface::readPixels(const SkImageInfo& dstInfo, void* dstPixels, size_t dstRowBytes, 190 int srcX, int srcY) { 191 return this->getCanvas()->readPixels(dstInfo, dstPixels, dstRowBytes, srcX, srcY); 192 } 193 194 GrBackendObject SkSurface::getTextureHandle(BackendHandleAccess access) { 195 return asSB(this)->onGetTextureHandle(access); 196 } 197 198 bool SkSurface::getRenderTargetHandle(GrBackendObject* obj, BackendHandleAccess access) { 199 return asSB(this)->onGetRenderTargetHandle(obj, access); 200 } 201 202 void SkSurface::prepareForExternalIO() { 203 asSB(this)->onPrepareForExternalIO(); 204 } 205 206 ////////////////////////////////////////////////////////////////////////////////////// 207 208 #if !SK_SUPPORT_GPU 209 210 SkSurface* SkSurface::NewRenderTargetDirect(GrRenderTarget*, const SkSurfaceProps*) { 211 return nullptr; 212 } 213 214 SkSurface* SkSurface::NewRenderTarget(GrContext*, SkBudgeted, const SkImageInfo&, int, 215 const SkSurfaceProps*, GrTextureStorageAllocator) { 216 return nullptr; 217 } 218 219 SkSurface* SkSurface::NewFromBackendTexture(GrContext*, const GrBackendTextureDesc&, 220 const SkSurfaceProps*) { 221 return nullptr; 222 } 223 224 SkSurface* SkSurface::NewFromBackendRenderTarget(GrContext*, const GrBackendRenderTargetDesc&, 225 const SkSurfaceProps*) { 226 return nullptr; 227 } 228 229 SkSurface* NewFromBackendTextureAsRenderTarget(GrContext*, const GrBackendTextureDesc&, 230 const SkSurfaceProps*) { 231 return nullptr; 232 } 233 234 #endif 235