1/*
2 * Copyright 2016 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// This is a GPU-backend specific test.
9
10#include "tests/Test.h"
11
12#include "include/gpu/GrBackendSurface.h"
13#include "include/gpu/GrDirectContext.h"
14#include "src/gpu/GrDirectContextPriv.h"
15#include "src/gpu/GrGpu.h"
16#include "src/gpu/GrProxyProvider.h"
17#include "src/gpu/GrRenderTarget.h"
18#include "src/gpu/GrRenderTargetProxy.h"
19#include "src/gpu/GrSurfaceProxy.h"
20#include "src/gpu/GrTexture.h"
21#include "src/gpu/GrTextureProxy.h"
22
23static sk_sp<GrSurfaceProxy> make_wrapped_rt(GrProxyProvider* provider,
24                                             GrGpu* gpu,
25                                             skiatest::Reporter* reporter,
26                                             const SkISize& size,
27                                             GrColorType colorType) {
28    auto backendRT = gpu->createTestingOnlyBackendRenderTarget(size, colorType);
29    return provider->wrapBackendRenderTarget(backendRT, nullptr);
30}
31
32void clean_up_wrapped_rt(GrGpu* gpu, sk_sp<GrSurfaceProxy> proxy) {
33    SkASSERT(proxy->unique());
34    SkASSERT(proxy->peekRenderTarget());
35    GrBackendRenderTarget rt = proxy->peekRenderTarget()->getBackendRenderTarget();
36    proxy.reset();
37    gpu->deleteTestingOnlyBackendRenderTarget(rt);
38}
39
40static sk_sp<GrSurfaceProxy> make_offscreen_rt(GrProxyProvider* provider,
41                                               SkISize dimensions,
42                                               GrColorType colorType) {
43    return provider->testingOnly_createInstantiatedProxy(dimensions, colorType, GrRenderable::kYes,
44                                                         1, SkBackingFit::kExact, SkBudgeted::kYes,
45                                                         GrProtected::kNo);
46}
47
48static sk_sp<GrSurfaceProxy> make_texture(GrProxyProvider* provider,
49                                          SkISize dimensions,
50                                          GrColorType colorType,
51                                          GrRenderable renderable) {
52    return provider->testingOnly_createInstantiatedProxy(dimensions, colorType, renderable, 1,
53                                                         SkBackingFit::kExact, SkBudgeted::kYes,
54                                                         GrProtected::kNo);
55}
56
57// Test converting between RenderTargetProxies and TextureProxies for preinstantiated Proxies
58DEF_GPUTEST_FOR_RENDERING_CONTEXTS(PreinstantiatedProxyConversionTest, reporter, ctxInfo) {
59    auto context = ctxInfo.directContext();
60    GrProxyProvider* proxyProvider = context->priv().proxyProvider();
61    GrGpu* gpu = context->priv().getGpu();
62
63    static constexpr auto kSize = SkISize::Make(64, 64);
64    static constexpr auto kColorType = GrColorType::kRGBA_8888;
65
66    {
67        // External on-screen render target.
68        sk_sp<GrSurfaceProxy> sProxy(
69                make_wrapped_rt(proxyProvider, gpu, reporter, kSize, kColorType));
70        if (sProxy) {
71            // RenderTarget-only
72            GrRenderTargetProxy* rtProxy = sProxy->asRenderTargetProxy();
73            REPORTER_ASSERT(reporter, rtProxy);
74            REPORTER_ASSERT(reporter, !rtProxy->asTextureProxy());
75            REPORTER_ASSERT(reporter, rtProxy->asRenderTargetProxy() == rtProxy);
76            clean_up_wrapped_rt(gpu, std::move(sProxy));
77        }
78    }
79
80    {
81        // Internal offscreen render target.
82        sk_sp<GrSurfaceProxy> sProxy(make_offscreen_rt(proxyProvider, kSize, kColorType));
83        if (sProxy) {
84            // Both RenderTarget and Texture
85            GrRenderTargetProxy* rtProxy = sProxy->asRenderTargetProxy();
86            REPORTER_ASSERT(reporter, rtProxy);
87            GrTextureProxy* tProxy = rtProxy->asTextureProxy();
88            REPORTER_ASSERT(reporter, tProxy);
89            REPORTER_ASSERT(reporter, tProxy->asRenderTargetProxy() == rtProxy);
90            REPORTER_ASSERT(reporter, rtProxy->asRenderTargetProxy() == rtProxy);
91        }
92    }
93
94    {
95        // Internal offscreen render target - but through GrTextureProxy
96        sk_sp<GrSurfaceProxy> sProxy(
97                make_texture(proxyProvider, kSize, kColorType, GrRenderable::kYes));
98        if (sProxy) {
99            // Both RenderTarget and Texture
100            GrTextureProxy* tProxy = sProxy->asTextureProxy();
101            REPORTER_ASSERT(reporter, tProxy);
102            GrRenderTargetProxy* rtProxy = tProxy->asRenderTargetProxy();
103            REPORTER_ASSERT(reporter, rtProxy);
104            REPORTER_ASSERT(reporter, rtProxy->asTextureProxy() == tProxy);
105            REPORTER_ASSERT(reporter, tProxy->asTextureProxy() == tProxy);
106        }
107    }
108
109    {
110        // force no-RT
111        sk_sp<GrSurfaceProxy> sProxy(
112                make_texture(proxyProvider, kSize, kColorType, GrRenderable::kNo));
113        if (sProxy) {
114            // Texture-only
115            GrTextureProxy* tProxy = sProxy->asTextureProxy();
116            REPORTER_ASSERT(reporter, tProxy);
117            REPORTER_ASSERT(reporter, tProxy->asTextureProxy() == tProxy);
118            REPORTER_ASSERT(reporter, !tProxy->asRenderTargetProxy());
119        }
120    }
121}
122
123// Test converting between RenderTargetProxies and TextureProxies for deferred
124// Proxies
125DEF_GPUTEST_FOR_RENDERING_CONTEXTS(DefferredProxyConversionTest, reporter, ctxInfo) {
126    auto context = ctxInfo.directContext();
127    GrProxyProvider* proxyProvider = context->priv().proxyProvider();
128    const GrCaps* caps = context->priv().caps();
129
130    static constexpr SkISize kDims = {64, 64};
131
132    const GrBackendFormat format = caps->getDefaultBackendFormat(GrColorType::kRGBA_8888,
133                                                                 GrRenderable::kYes);
134    {
135        sk_sp<GrTextureProxy> proxy = proxyProvider->createProxy(
136                format, kDims, GrRenderable::kYes, 1, GrMipmapped::kNo, SkBackingFit::kApprox,
137                SkBudgeted::kYes, GrProtected::kNo);
138
139        // Both RenderTarget and Texture
140        GrRenderTargetProxy* rtProxy = proxy->asRenderTargetProxy();
141        REPORTER_ASSERT(reporter, rtProxy);
142        GrTextureProxy* tProxy = rtProxy->asTextureProxy();
143        REPORTER_ASSERT(reporter, tProxy);
144        REPORTER_ASSERT(reporter, tProxy->asRenderTargetProxy() == rtProxy);
145        REPORTER_ASSERT(reporter, rtProxy->asRenderTargetProxy() == rtProxy);
146    }
147
148    {
149        sk_sp<GrTextureProxy> proxy = proxyProvider->createProxy(
150                format, kDims, GrRenderable::kYes, 1, GrMipmapped::kNo, SkBackingFit::kApprox,
151                SkBudgeted::kYes, GrProtected::kNo);
152
153        // Both RenderTarget and Texture - but via GrTextureProxy
154        GrTextureProxy* tProxy = proxy->asTextureProxy();
155        REPORTER_ASSERT(reporter, tProxy);
156        GrRenderTargetProxy* rtProxy = tProxy->asRenderTargetProxy();
157        REPORTER_ASSERT(reporter, rtProxy);
158        REPORTER_ASSERT(reporter, rtProxy->asTextureProxy() == tProxy);
159        REPORTER_ASSERT(reporter, tProxy->asTextureProxy() == tProxy);
160    }
161
162    {
163        sk_sp<GrTextureProxy> proxy = proxyProvider->createProxy(
164                format, kDims, GrRenderable::kNo, 1, GrMipmapped::kNo, SkBackingFit::kApprox,
165                SkBudgeted::kYes, GrProtected::kNo);
166        // Texture-only
167        GrTextureProxy* tProxy = proxy->asTextureProxy();
168        REPORTER_ASSERT(reporter, tProxy);
169        REPORTER_ASSERT(reporter, tProxy->asTextureProxy() == tProxy);
170        REPORTER_ASSERT(reporter, !tProxy->asRenderTargetProxy());
171    }
172}
173