Home | History | Annotate | Download | only in image
      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