Home | History | Annotate | Download | only in tests
      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 
     24 static const int MAIN_W = 8, MAIN_H = 16;
     25 static const int CHILD_W = 16, CHILD_H = 16;
     26 
     27 void 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 
     53 void 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 
     98 void 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 
    138 DEF_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