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 "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