OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2013 Google Inc. | 2 * Copyright 2013 Google Inc. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
6 */ | 6 */ |
7 | 7 |
8 #include <functional> | 8 #include <functional> |
9 #include "SkCanvas.h" | 9 #include "SkCanvas.h" |
10 #include "SkData.h" | 10 #include "SkData.h" |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
76 } | 76 } |
77 #if SK_SUPPORT_GPU | 77 #if SK_SUPPORT_GPU |
78 DEF_GPUTEST_FOR_GL_RENDERING_CONTEXTS(SurfaceEmpty_Gpu, reporter, ctxInfo) { | 78 DEF_GPUTEST_FOR_GL_RENDERING_CONTEXTS(SurfaceEmpty_Gpu, reporter, ctxInfo) { |
79 const SkImageInfo info = SkImageInfo::Make(0, 0, kN32_SkColorType, kPremul_S
kAlphaType); | 79 const SkImageInfo info = SkImageInfo::Make(0, 0, kN32_SkColorType, kPremul_S
kAlphaType); |
80 REPORTER_ASSERT(reporter, nullptr == | 80 REPORTER_ASSERT(reporter, nullptr == |
81 SkSurface::MakeRenderTarget(ctxInfo.fGrContext, SkBudgeted::
kNo, info, 0, | 81 SkSurface::MakeRenderTarget(ctxInfo.fGrContext, SkBudgeted::
kNo, info, 0, |
82 nullptr)); | 82 nullptr)); |
83 } | 83 } |
84 #endif | 84 #endif |
85 | 85 |
| 86 #if SK_SUPPORT_GPU |
| 87 DEF_GPUTEST_FOR_GL_RENDERING_CONTEXTS(SurfaceWrappedTexture, reporter, ctxInfo)
{ |
| 88 GrGpu* gpu = ctxInfo.fGrContext->getGpu(); |
| 89 if (!gpu) { |
| 90 return; |
| 91 } |
| 92 |
| 93 // Test the wrapped factory for SkSurface by creating a backend texture and
then wrap it in |
| 94 // a SkSurface. |
| 95 static const int kW = 100; |
| 96 static const int kH = 100; |
| 97 static const uint32_t kOrigColor = 0xFFAABBCC; |
| 98 SkAutoTArray<uint32_t> pixels(kW * kH); |
| 99 sk_memset32(pixels.get(), kOrigColor, kW * kH); |
| 100 GrBackendObject texHandle = gpu->createTestingOnlyBackendTexture(pixels.get(
), kW, kH, |
| 101 kRGBA_8888_
GrPixelConfig); |
| 102 |
| 103 GrBackendTextureDesc wrappedDesc; |
| 104 wrappedDesc.fConfig = kRGBA_8888_GrPixelConfig; |
| 105 wrappedDesc.fWidth = kW; |
| 106 wrappedDesc.fHeight = kH; |
| 107 wrappedDesc.fOrigin = kBottomLeft_GrSurfaceOrigin; |
| 108 wrappedDesc.fSampleCnt = 0; |
| 109 wrappedDesc.fFlags = kRenderTarget_GrBackendTextureFlag; |
| 110 wrappedDesc.fTextureHandle = texHandle; |
| 111 |
| 112 auto surface(SkSurface::MakeFromBackendTexture(ctxInfo.fGrContext, wrappedDe
sc, nullptr)); |
| 113 REPORTER_ASSERT(reporter, surface); |
| 114 if (surface) { |
| 115 // Validate that we can draw to the canvas and that the original texture
color is preserved |
| 116 // in pixels that aren't rendered to via the surface. |
| 117 SkPaint paint; |
| 118 static const SkColor kRectColor = ~kOrigColor | 0xFF000000; |
| 119 paint.setColor(kRectColor); |
| 120 surface->getCanvas()->drawRect(SkRect::MakeWH(SkIntToScalar(kW), SkIntTo
Scalar(kH)/2), |
| 121 paint); |
| 122 SkImageInfo readInfo = SkImageInfo::MakeN32Premul(kW, kH); |
| 123 surface->readPixels(readInfo, pixels.get(), kW * sizeof(uint32_t), 0, 0)
; |
| 124 bool stop = false; |
| 125 SkPMColor origColorPM = SkPackARGB32((kOrigColor >> 24 & 0xFF), |
| 126 (kOrigColor >> 0 & 0xFF), |
| 127 (kOrigColor >> 8 & 0xFF), |
| 128 (kOrigColor >> 16 & 0xFF)); |
| 129 SkPMColor rectColorPM = SkPackARGB32((kRectColor >> 24 & 0xFF), |
| 130 (kRectColor >> 16 & 0xFF), |
| 131 (kRectColor >> 8 & 0xFF), |
| 132 (kRectColor >> 0 & 0xFF)); |
| 133 for (int y = 0; y < kH/2 && !stop; ++y) { |
| 134 for (int x = 0; x < kW && !stop; ++x) { |
| 135 REPORTER_ASSERT(reporter, rectColorPM == pixels[x + y * kW]); |
| 136 if (rectColorPM != pixels[x + y * kW]) { |
| 137 stop = true; |
| 138 } |
| 139 } |
| 140 } |
| 141 stop = false; |
| 142 for (int y = kH/2; y < kH && !stop; ++y) { |
| 143 for (int x = 0; x < kW && !stop; ++x) { |
| 144 REPORTER_ASSERT(reporter, origColorPM == pixels[x + y * kW]); |
| 145 if (origColorPM != pixels[x + y * kW]) { |
| 146 stop = true; |
| 147 } |
| 148 } |
| 149 } |
| 150 } |
| 151 gpu->deleteTestingOnlyBackendTexture(texHandle); |
| 152 } |
| 153 #endif |
| 154 |
86 static void test_canvas_peek(skiatest::Reporter* reporter, | 155 static void test_canvas_peek(skiatest::Reporter* reporter, |
87 sk_sp<SkSurface>& surface, | 156 sk_sp<SkSurface>& surface, |
88 const SkImageInfo& requestInfo, | 157 const SkImageInfo& requestInfo, |
89 bool expectPeekSuccess) { | 158 bool expectPeekSuccess) { |
90 const SkColor color = SK_ColorRED; | 159 const SkColor color = SK_ColorRED; |
91 const SkPMColor pmcolor = SkPreMultiplyColor(color); | 160 const SkPMColor pmcolor = SkPreMultiplyColor(color); |
92 surface->getCanvas()->clear(color); | 161 surface->getCanvas()->clear(color); |
93 | 162 |
94 SkPixmap pmap; | 163 SkPixmap pmap; |
95 bool success = surface->getCanvas()->peekPixels(&pmap); | 164 bool success = surface->getCanvas()->peekPixels(&pmap); |
(...skipping 648 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
744 check_rowbytes_remain_consistent(surf1.get(), reporter); | 813 check_rowbytes_remain_consistent(surf1.get(), reporter); |
745 | 814 |
746 // Try some illegal rowByte values | 815 // Try some illegal rowByte values |
747 auto s = SkSurface::MakeRaster(info, 396, nullptr); // needs to be at lea
st 400 | 816 auto s = SkSurface::MakeRaster(info, 396, nullptr); // needs to be at lea
st 400 |
748 REPORTER_ASSERT(reporter, nullptr == s); | 817 REPORTER_ASSERT(reporter, nullptr == s); |
749 s = SkSurface::MakeRaster(info, 1 << 30, nullptr); // allocation to large | 818 s = SkSurface::MakeRaster(info, 1 << 30, nullptr); // allocation to large |
750 REPORTER_ASSERT(reporter, nullptr == s); | 819 REPORTER_ASSERT(reporter, nullptr == s); |
751 } | 820 } |
752 | 821 |
753 #if SK_SUPPORT_GPU | 822 #if SK_SUPPORT_GPU |
754 static sk_sp<SkSurface> create_gpu_surface_backend_texture( | |
755 GrContext* context, int sampleCnt, uint32_t color, GrBackendObject* outTextu
re) { | |
756 const int kWidth = 10; | |
757 const int kHeight = 10; | |
758 SkAutoTDeleteArray<uint32_t> pixels(new uint32_t[kWidth * kHeight]); | |
759 sk_memset32(pixels.get(), color, kWidth * kHeight); | |
760 GrBackendTextureDesc desc; | |
761 desc.fConfig = kRGBA_8888_GrPixelConfig; | |
762 desc.fWidth = kWidth; | |
763 desc.fHeight = kHeight; | |
764 desc.fFlags = kRenderTarget_GrBackendTextureFlag; | |
765 desc.fTextureHandle = context->getGpu()->createTestingOnlyBackendTexture( | |
766 pixels.get(), kWidth, kHeight, kRGBA_8888_GrPixelConfig); | |
767 sk_sp<SkSurface> surface = SkSurface::MakeFromBackendTexture(context, desc,
nullptr); | |
768 if (!surface) { | |
769 context->getGpu()->deleteTestingOnlyBackendTexture(desc.fTextureHandle); | |
770 return nullptr; | |
771 } | |
772 *outTexture = desc.fTextureHandle; | |
773 return surface; | |
774 } | |
775 | 823 |
776 static sk_sp<SkSurface> create_gpu_surface_backend_texture_as_render_target( | 824 void test_surface_clear(skiatest::Reporter* reporter, sk_sp<SkSurface> surface, |
777 GrContext* context, int sampleCnt, uint32_t color, GrBackendObject* outTextu
re) { | 825 std::function<GrSurface*(SkSurface*)> grSurfaceGetter, |
778 const int kWidth = 10; | 826 uint32_t expectedValue) { |
779 const int kHeight = 10; | |
780 SkAutoTDeleteArray<uint32_t> pixels(new uint32_t[kWidth * kHeight]); | |
781 sk_memset32(pixels.get(), color, kWidth * kHeight); | |
782 GrBackendTextureDesc desc; | |
783 desc.fConfig = kRGBA_8888_GrPixelConfig; | |
784 desc.fWidth = kWidth; | |
785 desc.fHeight = kHeight; | |
786 desc.fFlags = kRenderTarget_GrBackendTextureFlag; | |
787 desc.fTextureHandle = context->getGpu()->createTestingOnlyBackendTexture( | |
788 pixels.get(), kWidth, kHeight, kRGBA_8888_GrPixelConfig); | |
789 sk_sp<SkSurface> surface = SkSurface::MakeFromBackendTextureAsRenderTarget(c
ontext, desc, | |
790 n
ullptr); | |
791 if (!surface) { | |
792 context->getGpu()->deleteTestingOnlyBackendTexture(desc.fTextureHandle); | |
793 return nullptr; | |
794 } | |
795 *outTexture = desc.fTextureHandle; | |
796 return surface; | |
797 } | |
798 | |
799 static void test_surface_clear(skiatest::Reporter* reporter, sk_sp<SkSurface> su
rface, | |
800 std::function<GrSurface*(SkSurface*)> grSurfaceGe
tter, | |
801 uint32_t expectedValue) { | |
802 if (!surface) { | 827 if (!surface) { |
803 ERRORF(reporter, "Could not create GPU SkSurface."); | 828 ERRORF(reporter, "Could not create GPU SkSurface."); |
804 return; | 829 return; |
805 } | 830 } |
806 int w = surface->width(); | 831 int w = surface->width(); |
807 int h = surface->height(); | 832 int h = surface->height(); |
808 SkAutoTDeleteArray<uint32_t> pixels(new uint32_t[w * h]); | 833 SkAutoTDeleteArray<uint32_t> pixels(new uint32_t[w * h]); |
809 sk_memset32(pixels.get(), ~expectedValue, w * h); | 834 memset(pixels.get(), ~expectedValue, sizeof(uint32_t) * w * h); |
810 | 835 |
811 SkAutoTUnref<GrSurface> grSurface(SkSafeRef(grSurfaceGetter(surface.get())))
; | 836 SkAutoTUnref<GrSurface> grSurface(SkSafeRef(grSurfaceGetter(surface.get())))
; |
812 if (!grSurface) { | 837 if (!grSurface) { |
813 ERRORF(reporter, "Could access render target of GPU SkSurface."); | 838 ERRORF(reporter, "Could access render target of GPU SkSurface."); |
814 return; | 839 return; |
815 } | 840 } |
816 surface.reset(); | 841 surface.reset(); |
817 grSurface->readPixels(0, 0, w, h, kRGBA_8888_GrPixelConfig, pixels.get()); | 842 grSurface->readPixels(0, 0, w, h, kRGBA_8888_GrPixelConfig, pixels.get()); |
818 for (int y = 0; y < h; ++y) { | 843 for (int y = 0; y < h; ++y) { |
819 for (int x = 0; x < w; ++x) { | 844 for (int x = 0; x < w; ++x) { |
(...skipping 20 matching lines...) Expand all Loading... |
840 [] (SkSurface* s){ | 865 [] (SkSurface* s){ |
841 GrDrawContext* dc = s->getCanvas()->internal_private_accessTopLayerD
rawContext(); | 866 GrDrawContext* dc = s->getCanvas()->internal_private_accessTopLayerD
rawContext(); |
842 return dc->accessRenderTarget(); }, | 867 return dc->accessRenderTarget(); }, |
843 [] (SkSurface* s){ | 868 [] (SkSurface* s){ |
844 SkBaseDevice* d = | 869 SkBaseDevice* d = |
845 s->getCanvas()->getDevice_just_for_deprecated_compatibility_test
ing(); | 870 s->getCanvas()->getDevice_just_for_deprecated_compatibility_test
ing(); |
846 return d->accessRenderTarget(); }, | 871 return d->accessRenderTarget(); }, |
847 [] (SkSurface* s){ sk_sp<SkImage> i(s->makeImageSnapshot()); | 872 [] (SkSurface* s){ sk_sp<SkImage> i(s->makeImageSnapshot()); |
848 return as_IB(i)->peekTexture(); }, | 873 return as_IB(i)->peekTexture(); }, |
849 }; | 874 }; |
850 | |
851 for (auto grSurfaceGetter : grSurfaceGetters) { | 875 for (auto grSurfaceGetter : grSurfaceGetters) { |
852 // Test that non-wrapped RTs are created clear. | |
853 for (auto& surface_func : {&create_gpu_surface, &create_gpu_scratch_surf
ace}) { | 876 for (auto& surface_func : {&create_gpu_surface, &create_gpu_scratch_surf
ace}) { |
854 auto surface = surface_func(context, kPremul_SkAlphaType, nullptr); | 877 auto surface = surface_func(context, kPremul_SkAlphaType, nullptr); |
855 test_surface_clear(reporter, surface, grSurfaceGetter, 0x0); | 878 test_surface_clear(reporter, surface, grSurfaceGetter, 0x0); |
856 } | 879 } |
857 // Wrapped RTs are *not* supposed to clear (to allow client to partially
update a surface). | 880 // Wrapped RTs are *not* supposed to clear (to allow client to partially
update a surface). |
858 // This is applicable only when sample count is 0. Otherwise contents ar
e undefined. | 881 static const int kWidth = 10; |
859 const uint32_t kOrigColor = 0xABABABAB; | 882 static const int kHeight = 10; |
860 for (auto& surface_func : {&create_gpu_surface_backend_texture, | 883 SkAutoTDeleteArray<uint32_t> pixels(new uint32_t[kWidth * kHeight]); |
861 &create_gpu_surface_backend_texture_as_render
_target}) { | 884 memset(pixels.get(), 0xAB, sizeof(uint32_t) * kWidth * kHeight); |
862 GrBackendObject textureObject; | 885 |
863 int sampleCnt = 0; | 886 GrBackendObject textureObject = |
864 auto surface = surface_func(context, sampleCnt, kOrigColor, &texture
Object); | 887 context->getGpu()->createTestingOnlyBackendTexture(pixels.get(),
kWidth, kHeight, |
865 test_surface_clear(reporter, surface, grSurfaceGetter, kOrigColor); | 888 kRGBA_8888_Gr
PixelConfig); |
866 surface.reset(); | 889 |
867 context->getGpu()->deleteTestingOnlyBackendTexture(textureObject); | 890 GrBackendTextureDesc desc; |
868 } | 891 desc.fConfig = kRGBA_8888_GrPixelConfig; |
| 892 desc.fWidth = kWidth; |
| 893 desc.fHeight = kHeight; |
| 894 desc.fFlags = kRenderTarget_GrBackendTextureFlag; |
| 895 desc.fTextureHandle = textureObject; |
| 896 |
| 897 auto surface = SkSurface::MakeFromBackendTexture(context, desc, nullptr)
; |
| 898 test_surface_clear(reporter, surface, grSurfaceGetter, 0xABABABAB); |
| 899 context->getGpu()->deleteTestingOnlyBackendTexture(textureObject); |
869 } | 900 } |
870 } | 901 } |
871 #endif | 902 #endif |
872 | |
873 #if SK_SUPPORT_GPU | |
874 static void test_surface_draw_path_triggering_stencil( | |
875 skiatest::Reporter* reporter, int sampleCnt, sk_sp<SkSurface> surface, | |
876 uint32_t origColor) { | |
877 const int kW = surface->width(); | |
878 const int kH = surface->height(); | |
879 SkPaint paint; | |
880 paint.setAntiAlias(true); | |
881 paint.setColor(SK_ColorGREEN); | |
882 SkPath clipPath; | |
883 clipPath.quadTo(SkIntToScalar(kW), SkIntToScalar(0), SkIntToScalar(kW), SkIn
tToScalar(kH)); | |
884 clipPath.lineTo(SkIntToScalar(0), SkIntToScalar(kH)); | |
885 clipPath.lineTo(SkIntToScalar(0), SkIntToScalar(0)); | |
886 clipPath.close(); | |
887 SkPath path; | |
888 path.quadTo(SkIntToScalar(0), SkIntToScalar(kH), SkIntToScalar(kW), SkIntToS
calar(kH)); | |
889 path.lineTo(SkIntToScalar(kW), SkIntToScalar(0)); | |
890 path.lineTo(SkIntToScalar(0), SkIntToScalar(0)); | |
891 path.close(); | |
892 surface->getCanvas()->clipPath(clipPath, SkRegion::kIntersect_Op, true); | |
893 surface->getCanvas()->drawPath(path, paint); | |
894 // TODO: verify the drawing in a way that passes all platforms. | |
895 } | |
896 | |
897 static void test_surface_draw_partially( | |
898 skiatest::Reporter* reporter, sk_sp<SkSurface> surface, uint32_t origColor)
{ | |
899 const int kW = surface->width(); | |
900 const int kH = surface->height(); | |
901 SkPaint paint; | |
902 const SkColor kRectColor = ~origColor | 0xFF000000; | |
903 paint.setColor(kRectColor); | |
904 surface->getCanvas()->drawRect(SkRect::MakeWH(SkIntToScalar(kW), SkIntToScal
ar(kH)/2), | |
905 paint); | |
906 SkAutoTDeleteArray<uint32_t> pixels(new uint32_t[kW * kH]); | |
907 sk_memset32(pixels.get(), ~origColor, kW * kH); | |
908 SkImageInfo readInfo = SkImageInfo::MakeN32Premul(kW, kH); | |
909 SkAssertResult(surface->readPixels(readInfo, pixels.get(), kW * sizeof(uint3
2_t), 0, 0)); | |
910 bool stop = false; | |
911 SkPMColor origColorPM = SkPackARGB32((origColor >> 24 & 0xFF), | |
912 (origColor >> 0 & 0xFF), | |
913 (origColor >> 8 & 0xFF), | |
914 (origColor >> 16 & 0xFF)); | |
915 SkPMColor rectColorPM = SkPackARGB32((kRectColor >> 24 & 0xFF), | |
916 (kRectColor >> 16 & 0xFF), | |
917 (kRectColor >> 8 & 0xFF), | |
918 (kRectColor >> 0 & 0xFF)); | |
919 for (int y = 0; y < kH/2 && !stop; ++y) { | |
920 for (int x = 0; x < kW && !stop; ++x) { | |
921 REPORTER_ASSERT(reporter, rectColorPM == pixels[x + y * kW]); | |
922 if (rectColorPM != pixels[x + y * kW]) { | |
923 stop = true; | |
924 } | |
925 } | |
926 } | |
927 stop = false; | |
928 for (int y = kH/2; y < kH && !stop; ++y) { | |
929 for (int x = 0; x < kW && !stop; ++x) { | |
930 REPORTER_ASSERT(reporter, origColorPM == pixels[x + y * kW]); | |
931 if (origColorPM != pixels[x + y * kW]) { | |
932 stop = true; | |
933 } | |
934 } | |
935 } | |
936 } | |
937 | |
938 DEF_GPUTEST_FOR_GL_RENDERING_CONTEXTS(SurfaceWrappedTextureDrawTests, reporter,
ctxInfo) { | |
939 GrGpu* gpu = ctxInfo.fGrContext->getGpu(); | |
940 if (!gpu) { | |
941 return; | |
942 } | |
943 static const uint32_t kOrigColor = 0xFFAABBCC; | |
944 | |
945 for (auto& surface_func : {&create_gpu_surface_backend_texture, | |
946 &create_gpu_surface_backend_texture_as_render_tar
get}) { | |
947 for (int sampleCnt : {0, 4, 8}) { | |
948 GrBackendObject textureObject; | |
949 auto surface = surface_func(ctxInfo.fGrContext, sampleCnt, kOrigColo
r, &textureObject); | |
950 if (!surface) { | |
951 continue; | |
952 } | |
953 // Validate that we can draw paths to a canvas of a surface created
with | |
954 // SkSurface::MakeFromBackendTextureAsRenderTarget. The code intends
to enforce the use | |
955 // of stencil buffer. The original bug prevented the creation of ste
ncil buffer, causing | |
956 // an assert while drawing paths. | |
957 test_surface_draw_path_triggering_stencil(reporter, sampleCnt, surfa
ce, kOrigColor); | |
958 surface.reset(); | |
959 gpu->deleteTestingOnlyBackendTexture(textureObject); | |
960 } | |
961 // Validate that we can draw to the canvas and that the original texture
color is | |
962 // preserved in pixels that aren't rendered to via the surface. | |
963 // This works only for non-multisampled case. | |
964 GrBackendObject textureObject; | |
965 auto surface = surface_func(ctxInfo.fGrContext, 0, kOrigColor, &textureO
bject); | |
966 if (surface) { | |
967 test_surface_draw_partially(reporter, surface, kOrigColor); | |
968 surface.reset(); | |
969 gpu->deleteTestingOnlyBackendTexture(textureObject); | |
970 } | |
971 } | |
972 } | |
973 #endif | |
OLD | NEW |