1 /* 2 * Copyright 2015 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 "Test.h" 9 #include "TestUtils.h" 10 11 #if SK_SUPPORT_GPU 12 #include "GrClip.h" 13 #include "GrContext.h" 14 #include "GrContextPriv.h" 15 #include "GrProxyProvider.h" 16 #include "GrRenderTargetContext.h" 17 #include "GrTest.h" 18 #include "gl/GLTestContext.h" 19 #include "gl/GrGLGpu.h" 20 #include "gl/GrGLUtil.h" 21 22 // skbug.com/5932 23 static void test_basic_draw_as_src(skiatest::Reporter* reporter, GrContext* context, 24 sk_sp<GrTextureProxy> rectProxy, uint32_t expectedPixelValues[]) { 25 sk_sp<GrRenderTargetContext> rtContext( 26 context->makeDeferredRenderTargetContext(SkBackingFit::kExact, rectProxy->width(), 27 rectProxy->height(), rectProxy->config(), 28 nullptr)); 29 for (auto filter : {GrSamplerState::Filter::kNearest, 30 GrSamplerState::Filter::kBilerp, 31 GrSamplerState::Filter::kMipMap}) { 32 rtContext->clear(nullptr, 0xDDCCBBAA, GrRenderTargetContext::CanClearFullscreen::kYes); 33 auto fp = GrSimpleTextureEffect::Make(rectProxy, SkMatrix::I(), filter); 34 GrPaint paint; 35 paint.setPorterDuffXPFactory(SkBlendMode::kSrc); 36 paint.addColorFragmentProcessor(std::move(fp)); 37 rtContext->drawPaint(GrNoClip(), std::move(paint), SkMatrix::I()); 38 test_read_pixels(reporter, rtContext.get(), expectedPixelValues, 39 "RectangleTexture-basic-draw"); 40 } 41 } 42 43 static void test_clear(skiatest::Reporter* reporter, GrSurfaceContext* rectContext) { 44 if (GrRenderTargetContext* rtc = rectContext->asRenderTargetContext()) { 45 // Clear the whole thing. 46 GrColor color0 = GrColorPackRGBA(0xA, 0xB, 0xC, 0xD); 47 rtc->clear(nullptr, color0, GrRenderTargetContext::CanClearFullscreen::kNo); 48 49 int w = rtc->width(); 50 int h = rtc->height(); 51 int pixelCnt = w * h; 52 SkAutoTMalloc<uint32_t> expectedPixels(pixelCnt); 53 54 // The clear color is a GrColor, our readback is to kRGBA_8888, which may be different. 55 uint32_t expectedColor0 = 0; 56 uint8_t* expectedBytes0 = SkTCast<uint8_t*>(&expectedColor0); 57 expectedBytes0[0] = GrColorUnpackR(color0); 58 expectedBytes0[1] = GrColorUnpackG(color0); 59 expectedBytes0[2] = GrColorUnpackB(color0); 60 expectedBytes0[3] = GrColorUnpackA(color0); 61 for (int i = 0; i < rtc->width() * rtc->height(); ++i) { 62 expectedPixels.get()[i] = expectedColor0; 63 } 64 65 // Clear the the top to a different color. 66 GrColor color1 = GrColorPackRGBA(0x1, 0x2, 0x3, 0x4); 67 SkIRect rect = SkIRect::MakeWH(w, h/2); 68 rtc->clear(&rect, color1, GrRenderTargetContext::CanClearFullscreen::kNo); 69 70 uint32_t expectedColor1 = 0; 71 uint8_t* expectedBytes1 = SkTCast<uint8_t*>(&expectedColor1); 72 expectedBytes1[0] = GrColorUnpackR(color1); 73 expectedBytes1[1] = GrColorUnpackG(color1); 74 expectedBytes1[2] = GrColorUnpackB(color1); 75 expectedBytes1[3] = GrColorUnpackA(color1); 76 77 for (int y = 0; y < h/2; ++y) { 78 for (int x = 0; x < w; ++x) { 79 expectedPixels.get()[y * h + x] = expectedColor1; 80 } 81 } 82 83 test_read_pixels(reporter, rtc, expectedPixels.get(), "RectangleTexture-clear"); 84 } 85 } 86 87 DEF_GPUTEST_FOR_GL_RENDERING_CONTEXTS(RectangleTexture, reporter, ctxInfo) { 88 GrContext* context = ctxInfo.grContext(); 89 GrProxyProvider* proxyProvider = context->contextPriv().proxyProvider(); 90 sk_gpu_test::GLTestContext* glContext = ctxInfo.glContext(); 91 static const int kWidth = 13; 92 static const int kHeight = 13; 93 94 GrColor pixels[kWidth * kHeight]; 95 for (int y = 0; y < kHeight; ++y) { 96 for (int x = 0; x < kWidth; ++x) { 97 pixels[y * kWidth + x] = y * kWidth + x; 98 } 99 } 100 101 for (auto origin : { kBottomLeft_GrSurfaceOrigin, kTopLeft_GrSurfaceOrigin }) { 102 bool useBLOrigin = kBottomLeft_GrSurfaceOrigin == origin; 103 104 GrGLuint rectTexID = glContext->createTextureRectangle(kWidth, kHeight, GR_GL_RGBA, 105 GR_GL_RGBA, GR_GL_UNSIGNED_BYTE, 106 pixels); 107 108 if (!rectTexID) { 109 return; 110 } 111 112 // Let GrContext know that we messed with the GL context directly. 113 context->resetContext(); 114 115 // Wrap the rectangle texture ID in a GrTexture 116 GrGLTextureInfo rectangleInfo; 117 rectangleInfo.fID = rectTexID; 118 rectangleInfo.fTarget = GR_GL_TEXTURE_RECTANGLE; 119 120 GrBackendTexture rectangleTex(kWidth, kHeight, kRGBA_8888_GrPixelConfig, rectangleInfo); 121 122 GrColor refPixels[kWidth * kHeight]; 123 for (int y = 0; y < kHeight; ++y) { 124 for (int x = 0; x < kWidth; ++x) { 125 int y0 = useBLOrigin ? kHeight - y - 1 : y; 126 refPixels[y * kWidth + x] = pixels[y0 * kWidth + x]; 127 } 128 } 129 130 sk_sp<GrTextureProxy> rectProxy = proxyProvider->createWrappedTextureProxy( 131 rectangleTex, origin); 132 133 if (!rectProxy) { 134 ERRORF(reporter, "Error creating proxy for rectangle texture."); 135 GR_GL_CALL(glContext->gl(), DeleteTextures(1, &rectTexID)); 136 continue; 137 } 138 139 test_basic_draw_as_src(reporter, context, rectProxy, refPixels); 140 141 // Test copy to both a texture and RT 142 test_copy_from_surface(reporter, context, rectProxy.get(), refPixels, 143 false, "RectangleTexture-copy-from"); 144 145 sk_sp<GrSurfaceContext> rectContext = context->contextPriv().makeWrappedSurfaceContext( 146 std::move(rectProxy)); 147 SkASSERT(rectContext); 148 149 test_read_pixels(reporter, rectContext.get(), refPixels, "RectangleTexture-read"); 150 151 test_copy_to_surface(reporter, context->contextPriv().proxyProvider(), 152 rectContext.get(), "RectangleTexture-copy-to"); 153 154 test_write_pixels(reporter, rectContext.get(), true, "RectangleTexture-write"); 155 156 test_clear(reporter, rectContext.get()); 157 158 GR_GL_CALL(glContext->gl(), DeleteTextures(1, &rectTexID)); 159 } 160 } 161 162 #endif 163