|  | /* | 
|  | * Copyright 2015 Google Inc. | 
|  | * | 
|  | * Use of this source code is governed by a BSD-style license that can be | 
|  | * found in the LICENSE file. | 
|  | */ | 
|  |  | 
|  | #include "tests/Test.h" | 
|  |  | 
|  | #ifdef SK_GL | 
|  | #include "include/core/SkAlphaType.h" | 
|  | #include "include/core/SkColor.h" | 
|  | #include "include/core/SkColorSpace.h" | 
|  | #include "include/core/SkColorType.h" | 
|  | #include "include/core/SkImageInfo.h" | 
|  | #include "include/core/SkMatrix.h" | 
|  | #include "include/core/SkPixmap.h" | 
|  | #include "include/core/SkRect.h" | 
|  | #include "include/core/SkRefCnt.h" | 
|  | #include "include/core/SkSamplingOptions.h" | 
|  | #include "include/core/SkTypes.h" | 
|  | #include "include/gpu/GrBackendSurface.h" | 
|  | #include "include/gpu/GrDirectContext.h" | 
|  | #include "include/gpu/GrTypes.h" | 
|  | #include "include/private/SkColorData.h" | 
|  | #include "include/private/SkTemplates.h" | 
|  | #include "include/private/gpu/ganesh/GrTypesPriv.h" | 
|  | #include "src/gpu/Swizzle.h" | 
|  | #include "src/gpu/ganesh/GrCaps.h" | 
|  | #include "src/gpu/ganesh/GrColor.h" | 
|  | #include "src/gpu/ganesh/GrDirectContextPriv.h" | 
|  | #include "src/gpu/ganesh/GrFragmentProcessor.h" | 
|  | #include "src/gpu/ganesh/GrImageInfo.h" | 
|  | #include "src/gpu/ganesh/GrPixmap.h" | 
|  | #include "src/gpu/ganesh/GrProxyProvider.h" | 
|  | #include "src/gpu/ganesh/GrSamplerState.h" | 
|  | #include "src/gpu/ganesh/GrSurfaceProxy.h" | 
|  | #include "src/gpu/ganesh/GrSurfaceProxyView.h" | 
|  | #include "src/gpu/ganesh/GrTexture.h" | 
|  | #include "src/gpu/ganesh/GrTextureProxy.h" | 
|  | #include "src/gpu/ganesh/SkGr.h" | 
|  | #include "src/gpu/ganesh/SurfaceContext.h" | 
|  | #include "src/gpu/ganesh/SurfaceFillContext.h" | 
|  | #include "src/gpu/ganesh/effects/GrTextureEffect.h" | 
|  | #include "src/gpu/ganesh/gl/GrGLDefines_impl.h" | 
|  | #include "tests/CtsEnforcement.h" | 
|  | #include "tests/TestUtils.h" | 
|  | #include "tools/gpu/ProxyUtils.h" | 
|  |  | 
|  | #include <cstdint> | 
|  | #include <initializer_list> | 
|  | #include <memory> | 
|  | #include <utility> | 
|  |  | 
|  | struct GrContextOptions; | 
|  |  | 
|  | // skbug.com/5932 | 
|  | static void test_basic_draw_as_src(skiatest::Reporter* reporter, GrDirectContext* dContext, | 
|  | GrSurfaceProxyView rectView, GrColorType colorType, | 
|  | SkAlphaType alphaType, uint32_t expectedPixelValues[]) { | 
|  | auto sfc = dContext->priv().makeSFC( | 
|  | {colorType, kPremul_SkAlphaType, nullptr, rectView.dimensions()}, /*label=*/{}); | 
|  | for (auto filter : {GrSamplerState::Filter::kNearest, GrSamplerState::Filter::kLinear}) { | 
|  | for (auto mm : {GrSamplerState::MipmapMode::kNone, GrSamplerState::MipmapMode::kLinear}) { | 
|  | sfc->clear(SkPMColor4f::FromBytes_RGBA(0xDDCCBBAA)); | 
|  | auto fp = GrTextureEffect::Make(rectView, alphaType, SkMatrix::I(), filter, mm); | 
|  | sfc->fillWithFP(std::move(fp)); | 
|  | TestReadPixels(reporter, dContext, sfc.get(), expectedPixelValues, | 
|  | "RectangleTexture-basic-draw"); | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | static void test_clear(skiatest::Reporter* reporter, GrDirectContext* dContext, | 
|  | skgpu::v1::SurfaceContext* rectContext) { | 
|  | if (auto sfc = rectContext->asFillContext()) { | 
|  | // Clear the whole thing. | 
|  | GrColor color0 = GrColorPackRGBA(0xA, 0xB, 0xC, 0xD); | 
|  | sfc->clear(SkPMColor4f::FromBytes_RGBA(color0)); | 
|  |  | 
|  | int w = sfc->width(); | 
|  | int h = sfc->height(); | 
|  | int pixelCnt = w * h; | 
|  | SkAutoTMalloc<uint32_t> expectedPixels(pixelCnt); | 
|  |  | 
|  | // The clear color is a GrColor, our readback is to kRGBA_8888, which may be different. | 
|  | uint32_t expectedColor0 = 0; | 
|  | uint8_t* expectedBytes0 = reinterpret_cast<uint8_t*>(&expectedColor0); | 
|  | expectedBytes0[0] = GrColorUnpackR(color0); | 
|  | expectedBytes0[1] = GrColorUnpackG(color0); | 
|  | expectedBytes0[2] = GrColorUnpackB(color0); | 
|  | expectedBytes0[3] = GrColorUnpackA(color0); | 
|  | for (int i = 0; i < sfc->width() * sfc->height(); ++i) { | 
|  | expectedPixels.get()[i] = expectedColor0; | 
|  | } | 
|  |  | 
|  | // Clear the the top to a different color. | 
|  | GrColor color1 = GrColorPackRGBA(0x1, 0x2, 0x3, 0x4); | 
|  | SkIRect rect = SkIRect::MakeWH(w, h/2); | 
|  | sfc->clear(rect, SkPMColor4f::FromBytes_RGBA(color1)); | 
|  |  | 
|  | uint32_t expectedColor1 = 0; | 
|  | uint8_t* expectedBytes1 = reinterpret_cast<uint8_t*>(&expectedColor1); | 
|  | expectedBytes1[0] = GrColorUnpackR(color1); | 
|  | expectedBytes1[1] = GrColorUnpackG(color1); | 
|  | expectedBytes1[2] = GrColorUnpackB(color1); | 
|  | expectedBytes1[3] = GrColorUnpackA(color1); | 
|  |  | 
|  | for (int y = 0; y < h/2; ++y) { | 
|  | for (int x = 0; x < w; ++x) { | 
|  | expectedPixels.get()[y * h + x] = expectedColor1; | 
|  | } | 
|  | } | 
|  |  | 
|  | TestReadPixels(reporter, dContext, sfc, expectedPixels.get(), "RectangleTexture-clear"); | 
|  | } | 
|  | } | 
|  |  | 
|  | static void test_copy_to_surface(skiatest::Reporter* reporter, | 
|  | GrDirectContext* dContext, | 
|  | skgpu::v1::SurfaceContext* dstContext, | 
|  | const char* testName) { | 
|  |  | 
|  | int pixelCnt = dstContext->width() * dstContext->height(); | 
|  | SkAutoTMalloc<uint32_t> pixels(pixelCnt); | 
|  | for (int y = 0; y < dstContext->width(); ++y) { | 
|  | for (int x = 0; x < dstContext->height(); ++x) { | 
|  | pixels.get()[y * dstContext->width() + x] = | 
|  | SkColorToPremulGrColor(SkColorSetARGB(2*y, y, x, x * y)); | 
|  | } | 
|  | } | 
|  |  | 
|  | for (auto renderable : {GrRenderable::kNo, GrRenderable::kYes}) { | 
|  | auto origin = dstContext->origin(); | 
|  | GrImageInfo info(GrColorType::kRGBA_8888, | 
|  | kPremul_SkAlphaType, | 
|  | nullptr, | 
|  | dstContext->dimensions()); | 
|  | GrCPixmap pixmap(info, pixels.get(), dstContext->width()*sizeof(uint32_t)); | 
|  | auto srcView = sk_gpu_test::MakeTextureProxyViewFromData(dContext, | 
|  | renderable, | 
|  | origin, | 
|  | pixmap); | 
|  | // If this assert ever fails we can add a fallback to do copy as draw, but until then we can | 
|  | // be more restrictive. | 
|  | SkAssertResult(dstContext->testCopy(srcView.refProxy())); | 
|  | TestReadPixels(reporter, dContext, dstContext, pixels.get(), testName); | 
|  | } | 
|  | } | 
|  |  | 
|  | DEF_GANESH_TEST_FOR_GL_RENDERING_CONTEXTS(RectangleTexture, | 
|  | reporter, | 
|  | ctxInfo, | 
|  | CtsEnforcement::kApiLevel_T) { | 
|  | auto dContext = ctxInfo.directContext(); | 
|  |  | 
|  | GrProxyProvider* proxyProvider = dContext->priv().proxyProvider(); | 
|  | static const int kWidth = 16; | 
|  | static const int kHeight = 16; | 
|  |  | 
|  | uint32_t pixels[kWidth * kHeight]; | 
|  | for (int y = 0; y < kHeight; ++y) { | 
|  | for (int x = 0; x < kWidth; ++x) { | 
|  | pixels[y * kWidth + x] = y * kWidth + x; | 
|  | } | 
|  | } | 
|  | auto ii = SkImageInfo::Make(kWidth, kHeight, kRGBA_8888_SkColorType, kPremul_SkAlphaType); | 
|  | SkPixmap pm(ii, pixels, sizeof(uint32_t)*kWidth); | 
|  |  | 
|  | for (auto origin : { kBottomLeft_GrSurfaceOrigin, kTopLeft_GrSurfaceOrigin }) { | 
|  |  | 
|  | auto format = GrBackendFormat::MakeGL(GR_GL_RGBA8, GR_GL_TEXTURE_RECTANGLE); | 
|  | GrBackendTexture rectangleTex = dContext->createBackendTexture( | 
|  | kWidth, kHeight, format, GrMipmapped::kNo, GrRenderable::kYes); | 
|  | if (!rectangleTex.isValid()) { | 
|  | continue; | 
|  | } | 
|  |  | 
|  | if (!dContext->updateBackendTexture(rectangleTex, &pm, 1, origin, nullptr, nullptr)) { | 
|  | continue; | 
|  | } | 
|  |  | 
|  | GrColor refPixels[kWidth * kHeight]; | 
|  | for (int y = 0; y < kHeight; ++y) { | 
|  | for (int x = 0; x < kWidth; ++x) { | 
|  | refPixels[y * kWidth + x] = pixels[y * kWidth + x]; | 
|  | } | 
|  | } | 
|  |  | 
|  | sk_sp<GrTextureProxy> rectProxy = proxyProvider->wrapBackendTexture( | 
|  | rectangleTex, kBorrow_GrWrapOwnership, GrWrapCacheable::kNo, kRW_GrIOType); | 
|  |  | 
|  | if (!rectProxy) { | 
|  | dContext->deleteBackendTexture(rectangleTex); | 
|  | continue; | 
|  | } | 
|  |  | 
|  | SkASSERT(rectProxy->mipmapped() == GrMipmapped::kNo); | 
|  | SkASSERT(rectProxy->peekTexture()->mipmapped() == GrMipmapped::kNo); | 
|  |  | 
|  | SkASSERT(rectProxy->textureType() == GrTextureType::kRectangle); | 
|  | SkASSERT(rectProxy->peekTexture()->textureType() == GrTextureType::kRectangle); | 
|  | SkASSERT(rectProxy->hasRestrictedSampling()); | 
|  | SkASSERT(rectProxy->peekTexture()->hasRestrictedSampling()); | 
|  |  | 
|  | GrImageInfo grII = ii; | 
|  | skgpu::Swizzle swizzle = dContext->priv().caps()->getReadSwizzle( | 
|  | rectangleTex.getBackendFormat(), grII.colorType()); | 
|  | GrSurfaceProxyView view(rectProxy, origin, swizzle); | 
|  |  | 
|  | test_basic_draw_as_src(reporter, dContext, view, grII.colorType(), kPremul_SkAlphaType, | 
|  | refPixels); | 
|  |  | 
|  | // Test copy to both a texture and RT | 
|  | TestCopyFromSurface(reporter, dContext, rectProxy, origin, grII.colorType(), refPixels, | 
|  | "RectangleTexture-copy-from"); | 
|  |  | 
|  | auto rectContext = dContext->priv().makeSC(std::move(view), grII.colorInfo()); | 
|  | SkASSERT(rectContext); | 
|  |  | 
|  | TestReadPixels(reporter, dContext, rectContext.get(), refPixels, "RectangleTexture-read"); | 
|  |  | 
|  | test_copy_to_surface(reporter, dContext, rectContext.get(), "RectangleTexture-copy-to"); | 
|  |  | 
|  | TestWritePixels(reporter, dContext, rectContext.get(), true, "RectangleTexture-write"); | 
|  |  | 
|  | test_clear(reporter, dContext, rectContext.get()); | 
|  |  | 
|  | dContext->deleteBackendTexture(rectangleTex); | 
|  | } | 
|  | } | 
|  | #endif |