Flutter Engine
The Flutter Engine
SurfaceTest.cpp
Go to the documentation of this file.
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
17#include "include/core/SkFont.h"
22#include "include/core/SkPath.h"
26#include "include/core/SkRect.h"
32#include "include/core/SkSize.h"
40#include "include/gpu/GrTypes.h"
67#include "tests/Test.h"
68#include "tests/TestHarness.h"
70#include "tools/ToolUtils.h"
75
76#include <cstddef>
77#include <cstdint>
78#include <initializer_list>
79#include <limits>
80#include <memory>
81#include <utility>
82
84struct GrContextOptions;
85
86static void release_direct_surface_storage(void* pixels, void* context) {
87 SkASSERT(pixels == context);
88 sk_free(pixels);
89}
91 SkImageInfo* requestedInfo = nullptr) {
92 const SkImageInfo info = SkImageInfo::MakeN32(10, 10, at);
93 if (requestedInfo) {
94 *requestedInfo = info;
95 }
97}
99 SkImageInfo* requestedInfo = nullptr) {
100 const SkImageInfo info = SkImageInfo::MakeN32(10, 10, at);
101 if (requestedInfo) {
102 *requestedInfo = info;
103 }
104 const size_t rowBytes = info.minRowBytes();
105 void* storage = sk_malloc_throw(info.computeByteSize(rowBytes));
106 return SkSurfaces::WrapPixels(info, storage, rowBytes, release_direct_surface_storage, storage);
107}
110 SkImageInfo* requestedInfo = nullptr) {
111 const SkImageInfo info = SkImageInfo::MakeN32(10, 10, at);
112 if (requestedInfo) {
113 *requestedInfo = info;
114 }
116}
119 SkImageInfo* requestedInfo = nullptr) {
120 const SkImageInfo info = SkImageInfo::MakeN32(10, 10, at);
121 if (requestedInfo) {
122 *requestedInfo = info;
123 }
125}
126
127DEF_TEST(SurfaceEmpty, reporter) {
128 const SkImageInfo info = SkImageInfo::Make(0, 0, kN32_SkColorType, kPremul_SkAlphaType);
130 REPORTER_ASSERT(reporter, nullptr == SkSurfaces::WrapPixels(info, nullptr, 0));
131}
133 reporter,
134 ctxInfo,
136 const SkImageInfo info = SkImageInfo::Make(0, 0, kN32_SkColorType, kPremul_SkAlphaType);
138 nullptr == SkSurfaces::RenderTarget(
139 ctxInfo.directContext(), skgpu::Budgeted::kNo, info));
140}
141
142DEF_GANESH_TEST_FOR_RENDERING_CONTEXTS(GrContext_colorTypeSupportedAsSurface,
143 reporter,
144 ctxInfo,
146 using namespace skgpu;
147
148 auto context = ctxInfo.directContext();
149
150 Protected isProtected = Protected(context->priv().caps()->supportsProtectedContent());
151
152 for (int ct = 0; ct < kLastEnum_SkColorType; ++ct) {
153 static constexpr int kSize = 10;
154
155 SkColorType colorType = static_cast<SkColorType>(ct);
157
158 {
159 bool can = context->colorTypeSupportedAsSurface(colorType);
160 auto surf = SkSurfaces::RenderTarget(context, Budgeted::kYes, info, 1, nullptr);
161 REPORTER_ASSERT(reporter, can == SkToBool(surf), "ct: %d, can: %d, surf: %d",
162 colorType, can, SkToBool(surf));
163
165 {kSize, kSize},
167 /*sample cnt*/ 1,
168 colorType,
169 /* colorSpace= */ nullptr,
171 isProtected);
172 REPORTER_ASSERT(reporter, can == SkToBool(surf), "ct: %d, can: %d, surf: %d",
173 colorType, can, SkToBool(surf));
174 }
175
176 // The MSAA test only makes sense if the colorType is renderable to begin with.
177 if (context->colorTypeSupportedAsSurface(colorType)) {
178 static constexpr int kSampleCnt = 2;
179
180 bool can = context->maxSurfaceSampleCountForColorType(colorType) >= kSampleCnt;
181 auto surf = SkSurfaces::RenderTarget(
182 context, Budgeted::kYes, info, kSampleCnt, nullptr);
183 REPORTER_ASSERT(reporter, can == SkToBool(surf), "ct: %d, can: %d, surf: %d",
184 colorType, can, SkToBool(surf));
185
187 context, {kSize, kSize}, kTopLeft_GrSurfaceOrigin, kSampleCnt, colorType,
188 /* colorSpace= */ nullptr, Mipmapped::kNo, isProtected);
189 REPORTER_ASSERT(reporter, can == SkToBool(surf),
190 "colorTypeSupportedAsSurface:%d, surf:%d, ct:%d", can, SkToBool(surf),
191 colorType);
192 // Ensure that the sample count stored on the resulting SkSurface is a valid value.
193 if (surf) {
194 auto rtp = skgpu::ganesh::TopDeviceTargetProxy(surf->getCanvas());
195 int storedCnt = rtp->numSamples();
196 const GrBackendFormat& format = rtp->backendFormat();
197 int allowedCnt =
198 context->priv().caps()->getRenderTargetSampleCount(storedCnt, format);
199 REPORTER_ASSERT(reporter, storedCnt == allowedCnt,
200 "Should store an allowed sample count (%d vs %d)", allowedCnt,
201 storedCnt);
202 }
203 }
204
205 for (int sampleCnt : {1, 2}) {
207 {16, 16},
209 sampleCnt,
210 colorType,
211 /* colorSpace= */ nullptr,
212 isProtected);
213 bool can = context->colorTypeSupportedAsSurface(colorType) &&
214 context->maxSurfaceSampleCountForColorType(colorType) >= sampleCnt;
215 if (!surf && can && colorType == kBGRA_8888_SkColorType && sampleCnt > 1 &&
216 context->backend() == GrBackendApi::kOpenGL) {
217 // This is an execeptional case. On iOS GLES we support MSAA BGRA for internally-
218 // created render targets by using a MSAA RGBA8 renderbuffer that resolves to a
219 // BGRA8 texture. However, the GL_APPLE_texture_format_BGRA8888 extension does not
220 // allow creation of BGRA8 renderbuffers and we don't support multisampled textures.
221 // So this is expected to fail. As of 10/5/2020 it actually seems to work to create
222 // a MSAA BGRA8 renderbuffer (at least in the simulator) but we don't want to rely
223 // on this undocumented behavior.
224 continue;
225 }
226 REPORTER_ASSERT(reporter, can == SkToBool(surf), "ct: %d, sc: %d, can: %d, surf: %d",
227 colorType, sampleCnt, can, SkToBool(surf));
228 if (surf) {
229 auto rtp = skgpu::ganesh::TopDeviceTargetProxy(surf->getCanvas());
230 int storedCnt = rtp->numSamples();
231 const GrBackendFormat& backendFormat = rtp->backendFormat();
232 int allowedCnt = context->priv().caps()->getRenderTargetSampleCount(storedCnt,
233 backendFormat);
234 REPORTER_ASSERT(reporter, storedCnt == allowedCnt,
235 "Should store an allowed sample count (%d vs %d)", allowedCnt,
236 storedCnt);
237 }
238 }
239 }
240}
241
242DEF_GANESH_TEST_FOR_RENDERING_CONTEXTS(GrContext_maxSurfaceSamplesForColorType,
243 reporter,
244 ctxInfo,
246 using namespace skgpu;
247
248 auto context = ctxInfo.directContext();
249
250 Protected isProtected = Protected(context->priv().caps()->supportsProtectedContent());
251
252 static constexpr int kSize = 10;
253
254 for (int ct = 0; ct < kLastEnum_SkColorType; ++ct) {
255
256 SkColorType colorType = static_cast<SkColorType>(ct);
257 int maxSampleCnt = context->maxSurfaceSampleCountForColorType(colorType);
258 if (!maxSampleCnt) {
259 continue;
260 }
261 if (!context->colorTypeSupportedAsSurface(colorType)) {
262 continue;
263 }
264
267 context, info, kTopLeft_GrSurfaceOrigin, maxSampleCnt, Mipmapped::kNo, isProtected);
268 if (!surf) {
269 ERRORF(reporter, "Could not make surface of color type %d.", colorType);
270 continue;
271 }
272 int sampleCnt = ((SkSurface_Ganesh*)(surf.get()))->getDevice()->targetProxy()->numSamples();
273 REPORTER_ASSERT(reporter, sampleCnt == maxSampleCnt, "Exected: %d, actual: %d",
274 maxSampleCnt, sampleCnt);
275 }
276}
277
280 const SkImageInfo& requestInfo,
281 bool expectPeekSuccess) {
282 const SkColor color = SK_ColorRED;
283 const SkPMColor pmcolor = SkPreMultiplyColor(color);
284 surface->getCanvas()->clear(color);
285
286 SkPixmap pmap;
287 bool success = surface->getCanvas()->peekPixels(&pmap);
288 REPORTER_ASSERT(reporter, expectPeekSuccess == success);
289
290 SkPixmap pmap2;
291 const void* addr2 = surface->peekPixels(&pmap2) ? pmap2.addr() : nullptr;
292
293 if (success) {
294 REPORTER_ASSERT(reporter, requestInfo == pmap.info());
295 REPORTER_ASSERT(reporter, requestInfo.minRowBytes() <= pmap.rowBytes());
296 REPORTER_ASSERT(reporter, pmcolor == *pmap.addr32());
297
298 REPORTER_ASSERT(reporter, pmap.addr() == pmap2.addr());
299 REPORTER_ASSERT(reporter, pmap.info() == pmap2.info());
300 REPORTER_ASSERT(reporter, pmap.rowBytes() == pmap2.rowBytes());
301 } else {
302 REPORTER_ASSERT(reporter, nullptr == addr2);
303 }
304}
305DEF_TEST(SurfaceCanvasPeek, reporter) {
306 for (auto& surface_func : { &create_surface, &create_direct_surface }) {
307 SkImageInfo requestInfo;
308 auto surface(surface_func(kPremul_SkAlphaType, &requestInfo));
309 test_canvas_peek(reporter, surface, requestInfo, true);
310 }
311}
313 reporter,
314 ctxInfo,
316 for (auto& surface_func : { &create_gpu_surface, &create_gpu_scratch_surface }) {
317 SkImageInfo requestInfo;
318 auto surface(surface_func(ctxInfo.directContext(), kPremul_SkAlphaType, &requestInfo));
319 test_canvas_peek(reporter, surface, requestInfo, false);
320 }
321}
322
324 SkAlphaType expectedAlphaType) {
326 if (surface) {
327 sk_sp<SkImage> image(surface->makeImageSnapshot());
329 if (image) {
330 REPORTER_ASSERT(reporter, image->alphaType() == expectedAlphaType);
331 }
332 }
333}
334DEF_TEST(SurfaceSnapshotAlphaType, reporter) {
335 for (auto& surface_func : { &create_surface, &create_direct_surface }) {
337 auto surface(surface_func(at, nullptr));
339 }
340 }
341}
342DEF_GANESH_TEST_FOR_RENDERING_CONTEXTS(SurfaceSnapshotAlphaType_Gpu,
343 reporter,
344 ctxInfo,
346 for (auto& surface_func : { &create_gpu_surface, &create_gpu_scratch_surface }) {
347 // GPU doesn't support creating unpremul surfaces, so only test opaque + premul
348 for (auto& at : { kOpaque_SkAlphaType, kPremul_SkAlphaType }) {
349 auto surface(surface_func(ctxInfo.directContext(), at, nullptr));
351 }
352 }
353}
354
358 sk_sp<SkImage> snap1(surface->makeImageSnapshot());
359
361 sk_sp<SkImage> snap2(surface->makeImageSnapshot());
362
363 // If the access mode triggers CoW, then the backend objects should reflect it.
364 REPORTER_ASSERT(reporter, GrBackendTexture::TestingOnly_Equals(tex1, tex2) == (snap1 == snap2));
365}
366
370 sk_sp<SkImage> snap1(surface->makeImageSnapshot());
371
373 sk_sp<SkImage> snap2(surface->makeImageSnapshot());
374
375 // If the access mode triggers CoW, then the backend objects should reflect it.
376 REPORTER_ASSERT(reporter, GrBackendRenderTarget::TestingOnly_Equals(rt1, rt2) ==
377 (snap1 == snap2));
378}
379
380DEF_GANESH_TEST_FOR_RENDERING_CONTEXTS(SurfaceBackendSurfaceAccessCopyOnWrite_Gpu,
381 reporter,
382 ctxInfo,
384 const SkSurfaces::BackendHandleAccess accessModes[] = {
388 };
389
390 for (auto& surface_func : { &create_gpu_surface, &create_gpu_scratch_surface }) {
391 for (auto& accessMode : accessModes) {
392 {
393 auto surface(surface_func(ctxInfo.directContext(), kPremul_SkAlphaType, nullptr));
395 }
396 {
397 auto surface(surface_func(ctxInfo.directContext(), kPremul_SkAlphaType, nullptr));
399 }
400 }
401 }
402}
403
404template <typename Type, Type (*func)(SkSurface*, SkSurface::BackendHandleAccess)>
406 sk_sp<SkImage> image0(surface->makeImageSnapshot());
407
409 REPORTER_ASSERT(reporter, obj.isValid());
410 sk_sp<SkImage> image1(surface->makeImageSnapshot());
411 // just read access should not affect the snapshot
412 REPORTER_ASSERT(reporter, image0->uniqueID() == image1->uniqueID());
413
415 REPORTER_ASSERT(reporter, obj.isValid());
416 sk_sp<SkImage> image2(surface->makeImageSnapshot());
417 // expect a new image, since we claimed we would write
418 REPORTER_ASSERT(reporter, image0->uniqueID() != image2->uniqueID());
419
421 REPORTER_ASSERT(reporter, obj.isValid());
422 sk_sp<SkImage> image3(surface->makeImageSnapshot());
423 // expect a new(er) image, since we claimed we would write
424 REPORTER_ASSERT(reporter, image0->uniqueID() != image3->uniqueID());
425 REPORTER_ASSERT(reporter, image2->uniqueID() != image3->uniqueID());
426}
427
428// No CPU test.
429DEF_GANESH_TEST_FOR_RENDERING_CONTEXTS(SurfaceBackendHandleAccessIDs_Gpu,
430 reporter,
431 ctxInfo,
433 for (auto& surface_func : { &create_gpu_surface, &create_gpu_scratch_surface }) {
434 {
435 auto surface(surface_func(ctxInfo.directContext(), kPremul_SkAlphaType, nullptr));
436 test_backend_unique_id<GrBackendTexture, &SkSurfaces::GetBackendTexture>(reporter,
437 surface.get());
438 }
439 {
440 auto surface(surface_func(ctxInfo.directContext(), kPremul_SkAlphaType, nullptr));
441 test_backend_unique_id<GrBackendRenderTarget, &SkSurfaces::GetBackendRenderTarget>(
442 reporter, surface.get());
443 }
444 }
445}
446
447// No CPU test.
448DEF_GANESH_TEST_FOR_RENDERING_CONTEXTS(SurfaceAbandonPostFlush_Gpu,
449 reporter,
450 ctxInfo,
452 auto direct = ctxInfo.directContext();
454 if (!surface) {
455 return;
456 }
457 // This flush can put command buffer refs on the GrGpuResource for the surface.
458 direct->flush(surface.get());
459 direct->abandonContext();
460 // We pass the test if we don't hit any asserts or crashes when the ref on the surface goes away
461 // after we abanonded the context. One thing specifically this checks is to make sure we're
462 // correctly handling the mix of normal refs and command buffer refs, and correctly deleting
463 // the object at the right time.
464}
465
466DEF_GANESH_TEST_FOR_RENDERING_CONTEXTS(SurfaceBackendAccessAbandoned_Gpu,
467 reporter,
468 ctxInfo,
470 auto dContext = ctxInfo.directContext();
472 if (!surface) {
473 return;
474 }
475
482
483 dContext->flush(surface.get());
484 dContext->abandonContext();
485
486 // After abandoning the context none of the backend surfaces should be valid.
493}
494
495// Verify that the right canvas commands trigger a copy on write.
497 SkCanvas* canvas = surface->getCanvas();
498
499 const SkRect testRect =
502 SkPath testPath;
505
506 const SkIRect testIRect = SkIRect::MakeXYWH(0, 0, 2, 1);
507
508 SkRegion testRegion;
509 testRegion.setRect(testIRect);
510
511
512 const SkColor testColor = 0x01020304;
513 const SkPaint testPaint;
514 const SkPoint testPoints[3] = {
518 };
519 const size_t testPointCount = 3;
520
521 SkBitmap testBitmap;
522 testBitmap.allocN32Pixels(10, 10);
523 testBitmap.eraseColor(0);
524
525 SkRRect testRRect;
526 testRRect.setRectXY(testRect, SK_Scalar1, SK_Scalar1);
527
528 SkString testText("Hello World");
529
530#define EXPECT_COPY_ON_WRITE(command) \
531 { \
532 sk_sp<SkImage> imageBefore = surface->makeImageSnapshot(); \
533 sk_sp<SkImage> aur_before(imageBefore); /*NOLINT*/ \
534 canvas-> command ; \
535 sk_sp<SkImage> imageAfter = surface->makeImageSnapshot(); \
536 sk_sp<SkImage> aur_after(imageAfter); /*NOLINT*/ \
537 REPORTER_ASSERT(reporter, imageBefore != imageAfter); \
538 }
539
540 EXPECT_COPY_ON_WRITE(clear(testColor))
541 EXPECT_COPY_ON_WRITE(drawPaint(testPaint))
542 EXPECT_COPY_ON_WRITE(drawPoints(SkCanvas::kPoints_PointMode, testPointCount, testPoints, \
543 testPaint))
544 EXPECT_COPY_ON_WRITE(drawOval(testRect, testPaint))
545 EXPECT_COPY_ON_WRITE(drawRect(testRect, testPaint))
546 EXPECT_COPY_ON_WRITE(drawRRect(testRRect, testPaint))
547 EXPECT_COPY_ON_WRITE(drawPath(testPath, testPaint))
548 EXPECT_COPY_ON_WRITE(drawImage(testBitmap.asImage(), 0, 0))
549 EXPECT_COPY_ON_WRITE(drawImageRect(testBitmap.asImage(), testRect, SkSamplingOptions()))
551}
552DEF_TEST(SurfaceCopyOnWrite, reporter) {
554}
556 reporter,
557 ctxInfo,
559 for (auto& surface_func : { &create_gpu_surface, &create_gpu_scratch_surface }) {
560 auto surface(surface_func(ctxInfo.directContext(), kPremul_SkAlphaType, nullptr));
562 }
563}
564
567 // This test succeeds by not triggering an assertion.
568 // The test verifies that the surface remains writable (usable) after
569 // acquiring and releasing a snapshot without triggering a copy on write.
570 SkCanvas* canvas = surface->getCanvas();
571 canvas->clear(1);
572 surface->makeImageSnapshot(); // Create and destroy SkImage
573 canvas->clear(2); // Must not assert internally
574}
575DEF_TEST(SurfaceWriteableAfterSnapshotRelease, reporter) {
577}
578DEF_GANESH_TEST_FOR_RENDERING_CONTEXTS(SurfaceWriteableAfterSnapshotRelease_Gpu,
579 reporter,
580 ctxInfo,
582 for (auto& surface_func : { &create_gpu_surface, &create_gpu_scratch_surface }) {
583 auto surface(surface_func(ctxInfo.directContext(), kPremul_SkAlphaType, nullptr));
585 }
586}
587
589 SkSurface* surface1,
590 SkSurface* surface2) {
591 // This is a regression test for crbug.com/263329
592 // Bug was caused by onCopyOnWrite releasing the old surface texture
593 // back to the scratch texture pool even though the texture is used
594 // by and active SkImage_Ganesh.
595 SkCanvas* canvas1 = surface1->getCanvas();
596 SkCanvas* canvas2 = surface2->getCanvas();
597 canvas1->clear(1);
598 sk_sp<SkImage> image1(surface1->makeImageSnapshot());
599 // Trigger copy on write, new backing is a scratch texture
600 canvas1->clear(2);
601 sk_sp<SkImage> image2(surface1->makeImageSnapshot());
602 // Trigger copy on write, old backing should not be returned to scratch
603 // pool because it is held by image2
604 canvas1->clear(3);
605
606 canvas2->clear(4);
607 sk_sp<SkImage> image3(surface2->makeImageSnapshot());
608 // Trigger copy on write on surface2. The new backing store should not
609 // be recycling a texture that is held by an existing image.
610 canvas2->clear(5);
611 sk_sp<SkImage> image4(surface2->makeImageSnapshot());
612
613 auto imageProxy = [ctx = surface1->recordingContext()](SkImage* img) {
615 SkASSERT(proxy);
616 return proxy;
617 };
618
619 REPORTER_ASSERT(reporter, imageProxy(image4.get()) != imageProxy(image3.get()));
620 // The following assertion checks crbug.com/263329
621 REPORTER_ASSERT(reporter, imageProxy(image4.get()) != imageProxy(image2.get()));
622 REPORTER_ASSERT(reporter, imageProxy(image4.get()) != imageProxy(image1.get()));
623 REPORTER_ASSERT(reporter, imageProxy(image3.get()) != imageProxy(image2.get()));
624 REPORTER_ASSERT(reporter, imageProxy(image3.get()) != imageProxy(image1.get()));
625 REPORTER_ASSERT(reporter, imageProxy(image2.get()) != imageProxy(image1.get()));
626}
628 reporter,
629 ctxInfo,
631 for (auto& surface_func : { &create_gpu_surface, &create_gpu_scratch_surface }) {
632 auto surface1(surface_func(ctxInfo.directContext(), kPremul_SkAlphaType, nullptr));
633 auto surface2(surface_func(ctxInfo.directContext(), kPremul_SkAlphaType, nullptr));
634 test_crbug263329(reporter, surface1.get(), surface2.get());
635 }
636}
637
638DEF_TEST(SurfaceGetTexture, reporter) {
639 auto surface(create_surface());
640 sk_sp<SkImage> image(surface->makeImageSnapshot());
641 REPORTER_ASSERT(reporter, !as_IB(image)->isTextureBacked());
642 surface->notifyContentWillChange(SkSurface::kDiscard_ContentChangeMode);
643 REPORTER_ASSERT(reporter, !as_IB(image)->isTextureBacked());
644}
646 reporter,
647 ctxInfo,
649 for (auto& surface_func : { &create_gpu_surface, &create_gpu_scratch_surface }) {
650 auto surface(surface_func(ctxInfo.directContext(), kPremul_SkAlphaType, nullptr));
651 sk_sp<SkImage> image(surface->makeImageSnapshot());
652
653 REPORTER_ASSERT(reporter, as_IB(image)->isTextureBacked());
654 GrBackendTexture backendTex;
655 bool ok = SkImages::GetBackendTextureFromImage(image, &backendTex, false);
657 REPORTER_ASSERT(reporter, backendTex.isValid());
658 surface->notifyContentWillChange(SkSurface::kDiscard_ContentChangeMode);
659 REPORTER_ASSERT(reporter, as_IB(image)->isTextureBacked());
660 GrBackendTexture backendTex2;
661 ok = SkImages::GetBackendTextureFromImage(image, &backendTex2, false);
663 REPORTER_ASSERT(reporter, GrBackendTexture::TestingOnly_Equals(backendTex, backendTex2));
664 }
665}
666
668 SkSurface_Ganesh* gsurf = (SkSurface_Ganesh*)surf.get();
669
670 GrRenderTargetProxy* proxy = gsurf->getDevice()->targetProxy();
671 return proxy->isBudgeted();
672}
673
676}
677
679 reporter,
680 ctxInfo,
683 GrDirectContext* dContext = ctxInfo.directContext();
684 for (auto budgeted : {skgpu::Budgeted::kNo, skgpu::Budgeted::kYes}) {
685 auto surface(SkSurfaces::RenderTarget(dContext, budgeted, info));
688
689 sk_sp<SkImage> image(surface->makeImageSnapshot());
690
691 // Initially the image shares a texture with the surface, and the
692 // the budgets should always match.
694 REPORTER_ASSERT(reporter, budgeted == is_budgeted(image.get(), dContext));
695
696 // Now trigger copy-on-write
697 surface->getCanvas()->clear(SK_ColorBLUE);
698
699 // They don't share a texture anymore but the budgets should still match.
701 REPORTER_ASSERT(reporter, budgeted == is_budgeted(image.get(), dContext));
702 }
703}
704
708 // Test passes by not asserting
709 surface->notifyContentWillChange(mode);
710}
714 // Verifies the robustness of SkSurface for handling use cases where calls
715 // are made before a canvas is created.
716 sk_sp<SkImage> image1 = surface->makeImageSnapshot();
717 sk_sp<SkImage> aur_image1(image1); // NOLINT(performance-unnecessary-copy-initialization)
718 surface->notifyContentWillChange(mode);
719 sk_sp<SkImage> image2 = surface->makeImageSnapshot();
720 sk_sp<SkImage> aur_image2(image2); // NOLINT(performance-unnecessary-copy-initialization)
721 REPORTER_ASSERT(reporter, image1 != image2);
722}
723DEF_TEST(SurfaceNoCanvas, reporter) {
726 for (auto& test_func : { &test_no_canvas1, &test_no_canvas2 }) {
727 for (auto& mode : modes) {
728 test_func(reporter, create_surface().get(), mode);
729 }
730 }
731}
733 reporter,
734 ctxInfo,
738 for (auto& surface_func : { &create_gpu_surface, &create_gpu_scratch_surface }) {
739 for (auto& test_func : { &test_no_canvas1, &test_no_canvas2 }) {
740 for (auto& mode : modes) {
741 auto surface(surface_func(ctxInfo.directContext(), kPremul_SkAlphaType, nullptr));
742 test_func(reporter, surface.get(), mode);
743 }
744 }
745 }
746}
747
749 SkPixmap surfacePM;
750 REPORTER_ASSERT(reporter, surface->peekPixels(&surfacePM));
751
752 sk_sp<SkImage> image(surface->makeImageSnapshot());
753 SkPixmap pm;
755
756 REPORTER_ASSERT(reporter, surfacePM.rowBytes() == pm.rowBytes());
757
758 // trigger a copy-on-write
759 surface->getCanvas()->drawPaint(SkPaint());
760 sk_sp<SkImage> image2(surface->makeImageSnapshot());
762
763 SkPixmap pm2;
764 REPORTER_ASSERT(reporter, image2->peekPixels(&pm2));
766}
767
768DEF_TEST(surface_rowbytes, reporter) {
770
771 auto surf0(SkSurfaces::Raster(info));
773
774 // specify a larger rowbytes
775 auto surf1(SkSurfaces::Raster(info, 500, nullptr));
777
778 // Try some illegal rowByte values
779 auto s = SkSurfaces::Raster(info, 396, nullptr); // needs to be at least 400
780 REPORTER_ASSERT(reporter, nullptr == s);
782 REPORTER_ASSERT(reporter, nullptr == s);
783}
784
785DEF_TEST(surface_raster_zeroinitialized, reporter) {
787 SkPixmap pixmap;
788 REPORTER_ASSERT(reporter, s->peekPixels(&pixmap));
789
790 for (int i = 0; i < pixmap.info().width(); ++i) {
791 for (int j = 0; j < pixmap.info().height(); ++j) {
792 REPORTER_ASSERT(reporter, *pixmap.addr32(i, j) == 0);
793 }
794 }
795}
796
798 int sampleCnt,
799 const SkColor4f& color) {
800 // On Pixel and Pixel2XL's with Adreno 530 and 540s, setting width and height to 10s reliably
801 // triggers what appears to be a driver race condition where the 10x10 surface from the
802 // OverdrawSurface_gpu test is reused(?) for this surface created by the SurfacePartialDraw_gpu
803 // test.
804 //
805 // Immediately after creation of this surface, readback shows the correct initial solid color.
806 // However, sometime before content is rendered into the upper half of the surface, the driver
807 // presumably cleans up the OverdrawSurface_gpu's memory which corrupts this color buffer. The
808 // top half of the surface is fine after the partially-covering rectangle is drawn, but the
809 // untouched bottom half contains random pixel values that trigger asserts in the
810 // SurfacePartialDraw_gpu test for no longer matching the initial color. Running the
811 // SurfacePartialDraw_gpu test without the OverdrawSurface_gpu test completes successfully.
812 //
813 // Requesting a much larger backend texture size seems to prevent it from reusing the same
814 // memory and avoids the issue.
815 const SkISize kSize = CurrentTestHarnessIsSkQP() ? SkISize{10, 10} : SkISize{100, 100};
816
817 auto surf = sk_gpu_test::MakeBackendTextureSurface(dContext,
818 kSize,
820 sampleCnt,
822 if (!surf) {
823 return nullptr;
824 }
825 surf->getCanvas()->clear(color);
826 return surf;
827}
828
829static bool supports_readpixels(const GrCaps* caps, SkSurface* surface) {
830 auto surfaceGpu = static_cast<SkSurface_Ganesh*>(surface);
831 GrRenderTarget* rt = surfaceGpu->getDevice()->targetProxy()->peekRenderTarget();
832 if (!rt) {
833 return false;
834 }
836}
837
839 int sampleCnt,
840 const SkColor4f& color) {
841 const int kWidth = 10;
842 const int kHeight = 10;
843
845 {kWidth, kHeight},
847 sampleCnt,
849 if (!surf) {
850 return nullptr;
851 }
852 surf->getCanvas()->clear(color);
853 return surf;
854}
855
857 GrDirectContext* dContext,
858 skgpu::ganesh::SurfaceContext* surfaceContext,
859 uint32_t expectedValue) {
860 int w = surfaceContext->width();
861 int h = surfaceContext->height();
862
864
866 readback.alloc(ii);
867
868 readback.erase(~expectedValue);
869 surfaceContext->readPixels(dContext, readback, {0, 0});
870 for (int y = 0; y < h; ++y) {
871 for (int x = 0; x < w; ++x) {
872 uint32_t pixel = readback.addr32()[y * w + x];
873 if (pixel != expectedValue) {
874 SkString msg;
875 if (expectedValue) {
876 msg = "SkSurface should have left render target unmodified";
877 } else {
878 msg = "SkSurface should have cleared the render target";
879 }
881 "%s but read 0x%08X (instead of 0x%08X) at %d,%d", msg.c_str(), pixel,
882 expectedValue, x, y);
883 return;
884 }
885 }
886 }
887}
888
890 auto dContext = ctxInfo.directContext();
891 // Snaps an image from a surface and then makes a SurfaceContext from the image's texture.
892 auto makeImageSurfaceContext = [dContext](SkSurface* surface) {
893 sk_sp<SkImage> i(surface->makeImageSnapshot());
894 auto [view, ct] = skgpu::ganesh::AsView(dContext, i, skgpu::Mipmapped::kNo);
895 GrColorInfo colorInfo(ct, i->alphaType(), i->refColorSpace());
896 return dContext->priv().makeSC(view, std::move(colorInfo));
897 };
898
899 // Test that non-wrapped RTs are created clear.
900 for (auto& surface_func : {&create_gpu_surface, &create_gpu_scratch_surface}) {
901 auto surface = surface_func(dContext, kPremul_SkAlphaType, nullptr);
902 if (!surface) {
903 ERRORF(reporter, "Could not create GPU SkSurface.");
904 return;
905 }
907 if (!sfc) {
908 ERRORF(reporter, "Could access surface context of GPU SkSurface.");
909 return;
910 }
911 test_surface_context_clear(reporter, dContext, sfc, 0x0);
912 auto imageSurfaceCtx = makeImageSurfaceContext(surface.get());
913 test_surface_context_clear(reporter, dContext, imageSurfaceCtx.get(), 0x0);
914 }
915
916 // Wrapped RTs are *not* supposed to clear (to allow client to partially update a surface).
917 const SkColor4f kOrigColor{.67f, .67f, .67f, 1};
918 for (auto& surfaceFunc :
920 auto surface = surfaceFunc(dContext, 1, kOrigColor);
921 if (!surface) {
922 ERRORF(reporter, "Could not create GPU SkSurface.");
923 return;
924 }
926 if (!sfc) {
927 ERRORF(reporter, "Could access surface context of GPU SkSurface.");
928 return;
929 }
930 test_surface_context_clear(reporter, dContext, sfc, kOrigColor.toSkColor());
931 auto imageSurfaceCtx = makeImageSurfaceContext(surface.get());
932 test_surface_context_clear(reporter, dContext, imageSurfaceCtx.get(),
933 kOrigColor.toSkColor());
934 }
935}
936
939 const int kW = surface->width();
940 const int kH = surface->height();
942 const SkColor kRectColor = ~origColor | 0xFF000000;
943 paint.setColor(kRectColor);
944 surface->getCanvas()->drawRect(SkRect::MakeIWH(kW, kH/2), paint);
945
946 // Read back RGBA to avoid format conversions that may not be supported on all platforms.
948
950 readback.alloc(readInfo);
951
952 readback.erase(~origColor);
953 REPORTER_ASSERT(reporter, surface->readPixels(readback.info(), readback.writable_addr(),
954 readback.rowBytes(), 0, 0));
955 bool stop = false;
956
957 SkPMColor origColorPM = SkPackARGB_as_RGBA(SkColorGetA(origColor),
958 SkColorGetR(origColor),
959 SkColorGetG(origColor),
960 SkColorGetB(origColor));
961 SkPMColor rectColorPM = SkPackARGB_as_RGBA(SkColorGetA(kRectColor),
962 SkColorGetR(kRectColor),
963 SkColorGetG(kRectColor),
964 SkColorGetB(kRectColor));
965
966 for (int y = 0; y < kH/2 && !stop; ++y) {
967 for (int x = 0; x < kW && !stop; ++x) {
968 REPORTER_ASSERT(reporter, rectColorPM == readback.addr32()[x + y * kW]);
969 if (rectColorPM != readback.addr32()[x + y * kW]) {
970 SkDebugf("--- got [%x] expected [%x], x = %d, y = %d\n",
971 readback.addr32()[x + y * kW], rectColorPM, x, y);
972 stop = true;
973 }
974 }
975 }
976 stop = false;
977 for (int y = kH/2; y < kH && !stop; ++y) {
978 for (int x = 0; x < kW && !stop; ++x) {
979 REPORTER_ASSERT(reporter, origColorPM == readback.addr32()[x + y * kW]);
980 if (origColorPM != readback.addr32()[x + y * kW]) {
981 SkDebugf("--- got [%x] expected [%x], x = %d, y = %d\n",
982 readback.addr32()[x + y * kW], origColorPM, x, y);
983 stop = true;
984 }
985 }
986 }
987}
988
990 reporter,
991 ctxInfo,
993 auto context = ctxInfo.directContext();
994
995 static const SkColor4f kOrigColor { 0.667f, 0.733f, 0.8f, 1 };
996
997 for (auto& surfaceFunc :
999 // Validate that we can draw to the canvas and that the original texture color is
1000 // preserved in pixels that aren't rendered to via the surface.
1001 // This works only for non-multisampled case.
1002 auto surface = surfaceFunc(context, 1, kOrigColor);
1003 if (surface && supports_readpixels(context->priv().caps(), surface.get())) {
1004 test_surface_draw_partially(reporter, surface, kOrigColor.toSkColor());
1005 }
1006 }
1007}
1008
1012 static void Release(void* self) {
1013 static_cast<ReleaseChecker*>(self)->fReleaseCount++;
1014 }
1015};
1016
1017DEF_GANESH_TEST_FOR_RENDERING_CONTEXTS(SurfaceWrappedWithRelease_Gpu,
1018 reporter,
1019 ctxInfo,
1021 const int kWidth = 10;
1022 const int kHeight = 10;
1023
1024 auto ctx = ctxInfo.directContext();
1025 GrGpu* gpu = ctx->priv().getGpu();
1026
1027 for (bool useTexture : {false, true}) {
1029 GrBackendRenderTarget backendRT;
1031
1032 ReleaseChecker releaseChecker;
1034
1035 if (useTexture) {
1038 mbet = sk_gpu_test::ManagedBackendTexture::MakeFromInfo(
1040 if (!mbet) {
1041 continue;
1042 }
1043
1045 ctx,
1046 mbet->texture(),
1047 texOrigin,
1048 /*sample count*/ 1,
1050 /*color space*/ nullptr,
1051 /*surface props*/ nullptr,
1052 sk_gpu_test::ManagedBackendTexture::ReleaseProc,
1053 mbet->releaseContext(ReleaseChecker::Release, &releaseChecker));
1054 } else {
1055 backendRT = gpu->createTestingOnlyBackendRenderTarget({kWidth, kHeight},
1057 if (!backendRT.isValid()) {
1058 continue;
1059 }
1061 backendRT,
1062 texOrigin,
1064 nullptr,
1065 nullptr,
1067 &releaseChecker);
1068 }
1069 if (!surface) {
1070 ERRORF(reporter, "Failed to create surface");
1071 continue;
1072 }
1073
1074 surface->getCanvas()->clear(SK_ColorRED);
1075 ctx->flush(surface.get());
1076 ctx->submit(GrSyncCpu::kYes);
1077
1078 // Now exercise the release proc
1079 REPORTER_ASSERT(reporter, 0 == releaseChecker.fReleaseCount);
1080 surface.reset(nullptr); // force a release of the surface
1081 REPORTER_ASSERT(reporter, 1 == releaseChecker.fReleaseCount);
1082
1083 if (!useTexture) {
1084 gpu->deleteTestingOnlyBackendRenderTarget(backendRT);
1085 }
1086 }
1087}
1088
1089DEF_GANESH_TEST_FOR_GL_CONTEXT(SurfaceAttachStencil_Gpu,
1090 reporter,
1091 ctxInfo,
1093 auto context = ctxInfo.directContext();
1094 const GrCaps* caps = context->priv().caps();
1095
1096 if (caps->avoidStencilBuffers()) {
1097 return;
1098 }
1099
1100 static const SkColor4f kOrigColor { 0.667f, 0.733f, 0.8f, 1 };
1101
1102 auto resourceProvider = context->priv().resourceProvider();
1103
1104 for (auto& surfaceFunc :
1106 for (int sampleCnt : {1, 4, 8}) {
1107 auto surface = surfaceFunc(context, sampleCnt, kOrigColor);
1108
1109 if (!surface && sampleCnt > 1) {
1110 // Certain platforms don't support MSAA, skip these.
1111 continue;
1112 }
1113
1114 // Validate that we can attach a stencil buffer to an SkSurface created by either of
1115 // our surface functions.
1116 auto rtp = skgpu::ganesh::TopDeviceTargetProxy(surface->getCanvas());
1117 GrRenderTarget* rt = rtp->peekRenderTarget();
1119 resourceProvider->attachStencilAttachment(rt, rt->numSamples() > 1));
1120 }
1121 }
1122}
1123
1124DEF_GANESH_TEST_FOR_RENDERING_CONTEXTS(ReplaceSurfaceBackendTexture,
1125 reporter,
1126 ctxInfo,
1128 auto context = ctxInfo.directContext();
1129
1130 for (int sampleCnt : {1, 2}) {
1132 auto mbet1 = sk_gpu_test::ManagedBackendTexture::MakeFromInfo(
1134 if (!mbet1) {
1135 continue;
1136 }
1137 auto mbet2 = sk_gpu_test::ManagedBackendTexture::MakeFromInfo(
1139 if (!mbet2) {
1140 ERRORF(reporter, "Expected to be able to make second texture");
1141 continue;
1142 }
1143 auto ii2 = ii.makeWH(8, 8);
1144 auto mbet3 = sk_gpu_test::ManagedBackendTexture::MakeFromInfo(
1146 GrBackendTexture backendTexture3;
1147 if (!mbet3) {
1148 ERRORF(reporter, "Couldn't create different sized texture.");
1149 continue;
1150 }
1151
1152 auto surf = SkSurfaces::WrapBackendTexture(context,
1153 mbet1->texture(),
1155 sampleCnt,
1157 ii.refColorSpace(),
1158 nullptr);
1159 if (!surf) {
1160 continue;
1161 }
1162 surf->getCanvas()->clear(SK_ColorBLUE);
1163 // Change matrix, layer, and clip state before swapping out the backing texture.
1164 surf->getCanvas()->translate(5, 5);
1165 surf->getCanvas()->saveLayer(nullptr, nullptr);
1166 surf->getCanvas()->clipRect(SkRect::MakeXYWH(0, 0, 1, 1));
1167 // switch origin while we're at it.
1168 bool replaced = surf->replaceBackendTexture(mbet2->texture(), kBottomLeft_GrSurfaceOrigin);
1169 REPORTER_ASSERT(reporter, replaced);
1170 SkPaint paint;
1171 paint.setColor(SK_ColorRED);
1172 surf->getCanvas()->drawRect(SkRect::MakeWH(5, 5), paint);
1173 surf->getCanvas()->restore();
1174
1175 // Check that the replacement texture got the right color values.
1177 pm.alloc(ii);
1178 bool bad = !surf->readPixels(pm, 0, 0);
1179 REPORTER_ASSERT(reporter, !bad, "Could not read surface.");
1180 for (int y = 0; y < ii.height() && !bad; ++y) {
1181 for (int x = 0; x < ii.width() && !bad; ++x) {
1182 auto expected = (x == 5 && y == 5) ? 0xFF0000FF : 0xFFFF0000;
1183 auto found = *pm.addr32(x, y);
1184 if (found != expected) {
1185 bad = true;
1186 ERRORF(reporter, "Expected color 0x%08x, found color 0x%08x at %d, %d.",
1187 expected, found, x, y);
1188 }
1189 }
1190 }
1191 // The original texture should still be all blue.
1192 surf = SkSurfaces::WrapBackendTexture(context,
1193 mbet1->texture(),
1195 sampleCnt,
1197 ii.refColorSpace(),
1198 nullptr);
1199 if (!surf) {
1200 ERRORF(reporter, "Could not create second surface.");
1201 continue;
1202 }
1203 bad = !surf->readPixels(pm, 0, 0);
1204 REPORTER_ASSERT(reporter, !bad, "Could not read second surface.");
1205 for (int y = 0; y < ii.height() && !bad; ++y) {
1206 for (int x = 0; x < ii.width() && !bad; ++x) {
1207 auto expected = 0xFFFF0000;
1208 auto found = *pm.addr32(x, y);
1209 if (found != expected) {
1210 bad = true;
1211 ERRORF(reporter, "Expected color 0x%08x, found color 0x%08x at %d, %d.",
1212 expected, found, x, y);
1213 }
1214 }
1215 }
1216
1217 // Can't replace with the same texture
1219 !surf->replaceBackendTexture(mbet1->texture(), kTopLeft_GrSurfaceOrigin));
1220 // Can't replace with invalid texture
1221 REPORTER_ASSERT(reporter, !surf->replaceBackendTexture({}, kTopLeft_GrSurfaceOrigin));
1222 // Can't replace with different size texture.
1224 !surf->replaceBackendTexture(mbet3->texture(), kTopLeft_GrSurfaceOrigin));
1225 // Can't replace texture of non-wrapped SkSurface.
1226 surf = SkSurfaces::RenderTarget(context, skgpu::Budgeted::kYes, ii, sampleCnt, nullptr);
1228 if (surf) {
1229 REPORTER_ASSERT(reporter, !surf->replaceBackendTexture(mbet1->texture(),
1231 }
1232 }
1233}
1234
1236 SkOverdrawCanvas canvas(surface->getCanvas());
1237 canvas.drawPaint(SkPaint());
1238 sk_sp<SkImage> image = surface->makeImageSnapshot();
1239
1242 for (int y = 0; y < 10; y++) {
1243 for (int x = 0; x < 10; x++) {
1244 REPORTER_ASSERT(r, 1 == SkGetPackedA32(*bitmap.getAddr32(x, y)));
1245 }
1246 }
1247}
1248
1249DEF_TEST(OverdrawSurface_Raster, r) {
1252}
1253
1255 r,
1256 ctxInfo,
1258 auto context = ctxInfo.directContext();
1261}
1262
1263DEF_TEST(Surface_null, r) {
1264 REPORTER_ASSERT(r, SkSurfaces::Null(0, 0) == nullptr);
1265
1266 const int w = 37;
1267 const int h = 1000;
1268 auto surf = SkSurfaces::Null(w, h);
1269 auto canvas = surf->getCanvas();
1270
1271 canvas->drawPaint(SkPaint()); // should not crash, but don't expect anything to draw
1272 REPORTER_ASSERT(r, surf->makeImageSnapshot() == nullptr);
1273}
1274
1275// assert: if a given imageinfo is valid for a surface, then it must be valid for an image
1276// (so the snapshot can succeed)
1277DEF_TEST(surface_image_unity, reporter) {
1278 auto do_test = [reporter](const SkImageInfo& info) {
1279 size_t rowBytes = info.minRowBytes();
1280 auto surf = SkSurfaces::Raster(info, rowBytes, nullptr);
1281 if (surf) {
1282 auto img = surf->makeImageSnapshot();
1283 if ((false)) { // change to true to document the differences
1284 if (!img) {
1285 SkDebugf("image failed: [%08X %08X] %14s %s\n",
1286 (uint32_t)info.width(),
1287 (uint32_t)info.height(),
1288 ToolUtils::colortype_name(info.colorType()),
1289 ToolUtils::alphatype_name(info.alphaType()));
1290 return;
1291 }
1292 }
1293 REPORTER_ASSERT(reporter, img != nullptr);
1294
1295 char tempPixel = 0; // just need a valid address (not a valid size)
1296 SkPixmap pmap = { info, &tempPixel, rowBytes };
1297 img = SkImages::RasterFromPixmap(pmap, nullptr, nullptr);
1298 REPORTER_ASSERT(reporter, img != nullptr);
1299 }
1300 };
1301
1302 const int32_t sizes[] = { -1, 0, 1, 1 << 18 };
1303 for (int cti = 0; cti <= kLastEnum_SkColorType; ++cti) {
1304 SkColorType ct = static_cast<SkColorType>(cti);
1305 for (int ati = 0; ati <= kLastEnum_SkAlphaType; ++ati) {
1306 SkAlphaType at = static_cast<SkAlphaType>(ati);
1307 for (int32_t size : sizes) {
1308 do_test(SkImageInfo::Make(1, size, ct, at));
1309 do_test(SkImageInfo::Make(size, 1, ct, at));
1310 }
1311 }
1312 }
1313}
static void readback(const SkBitmap &src, int *result, int resultCount)
Definition: BlurTest.cpp:264
static void info(const char *fmt,...) SK_PRINTF_LIKE(1
Definition: DM.cpp:213
reporter
Definition: FontMgrTest.cpp:39
GrSurfaceOrigin
Definition: GrTypes.h:147
@ kBottomLeft_GrSurfaceOrigin
Definition: GrTypes.h:149
@ kTopLeft_GrSurfaceOrigin
Definition: GrTypes.h:148
skgpu::Protected Protected
kUnpremul_SkAlphaType
SkAlphaType
Definition: SkAlphaType.h:26
@ kOpaque_SkAlphaType
pixel is opaque
Definition: SkAlphaType.h:28
@ kPremul_SkAlphaType
pixel components are premultiplied by alpha
Definition: SkAlphaType.h:29
@ kLastEnum_SkAlphaType
last valid value
Definition: SkAlphaType.h:31
#define SkASSERT(cond)
Definition: SkAssert.h:116
static uint32_t SkPackARGB_as_RGBA(U8CPU a, U8CPU r, U8CPU g, U8CPU b)
Definition: SkColorData.h:65
#define SkGetPackedA32(packed)
Definition: SkColorPriv.h:92
SkColorType
Definition: SkColorType.h:19
@ kBGRA_8888_SkColorType
pixel with 8 bits for blue, green, red, alpha; in 32-bit word
Definition: SkColorType.h:26
@ kLastEnum_SkColorType
last valid value
Definition: SkColorType.h:56
@ kRGBA_8888_SkColorType
pixel with 8 bits for red, green, blue, alpha; in 32-bit word
Definition: SkColorType.h:24
#define SkColorGetR(color)
Definition: SkColor.h:65
#define SkColorGetG(color)
Definition: SkColor.h:69
SK_API SkPMColor SkPreMultiplyColor(SkColor c)
Definition: SkColor.cpp:21
uint32_t SkColor
Definition: SkColor.h:37
uint32_t SkPMColor
Definition: SkColor.h:205
constexpr SkColor SK_ColorBLUE
Definition: SkColor.h:135
constexpr SkColor SK_ColorRED
Definition: SkColor.h:126
#define SkColorGetA(color)
Definition: SkColor.h:61
#define SkColorGetB(color)
Definition: SkColor.h:73
void SK_SPI SkDebugf(const char format[],...) SK_PRINTF_LIKE(1
static SkColorType colorType(AImageDecoder *decoder, const AImageDecoderHeaderInfo *headerInfo)
static bool ok(int result)
static SkImage_Base * as_IB(SkImage *image)
Definition: SkImage_Base.h:201
SK_API void sk_free(void *)
static void * sk_malloc_throw(size_t size)
Definition: SkMalloc.h:67
#define SK_Scalar1
Definition: SkScalar.h:18
#define SkIntToScalar(x)
Definition: SkScalar.h:57
static constexpr bool SkToBool(const T &x)
Definition: SkTo.h:35
static void test_backend_rendertarget_access_copy_on_write(skiatest::Reporter *reporter, SkSurface *surface, SkSurface::BackendHandleAccess access)
static void check_rowbytes_remain_consistent(SkSurface *surface, skiatest::Reporter *reporter)
DEF_GANESH_TEST_FOR_RENDERING_CONTEXTS(SurfaceEmpty_Gpu, reporter, ctxInfo, CtsEnforcement::kApiLevel_T)
static skgpu::Budgeted is_budgeted(const sk_sp< SkSurface > &surf)
DEF_TEST(SurfaceEmpty, reporter)
static void test_surface_draw_partially(skiatest::Reporter *reporter, sk_sp< SkSurface > surface, SkColor origColor)
static void test_surface_context_clear(skiatest::Reporter *reporter, GrDirectContext *dContext, skgpu::ganesh::SurfaceContext *surfaceContext, uint32_t expectedValue)
static void test_overdraw_surface(skiatest::Reporter *r, SkSurface *surface)
static void test_copy_on_write(skiatest::Reporter *reporter, SkSurface *surface)
static void test_backend_texture_access_copy_on_write(skiatest::Reporter *reporter, SkSurface *surface, SkSurface::BackendHandleAccess access)
static void test_writable_after_snapshot_release(skiatest::Reporter *reporter, SkSurface *surface)
DEF_GANESH_TEST_FOR_GL_CONTEXT(SurfaceClear_Gpu, reporter, ctxInfo, CtsEnforcement::kApiLevel_T)
static void test_canvas_peek(skiatest::Reporter *reporter, sk_sp< SkSurface > &surface, const SkImageInfo &requestInfo, bool expectPeekSuccess)
static sk_sp< SkSurface > create_gpu_surface_backend_texture(GrDirectContext *dContext, int sampleCnt, const SkColor4f &color)
static sk_sp< SkSurface > create_surface(SkAlphaType at=kPremul_SkAlphaType, SkImageInfo *requestedInfo=nullptr)
Definition: SurfaceTest.cpp:90
#define EXPECT_COPY_ON_WRITE(command)
static sk_sp< SkSurface > create_gpu_surface_backend_render_target(GrDirectContext *dContext, int sampleCnt, const SkColor4f &color)
static bool supports_readpixels(const GrCaps *caps, SkSurface *surface)
static sk_sp< SkSurface > create_direct_surface(SkAlphaType at=kPremul_SkAlphaType, SkImageInfo *requestedInfo=nullptr)
Definition: SurfaceTest.cpp:98
static void test_no_canvas2(skiatest::Reporter *reporter, SkSurface *surface, SkSurface::ContentChangeMode mode)
static void test_backend_unique_id(skiatest::Reporter *reporter, SkSurface *surface)
static sk_sp< SkSurface > create_gpu_surface(GrRecordingContext *rContext, SkAlphaType at=kPremul_SkAlphaType, SkImageInfo *requestedInfo=nullptr)
static void test_snapshot_alphatype(skiatest::Reporter *reporter, const sk_sp< SkSurface > &surface, SkAlphaType expectedAlphaType)
static sk_sp< SkSurface > create_gpu_scratch_surface(GrRecordingContext *rContext, SkAlphaType at=kPremul_SkAlphaType, SkImageInfo *requestedInfo=nullptr)
static void test_no_canvas1(skiatest::Reporter *reporter, SkSurface *surface, SkSurface::ContentChangeMode mode)
static void test_crbug263329(skiatest::Reporter *reporter, SkSurface *surface1, SkSurface *surface2)
static void release_direct_surface_storage(void *pixels, void *context)
Definition: SurfaceTest.cpp:86
bool CurrentTestHarnessIsSkQP()
Definition: TestHarness.cpp:10
#define REPORTER_ASSERT(r, cond,...)
Definition: Test.h:286
#define ERRORF(r,...)
Definition: Test.h:293
constexpr int kH
constexpr int kW
bool isValid() const
Definition: GrCaps.h:57
virtual SurfaceReadPixelsSupport surfaceSupportsReadPixels(const GrSurface *) const =0
bool avoidStencilBuffers() const
Definition: GrCaps.h:139
Definition: GrGpu.h:62
int numSamples() const
skgpu::Budgeted isBudgeted() const
void alloc(const SkImageInfo &)
sk_sp< SkImage > asImage() const
Definition: SkBitmap.cpp:645
void allocN32Pixels(int width, int height, bool isOpaque=false)
Definition: SkBitmap.cpp:232
void eraseColor(SkColor4f) const
Definition: SkBitmap.cpp:442
void drawPaint(const SkPaint &paint)
Definition: SkCanvas.cpp:1668
void clear(SkColor color)
Definition: SkCanvas.h:1199
@ kPoints_PointMode
draw each point separately
Definition: SkCanvas.h:1241
uint32_t uniqueID() const
Definition: SkImage.h:311
SkAlphaType alphaType() const
Definition: SkImage.cpp:154
bool peekPixels(SkPixmap *pixmap) const
Definition: SkImage.cpp:34
bool asLegacyBitmap(SkBitmap *bitmap, LegacyBitmapMode legacyBitmapMode=kRO_LegacyBitmapMode) const
Definition: SkImage.cpp:233
Definition: SkPath.h:59
SkPath & addRect(const SkRect &rect, SkPathDirection dir, unsigned start)
Definition: SkPath.cpp:864
const uint32_t * addr32() const
Definition: SkPixmap.h:352
size_t rowBytes() const
Definition: SkPixmap.h:145
const SkImageInfo & info() const
Definition: SkPixmap.h:135
const void * addr() const
Definition: SkPixmap.h:153
void setRectXY(const SkRect &rect, SkScalar xRad, SkScalar yRad)
Definition: SkRRect.cpp:52
bool setRect(const SkIRect &rect)
Definition: SkRegion.cpp:192
const char * c_str() const
Definition: SkString.h:133
skgpu::ganesh::Device * getDevice()
ContentChangeMode
Definition: SkSurface.h:203
@ kDiscard_ContentChangeMode
discards surface on change
Definition: SkSurface.h:204
@ kRetain_ContentChangeMode
preserves surface on change
Definition: SkSurface.h:205
SkCanvas * getCanvas()
Definition: SkSurface.cpp:82
GrRecordingContext * recordingContext() const
Definition: SkSurface.cpp:228
sk_sp< SkImage > makeImageSnapshot()
Definition: SkSurface.cpp:90
BackendHandleAccess
Definition: SkSurface.h:229
@ kFlushRead
back-end object is readable
@ kFlushWrite
back-end object is writable
@ kDiscardWrite
back-end object must be overwritten
T * get() const
Definition: SkRefCnt.h:303
GrRenderTargetProxy * targetProxy()
Definition: Device.cpp:1287
bool readPixels(GrDirectContext *dContext, GrPixmap dst, SkIPoint srcPt)
const Paint & paint
Definition: color_source.cc:38
DlColor color
VkSurfaceKHR surface
Definition: main.cc:49
struct MyStruct s
uint32_t uint32_t * format
static SkScalar drawString(SkCanvas *canvas, const SkString &text, SkScalar x, SkScalar y, const SkFont &font)
Definition: fontmgr.cpp:39
static float max(float r, float g, float b)
Definition: hsl.cpp:49
constexpr int kSize
static void drawPath(SkPath &path, SkCanvas *canvas, SkColor color, const SkRect &clip, SkPaint::Cap cap, SkPaint::Join join, SkPaint::Style style, SkPathFillType fill, SkScalar strokeWidth)
Definition: linepaths.cpp:22
double y
double x
SK_API sk_sp< SkImage > RasterFromPixmap(const SkPixmap &pixmap, RasterReleaseProc rasterReleaseProc, ReleaseContext releaseContext)
SK_API bool GetBackendTextureFromImage(const SkImage *img, GrBackendTexture *outTexture, bool flushPendingGrContextIO, GrSurfaceOrigin *origin=nullptr)
sk_sp< const SkImage > image
Definition: SkRecords.h:269
SK_API sk_sp< SkSurface > Raster(const SkImageInfo &imageInfo, size_t rowBytes, const SkSurfaceProps *surfaceProps)
SK_API sk_sp< SkSurface > WrapPixels(const SkImageInfo &imageInfo, void *pixels, size_t rowBytes, const SkSurfaceProps *surfaceProps=nullptr)
SK_API sk_sp< SkSurface > WrapBackendRenderTarget(GrRecordingContext *context, const GrBackendRenderTarget &backendRenderTarget, GrSurfaceOrigin origin, SkColorType colorType, sk_sp< SkColorSpace > colorSpace, const SkSurfaceProps *surfaceProps, RenderTargetReleaseProc releaseProc=nullptr, ReleaseContext releaseContext=nullptr)
SK_API GrBackendTexture GetBackendTexture(SkSurface *, BackendHandleAccess)
SK_API sk_sp< SkSurface > WrapBackendTexture(GrRecordingContext *context, const GrBackendTexture &backendTexture, GrSurfaceOrigin origin, int sampleCnt, SkColorType colorType, sk_sp< SkColorSpace > colorSpace, const SkSurfaceProps *surfaceProps, TextureReleaseProc textureReleaseProc=nullptr, ReleaseContext releaseContext=nullptr)
SK_API GrBackendRenderTarget GetBackendRenderTarget(SkSurface *, BackendHandleAccess)
SK_API sk_sp< SkSurface > RenderTarget(GrRecordingContext *context, skgpu::Budgeted budgeted, const SkImageInfo &imageInfo, int sampleCount, GrSurfaceOrigin surfaceOrigin, const SkSurfaceProps *surfaceProps, bool shouldCreateWithMips=false, bool isProtected=false)
SK_API sk_sp< SkSurface > Null(int width, int height)
SkFont DefaultPortableFont()
const char * colortype_name(SkColorType ct)
Definition: ToolUtils.cpp:65
const char * alphatype_name(SkAlphaType at)
Definition: ToolUtils.cpp:55
Definition: bitmap.py:1
it will be possible to load the file into Perfetto s trace viewer disable asset Prevents usage of any non test fonts unless they were explicitly Loaded via prefetched default font Indicates whether the embedding started a prefetch of the default font manager before creating the engine run In non interactive mode
Definition: switches.h:228
it will be possible to load the file into Perfetto s trace viewer disable asset Prevents usage of any non test fonts unless they were explicitly Loaded via prefetched default font Indicates whether the embedding started a prefetch of the default font manager before creating the engine run In non interactive keep the shell running after the Dart script has completed enable serial On low power devices with low core running concurrent GC tasks on threads can cause them to contend with the UI thread which could potentially lead to jank This option turns off all concurrent GC activities domain network JSON encoded network policy per domain This overrides the DisallowInsecureConnections switch Embedder can specify whether to allow or disallow insecure connections at a domain level old gen heap size
Definition: switches.h:259
const myers::Point & get(const myers::Segment &)
sk_sp< SkSurface > MakeBackendRenderTargetSurface(GrDirectContext *dContext, const SkImageInfo &ii, GrSurfaceOrigin origin, int sampleCnt, GrProtected isProtected, const SkSurfaceProps *props)
GrTextureProxy * GetTextureImageProxy(SkImage *image, GrRecordingContext *rContext)
Definition: ProxyUtils.cpp:32
sk_sp< SkSurface > MakeBackendTextureSurface(GrDirectContext *dContext, const SkImageInfo &ii, GrSurfaceOrigin origin, int sampleCnt, skgpu::Mipmapped mipmapped, GrProtected isProtected, const SkSurfaceProps *props)
SurfaceFillContext * TopDeviceSurfaceFillContext(const SkCanvas *canvas)
Definition: GrCanvas.cpp:27
std::tuple< GrSurfaceProxyView, GrColorType > AsView(GrRecordingContext *rContext, const SkImage *img, skgpu::Mipmapped mipmapped, GrImageTexGenPolicy policy)
GrRenderTargetProxy * TopDeviceTargetProxy(const SkCanvas *canvas)
Definition: GrCanvas.cpp:34
Definition: GpuTools.h:21
Budgeted
Definition: GpuTypes.h:35
Protected
Definition: GpuTypes.h:61
SkScalar w
SkScalar h
int32_t height
int32_t width
static void Release(void *self)
Definition: SkRect.h:32
static constexpr SkIRect MakeXYWH(int32_t x, int32_t y, int32_t w, int32_t h)
Definition: SkRect.h:104
Definition: SkSize.h:16
static SkImageInfo MakeN32Premul(int width, int height)
size_t minRowBytes() const
Definition: SkImageInfo.h:517
static SkImageInfo MakeN32(int width, int height, SkAlphaType at)
static SkImageInfo Make(int width, int height, SkColorType ct, SkAlphaType at)
static SkRect MakeIWH(int w, int h)
Definition: SkRect.h:623
static constexpr SkRect MakeXYWH(float x, float y, float w, float h)
Definition: SkRect.h:659
static constexpr SkRect MakeWH(float w, float h)
Definition: SkRect.h:609
constexpr size_t kHeight
constexpr size_t kWidth