• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2019 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 #include "tests/Test.h"
9 
10 #include <chrono>
11 #include "include/core/SkSurface.h"
12 #include "include/gpu/GrContext.h"
13 #include "src/gpu/GrContextPriv.h"
14 #include "src/gpu/GrGpu.h"
15 
16 using namespace sk_gpu_test;
17 
testing_finished_proc(void * ctx)18 static void testing_finished_proc(void* ctx) {
19     int* count = (int*)ctx;
20     *count += 1;
21 }
22 
busy_wait_for_callback(int * count,int expectedValue,GrContext * ctx,skiatest::Reporter * reporter)23 static void busy_wait_for_callback(int* count, int expectedValue, GrContext* ctx,
24                                    skiatest::Reporter* reporter) {
25     // Busy waiting should detect that the work is done.
26     auto begin = std::chrono::steady_clock::now();
27     auto end = begin;
28     do {
29         ctx->checkAsyncWorkCompletion();
30         end = std::chrono::steady_clock::now();
31     } while (*count != expectedValue && (end - begin) < std::chrono::seconds(1));
32     if (*count != expectedValue) {
33         ERRORF(reporter, "Expected count failed to reach %d within 1 second of busy waiting.",
34                expectedValue);
35     }
36 }
37 
DEF_GPUTEST_FOR_RENDERING_CONTEXTS(FlushFinishedProcTest,reporter,ctxInfo)38 DEF_GPUTEST_FOR_RENDERING_CONTEXTS(FlushFinishedProcTest, reporter, ctxInfo) {
39     GrContext* ctx = ctxInfo.grContext();
40 
41     SkImageInfo info =
42             SkImageInfo::Make(8, 8, kRGBA_8888_SkColorType, kPremul_SkAlphaType);
43     sk_sp<SkSurface> surface = SkSurface::MakeRenderTarget(ctx, SkBudgeted::kNo, info);
44     SkCanvas* canvas = surface->getCanvas();
45 
46     canvas->clear(SK_ColorGREEN);
47     auto image = surface->makeImageSnapshot();
48 
49     GrFlushInfo flushInfoSyncCpu;
50     flushInfoSyncCpu.fFlags = kSyncCpu_GrFlushFlag;
51     ctx->flush(flushInfoSyncCpu);
52 
53     int count = 0;
54 
55     GrFlushInfo flushInfoFinishedProc;
56     flushInfoFinishedProc.fFinishedProc = testing_finished_proc;
57     flushInfoFinishedProc.fFinishedContext = (void*)&count;
58     // There is no work on the surface so flushing may immediately call the finished proc.
59     surface->flush(SkSurface::BackendSurfaceAccess::kNoAccess, flushInfoFinishedProc);
60     REPORTER_ASSERT(reporter, count == 0 || count == 1);
61     // Busy waiting should detect that the work is done.
62     busy_wait_for_callback(&count, 1, ctx, reporter);
63 
64     canvas->clear(SK_ColorRED);
65 
66     surface->flush(SkSurface::BackendSurfaceAccess::kNoAccess, flushInfoFinishedProc);
67 
68     bool expectAsyncCallback =
69             ctx->backend() == GrBackendApi::kVulkan ||
70             ((ctx->backend() == GrBackendApi::kOpenGL) && ctx->priv().caps()->fenceSyncSupport());
71     if (expectAsyncCallback) {
72         // On Vulkan the command buffer we just submitted may or may not have finished immediately
73         // so the finish proc may not have been called.
74         REPORTER_ASSERT(reporter, count == 1 || count == 2);
75     } else {
76         REPORTER_ASSERT(reporter, count == 2);
77     }
78     ctx->flush(flushInfoSyncCpu);
79     REPORTER_ASSERT(reporter, count == 2);
80 
81     // Test flushing via the SkImage
82     canvas->drawImage(image, 0, 0);
83     image->flush(ctx, flushInfoFinishedProc);
84     if (expectAsyncCallback) {
85         // On Vulkan the command buffer we just submitted may or may not have finished immediately
86         // so the finish proc may not have been called.
87         REPORTER_ASSERT(reporter, count == 2 || count == 3);
88     } else {
89         REPORTER_ASSERT(reporter, count == 3);
90     }
91     ctx->flush(flushInfoSyncCpu);
92     REPORTER_ASSERT(reporter, count == 3);
93 
94     // Test flushing via the GrContext
95     canvas->clear(SK_ColorBLUE);
96     ctx->flush(flushInfoFinishedProc);
97     if (expectAsyncCallback) {
98         // On Vulkan the command buffer we just submitted may or may not have finished immediately
99         // so the finish proc may not have been called.
100         REPORTER_ASSERT(reporter, count == 3 || count == 4);
101     } else {
102         REPORTER_ASSERT(reporter, count == 4);
103     }
104     ctx->flush(flushInfoSyncCpu);
105     REPORTER_ASSERT(reporter, count == 4);
106 
107     // There is no work on the surface so flushing may immediately call the finished proc.
108     ctx->flush(flushInfoFinishedProc);
109     REPORTER_ASSERT(reporter, count == 4 || count == 5);
110     busy_wait_for_callback(&count, 5, ctx, reporter);
111 
112     count = 0;
113     int count2 = 0;
114     canvas->clear(SK_ColorGREEN);
115     surface->flush(SkSurface::BackendSurfaceAccess::kNoAccess, flushInfoFinishedProc);
116     // There is no work to be flushed here so this will return immediately, but make sure the
117     // finished call from this proc isn't called till the previous surface flush also is finished.
118     flushInfoFinishedProc.fFinishedContext = (void*)&count2;
119     ctx->flush(flushInfoFinishedProc);
120     REPORTER_ASSERT(reporter, count <= 1 && count2 <= count);
121 
122     ctx->flush(flushInfoSyncCpu);
123 
124     REPORTER_ASSERT(reporter, count == 1);
125     REPORTER_ASSERT(reporter, count == count2);
126 }
127 
128