• 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             ((ctx->backend() == GrBackendApi::kMetal) && ctx->priv().caps()->fenceSyncSupport());
72     if (expectAsyncCallback) {
73         // On Vulkan the command buffer we just submitted may or may not have finished immediately
74         // so the finish proc may not have been called.
75         REPORTER_ASSERT(reporter, count == 1 || count == 2);
76     } else {
77         REPORTER_ASSERT(reporter, count == 2);
78     }
79     ctx->flush(flushInfoSyncCpu);
80     REPORTER_ASSERT(reporter, count == 2);
81 
82     // Test flushing via the SkImage
83     canvas->drawImage(image, 0, 0);
84     image->flush(ctx, flushInfoFinishedProc);
85     if (expectAsyncCallback) {
86         // On Vulkan the command buffer we just submitted may or may not have finished immediately
87         // so the finish proc may not have been called.
88         REPORTER_ASSERT(reporter, count == 2 || count == 3);
89     } else {
90         REPORTER_ASSERT(reporter, count == 3);
91     }
92     ctx->flush(flushInfoSyncCpu);
93     REPORTER_ASSERT(reporter, count == 3);
94 
95     // Test flushing via the GrContext
96     canvas->clear(SK_ColorBLUE);
97     ctx->flush(flushInfoFinishedProc);
98     if (expectAsyncCallback) {
99         // On Vulkan the command buffer we just submitted may or may not have finished immediately
100         // so the finish proc may not have been called.
101         REPORTER_ASSERT(reporter, count == 3 || count == 4);
102     } else {
103         REPORTER_ASSERT(reporter, count == 4);
104     }
105     ctx->flush(flushInfoSyncCpu);
106     REPORTER_ASSERT(reporter, count == 4);
107 
108     // There is no work on the surface so flushing may immediately call the finished proc.
109     ctx->flush(flushInfoFinishedProc);
110     REPORTER_ASSERT(reporter, count == 4 || count == 5);
111     busy_wait_for_callback(&count, 5, ctx, reporter);
112 
113     count = 0;
114     int count2 = 0;
115     canvas->clear(SK_ColorGREEN);
116     surface->flush(SkSurface::BackendSurfaceAccess::kNoAccess, flushInfoFinishedProc);
117     // There is no work to be flushed here so this will return immediately, but make sure the
118     // finished call from this proc isn't called till the previous surface flush also is finished.
119     flushInfoFinishedProc.fFinishedContext = (void*)&count2;
120     ctx->flush(flushInfoFinishedProc);
121     REPORTER_ASSERT(reporter, count <= 1 && count2 <= count);
122 
123     ctx->flush(flushInfoSyncCpu);
124 
125     REPORTER_ASSERT(reporter, count == 1);
126     REPORTER_ASSERT(reporter, count == count2);
127 }
128 
129