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" 13static 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 37SkSurfaceProps::SkSurfaceProps() : fFlags(0), fPixelGeometry(kUnknown_SkPixelGeometry) {} 38 39SkSurfaceProps::SkSurfaceProps(InitType) : fFlags(0), fPixelGeometry(compute_default_geometry()) {} 40 41SkSurfaceProps::SkSurfaceProps(uint32_t flags, InitType) 42 : fFlags(flags) 43 , fPixelGeometry(compute_default_geometry()) 44{} 45 46SkSurfaceProps::SkSurfaceProps(uint32_t flags, SkPixelGeometry pg) 47 : fFlags(flags), fPixelGeometry(pg) 48{} 49 50SkSurfaceProps::SkSurfaceProps(const SkSurfaceProps& other) 51 : fFlags(other.fFlags) 52 , fPixelGeometry(other.fPixelGeometry) 53{} 54 55/////////////////////////////////////////////////////////////////////////////// 56 57SkSurface_Base::SkSurface_Base(int width, int height, const SkSurfaceProps* props) 58 : INHERITED(width, height, props) 59{ 60 fCachedCanvas = nullptr; 61 fCachedImage = nullptr; 62} 63 64SkSurface_Base::SkSurface_Base(const SkImageInfo& info, const SkSurfaceProps* props) 65 : INHERITED(info, props) 66{ 67 fCachedCanvas = nullptr; 68 fCachedImage = nullptr; 69} 70 71SkSurface_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 81void 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 89bool SkSurface_Base::outstandingImageSnapshot() const { 90 return fCachedImage && !fCachedImage->unique(); 91} 92 93void 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 123uint32_t SkSurface_Base::newGenerationID() { 124 SkASSERT(!fCachedCanvas || fCachedCanvas->getSurfaceBase() == this); 125 static int32_t gID; 126 return sk_atomic_inc(&gID) + 1; 127} 128 129static SkSurface_Base* asSB(SkSurface* surface) { 130 return static_cast<SkSurface_Base*>(surface); 131} 132 133/////////////////////////////////////////////////////////////////////////////// 134 135SkSurface::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 143SkSurface::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 151uint32_t SkSurface::generationID() { 152 if (0 == fGenerationID) { 153 fGenerationID = asSB(this)->newGenerationID(); 154 } 155 return fGenerationID; 156} 157 158void SkSurface::notifyContentWillChange(ContentChangeMode mode) { 159 asSB(this)->aboutToDraw(mode); 160} 161 162SkCanvas* SkSurface::getCanvas() { 163 return asSB(this)->getCachedCanvas(); 164} 165 166SkImage* SkSurface::newImageSnapshot(SkBudgeted budgeted) { 167 // the caller will call unref() to balance this 168 return asSB(this)->refCachedImage(budgeted, kNo_ForceUnique); 169} 170 171SkImage* SkSurface::newImageSnapshot(SkBudgeted budgeted, ForceUnique unique) { 172 // the caller will call unref() to balance this 173 return asSB(this)->refCachedImage(budgeted, unique); 174} 175 176SkSurface* SkSurface::newSurface(const SkImageInfo& info) { 177 return asSB(this)->onNewSurface(info); 178} 179 180void SkSurface::draw(SkCanvas* canvas, SkScalar x, SkScalar y, 181 const SkPaint* paint) { 182 return asSB(this)->onDraw(canvas, x, y, paint); 183} 184 185const void* SkSurface::peekPixels(SkImageInfo* info, size_t* rowBytes) { 186 return this->getCanvas()->peekPixels(info, rowBytes); 187} 188 189bool 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 194GrBackendObject SkSurface::getTextureHandle(BackendHandleAccess access) { 195 return asSB(this)->onGetTextureHandle(access); 196} 197 198bool SkSurface::getRenderTargetHandle(GrBackendObject* obj, BackendHandleAccess access) { 199 return asSB(this)->onGetRenderTargetHandle(obj, access); 200} 201 202void SkSurface::prepareForExternalIO() { 203 asSB(this)->onPrepareForExternalIO(); 204} 205 206////////////////////////////////////////////////////////////////////////////////////// 207 208#if !SK_SUPPORT_GPU 209 210SkSurface* SkSurface::NewRenderTargetDirect(GrRenderTarget*, const SkSurfaceProps*) { 211 return nullptr; 212} 213 214SkSurface* SkSurface::NewRenderTarget(GrContext*, SkBudgeted, const SkImageInfo&, int, 215 const SkSurfaceProps*, GrTextureStorageAllocator) { 216 return nullptr; 217} 218 219SkSurface* SkSurface::NewFromBackendTexture(GrContext*, const GrBackendTextureDesc&, 220 const SkSurfaceProps*) { 221 return nullptr; 222} 223 224SkSurface* SkSurface::NewFromBackendRenderTarget(GrContext*, const GrBackendRenderTargetDesc&, 225 const SkSurfaceProps*) { 226 return nullptr; 227} 228 229SkSurface* NewFromBackendTextureAsRenderTarget(GrContext*, const GrBackendTextureDesc&, 230 const SkSurfaceProps*) { 231 return nullptr; 232} 233 234#endif 235