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
10f7b8b8affec91fcfab0d79199e466c16c254fe56ericrk#include "GrResourceProvider.h"
115d4ba8869476831ee73b15a052af8003d0a1fa2ereed@google.com#include "SkCanvas.h"
1297b6b0730dcb0feee9224ff04eb3985ca4bd0216robertphillips@google.com#include "SkGpuDevice.h"
13afe3005be3392e43bc51eb7eb2017eefaed85ad1bsalomon#include "SkImage_Base.h"
148b26b99c97473f020df4b9d4ba789e074e06ceddreed#include "SkImage_Gpu.h"
15afe3005be3392e43bc51eb7eb2017eefaed85ad1bsalomon#include "SkImagePriv.h"
16afe3005be3392e43bc51eb7eb2017eefaed85ad1bsalomon#include "SkSurface_Base.h"
175d4ba8869476831ee73b15a052af8003d0a1fa2ereed@google.com
18f037e0bf138a4e842f39e19864d05010a54950c9reed#if SK_SUPPORT_GPU
19f037e0bf138a4e842f39e19864d05010a54950c9reed
20afe3005be3392e43bc51eb7eb2017eefaed85ad1bsalomonSkSurface_Gpu::SkSurface_Gpu(SkGpuDevice* device)
21afe3005be3392e43bc51eb7eb2017eefaed85ad1bsalomon    : INHERITED(device->width(), device->height(), &device->surfaceProps())
22afe3005be3392e43bc51eb7eb2017eefaed85ad1bsalomon    , fDevice(SkRef(device)) {
2397b6b0730dcb0feee9224ff04eb3985ca4bd0216robertphillips@google.com}
245d4ba8869476831ee73b15a052af8003d0a1fa2ereed@google.com
2597b6b0730dcb0feee9224ff04eb3985ca4bd0216robertphillips@google.comSkSurface_Gpu::~SkSurface_Gpu() {
26abcfab4d68d53900ef33320bb2622696c14d14b0kkinnunen    fDevice->unref();
275d4ba8869476831ee73b15a052af8003d0a1fa2ereed@google.com}
285d4ba8869476831ee73b15a052af8003d0a1fa2ereed@google.com
2981793410a80b1bb147e765caccdd7fb36e34edf8joshualittstatic GrRenderTarget* prepare_rt_for_external_access(SkSurface_Gpu* surface,
3081793410a80b1bb147e765caccdd7fb36e34edf8joshualitt                                                      SkSurface::BackendHandleAccess access) {
31fa5e68e4b4a10227d3e2c0725b55260175903a80reed    switch (access) {
3281793410a80b1bb147e765caccdd7fb36e34edf8joshualitt        case SkSurface::kFlushRead_BackendHandleAccess:
33fa5e68e4b4a10227d3e2c0725b55260175903a80reed            break;
3481793410a80b1bb147e765caccdd7fb36e34edf8joshualitt        case SkSurface::kFlushWrite_BackendHandleAccess:
3581793410a80b1bb147e765caccdd7fb36e34edf8joshualitt        case SkSurface::kDiscardWrite_BackendHandleAccess:
36884200ef76bbd25ab31e061a24cc8c8268dacca0reed            // for now we don't special-case on Discard, but we may in the future.
3781793410a80b1bb147e765caccdd7fb36e34edf8joshualitt            surface->notifyContentWillChange(SkSurface::kRetain_ContentChangeMode);
38dca20ce4e1a522d6f70c79252a169456b48619dbreed            // legacy: need to dirty the bitmap's genID in our device (curse it)
3981793410a80b1bb147e765caccdd7fb36e34edf8joshualitt            surface->getDevice()->accessBitmap(false).notifyPixelsChanged();
40fa5e68e4b4a10227d3e2c0725b55260175903a80reed            break;
41fa5e68e4b4a10227d3e2c0725b55260175903a80reed    }
42e2639089bddc4fbb129ae039cb12c01be087b397fmalita
43e2639089bddc4fbb129ae039cb12c01be087b397fmalita    // Grab the render target *after* firing notifications, as it may get switched if CoW kicks in.
44e2639089bddc4fbb129ae039cb12c01be087b397fmalita    GrRenderTarget* rt = surface->getDevice()->accessRenderTarget();
45c49e8682ab0614e1b6816dadd00f65d770ab6999bsalomon    rt->prepareForExternalIO();
4681793410a80b1bb147e765caccdd7fb36e34edf8joshualitt    return rt;
4781793410a80b1bb147e765caccdd7fb36e34edf8joshualitt}
4881793410a80b1bb147e765caccdd7fb36e34edf8joshualitt
4981793410a80b1bb147e765caccdd7fb36e34edf8joshualittGrBackendObject SkSurface_Gpu::onGetTextureHandle(BackendHandleAccess access) {
5081793410a80b1bb147e765caccdd7fb36e34edf8joshualitt    GrRenderTarget* rt = prepare_rt_for_external_access(this, access);
5181793410a80b1bb147e765caccdd7fb36e34edf8joshualitt    GrTexture* texture = rt->asTexture();
5281793410a80b1bb147e765caccdd7fb36e34edf8joshualitt    if (texture) {
5381793410a80b1bb147e765caccdd7fb36e34edf8joshualitt        return texture->getTextureHandle();
5481793410a80b1bb147e765caccdd7fb36e34edf8joshualitt    }
5581793410a80b1bb147e765caccdd7fb36e34edf8joshualitt    return 0;
5681793410a80b1bb147e765caccdd7fb36e34edf8joshualitt}
5781793410a80b1bb147e765caccdd7fb36e34edf8joshualitt
5881793410a80b1bb147e765caccdd7fb36e34edf8joshualittbool SkSurface_Gpu::onGetRenderTargetHandle(GrBackendObject* obj, BackendHandleAccess access) {
5981793410a80b1bb147e765caccdd7fb36e34edf8joshualitt    GrRenderTarget* rt = prepare_rt_for_external_access(this, access);
6081793410a80b1bb147e765caccdd7fb36e34edf8joshualitt    *obj = rt->getRenderTargetHandle();
6181793410a80b1bb147e765caccdd7fb36e34edf8joshualitt    return true;
62fa5e68e4b4a10227d3e2c0725b55260175903a80reed}
63fa5e68e4b4a10227d3e2c0725b55260175903a80reed
645d4ba8869476831ee73b15a052af8003d0a1fa2ereed@google.comSkCanvas* SkSurface_Gpu::onNewCanvas() {
654a8126e7f81384526629b1e21bf89b632ea13cd9reed    SkCanvas::InitFlags flags = SkCanvas::kDefault_InitFlags;
66b5b497423c581cda24f65dcc7b274fe79ef79588bsalomon    flags = static_cast<SkCanvas::InitFlags>(flags | SkCanvas::kConservativeRasterClip_InitFlag);
674a8126e7f81384526629b1e21bf89b632ea13cd9reed
68385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary    return new SkCanvas(fDevice, flags);
695d4ba8869476831ee73b15a052af8003d0a1fa2ereed@google.com}
705d4ba8869476831ee73b15a052af8003d0a1fa2ereed@google.com
712bd8b8100529c96c81c30f749f672f4caf775b04reed@google.comSkSurface* SkSurface_Gpu::onNewSurface(const SkImageInfo& info) {
72b8d00db075b5ea09e353508a26ef5ced50722a6ccommit-bot@chromium.org    GrRenderTarget* rt = fDevice->accessRenderTarget();
73dded69693dd3779f081326cde24c3954505b129dvbuzinov    int sampleCount = rt->numColorSamples();
74afe3005be3392e43bc51eb7eb2017eefaed85ad1bsalomon    // TODO: Make caller specify this (change virtual signature of onNewSurface).
755ec26ae9bfca635ccc98283aad5deda11519d826bsalomon    static const SkBudgeted kBudgeted = SkBudgeted::kNo;
76afe3005be3392e43bc51eb7eb2017eefaed85ad1bsalomon    return SkSurface::NewRenderTarget(fDevice->context(), kBudgeted, info, sampleCount,
77afe3005be3392e43bc51eb7eb2017eefaed85ad1bsalomon                                      &this->props());
785d4ba8869476831ee73b15a052af8003d0a1fa2ereed@google.com}
795d4ba8869476831ee73b15a052af8003d0a1fa2ereed@google.com
805ec26ae9bfca635ccc98283aad5deda11519d826bsalomonSkImage* SkSurface_Gpu::onNewImageSnapshot(SkBudgeted budgeted, ForceCopyMode forceCopyMode) {
81f47b9a3b88a037a481eb70f01a4cf9f5be34dc28bsalomon    GrRenderTarget* rt = fDevice->accessRenderTarget();
82f47b9a3b88a037a481eb70f01a4cf9f5be34dc28bsalomon    SkASSERT(rt);
83f47b9a3b88a037a481eb70f01a4cf9f5be34dc28bsalomon    GrTexture* tex = rt->asTexture();
84f47b9a3b88a037a481eb70f01a4cf9f5be34dc28bsalomon    SkAutoTUnref<GrTexture> copy;
85f47b9a3b88a037a481eb70f01a4cf9f5be34dc28bsalomon    // TODO: Force a copy when the rt is an external resource.
86f47b9a3b88a037a481eb70f01a4cf9f5be34dc28bsalomon    if (kYes_ForceCopyMode == forceCopyMode || !tex) {
87f47b9a3b88a037a481eb70f01a4cf9f5be34dc28bsalomon        GrSurfaceDesc desc = fDevice->accessRenderTarget()->desc();
88f47b9a3b88a037a481eb70f01a4cf9f5be34dc28bsalomon        GrContext* ctx = fDevice->context();
89dcceacf57429131b7b4645fadfdb25937bc8ebf5Brian Salomon        desc.fFlags = desc.fFlags & ~kRenderTarget_GrSurfaceFlag;
905ec26ae9bfca635ccc98283aad5deda11519d826bsalomon        copy.reset(ctx->textureProvider()->createTexture(desc, budgeted));
91f47b9a3b88a037a481eb70f01a4cf9f5be34dc28bsalomon        if (!copy) {
92f47b9a3b88a037a481eb70f01a4cf9f5be34dc28bsalomon            return nullptr;
93f47b9a3b88a037a481eb70f01a4cf9f5be34dc28bsalomon        }
94f47b9a3b88a037a481eb70f01a4cf9f5be34dc28bsalomon        if (!ctx->copySurface(copy, rt)) {
95f47b9a3b88a037a481eb70f01a4cf9f5be34dc28bsalomon            return nullptr;
96f47b9a3b88a037a481eb70f01a4cf9f5be34dc28bsalomon        }
97f47b9a3b88a037a481eb70f01a4cf9f5be34dc28bsalomon        tex = copy;
98f47b9a3b88a037a481eb70f01a4cf9f5be34dc28bsalomon    }
998b26b99c97473f020df4b9d4ba789e074e06ceddreed    const SkImageInfo info = fDevice->imageInfo();
10096fcdcc219d2a0d3579719b84b28bede76efba64halcanary    SkImage* image = nullptr;
1018b26b99c97473f020df4b9d4ba789e074e06ceddreed    if (tex) {
102385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary        image = new SkImage_Gpu(info.width(), info.height(), kNeedNewImageUniqueID,
1037b6945bc4e639d7cc4a49b84d492690f8e865566reed                                info.alphaType(), tex, budgeted);
1048b26b99c97473f020df4b9d4ba789e074e06ceddreed    }
1054af267b11964d4a8acdb232ac46094c84d890e88reed    return image;
1065d4ba8869476831ee73b15a052af8003d0a1fa2ereed@google.com}
1075d4ba8869476831ee73b15a052af8003d0a1fa2ereed@google.com
108abcfab4d68d53900ef33320bb2622696c14d14b0kkinnunen// Create a new render target and, if necessary, copy the contents of the old
109abcfab4d68d53900ef33320bb2622696c14d14b0kkinnunen// render target into it. Note that this flushes the SkGpuDevice but
11097b6b0730dcb0feee9224ff04eb3985ca4bd0216robertphillips@google.com// doesn't force an OpenGL flush.
111c4c9870953037be94da00ac9db887d171f6e479ccommit-bot@chromium.orgvoid SkSurface_Gpu::onCopyOnWrite(ContentChangeMode mode) {
112b8d00db075b5ea09e353508a26ef5ced50722a6ccommit-bot@chromium.org    GrRenderTarget* rt = fDevice->accessRenderTarget();
113eaaaf0b16c4e55ff8a48c5ac1ed623a6ba469053bsalomon    // are we sharing our render target with the image? Note this call should never create a new
114eaaaf0b16c4e55ff8a48c5ac1ed623a6ba469053bsalomon    // image because onCopyOnWrite is only called when there is a cached image.
1155ec26ae9bfca635ccc98283aad5deda11519d826bsalomon    SkAutoTUnref<SkImage> image(this->refCachedImage(SkBudgeted::kNo, kNo_ForceUnique));
116eaaaf0b16c4e55ff8a48c5ac1ed623a6ba469053bsalomon    SkASSERT(image);
11755812362f1df3c1f7341f687d5bab0adab8ac954bsalomon    if (rt->asTexture() == as_IB(image)->getTexture()) {
118abcfab4d68d53900ef33320bb2622696c14d14b0kkinnunen        this->fDevice->replaceRenderTarget(SkSurface::kRetain_ContentChangeMode == mode);
119eaaaf0b16c4e55ff8a48c5ac1ed623a6ba469053bsalomon        SkTextureImageApplyBudgetedDecision(image);
12028361fad1054d59ed4e6a320c7a8b8782a1487c7commit-bot@chromium.org    } else if (kDiscard_ContentChangeMode == mode) {
12128361fad1054d59ed4e6a320c7a8b8782a1487c7commit-bot@chromium.org        this->SkSurface_Gpu::onDiscard();
12297b6b0730dcb0feee9224ff04eb3985ca4bd0216robertphillips@google.com    }
1235d4ba8869476831ee73b15a052af8003d0a1fa2ereed@google.com}
1245d4ba8869476831ee73b15a052af8003d0a1fa2ereed@google.com
12528361fad1054d59ed4e6a320c7a8b8782a1487c7commit-bot@chromium.orgvoid SkSurface_Gpu::onDiscard() {
12628361fad1054d59ed4e6a320c7a8b8782a1487c7commit-bot@chromium.org    fDevice->accessRenderTarget()->discard();
12728361fad1054d59ed4e6a320c7a8b8782a1487c7commit-bot@chromium.org}
12828361fad1054d59ed4e6a320c7a8b8782a1487c7commit-bot@chromium.org
129f7b8b8affec91fcfab0d79199e466c16c254fe56ericrkvoid SkSurface_Gpu::onPrepareForExternalIO() {
130f7b8b8affec91fcfab0d79199e466c16c254fe56ericrk    fDevice->accessRenderTarget()->prepareForExternalIO();
131f7b8b8affec91fcfab0d79199e466c16c254fe56ericrk}
132f7b8b8affec91fcfab0d79199e466c16c254fe56ericrk
1335d4ba8869476831ee73b15a052af8003d0a1fa2ereed@google.com///////////////////////////////////////////////////////////////////////////////
1345d4ba8869476831ee73b15a052af8003d0a1fa2ereed@google.com
1354a8126e7f81384526629b1e21bf89b632ea13cd9reedSkSurface* SkSurface::NewRenderTargetDirect(GrRenderTarget* target, const SkSurfaceProps* props) {
13674f681dce2fbadd481596aea15afb3e0fb36ceffbsalomon    SkAutoTUnref<SkGpuDevice> device(
13774f681dce2fbadd481596aea15afb3e0fb36ceffbsalomon        SkGpuDevice::Create(target, props, SkGpuDevice::kUninit_InitContents));
138afe3005be3392e43bc51eb7eb2017eefaed85ad1bsalomon    if (!device) {
13996fcdcc219d2a0d3579719b84b28bede76efba64halcanary        return nullptr;
1405d4ba8869476831ee73b15a052af8003d0a1fa2ereed@google.com    }
141385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary    return new SkSurface_Gpu(device);
142372b7a4f565354d2101092c6bac6f9550ad506fdreed@google.com}
143fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
1445ec26ae9bfca635ccc98283aad5deda11519d826bsalomonSkSurface* SkSurface::NewRenderTarget(GrContext* ctx, SkBudgeted budgeted, const SkImageInfo& info,
1459a1ed5d81dbfc7d5b67b568dfe12b4033a9af154erikchen                                      int sampleCount, const SkSurfaceProps* props,
1469a1ed5d81dbfc7d5b67b568dfe12b4033a9af154erikchen                                      GrTextureStorageAllocator customAllocator) {
1479a1ed5d81dbfc7d5b67b568dfe12b4033a9af154erikchen    SkAutoTUnref<SkGpuDevice> device(SkGpuDevice::Create(
1489a1ed5d81dbfc7d5b67b568dfe12b4033a9af154erikchen            ctx, budgeted, info, sampleCount, props, SkGpuDevice::kClear_InitContents,
1499a1ed5d81dbfc7d5b67b568dfe12b4033a9af154erikchen            customAllocator));
150afe3005be3392e43bc51eb7eb2017eefaed85ad1bsalomon    if (!device) {
15196fcdcc219d2a0d3579719b84b28bede76efba64halcanary        return nullptr;
1525d4ba8869476831ee73b15a052af8003d0a1fa2ereed@google.com    }
153385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary    return new SkSurface_Gpu(device);
1545d4ba8869476831ee73b15a052af8003d0a1fa2ereed@google.com}
155f037e0bf138a4e842f39e19864d05010a54950c9reed
156d3e259a16cf85454f629f5fe75b60b9863c1e138bsalomonSkSurface* SkSurface::NewFromBackendTexture(GrContext* context, const GrBackendTextureDesc& desc,
157d3e259a16cf85454f629f5fe75b60b9863c1e138bsalomon                                            const SkSurfaceProps* props) {
15896fcdcc219d2a0d3579719b84b28bede76efba64halcanary    if (nullptr == context) {
15996fcdcc219d2a0d3579719b84b28bede76efba64halcanary        return nullptr;
160e4579adfdfb4b9f195d162835a69d9c2a974a6acbsalomon    }
161e4579adfdfb4b9f195d162835a69d9c2a974a6acbsalomon    if (!SkToBool(desc.fFlags & kRenderTarget_GrBackendTextureFlag)) {
16296fcdcc219d2a0d3579719b84b28bede76efba64halcanary        return nullptr;
163e4579adfdfb4b9f195d162835a69d9c2a974a6acbsalomon    }
1646dc6f5f4a153d33ed91565cb3cd397a310a937d0bsalomon    SkAutoTUnref<GrSurface> surface(context->textureProvider()->wrapBackendTexture(desc,
1656dc6f5f4a153d33ed91565cb3cd397a310a937d0bsalomon                                    kBorrow_GrWrapOwnership));
166e4579adfdfb4b9f195d162835a69d9c2a974a6acbsalomon    if (!surface) {
16796fcdcc219d2a0d3579719b84b28bede76efba64halcanary        return nullptr;
168e4579adfdfb4b9f195d162835a69d9c2a974a6acbsalomon    }
16974f681dce2fbadd481596aea15afb3e0fb36ceffbsalomon    SkAutoTUnref<SkGpuDevice> device(SkGpuDevice::Create(surface->asRenderTarget(), props,
17074f681dce2fbadd481596aea15afb3e0fb36ceffbsalomon                                                         SkGpuDevice::kUninit_InitContents));
171e4579adfdfb4b9f195d162835a69d9c2a974a6acbsalomon    if (!device) {
17296fcdcc219d2a0d3579719b84b28bede76efba64halcanary        return nullptr;
173e4579adfdfb4b9f195d162835a69d9c2a974a6acbsalomon    }
174385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary    return new SkSurface_Gpu(device);
175e4579adfdfb4b9f195d162835a69d9c2a974a6acbsalomon}
176e4579adfdfb4b9f195d162835a69d9c2a974a6acbsalomon
177d3e259a16cf85454f629f5fe75b60b9863c1e138bsalomonSkSurface* SkSurface::NewFromBackendRenderTarget(GrContext* context,
178d3e259a16cf85454f629f5fe75b60b9863c1e138bsalomon                                                 const GrBackendRenderTargetDesc& desc,
179d3e259a16cf85454f629f5fe75b60b9863c1e138bsalomon                                                 const SkSurfaceProps* props) {
18096fcdcc219d2a0d3579719b84b28bede76efba64halcanary    if (nullptr == context) {
18196fcdcc219d2a0d3579719b84b28bede76efba64halcanary        return nullptr;
182d3e259a16cf85454f629f5fe75b60b9863c1e138bsalomon    }
183d3e259a16cf85454f629f5fe75b60b9863c1e138bsalomon    SkAutoTUnref<GrRenderTarget> rt(context->textureProvider()->wrapBackendRenderTarget(desc));
184d3e259a16cf85454f629f5fe75b60b9863c1e138bsalomon    if (!rt) {
18596fcdcc219d2a0d3579719b84b28bede76efba64halcanary        return nullptr;
186d3e259a16cf85454f629f5fe75b60b9863c1e138bsalomon    }
187d3e259a16cf85454f629f5fe75b60b9863c1e138bsalomon    SkAutoTUnref<SkGpuDevice> device(SkGpuDevice::Create(rt, props,
188d3e259a16cf85454f629f5fe75b60b9863c1e138bsalomon                                                         SkGpuDevice::kUninit_InitContents));
189d3e259a16cf85454f629f5fe75b60b9863c1e138bsalomon    if (!device) {
19096fcdcc219d2a0d3579719b84b28bede76efba64halcanary        return nullptr;
191d3e259a16cf85454f629f5fe75b60b9863c1e138bsalomon    }
192385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary    return new SkSurface_Gpu(device);
193d3e259a16cf85454f629f5fe75b60b9863c1e138bsalomon}
194d3e259a16cf85454f629f5fe75b60b9863c1e138bsalomon
195f7b8b8affec91fcfab0d79199e466c16c254fe56ericrkSkSurface* SkSurface::NewFromBackendTextureAsRenderTarget(GrContext* context,
196f7b8b8affec91fcfab0d79199e466c16c254fe56ericrk                                                          const GrBackendTextureDesc& desc,
197f7b8b8affec91fcfab0d79199e466c16c254fe56ericrk                                                          const SkSurfaceProps* props) {
198f7b8b8affec91fcfab0d79199e466c16c254fe56ericrk    if (nullptr == context) {
199f7b8b8affec91fcfab0d79199e466c16c254fe56ericrk        return nullptr;
200f7b8b8affec91fcfab0d79199e466c16c254fe56ericrk    }
201f7b8b8affec91fcfab0d79199e466c16c254fe56ericrk    SkAutoTUnref<GrRenderTarget> rt(
202f7b8b8affec91fcfab0d79199e466c16c254fe56ericrk            context->resourceProvider()->wrapBackendTextureAsRenderTarget(desc));
203f7b8b8affec91fcfab0d79199e466c16c254fe56ericrk    if (!rt) {
204f7b8b8affec91fcfab0d79199e466c16c254fe56ericrk        return nullptr;
205f7b8b8affec91fcfab0d79199e466c16c254fe56ericrk    }
206f7b8b8affec91fcfab0d79199e466c16c254fe56ericrk    SkAutoTUnref<SkGpuDevice> device(SkGpuDevice::Create(rt, props,
207f7b8b8affec91fcfab0d79199e466c16c254fe56ericrk                                                         SkGpuDevice::kUninit_InitContents));
208f7b8b8affec91fcfab0d79199e466c16c254fe56ericrk    if (!device) {
209f7b8b8affec91fcfab0d79199e466c16c254fe56ericrk        return nullptr;
210f7b8b8affec91fcfab0d79199e466c16c254fe56ericrk    }
211f7b8b8affec91fcfab0d79199e466c16c254fe56ericrk    return new SkSurface_Gpu(device);
212f7b8b8affec91fcfab0d79199e466c16c254fe56ericrk}
213f7b8b8affec91fcfab0d79199e466c16c254fe56ericrk
214f037e0bf138a4e842f39e19864d05010a54950c9reed#endif
215