15d4ba8869476831ee73b15a052af8003d0a1fa2ereed@google.com/*
25d4ba8869476831ee73b15a052af8003d0a1fa2ereed@google.com * Copyright 2012 Google Inc.
35d4ba8869476831ee73b15a052af8003d0a1fa2ereed@google.com *
45d4ba8869476831ee73b15a052af8003d0a1fa2ereed@google.com * Use of this source code is governed by a BSD-style license that can be
55d4ba8869476831ee73b15a052af8003d0a1fa2ereed@google.com * found in the LICENSE file.
65d4ba8869476831ee73b15a052af8003d0a1fa2ereed@google.com */
75d4ba8869476831ee73b15a052af8003d0a1fa2ereed@google.com
8afe3005be3392e43bc51eb7eb2017eefaed85ad1bsalomon#include "SkSurface_Gpu.h"
9afe3005be3392e43bc51eb7eb2017eefaed85ad1bsalomon
105d4ba8869476831ee73b15a052af8003d0a1fa2ereed@google.com#include "SkCanvas.h"
1197b6b0730dcb0feee9224ff04eb3985ca4bd0216robertphillips@google.com#include "SkGpuDevice.h"
12afe3005be3392e43bc51eb7eb2017eefaed85ad1bsalomon#include "SkImage_Base.h"
138b26b99c97473f020df4b9d4ba789e074e06ceddreed#include "SkImage_Gpu.h"
14afe3005be3392e43bc51eb7eb2017eefaed85ad1bsalomon#include "SkImagePriv.h"
15afe3005be3392e43bc51eb7eb2017eefaed85ad1bsalomon#include "SkSurface_Base.h"
165d4ba8869476831ee73b15a052af8003d0a1fa2ereed@google.com
17f037e0bf138a4e842f39e19864d05010a54950c9reed#if SK_SUPPORT_GPU
18f037e0bf138a4e842f39e19864d05010a54950c9reed
1997b6b0730dcb0feee9224ff04eb3985ca4bd0216robertphillips@google.com///////////////////////////////////////////////////////////////////////////////
205d4ba8869476831ee73b15a052af8003d0a1fa2ereed@google.com
21afe3005be3392e43bc51eb7eb2017eefaed85ad1bsalomonSkSurface_Gpu::SkSurface_Gpu(SkGpuDevice* device)
22afe3005be3392e43bc51eb7eb2017eefaed85ad1bsalomon    : INHERITED(device->width(), device->height(), &device->surfaceProps())
23afe3005be3392e43bc51eb7eb2017eefaed85ad1bsalomon    , fDevice(SkRef(device)) {
2497b6b0730dcb0feee9224ff04eb3985ca4bd0216robertphillips@google.com}
255d4ba8869476831ee73b15a052af8003d0a1fa2ereed@google.com
2697b6b0730dcb0feee9224ff04eb3985ca4bd0216robertphillips@google.comSkSurface_Gpu::~SkSurface_Gpu() {
27abcfab4d68d53900ef33320bb2622696c14d14b0kkinnunen    fDevice->unref();
285d4ba8869476831ee73b15a052af8003d0a1fa2ereed@google.com}
295d4ba8869476831ee73b15a052af8003d0a1fa2ereed@google.com
305d4ba8869476831ee73b15a052af8003d0a1fa2ereed@google.comSkCanvas* SkSurface_Gpu::onNewCanvas() {
314a8126e7f81384526629b1e21bf89b632ea13cd9reed    SkCanvas::InitFlags flags = SkCanvas::kDefault_InitFlags;
324a8126e7f81384526629b1e21bf89b632ea13cd9reed    // When we think this works...
334a8126e7f81384526629b1e21bf89b632ea13cd9reed//    flags |= SkCanvas::kConservativeRasterClip_InitFlag;
344a8126e7f81384526629b1e21bf89b632ea13cd9reed
354a8126e7f81384526629b1e21bf89b632ea13cd9reed    return SkNEW_ARGS(SkCanvas, (fDevice, &this->props(), flags));
365d4ba8869476831ee73b15a052af8003d0a1fa2ereed@google.com}
375d4ba8869476831ee73b15a052af8003d0a1fa2ereed@google.com
382bd8b8100529c96c81c30f749f672f4caf775b04reed@google.comSkSurface* SkSurface_Gpu::onNewSurface(const SkImageInfo& info) {
39b8d00db075b5ea09e353508a26ef5ced50722a6ccommit-bot@chromium.org    GrRenderTarget* rt = fDevice->accessRenderTarget();
4097b6b0730dcb0feee9224ff04eb3985ca4bd0216robertphillips@google.com    int sampleCount = rt->numSamples();
41afe3005be3392e43bc51eb7eb2017eefaed85ad1bsalomon    // TODO: Make caller specify this (change virtual signature of onNewSurface).
42afe3005be3392e43bc51eb7eb2017eefaed85ad1bsalomon    static const Budgeted kBudgeted = kNo_Budgeted;
43afe3005be3392e43bc51eb7eb2017eefaed85ad1bsalomon    return SkSurface::NewRenderTarget(fDevice->context(), kBudgeted, info, sampleCount,
44afe3005be3392e43bc51eb7eb2017eefaed85ad1bsalomon                                      &this->props());
455d4ba8869476831ee73b15a052af8003d0a1fa2ereed@google.com}
465d4ba8869476831ee73b15a052af8003d0a1fa2ereed@google.com
47eaaaf0b16c4e55ff8a48c5ac1ed623a6ba469053bsalomonSkImage* SkSurface_Gpu::onNewImageSnapshot(Budgeted budgeted) {
488b26b99c97473f020df4b9d4ba789e074e06ceddreed    const SkImageInfo info = fDevice->imageInfo();
494af267b11964d4a8acdb232ac46094c84d890e88reed    const int sampleCount = fDevice->accessRenderTarget()->numSamples();
508b26b99c97473f020df4b9d4ba789e074e06ceddreed    SkImage* image = NULL;
518b26b99c97473f020df4b9d4ba789e074e06ceddreed    GrTexture* tex = fDevice->accessRenderTarget()->asTexture();
528b26b99c97473f020df4b9d4ba789e074e06ceddreed    if (tex) {
538b26b99c97473f020df4b9d4ba789e074e06ceddreed        image = SkNEW_ARGS(SkImage_Gpu,
548b26b99c97473f020df4b9d4ba789e074e06ceddreed                           (info.width(), info.height(), info.alphaType(),
558b26b99c97473f020df4b9d4ba789e074e06ceddreed                            tex, sampleCount, budgeted));
568b26b99c97473f020df4b9d4ba789e074e06ceddreed    }
574af267b11964d4a8acdb232ac46094c84d890e88reed    if (image) {
584af267b11964d4a8acdb232ac46094c84d890e88reed        as_IB(image)->initWithProps(this->props());
594af267b11964d4a8acdb232ac46094c84d890e88reed    }
604af267b11964d4a8acdb232ac46094c84d890e88reed    return image;
615d4ba8869476831ee73b15a052af8003d0a1fa2ereed@google.com}
625d4ba8869476831ee73b15a052af8003d0a1fa2ereed@google.com
635d4ba8869476831ee73b15a052af8003d0a1fa2ereed@google.comvoid SkSurface_Gpu::onDraw(SkCanvas* canvas, SkScalar x, SkScalar y,
645d4ba8869476831ee73b15a052af8003d0a1fa2ereed@google.com                              const SkPaint* paint) {
6597b6b0730dcb0feee9224ff04eb3985ca4bd0216robertphillips@google.com    canvas->drawBitmap(fDevice->accessBitmap(false), x, y, paint);
6697b6b0730dcb0feee9224ff04eb3985ca4bd0216robertphillips@google.com}
6797b6b0730dcb0feee9224ff04eb3985ca4bd0216robertphillips@google.com
68abcfab4d68d53900ef33320bb2622696c14d14b0kkinnunen// Create a new render target and, if necessary, copy the contents of the old
69abcfab4d68d53900ef33320bb2622696c14d14b0kkinnunen// render target into it. Note that this flushes the SkGpuDevice but
7097b6b0730dcb0feee9224ff04eb3985ca4bd0216robertphillips@google.com// doesn't force an OpenGL flush.
71c4c9870953037be94da00ac9db887d171f6e479ccommit-bot@chromium.orgvoid SkSurface_Gpu::onCopyOnWrite(ContentChangeMode mode) {
72b8d00db075b5ea09e353508a26ef5ced50722a6ccommit-bot@chromium.org    GrRenderTarget* rt = fDevice->accessRenderTarget();
73eaaaf0b16c4e55ff8a48c5ac1ed623a6ba469053bsalomon    // are we sharing our render target with the image? Note this call should never create a new
74eaaaf0b16c4e55ff8a48c5ac1ed623a6ba469053bsalomon    // image because onCopyOnWrite is only called when there is a cached image.
75eaaaf0b16c4e55ff8a48c5ac1ed623a6ba469053bsalomon    SkImage* image = this->getCachedImage(kNo_Budgeted);
76eaaaf0b16c4e55ff8a48c5ac1ed623a6ba469053bsalomon    SkASSERT(image);
778b26b99c97473f020df4b9d4ba789e074e06ceddreed    if (rt->asTexture() == image->getTexture()) {
78abcfab4d68d53900ef33320bb2622696c14d14b0kkinnunen        this->fDevice->replaceRenderTarget(SkSurface::kRetain_ContentChangeMode == mode);
79eaaaf0b16c4e55ff8a48c5ac1ed623a6ba469053bsalomon        SkTextureImageApplyBudgetedDecision(image);
8028361fad1054d59ed4e6a320c7a8b8782a1487c7commit-bot@chromium.org    } else if (kDiscard_ContentChangeMode == mode) {
8128361fad1054d59ed4e6a320c7a8b8782a1487c7commit-bot@chromium.org        this->SkSurface_Gpu::onDiscard();
8297b6b0730dcb0feee9224ff04eb3985ca4bd0216robertphillips@google.com    }
835d4ba8869476831ee73b15a052af8003d0a1fa2ereed@google.com}
845d4ba8869476831ee73b15a052af8003d0a1fa2ereed@google.com
8528361fad1054d59ed4e6a320c7a8b8782a1487c7commit-bot@chromium.orgvoid SkSurface_Gpu::onDiscard() {
8628361fad1054d59ed4e6a320c7a8b8782a1487c7commit-bot@chromium.org    fDevice->accessRenderTarget()->discard();
8728361fad1054d59ed4e6a320c7a8b8782a1487c7commit-bot@chromium.org}
8828361fad1054d59ed4e6a320c7a8b8782a1487c7commit-bot@chromium.org
895d4ba8869476831ee73b15a052af8003d0a1fa2ereed@google.com///////////////////////////////////////////////////////////////////////////////
905d4ba8869476831ee73b15a052af8003d0a1fa2ereed@google.com
914a8126e7f81384526629b1e21bf89b632ea13cd9reedSkSurface* SkSurface::NewRenderTargetDirect(GrRenderTarget* target, const SkSurfaceProps* props) {
92afe3005be3392e43bc51eb7eb2017eefaed85ad1bsalomon    SkAutoTUnref<SkGpuDevice> device(SkGpuDevice::Create(target, props));
93afe3005be3392e43bc51eb7eb2017eefaed85ad1bsalomon    if (!device) {
945d4ba8869476831ee73b15a052af8003d0a1fa2ereed@google.com        return NULL;
955d4ba8869476831ee73b15a052af8003d0a1fa2ereed@google.com    }
96afe3005be3392e43bc51eb7eb2017eefaed85ad1bsalomon    return SkNEW_ARGS(SkSurface_Gpu, (device));
97372b7a4f565354d2101092c6bac6f9550ad506fdreed@google.com}
98fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
99afe3005be3392e43bc51eb7eb2017eefaed85ad1bsalomonSkSurface* SkSurface::NewRenderTarget(GrContext* ctx, Budgeted budgeted, const SkImageInfo& info,
100afe3005be3392e43bc51eb7eb2017eefaed85ad1bsalomon                                      int sampleCount, const SkSurfaceProps* props) {
101afe3005be3392e43bc51eb7eb2017eefaed85ad1bsalomon    SkAutoTUnref<SkGpuDevice> device(SkGpuDevice::Create(ctx, budgeted, info, sampleCount, props,
102afe3005be3392e43bc51eb7eb2017eefaed85ad1bsalomon                                                         SkGpuDevice::kNeedClear_Flag));
103afe3005be3392e43bc51eb7eb2017eefaed85ad1bsalomon    if (!device) {
1045d4ba8869476831ee73b15a052af8003d0a1fa2ereed@google.com        return NULL;
1055d4ba8869476831ee73b15a052af8003d0a1fa2ereed@google.com    }
106afe3005be3392e43bc51eb7eb2017eefaed85ad1bsalomon    return SkNEW_ARGS(SkSurface_Gpu, (device));
1075d4ba8869476831ee73b15a052af8003d0a1fa2ereed@google.com}
108f037e0bf138a4e842f39e19864d05010a54950c9reed
109e4579adfdfb4b9f195d162835a69d9c2a974a6acbsalomonSkSurface* SkSurface::NewWrappedRenderTarget(GrContext* context, GrBackendTextureDesc desc,
110e4579adfdfb4b9f195d162835a69d9c2a974a6acbsalomon                                             const SkSurfaceProps* props) {
111e4579adfdfb4b9f195d162835a69d9c2a974a6acbsalomon    if (NULL == context) {
112e4579adfdfb4b9f195d162835a69d9c2a974a6acbsalomon        return NULL;
113e4579adfdfb4b9f195d162835a69d9c2a974a6acbsalomon    }
114e4579adfdfb4b9f195d162835a69d9c2a974a6acbsalomon    if (!SkToBool(desc.fFlags & kRenderTarget_GrBackendTextureFlag)) {
115e4579adfdfb4b9f195d162835a69d9c2a974a6acbsalomon        return NULL;
116e4579adfdfb4b9f195d162835a69d9c2a974a6acbsalomon    }
117d309e7aa0efa2d5dd7e7b1af97026fcd3a047e98bsalomon    SkAutoTUnref<GrSurface> surface(context->textureProvider()->wrapBackendTexture(desc));
118e4579adfdfb4b9f195d162835a69d9c2a974a6acbsalomon    if (!surface) {
119e4579adfdfb4b9f195d162835a69d9c2a974a6acbsalomon        return NULL;
120e4579adfdfb4b9f195d162835a69d9c2a974a6acbsalomon    }
121e4579adfdfb4b9f195d162835a69d9c2a974a6acbsalomon    SkAutoTUnref<SkGpuDevice> device(SkGpuDevice::Create(surface->asRenderTarget(), props,
122e4579adfdfb4b9f195d162835a69d9c2a974a6acbsalomon                                                         SkGpuDevice::kNeedClear_Flag));
123e4579adfdfb4b9f195d162835a69d9c2a974a6acbsalomon    if (!device) {
124e4579adfdfb4b9f195d162835a69d9c2a974a6acbsalomon        return NULL;
125e4579adfdfb4b9f195d162835a69d9c2a974a6acbsalomon    }
126e4579adfdfb4b9f195d162835a69d9c2a974a6acbsalomon    return SkNEW_ARGS(SkSurface_Gpu, (device));
127e4579adfdfb4b9f195d162835a69d9c2a974a6acbsalomon}
128e4579adfdfb4b9f195d162835a69d9c2a974a6acbsalomon
129f037e0bf138a4e842f39e19864d05010a54950c9reed#endif
130