1c9062047cea66575868270b4dcaeb1dab113c8a7reed@google.com/*
2c9062047cea66575868270b4dcaeb1dab113c8a7reed@google.com * Copyright 2012 Google Inc.
3c9062047cea66575868270b4dcaeb1dab113c8a7reed@google.com *
4c9062047cea66575868270b4dcaeb1dab113c8a7reed@google.com * Use of this source code is governed by a BSD-style license that can be
5c9062047cea66575868270b4dcaeb1dab113c8a7reed@google.com * found in the LICENSE file.
6c9062047cea66575868270b4dcaeb1dab113c8a7reed@google.com */
7c9062047cea66575868270b4dcaeb1dab113c8a7reed@google.com
89ea5a3bc7361cb88d37280b5922fba9430fed328reed@google.com#include "SkSurface_Base.h"
9889b09edfeb5f461ca283dfd08ee6b23560a7859reed@google.com#include "SkImagePriv.h"
10889b09edfeb5f461ca283dfd08ee6b23560a7859reed@google.com#include "SkCanvas.h"
11889b09edfeb5f461ca283dfd08ee6b23560a7859reed@google.com
124a8126e7f81384526629b1e21bf89b632ea13cd9reed#include "SkFontLCDConfig.h"
134a8126e7f81384526629b1e21bf89b632ea13cd9reedstatic SkPixelGeometry compute_default_geometry() {
144a8126e7f81384526629b1e21bf89b632ea13cd9reed    SkFontLCDConfig::LCDOrder order = SkFontLCDConfig::GetSubpixelOrder();
154a8126e7f81384526629b1e21bf89b632ea13cd9reed    if (SkFontLCDConfig::kNONE_LCDOrder == order) {
164a8126e7f81384526629b1e21bf89b632ea13cd9reed        return kUnknown_SkPixelGeometry;
174a8126e7f81384526629b1e21bf89b632ea13cd9reed    } else {
184a8126e7f81384526629b1e21bf89b632ea13cd9reed        // Bit0 is RGB(0), BGR(1)
194a8126e7f81384526629b1e21bf89b632ea13cd9reed        // Bit1 is H(0), V(1)
204a8126e7f81384526629b1e21bf89b632ea13cd9reed        const SkPixelGeometry gGeo[] = {
214a8126e7f81384526629b1e21bf89b632ea13cd9reed            kRGB_H_SkPixelGeometry,
224a8126e7f81384526629b1e21bf89b632ea13cd9reed            kBGR_H_SkPixelGeometry,
234a8126e7f81384526629b1e21bf89b632ea13cd9reed            kRGB_V_SkPixelGeometry,
244a8126e7f81384526629b1e21bf89b632ea13cd9reed            kBGR_V_SkPixelGeometry,
254a8126e7f81384526629b1e21bf89b632ea13cd9reed        };
264a8126e7f81384526629b1e21bf89b632ea13cd9reed        int index = 0;
274a8126e7f81384526629b1e21bf89b632ea13cd9reed        if (SkFontLCDConfig::kBGR_LCDOrder == order) {
284a8126e7f81384526629b1e21bf89b632ea13cd9reed            index |= 1;
294a8126e7f81384526629b1e21bf89b632ea13cd9reed        }
304a8126e7f81384526629b1e21bf89b632ea13cd9reed        if (SkFontLCDConfig::kVertical_LCDOrientation == SkFontLCDConfig::GetSubpixelOrientation()){
314a8126e7f81384526629b1e21bf89b632ea13cd9reed            index |= 2;
324a8126e7f81384526629b1e21bf89b632ea13cd9reed        }
334a8126e7f81384526629b1e21bf89b632ea13cd9reed        return gGeo[index];
344a8126e7f81384526629b1e21bf89b632ea13cd9reed    }
354a8126e7f81384526629b1e21bf89b632ea13cd9reed}
364a8126e7f81384526629b1e21bf89b632ea13cd9reed
374a8126e7f81384526629b1e21bf89b632ea13cd9reedSkSurfaceProps::SkSurfaceProps() : fFlags(0), fPixelGeometry(kUnknown_SkPixelGeometry) {}
384a8126e7f81384526629b1e21bf89b632ea13cd9reed
394a8126e7f81384526629b1e21bf89b632ea13cd9reedSkSurfaceProps::SkSurfaceProps(InitType) : fFlags(0), fPixelGeometry(compute_default_geometry()) {}
404a8126e7f81384526629b1e21bf89b632ea13cd9reed
414a8126e7f81384526629b1e21bf89b632ea13cd9reedSkSurfaceProps::SkSurfaceProps(uint32_t flags, InitType)
424a8126e7f81384526629b1e21bf89b632ea13cd9reed    : fFlags(flags)
434a8126e7f81384526629b1e21bf89b632ea13cd9reed    , fPixelGeometry(compute_default_geometry())
444a8126e7f81384526629b1e21bf89b632ea13cd9reed{}
454a8126e7f81384526629b1e21bf89b632ea13cd9reed
464a8126e7f81384526629b1e21bf89b632ea13cd9reedSkSurfaceProps::SkSurfaceProps(uint32_t flags, SkPixelGeometry pg)
474a8126e7f81384526629b1e21bf89b632ea13cd9reed    : fFlags(flags), fPixelGeometry(pg)
484a8126e7f81384526629b1e21bf89b632ea13cd9reed{}
494a8126e7f81384526629b1e21bf89b632ea13cd9reed
504af267b11964d4a8acdb232ac46094c84d890e88reedSkSurfaceProps::SkSurfaceProps(const SkSurfaceProps& other)
514af267b11964d4a8acdb232ac46094c84d890e88reed    : fFlags(other.fFlags)
524af267b11964d4a8acdb232ac46094c84d890e88reed    , fPixelGeometry(other.fPixelGeometry)
534af267b11964d4a8acdb232ac46094c84d890e88reed{}
544af267b11964d4a8acdb232ac46094c84d890e88reed
55889b09edfeb5f461ca283dfd08ee6b23560a7859reed@google.com///////////////////////////////////////////////////////////////////////////////
56889b09edfeb5f461ca283dfd08ee6b23560a7859reed@google.com
574a8126e7f81384526629b1e21bf89b632ea13cd9reedSkSurface_Base::SkSurface_Base(int width, int height, const SkSurfaceProps* props)
584a8126e7f81384526629b1e21bf89b632ea13cd9reed    : INHERITED(width, height, props)
594a8126e7f81384526629b1e21bf89b632ea13cd9reed{
609ea5a3bc7361cb88d37280b5922fba9430fed328reed@google.com    fCachedCanvas = NULL;
6197af1a64ae6bdddd346d8babfd9f188279dd6644reed@google.com    fCachedImage = NULL;
629ea5a3bc7361cb88d37280b5922fba9430fed328reed@google.com}
63889b09edfeb5f461ca283dfd08ee6b23560a7859reed@google.com
644a8126e7f81384526629b1e21bf89b632ea13cd9reedSkSurface_Base::SkSurface_Base(const SkImageInfo& info, const SkSurfaceProps* props)
654a8126e7f81384526629b1e21bf89b632ea13cd9reed    : INHERITED(info, props)
664a8126e7f81384526629b1e21bf89b632ea13cd9reed{
671360c52b10dad45d7a6850370eab40c6253d7988reed@google.com    fCachedCanvas = NULL;
681360c52b10dad45d7a6850370eab40c6253d7988reed@google.com    fCachedImage = NULL;
691360c52b10dad45d7a6850370eab40c6253d7988reed@google.com}
701360c52b10dad45d7a6850370eab40c6253d7988reed@google.com
719ea5a3bc7361cb88d37280b5922fba9430fed328reed@google.comSkSurface_Base::~SkSurface_Base() {
7297af1a64ae6bdddd346d8babfd9f188279dd6644reed@google.com    // in case the canvas outsurvives us, we null the callback
7397af1a64ae6bdddd346d8babfd9f188279dd6644reed@google.com    if (fCachedCanvas) {
7497af1a64ae6bdddd346d8babfd9f188279dd6644reed@google.com        fCachedCanvas->setSurfaceBase(NULL);
7597af1a64ae6bdddd346d8babfd9f188279dd6644reed@google.com    }
7697af1a64ae6bdddd346d8babfd9f188279dd6644reed@google.com
7797af1a64ae6bdddd346d8babfd9f188279dd6644reed@google.com    SkSafeUnref(fCachedImage);
789ea5a3bc7361cb88d37280b5922fba9430fed328reed@google.com    SkSafeUnref(fCachedCanvas);
799ea5a3bc7361cb88d37280b5922fba9430fed328reed@google.com}
80889b09edfeb5f461ca283dfd08ee6b23560a7859reed@google.com
814a8126e7f81384526629b1e21bf89b632ea13cd9reedvoid SkSurface_Base::onDraw(SkCanvas* canvas, SkScalar x, SkScalar y, const SkPaint* paint) {
82eaaaf0b16c4e55ff8a48c5ac1ed623a6ba469053bsalomon    SkImage* image = this->newImageSnapshot(kYes_Budgeted);
83889b09edfeb5f461ca283dfd08ee6b23560a7859reed@google.com    if (image) {
84b5fae93d72c7b6480f83fd8a7b534cd1fdfcd49apiotaixr        canvas->drawImage(image, x, y, paint);
85889b09edfeb5f461ca283dfd08ee6b23560a7859reed@google.com        image->unref();
86889b09edfeb5f461ca283dfd08ee6b23560a7859reed@google.com    }
87889b09edfeb5f461ca283dfd08ee6b23560a7859reed@google.com}
88889b09edfeb5f461ca283dfd08ee6b23560a7859reed@google.com
89c4c9870953037be94da00ac9db887d171f6e479ccommit-bot@chromium.orgvoid SkSurface_Base::aboutToDraw(ContentChangeMode mode) {
9097af1a64ae6bdddd346d8babfd9f188279dd6644reed@google.com    this->dirtyGenerationID();
9197af1a64ae6bdddd346d8babfd9f188279dd6644reed@google.com
9228361fad1054d59ed4e6a320c7a8b8782a1487c7commit-bot@chromium.org    SkASSERT(!fCachedCanvas || fCachedCanvas->getSurfaceBase() == this);
9397af1a64ae6bdddd346d8babfd9f188279dd6644reed@google.com
9449f085dddff10473b6ebf832a974288300224e60bsalomon    if (fCachedImage) {
9597af1a64ae6bdddd346d8babfd9f188279dd6644reed@google.com        // the surface may need to fork its backend, if its sharing it with
9697af1a64ae6bdddd346d8babfd9f188279dd6644reed@google.com        // the cached image. Note: we only call if there is an outstanding owner
9797af1a64ae6bdddd346d8babfd9f188279dd6644reed@google.com        // on the image (besides us).
98f64c6842c15e1ba126639be7578e4642cb396987bungeman@google.com        if (!fCachedImage->unique()) {
99c4c9870953037be94da00ac9db887d171f6e479ccommit-bot@chromium.org            this->onCopyOnWrite(mode);
10097af1a64ae6bdddd346d8babfd9f188279dd6644reed@google.com        }
10197af1a64ae6bdddd346d8babfd9f188279dd6644reed@google.com
10297af1a64ae6bdddd346d8babfd9f188279dd6644reed@google.com        // regardless of copy-on-write, we must drop our cached image now, so
10397af1a64ae6bdddd346d8babfd9f188279dd6644reed@google.com        // that the next request will get our new contents.
10497af1a64ae6bdddd346d8babfd9f188279dd6644reed@google.com        fCachedImage->unref();
10597af1a64ae6bdddd346d8babfd9f188279dd6644reed@google.com        fCachedImage = NULL;
10628361fad1054d59ed4e6a320c7a8b8782a1487c7commit-bot@chromium.org    } else if (kDiscard_ContentChangeMode == mode) {
10728361fad1054d59ed4e6a320c7a8b8782a1487c7commit-bot@chromium.org        this->onDiscard();
10897af1a64ae6bdddd346d8babfd9f188279dd6644reed@google.com    }
10997af1a64ae6bdddd346d8babfd9f188279dd6644reed@google.com}
11097af1a64ae6bdddd346d8babfd9f188279dd6644reed@google.com
11197af1a64ae6bdddd346d8babfd9f188279dd6644reed@google.comuint32_t SkSurface_Base::newGenerationID() {
11228361fad1054d59ed4e6a320c7a8b8782a1487c7commit-bot@chromium.org    SkASSERT(!fCachedCanvas || fCachedCanvas->getSurfaceBase() == this);
11397af1a64ae6bdddd346d8babfd9f188279dd6644reed@google.com    static int32_t gID;
11497af1a64ae6bdddd346d8babfd9f188279dd6644reed@google.com    return sk_atomic_inc(&gID) + 1;
11597af1a64ae6bdddd346d8babfd9f188279dd6644reed@google.com}
11697af1a64ae6bdddd346d8babfd9f188279dd6644reed@google.com
117889b09edfeb5f461ca283dfd08ee6b23560a7859reed@google.comstatic SkSurface_Base* asSB(SkSurface* surface) {
118889b09edfeb5f461ca283dfd08ee6b23560a7859reed@google.com    return static_cast<SkSurface_Base*>(surface);
119889b09edfeb5f461ca283dfd08ee6b23560a7859reed@google.com}
120889b09edfeb5f461ca283dfd08ee6b23560a7859reed@google.com
121889b09edfeb5f461ca283dfd08ee6b23560a7859reed@google.com///////////////////////////////////////////////////////////////////////////////
122889b09edfeb5f461ca283dfd08ee6b23560a7859reed@google.com
1234a8126e7f81384526629b1e21bf89b632ea13cd9reedSkSurface::SkSurface(int width, int height, const SkSurfaceProps* props)
1244a8126e7f81384526629b1e21bf89b632ea13cd9reed    : fProps(SkSurfacePropsCopyOrDefault(props)), fWidth(width), fHeight(height)
1254a8126e7f81384526629b1e21bf89b632ea13cd9reed{
126b2497c2d945c0a5d770865b026e2d5947bf37c91reed    SkASSERT(fWidth > 0);
127b2497c2d945c0a5d770865b026e2d5947bf37c91reed    SkASSERT(fHeight > 0);
1281360c52b10dad45d7a6850370eab40c6253d7988reed@google.com    fGenerationID = 0;
1291360c52b10dad45d7a6850370eab40c6253d7988reed@google.com}
1301360c52b10dad45d7a6850370eab40c6253d7988reed@google.com
1314a8126e7f81384526629b1e21bf89b632ea13cd9reedSkSurface::SkSurface(const SkImageInfo& info, const SkSurfaceProps* props)
1324a8126e7f81384526629b1e21bf89b632ea13cd9reed    : fProps(SkSurfacePropsCopyOrDefault(props)), fWidth(info.width()), fHeight(info.height())
1334a8126e7f81384526629b1e21bf89b632ea13cd9reed{
134b2497c2d945c0a5d770865b026e2d5947bf37c91reed    SkASSERT(fWidth > 0);
135b2497c2d945c0a5d770865b026e2d5947bf37c91reed    SkASSERT(fHeight > 0);
136889b09edfeb5f461ca283dfd08ee6b23560a7859reed@google.com    fGenerationID = 0;
137889b09edfeb5f461ca283dfd08ee6b23560a7859reed@google.com}
138889b09edfeb5f461ca283dfd08ee6b23560a7859reed@google.com
13997af1a64ae6bdddd346d8babfd9f188279dd6644reed@google.comuint32_t SkSurface::generationID() {
14097af1a64ae6bdddd346d8babfd9f188279dd6644reed@google.com    if (0 == fGenerationID) {
14197af1a64ae6bdddd346d8babfd9f188279dd6644reed@google.com        fGenerationID = asSB(this)->newGenerationID();
14297af1a64ae6bdddd346d8babfd9f188279dd6644reed@google.com    }
14397af1a64ae6bdddd346d8babfd9f188279dd6644reed@google.com    return fGenerationID;
14497af1a64ae6bdddd346d8babfd9f188279dd6644reed@google.com}
14597af1a64ae6bdddd346d8babfd9f188279dd6644reed@google.com
146c4c9870953037be94da00ac9db887d171f6e479ccommit-bot@chromium.orgvoid SkSurface::notifyContentWillChange(ContentChangeMode mode) {
147c4c9870953037be94da00ac9db887d171f6e479ccommit-bot@chromium.org    asSB(this)->aboutToDraw(mode);
14897af1a64ae6bdddd346d8babfd9f188279dd6644reed@google.com}
14997af1a64ae6bdddd346d8babfd9f188279dd6644reed@google.com
1509ea5a3bc7361cb88d37280b5922fba9430fed328reed@google.comSkCanvas* SkSurface::getCanvas() {
1519ea5a3bc7361cb88d37280b5922fba9430fed328reed@google.com    return asSB(this)->getCachedCanvas();
152889b09edfeb5f461ca283dfd08ee6b23560a7859reed@google.com}
153889b09edfeb5f461ca283dfd08ee6b23560a7859reed@google.com
154eaaaf0b16c4e55ff8a48c5ac1ed623a6ba469053bsalomonSkImage* SkSurface::newImageSnapshot(Budgeted budgeted) {
155eaaaf0b16c4e55ff8a48c5ac1ed623a6ba469053bsalomon    SkImage* image = asSB(this)->getCachedImage(budgeted);
15697af1a64ae6bdddd346d8babfd9f188279dd6644reed@google.com    SkSafeRef(image);   // the caller will call unref() to balance this
15797af1a64ae6bdddd346d8babfd9f188279dd6644reed@google.com    return image;
158889b09edfeb5f461ca283dfd08ee6b23560a7859reed@google.com}
159889b09edfeb5f461ca283dfd08ee6b23560a7859reed@google.com
1602bd8b8100529c96c81c30f749f672f4caf775b04reed@google.comSkSurface* SkSurface::newSurface(const SkImageInfo& info) {
161b947625800a26194fcf63d7b57dadb1a63677f6amike@reedtribe.org    return asSB(this)->onNewSurface(info);
162889b09edfeb5f461ca283dfd08ee6b23560a7859reed@google.com}
163889b09edfeb5f461ca283dfd08ee6b23560a7859reed@google.com
164889b09edfeb5f461ca283dfd08ee6b23560a7859reed@google.comvoid SkSurface::draw(SkCanvas* canvas, SkScalar x, SkScalar y,
165889b09edfeb5f461ca283dfd08ee6b23560a7859reed@google.com                     const SkPaint* paint) {
166889b09edfeb5f461ca283dfd08ee6b23560a7859reed@google.com    return asSB(this)->onDraw(canvas, x, y, paint);
167889b09edfeb5f461ca283dfd08ee6b23560a7859reed@google.com}
168c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org
169c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.orgconst void* SkSurface::peekPixels(SkImageInfo* info, size_t* rowBytes) {
170c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org    return this->getCanvas()->peekPixels(info, rowBytes);
171c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org}
1724a8126e7f81384526629b1e21bf89b632ea13cd9reed
1737543aa2b365abfc968bd84ee32247ac51f904608reedbool SkSurface::readPixels(const SkImageInfo& dstInfo, void* dstPixels, size_t dstRowBytes,
1747543aa2b365abfc968bd84ee32247ac51f904608reed                           int srcX, int srcY) {
1757543aa2b365abfc968bd84ee32247ac51f904608reed    return this->getCanvas()->readPixels(dstInfo, dstPixels, dstRowBytes, srcX, srcY);
1767543aa2b365abfc968bd84ee32247ac51f904608reed}
1777543aa2b365abfc968bd84ee32247ac51f904608reed
1784a8126e7f81384526629b1e21bf89b632ea13cd9reed//////////////////////////////////////////////////////////////////////////////////////
1794a8126e7f81384526629b1e21bf89b632ea13cd9reed
1804a8126e7f81384526629b1e21bf89b632ea13cd9reed#if !SK_SUPPORT_GPU
1814a8126e7f81384526629b1e21bf89b632ea13cd9reed
1824a8126e7f81384526629b1e21bf89b632ea13cd9reedSkSurface* SkSurface::NewRenderTargetDirect(GrRenderTarget*, const SkSurfaceProps*) {
1834a8126e7f81384526629b1e21bf89b632ea13cd9reed    return NULL;
1844a8126e7f81384526629b1e21bf89b632ea13cd9reed}
1854a8126e7f81384526629b1e21bf89b632ea13cd9reed
186afe3005be3392e43bc51eb7eb2017eefaed85ad1bsalomonSkSurface* SkSurface::NewRenderTarget(GrContext*, Budgeted, const SkImageInfo&, int,
187afe3005be3392e43bc51eb7eb2017eefaed85ad1bsalomon                                      const SkSurfaceProps*) {
1884a8126e7f81384526629b1e21bf89b632ea13cd9reed    return NULL;
1894a8126e7f81384526629b1e21bf89b632ea13cd9reed}
1904a8126e7f81384526629b1e21bf89b632ea13cd9reed
191e4579adfdfb4b9f195d162835a69d9c2a974a6acbsalomonSkSurface* SkSurface::NewWrappedRenderTarget(GrContext*, GrBackendTextureDesc,
192e4579adfdfb4b9f195d162835a69d9c2a974a6acbsalomon                                             const SkSurfaceProps*) {
193e4579adfdfb4b9f195d162835a69d9c2a974a6acbsalomon    return NULL;
194e4579adfdfb4b9f195d162835a69d9c2a974a6acbsalomon}
1954a8126e7f81384526629b1e21bf89b632ea13cd9reed
1964a8126e7f81384526629b1e21bf89b632ea13cd9reed#endif
197