SurfaceTest.cpp 51 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158
  1. /*
  2. * Copyright 2013 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. #include "include/core/SkCanvas.h"
  8. #include "include/core/SkData.h"
  9. #include "include/core/SkOverdrawCanvas.h"
  10. #include "include/core/SkPath.h"
  11. #include "include/core/SkRRect.h"
  12. #include "include/core/SkRegion.h"
  13. #include "include/core/SkSurface.h"
  14. #include "include/gpu/GrBackendSurface.h"
  15. #include "include/gpu/GrContext.h"
  16. #include "src/core/SkAutoPixmapStorage.h"
  17. #include "src/core/SkDevice.h"
  18. #include "src/core/SkUtils.h"
  19. #include "src/gpu/GrContextPriv.h"
  20. #include "src/gpu/GrGpu.h"
  21. #include "src/gpu/GrGpuResourcePriv.h"
  22. #include "src/gpu/GrRenderTargetContext.h"
  23. #include "src/gpu/GrResourceProvider.h"
  24. #include "src/gpu/SkGpuDevice.h"
  25. #include "src/image/SkImage_Base.h"
  26. #include "src/image/SkImage_Gpu.h"
  27. #include "src/image/SkSurface_Gpu.h"
  28. #include "tests/Test.h"
  29. #include "tests/TestUtils.h"
  30. #include <functional>
  31. #include <initializer_list>
  32. #include <vector>
  33. #include "tools/ToolUtils.h"
  34. static void release_direct_surface_storage(void* pixels, void* context) {
  35. SkASSERT(pixels == context);
  36. sk_free(pixels);
  37. }
  38. static sk_sp<SkSurface> create_surface(SkAlphaType at = kPremul_SkAlphaType,
  39. SkImageInfo* requestedInfo = nullptr) {
  40. const SkImageInfo info = SkImageInfo::MakeN32(10, 10, at);
  41. if (requestedInfo) {
  42. *requestedInfo = info;
  43. }
  44. return SkSurface::MakeRaster(info);
  45. }
  46. static sk_sp<SkSurface> create_direct_surface(SkAlphaType at = kPremul_SkAlphaType,
  47. SkImageInfo* requestedInfo = nullptr) {
  48. const SkImageInfo info = SkImageInfo::MakeN32(10, 10, at);
  49. if (requestedInfo) {
  50. *requestedInfo = info;
  51. }
  52. const size_t rowBytes = info.minRowBytes();
  53. void* storage = sk_malloc_throw(info.computeByteSize(rowBytes));
  54. return SkSurface::MakeRasterDirectReleaseProc(info, storage, rowBytes,
  55. release_direct_surface_storage,
  56. storage);
  57. }
  58. static sk_sp<SkSurface> create_gpu_surface(GrContext* context, SkAlphaType at = kPremul_SkAlphaType,
  59. SkImageInfo* requestedInfo = nullptr) {
  60. const SkImageInfo info = SkImageInfo::MakeN32(10, 10, at);
  61. if (requestedInfo) {
  62. *requestedInfo = info;
  63. }
  64. return SkSurface::MakeRenderTarget(context, SkBudgeted::kNo, info);
  65. }
  66. static sk_sp<SkSurface> create_gpu_scratch_surface(GrContext* context,
  67. SkAlphaType at = kPremul_SkAlphaType,
  68. SkImageInfo* requestedInfo = nullptr) {
  69. const SkImageInfo info = SkImageInfo::MakeN32(10, 10, at);
  70. if (requestedInfo) {
  71. *requestedInfo = info;
  72. }
  73. return SkSurface::MakeRenderTarget(context, SkBudgeted::kYes, info);
  74. }
  75. DEF_TEST(SurfaceEmpty, reporter) {
  76. const SkImageInfo info = SkImageInfo::Make(0, 0, kN32_SkColorType, kPremul_SkAlphaType);
  77. REPORTER_ASSERT(reporter, nullptr == SkSurface::MakeRaster(info));
  78. REPORTER_ASSERT(reporter, nullptr == SkSurface::MakeRasterDirect(info, nullptr, 0));
  79. }
  80. DEF_GPUTEST_FOR_RENDERING_CONTEXTS(SurfaceEmpty_Gpu, reporter, ctxInfo) {
  81. const SkImageInfo info = SkImageInfo::Make(0, 0, kN32_SkColorType, kPremul_SkAlphaType);
  82. REPORTER_ASSERT(reporter, nullptr ==
  83. SkSurface::MakeRenderTarget(ctxInfo.grContext(), SkBudgeted::kNo, info));
  84. }
  85. DEF_GPUTEST_FOR_RENDERING_CONTEXTS(GrContext_colorTypeSupportedAsSurface, reporter, ctxInfo) {
  86. GrContext* context = ctxInfo.grContext();
  87. for (int ct = 0; ct < kLastEnum_SkColorType; ++ct) {
  88. static constexpr int kSize = 10;
  89. SkColorType colorType = static_cast<SkColorType>(ct);
  90. auto info = SkImageInfo::Make(kSize, kSize, colorType, kOpaque_SkAlphaType, nullptr);
  91. bool can = context->colorTypeSupportedAsSurface(colorType);
  92. auto surf = SkSurface::MakeRenderTarget(context, SkBudgeted::kYes, info, 1, nullptr);
  93. REPORTER_ASSERT(reporter, can == SkToBool(surf), "ct: %d, can: %d, surf: %d",
  94. colorType, can, SkToBool(surf));
  95. GrBackendTexture backendTex = context->createBackendTexture(
  96. kSize, kSize, colorType,
  97. SkColors::kTransparent, GrMipMapped::kNo, GrRenderable::kYes, GrProtected::kNo);
  98. surf = SkSurface::MakeFromBackendTexture(context, backendTex,
  99. kTopLeft_GrSurfaceOrigin, 0, colorType, nullptr,
  100. nullptr);
  101. REPORTER_ASSERT(reporter, can == SkToBool(surf), "ct: %d, can: %d, surf: %d",
  102. colorType, can, SkToBool(surf));
  103. surf = SkSurface::MakeFromBackendTextureAsRenderTarget(context, backendTex,
  104. kTopLeft_GrSurfaceOrigin, 1,
  105. colorType, nullptr, nullptr);
  106. REPORTER_ASSERT(reporter, can == SkToBool(surf), "ct: %d, can: %d, surf: %d",
  107. colorType, can, SkToBool(surf));
  108. surf.reset();
  109. context->flush();
  110. context->deleteBackendTexture(backendTex);
  111. static constexpr int kSampleCnt = 2;
  112. can = context->maxSurfaceSampleCountForColorType(colorType) >= kSampleCnt;
  113. surf = SkSurface::MakeRenderTarget(context, SkBudgeted::kYes, info, kSampleCnt, nullptr);
  114. REPORTER_ASSERT(reporter, can == SkToBool(surf), "ct: %d, can: %d, surf: %d",
  115. colorType, can, SkToBool(surf));
  116. backendTex = context->createBackendTexture(kSize, kSize, colorType,
  117. SkColors::kTransparent,
  118. GrMipMapped::kNo, GrRenderable::kYes,
  119. GrProtected::kNo);
  120. surf = SkSurface::MakeFromBackendTexture(context, backendTex,
  121. kTopLeft_GrSurfaceOrigin, kSampleCnt, colorType,
  122. nullptr, nullptr);
  123. REPORTER_ASSERT(reporter, can == SkToBool(surf),
  124. "colorTypeSupportedAsSurface:%d, surf:%d, ct:%d", can, SkToBool(surf),
  125. colorType);
  126. // Ensure that the sample count stored on the resulting SkSurface is a valid value.
  127. if (surf) {
  128. auto* rtc = ((SkSurface_Gpu*)(surf.get()))->getDevice()->accessRenderTargetContext();
  129. int storedCnt = rtc->numSamples();
  130. int allowedCnt = context->priv().caps()->getRenderTargetSampleCount(
  131. storedCnt, rtc->asSurfaceProxy()->config());
  132. REPORTER_ASSERT(reporter, storedCnt == allowedCnt,
  133. "Should store an allowed sample count (%d vs %d)", allowedCnt,
  134. storedCnt);
  135. }
  136. surf = SkSurface::MakeFromBackendTextureAsRenderTarget(context, backendTex,
  137. kTopLeft_GrSurfaceOrigin, kSampleCnt,
  138. colorType, nullptr, nullptr);
  139. REPORTER_ASSERT(reporter, can == SkToBool(surf),
  140. "colorTypeSupportedAsSurface:%d, surf:%d, ct:%d", can, SkToBool(surf),
  141. colorType);
  142. if (surf) {
  143. auto* rtc = ((SkSurface_Gpu*)(surf.get()))->getDevice()->accessRenderTargetContext();
  144. int storedCnt = rtc->numSamples();
  145. int allowedCnt = context->priv().caps()->getRenderTargetSampleCount(
  146. storedCnt, rtc->asSurfaceProxy()->config());
  147. REPORTER_ASSERT(reporter, storedCnt == allowedCnt,
  148. "Should store an allowed sample count (%d vs %d)", allowedCnt,
  149. storedCnt);
  150. }
  151. surf.reset();
  152. context->flush();
  153. context->deleteBackendTexture(backendTex);
  154. auto* gpu = context->priv().getGpu();
  155. GrBackendRenderTarget backendRenderTarget = gpu->createTestingOnlyBackendRenderTarget(
  156. 16, 16, SkColorTypeToGrColorType(colorType));
  157. can = context->colorTypeSupportedAsSurface(colorType);
  158. surf = SkSurface::MakeFromBackendRenderTarget(context, backendRenderTarget,
  159. kTopLeft_GrSurfaceOrigin, colorType, nullptr,
  160. nullptr);
  161. REPORTER_ASSERT(reporter, can == SkToBool(surf), "ct: %d, can: %d, surf: %d", colorType,
  162. can, SkToBool(surf));
  163. surf.reset();
  164. context->flush();
  165. if (backendRenderTarget.isValid()) {
  166. gpu->deleteTestingOnlyBackendRenderTarget(backendRenderTarget);
  167. }
  168. }
  169. }
  170. DEF_GPUTEST_FOR_RENDERING_CONTEXTS(GrContext_maxSurfaceSamplesForColorType, reporter, ctxInfo) {
  171. GrContext* context = ctxInfo.grContext();
  172. static constexpr int kSize = 10;
  173. for (int ct = 0; ct < kLastEnum_SkColorType; ++ct) {
  174. SkColorType colorType = static_cast<SkColorType>(ct);
  175. int max = context->maxSurfaceSampleCountForColorType(colorType);
  176. if (!max) {
  177. continue;
  178. }
  179. GrBackendTexture backendTex = context->createBackendTexture(
  180. kSize, kSize, colorType, SkColors::kTransparent,
  181. GrMipMapped::kNo, GrRenderable::kYes, GrProtected::kNo);
  182. if (!backendTex.isValid()) {
  183. continue;
  184. }
  185. SkScopeExit freeTex([&backendTex, context] {
  186. context->deleteBackendTexture(backendTex);
  187. });
  188. auto info = SkImageInfo::Make(kSize, kSize, colorType, kOpaque_SkAlphaType, nullptr);
  189. auto surf = SkSurface::MakeFromBackendTexture(context, backendTex,
  190. kTopLeft_GrSurfaceOrigin, max,
  191. colorType, nullptr, nullptr);
  192. REPORTER_ASSERT(reporter, surf);
  193. if (!surf) {
  194. continue;
  195. }
  196. int sampleCnt = ((SkSurface_Gpu*)(surf.get()))
  197. ->getDevice()
  198. ->accessRenderTargetContext()
  199. ->numSamples();
  200. REPORTER_ASSERT(reporter, sampleCnt == max, "Exected: %d, actual: %d", max, sampleCnt);
  201. }
  202. }
  203. static void test_canvas_peek(skiatest::Reporter* reporter,
  204. sk_sp<SkSurface>& surface,
  205. const SkImageInfo& requestInfo,
  206. bool expectPeekSuccess) {
  207. const SkColor color = SK_ColorRED;
  208. const SkPMColor pmcolor = SkPreMultiplyColor(color);
  209. surface->getCanvas()->clear(color);
  210. SkPixmap pmap;
  211. bool success = surface->getCanvas()->peekPixels(&pmap);
  212. REPORTER_ASSERT(reporter, expectPeekSuccess == success);
  213. SkPixmap pmap2;
  214. const void* addr2 = surface->peekPixels(&pmap2) ? pmap2.addr() : nullptr;
  215. if (success) {
  216. REPORTER_ASSERT(reporter, requestInfo == pmap.info());
  217. REPORTER_ASSERT(reporter, requestInfo.minRowBytes() <= pmap.rowBytes());
  218. REPORTER_ASSERT(reporter, pmcolor == *pmap.addr32());
  219. REPORTER_ASSERT(reporter, pmap.addr() == pmap2.addr());
  220. REPORTER_ASSERT(reporter, pmap.info() == pmap2.info());
  221. REPORTER_ASSERT(reporter, pmap.rowBytes() == pmap2.rowBytes());
  222. } else {
  223. REPORTER_ASSERT(reporter, nullptr == addr2);
  224. }
  225. }
  226. DEF_TEST(SurfaceCanvasPeek, reporter) {
  227. for (auto& surface_func : { &create_surface, &create_direct_surface }) {
  228. SkImageInfo requestInfo;
  229. auto surface(surface_func(kPremul_SkAlphaType, &requestInfo));
  230. test_canvas_peek(reporter, surface, requestInfo, true);
  231. }
  232. }
  233. DEF_GPUTEST_FOR_RENDERING_CONTEXTS(SurfaceCanvasPeek_Gpu, reporter, ctxInfo) {
  234. for (auto& surface_func : { &create_gpu_surface, &create_gpu_scratch_surface }) {
  235. SkImageInfo requestInfo;
  236. auto surface(surface_func(ctxInfo.grContext(), kPremul_SkAlphaType, &requestInfo));
  237. test_canvas_peek(reporter, surface, requestInfo, false);
  238. }
  239. }
  240. static void test_snapshot_alphatype(skiatest::Reporter* reporter, const sk_sp<SkSurface>& surface,
  241. SkAlphaType expectedAlphaType) {
  242. REPORTER_ASSERT(reporter, surface);
  243. if (surface) {
  244. sk_sp<SkImage> image(surface->makeImageSnapshot());
  245. REPORTER_ASSERT(reporter, image);
  246. if (image) {
  247. REPORTER_ASSERT(reporter, image->alphaType() == expectedAlphaType);
  248. }
  249. }
  250. }
  251. DEF_TEST(SurfaceSnapshotAlphaType, reporter) {
  252. for (auto& surface_func : { &create_surface, &create_direct_surface }) {
  253. for (auto& at: { kOpaque_SkAlphaType, kPremul_SkAlphaType, kUnpremul_SkAlphaType }) {
  254. auto surface(surface_func(at, nullptr));
  255. test_snapshot_alphatype(reporter, surface, at);
  256. }
  257. }
  258. }
  259. DEF_GPUTEST_FOR_RENDERING_CONTEXTS(SurfaceSnapshotAlphaType_Gpu, reporter, ctxInfo) {
  260. for (auto& surface_func : { &create_gpu_surface, &create_gpu_scratch_surface }) {
  261. // GPU doesn't support creating unpremul surfaces, so only test opaque + premul
  262. for (auto& at : { kOpaque_SkAlphaType, kPremul_SkAlphaType }) {
  263. auto surface(surface_func(ctxInfo.grContext(), at, nullptr));
  264. test_snapshot_alphatype(reporter, surface, at);
  265. }
  266. }
  267. }
  268. static void test_backend_texture_access_copy_on_write(
  269. skiatest::Reporter* reporter, SkSurface* surface, SkSurface::BackendHandleAccess access) {
  270. GrBackendTexture tex1 = surface->getBackendTexture(access);
  271. sk_sp<SkImage> snap1(surface->makeImageSnapshot());
  272. GrBackendTexture tex2 = surface->getBackendTexture(access);
  273. sk_sp<SkImage> snap2(surface->makeImageSnapshot());
  274. // If the access mode triggers CoW, then the backend objects should reflect it.
  275. REPORTER_ASSERT(reporter, GrBackendTexture::TestingOnly_Equals(tex1, tex2) == (snap1 == snap2));
  276. }
  277. static void test_backend_rendertarget_access_copy_on_write(
  278. skiatest::Reporter* reporter, SkSurface* surface, SkSurface::BackendHandleAccess access) {
  279. GrBackendRenderTarget rt1 = surface->getBackendRenderTarget(access);
  280. sk_sp<SkImage> snap1(surface->makeImageSnapshot());
  281. GrBackendRenderTarget rt2 = surface->getBackendRenderTarget(access);
  282. sk_sp<SkImage> snap2(surface->makeImageSnapshot());
  283. // If the access mode triggers CoW, then the backend objects should reflect it.
  284. REPORTER_ASSERT(reporter, GrBackendRenderTarget::TestingOnly_Equals(rt1, rt2) ==
  285. (snap1 == snap2));
  286. }
  287. DEF_GPUTEST_FOR_RENDERING_CONTEXTS(SurfaceBackendSurfaceAccessCopyOnWrite_Gpu, reporter, ctxInfo) {
  288. const SkSurface::BackendHandleAccess accessModes[] = {
  289. SkSurface::kFlushRead_BackendHandleAccess,
  290. SkSurface::kFlushWrite_BackendHandleAccess,
  291. SkSurface::kDiscardWrite_BackendHandleAccess,
  292. };
  293. for (auto& surface_func : { &create_gpu_surface, &create_gpu_scratch_surface }) {
  294. for (auto& accessMode : accessModes) {
  295. {
  296. auto surface(surface_func(ctxInfo.grContext(), kPremul_SkAlphaType, nullptr));
  297. test_backend_texture_access_copy_on_write(reporter, surface.get(), accessMode);
  298. }
  299. {
  300. auto surface(surface_func(ctxInfo.grContext(), kPremul_SkAlphaType, nullptr));
  301. test_backend_rendertarget_access_copy_on_write(reporter, surface.get(), accessMode);
  302. }
  303. }
  304. }
  305. }
  306. template<typename Type, Type(SkSurface::*func)(SkSurface::BackendHandleAccess)>
  307. static void test_backend_unique_id(skiatest::Reporter* reporter, SkSurface* surface) {
  308. sk_sp<SkImage> image0(surface->makeImageSnapshot());
  309. Type obj = (surface->*func)(SkSurface::kFlushRead_BackendHandleAccess);
  310. REPORTER_ASSERT(reporter, obj.isValid());
  311. sk_sp<SkImage> image1(surface->makeImageSnapshot());
  312. // just read access should not affect the snapshot
  313. REPORTER_ASSERT(reporter, image0->uniqueID() == image1->uniqueID());
  314. obj = (surface->*func)(SkSurface::kFlushWrite_BackendHandleAccess);
  315. REPORTER_ASSERT(reporter, obj.isValid());
  316. sk_sp<SkImage> image2(surface->makeImageSnapshot());
  317. // expect a new image, since we claimed we would write
  318. REPORTER_ASSERT(reporter, image0->uniqueID() != image2->uniqueID());
  319. obj = (surface->*func)(SkSurface::kDiscardWrite_BackendHandleAccess);
  320. REPORTER_ASSERT(reporter, obj.isValid());
  321. sk_sp<SkImage> image3(surface->makeImageSnapshot());
  322. // expect a new(er) image, since we claimed we would write
  323. REPORTER_ASSERT(reporter, image0->uniqueID() != image3->uniqueID());
  324. REPORTER_ASSERT(reporter, image2->uniqueID() != image3->uniqueID());
  325. }
  326. // No CPU test.
  327. DEF_GPUTEST_FOR_RENDERING_CONTEXTS(SurfaceBackendHandleAccessIDs_Gpu, reporter, ctxInfo) {
  328. for (auto& surface_func : { &create_gpu_surface, &create_gpu_scratch_surface }) {
  329. {
  330. auto surface(surface_func(ctxInfo.grContext(), kPremul_SkAlphaType, nullptr));
  331. test_backend_unique_id<GrBackendTexture, &SkSurface::getBackendTexture>(reporter,
  332. surface.get());
  333. }
  334. {
  335. auto surface(surface_func(ctxInfo.grContext(), kPremul_SkAlphaType, nullptr));
  336. test_backend_unique_id<GrBackendRenderTarget, &SkSurface::getBackendRenderTarget>(
  337. reporter, surface.get());
  338. }
  339. }
  340. }
  341. // Verify that the right canvas commands trigger a copy on write.
  342. static void test_copy_on_write(skiatest::Reporter* reporter, SkSurface* surface) {
  343. SkCanvas* canvas = surface->getCanvas();
  344. const SkRect testRect =
  345. SkRect::MakeXYWH(SkIntToScalar(0), SkIntToScalar(0),
  346. SkIntToScalar(4), SkIntToScalar(5));
  347. SkPath testPath;
  348. testPath.addRect(SkRect::MakeXYWH(SkIntToScalar(0), SkIntToScalar(0),
  349. SkIntToScalar(2), SkIntToScalar(1)));
  350. const SkIRect testIRect = SkIRect::MakeXYWH(0, 0, 2, 1);
  351. SkRegion testRegion;
  352. testRegion.setRect(testIRect);
  353. const SkColor testColor = 0x01020304;
  354. const SkPaint testPaint;
  355. const SkPoint testPoints[3] = {
  356. {SkIntToScalar(0), SkIntToScalar(0)},
  357. {SkIntToScalar(2), SkIntToScalar(1)},
  358. {SkIntToScalar(0), SkIntToScalar(2)}
  359. };
  360. const size_t testPointCount = 3;
  361. SkBitmap testBitmap;
  362. testBitmap.allocN32Pixels(10, 10);
  363. testBitmap.eraseColor(0);
  364. SkRRect testRRect;
  365. testRRect.setRectXY(testRect, SK_Scalar1, SK_Scalar1);
  366. SkString testText("Hello World");
  367. #define EXPECT_COPY_ON_WRITE(command) \
  368. { \
  369. sk_sp<SkImage> imageBefore = surface->makeImageSnapshot(); \
  370. sk_sp<SkImage> aur_before(imageBefore); \
  371. canvas-> command ; \
  372. sk_sp<SkImage> imageAfter = surface->makeImageSnapshot(); \
  373. sk_sp<SkImage> aur_after(imageAfter); \
  374. REPORTER_ASSERT(reporter, imageBefore != imageAfter); \
  375. }
  376. EXPECT_COPY_ON_WRITE(clear(testColor))
  377. EXPECT_COPY_ON_WRITE(drawPaint(testPaint))
  378. EXPECT_COPY_ON_WRITE(drawPoints(SkCanvas::kPoints_PointMode, testPointCount, testPoints, \
  379. testPaint))
  380. EXPECT_COPY_ON_WRITE(drawOval(testRect, testPaint))
  381. EXPECT_COPY_ON_WRITE(drawRect(testRect, testPaint))
  382. EXPECT_COPY_ON_WRITE(drawRRect(testRRect, testPaint))
  383. EXPECT_COPY_ON_WRITE(drawPath(testPath, testPaint))
  384. EXPECT_COPY_ON_WRITE(drawBitmap(testBitmap, 0, 0))
  385. EXPECT_COPY_ON_WRITE(drawBitmapRect(testBitmap, testRect, nullptr))
  386. EXPECT_COPY_ON_WRITE(drawBitmapNine(testBitmap, testIRect, testRect, nullptr))
  387. EXPECT_COPY_ON_WRITE(drawString(testText, 0, 1, SkFont(), testPaint))
  388. }
  389. DEF_TEST(SurfaceCopyOnWrite, reporter) {
  390. test_copy_on_write(reporter, create_surface().get());
  391. }
  392. DEF_GPUTEST_FOR_RENDERING_CONTEXTS(SurfaceCopyOnWrite_Gpu, reporter, ctxInfo) {
  393. for (auto& surface_func : { &create_gpu_surface, &create_gpu_scratch_surface }) {
  394. auto surface(surface_func(ctxInfo.grContext(), kPremul_SkAlphaType, nullptr));
  395. test_copy_on_write(reporter, surface.get());
  396. }
  397. }
  398. static void test_writable_after_snapshot_release(skiatest::Reporter* reporter,
  399. SkSurface* surface) {
  400. // This test succeeds by not triggering an assertion.
  401. // The test verifies that the surface remains writable (usable) after
  402. // acquiring and releasing a snapshot without triggering a copy on write.
  403. SkCanvas* canvas = surface->getCanvas();
  404. canvas->clear(1);
  405. surface->makeImageSnapshot(); // Create and destroy SkImage
  406. canvas->clear(2); // Must not assert internally
  407. }
  408. DEF_TEST(SurfaceWriteableAfterSnapshotRelease, reporter) {
  409. test_writable_after_snapshot_release(reporter, create_surface().get());
  410. }
  411. DEF_GPUTEST_FOR_RENDERING_CONTEXTS(SurfaceWriteableAfterSnapshotRelease_Gpu, reporter, ctxInfo) {
  412. for (auto& surface_func : { &create_gpu_surface, &create_gpu_scratch_surface }) {
  413. auto surface(surface_func(ctxInfo.grContext(), kPremul_SkAlphaType, nullptr));
  414. test_writable_after_snapshot_release(reporter, surface.get());
  415. }
  416. }
  417. static void test_crbug263329(skiatest::Reporter* reporter,
  418. SkSurface* surface1,
  419. SkSurface* surface2) {
  420. // This is a regression test for crbug.com/263329
  421. // Bug was caused by onCopyOnWrite releasing the old surface texture
  422. // back to the scratch texture pool even though the texture is used
  423. // by and active SkImage_Gpu.
  424. SkCanvas* canvas1 = surface1->getCanvas();
  425. SkCanvas* canvas2 = surface2->getCanvas();
  426. canvas1->clear(1);
  427. sk_sp<SkImage> image1(surface1->makeImageSnapshot());
  428. // Trigger copy on write, new backing is a scratch texture
  429. canvas1->clear(2);
  430. sk_sp<SkImage> image2(surface1->makeImageSnapshot());
  431. // Trigger copy on write, old backing should not be returned to scratch
  432. // pool because it is held by image2
  433. canvas1->clear(3);
  434. canvas2->clear(4);
  435. sk_sp<SkImage> image3(surface2->makeImageSnapshot());
  436. // Trigger copy on write on surface2. The new backing store should not
  437. // be recycling a texture that is held by an existing image.
  438. canvas2->clear(5);
  439. sk_sp<SkImage> image4(surface2->makeImageSnapshot());
  440. REPORTER_ASSERT(reporter, as_IB(image4)->getTexture() != as_IB(image3)->getTexture());
  441. // The following assertion checks crbug.com/263329
  442. REPORTER_ASSERT(reporter, as_IB(image4)->getTexture() != as_IB(image2)->getTexture());
  443. REPORTER_ASSERT(reporter, as_IB(image4)->getTexture() != as_IB(image1)->getTexture());
  444. REPORTER_ASSERT(reporter, as_IB(image3)->getTexture() != as_IB(image2)->getTexture());
  445. REPORTER_ASSERT(reporter, as_IB(image3)->getTexture() != as_IB(image1)->getTexture());
  446. REPORTER_ASSERT(reporter, as_IB(image2)->getTexture() != as_IB(image1)->getTexture());
  447. }
  448. DEF_GPUTEST_FOR_RENDERING_CONTEXTS(SurfaceCRBug263329_Gpu, reporter, ctxInfo) {
  449. for (auto& surface_func : { &create_gpu_surface, &create_gpu_scratch_surface }) {
  450. auto surface1(surface_func(ctxInfo.grContext(), kPremul_SkAlphaType, nullptr));
  451. auto surface2(surface_func(ctxInfo.grContext(), kPremul_SkAlphaType, nullptr));
  452. test_crbug263329(reporter, surface1.get(), surface2.get());
  453. }
  454. }
  455. DEF_TEST(SurfaceGetTexture, reporter) {
  456. auto surface(create_surface());
  457. sk_sp<SkImage> image(surface->makeImageSnapshot());
  458. REPORTER_ASSERT(reporter, !as_IB(image)->isTextureBacked());
  459. surface->notifyContentWillChange(SkSurface::kDiscard_ContentChangeMode);
  460. REPORTER_ASSERT(reporter, !as_IB(image)->isTextureBacked());
  461. }
  462. DEF_GPUTEST_FOR_RENDERING_CONTEXTS(SurfacepeekTexture_Gpu, reporter, ctxInfo) {
  463. for (auto& surface_func : { &create_gpu_surface, &create_gpu_scratch_surface }) {
  464. auto surface(surface_func(ctxInfo.grContext(), kPremul_SkAlphaType, nullptr));
  465. sk_sp<SkImage> image(surface->makeImageSnapshot());
  466. REPORTER_ASSERT(reporter, as_IB(image)->isTextureBacked());
  467. GrBackendTexture backendTex = image->getBackendTexture(false);
  468. REPORTER_ASSERT(reporter, backendTex.isValid());
  469. surface->notifyContentWillChange(SkSurface::kDiscard_ContentChangeMode);
  470. REPORTER_ASSERT(reporter, as_IB(image)->isTextureBacked());
  471. GrBackendTexture backendTex2 = image->getBackendTexture(false);
  472. REPORTER_ASSERT(reporter, GrBackendTexture::TestingOnly_Equals(backendTex, backendTex2));
  473. }
  474. }
  475. static SkBudgeted is_budgeted(const sk_sp<SkSurface>& surf) {
  476. SkSurface_Gpu* gsurf = (SkSurface_Gpu*)surf.get();
  477. GrRenderTargetProxy* proxy = gsurf->getDevice()->accessRenderTargetContext()
  478. ->asRenderTargetProxy();
  479. return proxy->isBudgeted();
  480. }
  481. static SkBudgeted is_budgeted(SkImage* image) {
  482. return ((SkImage_Gpu*)image)->peekProxy()->isBudgeted();
  483. }
  484. static SkBudgeted is_budgeted(const sk_sp<SkImage> image) {
  485. return is_budgeted(image.get());
  486. }
  487. DEF_GPUTEST_FOR_RENDERING_CONTEXTS(SurfaceBudget, reporter, ctxInfo) {
  488. SkImageInfo info = SkImageInfo::MakeN32Premul(8,8);
  489. for (auto budgeted : { SkBudgeted::kNo, SkBudgeted::kYes }) {
  490. auto surface(SkSurface::MakeRenderTarget(ctxInfo.grContext(), budgeted, info));
  491. SkASSERT(surface);
  492. REPORTER_ASSERT(reporter, budgeted == is_budgeted(surface));
  493. sk_sp<SkImage> image(surface->makeImageSnapshot());
  494. // Initially the image shares a texture with the surface, and the
  495. // the budgets should always match.
  496. REPORTER_ASSERT(reporter, budgeted == is_budgeted(surface));
  497. REPORTER_ASSERT(reporter, budgeted == is_budgeted(image));
  498. // Now trigger copy-on-write
  499. surface->getCanvas()->clear(SK_ColorBLUE);
  500. // They don't share a texture anymore but the budgets should still match.
  501. REPORTER_ASSERT(reporter, budgeted == is_budgeted(surface));
  502. REPORTER_ASSERT(reporter, budgeted == is_budgeted(image));
  503. }
  504. }
  505. static void test_no_canvas1(skiatest::Reporter* reporter,
  506. SkSurface* surface,
  507. SkSurface::ContentChangeMode mode) {
  508. // Test passes by not asserting
  509. surface->notifyContentWillChange(mode);
  510. }
  511. static void test_no_canvas2(skiatest::Reporter* reporter,
  512. SkSurface* surface,
  513. SkSurface::ContentChangeMode mode) {
  514. // Verifies the robustness of SkSurface for handling use cases where calls
  515. // are made before a canvas is created.
  516. sk_sp<SkImage> image1 = surface->makeImageSnapshot();
  517. sk_sp<SkImage> aur_image1(image1);
  518. surface->notifyContentWillChange(mode);
  519. sk_sp<SkImage> image2 = surface->makeImageSnapshot();
  520. sk_sp<SkImage> aur_image2(image2);
  521. REPORTER_ASSERT(reporter, image1 != image2);
  522. }
  523. DEF_TEST(SurfaceNoCanvas, reporter) {
  524. SkSurface::ContentChangeMode modes[] =
  525. { SkSurface::kDiscard_ContentChangeMode, SkSurface::kRetain_ContentChangeMode};
  526. for (auto& test_func : { &test_no_canvas1, &test_no_canvas2 }) {
  527. for (auto& mode : modes) {
  528. test_func(reporter, create_surface().get(), mode);
  529. }
  530. }
  531. }
  532. DEF_GPUTEST_FOR_RENDERING_CONTEXTS(SurfaceNoCanvas_Gpu, reporter, ctxInfo) {
  533. SkSurface::ContentChangeMode modes[] =
  534. { SkSurface::kDiscard_ContentChangeMode, SkSurface::kRetain_ContentChangeMode};
  535. for (auto& surface_func : { &create_gpu_surface, &create_gpu_scratch_surface }) {
  536. for (auto& test_func : { &test_no_canvas1, &test_no_canvas2 }) {
  537. for (auto& mode : modes) {
  538. auto surface(surface_func(ctxInfo.grContext(), kPremul_SkAlphaType, nullptr));
  539. test_func(reporter, surface.get(), mode);
  540. }
  541. }
  542. }
  543. }
  544. static void check_rowbytes_remain_consistent(SkSurface* surface, skiatest::Reporter* reporter) {
  545. SkPixmap surfacePM;
  546. REPORTER_ASSERT(reporter, surface->peekPixels(&surfacePM));
  547. sk_sp<SkImage> image(surface->makeImageSnapshot());
  548. SkPixmap pm;
  549. REPORTER_ASSERT(reporter, image->peekPixels(&pm));
  550. REPORTER_ASSERT(reporter, surfacePM.rowBytes() == pm.rowBytes());
  551. // trigger a copy-on-write
  552. surface->getCanvas()->drawPaint(SkPaint());
  553. sk_sp<SkImage> image2(surface->makeImageSnapshot());
  554. REPORTER_ASSERT(reporter, image->uniqueID() != image2->uniqueID());
  555. SkPixmap pm2;
  556. REPORTER_ASSERT(reporter, image2->peekPixels(&pm2));
  557. REPORTER_ASSERT(reporter, pm2.rowBytes() == pm.rowBytes());
  558. }
  559. DEF_TEST(surface_rowbytes, reporter) {
  560. const SkImageInfo info = SkImageInfo::MakeN32Premul(100, 100);
  561. auto surf0(SkSurface::MakeRaster(info));
  562. check_rowbytes_remain_consistent(surf0.get(), reporter);
  563. // specify a larger rowbytes
  564. auto surf1(SkSurface::MakeRaster(info, 500, nullptr));
  565. check_rowbytes_remain_consistent(surf1.get(), reporter);
  566. // Try some illegal rowByte values
  567. auto s = SkSurface::MakeRaster(info, 396, nullptr); // needs to be at least 400
  568. REPORTER_ASSERT(reporter, nullptr == s);
  569. s = SkSurface::MakeRaster(info, std::numeric_limits<size_t>::max(), nullptr);
  570. REPORTER_ASSERT(reporter, nullptr == s);
  571. }
  572. DEF_TEST(surface_raster_zeroinitialized, reporter) {
  573. sk_sp<SkSurface> s(SkSurface::MakeRasterN32Premul(100, 100));
  574. SkPixmap pixmap;
  575. REPORTER_ASSERT(reporter, s->peekPixels(&pixmap));
  576. for (int i = 0; i < pixmap.info().width(); ++i) {
  577. for (int j = 0; j < pixmap.info().height(); ++j) {
  578. REPORTER_ASSERT(reporter, *pixmap.addr32(i, j) == 0);
  579. }
  580. }
  581. }
  582. static sk_sp<SkSurface> create_gpu_surface_backend_texture(
  583. GrContext* ctx, int sampleCnt, const SkColor4f& color, GrBackendTexture* outTexture) {
  584. // On Pixel and Pixel2XL's with Adreno 530 and 540s, setting width and height to 10s reliably
  585. // triggers what appears to be a driver race condition where the 10x10 surface from the
  586. // OverdrawSurface_gpu test is reused(?) for this surface created by the SurfacePartialDraw_gpu
  587. // test.
  588. //
  589. // Immediately after creation of this surface, readback shows the correct initial solid color.
  590. // However, sometime before content is rendered into the upper half of the surface, the driver
  591. // presumably cleans up the OverdrawSurface_gpu's memory which corrupts this color buffer. The
  592. // top half of the surface is fine after the partially-covering rectangle is drawn, but the
  593. // untouched bottom half contains random pixel values that trigger asserts in the
  594. // SurfacePartialDraw_gpu test for no longer matching the initial color. Running the
  595. // SurfacePartialDraw_gpu test without the OverdrawSurface_gpu test completes successfully.
  596. //
  597. // Requesting a much larger backend texture size seems to prevent it from reusing the same
  598. // memory and avoids the issue.
  599. #if defined(SK_BUILD_FOR_SKQP)
  600. const int kWidth = 10;
  601. const int kHeight = 10;
  602. #else
  603. const int kWidth = 100;
  604. const int kHeight = 100;
  605. #endif
  606. SkImageInfo ii = SkImageInfo::Make(kWidth, kHeight, SkColorType::kRGBA_8888_SkColorType,
  607. kPremul_SkAlphaType);
  608. if (!create_backend_texture(ctx, outTexture, ii, color, GrMipMapped::kNo,
  609. GrRenderable::kYes)) {
  610. return nullptr;
  611. }
  612. sk_sp<SkSurface> surface = SkSurface::MakeFromBackendTexture(ctx, *outTexture,
  613. kTopLeft_GrSurfaceOrigin, sampleCnt,
  614. kRGBA_8888_SkColorType,
  615. nullptr, nullptr);
  616. if (!surface) {
  617. delete_backend_texture(ctx, *outTexture);
  618. return nullptr;
  619. }
  620. return surface;
  621. }
  622. static sk_sp<SkSurface> create_gpu_surface_backend_texture_as_render_target(
  623. GrContext* ctx, int sampleCnt, const SkColor4f& color, GrBackendTexture* outTexture) {
  624. const int kWidth = 10;
  625. const int kHeight = 10;
  626. SkImageInfo ii = SkImageInfo::Make(kWidth, kHeight, SkColorType::kRGBA_8888_SkColorType,
  627. kPremul_SkAlphaType);
  628. if (!create_backend_texture(ctx, outTexture, ii, color, GrMipMapped::kNo,
  629. GrRenderable::kYes)) {
  630. return nullptr;
  631. }
  632. sk_sp<SkSurface> surface = SkSurface::MakeFromBackendTextureAsRenderTarget(
  633. ctx, *outTexture, kTopLeft_GrSurfaceOrigin, sampleCnt, kRGBA_8888_SkColorType,
  634. nullptr, nullptr);
  635. if (!surface) {
  636. delete_backend_texture(ctx, *outTexture);
  637. return nullptr;
  638. }
  639. return surface;
  640. }
  641. static void test_surface_clear(skiatest::Reporter* reporter, sk_sp<SkSurface> surface,
  642. std::function<sk_sp<GrSurfaceContext>(SkSurface*)> grSurfaceGetter,
  643. uint32_t expectedValue) {
  644. if (!surface) {
  645. ERRORF(reporter, "Could not create GPU SkSurface.");
  646. return;
  647. }
  648. int w = surface->width();
  649. int h = surface->height();
  650. std::unique_ptr<uint32_t[]> pixels(new uint32_t[w * h]);
  651. sk_memset32(pixels.get(), ~expectedValue, w * h);
  652. sk_sp<GrSurfaceContext> grSurfaceContext(grSurfaceGetter(surface.get()));
  653. if (!grSurfaceContext) {
  654. ERRORF(reporter, "Could access render target of GPU SkSurface.");
  655. return;
  656. }
  657. surface.reset();
  658. SkImageInfo ii = SkImageInfo::Make(w, h, kRGBA_8888_SkColorType, kPremul_SkAlphaType);
  659. grSurfaceContext->readPixels(ii, pixels.get(), 0, {0, 0});
  660. for (int y = 0; y < h; ++y) {
  661. for (int x = 0; x < w; ++x) {
  662. uint32_t pixel = pixels.get()[y * w + x];
  663. if (pixel != expectedValue) {
  664. SkString msg;
  665. if (expectedValue) {
  666. msg = "SkSurface should have left render target unmodified";
  667. } else {
  668. msg = "SkSurface should have cleared the render target";
  669. }
  670. ERRORF(reporter,
  671. "%s but read 0x%08x (instead of 0x%08x) at %x,%d", msg.c_str(), pixel,
  672. expectedValue, x, y);
  673. return;
  674. }
  675. }
  676. }
  677. }
  678. DEF_GPUTEST_FOR_GL_RENDERING_CONTEXTS(SurfaceClear_Gpu, reporter, ctxInfo) {
  679. GrContext* context = ctxInfo.grContext();
  680. std::function<sk_sp<GrSurfaceContext>(SkSurface*)> grSurfaceContextGetters[] = {
  681. [] (SkSurface* s){
  682. return sk_ref_sp(s->getCanvas()->internal_private_accessTopLayerRenderTargetContext());
  683. },
  684. [context] (SkSurface* s){
  685. sk_sp<SkImage> i(s->makeImageSnapshot());
  686. SkImage_Gpu* gpuImage = (SkImage_Gpu *) as_IB(i);
  687. sk_sp<GrTextureProxy> proxy = gpuImage->asTextureProxyRef(context);
  688. return context->priv().makeWrappedSurfaceContext(
  689. std::move(proxy), SkColorTypeToGrColorType(i->colorType()), kPremul_SkAlphaType,
  690. gpuImage->refColorSpace());
  691. }
  692. };
  693. for (auto grSurfaceGetter : grSurfaceContextGetters) {
  694. // Test that non-wrapped RTs are created clear.
  695. for (auto& surface_func : {&create_gpu_surface, &create_gpu_scratch_surface}) {
  696. auto surface = surface_func(context, kPremul_SkAlphaType, nullptr);
  697. test_surface_clear(reporter, surface, grSurfaceGetter, 0x0);
  698. }
  699. // Wrapped RTs are *not* supposed to clear (to allow client to partially update a surface).
  700. const SkColor4f kOrigColor { .67f, .67f, .67f, 1 };
  701. for (auto& surfaceFunc : {&create_gpu_surface_backend_texture,
  702. &create_gpu_surface_backend_texture_as_render_target}) {
  703. GrBackendTexture backendTex;
  704. auto surface = surfaceFunc(context, 1, kOrigColor, &backendTex);
  705. test_surface_clear(reporter, surface, grSurfaceGetter, kOrigColor.toSkColor());
  706. surface.reset();
  707. context->deleteBackendTexture(backendTex);
  708. }
  709. }
  710. }
  711. static void test_surface_draw_partially(
  712. skiatest::Reporter* reporter, sk_sp<SkSurface> surface, uint32_t origColor) {
  713. const int kW = surface->width();
  714. const int kH = surface->height();
  715. SkPaint paint;
  716. const SkColor kRectColor = ~origColor | 0xFF000000;
  717. paint.setColor(kRectColor);
  718. surface->getCanvas()->drawRect(SkRect::MakeWH(SkIntToScalar(kW), SkIntToScalar(kH)/2),
  719. paint);
  720. std::unique_ptr<uint32_t[]> pixels(new uint32_t[kW * kH]);
  721. sk_memset32(pixels.get(), ~origColor, kW * kH);
  722. // Read back RGBA to avoid format conversions that may not be supported on all platforms.
  723. SkImageInfo readInfo = SkImageInfo::Make(kW, kH, kRGBA_8888_SkColorType, kPremul_SkAlphaType);
  724. SkAssertResult(surface->readPixels(readInfo, pixels.get(), kW * sizeof(uint32_t), 0, 0));
  725. bool stop = false;
  726. SkPMColor origColorPM = SkPackARGB_as_RGBA((origColor >> 24 & 0xFF),
  727. (origColor >> 0 & 0xFF),
  728. (origColor >> 8 & 0xFF),
  729. (origColor >> 16 & 0xFF));
  730. SkPMColor rectColorPM = SkPackARGB_as_RGBA((kRectColor >> 24 & 0xFF),
  731. (kRectColor >> 16 & 0xFF),
  732. (kRectColor >> 8 & 0xFF),
  733. (kRectColor >> 0 & 0xFF));
  734. for (int y = 0; y < kH/2 && !stop; ++y) {
  735. for (int x = 0; x < kW && !stop; ++x) {
  736. REPORTER_ASSERT(reporter, rectColorPM == pixels[x + y * kW]);
  737. if (rectColorPM != pixels[x + y * kW]) {
  738. SkDebugf("--- got [%x] expected [%x], x = %d, y = %d\n",
  739. pixels[x + y * kW], rectColorPM, x, y);
  740. stop = true;
  741. }
  742. }
  743. }
  744. stop = false;
  745. for (int y = kH/2; y < kH && !stop; ++y) {
  746. for (int x = 0; x < kW && !stop; ++x) {
  747. REPORTER_ASSERT(reporter, origColorPM == pixels[x + y * kW]);
  748. if (origColorPM != pixels[x + y * kW]) {
  749. SkDebugf("--- got [%x] expected [%x], x = %d, y = %d\n",
  750. pixels[x + y * kW], origColorPM, x, y);
  751. stop = true;
  752. }
  753. }
  754. }
  755. }
  756. DEF_GPUTEST_FOR_RENDERING_CONTEXTS(SurfacePartialDraw_Gpu, reporter, ctxInfo) {
  757. GrContext* context = ctxInfo.grContext();
  758. static const SkColor4f kOrigColor { 0.667f, 0.733f, 0.8f, 1 };
  759. for (auto& surfaceFunc : {&create_gpu_surface_backend_texture,
  760. &create_gpu_surface_backend_texture_as_render_target}) {
  761. // Validate that we can draw to the canvas and that the original texture color is
  762. // preserved in pixels that aren't rendered to via the surface.
  763. // This works only for non-multisampled case.
  764. GrBackendTexture backendTex;
  765. auto surface = surfaceFunc(context, 1, kOrigColor, &backendTex);
  766. if (surface) {
  767. test_surface_draw_partially(reporter, surface, kOrigColor.toSkColor());
  768. surface.reset();
  769. context->deleteBackendTexture(backendTex);
  770. }
  771. }
  772. }
  773. struct ReleaseChecker {
  774. ReleaseChecker() : fReleaseCount(0) {}
  775. int fReleaseCount;
  776. static void Release(void* self) {
  777. static_cast<ReleaseChecker*>(self)->fReleaseCount++;
  778. }
  779. };
  780. DEF_GPUTEST_FOR_RENDERING_CONTEXTS(SurfaceWrappedWithRelease_Gpu, reporter, ctxInfo) {
  781. const int kWidth = 10;
  782. const int kHeight = 10;
  783. GrContext* ctx = ctxInfo.grContext();
  784. GrGpu* gpu = ctx->priv().getGpu();
  785. for (bool useTexture : {false, true}) {
  786. GrBackendTexture backendTex;
  787. GrBackendRenderTarget backendRT;
  788. sk_sp<SkSurface> surface;
  789. ReleaseChecker releaseChecker;
  790. GrSurfaceOrigin texOrigin = kBottomLeft_GrSurfaceOrigin;
  791. if (useTexture) {
  792. SkImageInfo ii = SkImageInfo::Make(kWidth, kHeight, SkColorType::kRGBA_8888_SkColorType,
  793. kPremul_SkAlphaType);
  794. if (!create_backend_texture(ctx, &backendTex, ii, SkColors::kRed, GrMipMapped::kNo,
  795. GrRenderable::kYes)) {
  796. continue;
  797. }
  798. surface = SkSurface::MakeFromBackendTexture(ctx, backendTex, texOrigin, 1,
  799. kRGBA_8888_SkColorType,
  800. nullptr, nullptr,
  801. ReleaseChecker::Release,
  802. &releaseChecker);
  803. } else {
  804. backendRT = gpu->createTestingOnlyBackendRenderTarget(kWidth, kHeight,
  805. GrColorType::kRGBA_8888);
  806. if (!backendRT.isValid()) {
  807. continue;
  808. }
  809. surface = SkSurface::MakeFromBackendRenderTarget(ctx, backendRT, texOrigin,
  810. kRGBA_8888_SkColorType,
  811. nullptr, nullptr,
  812. ReleaseChecker::Release,
  813. &releaseChecker);
  814. }
  815. if (!surface) {
  816. ERRORF(reporter, "Failed to create surface");
  817. continue;
  818. }
  819. surface->getCanvas()->clear(SK_ColorRED);
  820. surface->flush();
  821. gpu->testingOnly_flushGpuAndSync();
  822. // Now exercise the release proc
  823. REPORTER_ASSERT(reporter, 0 == releaseChecker.fReleaseCount);
  824. surface.reset(nullptr); // force a release of the surface
  825. REPORTER_ASSERT(reporter, 1 == releaseChecker.fReleaseCount);
  826. if (useTexture) {
  827. delete_backend_texture(ctx, backendTex);
  828. } else {
  829. gpu->deleteTestingOnlyBackendRenderTarget(backendRT);
  830. }
  831. }
  832. }
  833. DEF_GPUTEST_FOR_GL_RENDERING_CONTEXTS(SurfaceAttachStencil_Gpu, reporter, ctxInfo) {
  834. GrContext* context = ctxInfo.grContext();
  835. const GrCaps* caps = context->priv().caps();
  836. if (caps->avoidStencilBuffers()) {
  837. return;
  838. }
  839. static const SkColor4f kOrigColor { 0.667f, 0.733f, 0.8f, 1 };
  840. auto resourceProvider = context->priv().resourceProvider();
  841. for (auto& surfaceFunc : {&create_gpu_surface_backend_texture,
  842. &create_gpu_surface_backend_texture_as_render_target}) {
  843. for (int sampleCnt : {1, 4, 8}) {
  844. GrBackendTexture backendTex;
  845. auto surface = surfaceFunc(context, sampleCnt, kOrigColor, &backendTex);
  846. if (!surface && sampleCnt > 1) {
  847. // Certain platforms don't support MSAA, skip these.
  848. continue;
  849. }
  850. // Validate that we can attach a stencil buffer to an SkSurface created by either of
  851. // our surface functions.
  852. GrRenderTarget* rt = surface->getCanvas()
  853. ->internal_private_accessTopLayerRenderTargetContext()->accessRenderTarget();
  854. REPORTER_ASSERT(reporter, resourceProvider->attachStencilAttachment(rt, sampleCnt));
  855. context->deleteBackendTexture(backendTex);
  856. }
  857. }
  858. }
  859. DEF_GPUTEST_FOR_RENDERING_CONTEXTS(ReplaceSurfaceBackendTexture, reporter, ctxInfo) {
  860. GrContext* context = ctxInfo.grContext();
  861. for (int sampleCnt : {1, 2}) {
  862. GrBackendTexture backendTexture1;
  863. auto ii = SkImageInfo::Make(10, 10, kRGBA_8888_SkColorType, kPremul_SkAlphaType, nullptr);
  864. if (!create_backend_texture(context, &backendTexture1, ii, SkColors::kTransparent,
  865. GrMipMapped::kNo, GrRenderable::kYes)) {
  866. continue;
  867. }
  868. SkScopeExit delete1(
  869. [context, &backendTexture1] { delete_backend_texture(context, backendTexture1); });
  870. GrBackendTexture backendTexture2;
  871. if (!create_backend_texture(context, &backendTexture2, ii, SkColors::kTransparent,
  872. GrMipMapped::kNo, GrRenderable::kYes)) {
  873. ERRORF(reporter, "Expected to be able to make second texture");
  874. continue;
  875. }
  876. SkScopeExit delete2(
  877. [context, &backendTexture2] { delete_backend_texture(context, backendTexture2); });
  878. auto ii2 = ii.makeWH(8, 8);
  879. GrBackendTexture backendTexture3;
  880. if (!create_backend_texture(context, &backendTexture3, ii2, SkColors::kTransparent,
  881. GrMipMapped::kNo, GrRenderable::kYes)) {
  882. ERRORF(reporter, "Couldn't create different sized texture.");
  883. continue;
  884. }
  885. SkScopeExit delete3(
  886. [context, &backendTexture3] { delete_backend_texture(context, backendTexture3); });
  887. auto surf = SkSurface::MakeFromBackendTexture(
  888. context, backendTexture1, kTopLeft_GrSurfaceOrigin, sampleCnt,
  889. kRGBA_8888_SkColorType, ii.refColorSpace(), nullptr);
  890. if (!surf) {
  891. continue;
  892. }
  893. surf->getCanvas()->clear(SK_ColorBLUE);
  894. // Change matrix, layer, and clip state before swapping out the backing texture.
  895. surf->getCanvas()->translate(5, 5);
  896. surf->getCanvas()->saveLayer(nullptr, nullptr);
  897. surf->getCanvas()->clipRect(SkRect::MakeXYWH(0, 0, 1, 1));
  898. // switch origin while we're at it.
  899. bool replaced = surf->replaceBackendTexture(backendTexture2, kBottomLeft_GrSurfaceOrigin);
  900. REPORTER_ASSERT(reporter, replaced);
  901. SkPaint paint;
  902. paint.setColor(SK_ColorRED);
  903. surf->getCanvas()->drawRect(SkRect::MakeWH(5, 5), paint);
  904. surf->getCanvas()->restore();
  905. // Check that the replacement texture got the right color values.
  906. SkAutoPixmapStorage pm;
  907. pm.alloc(ii);
  908. bool bad = !surf->readPixels(pm, 0, 0);
  909. REPORTER_ASSERT(reporter, !bad, "Could not read surface.");
  910. for (int y = 0; y < ii.height() && !bad; ++y) {
  911. for (int x = 0; x < ii.width() && !bad; ++x) {
  912. auto expected = (x == 5 && y == 5) ? 0xFF0000FF : 0xFFFF0000;
  913. auto found = *pm.addr32(x, y);
  914. if (found != expected) {
  915. bad = true;
  916. ERRORF(reporter, "Expected color 0x%08x, found color 0x%08x at %d, %d.",
  917. expected, found, x, y);
  918. }
  919. }
  920. }
  921. // The original texture should still be all blue.
  922. surf = SkSurface::MakeFromBackendTexture(
  923. context, backendTexture1, kBottomLeft_GrSurfaceOrigin, sampleCnt,
  924. kRGBA_8888_SkColorType, ii.refColorSpace(), nullptr);
  925. if (!surf) {
  926. ERRORF(reporter, "Could not create second surface.");
  927. continue;
  928. }
  929. bad = !surf->readPixels(pm, 0, 0);
  930. REPORTER_ASSERT(reporter, !bad, "Could not read second surface.");
  931. for (int y = 0; y < ii.height() && !bad; ++y) {
  932. for (int x = 0; x < ii.width() && !bad; ++x) {
  933. auto expected = 0xFFFF0000;
  934. auto found = *pm.addr32(x, y);
  935. if (found != expected) {
  936. bad = true;
  937. ERRORF(reporter, "Expected color 0x%08x, found color 0x%08x at %d, %d.",
  938. expected, found, x, y);
  939. }
  940. }
  941. }
  942. // Can't replace with the same texture
  943. REPORTER_ASSERT(reporter,
  944. !surf->replaceBackendTexture(backendTexture1, kTopLeft_GrSurfaceOrigin));
  945. // Can't replace with invalid texture
  946. REPORTER_ASSERT(reporter, !surf->replaceBackendTexture({}, kTopLeft_GrSurfaceOrigin));
  947. // Can't replace with different size texture.
  948. REPORTER_ASSERT(reporter,
  949. !surf->replaceBackendTexture(backendTexture3, kTopLeft_GrSurfaceOrigin));
  950. // Can't replace texture of non-wrapped SkSurface.
  951. surf = SkSurface::MakeRenderTarget(context, SkBudgeted::kYes, ii, sampleCnt, nullptr);
  952. REPORTER_ASSERT(reporter, surf);
  953. if (surf) {
  954. REPORTER_ASSERT(reporter, !surf->replaceBackendTexture(backendTexture1,
  955. kTopLeft_GrSurfaceOrigin));
  956. }
  957. }
  958. }
  959. static void test_overdraw_surface(skiatest::Reporter* r, SkSurface* surface) {
  960. SkOverdrawCanvas canvas(surface->getCanvas());
  961. canvas.drawPaint(SkPaint());
  962. sk_sp<SkImage> image = surface->makeImageSnapshot();
  963. SkBitmap bitmap;
  964. image->asLegacyBitmap(&bitmap);
  965. for (int y = 0; y < 10; y++) {
  966. for (int x = 0; x < 10; x++) {
  967. REPORTER_ASSERT(r, 1 == SkGetPackedA32(*bitmap.getAddr32(x, y)));
  968. }
  969. }
  970. }
  971. DEF_TEST(OverdrawSurface_Raster, r) {
  972. sk_sp<SkSurface> surface = create_surface();
  973. test_overdraw_surface(r, surface.get());
  974. }
  975. DEF_GPUTEST_FOR_RENDERING_CONTEXTS(OverdrawSurface_Gpu, r, ctxInfo) {
  976. GrContext* context = ctxInfo.grContext();
  977. sk_sp<SkSurface> surface = create_gpu_surface(context);
  978. test_overdraw_surface(r, surface.get());
  979. }
  980. DEF_TEST(Surface_null, r) {
  981. REPORTER_ASSERT(r, SkSurface::MakeNull(0, 0) == nullptr);
  982. const int w = 37;
  983. const int h = 1000;
  984. auto surf = SkSurface::MakeNull(w, h);
  985. auto canvas = surf->getCanvas();
  986. canvas->drawPaint(SkPaint()); // should not crash, but don't expect anything to draw
  987. REPORTER_ASSERT(r, surf->makeImageSnapshot() == nullptr);
  988. }
  989. // assert: if a given imageinfo is valid for a surface, then it must be valid for an image
  990. // (so the snapshot can succeed)
  991. DEF_TEST(surface_image_unity, reporter) {
  992. auto do_test = [reporter](const SkImageInfo& info) {
  993. size_t rowBytes = info.minRowBytes();
  994. auto surf = SkSurface::MakeRaster(info, rowBytes, nullptr);
  995. if (surf) {
  996. auto img = surf->makeImageSnapshot();
  997. if (!img && false) { // change to true to document the differences
  998. SkDebugf("image failed: [%08X %08X] %14s %s\n",
  999. info.width(),
  1000. info.height(),
  1001. ToolUtils::colortype_name(info.colorType()),
  1002. ToolUtils::alphatype_name(info.alphaType()));
  1003. return;
  1004. }
  1005. REPORTER_ASSERT(reporter, img != nullptr);
  1006. char dummyPixel = 0; // just need a valid address (not a valid size)
  1007. SkPixmap pmap = { info, &dummyPixel, rowBytes };
  1008. img = SkImage::MakeFromRaster(pmap, nullptr, nullptr);
  1009. REPORTER_ASSERT(reporter, img != nullptr);
  1010. }
  1011. };
  1012. const int32_t sizes[] = { -1, 0, 1, 1 << 18 };
  1013. for (int cti = 0; cti <= kLastEnum_SkColorType; ++cti) {
  1014. SkColorType ct = static_cast<SkColorType>(cti);
  1015. for (int ati = 0; ati <= kLastEnum_SkAlphaType; ++ati) {
  1016. SkAlphaType at = static_cast<SkAlphaType>(ati);
  1017. for (int32_t size : sizes) {
  1018. do_test(SkImageInfo::Make(1, size, ct, at));
  1019. do_test(SkImageInfo::Make(size, 1, ct, at));
  1020. }
  1021. }
  1022. }
  1023. }