KleidiCV Coverage Report


Directory: ./
File: kleidicv/src/filters/separable_filter_2d_api.cpp
Date: 2025-09-25 14:13:34
Exec Total Coverage
Lines: 61 61 100.0%
Functions: 8 8 100.0%
Branches: 46 47 97.9%

Line Branch Exec Source
1 // SPDX-FileCopyrightText: 2023 - 2025 Arm Limited and/or its affiliates <open-source-office@arm.com>
2 //
3 // SPDX-License-Identifier: Apache-2.0
4
5 #include "kleidicv/dispatch.h"
6 #include "kleidicv/filters/separable_filter_2d.h"
7 #include "kleidicv/kleidicv.h"
8 #include "kleidicv/workspace/separable.h"
9
10 namespace kleidicv {
11
12 namespace neon {
13
14 template <typename T>
15 kleidicv_error_t separable_filter_2d_stripe(
16 const T *src, size_t src_stride, T *dst, size_t dst_stride, size_t width,
17 size_t height, size_t y_begin, size_t y_end, size_t channels,
18 const T *kernel_x, size_t kernel_width, const T *kernel_y,
19 size_t kernel_height, FixedBorderType border_type,
20 kleidicv_filter_context_t *context);
21
22 } // namespace neon
23
24 namespace sve2 {
25
26 template <typename T>
27 kleidicv_error_t separable_filter_2d_stripe(
28 const T *src, size_t src_stride, T *dst, size_t dst_stride, size_t width,
29 size_t height, size_t y_begin, size_t y_end, size_t channels,
30 const T *kernel_x, size_t kernel_width, const T *kernel_y,
31 size_t kernel_height, FixedBorderType border_type,
32 kleidicv_filter_context_t *context);
33
34 } // namespace sve2
35
36 namespace sme {
37
38 template <typename T>
39 kleidicv_error_t separable_filter_2d_stripe(
40 const T *src, size_t src_stride, T *dst, size_t dst_stride, size_t width,
41 size_t height, size_t y_begin, size_t y_end, size_t channels,
42 const T *kernel_x, size_t kernel_width, const T *kernel_y,
43 size_t kernel_height, FixedBorderType border_type,
44 kleidicv_filter_context_t *context);
45
46 } // namespace sme
47
48 } // namespace kleidicv
49
50 #define KLEIDICV_DEFINE_C_API(name, type) \
51 KLEIDICV_MULTIVERSION_C_API( \
52 name, &kleidicv::neon::separable_filter_2d_stripe<type>, \
53 KLEIDICV_SVE2_IMPL_IF(kleidicv::sve2::separable_filter_2d_stripe<type>), \
54 &kleidicv::sme::separable_filter_2d_stripe<type>, nullptr)
55
56
4/4
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 1 times.
8 KLEIDICV_DEFINE_C_API(kleidicv_separable_filter_2d_stripe_u8, uint8_t);
57
4/4
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 1 times.
8 KLEIDICV_DEFINE_C_API(kleidicv_separable_filter_2d_stripe_u16, uint16_t);
58
4/4
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 1 times.
8 KLEIDICV_DEFINE_C_API(kleidicv_separable_filter_2d_stripe_s16, int16_t);
59
60 extern "C" {
61
62 using KLEIDICV_TARGET_NAMESPACE::Rectangle;
63 using KLEIDICV_TARGET_NAMESPACE::SeparableFilterWorkspace;
64
65 2088 kleidicv_error_t kleidicv_filter_context_create(
66 kleidicv_filter_context_t **context, size_t max_channels,
67 size_t max_kernel_width, size_t max_kernel_height, size_t max_image_width,
68 size_t max_image_height) {
69
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 2085 times.
2088 CHECK_POINTERS(context);
70
71
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 2082 times.
2085 if (max_kernel_width != max_kernel_height) {
72 3 return KLEIDICV_ERROR_NOT_IMPLEMENTED;
73 }
74
75
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 2079 times.
2082 if (max_channels > KLEIDICV_MAXIMUM_CHANNEL_COUNT) {
76 3 return KLEIDICV_ERROR_NOT_IMPLEMENTED;
77 }
78
79
6/7
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 2076 times.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 2073 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 6 times.
✓ Branch 6 taken 2073 times.
2079 CHECK_IMAGE_SIZE(max_image_width, max_image_height);
80
81 // As we cannot predict the intermediate size based on the parameters given,
82 // just use the largest possible size out of all available operations.
83 2073 constexpr size_t intermediate_size = sizeof(uint32_t);
84 4146 auto workspace = SeparableFilterWorkspace::create(
85 2073 Rectangle{max_image_width, max_image_height}, max_channels,
86 intermediate_size);
87
2/2
✓ Branch 0 taken 2070 times.
✓ Branch 1 taken 3 times.
2073 if (!workspace) {
88 3 *context = nullptr;
89 3 return KLEIDICV_ERROR_ALLOCATION;
90 }
91
92 2070 *context = reinterpret_cast<kleidicv_filter_context_t *>(workspace.release());
93 2070 return KLEIDICV_OK;
94 2088 }
95
96 2073 kleidicv_error_t kleidicv_filter_context_release(
97 kleidicv_filter_context_t *context) {
98
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 2070 times.
2073 CHECK_POINTERS(context);
99
100 // Deliberately create and immediately destroy a unique_ptr to delete the
101 // workspace.
102 // NOLINTBEGIN(bugprone-unused-raii)
103 2070 SeparableFilterWorkspace::Pointer{
104 2070 reinterpret_cast<SeparableFilterWorkspace *>(context)};
105 // NOLINTEND(bugprone-unused-raii)
106 2070 return KLEIDICV_OK;
107 2073 }
108
109 252 kleidicv_error_t kleidicv_separable_filter_2d_u8(
110 const uint8_t *src, size_t src_stride, uint8_t *dst, size_t dst_stride,
111 size_t width, size_t height, size_t channels, const uint8_t *kernel_x,
112 size_t kernel_width, const uint8_t *kernel_y, size_t kernel_height,
113 kleidicv_border_type_t border_type, kleidicv_filter_context_t *context) {
114
4/4
✓ Branch 0 taken 75 times.
✓ Branch 1 taken 177 times.
✓ Branch 2 taken 75 times.
✓ Branch 3 taken 177 times.
504 if (!kleidicv::separable_filter_2d_is_implemented(width, height, kernel_width,
115 252 kernel_height)) {
116 75 return KLEIDICV_ERROR_NOT_IMPLEMENTED;
117 }
118 177 auto fixed_border_type = kleidicv::get_fixed_border_type(border_type);
119
2/2
✓ Branch 0 taken 168 times.
✓ Branch 1 taken 9 times.
177 if (!fixed_border_type) {
120 9 return KLEIDICV_ERROR_NOT_IMPLEMENTED;
121 }
122
123 336 return kleidicv_separable_filter_2d_stripe_u8(
124 168 src, src_stride, dst, dst_stride, width, height, 0, height, channels,
125 168 kernel_x, kernel_width, kernel_y, kernel_height, *fixed_border_type,
126 168 context);
127 252 }
128
129 252 kleidicv_error_t kleidicv_separable_filter_2d_u16(
130 const uint16_t *src, size_t src_stride, uint16_t *dst, size_t dst_stride,
131 size_t width, size_t height, size_t channels, const uint16_t *kernel_x,
132 size_t kernel_width, const uint16_t *kernel_y, size_t kernel_height,
133 kleidicv_border_type_t border_type, kleidicv_filter_context_t *context) {
134
4/4
✓ Branch 0 taken 75 times.
✓ Branch 1 taken 177 times.
✓ Branch 2 taken 75 times.
✓ Branch 3 taken 177 times.
504 if (!kleidicv::separable_filter_2d_is_implemented(width, height, kernel_width,
135 252 kernel_height)) {
136 75 return KLEIDICV_ERROR_NOT_IMPLEMENTED;
137 }
138 177 auto fixed_border_type = kleidicv::get_fixed_border_type(border_type);
139
2/2
✓ Branch 0 taken 168 times.
✓ Branch 1 taken 9 times.
177 if (!fixed_border_type) {
140 9 return KLEIDICV_ERROR_NOT_IMPLEMENTED;
141 }
142
143 336 return kleidicv_separable_filter_2d_stripe_u16(
144 168 src, src_stride, dst, dst_stride, width, height, 0, height, channels,
145 168 kernel_x, kernel_width, kernel_y, kernel_height, *fixed_border_type,
146 168 context);
147 252 }
148
149 249 kleidicv_error_t kleidicv_separable_filter_2d_s16(
150 const int16_t *src, size_t src_stride, int16_t *dst, size_t dst_stride,
151 size_t width, size_t height, size_t channels, const int16_t *kernel_x,
152 size_t kernel_width, const int16_t *kernel_y, size_t kernel_height,
153 kleidicv_border_type_t border_type, kleidicv_filter_context_t *context) {
154
4/4
✓ Branch 0 taken 75 times.
✓ Branch 1 taken 174 times.
✓ Branch 2 taken 75 times.
✓ Branch 3 taken 174 times.
498 if (!kleidicv::separable_filter_2d_is_implemented(width, height, kernel_width,
155 249 kernel_height)) {
156 75 return KLEIDICV_ERROR_NOT_IMPLEMENTED;
157 }
158 174 auto fixed_border_type = kleidicv::get_fixed_border_type(border_type);
159
2/2
✓ Branch 0 taken 165 times.
✓ Branch 1 taken 9 times.
174 if (!fixed_border_type) {
160 9 return KLEIDICV_ERROR_NOT_IMPLEMENTED;
161 }
162
163 330 return kleidicv_separable_filter_2d_stripe_s16(
164 165 src, src_stride, dst, dst_stride, width, height, 0, height, channels,
165 165 kernel_x, kernel_width, kernel_y, kernel_height, *fixed_border_type,
166 165 context);
167 249 }
168
169 } // extern "C"
170