blob: 72e8e05401fc69158e9fd9f30c0ae0a75e7e748f [file] [log] [blame]
/*
* Copyright 2017 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "SkTypes.h"
#if SK_SUPPORT_GPU
#include "GrContextFactory.h"
#include "GrTest.h"
#include "Test.h"
#include "GrBackendSemaphore.h"
#include "GrBackendSurface.h"
#include "SkCanvas.h"
#include "SkSurface.h"
#ifdef SK_VULKAN
#include "vk/GrVkTypes.h"
#endif
static const int MAIN_W = 8, MAIN_H = 16;
static const int CHILD_W = 16, CHILD_H = 16;
void check_pixels(skiatest::Reporter* reporter, const SkBitmap& bitmap) {
const uint32_t* canvasPixels = static_cast<const uint32_t*>(bitmap.getPixels());
bool failureFound = false;
SkPMColor expectedPixel;
for (int cy = 0; cy < CHILD_H && !failureFound; ++cy) {
for (int cx = 0; cx < CHILD_W && !failureFound; ++cx) {
SkPMColor canvasPixel = canvasPixels[cy * CHILD_W + cx];
if (cy < CHILD_H / 2) {
if (cx < CHILD_W / 2) {
expectedPixel = 0xFF0000FF; // Red
} else {
expectedPixel = 0xFFFF0000; // Blue
}
} else {
expectedPixel = 0xFF00FF00; // Green
}
if (expectedPixel != canvasPixel) {
failureFound = true;
ERRORF(reporter, "Wrong color at %d, %d. Got 0x%08x when we expected 0x%08x",
cx, cy, canvasPixel, expectedPixel);
}
}
}
}
void draw_child(skiatest::Reporter* reporter,
const sk_gpu_test::ContextInfo& childInfo,
const GrBackendObject& backendImage,
const GrBackendSemaphore& semaphore) {
GrBackendTexture backendTexture = GrTest::CreateBackendTexture(childInfo.backend(),
MAIN_W, MAIN_H,
kRGBA_8888_GrPixelConfig,
backendImage);
childInfo.testContext()->makeCurrent();
const SkImageInfo childII = SkImageInfo::Make(CHILD_W, CHILD_H, kRGBA_8888_SkColorType,
kPremul_SkAlphaType);
GrContext* childCtx = childInfo.grContext();
sk_sp<SkSurface> childSurface(SkSurface::MakeRenderTarget(childCtx, SkBudgeted::kNo,
childII, 0, kTopLeft_GrSurfaceOrigin,
nullptr));
sk_sp<SkImage> childImage = SkImage::MakeFromTexture(childCtx,
backendTexture,
kTopLeft_GrSurfaceOrigin,
kPremul_SkAlphaType,
nullptr);
SkCanvas* childCanvas = childSurface->getCanvas();
childCanvas->clear(SK_ColorRED);
childSurface->wait(1, &semaphore);
childCanvas->drawImage(childImage, CHILD_W/2, 0);
SkPaint paint;
paint.setColor(SK_ColorGREEN);
SkIRect rect = SkIRect::MakeLTRB(0, CHILD_H/2, CHILD_W, CHILD_H);
childCanvas->drawIRect(rect, paint);
// read pixels
SkBitmap bitmap;
bitmap.allocPixels(childII);
childCanvas->readPixels(bitmap, 0, 0);
check_pixels(reporter, bitmap);
}
void surface_semaphore_test(skiatest::Reporter* reporter,
const sk_gpu_test::ContextInfo& mainInfo,
const sk_gpu_test::ContextInfo& childInfo1,
const sk_gpu_test::ContextInfo& childInfo2) {
GrContext* mainCtx = mainInfo.grContext();
if (!mainCtx->caps()->fenceSyncSupport()) {
return;
}
const SkImageInfo ii = SkImageInfo::Make(MAIN_W, MAIN_H, kRGBA_8888_SkColorType,
kPremul_SkAlphaType);
sk_sp<SkSurface> mainSurface(SkSurface::MakeRenderTarget(mainCtx, SkBudgeted::kNo,
ii, 0, kTopLeft_GrSurfaceOrigin,
nullptr));
SkCanvas* mainCanvas = mainSurface->getCanvas();
mainCanvas->clear(SK_ColorBLUE);
SkAutoTArray<GrBackendSemaphore> semaphores(2);
mainSurface->flushAndSignalSemaphores(2, semaphores.get());
sk_sp<SkImage> mainImage = mainSurface->makeImageSnapshot();
GrBackendObject backendImage = mainImage->getTextureHandle(false);
draw_child(reporter, childInfo1, backendImage, semaphores[0]);
#ifdef SK_VULKAN
if (kVulkan_GrBackend == mainInfo.backend()) {
// In Vulkan we need to make sure we are sending the correct VkImageLayout in with the
// backendImage. After the first child draw the layout gets changed to SHADER_READ, so
// we just manually set that here.
GrVkImageInfo* vkInfo = (GrVkImageInfo*)backendImage;
vkInfo->updateImageLayout(VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
}
#endif
draw_child(reporter, childInfo2, backendImage, semaphores[1]);
}
DEF_GPUTEST(SurfaceSemaphores, reporter, factory) {
#if defined(SK_BUILD_FOR_UNIX) || defined(SK_BUILD_FOR_WIN) || defined(SK_BUILD_FOR_MAC)
static constexpr auto kNativeGLType = sk_gpu_test::GrContextFactory::kGL_ContextType;
#else
static constexpr auto kNativeGLType = sk_gpu_test::GrContextFactory::kGLES_ContextType;
#endif
for (int typeInt = 0; typeInt < sk_gpu_test::GrContextFactory::kContextTypeCnt; ++typeInt) {
sk_gpu_test::GrContextFactory::ContextType contextType =
(sk_gpu_test::GrContextFactory::ContextType) typeInt;
// Use "native" instead of explicitly trying OpenGL and OpenGL ES. Do not use GLES on
// desktop since tests do not account for not fixing http://skbug.com/2809
if (contextType == sk_gpu_test::GrContextFactory::kGL_ContextType ||
contextType == sk_gpu_test::GrContextFactory::kGLES_ContextType) {
if (contextType != kNativeGLType) {
continue;
}
}
sk_gpu_test::ContextInfo ctxInfo = factory->getContextInfo(
contextType, sk_gpu_test::GrContextFactory::ContextOverrides::kDisableNVPR);
if (!sk_gpu_test::GrContextFactory::IsRenderingContext(contextType)) {
continue;
}
skiatest::ReporterContext ctx(
reporter, SkString(sk_gpu_test::GrContextFactory::ContextTypeName(contextType)));
if (ctxInfo.grContext()) {
sk_gpu_test::ContextInfo child1 = factory->getSharedContextInfo(ctxInfo.grContext(), 0);
sk_gpu_test::ContextInfo child2 = factory->getSharedContextInfo(ctxInfo.grContext(), 1);
if (!child1.grContext() || !child2.grContext()) {
continue;
}
surface_semaphore_test(reporter, ctxInfo, child1, child2);
}
}
}
#endif