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 | |
155 static void test_canvas_peek(skiatest::Reporter* reporter, | 86 static void test_canvas_peek(skiatest::Reporter* reporter, |
156 sk_sp<SkSurface>& surface, | 87 sk_sp<SkSurface>& surface, |
157 const SkImageInfo& requestInfo, | 88 const SkImageInfo& requestInfo, |
158 bool expectPeekSuccess) { | 89 bool expectPeekSuccess) { |
159 const SkColor color = SK_ColorRED; | 90 const SkColor color = SK_ColorRED; |
160 const SkPMColor pmcolor = SkPreMultiplyColor(color); | 91 const SkPMColor pmcolor = SkPreMultiplyColor(color); |
161 surface->getCanvas()->clear(color); | 92 surface->getCanvas()->clear(color); |
162 | 93 |
163 SkPixmap pmap; | 94 SkPixmap pmap; |
164 bool success = surface->getCanvas()->peekPixels(&pmap); | 95 bool success = surface->getCanvas()->peekPixels(&pmap); |
(...skipping 648 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
813 check_rowbytes_remain_consistent(surf1.get(), reporter); | 744 check_rowbytes_remain_consistent(surf1.get(), reporter); |
814 | 745 |
815 // Try some illegal rowByte values | 746 // Try some illegal rowByte values |
816 auto s = SkSurface::MakeRaster(info, 396, nullptr); // needs to be at lea
st 400 | 747 auto s = SkSurface::MakeRaster(info, 396, nullptr); // needs to be at lea
st 400 |
817 REPORTER_ASSERT(reporter, nullptr == s); | 748 REPORTER_ASSERT(reporter, nullptr == s); |
818 s = SkSurface::MakeRaster(info, 1 << 30, nullptr); // allocation to large | 749 s = SkSurface::MakeRaster(info, 1 << 30, nullptr); // allocation to large |
819 REPORTER_ASSERT(reporter, nullptr == s); | 750 REPORTER_ASSERT(reporter, nullptr == s); |
820 } | 751 } |
821 | 752 |
822 #if SK_SUPPORT_GPU | 753 #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 } |
823 | 775 |
824 void test_surface_clear(skiatest::Reporter* reporter, sk_sp<SkSurface> surface, | 776 static sk_sp<SkSurface> create_gpu_surface_backend_texture_as_render_target( |
825 std::function<GrSurface*(SkSurface*)> grSurfaceGetter, | 777 GrContext* context, int sampleCnt, uint32_t color, GrBackendObject* outTextu
re) { |
826 uint32_t expectedValue) { | 778 const int kWidth = 10; |
| 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) { |
827 if (!surface) { | 802 if (!surface) { |
828 ERRORF(reporter, "Could not create GPU SkSurface."); | 803 ERRORF(reporter, "Could not create GPU SkSurface."); |
829 return; | 804 return; |
830 } | 805 } |
831 int w = surface->width(); | 806 int w = surface->width(); |
832 int h = surface->height(); | 807 int h = surface->height(); |
833 SkAutoTDeleteArray<uint32_t> pixels(new uint32_t[w * h]); | 808 SkAutoTDeleteArray<uint32_t> pixels(new uint32_t[w * h]); |
834 memset(pixels.get(), ~expectedValue, sizeof(uint32_t) * w * h); | 809 sk_memset32(pixels.get(), ~expectedValue, w * h); |
835 | 810 |
836 SkAutoTUnref<GrSurface> grSurface(SkSafeRef(grSurfaceGetter(surface.get())))
; | 811 SkAutoTUnref<GrSurface> grSurface(SkSafeRef(grSurfaceGetter(surface.get())))
; |
837 if (!grSurface) { | 812 if (!grSurface) { |
838 ERRORF(reporter, "Could access render target of GPU SkSurface."); | 813 ERRORF(reporter, "Could access render target of GPU SkSurface."); |
839 return; | 814 return; |
840 } | 815 } |
841 surface.reset(); | 816 surface.reset(); |
842 grSurface->readPixels(0, 0, w, h, kRGBA_8888_GrPixelConfig, pixels.get()); | 817 grSurface->readPixels(0, 0, w, h, kRGBA_8888_GrPixelConfig, pixels.get()); |
843 for (int y = 0; y < h; ++y) { | 818 for (int y = 0; y < h; ++y) { |
844 for (int x = 0; x < w; ++x) { | 819 for (int x = 0; x < w; ++x) { |
(...skipping 20 matching lines...) Expand all Loading... |
865 [] (SkSurface* s){ | 840 [] (SkSurface* s){ |
866 GrDrawContext* dc = s->getCanvas()->internal_private_accessTopLayerD
rawContext(); | 841 GrDrawContext* dc = s->getCanvas()->internal_private_accessTopLayerD
rawContext(); |
867 return dc->accessRenderTarget(); }, | 842 return dc->accessRenderTarget(); }, |
868 [] (SkSurface* s){ | 843 [] (SkSurface* s){ |
869 SkBaseDevice* d = | 844 SkBaseDevice* d = |
870 s->getCanvas()->getDevice_just_for_deprecated_compatibility_test
ing(); | 845 s->getCanvas()->getDevice_just_for_deprecated_compatibility_test
ing(); |
871 return d->accessRenderTarget(); }, | 846 return d->accessRenderTarget(); }, |
872 [] (SkSurface* s){ sk_sp<SkImage> i(s->makeImageSnapshot()); | 847 [] (SkSurface* s){ sk_sp<SkImage> i(s->makeImageSnapshot()); |
873 return as_IB(i)->peekTexture(); }, | 848 return as_IB(i)->peekTexture(); }, |
874 }; | 849 }; |
| 850 |
875 for (auto grSurfaceGetter : grSurfaceGetters) { | 851 for (auto grSurfaceGetter : grSurfaceGetters) { |
| 852 // Test that non-wrapped RTs are created clear. |
876 for (auto& surface_func : {&create_gpu_surface, &create_gpu_scratch_surf
ace}) { | 853 for (auto& surface_func : {&create_gpu_surface, &create_gpu_scratch_surf
ace}) { |
877 auto surface = surface_func(context, kPremul_SkAlphaType, nullptr); | 854 auto surface = surface_func(context, kPremul_SkAlphaType, nullptr); |
878 test_surface_clear(reporter, surface, grSurfaceGetter, 0x0); | 855 test_surface_clear(reporter, surface, grSurfaceGetter, 0x0); |
879 } | 856 } |
880 // Wrapped RTs are *not* supposed to clear (to allow client to partially
update a surface). | 857 // Wrapped RTs are *not* supposed to clear (to allow client to partially
update a surface). |
881 static const int kWidth = 10; | 858 // This is applicable only when sample count is 0. Otherwise contents ar
e undefined. |
882 static const int kHeight = 10; | 859 const uint32_t kOrigColor = 0xABABABAB; |
883 SkAutoTDeleteArray<uint32_t> pixels(new uint32_t[kWidth * kHeight]); | 860 for (auto& surface_func : {&create_gpu_surface_backend_texture, |
884 memset(pixels.get(), 0xAB, sizeof(uint32_t) * kWidth * kHeight); | 861 &create_gpu_surface_backend_texture_as_render
_target}) { |
885 | 862 GrBackendObject textureObject; |
886 GrBackendObject textureObject = | 863 int sampleCnt = 0; |
887 context->getGpu()->createTestingOnlyBackendTexture(pixels.get(),
kWidth, kHeight, | 864 auto surface = surface_func(context, sampleCnt, kOrigColor, &texture
Object); |
888 kRGBA_8888_Gr
PixelConfig); | 865 test_surface_clear(reporter, surface, grSurfaceGetter, kOrigColor); |
889 | 866 surface.reset(); |
890 GrBackendTextureDesc desc; | 867 context->getGpu()->deleteTestingOnlyBackendTexture(textureObject); |
891 desc.fConfig = kRGBA_8888_GrPixelConfig; | 868 } |
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); | |
900 } | 869 } |
901 } | 870 } |
902 #endif | 871 #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 |