SurfaceTest.cpp revision 175dd9b5e3d7d749738dac743d2ac360b5340187
1995beb6b00afc0e28f5effc8a22a7a3dcb2544e8junov@chromium.org/* 2995beb6b00afc0e28f5effc8a22a7a3dcb2544e8junov@chromium.org * Copyright 2013 Google Inc. 3995beb6b00afc0e28f5effc8a22a7a3dcb2544e8junov@chromium.org * 4995beb6b00afc0e28f5effc8a22a7a3dcb2544e8junov@chromium.org * Use of this source code is governed by a BSD-style license that can be 5995beb6b00afc0e28f5effc8a22a7a3dcb2544e8junov@chromium.org * found in the LICENSE file. 6995beb6b00afc0e28f5effc8a22a7a3dcb2544e8junov@chromium.org */ 74ee16bfaedb14aff8cf102f1f0722ff2529a9699tfarina@chromium.org 8e63ffef6248bd103b5f7827f1e4bc75e47ca9e20bsalomon#include <functional> 9995beb6b00afc0e28f5effc8a22a7a3dcb2544e8junov@chromium.org#include "SkCanvas.h" 104f7c61583b16e3056cf3350fcef42dcc6d3483b7reed@google.com#include "SkData.h" 1141e010cb901c0da9066c4df562030808c9ccd7f8reed#include "SkDevice.h" 1255812362f1df3c1f7341f687d5bab0adab8ac954bsalomon#include "SkImage_Base.h" 13d3ebb48320cf1b7e969974673e4bd7743816985ebungeman#include "SkPath.h" 14995beb6b00afc0e28f5effc8a22a7a3dcb2544e8junov@chromium.org#include "SkRRect.h" 15995beb6b00afc0e28f5effc8a22a7a3dcb2544e8junov@chromium.org#include "SkSurface.h" 164f7c61583b16e3056cf3350fcef42dcc6d3483b7reed@google.com#include "SkUtils.h" 17995beb6b00afc0e28f5effc8a22a7a3dcb2544e8junov@chromium.org#include "Test.h" 18995beb6b00afc0e28f5effc8a22a7a3dcb2544e8junov@chromium.org 19995beb6b00afc0e28f5effc8a22a7a3dcb2544e8junov@chromium.org#if SK_SUPPORT_GPU 20179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen#include "GrContext.h" 21175dd9b5e3d7d749738dac743d2ac360b5340187robertphillips#include "GrDrawContext.h" 22179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen#include "GrGpu.h" 23995beb6b00afc0e28f5effc8a22a7a3dcb2544e8junov@chromium.org#endif 24995beb6b00afc0e28f5effc8a22a7a3dcb2544e8junov@chromium.org 25179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen#include <initializer_list> 2674f681dce2fbadd481596aea15afb3e0fb36ceffbsalomon 27179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunenstatic void release_direct_surface_storage(void* pixels, void* context) { 28982542dce8acbd2f3e7642268b21e76b93230dafreed SkASSERT(pixels == context); 29982542dce8acbd2f3e7642268b21e76b93230dafreed sk_free(pixels); 30982542dce8acbd2f3e7642268b21e76b93230dafreed} 31e8f3062a36d3682f4019309a32b5b84dc9eddf8creedstatic sk_sp<SkSurface> create_surface(SkAlphaType at = kPremul_SkAlphaType, 32e8f3062a36d3682f4019309a32b5b84dc9eddf8creed SkImageInfo* requestedInfo = nullptr) { 3374f681dce2fbadd481596aea15afb3e0fb36ceffbsalomon const SkImageInfo info = SkImageInfo::MakeN32(10, 10, at); 34c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org if (requestedInfo) { 35c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org *requestedInfo = info; 36c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org } 37e8f3062a36d3682f4019309a32b5b84dc9eddf8creed return SkSurface::MakeRaster(info); 38179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen} 39e8f3062a36d3682f4019309a32b5b84dc9eddf8creedstatic sk_sp<SkSurface> create_direct_surface(SkAlphaType at = kPremul_SkAlphaType, 40e8f3062a36d3682f4019309a32b5b84dc9eddf8creed SkImageInfo* requestedInfo = nullptr) { 41179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen const SkImageInfo info = SkImageInfo::MakeN32(10, 10, at); 42179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen if (requestedInfo) { 43179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen *requestedInfo = info; 44179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen } 45179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen const size_t rowBytes = info.minRowBytes(); 46179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen void* storage = sk_malloc_throw(info.getSafeSize(rowBytes)); 47e8f3062a36d3682f4019309a32b5b84dc9eddf8creed return SkSurface::MakeRasterDirectReleaseProc(info, storage, rowBytes, 48e8f3062a36d3682f4019309a32b5b84dc9eddf8creed release_direct_surface_storage, 49e8f3062a36d3682f4019309a32b5b84dc9eddf8creed storage); 50179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen} 51179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen#if SK_SUPPORT_GPU 52e8f3062a36d3682f4019309a32b5b84dc9eddf8creedstatic sk_sp<SkSurface> create_gpu_surface(GrContext* context, SkAlphaType at = kPremul_SkAlphaType, 53e8f3062a36d3682f4019309a32b5b84dc9eddf8creed SkImageInfo* requestedInfo = nullptr) { 54179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen const SkImageInfo info = SkImageInfo::MakeN32(10, 10, at); 55179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen if (requestedInfo) { 56179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen *requestedInfo = info; 57179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen } 58e8f3062a36d3682f4019309a32b5b84dc9eddf8creed return SkSurface::MakeRenderTarget(context, SkBudgeted::kNo, info, 0, nullptr); 59179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen} 60e8f3062a36d3682f4019309a32b5b84dc9eddf8creedstatic sk_sp<SkSurface> create_gpu_scratch_surface(GrContext* context, 61e8f3062a36d3682f4019309a32b5b84dc9eddf8creed SkAlphaType at = kPremul_SkAlphaType, 62e8f3062a36d3682f4019309a32b5b84dc9eddf8creed SkImageInfo* requestedInfo = nullptr) { 63179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen const SkImageInfo info = SkImageInfo::MakeN32(10, 10, at); 64179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen if (requestedInfo) { 65179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen *requestedInfo = info; 66995beb6b00afc0e28f5effc8a22a7a3dcb2544e8junov@chromium.org } 67e8f3062a36d3682f4019309a32b5b84dc9eddf8creed return SkSurface::MakeRenderTarget(context, SkBudgeted::kYes, info, 0, nullptr); 68995beb6b00afc0e28f5effc8a22a7a3dcb2544e8junov@chromium.org} 69179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen#endif 70995beb6b00afc0e28f5effc8a22a7a3dcb2544e8junov@chromium.org 71179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunenDEF_TEST(SurfaceEmpty, reporter) { 72b2497c2d945c0a5d770865b026e2d5947bf37c91reed const SkImageInfo info = SkImageInfo::Make(0, 0, kN32_SkColorType, kPremul_SkAlphaType); 73e8f3062a36d3682f4019309a32b5b84dc9eddf8creed REPORTER_ASSERT(reporter, nullptr == SkSurface::MakeRaster(info)); 74e8f3062a36d3682f4019309a32b5b84dc9eddf8creed REPORTER_ASSERT(reporter, nullptr == SkSurface::MakeRasterDirect(info, nullptr, 0)); 75b2497c2d945c0a5d770865b026e2d5947bf37c91reed 76179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen} 77e4579adfdfb4b9f195d162835a69d9c2a974a6acbsalomon#if SK_SUPPORT_GPU 78758586c7f11a6b3529bd4a1c9b4e982a0d0b0582bsalomonDEF_GPUTEST_FOR_GL_RENDERING_CONTEXTS(SurfaceEmpty_Gpu, reporter, ctxInfo) { 79179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen const SkImageInfo info = SkImageInfo::Make(0, 0, kN32_SkColorType, kPremul_SkAlphaType); 80179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen REPORTER_ASSERT(reporter, nullptr == 81f2f1c17e331fe1e0ce695969970ecebc81e12cebbsalomon SkSurface::MakeRenderTarget(ctxInfo.fGrContext, SkBudgeted::kNo, info, 0, 82f2f1c17e331fe1e0ce695969970ecebc81e12cebbsalomon nullptr)); 83179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen} 84179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen#endif 857a61793d9603f07a9039b5abf814eb25842e211bbsalomon 86179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen#if SK_SUPPORT_GPU 87758586c7f11a6b3529bd4a1c9b4e982a0d0b0582bsalomonDEF_GPUTEST_FOR_GL_RENDERING_CONTEXTS(SurfaceWrappedTexture, reporter, ctxInfo) { 88f2f1c17e331fe1e0ce695969970ecebc81e12cebbsalomon GrGpu* gpu = ctxInfo.fGrContext->getGpu(); 89672bb7fc6640e3fc68107354ed4ae45a2a1e2d29jvanverth if (!gpu) { 907a61793d9603f07a9039b5abf814eb25842e211bbsalomon return; 917a61793d9603f07a9039b5abf814eb25842e211bbsalomon } 927a61793d9603f07a9039b5abf814eb25842e211bbsalomon 93672bb7fc6640e3fc68107354ed4ae45a2a1e2d29jvanverth // Test the wrapped factory for SkSurface by creating a backend texture and then wrap it in 9481793410a80b1bb147e765caccdd7fb36e34edf8joshualitt // a SkSurface. 9581793410a80b1bb147e765caccdd7fb36e34edf8joshualitt static const int kW = 100; 9681793410a80b1bb147e765caccdd7fb36e34edf8joshualitt static const int kH = 100; 9781793410a80b1bb147e765caccdd7fb36e34edf8joshualitt static const uint32_t kOrigColor = 0xFFAABBCC; 9881793410a80b1bb147e765caccdd7fb36e34edf8joshualitt SkAutoTArray<uint32_t> pixels(kW * kH); 9981793410a80b1bb147e765caccdd7fb36e34edf8joshualitt sk_memset32(pixels.get(), kOrigColor, kW * kH); 100091f60c2a0e4504c017b8a67ff96a0e829519b14bsalomon GrBackendObject texHandle = gpu->createTestingOnlyBackendTexture(pixels.get(), kW, kH, 101091f60c2a0e4504c017b8a67ff96a0e829519b14bsalomon kRGBA_8888_GrPixelConfig); 10281793410a80b1bb147e765caccdd7fb36e34edf8joshualitt 10381793410a80b1bb147e765caccdd7fb36e34edf8joshualitt GrBackendTextureDesc wrappedDesc; 10481793410a80b1bb147e765caccdd7fb36e34edf8joshualitt wrappedDesc.fConfig = kRGBA_8888_GrPixelConfig; 10581793410a80b1bb147e765caccdd7fb36e34edf8joshualitt wrappedDesc.fWidth = kW; 10681793410a80b1bb147e765caccdd7fb36e34edf8joshualitt wrappedDesc.fHeight = kH; 10781793410a80b1bb147e765caccdd7fb36e34edf8joshualitt wrappedDesc.fOrigin = kBottomLeft_GrSurfaceOrigin; 10881793410a80b1bb147e765caccdd7fb36e34edf8joshualitt wrappedDesc.fSampleCnt = 0; 10981793410a80b1bb147e765caccdd7fb36e34edf8joshualitt wrappedDesc.fFlags = kRenderTarget_GrBackendTextureFlag; 110091f60c2a0e4504c017b8a67ff96a0e829519b14bsalomon wrappedDesc.fTextureHandle = texHandle; 11181793410a80b1bb147e765caccdd7fb36e34edf8joshualitt 112f2f1c17e331fe1e0ce695969970ecebc81e12cebbsalomon auto surface(SkSurface::MakeFromBackendTexture(ctxInfo.fGrContext, wrappedDesc, nullptr)); 11381793410a80b1bb147e765caccdd7fb36e34edf8joshualitt REPORTER_ASSERT(reporter, surface); 11481793410a80b1bb147e765caccdd7fb36e34edf8joshualitt if (surface) { 11581793410a80b1bb147e765caccdd7fb36e34edf8joshualitt // Validate that we can draw to the canvas and that the original texture color is preserved 11681793410a80b1bb147e765caccdd7fb36e34edf8joshualitt // in pixels that aren't rendered to via the surface. 11781793410a80b1bb147e765caccdd7fb36e34edf8joshualitt SkPaint paint; 11881793410a80b1bb147e765caccdd7fb36e34edf8joshualitt static const SkColor kRectColor = ~kOrigColor | 0xFF000000; 11981793410a80b1bb147e765caccdd7fb36e34edf8joshualitt paint.setColor(kRectColor); 12081793410a80b1bb147e765caccdd7fb36e34edf8joshualitt surface->getCanvas()->drawRect(SkRect::MakeWH(SkIntToScalar(kW), SkIntToScalar(kH)/2), 12181793410a80b1bb147e765caccdd7fb36e34edf8joshualitt paint); 12281793410a80b1bb147e765caccdd7fb36e34edf8joshualitt SkImageInfo readInfo = SkImageInfo::MakeN32Premul(kW, kH); 12381793410a80b1bb147e765caccdd7fb36e34edf8joshualitt surface->readPixels(readInfo, pixels.get(), kW * sizeof(uint32_t), 0, 0); 12481793410a80b1bb147e765caccdd7fb36e34edf8joshualitt bool stop = false; 12581793410a80b1bb147e765caccdd7fb36e34edf8joshualitt SkPMColor origColorPM = SkPackARGB32((kOrigColor >> 24 & 0xFF), 12681793410a80b1bb147e765caccdd7fb36e34edf8joshualitt (kOrigColor >> 0 & 0xFF), 12781793410a80b1bb147e765caccdd7fb36e34edf8joshualitt (kOrigColor >> 8 & 0xFF), 12881793410a80b1bb147e765caccdd7fb36e34edf8joshualitt (kOrigColor >> 16 & 0xFF)); 12981793410a80b1bb147e765caccdd7fb36e34edf8joshualitt SkPMColor rectColorPM = SkPackARGB32((kRectColor >> 24 & 0xFF), 13081793410a80b1bb147e765caccdd7fb36e34edf8joshualitt (kRectColor >> 16 & 0xFF), 13181793410a80b1bb147e765caccdd7fb36e34edf8joshualitt (kRectColor >> 8 & 0xFF), 13281793410a80b1bb147e765caccdd7fb36e34edf8joshualitt (kRectColor >> 0 & 0xFF)); 13381793410a80b1bb147e765caccdd7fb36e34edf8joshualitt for (int y = 0; y < kH/2 && !stop; ++y) { 13481793410a80b1bb147e765caccdd7fb36e34edf8joshualitt for (int x = 0; x < kW && !stop; ++x) { 13581793410a80b1bb147e765caccdd7fb36e34edf8joshualitt REPORTER_ASSERT(reporter, rectColorPM == pixels[x + y * kW]); 13681793410a80b1bb147e765caccdd7fb36e34edf8joshualitt if (rectColorPM != pixels[x + y * kW]) { 13781793410a80b1bb147e765caccdd7fb36e34edf8joshualitt stop = true; 1387a61793d9603f07a9039b5abf814eb25842e211bbsalomon } 1397a61793d9603f07a9039b5abf814eb25842e211bbsalomon } 14081793410a80b1bb147e765caccdd7fb36e34edf8joshualitt } 14181793410a80b1bb147e765caccdd7fb36e34edf8joshualitt stop = false; 14281793410a80b1bb147e765caccdd7fb36e34edf8joshualitt for (int y = kH/2; y < kH && !stop; ++y) { 14381793410a80b1bb147e765caccdd7fb36e34edf8joshualitt for (int x = 0; x < kW && !stop; ++x) { 14481793410a80b1bb147e765caccdd7fb36e34edf8joshualitt REPORTER_ASSERT(reporter, origColorPM == pixels[x + y * kW]); 14581793410a80b1bb147e765caccdd7fb36e34edf8joshualitt if (origColorPM != pixels[x + y * kW]) { 14681793410a80b1bb147e765caccdd7fb36e34edf8joshualitt stop = true; 1477a61793d9603f07a9039b5abf814eb25842e211bbsalomon } 1487a61793d9603f07a9039b5abf814eb25842e211bbsalomon } 1497a61793d9603f07a9039b5abf814eb25842e211bbsalomon } 1507a61793d9603f07a9039b5abf814eb25842e211bbsalomon } 15167d7620285cdfa60158add6615db03bd48e6d8b0bsalomon gpu->deleteTestingOnlyBackendTexture(texHandle); 152e4579adfdfb4b9f195d162835a69d9c2a974a6acbsalomon} 153e4579adfdfb4b9f195d162835a69d9c2a974a6acbsalomon#endif 154e4579adfdfb4b9f195d162835a69d9c2a974a6acbsalomon 155179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunenstatic void test_canvas_peek(skiatest::Reporter* reporter, 156e8f3062a36d3682f4019309a32b5b84dc9eddf8creed sk_sp<SkSurface>& surface, 157179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen const SkImageInfo& requestInfo, 158179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen bool expectPeekSuccess) { 159c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org const SkColor color = SK_ColorRED; 160c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org const SkPMColor pmcolor = SkPreMultiplyColor(color); 161179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen surface->getCanvas()->clear(color); 162179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen 1636ceeebd37a43d879c120b6ba100ae1febdd67a18reed SkPixmap pmap; 1646ceeebd37a43d879c120b6ba100ae1febdd67a18reed bool success = surface->getCanvas()->peekPixels(&pmap); 165179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen REPORTER_ASSERT(reporter, expectPeekSuccess == success); 166179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen 1676ceeebd37a43d879c120b6ba100ae1febdd67a18reed SkPixmap pmap2; 1686ceeebd37a43d879c120b6ba100ae1febdd67a18reed const void* addr2 = surface->peekPixels(&pmap2) ? pmap2.addr() : nullptr; 169179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen 170179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen if (success) { 1716ceeebd37a43d879c120b6ba100ae1febdd67a18reed REPORTER_ASSERT(reporter, requestInfo == pmap.info()); 1726ceeebd37a43d879c120b6ba100ae1febdd67a18reed REPORTER_ASSERT(reporter, requestInfo.minRowBytes() <= pmap.rowBytes()); 1736ceeebd37a43d879c120b6ba100ae1febdd67a18reed REPORTER_ASSERT(reporter, pmcolor == *pmap.addr32()); 174179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen 1756ceeebd37a43d879c120b6ba100ae1febdd67a18reed REPORTER_ASSERT(reporter, pmap.addr() == pmap2.addr()); 1766ceeebd37a43d879c120b6ba100ae1febdd67a18reed REPORTER_ASSERT(reporter, pmap.info() == pmap2.info()); 1776ceeebd37a43d879c120b6ba100ae1febdd67a18reed REPORTER_ASSERT(reporter, pmap.rowBytes() == pmap2.rowBytes()); 178179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen } else { 179179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen REPORTER_ASSERT(reporter, nullptr == addr2); 180179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen } 181179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen} 182179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunenDEF_TEST(SurfaceCanvasPeek, reporter) { 183179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen for (auto& surface_func : { &create_surface, &create_direct_surface }) { 184179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen SkImageInfo requestInfo; 185e8f3062a36d3682f4019309a32b5b84dc9eddf8creed auto surface(surface_func(kPremul_SkAlphaType, &requestInfo)); 186179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen test_canvas_peek(reporter, surface, requestInfo, true); 187179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen } 188179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen} 189e904c09a3a9c701e8d91f2f6ee161feda7615d90bsalomon#if SK_SUPPORT_GPU 190758586c7f11a6b3529bd4a1c9b4e982a0d0b0582bsalomonDEF_GPUTEST_FOR_GL_RENDERING_CONTEXTS(SurfaceCanvasPeek_Gpu, reporter, ctxInfo) { 191179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen for (auto& surface_func : { &create_gpu_surface, &create_gpu_scratch_surface }) { 192179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen SkImageInfo requestInfo; 193f2f1c17e331fe1e0ce695969970ecebc81e12cebbsalomon auto surface(surface_func(ctxInfo.fGrContext, kPremul_SkAlphaType, &requestInfo)); 194179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen test_canvas_peek(reporter, surface, requestInfo, false); 195c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org } 196c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org} 197179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen#endif 198c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org 19941e010cb901c0da9066c4df562030808c9ccd7f8reed// For compatibility with clients that still call accessBitmap(), we need to ensure that we bump 20041e010cb901c0da9066c4df562030808c9ccd7f8reed// the bitmap's genID when we draw to it, else they won't know it has new values. When they are 20141e010cb901c0da9066c4df562030808c9ccd7f8reed// exclusively using surface/image, and we can hide accessBitmap from device, we can remove this 20241e010cb901c0da9066c4df562030808c9ccd7f8reed// test. 203e8f3062a36d3682f4019309a32b5b84dc9eddf8creedvoid test_access_pixels(skiatest::Reporter* reporter, const sk_sp<SkSurface>& surface) { 204179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen SkCanvas* canvas = surface->getCanvas(); 205179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen canvas->clear(0); 206179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen 207179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen SkBaseDevice* device = canvas->getDevice_just_for_deprecated_compatibility_testing(); 208179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen SkBitmap bm = device->accessBitmap(false); 209179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen uint32_t genID0 = bm.getGenerationID(); 210179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen // Now we draw something, which needs to "dirty" the genID (sorta like copy-on-write) 211179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen canvas->drawColor(SK_ColorBLUE); 212179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen // Now check that we get a different genID 213179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen uint32_t genID1 = bm.getGenerationID(); 214179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen REPORTER_ASSERT(reporter, genID0 != genID1); 215179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen} 216179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunenDEF_TEST(SurfaceAccessPixels, reporter) { 217179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen for (auto& surface_func : { &create_surface, &create_direct_surface }) { 218e8f3062a36d3682f4019309a32b5b84dc9eddf8creed auto surface(surface_func(kPremul_SkAlphaType, nullptr)); 219179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen test_access_pixels(reporter, surface); 220179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen } 221179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen} 22241e010cb901c0da9066c4df562030808c9ccd7f8reed#if SK_SUPPORT_GPU 223758586c7f11a6b3529bd4a1c9b4e982a0d0b0582bsalomonDEF_GPUTEST_FOR_GL_RENDERING_CONTEXTS(SurfaceAccessPixels_Gpu, reporter, ctxInfo) { 224179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen for (auto& surface_func : { &create_gpu_surface, &create_gpu_scratch_surface }) { 225f2f1c17e331fe1e0ce695969970ecebc81e12cebbsalomon auto surface(surface_func(ctxInfo.fGrContext, kPremul_SkAlphaType, nullptr)); 226179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen test_access_pixels(reporter, surface); 227179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen } 228179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen} 22941e010cb901c0da9066c4df562030808c9ccd7f8reed#endif 230179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen 231e8f3062a36d3682f4019309a32b5b84dc9eddf8creedstatic void test_snapshot_alphatype(skiatest::Reporter* reporter, const sk_sp<SkSurface>& surface, 232179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen bool expectOpaque) { 233179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen REPORTER_ASSERT(reporter, surface); 234179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen if (surface) { 2359ce9d6772df650ceb0511f275e1a83dffa78ff72reed sk_sp<SkImage> image(surface->makeImageSnapshot()); 236179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen REPORTER_ASSERT(reporter, image); 237179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen if (image) { 238179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen REPORTER_ASSERT(reporter, image->isOpaque() == SkToBool(expectOpaque)); 23941e010cb901c0da9066c4df562030808c9ccd7f8reed } 240179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen } 241179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen} 242179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunenDEF_TEST(SurfaceSnapshotAlphaType, reporter) { 243179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen for (auto& surface_func : { &create_surface, &create_direct_surface }) { 244179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen for (auto& isOpaque : { true, false }) { 245179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen SkAlphaType alphaType = isOpaque ? kOpaque_SkAlphaType : kPremul_SkAlphaType; 246e8f3062a36d3682f4019309a32b5b84dc9eddf8creed auto surface(surface_func(alphaType, nullptr)); 247179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen test_snapshot_alphatype(reporter, surface, isOpaque); 24841e010cb901c0da9066c4df562030808c9ccd7f8reed } 24941e010cb901c0da9066c4df562030808c9ccd7f8reed } 25041e010cb901c0da9066c4df562030808c9ccd7f8reed} 25174f681dce2fbadd481596aea15afb3e0fb36ceffbsalomon#if SK_SUPPORT_GPU 252758586c7f11a6b3529bd4a1c9b4e982a0d0b0582bsalomonDEF_GPUTEST_FOR_GL_RENDERING_CONTEXTS(SurfaceSnapshotAlphaType_Gpu, reporter, ctxInfo) { 253179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen for (auto& surface_func : { &create_gpu_surface, &create_gpu_scratch_surface }) { 254179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen for (auto& isOpaque : { true, false }) { 255179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen SkAlphaType alphaType = isOpaque ? kOpaque_SkAlphaType : kPremul_SkAlphaType; 256f2f1c17e331fe1e0ce695969970ecebc81e12cebbsalomon auto surface(surface_func(ctxInfo.fGrContext, alphaType, nullptr)); 257179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen test_snapshot_alphatype(reporter, surface, isOpaque); 258179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen } 25974f681dce2fbadd481596aea15afb3e0fb36ceffbsalomon } 260179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen} 26174f681dce2fbadd481596aea15afb3e0fb36ceffbsalomon#endif 262179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen 263179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunenstatic GrBackendObject get_surface_backend_texture_handle( 264179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen SkSurface* s, SkSurface::BackendHandleAccess a) { 265179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen return s->getTextureHandle(a); 266179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen} 267179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunenstatic GrBackendObject get_surface_backend_render_target_handle( 268179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen SkSurface* s, SkSurface::BackendHandleAccess a) { 269179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen GrBackendObject result; 270179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen if (!s->getRenderTargetHandle(&result, a)) { 271179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen return 0; 27274f681dce2fbadd481596aea15afb3e0fb36ceffbsalomon } 273179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen return result; 27474f681dce2fbadd481596aea15afb3e0fb36ceffbsalomon} 27574f681dce2fbadd481596aea15afb3e0fb36ceffbsalomon 276179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunenstatic void test_backend_handle_access_copy_on_write( 277179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen skiatest::Reporter* reporter, SkSurface* surface, SkSurface::BackendHandleAccess mode, 278179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen GrBackendObject (*func)(SkSurface*, SkSurface::BackendHandleAccess)) { 279e2639089bddc4fbb129ae039cb12c01be087b397fmalita GrBackendObject obj1 = func(surface, mode); 2809ce9d6772df650ceb0511f275e1a83dffa78ff72reed sk_sp<SkImage> snap1(surface->makeImageSnapshot()); 281e2639089bddc4fbb129ae039cb12c01be087b397fmalita 282e2639089bddc4fbb129ae039cb12c01be087b397fmalita GrBackendObject obj2 = func(surface, mode); 2839ce9d6772df650ceb0511f275e1a83dffa78ff72reed sk_sp<SkImage> snap2(surface->makeImageSnapshot()); 284e2639089bddc4fbb129ae039cb12c01be087b397fmalita 285e2639089bddc4fbb129ae039cb12c01be087b397fmalita // If the access mode triggers CoW, then the backend objects should reflect it. 286e2639089bddc4fbb129ae039cb12c01be087b397fmalita REPORTER_ASSERT(reporter, (obj1 == obj2) == (snap1 == snap2)); 287e2639089bddc4fbb129ae039cb12c01be087b397fmalita} 288179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunenDEF_TEST(SurfaceBackendHandleAccessCopyOnWrite, reporter) { 289179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen const SkSurface::BackendHandleAccess accessModes[] = { 290179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen SkSurface::kFlushRead_BackendHandleAccess, 291179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen SkSurface::kFlushWrite_BackendHandleAccess, 292179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen SkSurface::kDiscardWrite_BackendHandleAccess, 293179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen }; 294179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen for (auto& handle_access_func : 295179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen { &get_surface_backend_texture_handle, &get_surface_backend_render_target_handle }) { 296179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen for (auto& accessMode : accessModes) { 297e8f3062a36d3682f4019309a32b5b84dc9eddf8creed auto surface(create_surface()); 298e8f3062a36d3682f4019309a32b5b84dc9eddf8creed test_backend_handle_access_copy_on_write(reporter, surface.get(), accessMode, 299179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen handle_access_func); 300179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen } 301179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen } 302179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen} 303179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen#if SK_SUPPORT_GPU 30468d9134bec16e91c4a6cde071bcaa579bc0801a7bsalomonDEF_GPUTEST_FOR_RENDERING_CONTEXTS(SurfaceBackendHandleAccessCopyOnWrite_Gpu, reporter, ctxInfo) { 305179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen const SkSurface::BackendHandleAccess accessModes[] = { 306179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen SkSurface::kFlushRead_BackendHandleAccess, 307179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen SkSurface::kFlushWrite_BackendHandleAccess, 308179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen SkSurface::kDiscardWrite_BackendHandleAccess, 309179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen }; 310179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen for (auto& surface_func : { &create_gpu_surface, &create_gpu_scratch_surface }) { 311179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen for (auto& handle_access_func : 312179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen { &get_surface_backend_texture_handle, &get_surface_backend_render_target_handle }) { 313179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen for (auto& accessMode : accessModes) { 314f2f1c17e331fe1e0ce695969970ecebc81e12cebbsalomon auto surface(surface_func(ctxInfo.fGrContext, kPremul_SkAlphaType, nullptr)); 315e8f3062a36d3682f4019309a32b5b84dc9eddf8creed test_backend_handle_access_copy_on_write(reporter, surface.get(), accessMode, 316179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen handle_access_func); 317179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen } 318179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen } 319179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen } 320179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen} 321179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen#endif 322e2639089bddc4fbb129ae039cb12c01be087b397fmalita 323f47b9a3b88a037a481eb70f01a4cf9f5be34dc28bsalomonstatic bool same_image(SkImage* a, SkImage* b, 324f47b9a3b88a037a481eb70f01a4cf9f5be34dc28bsalomon std::function<intptr_t(SkImage*)> getImageBackingStore) { 325f47b9a3b88a037a481eb70f01a4cf9f5be34dc28bsalomon return getImageBackingStore(a) == getImageBackingStore(b); 326f47b9a3b88a037a481eb70f01a4cf9f5be34dc28bsalomon} 327f47b9a3b88a037a481eb70f01a4cf9f5be34dc28bsalomon 328f47b9a3b88a037a481eb70f01a4cf9f5be34dc28bsalomonstatic bool same_image_surf(SkImage* a, SkSurface* b, 329f47b9a3b88a037a481eb70f01a4cf9f5be34dc28bsalomon std::function<intptr_t(SkImage*)> getImageBackingStore, 330f47b9a3b88a037a481eb70f01a4cf9f5be34dc28bsalomon std::function<intptr_t(SkSurface*)> getSurfaceBackingStore) { 331f47b9a3b88a037a481eb70f01a4cf9f5be34dc28bsalomon return getImageBackingStore(a) == getSurfaceBackingStore(b); 332f47b9a3b88a037a481eb70f01a4cf9f5be34dc28bsalomon} 333f47b9a3b88a037a481eb70f01a4cf9f5be34dc28bsalomon 334f47b9a3b88a037a481eb70f01a4cf9f5be34dc28bsalomonstatic void test_unique_image_snap(skiatest::Reporter* reporter, SkSurface* surface, 335f47b9a3b88a037a481eb70f01a4cf9f5be34dc28bsalomon bool surfaceIsDirect, 336f47b9a3b88a037a481eb70f01a4cf9f5be34dc28bsalomon std::function<intptr_t(SkImage*)> imageBackingStore, 337f47b9a3b88a037a481eb70f01a4cf9f5be34dc28bsalomon std::function<intptr_t(SkSurface*)> surfaceBackingStore) { 338f47b9a3b88a037a481eb70f01a4cf9f5be34dc28bsalomon std::function<intptr_t(SkImage*)> ibs = imageBackingStore; 339f47b9a3b88a037a481eb70f01a4cf9f5be34dc28bsalomon std::function<intptr_t(SkSurface*)> sbs = surfaceBackingStore; 3405ec26ae9bfca635ccc98283aad5deda11519d826bsalomon static const SkBudgeted kB = SkBudgeted::kNo; 341f47b9a3b88a037a481eb70f01a4cf9f5be34dc28bsalomon { 3429ce9d6772df650ceb0511f275e1a83dffa78ff72reed sk_sp<SkImage> image(surface->makeImageSnapshot(kB, SkSurface::kYes_ForceUnique)); 3439ce9d6772df650ceb0511f275e1a83dffa78ff72reed REPORTER_ASSERT(reporter, !same_image_surf(image.get(), surface, ibs, sbs)); 344f47b9a3b88a037a481eb70f01a4cf9f5be34dc28bsalomon REPORTER_ASSERT(reporter, image->unique()); 345f47b9a3b88a037a481eb70f01a4cf9f5be34dc28bsalomon } 346f47b9a3b88a037a481eb70f01a4cf9f5be34dc28bsalomon { 3479ce9d6772df650ceb0511f275e1a83dffa78ff72reed sk_sp<SkImage> image1(surface->makeImageSnapshot(kB, SkSurface::kYes_ForceUnique)); 3489ce9d6772df650ceb0511f275e1a83dffa78ff72reed REPORTER_ASSERT(reporter, !same_image_surf(image1.get(), surface, ibs, sbs)); 349f47b9a3b88a037a481eb70f01a4cf9f5be34dc28bsalomon REPORTER_ASSERT(reporter, image1->unique()); 3509ce9d6772df650ceb0511f275e1a83dffa78ff72reed sk_sp<SkImage> image2(surface->makeImageSnapshot(kB, SkSurface::kYes_ForceUnique)); 3519ce9d6772df650ceb0511f275e1a83dffa78ff72reed REPORTER_ASSERT(reporter, !same_image_surf(image2.get(), surface, ibs, sbs)); 3529ce9d6772df650ceb0511f275e1a83dffa78ff72reed REPORTER_ASSERT(reporter, !same_image(image1.get(), image2.get(), ibs)); 353f47b9a3b88a037a481eb70f01a4cf9f5be34dc28bsalomon REPORTER_ASSERT(reporter, image2->unique()); 354f47b9a3b88a037a481eb70f01a4cf9f5be34dc28bsalomon } 355f47b9a3b88a037a481eb70f01a4cf9f5be34dc28bsalomon { 3569ce9d6772df650ceb0511f275e1a83dffa78ff72reed sk_sp<SkImage> image1(surface->makeImageSnapshot(kB, SkSurface::kNo_ForceUnique)); 3579ce9d6772df650ceb0511f275e1a83dffa78ff72reed sk_sp<SkImage> image2(surface->makeImageSnapshot(kB, SkSurface::kYes_ForceUnique)); 3589ce9d6772df650ceb0511f275e1a83dffa78ff72reed sk_sp<SkImage> image3(surface->makeImageSnapshot(kB, SkSurface::kNo_ForceUnique)); 3599ce9d6772df650ceb0511f275e1a83dffa78ff72reed sk_sp<SkImage> image4(surface->makeImageSnapshot(kB, SkSurface::kYes_ForceUnique)); 360f47b9a3b88a037a481eb70f01a4cf9f5be34dc28bsalomon // Image 1 and 3 ought to be the same (or we're missing an optimization). 3619ce9d6772df650ceb0511f275e1a83dffa78ff72reed REPORTER_ASSERT(reporter, same_image(image1.get(), image3.get(), ibs)); 362f47b9a3b88a037a481eb70f01a4cf9f5be34dc28bsalomon // If the surface is not direct then images 1 and 3 should alias the surface's 363f47b9a3b88a037a481eb70f01a4cf9f5be34dc28bsalomon // store. 3649ce9d6772df650ceb0511f275e1a83dffa78ff72reed REPORTER_ASSERT(reporter, !surfaceIsDirect == same_image_surf(image1.get(), surface, ibs, sbs)); 365f47b9a3b88a037a481eb70f01a4cf9f5be34dc28bsalomon // Image 2 should not be shared with any other image. 3669ce9d6772df650ceb0511f275e1a83dffa78ff72reed REPORTER_ASSERT(reporter, !same_image(image1.get(), image2.get(), ibs) && 3679ce9d6772df650ceb0511f275e1a83dffa78ff72reed !same_image(image3.get(), image2.get(), ibs) && 3689ce9d6772df650ceb0511f275e1a83dffa78ff72reed !same_image(image4.get(), image2.get(), ibs)); 369f47b9a3b88a037a481eb70f01a4cf9f5be34dc28bsalomon REPORTER_ASSERT(reporter, image2->unique()); 3709ce9d6772df650ceb0511f275e1a83dffa78ff72reed REPORTER_ASSERT(reporter, !same_image_surf(image2.get(), surface, ibs, sbs)); 371f47b9a3b88a037a481eb70f01a4cf9f5be34dc28bsalomon // Image 4 should not be shared with any other image. 3729ce9d6772df650ceb0511f275e1a83dffa78ff72reed REPORTER_ASSERT(reporter, !same_image(image1.get(), image4.get(), ibs) && 3739ce9d6772df650ceb0511f275e1a83dffa78ff72reed !same_image(image3.get(), image4.get(), ibs)); 3749ce9d6772df650ceb0511f275e1a83dffa78ff72reed REPORTER_ASSERT(reporter, !same_image_surf(image4.get(), surface, ibs, sbs)); 375f47b9a3b88a037a481eb70f01a4cf9f5be34dc28bsalomon REPORTER_ASSERT(reporter, image4->unique()); 376f47b9a3b88a037a481eb70f01a4cf9f5be34dc28bsalomon } 377f47b9a3b88a037a481eb70f01a4cf9f5be34dc28bsalomon} 378f47b9a3b88a037a481eb70f01a4cf9f5be34dc28bsalomon 379f47b9a3b88a037a481eb70f01a4cf9f5be34dc28bsalomonDEF_TEST(UniqueImageSnapshot, reporter) { 380f47b9a3b88a037a481eb70f01a4cf9f5be34dc28bsalomon auto getImageBackingStore = [reporter](SkImage* image) { 381f47b9a3b88a037a481eb70f01a4cf9f5be34dc28bsalomon SkPixmap pm; 382f47b9a3b88a037a481eb70f01a4cf9f5be34dc28bsalomon bool success = image->peekPixels(&pm); 383f47b9a3b88a037a481eb70f01a4cf9f5be34dc28bsalomon REPORTER_ASSERT(reporter, success); 384f47b9a3b88a037a481eb70f01a4cf9f5be34dc28bsalomon return reinterpret_cast<intptr_t>(pm.addr()); 385f47b9a3b88a037a481eb70f01a4cf9f5be34dc28bsalomon }; 386f47b9a3b88a037a481eb70f01a4cf9f5be34dc28bsalomon auto getSufaceBackingStore = [reporter](SkSurface* surface) { 3876ceeebd37a43d879c120b6ba100ae1febdd67a18reed SkPixmap pmap; 3886ceeebd37a43d879c120b6ba100ae1febdd67a18reed const void* pixels = surface->getCanvas()->peekPixels(&pmap) ? pmap.addr() : nullptr; 389f47b9a3b88a037a481eb70f01a4cf9f5be34dc28bsalomon REPORTER_ASSERT(reporter, pixels); 390f47b9a3b88a037a481eb70f01a4cf9f5be34dc28bsalomon return reinterpret_cast<intptr_t>(pixels); 391f47b9a3b88a037a481eb70f01a4cf9f5be34dc28bsalomon }; 392f47b9a3b88a037a481eb70f01a4cf9f5be34dc28bsalomon 393e8f3062a36d3682f4019309a32b5b84dc9eddf8creed auto surface(create_surface()); 394e8f3062a36d3682f4019309a32b5b84dc9eddf8creed test_unique_image_snap(reporter, surface.get(), false, getImageBackingStore, 395e8f3062a36d3682f4019309a32b5b84dc9eddf8creed getSufaceBackingStore); 396e8f3062a36d3682f4019309a32b5b84dc9eddf8creed surface = create_direct_surface(); 397e8f3062a36d3682f4019309a32b5b84dc9eddf8creed test_unique_image_snap(reporter, surface.get(), true, getImageBackingStore, 398e8f3062a36d3682f4019309a32b5b84dc9eddf8creed getSufaceBackingStore); 399f47b9a3b88a037a481eb70f01a4cf9f5be34dc28bsalomon} 400f47b9a3b88a037a481eb70f01a4cf9f5be34dc28bsalomon 401f47b9a3b88a037a481eb70f01a4cf9f5be34dc28bsalomon#if SK_SUPPORT_GPU 40268d9134bec16e91c4a6cde071bcaa579bc0801a7bsalomonDEF_GPUTEST_FOR_RENDERING_CONTEXTS(UniqueImageSnapshot_Gpu, reporter, ctxInfo) { 403f2f1c17e331fe1e0ce695969970ecebc81e12cebbsalomon GrContext* context = ctxInfo.fGrContext; 404f47b9a3b88a037a481eb70f01a4cf9f5be34dc28bsalomon for (auto& surface_func : { &create_gpu_surface, &create_gpu_scratch_surface }) { 405e8f3062a36d3682f4019309a32b5b84dc9eddf8creed auto surface(surface_func(context, kOpaque_SkAlphaType, nullptr)); 406f47b9a3b88a037a481eb70f01a4cf9f5be34dc28bsalomon 407f47b9a3b88a037a481eb70f01a4cf9f5be34dc28bsalomon auto imageBackingStore = [reporter](SkImage* image) { 408f47b9a3b88a037a481eb70f01a4cf9f5be34dc28bsalomon GrTexture* texture = as_IB(image)->peekTexture(); 409f47b9a3b88a037a481eb70f01a4cf9f5be34dc28bsalomon if (!texture) { 410f47b9a3b88a037a481eb70f01a4cf9f5be34dc28bsalomon ERRORF(reporter, "Not texture backed."); 411f47b9a3b88a037a481eb70f01a4cf9f5be34dc28bsalomon return static_cast<intptr_t>(0); 412f47b9a3b88a037a481eb70f01a4cf9f5be34dc28bsalomon } 413f47b9a3b88a037a481eb70f01a4cf9f5be34dc28bsalomon return static_cast<intptr_t>(texture->getUniqueID()); 414f47b9a3b88a037a481eb70f01a4cf9f5be34dc28bsalomon }; 415f47b9a3b88a037a481eb70f01a4cf9f5be34dc28bsalomon 416f47b9a3b88a037a481eb70f01a4cf9f5be34dc28bsalomon auto surfaceBackingStore = [reporter](SkSurface* surface) { 417175dd9b5e3d7d749738dac743d2ac360b5340187robertphillips GrDrawContext* dc = surface->getCanvas()->internal_private_accessTopLayerDrawContext(); 418175dd9b5e3d7d749738dac743d2ac360b5340187robertphillips GrRenderTarget* rt = dc->accessRenderTarget(); 419f47b9a3b88a037a481eb70f01a4cf9f5be34dc28bsalomon if (!rt) { 420f47b9a3b88a037a481eb70f01a4cf9f5be34dc28bsalomon ERRORF(reporter, "Not render target backed."); 421f47b9a3b88a037a481eb70f01a4cf9f5be34dc28bsalomon return static_cast<intptr_t>(0); 422f47b9a3b88a037a481eb70f01a4cf9f5be34dc28bsalomon } 423f47b9a3b88a037a481eb70f01a4cf9f5be34dc28bsalomon return static_cast<intptr_t>(rt->getUniqueID()); 424f47b9a3b88a037a481eb70f01a4cf9f5be34dc28bsalomon }; 425f47b9a3b88a037a481eb70f01a4cf9f5be34dc28bsalomon 426e8f3062a36d3682f4019309a32b5b84dc9eddf8creed test_unique_image_snap(reporter, surface.get(), false, imageBackingStore, 427e8f3062a36d3682f4019309a32b5b84dc9eddf8creed surfaceBackingStore); 428f47b9a3b88a037a481eb70f01a4cf9f5be34dc28bsalomon 429f47b9a3b88a037a481eb70f01a4cf9f5be34dc28bsalomon // Test again with a "direct" render target; 430f47b9a3b88a037a481eb70f01a4cf9f5be34dc28bsalomon GrBackendObject textureObject = context->getGpu()->createTestingOnlyBackendTexture(nullptr, 431f47b9a3b88a037a481eb70f01a4cf9f5be34dc28bsalomon 10, 10, kRGBA_8888_GrPixelConfig); 432f47b9a3b88a037a481eb70f01a4cf9f5be34dc28bsalomon GrBackendTextureDesc desc; 433f47b9a3b88a037a481eb70f01a4cf9f5be34dc28bsalomon desc.fConfig = kRGBA_8888_GrPixelConfig; 434f47b9a3b88a037a481eb70f01a4cf9f5be34dc28bsalomon desc.fWidth = 10; 435f47b9a3b88a037a481eb70f01a4cf9f5be34dc28bsalomon desc.fHeight = 10; 436f47b9a3b88a037a481eb70f01a4cf9f5be34dc28bsalomon desc.fFlags = kRenderTarget_GrBackendTextureFlag; 437f47b9a3b88a037a481eb70f01a4cf9f5be34dc28bsalomon desc.fTextureHandle = textureObject; 438f47b9a3b88a037a481eb70f01a4cf9f5be34dc28bsalomon GrTexture* texture = context->textureProvider()->wrapBackendTexture(desc); 439f47b9a3b88a037a481eb70f01a4cf9f5be34dc28bsalomon { 440e8f3062a36d3682f4019309a32b5b84dc9eddf8creed auto surface(SkSurface::MakeRenderTargetDirect(texture->asRenderTarget())); 441e8f3062a36d3682f4019309a32b5b84dc9eddf8creed test_unique_image_snap(reporter, surface.get(), true, imageBackingStore, 442f47b9a3b88a037a481eb70f01a4cf9f5be34dc28bsalomon surfaceBackingStore); 443f47b9a3b88a037a481eb70f01a4cf9f5be34dc28bsalomon } 444f47b9a3b88a037a481eb70f01a4cf9f5be34dc28bsalomon texture->unref(); 445f47b9a3b88a037a481eb70f01a4cf9f5be34dc28bsalomon context->getGpu()->deleteTestingOnlyBackendTexture(textureObject); 446f47b9a3b88a037a481eb70f01a4cf9f5be34dc28bsalomon } 447f47b9a3b88a037a481eb70f01a4cf9f5be34dc28bsalomon} 448f47b9a3b88a037a481eb70f01a4cf9f5be34dc28bsalomon#endif 449f47b9a3b88a037a481eb70f01a4cf9f5be34dc28bsalomon 450179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen#if SK_SUPPORT_GPU 451179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen// May we (soon) eliminate the need to keep testing this, by hiding the bloody device! 452179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunenstatic uint32_t get_legacy_gen_id(SkSurface* surface) { 453179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen SkBaseDevice* device = 454179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen surface->getCanvas()->getDevice_just_for_deprecated_compatibility_testing(); 455179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen return device->accessBitmap(false).getGenerationID(); 456179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen} 457179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen/* 458179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen * Test legacy behavor of bumping the surface's device's bitmap's genID when we access its 459179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen * texture handle for writing. 460179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen * 4619ce9d6772df650ceb0511f275e1a83dffa78ff72reed * Note: this needs to be tested separately from checking makeImageSnapshot, as calling that 462179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen * can also incidentally bump the genID (when a new backing surface is created). 463179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen */ 464179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunenstatic void test_backend_handle_gen_id( 465179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen skiatest::Reporter* reporter, SkSurface* surface, 466179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen GrBackendObject (*func)(SkSurface*, SkSurface::BackendHandleAccess)) { 467179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen const uint32_t gen0 = get_legacy_gen_id(surface); 468179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen func(surface, SkSurface::kFlushRead_BackendHandleAccess); 469179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen const uint32_t gen1 = get_legacy_gen_id(surface); 470179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen REPORTER_ASSERT(reporter, gen0 == gen1); 471179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen 472179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen func(surface, SkSurface::kFlushWrite_BackendHandleAccess); 473179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen const uint32_t gen2 = get_legacy_gen_id(surface); 474179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen REPORTER_ASSERT(reporter, gen0 != gen2); 475179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen 476179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen func(surface, SkSurface::kDiscardWrite_BackendHandleAccess); 477179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen const uint32_t gen3 = get_legacy_gen_id(surface); 478179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen REPORTER_ASSERT(reporter, gen0 != gen3); 479179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen REPORTER_ASSERT(reporter, gen2 != gen3); 480179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen} 481179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunenstatic void test_backend_handle_unique_id( 482179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen skiatest::Reporter* reporter, SkSurface* surface, 483179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen GrBackendObject (*func)(SkSurface*, SkSurface::BackendHandleAccess)) { 4849ce9d6772df650ceb0511f275e1a83dffa78ff72reed sk_sp<SkImage> image0(surface->makeImageSnapshot()); 485179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen GrBackendObject obj = func(surface, SkSurface::kFlushRead_BackendHandleAccess); 486179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen REPORTER_ASSERT(reporter, obj != 0); 4879ce9d6772df650ceb0511f275e1a83dffa78ff72reed sk_sp<SkImage> image1(surface->makeImageSnapshot()); 488179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen // just read access should not affect the snapshot 489179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen REPORTER_ASSERT(reporter, image0->uniqueID() == image1->uniqueID()); 490179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen 491179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen obj = func(surface, SkSurface::kFlushWrite_BackendHandleAccess); 492179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen REPORTER_ASSERT(reporter, obj != 0); 4939ce9d6772df650ceb0511f275e1a83dffa78ff72reed sk_sp<SkImage> image2(surface->makeImageSnapshot()); 494179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen // expect a new image, since we claimed we would write 495179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen REPORTER_ASSERT(reporter, image0->uniqueID() != image2->uniqueID()); 496179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen 497179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen obj = func(surface, SkSurface::kDiscardWrite_BackendHandleAccess); 498179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen REPORTER_ASSERT(reporter, obj != 0); 4999ce9d6772df650ceb0511f275e1a83dffa78ff72reed sk_sp<SkImage> image3(surface->makeImageSnapshot()); 500179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen // expect a new(er) image, since we claimed we would write 501179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen REPORTER_ASSERT(reporter, image0->uniqueID() != image3->uniqueID()); 502179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen REPORTER_ASSERT(reporter, image2->uniqueID() != image3->uniqueID()); 503179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen} 504179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen// No CPU test. 50568d9134bec16e91c4a6cde071bcaa579bc0801a7bsalomonDEF_GPUTEST_FOR_RENDERING_CONTEXTS(SurfaceBackendHandleAccessIDs_Gpu, reporter, ctxInfo) { 506179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen for (auto& surface_func : { &create_gpu_surface, &create_gpu_scratch_surface }) { 507179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen for (auto& test_func : { &test_backend_handle_unique_id, &test_backend_handle_gen_id }) { 508179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen for (auto& handle_access_func : 509179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen { &get_surface_backend_texture_handle, &get_surface_backend_render_target_handle}) { 510f2f1c17e331fe1e0ce695969970ecebc81e12cebbsalomon auto surface(surface_func(ctxInfo.fGrContext, kPremul_SkAlphaType, nullptr)); 511e8f3062a36d3682f4019309a32b5b84dc9eddf8creed test_func(reporter, surface.get(), handle_access_func); 512179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen } 513179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen } 514179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen } 515179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen} 516179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen#endif 517179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen 518179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen// Verify that the right canvas commands trigger a copy on write. 519179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunenstatic void test_copy_on_write(skiatest::Reporter* reporter, SkSurface* surface) { 520995beb6b00afc0e28f5effc8a22a7a3dcb2544e8junov@chromium.org SkCanvas* canvas = surface->getCanvas(); 521995beb6b00afc0e28f5effc8a22a7a3dcb2544e8junov@chromium.org 522995beb6b00afc0e28f5effc8a22a7a3dcb2544e8junov@chromium.org const SkRect testRect = 523995beb6b00afc0e28f5effc8a22a7a3dcb2544e8junov@chromium.org SkRect::MakeXYWH(SkIntToScalar(0), SkIntToScalar(0), 524995beb6b00afc0e28f5effc8a22a7a3dcb2544e8junov@chromium.org SkIntToScalar(4), SkIntToScalar(5)); 525995beb6b00afc0e28f5effc8a22a7a3dcb2544e8junov@chromium.org SkPath testPath; 526995beb6b00afc0e28f5effc8a22a7a3dcb2544e8junov@chromium.org testPath.addRect(SkRect::MakeXYWH(SkIntToScalar(0), SkIntToScalar(0), 527995beb6b00afc0e28f5effc8a22a7a3dcb2544e8junov@chromium.org SkIntToScalar(2), SkIntToScalar(1))); 528995beb6b00afc0e28f5effc8a22a7a3dcb2544e8junov@chromium.org 529995beb6b00afc0e28f5effc8a22a7a3dcb2544e8junov@chromium.org const SkIRect testIRect = SkIRect::MakeXYWH(0, 0, 2, 1); 530995beb6b00afc0e28f5effc8a22a7a3dcb2544e8junov@chromium.org 531995beb6b00afc0e28f5effc8a22a7a3dcb2544e8junov@chromium.org SkRegion testRegion; 532995beb6b00afc0e28f5effc8a22a7a3dcb2544e8junov@chromium.org testRegion.setRect(testIRect); 533995beb6b00afc0e28f5effc8a22a7a3dcb2544e8junov@chromium.org 534995beb6b00afc0e28f5effc8a22a7a3dcb2544e8junov@chromium.org 535995beb6b00afc0e28f5effc8a22a7a3dcb2544e8junov@chromium.org const SkColor testColor = 0x01020304; 536995beb6b00afc0e28f5effc8a22a7a3dcb2544e8junov@chromium.org const SkPaint testPaint; 537995beb6b00afc0e28f5effc8a22a7a3dcb2544e8junov@chromium.org const SkPoint testPoints[3] = { 538995beb6b00afc0e28f5effc8a22a7a3dcb2544e8junov@chromium.org {SkIntToScalar(0), SkIntToScalar(0)}, 539995beb6b00afc0e28f5effc8a22a7a3dcb2544e8junov@chromium.org {SkIntToScalar(2), SkIntToScalar(1)}, 540995beb6b00afc0e28f5effc8a22a7a3dcb2544e8junov@chromium.org {SkIntToScalar(0), SkIntToScalar(2)} 541995beb6b00afc0e28f5effc8a22a7a3dcb2544e8junov@chromium.org }; 542995beb6b00afc0e28f5effc8a22a7a3dcb2544e8junov@chromium.org const size_t testPointCount = 3; 543995beb6b00afc0e28f5effc8a22a7a3dcb2544e8junov@chromium.org 544995beb6b00afc0e28f5effc8a22a7a3dcb2544e8junov@chromium.org SkBitmap testBitmap; 545deee496cd30070e52556dcb538c2e5eb39b66b81mike@reedtribe.org testBitmap.allocN32Pixels(10, 10); 546d1ce77d548ab098c2f455e9b0fa1f195e75cd8edrobertphillips@google.com testBitmap.eraseColor(0); 547995beb6b00afc0e28f5effc8a22a7a3dcb2544e8junov@chromium.org 548995beb6b00afc0e28f5effc8a22a7a3dcb2544e8junov@chromium.org SkRRect testRRect; 549995beb6b00afc0e28f5effc8a22a7a3dcb2544e8junov@chromium.org testRRect.setRectXY(testRect, SK_Scalar1, SK_Scalar1); 550995beb6b00afc0e28f5effc8a22a7a3dcb2544e8junov@chromium.org 551995beb6b00afc0e28f5effc8a22a7a3dcb2544e8junov@chromium.org SkString testText("Hello World"); 552995beb6b00afc0e28f5effc8a22a7a3dcb2544e8junov@chromium.org const SkPoint testPoints2[] = { 553995beb6b00afc0e28f5effc8a22a7a3dcb2544e8junov@chromium.org { SkIntToScalar(0), SkIntToScalar(1) }, 554995beb6b00afc0e28f5effc8a22a7a3dcb2544e8junov@chromium.org { SkIntToScalar(1), SkIntToScalar(1) }, 555995beb6b00afc0e28f5effc8a22a7a3dcb2544e8junov@chromium.org { SkIntToScalar(2), SkIntToScalar(1) }, 556995beb6b00afc0e28f5effc8a22a7a3dcb2544e8junov@chromium.org { SkIntToScalar(3), SkIntToScalar(1) }, 557995beb6b00afc0e28f5effc8a22a7a3dcb2544e8junov@chromium.org { SkIntToScalar(4), SkIntToScalar(1) }, 558995beb6b00afc0e28f5effc8a22a7a3dcb2544e8junov@chromium.org { SkIntToScalar(5), SkIntToScalar(1) }, 559995beb6b00afc0e28f5effc8a22a7a3dcb2544e8junov@chromium.org { SkIntToScalar(6), SkIntToScalar(1) }, 560995beb6b00afc0e28f5effc8a22a7a3dcb2544e8junov@chromium.org { SkIntToScalar(7), SkIntToScalar(1) }, 561995beb6b00afc0e28f5effc8a22a7a3dcb2544e8junov@chromium.org { SkIntToScalar(8), SkIntToScalar(1) }, 562995beb6b00afc0e28f5effc8a22a7a3dcb2544e8junov@chromium.org { SkIntToScalar(9), SkIntToScalar(1) }, 563995beb6b00afc0e28f5effc8a22a7a3dcb2544e8junov@chromium.org { SkIntToScalar(10), SkIntToScalar(1) }, 564995beb6b00afc0e28f5effc8a22a7a3dcb2544e8junov@chromium.org }; 565995beb6b00afc0e28f5effc8a22a7a3dcb2544e8junov@chromium.org 566995beb6b00afc0e28f5effc8a22a7a3dcb2544e8junov@chromium.org#define EXPECT_COPY_ON_WRITE(command) \ 567995beb6b00afc0e28f5effc8a22a7a3dcb2544e8junov@chromium.org { \ 5689ce9d6772df650ceb0511f275e1a83dffa78ff72reed sk_sp<SkImage> imageBefore = surface->makeImageSnapshot(); \ 5699ce9d6772df650ceb0511f275e1a83dffa78ff72reed sk_sp<SkImage> aur_before(imageBefore); \ 570995beb6b00afc0e28f5effc8a22a7a3dcb2544e8junov@chromium.org canvas-> command ; \ 5719ce9d6772df650ceb0511f275e1a83dffa78ff72reed sk_sp<SkImage> imageAfter = surface->makeImageSnapshot(); \ 5729ce9d6772df650ceb0511f275e1a83dffa78ff72reed sk_sp<SkImage> aur_after(imageAfter); \ 573995beb6b00afc0e28f5effc8a22a7a3dcb2544e8junov@chromium.org REPORTER_ASSERT(reporter, imageBefore != imageAfter); \ 574995beb6b00afc0e28f5effc8a22a7a3dcb2544e8junov@chromium.org } 575995beb6b00afc0e28f5effc8a22a7a3dcb2544e8junov@chromium.org 576995beb6b00afc0e28f5effc8a22a7a3dcb2544e8junov@chromium.org EXPECT_COPY_ON_WRITE(clear(testColor)) 577995beb6b00afc0e28f5effc8a22a7a3dcb2544e8junov@chromium.org EXPECT_COPY_ON_WRITE(drawPaint(testPaint)) 578995beb6b00afc0e28f5effc8a22a7a3dcb2544e8junov@chromium.org EXPECT_COPY_ON_WRITE(drawPoints(SkCanvas::kPoints_PointMode, testPointCount, testPoints, \ 579995beb6b00afc0e28f5effc8a22a7a3dcb2544e8junov@chromium.org testPaint)) 580995beb6b00afc0e28f5effc8a22a7a3dcb2544e8junov@chromium.org EXPECT_COPY_ON_WRITE(drawOval(testRect, testPaint)) 581995beb6b00afc0e28f5effc8a22a7a3dcb2544e8junov@chromium.org EXPECT_COPY_ON_WRITE(drawRect(testRect, testPaint)) 582995beb6b00afc0e28f5effc8a22a7a3dcb2544e8junov@chromium.org EXPECT_COPY_ON_WRITE(drawRRect(testRRect, testPaint)) 583995beb6b00afc0e28f5effc8a22a7a3dcb2544e8junov@chromium.org EXPECT_COPY_ON_WRITE(drawPath(testPath, testPaint)) 584995beb6b00afc0e28f5effc8a22a7a3dcb2544e8junov@chromium.org EXPECT_COPY_ON_WRITE(drawBitmap(testBitmap, 0, 0)) 585e47829b6b1eeb6b0c97ccb3df3016d197046824creed EXPECT_COPY_ON_WRITE(drawBitmapRect(testBitmap, testRect, nullptr)) 58696fcdcc219d2a0d3579719b84b28bede76efba64halcanary EXPECT_COPY_ON_WRITE(drawBitmapNine(testBitmap, testIRect, testRect, nullptr)) 587995beb6b00afc0e28f5effc8a22a7a3dcb2544e8junov@chromium.org EXPECT_COPY_ON_WRITE(drawText(testText.c_str(), testText.size(), 0, 1, testPaint)) 588995beb6b00afc0e28f5effc8a22a7a3dcb2544e8junov@chromium.org EXPECT_COPY_ON_WRITE(drawPosText(testText.c_str(), testText.size(), testPoints2, \ 589995beb6b00afc0e28f5effc8a22a7a3dcb2544e8junov@chromium.org testPaint)) 59096fcdcc219d2a0d3579719b84b28bede76efba64halcanary EXPECT_COPY_ON_WRITE(drawTextOnPath(testText.c_str(), testText.size(), testPath, nullptr, \ 591995beb6b00afc0e28f5effc8a22a7a3dcb2544e8junov@chromium.org testPaint)) 592179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen} 593179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunenDEF_TEST(SurfaceCopyOnWrite, reporter) { 594e8f3062a36d3682f4019309a32b5b84dc9eddf8creed test_copy_on_write(reporter, create_surface().get()); 595179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen} 596179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen#if SK_SUPPORT_GPU 597758586c7f11a6b3529bd4a1c9b4e982a0d0b0582bsalomonDEF_GPUTEST_FOR_GL_RENDERING_CONTEXTS(SurfaceCopyOnWrite_Gpu, reporter, ctxInfo) { 598179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen for (auto& surface_func : { &create_gpu_surface, &create_gpu_scratch_surface }) { 599f2f1c17e331fe1e0ce695969970ecebc81e12cebbsalomon auto surface(surface_func(ctxInfo.fGrContext, kPremul_SkAlphaType, nullptr)); 600e8f3062a36d3682f4019309a32b5b84dc9eddf8creed test_copy_on_write(reporter, surface.get()); 601e2639089bddc4fbb129ae039cb12c01be087b397fmalita } 602995beb6b00afc0e28f5effc8a22a7a3dcb2544e8junov@chromium.org} 603179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen#endif 604995beb6b00afc0e28f5effc8a22a7a3dcb2544e8junov@chromium.org 605179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunenstatic void test_writable_after_snapshot_release(skiatest::Reporter* reporter, 606179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen SkSurface* surface) { 607af0583528c7dd5344abfe14347377011abe374e2junov@chromium.org // This test succeeds by not triggering an assertion. 608af0583528c7dd5344abfe14347377011abe374e2junov@chromium.org // The test verifies that the surface remains writable (usable) after 609af0583528c7dd5344abfe14347377011abe374e2junov@chromium.org // acquiring and releasing a snapshot without triggering a copy on write. 610af0583528c7dd5344abfe14347377011abe374e2junov@chromium.org SkCanvas* canvas = surface->getCanvas(); 611af0583528c7dd5344abfe14347377011abe374e2junov@chromium.org canvas->clear(1); 6129ce9d6772df650ceb0511f275e1a83dffa78ff72reed surface->makeImageSnapshot(); // Create and destroy SkImage 6134d24b747e272355395f456e088a2d0177c00ddb5commit-bot@chromium.org canvas->clear(2); // Must not assert internally 614995beb6b00afc0e28f5effc8a22a7a3dcb2544e8junov@chromium.org} 615179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunenDEF_TEST(SurfaceWriteableAfterSnapshotRelease, reporter) { 616e8f3062a36d3682f4019309a32b5b84dc9eddf8creed test_writable_after_snapshot_release(reporter, create_surface().get()); 617179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen} 618179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen#if SK_SUPPORT_GPU 619758586c7f11a6b3529bd4a1c9b4e982a0d0b0582bsalomonDEF_GPUTEST_FOR_GL_RENDERING_CONTEXTS(SurfaceWriteableAfterSnapshotRelease_Gpu, reporter, ctxInfo) { 620179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen for (auto& surface_func : { &create_gpu_surface, &create_gpu_scratch_surface }) { 621f2f1c17e331fe1e0ce695969970ecebc81e12cebbsalomon auto surface(surface_func(ctxInfo.fGrContext, kPremul_SkAlphaType, nullptr)); 622e8f3062a36d3682f4019309a32b5b84dc9eddf8creed test_writable_after_snapshot_release(reporter, surface.get()); 623179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen } 624179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen} 625179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen#endif 626da90474b5fcc019fb0971d12360bd05213ad4dc8junov@chromium.org 627b516a4177931b8febf859752b49f094f70539eaejunov@chromium.org#if SK_SUPPORT_GPU 628179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunenstatic void test_crbug263329(skiatest::Reporter* reporter, 629179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen SkSurface* surface1, 630179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen SkSurface* surface2) { 6314d24b747e272355395f456e088a2d0177c00ddb5commit-bot@chromium.org // This is a regression test for crbug.com/263329 6324d24b747e272355395f456e088a2d0177c00ddb5commit-bot@chromium.org // Bug was caused by onCopyOnWrite releasing the old surface texture 6334d24b747e272355395f456e088a2d0177c00ddb5commit-bot@chromium.org // back to the scratch texture pool even though the texture is used 6344d24b747e272355395f456e088a2d0177c00ddb5commit-bot@chromium.org // by and active SkImage_Gpu. 6354d24b747e272355395f456e088a2d0177c00ddb5commit-bot@chromium.org SkCanvas* canvas1 = surface1->getCanvas(); 6364d24b747e272355395f456e088a2d0177c00ddb5commit-bot@chromium.org SkCanvas* canvas2 = surface2->getCanvas(); 6374d24b747e272355395f456e088a2d0177c00ddb5commit-bot@chromium.org canvas1->clear(1); 6389ce9d6772df650ceb0511f275e1a83dffa78ff72reed sk_sp<SkImage> image1(surface1->makeImageSnapshot()); 6394d24b747e272355395f456e088a2d0177c00ddb5commit-bot@chromium.org // Trigger copy on write, new backing is a scratch texture 6404d24b747e272355395f456e088a2d0177c00ddb5commit-bot@chromium.org canvas1->clear(2); 6419ce9d6772df650ceb0511f275e1a83dffa78ff72reed sk_sp<SkImage> image2(surface1->makeImageSnapshot()); 6424d24b747e272355395f456e088a2d0177c00ddb5commit-bot@chromium.org // Trigger copy on write, old backing should not be returned to scratch 6434d24b747e272355395f456e088a2d0177c00ddb5commit-bot@chromium.org // pool because it is held by image2 6444d24b747e272355395f456e088a2d0177c00ddb5commit-bot@chromium.org canvas1->clear(3); 6454d24b747e272355395f456e088a2d0177c00ddb5commit-bot@chromium.org 6464d24b747e272355395f456e088a2d0177c00ddb5commit-bot@chromium.org canvas2->clear(4); 6479ce9d6772df650ceb0511f275e1a83dffa78ff72reed sk_sp<SkImage> image3(surface2->makeImageSnapshot()); 6484d24b747e272355395f456e088a2d0177c00ddb5commit-bot@chromium.org // Trigger copy on write on surface2. The new backing store should not 6494d24b747e272355395f456e088a2d0177c00ddb5commit-bot@chromium.org // be recycling a texture that is held by an existing image. 6504d24b747e272355395f456e088a2d0177c00ddb5commit-bot@chromium.org canvas2->clear(5); 6519ce9d6772df650ceb0511f275e1a83dffa78ff72reed sk_sp<SkImage> image4(surface2->makeImageSnapshot()); 65284a4e5a8d683bf17d6c3058b977b9dfb000428afbsalomon REPORTER_ASSERT(reporter, as_IB(image4)->peekTexture() != as_IB(image3)->peekTexture()); 6534d24b747e272355395f456e088a2d0177c00ddb5commit-bot@chromium.org // The following assertion checks crbug.com/263329 65484a4e5a8d683bf17d6c3058b977b9dfb000428afbsalomon REPORTER_ASSERT(reporter, as_IB(image4)->peekTexture() != as_IB(image2)->peekTexture()); 65584a4e5a8d683bf17d6c3058b977b9dfb000428afbsalomon REPORTER_ASSERT(reporter, as_IB(image4)->peekTexture() != as_IB(image1)->peekTexture()); 65684a4e5a8d683bf17d6c3058b977b9dfb000428afbsalomon REPORTER_ASSERT(reporter, as_IB(image3)->peekTexture() != as_IB(image2)->peekTexture()); 65784a4e5a8d683bf17d6c3058b977b9dfb000428afbsalomon REPORTER_ASSERT(reporter, as_IB(image3)->peekTexture() != as_IB(image1)->peekTexture()); 65884a4e5a8d683bf17d6c3058b977b9dfb000428afbsalomon REPORTER_ASSERT(reporter, as_IB(image2)->peekTexture() != as_IB(image1)->peekTexture()); 6594d24b747e272355395f456e088a2d0177c00ddb5commit-bot@chromium.org} 660758586c7f11a6b3529bd4a1c9b4e982a0d0b0582bsalomonDEF_GPUTEST_FOR_GL_RENDERING_CONTEXTS(SurfaceCRBug263329_Gpu, reporter, ctxInfo) { 661179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen for (auto& surface_func : { &create_gpu_surface, &create_gpu_scratch_surface }) { 662f2f1c17e331fe1e0ce695969970ecebc81e12cebbsalomon auto surface1(surface_func(ctxInfo.fGrContext, kPremul_SkAlphaType, nullptr)); 663f2f1c17e331fe1e0ce695969970ecebc81e12cebbsalomon auto surface2(surface_func(ctxInfo.fGrContext, kPremul_SkAlphaType, nullptr)); 664e8f3062a36d3682f4019309a32b5b84dc9eddf8creed test_crbug263329(reporter, surface1.get(), surface2.get()); 665179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen } 666179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen} 667179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen#endif 6684d24b747e272355395f456e088a2d0177c00ddb5commit-bot@chromium.org 669179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunenDEF_TEST(SurfaceGetTexture, reporter) { 670e8f3062a36d3682f4019309a32b5b84dc9eddf8creed auto surface(create_surface()); 6719ce9d6772df650ceb0511f275e1a83dffa78ff72reed sk_sp<SkImage> image(surface->makeImageSnapshot()); 67284a4e5a8d683bf17d6c3058b977b9dfb000428afbsalomon REPORTER_ASSERT(reporter, as_IB(image)->peekTexture() == nullptr); 673179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen surface->notifyContentWillChange(SkSurface::kDiscard_ContentChangeMode); 67484a4e5a8d683bf17d6c3058b977b9dfb000428afbsalomon REPORTER_ASSERT(reporter, as_IB(image)->peekTexture() == nullptr); 675179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen} 676179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen#if SK_SUPPORT_GPU 677758586c7f11a6b3529bd4a1c9b4e982a0d0b0582bsalomonDEF_GPUTEST_FOR_GL_RENDERING_CONTEXTS(SurfacepeekTexture_Gpu, reporter, ctxInfo) { 678179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen for (auto& surface_func : { &create_gpu_surface, &create_gpu_scratch_surface }) { 679f2f1c17e331fe1e0ce695969970ecebc81e12cebbsalomon auto surface(surface_func(ctxInfo.fGrContext, kPremul_SkAlphaType, nullptr)); 6809ce9d6772df650ceb0511f275e1a83dffa78ff72reed sk_sp<SkImage> image(surface->makeImageSnapshot()); 68184a4e5a8d683bf17d6c3058b977b9dfb000428afbsalomon GrTexture* texture = as_IB(image)->peekTexture(); 68249f085dddff10473b6ebf832a974288300224e60bsalomon REPORTER_ASSERT(reporter, texture); 683da90474b5fcc019fb0971d12360bd05213ad4dc8junov@chromium.org REPORTER_ASSERT(reporter, 0 != texture->getTextureHandle()); 684179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen surface->notifyContentWillChange(SkSurface::kDiscard_ContentChangeMode); 68584a4e5a8d683bf17d6c3058b977b9dfb000428afbsalomon REPORTER_ASSERT(reporter, as_IB(image)->peekTexture() == texture); 686da90474b5fcc019fb0971d12360bd05213ad4dc8junov@chromium.org } 687da90474b5fcc019fb0971d12360bd05213ad4dc8junov@chromium.org} 688179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen#endif 689eaaaf0b16c4e55ff8a48c5ac1ed623a6ba469053bsalomon 690179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen#if SK_SUPPORT_GPU 6913582d3ee9fffdec715f5e4949a241ab08e6271ecbsalomon#include "GrGpuResourcePriv.h" 692eaaaf0b16c4e55ff8a48c5ac1ed623a6ba469053bsalomon#include "SkGpuDevice.h" 693eaaaf0b16c4e55ff8a48c5ac1ed623a6ba469053bsalomon#include "SkImage_Gpu.h" 694eaaaf0b16c4e55ff8a48c5ac1ed623a6ba469053bsalomon#include "SkSurface_Gpu.h" 695eaaaf0b16c4e55ff8a48c5ac1ed623a6ba469053bsalomon 696e8f3062a36d3682f4019309a32b5b84dc9eddf8creedstatic SkBudgeted is_budgeted(const sk_sp<SkSurface>& surf) { 697e8f3062a36d3682f4019309a32b5b84dc9eddf8creed SkSurface_Gpu* gsurf = (SkSurface_Gpu*)surf.get(); 698e8f3062a36d3682f4019309a32b5b84dc9eddf8creed return gsurf->getDevice()->accessRenderTarget()->resourcePriv().isBudgeted(); 699eaaaf0b16c4e55ff8a48c5ac1ed623a6ba469053bsalomon} 700eaaaf0b16c4e55ff8a48c5ac1ed623a6ba469053bsalomon 7015ec26ae9bfca635ccc98283aad5deda11519d826bsalomonstatic SkBudgeted is_budgeted(SkImage* image) { 70284a4e5a8d683bf17d6c3058b977b9dfb000428afbsalomon return ((SkImage_Gpu*)image)->peekTexture()->resourcePriv().isBudgeted(); 703eaaaf0b16c4e55ff8a48c5ac1ed623a6ba469053bsalomon} 704eaaaf0b16c4e55ff8a48c5ac1ed623a6ba469053bsalomon 7059ce9d6772df650ceb0511f275e1a83dffa78ff72reedstatic SkBudgeted is_budgeted(const sk_sp<SkImage> image) { 7069ce9d6772df650ceb0511f275e1a83dffa78ff72reed return is_budgeted(image.get()); 7079ce9d6772df650ceb0511f275e1a83dffa78ff72reed} 7089ce9d6772df650ceb0511f275e1a83dffa78ff72reed 709758586c7f11a6b3529bd4a1c9b4e982a0d0b0582bsalomonDEF_GPUTEST_FOR_GL_RENDERING_CONTEXTS(SurfaceBudget, reporter, ctxInfo) { 710eaaaf0b16c4e55ff8a48c5ac1ed623a6ba469053bsalomon SkImageInfo info = SkImageInfo::MakeN32Premul(8,8); 7115ec26ae9bfca635ccc98283aad5deda11519d826bsalomon for (auto sbudgeted : { SkBudgeted::kNo, SkBudgeted::kYes }) { 7125ec26ae9bfca635ccc98283aad5deda11519d826bsalomon for (auto ibudgeted : { SkBudgeted::kNo, SkBudgeted::kYes }) { 713f2f1c17e331fe1e0ce695969970ecebc81e12cebbsalomon auto surface(SkSurface::MakeRenderTarget(ctxInfo.fGrContext, sbudgeted, info)); 714eaaaf0b16c4e55ff8a48c5ac1ed623a6ba469053bsalomon SkASSERT(surface); 715eaaaf0b16c4e55ff8a48c5ac1ed623a6ba469053bsalomon REPORTER_ASSERT(reporter, sbudgeted == is_budgeted(surface)); 716eaaaf0b16c4e55ff8a48c5ac1ed623a6ba469053bsalomon 7179ce9d6772df650ceb0511f275e1a83dffa78ff72reed sk_sp<SkImage> image(surface->makeImageSnapshot(ibudgeted)); 718eaaaf0b16c4e55ff8a48c5ac1ed623a6ba469053bsalomon 719eaaaf0b16c4e55ff8a48c5ac1ed623a6ba469053bsalomon // Initially the image shares a texture with the surface, and the surface decides 720eaaaf0b16c4e55ff8a48c5ac1ed623a6ba469053bsalomon // whether it is budgeted or not. 721eaaaf0b16c4e55ff8a48c5ac1ed623a6ba469053bsalomon REPORTER_ASSERT(reporter, sbudgeted == is_budgeted(surface)); 722eaaaf0b16c4e55ff8a48c5ac1ed623a6ba469053bsalomon REPORTER_ASSERT(reporter, sbudgeted == is_budgeted(image)); 723eaaaf0b16c4e55ff8a48c5ac1ed623a6ba469053bsalomon 724eaaaf0b16c4e55ff8a48c5ac1ed623a6ba469053bsalomon // Now trigger copy-on-write 725eaaaf0b16c4e55ff8a48c5ac1ed623a6ba469053bsalomon surface->getCanvas()->clear(SK_ColorBLUE); 726eaaaf0b16c4e55ff8a48c5ac1ed623a6ba469053bsalomon 727eaaaf0b16c4e55ff8a48c5ac1ed623a6ba469053bsalomon // They don't share a texture anymore. They should each have made their own budget 728eaaaf0b16c4e55ff8a48c5ac1ed623a6ba469053bsalomon // decision. 729eaaaf0b16c4e55ff8a48c5ac1ed623a6ba469053bsalomon REPORTER_ASSERT(reporter, sbudgeted == is_budgeted(surface)); 730eaaaf0b16c4e55ff8a48c5ac1ed623a6ba469053bsalomon REPORTER_ASSERT(reporter, ibudgeted == is_budgeted(image)); 731eaaaf0b16c4e55ff8a48c5ac1ed623a6ba469053bsalomon } 732eaaaf0b16c4e55ff8a48c5ac1ed623a6ba469053bsalomon } 733eaaaf0b16c4e55ff8a48c5ac1ed623a6ba469053bsalomon} 734b516a4177931b8febf859752b49f094f70539eaejunov@chromium.org#endif 735da90474b5fcc019fb0971d12360bd05213ad4dc8junov@chromium.org 736179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunenstatic void test_no_canvas1(skiatest::Reporter* reporter, 737179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen SkSurface* surface, 738179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen SkSurface::ContentChangeMode mode) { 739179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen // Test passes by not asserting 740179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen surface->notifyContentWillChange(mode); 741179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen SkDEBUGCODE(surface->validate();) 742179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen} 743179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunenstatic void test_no_canvas2(skiatest::Reporter* reporter, 744179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen SkSurface* surface, 745179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen SkSurface::ContentChangeMode mode) { 746acea3ef448c9903de3aa6a013c839dce577e6ce3junov@chromium.org // Verifies the robustness of SkSurface for handling use cases where calls 747acea3ef448c9903de3aa6a013c839dce577e6ce3junov@chromium.org // are made before a canvas is created. 7489ce9d6772df650ceb0511f275e1a83dffa78ff72reed sk_sp<SkImage> image1 = surface->makeImageSnapshot(); 7499ce9d6772df650ceb0511f275e1a83dffa78ff72reed sk_sp<SkImage> aur_image1(image1); 750179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen SkDEBUGCODE(image1->validate();) 751179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen SkDEBUGCODE(surface->validate();) 752179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen surface->notifyContentWillChange(mode); 753179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen SkDEBUGCODE(image1->validate();) 754179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen SkDEBUGCODE(surface->validate();) 7559ce9d6772df650ceb0511f275e1a83dffa78ff72reed sk_sp<SkImage> image2 = surface->makeImageSnapshot(); 7569ce9d6772df650ceb0511f275e1a83dffa78ff72reed sk_sp<SkImage> aur_image2(image2); 757179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen SkDEBUGCODE(image2->validate();) 758179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen SkDEBUGCODE(surface->validate();) 759179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen REPORTER_ASSERT(reporter, image1 != image2); 760179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen} 761179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunenDEF_TEST(SurfaceNoCanvas, reporter) { 762179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen SkSurface::ContentChangeMode modes[] = 763179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen { SkSurface::kDiscard_ContentChangeMode, SkSurface::kRetain_ContentChangeMode}; 764179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen for (auto& test_func : { &test_no_canvas1, &test_no_canvas2 }) { 765179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen for (auto& mode : modes) { 766e8f3062a36d3682f4019309a32b5b84dc9eddf8creed test_func(reporter, create_surface().get(), mode); 767179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen } 768acea3ef448c9903de3aa6a013c839dce577e6ce3junov@chromium.org } 769acea3ef448c9903de3aa6a013c839dce577e6ce3junov@chromium.org} 770b516a4177931b8febf859752b49f094f70539eaejunov@chromium.org#if SK_SUPPORT_GPU 771758586c7f11a6b3529bd4a1c9b4e982a0d0b0582bsalomonDEF_GPUTEST_FOR_GL_RENDERING_CONTEXTS(SurfaceNoCanvas_Gpu, reporter, ctxInfo) { 772179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen SkSurface::ContentChangeMode modes[] = 773179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen { SkSurface::kDiscard_ContentChangeMode, SkSurface::kRetain_ContentChangeMode}; 774179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen for (auto& surface_func : { &create_gpu_surface, &create_gpu_scratch_surface }) { 775179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen for (auto& test_func : { &test_no_canvas1, &test_no_canvas2 }) { 776179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen for (auto& mode : modes) { 777f2f1c17e331fe1e0ce695969970ecebc81e12cebbsalomon auto surface(surface_func(ctxInfo.fGrContext, kPremul_SkAlphaType, nullptr)); 778e8f3062a36d3682f4019309a32b5b84dc9eddf8creed test_func(reporter, surface.get(), mode); 779e904c09a3a9c701e8d91f2f6ee161feda7615d90bsalomon } 7803bddb38e6468c6294e40e5307f05e6b56bdd6a6crobertphillips@google.com } 781af0583528c7dd5344abfe14347377011abe374e2junov@chromium.org } 782995beb6b00afc0e28f5effc8a22a7a3dcb2544e8junov@chromium.org} 783179a8f5f7feab052e24596d0d04ab5cf2ccab5e0kkinnunen#endif 7849cd016e9b63f3827580d5b19a187dbf26b8e1436reed 7859cd016e9b63f3827580d5b19a187dbf26b8e1436reedstatic void check_rowbytes_remain_consistent(SkSurface* surface, skiatest::Reporter* reporter) { 7866ceeebd37a43d879c120b6ba100ae1febdd67a18reed SkPixmap surfacePM; 7876ceeebd37a43d879c120b6ba100ae1febdd67a18reed REPORTER_ASSERT(reporter, surface->peekPixels(&surfacePM)); 7889cd016e9b63f3827580d5b19a187dbf26b8e1436reed 7899ce9d6772df650ceb0511f275e1a83dffa78ff72reed sk_sp<SkImage> image(surface->makeImageSnapshot()); 7906ceeebd37a43d879c120b6ba100ae1febdd67a18reed SkPixmap pm; 7916ceeebd37a43d879c120b6ba100ae1febdd67a18reed REPORTER_ASSERT(reporter, image->peekPixels(&pm)); 7929cd016e9b63f3827580d5b19a187dbf26b8e1436reed 7936ceeebd37a43d879c120b6ba100ae1febdd67a18reed REPORTER_ASSERT(reporter, surfacePM.rowBytes() == pm.rowBytes()); 7949cd016e9b63f3827580d5b19a187dbf26b8e1436reed 7959cd016e9b63f3827580d5b19a187dbf26b8e1436reed // trigger a copy-on-write 7969cd016e9b63f3827580d5b19a187dbf26b8e1436reed surface->getCanvas()->drawPaint(SkPaint()); 7979ce9d6772df650ceb0511f275e1a83dffa78ff72reed sk_sp<SkImage> image2(surface->makeImageSnapshot()); 7989cd016e9b63f3827580d5b19a187dbf26b8e1436reed REPORTER_ASSERT(reporter, image->uniqueID() != image2->uniqueID()); 7999cd016e9b63f3827580d5b19a187dbf26b8e1436reed 8006ceeebd37a43d879c120b6ba100ae1febdd67a18reed SkPixmap pm2; 8016ceeebd37a43d879c120b6ba100ae1febdd67a18reed REPORTER_ASSERT(reporter, image2->peekPixels(&pm2)); 8026ceeebd37a43d879c120b6ba100ae1febdd67a18reed REPORTER_ASSERT(reporter, pm2.rowBytes() == pm.rowBytes()); 8039cd016e9b63f3827580d5b19a187dbf26b8e1436reed} 8049cd016e9b63f3827580d5b19a187dbf26b8e1436reed 8059cd016e9b63f3827580d5b19a187dbf26b8e1436reedDEF_TEST(surface_rowbytes, reporter) { 8069cd016e9b63f3827580d5b19a187dbf26b8e1436reed const SkImageInfo info = SkImageInfo::MakeN32Premul(100, 100); 8079cd016e9b63f3827580d5b19a187dbf26b8e1436reed 808e8f3062a36d3682f4019309a32b5b84dc9eddf8creed auto surf0(SkSurface::MakeRaster(info)); 809e8f3062a36d3682f4019309a32b5b84dc9eddf8creed check_rowbytes_remain_consistent(surf0.get(), reporter); 8109cd016e9b63f3827580d5b19a187dbf26b8e1436reed 8119cd016e9b63f3827580d5b19a187dbf26b8e1436reed // specify a larger rowbytes 812e8f3062a36d3682f4019309a32b5b84dc9eddf8creed auto surf1(SkSurface::MakeRaster(info, 500, nullptr)); 813e8f3062a36d3682f4019309a32b5b84dc9eddf8creed check_rowbytes_remain_consistent(surf1.get(), reporter); 8149cd016e9b63f3827580d5b19a187dbf26b8e1436reed 8159cd016e9b63f3827580d5b19a187dbf26b8e1436reed // Try some illegal rowByte values 816e8f3062a36d3682f4019309a32b5b84dc9eddf8creed auto s = SkSurface::MakeRaster(info, 396, nullptr); // needs to be at least 400 8179cd016e9b63f3827580d5b19a187dbf26b8e1436reed REPORTER_ASSERT(reporter, nullptr == s); 818e8f3062a36d3682f4019309a32b5b84dc9eddf8creed s = SkSurface::MakeRaster(info, 1 << 30, nullptr); // allocation to large 8199cd016e9b63f3827580d5b19a187dbf26b8e1436reed REPORTER_ASSERT(reporter, nullptr == s); 8209cd016e9b63f3827580d5b19a187dbf26b8e1436reed} 821e63ffef6248bd103b5f7827f1e4bc75e47ca9e20bsalomon 822e63ffef6248bd103b5f7827f1e4bc75e47ca9e20bsalomon#if SK_SUPPORT_GPU 823e63ffef6248bd103b5f7827f1e4bc75e47ca9e20bsalomon 824e8f3062a36d3682f4019309a32b5b84dc9eddf8creedvoid test_surface_clear(skiatest::Reporter* reporter, sk_sp<SkSurface> surface, 825e63ffef6248bd103b5f7827f1e4bc75e47ca9e20bsalomon std::function<GrSurface*(SkSurface*)> grSurfaceGetter, 826e63ffef6248bd103b5f7827f1e4bc75e47ca9e20bsalomon uint32_t expectedValue) { 827e63ffef6248bd103b5f7827f1e4bc75e47ca9e20bsalomon if (!surface) { 828e63ffef6248bd103b5f7827f1e4bc75e47ca9e20bsalomon ERRORF(reporter, "Could not create GPU SkSurface."); 829e63ffef6248bd103b5f7827f1e4bc75e47ca9e20bsalomon return; 830e63ffef6248bd103b5f7827f1e4bc75e47ca9e20bsalomon } 831e63ffef6248bd103b5f7827f1e4bc75e47ca9e20bsalomon int w = surface->width(); 832e63ffef6248bd103b5f7827f1e4bc75e47ca9e20bsalomon int h = surface->height(); 833e63ffef6248bd103b5f7827f1e4bc75e47ca9e20bsalomon SkAutoTDeleteArray<uint32_t> pixels(new uint32_t[w * h]); 834e63ffef6248bd103b5f7827f1e4bc75e47ca9e20bsalomon memset(pixels.get(), ~expectedValue, sizeof(uint32_t) * w * h); 835e63ffef6248bd103b5f7827f1e4bc75e47ca9e20bsalomon 836e8f3062a36d3682f4019309a32b5b84dc9eddf8creed SkAutoTUnref<GrSurface> grSurface(SkSafeRef(grSurfaceGetter(surface.get()))); 837e63ffef6248bd103b5f7827f1e4bc75e47ca9e20bsalomon if (!grSurface) { 838e63ffef6248bd103b5f7827f1e4bc75e47ca9e20bsalomon ERRORF(reporter, "Could access render target of GPU SkSurface."); 839e63ffef6248bd103b5f7827f1e4bc75e47ca9e20bsalomon return; 840e63ffef6248bd103b5f7827f1e4bc75e47ca9e20bsalomon } 8412fba80912027999b560a97a832948c37ab36acfebsalomon surface.reset(); 842e63ffef6248bd103b5f7827f1e4bc75e47ca9e20bsalomon grSurface->readPixels(0, 0, w, h, kRGBA_8888_GrPixelConfig, pixels.get()); 843e63ffef6248bd103b5f7827f1e4bc75e47ca9e20bsalomon for (int y = 0; y < h; ++y) { 844e63ffef6248bd103b5f7827f1e4bc75e47ca9e20bsalomon for (int x = 0; x < w; ++x) { 845e63ffef6248bd103b5f7827f1e4bc75e47ca9e20bsalomon uint32_t pixel = pixels.get()[y * w + x]; 846e63ffef6248bd103b5f7827f1e4bc75e47ca9e20bsalomon if (pixel != expectedValue) { 847e63ffef6248bd103b5f7827f1e4bc75e47ca9e20bsalomon SkString msg; 848e63ffef6248bd103b5f7827f1e4bc75e47ca9e20bsalomon if (expectedValue) { 849e63ffef6248bd103b5f7827f1e4bc75e47ca9e20bsalomon msg = "SkSurface should have left render target unmodified"; 850e63ffef6248bd103b5f7827f1e4bc75e47ca9e20bsalomon } else { 851e63ffef6248bd103b5f7827f1e4bc75e47ca9e20bsalomon msg = "SkSurface should have cleared the render target"; 852e63ffef6248bd103b5f7827f1e4bc75e47ca9e20bsalomon } 853e63ffef6248bd103b5f7827f1e4bc75e47ca9e20bsalomon ERRORF(reporter, 854e63ffef6248bd103b5f7827f1e4bc75e47ca9e20bsalomon "%s but read 0x%08x (instead of 0x%08x) at %x,%d", msg.c_str(), pixel, 855e63ffef6248bd103b5f7827f1e4bc75e47ca9e20bsalomon expectedValue, x, y); 856e63ffef6248bd103b5f7827f1e4bc75e47ca9e20bsalomon return; 857e63ffef6248bd103b5f7827f1e4bc75e47ca9e20bsalomon } 858e63ffef6248bd103b5f7827f1e4bc75e47ca9e20bsalomon } 859e63ffef6248bd103b5f7827f1e4bc75e47ca9e20bsalomon } 860e63ffef6248bd103b5f7827f1e4bc75e47ca9e20bsalomon} 861e63ffef6248bd103b5f7827f1e4bc75e47ca9e20bsalomon 862758586c7f11a6b3529bd4a1c9b4e982a0d0b0582bsalomonDEF_GPUTEST_FOR_GL_RENDERING_CONTEXTS(SurfaceClear_Gpu, reporter, ctxInfo) { 863f2f1c17e331fe1e0ce695969970ecebc81e12cebbsalomon GrContext* context = ctxInfo.fGrContext; 864e63ffef6248bd103b5f7827f1e4bc75e47ca9e20bsalomon std::function<GrSurface*(SkSurface*)> grSurfaceGetters[] = { 865175dd9b5e3d7d749738dac743d2ac360b5340187robertphillips [] (SkSurface* s){ 866175dd9b5e3d7d749738dac743d2ac360b5340187robertphillips GrDrawContext* dc = s->getCanvas()->internal_private_accessTopLayerDrawContext(); 867175dd9b5e3d7d749738dac743d2ac360b5340187robertphillips return dc->accessRenderTarget(); }, 868e63ffef6248bd103b5f7827f1e4bc75e47ca9e20bsalomon [] (SkSurface* s){ 869e63ffef6248bd103b5f7827f1e4bc75e47ca9e20bsalomon SkBaseDevice* d = 870e63ffef6248bd103b5f7827f1e4bc75e47ca9e20bsalomon s->getCanvas()->getDevice_just_for_deprecated_compatibility_testing(); 871e63ffef6248bd103b5f7827f1e4bc75e47ca9e20bsalomon return d->accessRenderTarget(); }, 8729ce9d6772df650ceb0511f275e1a83dffa78ff72reed [] (SkSurface* s){ sk_sp<SkImage> i(s->makeImageSnapshot()); 873e63ffef6248bd103b5f7827f1e4bc75e47ca9e20bsalomon return as_IB(i)->peekTexture(); }, 874e63ffef6248bd103b5f7827f1e4bc75e47ca9e20bsalomon }; 875e63ffef6248bd103b5f7827f1e4bc75e47ca9e20bsalomon for (auto grSurfaceGetter : grSurfaceGetters) { 876e63ffef6248bd103b5f7827f1e4bc75e47ca9e20bsalomon for (auto& surface_func : {&create_gpu_surface, &create_gpu_scratch_surface}) { 877e8f3062a36d3682f4019309a32b5b84dc9eddf8creed auto surface = surface_func(context, kPremul_SkAlphaType, nullptr); 878e63ffef6248bd103b5f7827f1e4bc75e47ca9e20bsalomon test_surface_clear(reporter, surface, grSurfaceGetter, 0x0); 879e63ffef6248bd103b5f7827f1e4bc75e47ca9e20bsalomon } 880e63ffef6248bd103b5f7827f1e4bc75e47ca9e20bsalomon // Wrapped RTs are *not* supposed to clear (to allow client to partially update a surface). 881e63ffef6248bd103b5f7827f1e4bc75e47ca9e20bsalomon static const int kWidth = 10; 882e63ffef6248bd103b5f7827f1e4bc75e47ca9e20bsalomon static const int kHeight = 10; 883e63ffef6248bd103b5f7827f1e4bc75e47ca9e20bsalomon SkAutoTDeleteArray<uint32_t> pixels(new uint32_t[kWidth * kHeight]); 884e63ffef6248bd103b5f7827f1e4bc75e47ca9e20bsalomon memset(pixels.get(), 0xAB, sizeof(uint32_t) * kWidth * kHeight); 885e63ffef6248bd103b5f7827f1e4bc75e47ca9e20bsalomon 886e63ffef6248bd103b5f7827f1e4bc75e47ca9e20bsalomon GrBackendObject textureObject = 887e63ffef6248bd103b5f7827f1e4bc75e47ca9e20bsalomon context->getGpu()->createTestingOnlyBackendTexture(pixels.get(), kWidth, kHeight, 888e63ffef6248bd103b5f7827f1e4bc75e47ca9e20bsalomon kRGBA_8888_GrPixelConfig); 889e63ffef6248bd103b5f7827f1e4bc75e47ca9e20bsalomon 890e63ffef6248bd103b5f7827f1e4bc75e47ca9e20bsalomon GrBackendTextureDesc desc; 891e63ffef6248bd103b5f7827f1e4bc75e47ca9e20bsalomon desc.fConfig = kRGBA_8888_GrPixelConfig; 892e63ffef6248bd103b5f7827f1e4bc75e47ca9e20bsalomon desc.fWidth = kWidth; 893e63ffef6248bd103b5f7827f1e4bc75e47ca9e20bsalomon desc.fHeight = kHeight; 894e63ffef6248bd103b5f7827f1e4bc75e47ca9e20bsalomon desc.fFlags = kRenderTarget_GrBackendTextureFlag; 895e63ffef6248bd103b5f7827f1e4bc75e47ca9e20bsalomon desc.fTextureHandle = textureObject; 896e63ffef6248bd103b5f7827f1e4bc75e47ca9e20bsalomon 897e8f3062a36d3682f4019309a32b5b84dc9eddf8creed auto surface = SkSurface::MakeFromBackendTexture(context, desc, nullptr); 898e63ffef6248bd103b5f7827f1e4bc75e47ca9e20bsalomon test_surface_clear(reporter, surface, grSurfaceGetter, 0xABABABAB); 899e63ffef6248bd103b5f7827f1e4bc75e47ca9e20bsalomon context->getGpu()->deleteTestingOnlyBackendTexture(textureObject); 900e63ffef6248bd103b5f7827f1e4bc75e47ca9e20bsalomon } 901e63ffef6248bd103b5f7827f1e4bc75e47ca9e20bsalomon} 902e63ffef6248bd103b5f7827f1e4bc75e47ca9e20bsalomon#endif 903