|  | /* | 
|  | * Copyright 2022 Google LLC | 
|  | * | 
|  | * Use of this source code is governed by a BSD-style license that can be | 
|  | * found in the LICENSE file. | 
|  | */ | 
|  |  | 
|  | #include "include/core/SkAlphaType.h" | 
|  | #include "include/core/SkBitmap.h" | 
|  | #include "include/core/SkCanvas.h" | 
|  | #include "include/core/SkColor.h" | 
|  | #include "include/core/SkColorSpace.h" | 
|  | #include "include/core/SkColorType.h" | 
|  | #include "include/core/SkImageInfo.h" | 
|  | #include "include/core/SkPaint.h" | 
|  | #include "include/core/SkRect.h" | 
|  | #include "include/core/SkRefCnt.h" | 
|  | #include "include/core/SkSurface.h" | 
|  | #include "include/gpu/GpuTypes.h" | 
|  | #include "include/gpu/ganesh/GrBackendSurface.h" | 
|  | #include "include/gpu/ganesh/GrDirectContext.h" | 
|  | #include "include/gpu/ganesh/GrTypes.h" | 
|  | #include "include/gpu/ganesh/SkSurfaceGanesh.h" | 
|  | #include "include/private/gpu/ganesh/GrTypesPriv.h" | 
|  | #include "src/gpu/ganesh/GrDirectContextPriv.h" | 
|  | #include "src/gpu/ganesh/GrUtil.h" | 
|  | #include "tests/CtsEnforcement.h" | 
|  | #include "tests/Test.h" | 
|  |  | 
|  | #include <cstdint> | 
|  |  | 
|  | struct GrContextOptions; | 
|  |  | 
|  | static void check_pixels(skiatest::Reporter* reporter, const SkBitmap& bitmap, | 
|  | GrSurfaceOrigin origin) { | 
|  | const uint32_t* canvasPixels = static_cast<const uint32_t*>(bitmap.getPixels()); | 
|  |  | 
|  | bool failureFound = false; | 
|  | bool foundNonBlue = false; | 
|  |  | 
|  | for (int cy = 0; cy < 8 && !failureFound; ++cy) { | 
|  | int cx = 4; // Just need to check one column; | 
|  | SkPMColor canvasPixel = canvasPixels[cy * 8 + cx]; | 
|  | // We don't know which way the GPU will snap so the non-blue line could either be at row | 
|  | // 3 or 4 since we drew the line at a y value of 4. We check that one of those two values | 
|  | // is green and all the rest are blue. The key thing is that we should not get any red | 
|  | // values since the green line in the saveLayer should snap the same way and overwrite the | 
|  | // red line. | 
|  | if (cy == 3) { | 
|  | if (canvasPixel != 0xFFFF0000 && canvasPixel != 0xFF00FF00) { | 
|  | failureFound = true; | 
|  | ERRORF(reporter, "Wrong color at %d, %d. Got 0x%08x when we expected Blue or Green." | 
|  | " Origin is: %s", | 
|  | cx, cy, canvasPixel, GrSurfaceOriginToStr(origin)); | 
|  | } | 
|  | if (canvasPixel != 0XFFFF0000) { | 
|  | foundNonBlue = true; | 
|  | } | 
|  | } else { | 
|  | SkPMColor expectedPixel; | 
|  | if (cy == 4 && !foundNonBlue) { | 
|  | expectedPixel = 0xFF00FF00; // Green | 
|  | } else { | 
|  | expectedPixel = 0xFFFF0000; // Blue | 
|  | } | 
|  | if (canvasPixel != expectedPixel) { | 
|  | failureFound = true; | 
|  | ERRORF(reporter, | 
|  | "Wrong color at %d, %d. Got 0x%08x when we expected 0x%08x. Origin is: %s", | 
|  | cx, cy, canvasPixel, expectedPixel, GrSurfaceOriginToStr(origin)); | 
|  | } | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | static void run_test(skiatest::Reporter* reporter, | 
|  | GrDirectContext* context, | 
|  | GrSurfaceOrigin origin) { | 
|  | using namespace skgpu; | 
|  |  | 
|  | Protected isProtected = Protected(context->priv().caps()->supportsProtectedContent()); | 
|  |  | 
|  | auto beTexture = context->createBackendTexture(8, | 
|  | 8, | 
|  | kRGBA_8888_SkColorType, | 
|  | Mipmapped::kNo, | 
|  | GrRenderable::kYes, | 
|  | isProtected); | 
|  | REPORTER_ASSERT(reporter, beTexture.isValid()); | 
|  | if (!beTexture.isValid()) { | 
|  | return; | 
|  | } | 
|  |  | 
|  | auto surface = SkSurfaces::WrapBackendTexture( | 
|  | context, beTexture, origin, 0, kRGBA_8888_SkColorType, nullptr, nullptr); | 
|  | REPORTER_ASSERT(reporter, surface); | 
|  | if (!surface) { | 
|  | return; | 
|  | } | 
|  |  | 
|  | SkCanvas* canvas = surface->getCanvas(); | 
|  |  | 
|  | canvas->clear(SK_ColorBLUE); | 
|  |  | 
|  | SkPaint paint; | 
|  | paint.setColor(SK_ColorRED); | 
|  | canvas->drawLine({ 0,4 }, { 8,4 }, paint); | 
|  |  | 
|  | SkRect bounds = SkRect::MakeWH(8, 8); | 
|  | SkPaint layerPaint; | 
|  | canvas->saveLayer(bounds, &paint); | 
|  | paint.setColor(SK_ColorGREEN); | 
|  | canvas->drawLine({ 0,4 }, { 8,4 }, paint); | 
|  | canvas->restore(); | 
|  |  | 
|  | SkBitmap bitmap; | 
|  | bitmap.allocPixels(SkImageInfo::Make(8, 8, kRGBA_8888_SkColorType, kPremul_SkAlphaType)); | 
|  | surface->readPixels(bitmap, 0, 0); | 
|  |  | 
|  | check_pixels(reporter, bitmap, origin); | 
|  |  | 
|  | context->deleteBackendTexture(beTexture); | 
|  | } | 
|  |  | 
|  | DEF_GANESH_TEST_FOR_RENDERING_CONTEXTS(SaveLayerOrigin, | 
|  | reporter, | 
|  | context_info, | 
|  | CtsEnforcement::kApiLevel_T) { | 
|  | GrDirectContext* context = context_info.directContext(); | 
|  | run_test(reporter, context, kBottomLeft_GrSurfaceOrigin); | 
|  | run_test(reporter, context, kTopLeft_GrSurfaceOrigin); | 
|  | } |