1/* 2 * Copyright 2017 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 "SkTypes.h" 9 10#if SK_SUPPORT_GPU 11#include "GrContextFactory.h" 12#include "GrTest.h" 13#include "Test.h" 14 15#include "GrBackendSemaphore.h" 16#include "GrBackendSurface.h" 17#include "SkCanvas.h" 18#include "SkSurface.h" 19 20#ifdef SK_VULKAN 21#include "vk/GrVkTypes.h" 22#endif 23 24static const int MAIN_W = 8, MAIN_H = 16; 25static const int CHILD_W = 16, CHILD_H = 16; 26 27void check_pixels(skiatest::Reporter* reporter, const SkBitmap& bitmap) { 28 const uint32_t* canvasPixels = static_cast<const uint32_t*>(bitmap.getPixels()); 29 30 bool failureFound = false; 31 SkPMColor expectedPixel; 32 for (int cy = 0; cy < CHILD_H && !failureFound; ++cy) { 33 for (int cx = 0; cx < CHILD_W && !failureFound; ++cx) { 34 SkPMColor canvasPixel = canvasPixels[cy * CHILD_W + cx]; 35 if (cy < CHILD_H / 2) { 36 if (cx < CHILD_W / 2) { 37 expectedPixel = 0xFF0000FF; // Red 38 } else { 39 expectedPixel = 0xFFFF0000; // Blue 40 } 41 } else { 42 expectedPixel = 0xFF00FF00; // Green 43 } 44 if (expectedPixel != canvasPixel) { 45 failureFound = true; 46 ERRORF(reporter, "Wrong color at %d, %d. Got 0x%08x when we expected 0x%08x", 47 cx, cy, canvasPixel, expectedPixel); 48 } 49 } 50 } 51} 52 53void draw_child(skiatest::Reporter* reporter, 54 const sk_gpu_test::ContextInfo& childInfo, 55 const GrBackendObject& backendImage, 56 const GrBackendSemaphore& semaphore) { 57 GrBackendTexture backendTexture = GrTest::CreateBackendTexture(childInfo.backend(), 58 MAIN_W, MAIN_H, 59 kRGBA_8888_GrPixelConfig, 60 backendImage); 61 62 childInfo.testContext()->makeCurrent(); 63 64 const SkImageInfo childII = SkImageInfo::Make(CHILD_W, CHILD_H, kRGBA_8888_SkColorType, 65 kPremul_SkAlphaType); 66 67 GrContext* childCtx = childInfo.grContext(); 68 sk_sp<SkSurface> childSurface(SkSurface::MakeRenderTarget(childCtx, SkBudgeted::kNo, 69 childII, 0, kTopLeft_GrSurfaceOrigin, 70 nullptr)); 71 72 sk_sp<SkImage> childImage = SkImage::MakeFromTexture(childCtx, 73 backendTexture, 74 kTopLeft_GrSurfaceOrigin, 75 kPremul_SkAlphaType, 76 nullptr); 77 78 SkCanvas* childCanvas = childSurface->getCanvas(); 79 childCanvas->clear(SK_ColorRED); 80 81 childSurface->wait(1, &semaphore); 82 83 childCanvas->drawImage(childImage, CHILD_W/2, 0); 84 85 SkPaint paint; 86 paint.setColor(SK_ColorGREEN); 87 SkIRect rect = SkIRect::MakeLTRB(0, CHILD_H/2, CHILD_W, CHILD_H); 88 childCanvas->drawIRect(rect, paint); 89 90 // read pixels 91 SkBitmap bitmap; 92 bitmap.allocPixels(childII); 93 childCanvas->readPixels(bitmap, 0, 0); 94 95 check_pixels(reporter, bitmap); 96} 97 98void surface_semaphore_test(skiatest::Reporter* reporter, 99 const sk_gpu_test::ContextInfo& mainInfo, 100 const sk_gpu_test::ContextInfo& childInfo1, 101 const sk_gpu_test::ContextInfo& childInfo2) { 102 GrContext* mainCtx = mainInfo.grContext(); 103 if (!mainCtx->caps()->fenceSyncSupport()) { 104 return; 105 } 106 107 const SkImageInfo ii = SkImageInfo::Make(MAIN_W, MAIN_H, kRGBA_8888_SkColorType, 108 kPremul_SkAlphaType); 109 110 sk_sp<SkSurface> mainSurface(SkSurface::MakeRenderTarget(mainCtx, SkBudgeted::kNo, 111 ii, 0, kTopLeft_GrSurfaceOrigin, 112 nullptr)); 113 SkCanvas* mainCanvas = mainSurface->getCanvas(); 114 mainCanvas->clear(SK_ColorBLUE); 115 116 SkAutoTArray<GrBackendSemaphore> semaphores(2); 117 118 mainSurface->flushAndSignalSemaphores(2, semaphores.get()); 119 120 sk_sp<SkImage> mainImage = mainSurface->makeImageSnapshot(); 121 GrBackendObject backendImage = mainImage->getTextureHandle(false); 122 123 draw_child(reporter, childInfo1, backendImage, semaphores[0]); 124 125#ifdef SK_VULKAN 126 if (kVulkan_GrBackend == mainInfo.backend()) { 127 // In Vulkan we need to make sure we are sending the correct VkImageLayout in with the 128 // backendImage. After the first child draw the layout gets changed to SHADER_READ, so 129 // we just manually set that here. 130 GrVkImageInfo* vkInfo = (GrVkImageInfo*)backendImage; 131 vkInfo->updateImageLayout(VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); 132 } 133#endif 134 135 draw_child(reporter, childInfo2, backendImage, semaphores[1]); 136} 137 138DEF_GPUTEST(SurfaceSemaphores, reporter, factory) { 139#if defined(SK_BUILD_FOR_UNIX) || defined(SK_BUILD_FOR_WIN) || defined(SK_BUILD_FOR_MAC) 140 static constexpr auto kNativeGLType = sk_gpu_test::GrContextFactory::kGL_ContextType; 141#else 142 static constexpr auto kNativeGLType = sk_gpu_test::GrContextFactory::kGLES_ContextType; 143#endif 144 145 for (int typeInt = 0; typeInt < sk_gpu_test::GrContextFactory::kContextTypeCnt; ++typeInt) { 146 sk_gpu_test::GrContextFactory::ContextType contextType = 147 (sk_gpu_test::GrContextFactory::ContextType) typeInt; 148 // Use "native" instead of explicitly trying OpenGL and OpenGL ES. Do not use GLES on 149 // desktop since tests do not account for not fixing http://skbug.com/2809 150 if (contextType == sk_gpu_test::GrContextFactory::kGL_ContextType || 151 contextType == sk_gpu_test::GrContextFactory::kGLES_ContextType) { 152 if (contextType != kNativeGLType) { 153 continue; 154 } 155 } 156 sk_gpu_test::ContextInfo ctxInfo = factory->getContextInfo( 157 contextType, sk_gpu_test::GrContextFactory::ContextOverrides::kDisableNVPR); 158 if (!sk_gpu_test::GrContextFactory::IsRenderingContext(contextType)) { 159 continue; 160 } 161 skiatest::ReporterContext ctx( 162 reporter, SkString(sk_gpu_test::GrContextFactory::ContextTypeName(contextType))); 163 if (ctxInfo.grContext()) { 164 sk_gpu_test::ContextInfo child1 = factory->getSharedContextInfo(ctxInfo.grContext(), 0); 165 sk_gpu_test::ContextInfo child2 = factory->getSharedContextInfo(ctxInfo.grContext(), 1); 166 if (!child1.grContext() || !child2.grContext()) { 167 continue; 168 } 169 170 surface_semaphore_test(reporter, ctxInfo, child1, child2); 171 } 172 } 173} 174 175#endif 176