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 = NULL; 61 fCachedImage = NULL; 62} 63 64SkSurface_Base::SkSurface_Base(const SkImageInfo& info, const SkSurfaceProps* props) 65 : INHERITED(info, props) 66{ 67 fCachedCanvas = NULL; 68 fCachedImage = NULL; 69} 70 71SkSurface_Base::~SkSurface_Base() { 72 // in case the canvas outsurvives us, we null the callback 73 if (fCachedCanvas) { 74 fCachedCanvas->setSurfaceBase(NULL); 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(kYes_Budgeted); 83 if (image) { 84 canvas->drawImage(image, x, y, paint); 85 image->unref(); 86 } 87} 88 89void SkSurface_Base::aboutToDraw(ContentChangeMode mode) { 90 this->dirtyGenerationID(); 91 92 SkASSERT(!fCachedCanvas || fCachedCanvas->getSurfaceBase() == this); 93 94 if (fCachedImage) { 95 // the surface may need to fork its backend, if its sharing it with 96 // the cached image. Note: we only call if there is an outstanding owner 97 // on the image (besides us). 98 if (!fCachedImage->unique()) { 99 this->onCopyOnWrite(mode); 100 } 101 102 // regardless of copy-on-write, we must drop our cached image now, so 103 // that the next request will get our new contents. 104 fCachedImage->unref(); 105 fCachedImage = NULL; 106 } else if (kDiscard_ContentChangeMode == mode) { 107 this->onDiscard(); 108 } 109} 110 111uint32_t SkSurface_Base::newGenerationID() { 112 SkASSERT(!fCachedCanvas || fCachedCanvas->getSurfaceBase() == this); 113 static int32_t gID; 114 return sk_atomic_inc(&gID) + 1; 115} 116 117static SkSurface_Base* asSB(SkSurface* surface) { 118 return static_cast<SkSurface_Base*>(surface); 119} 120 121/////////////////////////////////////////////////////////////////////////////// 122 123SkSurface::SkSurface(int width, int height, const SkSurfaceProps* props) 124 : fProps(SkSurfacePropsCopyOrDefault(props)), fWidth(width), fHeight(height) 125{ 126 SkASSERT(fWidth > 0); 127 SkASSERT(fHeight > 0); 128 fGenerationID = 0; 129} 130 131SkSurface::SkSurface(const SkImageInfo& info, const SkSurfaceProps* props) 132 : fProps(SkSurfacePropsCopyOrDefault(props)), fWidth(info.width()), fHeight(info.height()) 133{ 134 SkASSERT(fWidth > 0); 135 SkASSERT(fHeight > 0); 136 fGenerationID = 0; 137} 138 139uint32_t SkSurface::generationID() { 140 if (0 == fGenerationID) { 141 fGenerationID = asSB(this)->newGenerationID(); 142 } 143 return fGenerationID; 144} 145 146void SkSurface::notifyContentWillChange(ContentChangeMode mode) { 147 asSB(this)->aboutToDraw(mode); 148} 149 150SkCanvas* SkSurface::getCanvas() { 151 return asSB(this)->getCachedCanvas(); 152} 153 154SkImage* SkSurface::newImageSnapshot(Budgeted budgeted) { 155 SkImage* image = asSB(this)->getCachedImage(budgeted); 156 SkSafeRef(image); // the caller will call unref() to balance this 157 return image; 158} 159 160SkSurface* SkSurface::newSurface(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 169const void* SkSurface::peekPixels(SkImageInfo* info, size_t* rowBytes) { 170 return this->getCanvas()->peekPixels(info, rowBytes); 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 178////////////////////////////////////////////////////////////////////////////////////// 179 180#if !SK_SUPPORT_GPU 181 182SkSurface* SkSurface::NewRenderTargetDirect(GrRenderTarget*, const SkSurfaceProps*) { 183 return NULL; 184} 185 186SkSurface* SkSurface::NewRenderTarget(GrContext*, Budgeted, const SkImageInfo&, int, 187 const SkSurfaceProps*) { 188 return NULL; 189} 190 191SkSurface* SkSurface::NewWrappedRenderTarget(GrContext*, GrBackendTextureDesc, 192 const SkSurfaceProps*) { 193 return NULL; 194} 195 196#endif 197