blob: 3a306ad3e6a882701be4b916e4dc8fe38cc81b35 [file] [log] [blame]
reed@google.com5d4ba882012-07-31 15:45:27 +00001/*
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
bsalomonafe30052015-01-16 07:32:33 -08008#include "SkSurface_Gpu.h"
9
reed@google.com5d4ba882012-07-31 15:45:27 +000010#include "SkCanvas.h"
robertphillips@google.com97b6b072012-10-31 14:48:39 +000011#include "SkGpuDevice.h"
bsalomonafe30052015-01-16 07:32:33 -080012#include "SkImage_Base.h"
reed8b26b992015-05-07 15:36:17 -070013#include "SkImage_Gpu.h"
bsalomonafe30052015-01-16 07:32:33 -080014#include "SkImagePriv.h"
15#include "SkSurface_Base.h"
reed@google.com5d4ba882012-07-31 15:45:27 +000016
reedf037e0b2014-10-30 11:34:15 -070017#if SK_SUPPORT_GPU
18
reed@google.com5d4ba882012-07-31 15:45:27 +000019///////////////////////////////////////////////////////////////////////////////
bsalomonafe30052015-01-16 07:32:33 -080020SkSurface_Gpu::SkSurface_Gpu(SkGpuDevice* device)
21 : INHERITED(device->width(), device->height(), &device->surfaceProps())
22 , fDevice(SkRef(device)) {
robertphillips@google.com97b6b072012-10-31 14:48:39 +000023}
reed@google.com5d4ba882012-07-31 15:45:27 +000024
robertphillips@google.com97b6b072012-10-31 14:48:39 +000025SkSurface_Gpu::~SkSurface_Gpu() {
kkinnunenabcfab42015-02-22 22:53:44 -080026 fDevice->unref();
reed@google.com5d4ba882012-07-31 15:45:27 +000027}
28
reedfa5e68e2015-06-29 07:37:01 -070029GrBackendObject SkSurface_Gpu::onGetTextureHandle(TextureHandleAccess access) {
30 GrRenderTarget* rt = fDevice->accessRenderTarget();
31 switch (access) {
32 case kFlushRead_TextureHandleAccess:
reedfa5e68e2015-06-29 07:37:01 -070033 break;
34 case kFlushWrite_TextureHandleAccess:
reed884200e2015-06-29 09:00:20 -070035 case kDiscardWrite_TextureHandleAccess:
36 // for now we don't special-case on Discard, but we may in the future.
reedfa5e68e2015-06-29 07:37:01 -070037 this->notifyContentWillChange(kRetain_ContentChangeMode);
reeddca20ce2015-07-03 10:43:43 -070038 // legacy: need to dirty the bitmap's genID in our device (curse it)
39 fDevice->fLegacyBitmap.notifyPixelsChanged();
reedfa5e68e2015-06-29 07:37:01 -070040 break;
reedfa5e68e2015-06-29 07:37:01 -070041 }
bsalomonc49e8682015-06-30 11:37:35 -070042 rt->prepareForExternalIO();
reedfa5e68e2015-06-29 07:37:01 -070043 return rt->asTexture()->getTextureHandle();
44}
45
reed@google.com5d4ba882012-07-31 15:45:27 +000046SkCanvas* SkSurface_Gpu::onNewCanvas() {
reed4a8126e2014-09-22 07:29:03 -070047 SkCanvas::InitFlags flags = SkCanvas::kDefault_InitFlags;
48 // When we think this works...
49// flags |= SkCanvas::kConservativeRasterClip_InitFlag;
50
robertphillipsfcf78292015-06-19 11:49:52 -070051 return SkNEW_ARGS(SkCanvas, (fDevice, flags));
reed@google.com5d4ba882012-07-31 15:45:27 +000052}
53
reed@google.com2bd8b812013-11-01 13:46:54 +000054SkSurface* SkSurface_Gpu::onNewSurface(const SkImageInfo& info) {
commit-bot@chromium.orgb8d00db2013-06-26 19:18:23 +000055 GrRenderTarget* rt = fDevice->accessRenderTarget();
vbuzinovdded6962015-06-12 08:59:45 -070056 int sampleCount = rt->numColorSamples();
bsalomonafe30052015-01-16 07:32:33 -080057 // TODO: Make caller specify this (change virtual signature of onNewSurface).
58 static const Budgeted kBudgeted = kNo_Budgeted;
59 return SkSurface::NewRenderTarget(fDevice->context(), kBudgeted, info, sampleCount,
60 &this->props());
reed@google.com5d4ba882012-07-31 15:45:27 +000061}
62
bsalomoneaaaf0b2015-01-23 08:08:04 -080063SkImage* SkSurface_Gpu::onNewImageSnapshot(Budgeted budgeted) {
reed8b26b992015-05-07 15:36:17 -070064 const SkImageInfo info = fDevice->imageInfo();
vbuzinovdded6962015-06-12 08:59:45 -070065 const int sampleCount = fDevice->accessRenderTarget()->numColorSamples();
reed8b26b992015-05-07 15:36:17 -070066 SkImage* image = NULL;
67 GrTexture* tex = fDevice->accessRenderTarget()->asTexture();
68 if (tex) {
69 image = SkNEW_ARGS(SkImage_Gpu,
70 (info.width(), info.height(), info.alphaType(),
71 tex, sampleCount, budgeted));
72 }
reed4af267b2014-11-21 08:46:37 -080073 if (image) {
74 as_IB(image)->initWithProps(this->props());
75 }
76 return image;
reed@google.com5d4ba882012-07-31 15:45:27 +000077}
78
kkinnunenabcfab42015-02-22 22:53:44 -080079// Create a new render target and, if necessary, copy the contents of the old
80// render target into it. Note that this flushes the SkGpuDevice but
robertphillips@google.com97b6b072012-10-31 14:48:39 +000081// doesn't force an OpenGL flush.
commit-bot@chromium.orgc4c98702013-04-22 14:28:01 +000082void SkSurface_Gpu::onCopyOnWrite(ContentChangeMode mode) {
commit-bot@chromium.orgb8d00db2013-06-26 19:18:23 +000083 GrRenderTarget* rt = fDevice->accessRenderTarget();
bsalomoneaaaf0b2015-01-23 08:08:04 -080084 // are we sharing our render target with the image? Note this call should never create a new
85 // image because onCopyOnWrite is only called when there is a cached image.
86 SkImage* image = this->getCachedImage(kNo_Budgeted);
87 SkASSERT(image);
bsalomon55812362015-06-10 08:49:28 -070088 if (rt->asTexture() == as_IB(image)->getTexture()) {
kkinnunenabcfab42015-02-22 22:53:44 -080089 this->fDevice->replaceRenderTarget(SkSurface::kRetain_ContentChangeMode == mode);
bsalomoneaaaf0b2015-01-23 08:08:04 -080090 SkTextureImageApplyBudgetedDecision(image);
commit-bot@chromium.org28361fa2014-03-28 16:08:05 +000091 } else if (kDiscard_ContentChangeMode == mode) {
92 this->SkSurface_Gpu::onDiscard();
robertphillips@google.com97b6b072012-10-31 14:48:39 +000093 }
reed@google.com5d4ba882012-07-31 15:45:27 +000094}
95
commit-bot@chromium.org28361fa2014-03-28 16:08:05 +000096void SkSurface_Gpu::onDiscard() {
97 fDevice->accessRenderTarget()->discard();
98}
99
reed@google.com5d4ba882012-07-31 15:45:27 +0000100///////////////////////////////////////////////////////////////////////////////
101
reed4a8126e2014-09-22 07:29:03 -0700102SkSurface* SkSurface::NewRenderTargetDirect(GrRenderTarget* target, const SkSurfaceProps* props) {
bsalomon74f681d2015-06-23 14:38:48 -0700103 SkAutoTUnref<SkGpuDevice> device(
104 SkGpuDevice::Create(target, props, SkGpuDevice::kUninit_InitContents));
bsalomonafe30052015-01-16 07:32:33 -0800105 if (!device) {
reed@google.com5d4ba882012-07-31 15:45:27 +0000106 return NULL;
107 }
bsalomonafe30052015-01-16 07:32:33 -0800108 return SkNEW_ARGS(SkSurface_Gpu, (device));
reed@google.com5d4ba882012-07-31 15:45:27 +0000109}
110
bsalomonafe30052015-01-16 07:32:33 -0800111SkSurface* SkSurface::NewRenderTarget(GrContext* ctx, Budgeted budgeted, const SkImageInfo& info,
112 int sampleCount, const SkSurfaceProps* props) {
113 SkAutoTUnref<SkGpuDevice> device(SkGpuDevice::Create(ctx, budgeted, info, sampleCount, props,
bsalomon74f681d2015-06-23 14:38:48 -0700114 SkGpuDevice::kClear_InitContents));
bsalomonafe30052015-01-16 07:32:33 -0800115 if (!device) {
reed@google.com5d4ba882012-07-31 15:45:27 +0000116 return NULL;
117 }
bsalomonafe30052015-01-16 07:32:33 -0800118 return SkNEW_ARGS(SkSurface_Gpu, (device));
reed@google.com5d4ba882012-07-31 15:45:27 +0000119}
reedf037e0b2014-10-30 11:34:15 -0700120
bsalomond3e259a2015-06-30 12:04:40 -0700121SkSurface* SkSurface::NewFromBackendTexture(GrContext* context, const GrBackendTextureDesc& desc,
122 const SkSurfaceProps* props) {
bsalomone4579ad2015-04-08 08:38:40 -0700123 if (NULL == context) {
124 return NULL;
125 }
126 if (!SkToBool(desc.fFlags & kRenderTarget_GrBackendTextureFlag)) {
127 return NULL;
128 }
bsalomon6dc6f5f2015-06-18 09:12:16 -0700129 SkAutoTUnref<GrSurface> surface(context->textureProvider()->wrapBackendTexture(desc,
130 kBorrow_GrWrapOwnership));
bsalomone4579ad2015-04-08 08:38:40 -0700131 if (!surface) {
132 return NULL;
133 }
bsalomon74f681d2015-06-23 14:38:48 -0700134 SkAutoTUnref<SkGpuDevice> device(SkGpuDevice::Create(surface->asRenderTarget(), props,
135 SkGpuDevice::kUninit_InitContents));
bsalomone4579ad2015-04-08 08:38:40 -0700136 if (!device) {
137 return NULL;
138 }
139 return SkNEW_ARGS(SkSurface_Gpu, (device));
140}
141
bsalomond3e259a2015-06-30 12:04:40 -0700142SkSurface* SkSurface::NewFromBackendRenderTarget(GrContext* context,
143 const GrBackendRenderTargetDesc& desc,
144 const SkSurfaceProps* props) {
145 if (NULL == context) {
146 return NULL;
147 }
148 SkAutoTUnref<GrRenderTarget> rt(context->textureProvider()->wrapBackendRenderTarget(desc));
149 if (!rt) {
150 return NULL;
151 }
152 SkAutoTUnref<SkGpuDevice> device(SkGpuDevice::Create(rt, props,
153 SkGpuDevice::kUninit_InitContents));
154 if (!device) {
155 return NULL;
156 }
157 return SkNEW_ARGS(SkSurface_Gpu, (device));
158}
159
reedf037e0b2014-10-30 11:34:15 -0700160#endif