Coverage Report

Created: 2026-10-17 06:56

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/work/dav1d/src/looprestoration_tmpl.c
Line
Count
Source
1
/*
2
 * Copyright © 2018, VideoLAN and dav1d authors
3
 * Copyright © 2018, Two Orioles, LLC
4
 * All rights reserved.
5
 *
6
 * Redistribution and use in source and binary forms, with or without
7
 * modification, are permitted provided that the following conditions are met:
8
 *
9
 * 1. Redistributions of source code must retain the above copyright notice, this
10
 *    list of conditions and the following disclaimer.
11
 *
12
 * 2. Redistributions in binary form must reproduce the above copyright notice,
13
 *    this list of conditions and the following disclaimer in the documentation
14
 *    and/or other materials provided with the distribution.
15
 *
16
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
17
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
20
 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26
 */
27
28
#include "config.h"
29
30
#include <stdint.h>
31
#include <stdlib.h>
32
#include <string.h>
33
34
#include "common/attributes.h"
35
#include "common/bitdepth.h"
36
#include "common/intops.h"
37
38
#include "src/looprestoration.h"
39
#include "src/tables.h"
40
41
// 256 * 1.5 + 3 + 3 = 390
42
7.81M
#define REST_UNIT_STRIDE (390)
43
44
static void wiener_filter_h(uint16_t *dst, const pixel (*left)[4],
45
                            const pixel *src, const int16_t fh[8],
46
                            const int w, const enum LrEdgeFlags edges
47
                            HIGHBD_DECL_SUFFIX)
48
7.16M
{
49
7.16M
    const int bitdepth = bitdepth_from_max(bitdepth_max);
50
7.16M
    const int round_bits_h = 3 + (bitdepth == 12) * 2;
51
7.16M
    const int rounding_off_h = 1 << (round_bits_h - 1);
52
7.16M
    const int clip_limit = 1 << (bitdepth + 1 + 7 - round_bits_h);
53
54
7.16M
    if (w < 6) {
55
        // For small widths, do the fully conditional loop with
56
        // conditions on each access.
57
9.79M
        for (int x = 0; x < w; x++) {
58
7.45M
            int sum = (1 << (bitdepth + 6));
59
7.45M
#if BITDEPTH == 8
60
7.45M
            sum += src[x] * 128;
61
7.45M
#endif
62
59.0M
            for (int i = 0; i < 7; i++) {
63
51.6M
                int idx = x + i - 3;
64
51.6M
                if (idx < 0) {
65
11.4M
                    if (!(edges & LR_HAVE_LEFT))
66
11.4M
                        sum += src[0] * fh[i];
67
18.4E
                    else if (left)
68
0
                        sum += left[0][4 + idx] * fh[i];
69
18.4E
                    else
70
18.4E
                        sum += src[idx] * fh[i];
71
40.1M
                } else if (idx >= w && !(edges & LR_HAVE_RIGHT)) {
72
11.1M
                    sum += src[w - 1] * fh[i];
73
11.1M
                } else
74
29.0M
                    sum += src[idx] * fh[i];
75
51.6M
            }
76
7.45M
            sum = iclip((sum + rounding_off_h) >> round_bits_h, 0, clip_limit - 1);
77
7.45M
            dst[x] = sum;
78
7.45M
        }
79
80
2.33M
        return;
81
2.33M
    }
82
83
    // For larger widths, do separate loops with less conditions; first
84
    // handle the start of the row.
85
4.83M
    int start = 3;
86
4.83M
    if (!(edges & LR_HAVE_LEFT)) {
87
        // If there's no left edge, pad using the leftmost pixel.
88
11.2M
        for (int x = 0; x < 3; x++) {
89
8.43M
            int sum = (1 << (bitdepth + 6));
90
8.43M
#if BITDEPTH == 8
91
8.43M
            sum += src[x] * 128;
92
8.43M
#endif
93
67.4M
            for (int i = 0; i < 7; i++) {
94
58.9M
                int idx = x + i - 3;
95
58.9M
                if (idx < 0)
96
16.8M
                    sum += src[0] * fh[i];
97
42.0M
                else
98
42.0M
                    sum += src[idx] * fh[i];
99
58.9M
            }
100
8.43M
            sum = iclip((sum + rounding_off_h) >> round_bits_h, 0, clip_limit - 1);
101
8.43M
            dst[x] = sum;
102
8.43M
        }
103
2.86M
    } else if (left) {
104
        // If we have the left edge and a separate left buffer, pad using that.
105
7.40M
        for (int x = 0; x < 3; x++) {
106
5.54M
            int sum = (1 << (bitdepth + 6));
107
5.54M
#if BITDEPTH == 8
108
5.54M
            sum += src[x] * 128;
109
5.54M
#endif
110
44.3M
            for (int i = 0; i < 7; i++) {
111
38.8M
                int idx = x + i - 3;
112
38.8M
                if (idx < 0)
113
11.0M
                    sum += left[0][4 + idx] * fh[i];
114
27.7M
                else
115
27.7M
                    sum += src[idx] * fh[i];
116
38.8M
            }
117
5.54M
            sum = iclip((sum + rounding_off_h) >> round_bits_h, 0, clip_limit - 1);
118
5.54M
            dst[x] = sum;
119
5.54M
        }
120
1.85M
    } else {
121
        // If we have the left edge, but no separate left buffer, we're in the
122
        // top/bottom area (lpf) with the left edge existing in the same
123
        // buffer; just do the regular loop from the start.
124
111k
        start = 0;
125
111k
    }
126
4.83M
    int end = w - 3;
127
4.83M
    if (edges & LR_HAVE_RIGHT)
128
1.86M
        end = w;
129
130
    // Do a condititon free loop for the bulk of the row.
131
389M
    for (int x = start; x < end; x++) {
132
384M
        int sum = (1 << (bitdepth + 6));
133
384M
#if BITDEPTH == 8
134
384M
        sum += src[x] * 128;
135
384M
#endif
136
3.05G
        for (int i = 0; i < 7; i++) {
137
2.67G
            int idx = x + i - 3;
138
2.67G
            sum += src[idx] * fh[i];
139
2.67G
        }
140
384M
        sum = iclip((sum + rounding_off_h) >> round_bits_h, 0, clip_limit - 1);
141
384M
        dst[x] = sum;
142
384M
    }
143
144
    // If we need to, calculate the end of the row with a condition for
145
    // right edge padding.
146
13.2M
    for (int x = end; x < w; x++) {
147
8.46M
        int sum = (1 << (bitdepth + 6));
148
8.46M
#if BITDEPTH == 8
149
8.46M
        sum += src[x] * 128;
150
8.46M
#endif
151
67.6M
        for (int i = 0; i < 7; i++) {
152
59.2M
            int idx = x + i - 3;
153
59.2M
            if (idx >= w)
154
16.8M
                sum += src[w - 1] * fh[i];
155
42.3M
            else
156
42.3M
                sum += src[idx] * fh[i];
157
59.2M
        }
158
8.46M
        sum = iclip((sum + rounding_off_h) >> round_bits_h, 0, clip_limit - 1);
159
8.46M
        dst[x] = sum;
160
8.46M
    }
161
4.83M
}
162
163
static void wiener_filter_v(pixel *p, uint16_t **ptrs, const int16_t fv[8],
164
                            const int w HIGHBD_DECL_SUFFIX)
165
325k
{
166
325k
    const int bitdepth = bitdepth_from_max(bitdepth_max);
167
168
325k
    const int round_bits_v = 11 - (bitdepth == 12) * 2;
169
325k
    const int rounding_off_v = 1 << (round_bits_v - 1);
170
325k
    const int round_offset = 1 << (bitdepth + (round_bits_v - 1));
171
172
18.1M
    for (int i = 0; i < w; i++) {
173
17.7M
        int sum = -round_offset;
174
175
        // Only filter using 6 input rows. The 7th row is assumed to be
176
        // identical to the last one.
177
        //
178
        // This function is assumed to only be called at the end, when doing
179
        // padding at the bottom.
180
124M
        for (int k = 0; k < 6; k++)
181
106M
            sum += ptrs[k][i] * fv[k];
182
17.7M
        sum += ptrs[5][i] * fv[6];
183
184
17.7M
        p[i] = iclip_pixel((sum + rounding_off_v) >> round_bits_v);
185
17.7M
    }
186
187
    // Shift the pointers, but only update the first 5; the 6th pointer is kept
188
    // as it was before (and the 7th is implicitly identical to the 6th).
189
1.95M
    for (int i = 0; i < 5; i++)
190
1.62M
        ptrs[i] = ptrs[i + 1];
191
325k
}
192
193
static void wiener_filter_hv(pixel *p, uint16_t **ptrs, const pixel (*left)[4],
194
                             const pixel *src, const int16_t filter[2][8],
195
                             const int w, const enum LrEdgeFlags edges
196
                             HIGHBD_DECL_SUFFIX)
197
6.40M
{
198
6.40M
    const int bitdepth = bitdepth_from_max(bitdepth_max);
199
200
6.40M
    const int round_bits_v = 11 - (bitdepth == 12) * 2;
201
6.40M
    const int rounding_off_v = 1 << (round_bits_v - 1);
202
6.40M
    const int round_offset = 1 << (bitdepth + (round_bits_v - 1));
203
204
6.40M
    const int16_t *fh = filter[0];
205
6.40M
    const int16_t *fv = filter[1];
206
207
    // Do combined horziontal and vertical filtering; doing horizontal
208
    // filtering of one row, combined with vertical filtering of 6
209
    // preexisting rows and the newly filtered row.
210
211
    // For simplicity in the C implementation, just do a separate call
212
    // of the horizontal filter, into a temporary buffer.
213
6.40M
    uint16_t tmp[REST_UNIT_STRIDE];
214
6.40M
    wiener_filter_h(tmp, left, src, fh, w, edges HIGHBD_TAIL_SUFFIX);
215
216
367M
    for (int i = 0; i < w; i++) {
217
360M
        int sum = -round_offset;
218
219
        // Filter using the 6 stored preexisting rows, and the newly
220
        // filtered one in tmp[].
221
2.51G
        for (int k = 0; k < 6; k++)
222
2.15G
            sum += ptrs[k][i] * fv[k];
223
360M
        sum += tmp[i] * fv[6];
224
        // At this point, after having read all inputs at point [i], we
225
        // could overwrite [i] with the newly filtered data.
226
227
360M
        p[i] = iclip_pixel((sum + rounding_off_v) >> round_bits_v);
228
360M
    }
229
230
    // For simplicity in the C implementation, just memcpy the newly
231
    // filtered row into ptrs[6]. Normally, in steady state filtering,
232
    // this output row, ptrs[6], is equal to ptrs[0]. However at startup,
233
    // at the top of the filtered area, we may have ptrs[0] equal to ptrs[1],
234
    // so we can't assume we can write into ptrs[0] but we need to keep
235
    // a separate pointer for the next row to write into.
236
6.40M
    memcpy(ptrs[6], tmp, sizeof(uint16_t) * REST_UNIT_STRIDE);
237
238
    // Rotate the window of pointers. Shift the 6 pointers downwards one step.
239
44.4M
    for (int i = 0; i < 6; i++)
240
38.0M
        ptrs[i] = ptrs[i + 1];
241
    // The topmost pointer, ptrs[6], which isn't used as input, is set to
242
    // ptrs[0], which will be used as output for the next _hv call.
243
    // At the start of the filtering, the caller may set ptrs[6] to the
244
    // right next buffer to fill in, instead.
245
6.40M
    ptrs[6] = ptrs[0];
246
6.40M
}
247
248
// FIXME Could split into luma and chroma specific functions,
249
// (since first and last tops are always 0 for chroma)
250
static void wiener_c(pixel *p, const ptrdiff_t stride,
251
                     const pixel (*left)[4],
252
                     const pixel *lpf, const int w, int h,
253
                     const LooprestorationParams *const params,
254
                     const enum LrEdgeFlags edges HIGHBD_DECL_SUFFIX)
255
209k
{
256
    // Values stored between horizontal and vertical filtering don't
257
    // fit in a uint8_t.
258
209k
    uint16_t hor[6 * REST_UNIT_STRIDE];
259
209k
    uint16_t *ptrs[7], *rows[6];
260
1.46M
    for (int i = 0; i < 6; i++)
261
1.25M
        rows[i] = &hor[i * REST_UNIT_STRIDE];
262
209k
    const int16_t (*const filter)[8] = params->filter;
263
209k
    const int16_t *fh = params->filter[0];
264
209k
    const int16_t *fv = params->filter[1];
265
209k
    const pixel *lpf_bottom = lpf + 6*PXSTRIDE(stride);
266
267
209k
    const pixel *src = p;
268
209k
    if (edges & LR_HAVE_TOP) {
269
117k
        ptrs[0] = rows[0];
270
117k
        ptrs[1] = rows[0];
271
117k
        ptrs[2] = rows[1];
272
117k
        ptrs[3] = rows[2];
273
117k
        ptrs[4] = rows[2];
274
117k
        ptrs[5] = rows[2];
275
276
117k
        wiener_filter_h(rows[0], NULL, lpf, fh, w, edges HIGHBD_TAIL_SUFFIX);
277
117k
        lpf += PXSTRIDE(stride);
278
117k
        wiener_filter_h(rows[1], NULL, lpf, fh, w, edges HIGHBD_TAIL_SUFFIX);
279
280
117k
        wiener_filter_h(rows[2], left, src, fh, w, edges HIGHBD_TAIL_SUFFIX);
281
117k
        left++;
282
117k
        src += PXSTRIDE(stride);
283
284
117k
        if (--h <= 0)
285
2.27k
            goto v1;
286
287
114k
        ptrs[4] = ptrs[5] = rows[3];
288
114k
        wiener_filter_h(rows[3], left, src, fh, w, edges HIGHBD_TAIL_SUFFIX);
289
114k
        left++;
290
114k
        src += PXSTRIDE(stride);
291
292
114k
        if (--h <= 0)
293
1.25k
            goto v2;
294
295
113k
        ptrs[5] = rows[4];
296
113k
        wiener_filter_h(rows[4], left, src, fh, w, edges HIGHBD_TAIL_SUFFIX);
297
113k
        left++;
298
113k
        src += PXSTRIDE(stride);
299
300
113k
        if (--h <= 0)
301
1.14k
            goto v3;
302
113k
    } else {
303
92.7k
        ptrs[0] = rows[0];
304
92.7k
        ptrs[1] = rows[0];
305
92.7k
        ptrs[2] = rows[0];
306
92.7k
        ptrs[3] = rows[0];
307
92.7k
        ptrs[4] = rows[0];
308
92.7k
        ptrs[5] = rows[0];
309
310
92.7k
        wiener_filter_h(rows[0], left, src, fh, w, edges HIGHBD_TAIL_SUFFIX);
311
92.7k
        left++;
312
92.7k
        src += PXSTRIDE(stride);
313
314
92.7k
        if (--h <= 0)
315
27.1k
            goto v1;
316
317
65.6k
        ptrs[4] = ptrs[5] = rows[1];
318
65.6k
        wiener_filter_h(rows[1], left, src, fh, w, edges HIGHBD_TAIL_SUFFIX);
319
65.6k
        left++;
320
65.6k
        src += PXSTRIDE(stride);
321
322
65.6k
        if (--h <= 0)
323
9.67k
            goto v2;
324
325
55.9k
        ptrs[5] = rows[2];
326
55.9k
        wiener_filter_h(rows[2], left, src, fh, w, edges HIGHBD_TAIL_SUFFIX);
327
55.9k
        left++;
328
55.9k
        src += PXSTRIDE(stride);
329
330
55.9k
        if (--h <= 0)
331
3.15k
            goto v3;
332
333
52.8k
        ptrs[6] = rows[3];
334
52.8k
        wiener_filter_hv(p, ptrs, left, src, filter, w, edges
335
52.8k
                         HIGHBD_TAIL_SUFFIX);
336
52.8k
        left++;
337
52.8k
        src += PXSTRIDE(stride);
338
52.8k
        p += PXSTRIDE(stride);
339
340
52.8k
        if (--h <= 0)
341
4.08k
            goto v3;
342
343
48.7k
        ptrs[6] = rows[4];
344
48.7k
        wiener_filter_hv(p, ptrs, left, src, filter, w, edges
345
48.7k
                         HIGHBD_TAIL_SUFFIX);
346
48.7k
        left++;
347
48.7k
        src += PXSTRIDE(stride);
348
48.7k
        p += PXSTRIDE(stride);
349
350
48.7k
        if (--h <= 0)
351
3.33k
            goto v3;
352
48.7k
    }
353
354
157k
    ptrs[6] = ptrs[5] + REST_UNIT_STRIDE;
355
6.06M
    do {
356
6.06M
        wiener_filter_hv(p, ptrs, left, src, filter, w, edges
357
6.06M
                         HIGHBD_TAIL_SUFFIX);
358
6.06M
        left++;
359
6.06M
        src += PXSTRIDE(stride);
360
6.06M
        p += PXSTRIDE(stride);
361
6.06M
    } while (--h > 0);
362
363
157k
    if (!(edges & LR_HAVE_BOTTOM))
364
40.6k
        goto v3;
365
366
117k
    wiener_filter_hv(p, ptrs, NULL, lpf_bottom, filter, w, edges
367
117k
                     HIGHBD_TAIL_SUFFIX);
368
117k
    lpf_bottom += PXSTRIDE(stride);
369
117k
    p += PXSTRIDE(stride);
370
371
117k
    wiener_filter_hv(p, ptrs, NULL, lpf_bottom, filter, w, edges
372
117k
                     HIGHBD_TAIL_SUFFIX);
373
117k
    p += PXSTRIDE(stride);
374
209k
v1:
375
209k
    wiener_filter_v(p, ptrs, fv, w HIGHBD_TAIL_SUFFIX);
376
377
209k
    return;
378
379
52.4k
v3:
380
52.4k
    wiener_filter_v(p, ptrs, fv, w HIGHBD_TAIL_SUFFIX);
381
52.4k
    p += PXSTRIDE(stride);
382
63.3k
v2:
383
63.3k
    wiener_filter_v(p, ptrs, fv, w HIGHBD_TAIL_SUFFIX);
384
63.3k
    p += PXSTRIDE(stride);
385
63.3k
    goto v1;
386
52.4k
}
387
388
// SGR
389
static NOINLINE void rotate(int32_t **sumsq_ptrs, coef **sum_ptrs, int n)
390
15.1M
{
391
15.1M
    int32_t *tmp32 = sumsq_ptrs[0];
392
15.1M
    coef *tmpc = sum_ptrs[0];
393
46.8M
    for (int i = 0; i < n - 1; i++) {
394
31.6M
        sumsq_ptrs[i] = sumsq_ptrs[i + 1];
395
31.6M
        sum_ptrs[i] = sum_ptrs[i + 1];
396
31.6M
    }
397
15.1M
    sumsq_ptrs[n - 1] = tmp32;
398
15.1M
    sum_ptrs[n - 1] = tmpc;
399
15.1M
}
400
401
static NOINLINE void rotate5_x2(int32_t **sumsq_ptrs, coef **sum_ptrs)
402
3.30M
{
403
3.30M
    int32_t *tmp32[2];
404
3.30M
    coef *tmpc[2];
405
3.30M
    memcpy(tmp32, sumsq_ptrs, 2 * sizeof(int32_t*));
406
3.30M
    memcpy(tmpc, sum_ptrs, 2 * sizeof(coef*));
407
3.30M
    memmove(&sumsq_ptrs[0], &sumsq_ptrs[2], 3 * sizeof(int32_t*));
408
3.30M
    memmove(&sum_ptrs[0], &sum_ptrs[2], 3 * sizeof(coef*));
409
3.30M
    memcpy(&sumsq_ptrs[3], tmp32, 2 * sizeof(int32_t*));
410
3.30M
    memcpy(&sum_ptrs[3], tmpc, 2 * sizeof(coef*));
411
3.30M
}
412
413
static NOINLINE void sgr_box3_row_h(int32_t *sumsq, coef *sum,
414
                                    const pixel (*left)[4],
415
                                    const pixel *src, const int w,
416
                                    const enum LrEdgeFlags edges)
417
6.33M
{
418
6.33M
    sumsq++;
419
6.33M
    sum++;
420
6.33M
    int a = edges & LR_HAVE_LEFT ? (left ? left[0][2] : src[-2]) : src[0];
421
6.33M
    int b = edges & LR_HAVE_LEFT ? (left ? left[0][3] : src[-1]) : src[0];
422
390M
    for (int x = -1; x < w + 1; x++) {
423
383M
        int c = (x + 1 < w || (edges & LR_HAVE_RIGHT)) ? src[x + 1] : src[w - 1];
424
383M
        sum[x] = a + b + c;
425
383M
        sumsq[x] = a * a + b * b + c * c;
426
383M
        a = b;
427
383M
        b = c;
428
383M
    }
429
6.33M
}
430
431
static NOINLINE void sgr_box5_row_h(int32_t *sumsq, coef *sum,
432
                                    const pixel (*left)[4],
433
                                    const pixel *src, const int w,
434
                                    const enum LrEdgeFlags edges)
435
6.72M
{
436
6.72M
    sumsq++;
437
6.72M
    sum++;
438
6.72M
    int a = edges & LR_HAVE_LEFT ? (left ? left[0][1] : src[-3]) : src[0];
439
6.72M
    int b = edges & LR_HAVE_LEFT ? (left ? left[0][2] : src[-2]) : src[0];
440
6.72M
    int c = edges & LR_HAVE_LEFT ? (left ? left[0][3] : src[-1]) : src[0];
441
6.72M
    int d = src[0];
442
422M
    for (int x = -1; x < w + 1; x++) {
443
415M
        int e = (x + 2 < w || (edges & LR_HAVE_RIGHT)) ? src[x + 2] : src[w - 1];
444
415M
        sum[x] = a + b + c + d + e;
445
415M
        sumsq[x] = a * a + b * b + c * c + d * d + e * e;
446
415M
        a = b;
447
415M
        b = c;
448
415M
        c = d;
449
415M
        d = e;
450
415M
    }
451
6.72M
}
452
453
static void sgr_box35_row_h(int32_t *sumsq3, coef *sum3,
454
                            int32_t *sumsq5, coef *sum5,
455
                            const pixel (*left)[4],
456
                            const pixel *src, const int w,
457
                            const enum LrEdgeFlags edges)
458
4.70M
{
459
4.70M
    sgr_box3_row_h(sumsq3, sum3, left, src, w, edges);
460
4.70M
    sgr_box5_row_h(sumsq5, sum5, left, src, w, edges);
461
4.70M
}
462
463
static NOINLINE void sgr_box3_row_v(int32_t **sumsq, coef **sum,
464
                                    int32_t *sumsq_out, coef *sum_out,
465
                                    const int w)
466
6.32M
{
467
387M
    for (int x = 0; x < w + 2; x++) {
468
381M
        int sq_a = sumsq[0][x];
469
381M
        int sq_b = sumsq[1][x];
470
381M
        int sq_c = sumsq[2][x];
471
381M
        int s_a = sum[0][x];
472
381M
        int s_b = sum[1][x];
473
381M
        int s_c = sum[2][x];
474
381M
        sumsq_out[x] = sq_a + sq_b + sq_c;
475
381M
        sum_out[x] = s_a + s_b + s_c;
476
381M
    }
477
6.32M
}
478
479
static NOINLINE void sgr_box5_row_v(int32_t **sumsq, coef **sum,
480
                                    int32_t *sumsq_out, coef *sum_out,
481
                                    const int w)
482
3.40M
{
483
214M
    for (int x = 0; x < w + 2; x++) {
484
211M
        int sq_a = sumsq[0][x];
485
211M
        int sq_b = sumsq[1][x];
486
211M
        int sq_c = sumsq[2][x];
487
211M
        int sq_d = sumsq[3][x];
488
211M
        int sq_e = sumsq[4][x];
489
211M
        int s_a = sum[0][x];
490
211M
        int s_b = sum[1][x];
491
211M
        int s_c = sum[2][x];
492
211M
        int s_d = sum[3][x];
493
211M
        int s_e = sum[4][x];
494
211M
        sumsq_out[x] = sq_a + sq_b + sq_c + sq_d + sq_e;
495
211M
        sum_out[x] = s_a + s_b + s_c + s_d + s_e;
496
211M
    }
497
3.40M
}
498
499
static NOINLINE void sgr_calc_row_ab(int32_t *AA, coef *BB, int w, int s,
500
                                     int bitdepth_max, int n, int sgr_one_by_x)
501
9.73M
{
502
9.73M
    const int bitdepth_min_8 = bitdepth_from_max(bitdepth_max) - 8;
503
542M
    for (int i = 0; i < w + 2; i++) {
504
532M
        const int a =
505
532M
            (AA[i] + ((1 << (2 * bitdepth_min_8)) >> 1)) >> (2 * bitdepth_min_8);
506
532M
        const int b =
507
532M
            (BB[i] + ((1 << bitdepth_min_8) >> 1)) >> bitdepth_min_8;
508
509
532M
        const unsigned p = imax(a * n - b * b, 0);
510
532M
        const unsigned z = (p * s + (1 << 19)) >> 20;
511
532M
        const unsigned x = dav1d_sgr_x_by_x[umin(z, 255)];
512
513
        // This is where we invert A and B, so that B is of size coef.
514
532M
        AA[i] = (x * BB[i] * sgr_one_by_x + (1 << 11)) >> 12;
515
532M
        BB[i] = x;
516
532M
    }
517
9.73M
}
518
519
static void sgr_box3_vert(int32_t **sumsq, coef **sum,
520
                          int32_t *sumsq_out, coef *sum_out,
521
                          const int w, const int s, const int bitdepth_max)
522
6.31M
{
523
6.31M
    sgr_box3_row_v(sumsq, sum, sumsq_out, sum_out, w);
524
6.31M
    sgr_calc_row_ab(sumsq_out, sum_out, w, s, bitdepth_max, 9, 455);
525
6.31M
    rotate(sumsq, sum, 3);
526
6.31M
}
527
528
static void sgr_box5_vert(int32_t **sumsq, coef **sum,
529
                          int32_t *sumsq_out, coef *sum_out,
530
                          const int w, const int s, const int bitdepth_max)
531
3.41M
{
532
3.41M
    sgr_box5_row_v(sumsq, sum, sumsq_out, sum_out, w);
533
3.41M
    sgr_calc_row_ab(sumsq_out, sum_out, w, s, bitdepth_max, 25, 164);
534
3.41M
    rotate5_x2(sumsq, sum);
535
3.41M
}
536
537
static void sgr_box3_hv(int32_t **sumsq, coef **sum,
538
                        int32_t *AA, coef *BB,
539
                        const pixel (*left)[4],
540
                        const pixel *src, const int w,
541
                        const int s,
542
                        const enum LrEdgeFlags edges,
543
                        const int bitdepth_max)
544
1.67M
{
545
1.67M
    sgr_box3_row_h(sumsq[2], sum[2], left, src, w, edges);
546
1.67M
    sgr_box3_vert(sumsq, sum, AA, BB, w, s, bitdepth_max);
547
1.67M
}
548
549
static NOINLINE void sgr_finish_filter_row1(coef *tmp,
550
                                            const pixel *src,
551
                                            int32_t **A_ptrs, coef **B_ptrs,
552
                                            const int w)
553
6.09M
{
554
6.09M
#define EIGHT_NEIGHBORS(P, i)\
555
702M
    ((P[1][i] + P[1][i - 1] + P[1][i + 1] + P[0][i] + P[2][i]) * 4 + \
556
702M
     (P[0][i - 1] + P[2][i - 1] +                           \
557
702M
      P[0][i + 1] + P[2][i + 1]) * 3)
558
357M
    for (int i = 0; i < w; i++) {
559
351M
        const int a = EIGHT_NEIGHBORS(B_ptrs, i + 1);
560
351M
        const int b = EIGHT_NEIGHBORS(A_ptrs, i + 1);
561
351M
        tmp[i] = (b - a * src[i] + (1 << 8)) >> 9;
562
351M
    }
563
6.09M
#undef EIGHT_NEIGHBORS
564
6.09M
}
565
566
15.3M
#define FILTER_OUT_STRIDE (384)
567
568
static NOINLINE void sgr_finish_filter2(coef *tmp,
569
                                        const pixel *src,
570
                                        const ptrdiff_t src_stride,
571
                                        int32_t **A_ptrs, coef **B_ptrs,
572
                                        const int w, const int h)
573
3.20M
{
574
3.20M
#define SIX_NEIGHBORS(P, i)\
575
387M
    ((P[0][i]     + P[1][i]) * 6 +   \
576
387M
     (P[0][i - 1] + P[1][i - 1] +    \
577
387M
      P[0][i + 1] + P[1][i + 1]) * 5)
578
197M
    for (int i = 0; i < w; i++) {
579
193M
        const int a = SIX_NEIGHBORS(B_ptrs, i + 1);
580
193M
        const int b = SIX_NEIGHBORS(A_ptrs, i + 1);
581
193M
        tmp[i] = (b - a * src[i] + (1 << 8)) >> 9;
582
193M
    }
583
3.20M
    if (h <= 1)
584
34.1k
        return;
585
3.17M
    tmp += FILTER_OUT_STRIDE;
586
3.17M
    src += PXSTRIDE(src_stride);
587
3.17M
    const int32_t *A = &A_ptrs[1][1];
588
3.17M
    const coef *B = &B_ptrs[1][1];
589
195M
    for (int i = 0; i < w; i++) {
590
192M
        const int a = B[i] * 6 + (B[i - 1] + B[i + 1]) * 5;
591
192M
        const int b = A[i] * 6 + (A[i - 1] + A[i + 1]) * 5;
592
192M
        tmp[i] = (b - a * src[i] + (1 << 7)) >> 8;
593
192M
    }
594
3.17M
#undef SIX_NEIGHBORS
595
3.17M
}
596
597
static NOINLINE void sgr_weighted_row1(pixel *dst, const coef *t1,
598
                                       const int w, const int w1 HIGHBD_DECL_SUFFIX)
599
3.48M
{
600
199M
    for (int i = 0; i < w; i++) {
601
196M
        const int v = w1 * t1[i];
602
196M
        dst[i] = iclip_pixel(dst[i] + ((v + (1 << 10)) >> 11));
603
196M
    }
604
3.48M
}
605
606
static NOINLINE void sgr_weighted2(pixel *dst, const ptrdiff_t dst_stride,
607
                                   const coef *t1, const coef *t2,
608
                                   const int w, const int h,
609
                                   const int w0, const int w1 HIGHBD_DECL_SUFFIX)
610
2.31M
{
611
6.82M
    for (int j = 0; j < h; j++) {
612
261M
        for (int i = 0; i < w; i++) {
613
256M
            const int v = w0 * t1[i] + w1 * t2[i];
614
256M
            dst[i] = iclip_pixel(dst[i] + ((v + (1 << 10)) >> 11));
615
256M
        }
616
4.50M
        dst += PXSTRIDE(dst_stride);
617
4.50M
        t1 += FILTER_OUT_STRIDE;
618
4.50M
        t2 += FILTER_OUT_STRIDE;
619
4.50M
    }
620
2.31M
}
621
622
static NOINLINE void sgr_finish1(pixel **dst, const ptrdiff_t stride,
623
                                 int32_t **A_ptrs, coef **B_ptrs, const int w,
624
                                 const int w1 HIGHBD_DECL_SUFFIX)
625
1.63M
{
626
    // Only one single row, no stride needed
627
1.63M
    ALIGN_STK_16(coef, tmp, 384,);
628
629
1.63M
    sgr_finish_filter_row1(tmp, *dst, A_ptrs, B_ptrs, w);
630
1.63M
    sgr_weighted_row1(*dst, tmp, w, w1 HIGHBD_TAIL_SUFFIX);
631
1.63M
    *dst += PXSTRIDE(stride);
632
1.63M
    rotate(A_ptrs, B_ptrs, 3);
633
1.63M
}
634
635
static NOINLINE void sgr_finish2(pixel **dst, const ptrdiff_t stride,
636
                                 int32_t **A_ptrs, coef **B_ptrs,
637
                                 const int w, const int h, const int w1
638
                                 HIGHBD_DECL_SUFFIX)
639
947k
{
640
947k
    ALIGN_STK_16(coef, tmp, 2*FILTER_OUT_STRIDE,);
641
642
947k
    sgr_finish_filter2(tmp, *dst, stride, A_ptrs, B_ptrs, w, h);
643
947k
    sgr_weighted_row1(*dst, tmp, w, w1 HIGHBD_TAIL_SUFFIX);
644
947k
    *dst += PXSTRIDE(stride);
645
947k
    if (h > 1) {
646
916k
        sgr_weighted_row1(*dst, tmp + FILTER_OUT_STRIDE, w, w1 HIGHBD_TAIL_SUFFIX);
647
916k
        *dst += PXSTRIDE(stride);
648
916k
    }
649
947k
    rotate(A_ptrs, B_ptrs, 2);
650
947k
}
651
652
static NOINLINE void sgr_finish_mix(pixel **dst, const ptrdiff_t stride,
653
                                    int32_t **A5_ptrs, coef **B5_ptrs,
654
                                    int32_t **A3_ptrs, coef **B3_ptrs,
655
                                    const int w, const int h,
656
                                    const int w0, const int w1 HIGHBD_DECL_SUFFIX)
657
2.25M
{
658
2.25M
    ALIGN_STK_16(coef, tmp5, 2*FILTER_OUT_STRIDE,);
659
2.25M
    ALIGN_STK_16(coef, tmp3, 2*FILTER_OUT_STRIDE,);
660
661
2.25M
    sgr_finish_filter2(tmp5, *dst, stride, A5_ptrs, B5_ptrs, w, h);
662
2.25M
    sgr_finish_filter_row1(tmp3, *dst, A3_ptrs, B3_ptrs, w);
663
2.25M
    if (h > 1)
664
2.28M
        sgr_finish_filter_row1(tmp3 + FILTER_OUT_STRIDE, *dst + PXSTRIDE(stride),
665
2.28M
                               &A3_ptrs[1], &B3_ptrs[1], w);
666
2.25M
    sgr_weighted2(*dst, stride, tmp5, tmp3, w, h, w0, w1 HIGHBD_TAIL_SUFFIX);
667
2.25M
    *dst += h*PXSTRIDE(stride);
668
2.25M
    rotate(A5_ptrs, B5_ptrs, 2);
669
2.25M
    rotate(A3_ptrs, B3_ptrs, 4);
670
2.25M
}
671
672
673
static void sgr_3x3_c(pixel *dst, const ptrdiff_t stride,
674
                      const pixel (*left)[4], const pixel *lpf,
675
                      const int w, int h,
676
                      const LooprestorationParams *const params,
677
                      const enum LrEdgeFlags edges HIGHBD_DECL_SUFFIX)
678
43.7k
{
679
4.54M
#define BUF_STRIDE (384 + 16)
680
43.7k
    ALIGN_STK_16(int32_t, sumsq_buf, BUF_STRIDE * 3 + 16,);
681
43.7k
    ALIGN_STK_16(coef, sum_buf, BUF_STRIDE * 3 + 16,);
682
43.7k
    int32_t *sumsq_ptrs[3], *sumsq_rows[3];
683
43.7k
    coef *sum_ptrs[3], *sum_rows[3];
684
175k
    for (int i = 0; i < 3; i++) {
685
131k
        sumsq_rows[i] = &sumsq_buf[i * BUF_STRIDE];
686
131k
        sum_rows[i] = &sum_buf[i * BUF_STRIDE];
687
131k
    }
688
689
43.7k
    ALIGN_STK_16(int32_t, A_buf, BUF_STRIDE * 3 + 16,);
690
43.7k
    ALIGN_STK_16(coef, B_buf, BUF_STRIDE * 3 + 16,);
691
43.7k
    int32_t *A_ptrs[3];
692
43.7k
    coef *B_ptrs[3];
693
175k
    for (int i = 0; i < 3; i++) {
694
131k
        A_ptrs[i] = &A_buf[i * BUF_STRIDE];
695
131k
        B_ptrs[i] = &B_buf[i * BUF_STRIDE];
696
131k
    }
697
43.7k
    const pixel *src = dst;
698
43.7k
    const pixel *lpf_bottom = lpf + 6*PXSTRIDE(stride);
699
700
43.7k
    if (edges & LR_HAVE_TOP) {
701
30.1k
        sumsq_ptrs[0] = sumsq_rows[0];
702
30.1k
        sumsq_ptrs[1] = sumsq_rows[1];
703
30.1k
        sumsq_ptrs[2] = sumsq_rows[2];
704
30.1k
        sum_ptrs[0] = sum_rows[0];
705
30.1k
        sum_ptrs[1] = sum_rows[1];
706
30.1k
        sum_ptrs[2] = sum_rows[2];
707
708
30.1k
        sgr_box3_row_h(sumsq_rows[0], sum_rows[0], NULL, lpf, w, edges);
709
30.1k
        lpf += PXSTRIDE(stride);
710
30.1k
        sgr_box3_row_h(sumsq_rows[1], sum_rows[1], NULL, lpf, w, edges);
711
712
30.1k
        sgr_box3_hv(sumsq_ptrs, sum_ptrs, A_ptrs[2], B_ptrs[2],
713
30.1k
                    left, src, w, params->sgr.s1, edges, BITDEPTH_MAX);
714
30.1k
        left++;
715
30.1k
        src += PXSTRIDE(stride);
716
30.1k
        rotate(A_ptrs, B_ptrs, 3);
717
718
30.1k
        if (--h <= 0)
719
1.01k
            goto vert_1;
720
721
29.1k
        sgr_box3_hv(sumsq_ptrs, sum_ptrs, A_ptrs[2], B_ptrs[2],
722
29.1k
                    left, src, w, params->sgr.s1, edges, BITDEPTH_MAX);
723
29.1k
        left++;
724
29.1k
        src += PXSTRIDE(stride);
725
29.1k
        rotate(A_ptrs, B_ptrs, 3);
726
727
29.1k
        if (--h <= 0)
728
1.00k
            goto vert_2;
729
29.1k
    } else {
730
13.6k
        sumsq_ptrs[0] = sumsq_rows[0];
731
13.6k
        sumsq_ptrs[1] = sumsq_rows[0];
732
13.6k
        sumsq_ptrs[2] = sumsq_rows[0];
733
13.6k
        sum_ptrs[0] = sum_rows[0];
734
13.6k
        sum_ptrs[1] = sum_rows[0];
735
13.6k
        sum_ptrs[2] = sum_rows[0];
736
737
13.6k
        sgr_box3_row_h(sumsq_rows[0], sum_rows[0], left, src, w, edges);
738
13.6k
        left++;
739
13.6k
        src += PXSTRIDE(stride);
740
741
13.6k
        sgr_box3_vert(sumsq_ptrs, sum_ptrs, A_ptrs[2], B_ptrs[2],
742
13.6k
                      w, params->sgr.s1, BITDEPTH_MAX);
743
13.6k
        rotate(A_ptrs, B_ptrs, 3);
744
745
13.6k
        if (--h <= 0)
746
1.93k
            goto vert_1;
747
748
11.6k
        sumsq_ptrs[2] = sumsq_rows[1];
749
11.6k
        sum_ptrs[2] = sum_rows[1];
750
751
11.6k
        sgr_box3_hv(sumsq_ptrs, sum_ptrs, A_ptrs[2], B_ptrs[2],
752
11.6k
                    left, src, w, params->sgr.s1, edges, BITDEPTH_MAX);
753
11.6k
        left++;
754
11.6k
        src += PXSTRIDE(stride);
755
11.6k
        rotate(A_ptrs, B_ptrs, 3);
756
757
11.6k
        if (--h <= 0)
758
1.34k
            goto vert_2;
759
760
10.3k
        sumsq_ptrs[2] = sumsq_rows[2];
761
10.3k
        sum_ptrs[2] = sum_rows[2];
762
10.3k
    }
763
764
1.55M
    do {
765
1.55M
        sgr_box3_hv(sumsq_ptrs, sum_ptrs, A_ptrs[2], B_ptrs[2],
766
1.55M
                    left, src, w, params->sgr.s1, edges, BITDEPTH_MAX);
767
1.55M
        left++;
768
1.55M
        src += PXSTRIDE(stride);
769
770
1.55M
        sgr_finish1(&dst, stride, A_ptrs, B_ptrs,
771
1.55M
                    w, params->sgr.w1 HIGHBD_TAIL_SUFFIX);
772
1.55M
    } while (--h > 0);
773
774
38.4k
    if (!(edges & LR_HAVE_BOTTOM))
775
11.4k
        goto vert_2;
776
777
26.9k
    sgr_box3_hv(sumsq_ptrs, sum_ptrs, A_ptrs[2], B_ptrs[2],
778
26.9k
                NULL, lpf_bottom, w, params->sgr.s1, edges, BITDEPTH_MAX);
779
26.9k
    lpf_bottom += PXSTRIDE(stride);
780
781
26.9k
    sgr_finish1(&dst, stride, A_ptrs, B_ptrs,
782
26.9k
                w, params->sgr.w1 HIGHBD_TAIL_SUFFIX);
783
784
26.9k
    sgr_box3_hv(sumsq_ptrs, sum_ptrs, A_ptrs[2], B_ptrs[2],
785
26.9k
                NULL, lpf_bottom, w, params->sgr.s1, edges, BITDEPTH_MAX);
786
787
26.9k
    sgr_finish1(&dst, stride, A_ptrs, B_ptrs,
788
26.9k
                w, params->sgr.w1 HIGHBD_TAIL_SUFFIX);
789
26.9k
    return;
790
791
13.8k
vert_2:
792
13.8k
    sumsq_ptrs[2] = sumsq_ptrs[1];
793
13.8k
    sum_ptrs[2] = sum_ptrs[1];
794
13.8k
    sgr_box3_vert(sumsq_ptrs, sum_ptrs, A_ptrs[2], B_ptrs[2],
795
13.8k
                  w, params->sgr.s1, BITDEPTH_MAX);
796
797
13.8k
    sgr_finish1(&dst, stride, A_ptrs, B_ptrs,
798
13.8k
                w, params->sgr.w1 HIGHBD_TAIL_SUFFIX);
799
800
16.7k
output_1:
801
16.7k
    sumsq_ptrs[2] = sumsq_ptrs[1];
802
16.7k
    sum_ptrs[2] = sum_ptrs[1];
803
16.7k
    sgr_box3_vert(sumsq_ptrs, sum_ptrs, A_ptrs[2], B_ptrs[2],
804
16.7k
                  w, params->sgr.s1, BITDEPTH_MAX);
805
806
16.7k
    sgr_finish1(&dst, stride, A_ptrs, B_ptrs,
807
16.7k
                w, params->sgr.w1 HIGHBD_TAIL_SUFFIX);
808
16.7k
    return;
809
810
2.95k
vert_1:
811
2.95k
    sumsq_ptrs[2] = sumsq_ptrs[1];
812
2.95k
    sum_ptrs[2] = sum_ptrs[1];
813
2.95k
    sgr_box3_vert(sumsq_ptrs, sum_ptrs, A_ptrs[2], B_ptrs[2],
814
2.95k
                  w, params->sgr.s1, BITDEPTH_MAX);
815
2.95k
    rotate(A_ptrs, B_ptrs, 3);
816
2.95k
    goto output_1;
817
13.8k
}
818
819
static void sgr_5x5_c(pixel *dst, const ptrdiff_t stride,
820
                      const pixel (*left)[4], const pixel *lpf,
821
                      const int w, int h,
822
                      const LooprestorationParams *const params,
823
                      const enum LrEdgeFlags edges HIGHBD_DECL_SUFFIX)
824
50.0k
{
825
50.0k
    ALIGN_STK_16(int32_t, sumsq_buf, BUF_STRIDE * 5 + 16,);
826
50.0k
    ALIGN_STK_16(coef, sum_buf, BUF_STRIDE * 5 + 16,);
827
50.0k
    int32_t *sumsq_ptrs[5], *sumsq_rows[5];
828
50.0k
    coef *sum_ptrs[5], *sum_rows[5];
829
300k
    for (int i = 0; i < 5; i++) {
830
250k
        sumsq_rows[i] = &sumsq_buf[i * BUF_STRIDE];
831
250k
        sum_rows[i] = &sum_buf[i * BUF_STRIDE];
832
250k
    }
833
834
50.0k
    ALIGN_STK_16(int32_t, A_buf, BUF_STRIDE * 2 + 16,);
835
50.0k
    ALIGN_STK_16(coef, B_buf, BUF_STRIDE * 2 + 16,);
836
50.0k
    int32_t *A_ptrs[2];
837
50.0k
    coef *B_ptrs[2];
838
150k
    for (int i = 0; i < 2; i++) {
839
100k
        A_ptrs[i] = &A_buf[i * BUF_STRIDE];
840
100k
        B_ptrs[i] = &B_buf[i * BUF_STRIDE];
841
100k
    }
842
50.0k
    const pixel *src = dst;
843
50.0k
    const pixel *lpf_bottom = lpf + 6*PXSTRIDE(stride);
844
845
50.0k
    if (edges & LR_HAVE_TOP) {
846
31.8k
        sumsq_ptrs[0] = sumsq_rows[0];
847
31.8k
        sumsq_ptrs[1] = sumsq_rows[0];
848
31.8k
        sumsq_ptrs[2] = sumsq_rows[1];
849
31.8k
        sumsq_ptrs[3] = sumsq_rows[2];
850
31.8k
        sumsq_ptrs[4] = sumsq_rows[3];
851
31.8k
        sum_ptrs[0] = sum_rows[0];
852
31.8k
        sum_ptrs[1] = sum_rows[0];
853
31.8k
        sum_ptrs[2] = sum_rows[1];
854
31.8k
        sum_ptrs[3] = sum_rows[2];
855
31.8k
        sum_ptrs[4] = sum_rows[3];
856
857
31.8k
        sgr_box5_row_h(sumsq_rows[0], sum_rows[0], NULL, lpf, w, edges);
858
31.8k
        lpf += PXSTRIDE(stride);
859
31.8k
        sgr_box5_row_h(sumsq_rows[1], sum_rows[1], NULL, lpf, w, edges);
860
861
31.8k
        sgr_box5_row_h(sumsq_rows[2], sum_rows[2], left, src, w, edges);
862
31.8k
        left++;
863
31.8k
        src += PXSTRIDE(stride);
864
865
31.8k
        if (--h <= 0)
866
1.06k
            goto vert_1;
867
868
30.7k
        sgr_box5_row_h(sumsq_rows[3], sum_rows[3], left, src, w, edges);
869
30.7k
        left++;
870
30.7k
        src += PXSTRIDE(stride);
871
30.7k
        sgr_box5_vert(sumsq_ptrs, sum_ptrs, A_ptrs[1], B_ptrs[1],
872
30.7k
                      w, params->sgr.s0, BITDEPTH_MAX);
873
30.7k
        rotate(A_ptrs, B_ptrs, 2);
874
875
30.7k
        if (--h <= 0)
876
1.02k
            goto vert_2;
877
878
        // ptrs are rotated by 2; both [3] and [4] now point at rows[0]; set
879
        // one of them to point at the previously unused rows[4].
880
29.7k
        sumsq_ptrs[3] = sumsq_rows[4];
881
29.7k
        sum_ptrs[3] = sum_rows[4];
882
29.7k
    } else {
883
18.2k
        sumsq_ptrs[0] = sumsq_rows[0];
884
18.2k
        sumsq_ptrs[1] = sumsq_rows[0];
885
18.2k
        sumsq_ptrs[2] = sumsq_rows[0];
886
18.2k
        sumsq_ptrs[3] = sumsq_rows[0];
887
18.2k
        sumsq_ptrs[4] = sumsq_rows[0];
888
18.2k
        sum_ptrs[0] = sum_rows[0];
889
18.2k
        sum_ptrs[1] = sum_rows[0];
890
18.2k
        sum_ptrs[2] = sum_rows[0];
891
18.2k
        sum_ptrs[3] = sum_rows[0];
892
18.2k
        sum_ptrs[4] = sum_rows[0];
893
894
18.2k
        sgr_box5_row_h(sumsq_rows[0], sum_rows[0], left, src, w, edges);
895
18.2k
        left++;
896
18.2k
        src += PXSTRIDE(stride);
897
898
18.2k
        if (--h <= 0)
899
2.08k
            goto vert_1;
900
901
16.1k
        sumsq_ptrs[4] = sumsq_rows[1];
902
16.1k
        sum_ptrs[4] = sum_rows[1];
903
904
16.1k
        sgr_box5_row_h(sumsq_rows[1], sum_rows[1], left, src, w, edges);
905
16.1k
        left++;
906
16.1k
        src += PXSTRIDE(stride);
907
908
16.1k
        sgr_box5_vert(sumsq_ptrs, sum_ptrs, A_ptrs[1], B_ptrs[1],
909
16.1k
                      w, params->sgr.s0, BITDEPTH_MAX);
910
16.1k
        rotate(A_ptrs, B_ptrs, 2);
911
912
16.1k
        if (--h <= 0)
913
2.08k
            goto vert_2;
914
915
14.0k
        sumsq_ptrs[3] = sumsq_rows[2];
916
14.0k
        sumsq_ptrs[4] = sumsq_rows[3];
917
14.0k
        sum_ptrs[3] = sum_rows[2];
918
14.0k
        sum_ptrs[4] = sum_rows[3];
919
920
14.0k
        sgr_box5_row_h(sumsq_rows[2], sum_rows[2], left, src, w, edges);
921
14.0k
        left++;
922
14.0k
        src += PXSTRIDE(stride);
923
924
14.0k
        if (--h <= 0)
925
1.53k
            goto odd;
926
927
12.5k
        sgr_box5_row_h(sumsq_rows[3], sum_rows[3], left, src, w, edges);
928
12.5k
        left++;
929
12.5k
        src += PXSTRIDE(stride);
930
931
12.5k
        sgr_box5_vert(sumsq_ptrs, sum_ptrs, A_ptrs[1], B_ptrs[1],
932
12.5k
                      w, params->sgr.s0, BITDEPTH_MAX);
933
12.5k
        sgr_finish2(&dst, stride, A_ptrs, B_ptrs,
934
12.5k
                    w, 2, params->sgr.w0 HIGHBD_TAIL_SUFFIX);
935
936
12.5k
        if (--h <= 0)
937
1.54k
            goto vert_2;
938
939
        // ptrs are rotated by 2; both [3] and [4] now point at rows[0]; set
940
        // one of them to point at the previously unused rows[4].
941
11.0k
        sumsq_ptrs[3] = sumsq_rows[4];
942
11.0k
        sum_ptrs[3] = sum_rows[4];
943
11.0k
    }
944
945
867k
    do {
946
867k
        sgr_box5_row_h(sumsq_ptrs[3], sum_ptrs[3], left, src, w, edges);
947
867k
        left++;
948
867k
        src += PXSTRIDE(stride);
949
950
867k
        if (--h <= 0)
951
5.37k
            goto odd;
952
953
861k
        sgr_box5_row_h(sumsq_ptrs[4], sum_ptrs[4], left, src, w, edges);
954
861k
        left++;
955
861k
        src += PXSTRIDE(stride);
956
957
861k
        sgr_box5_vert(sumsq_ptrs, sum_ptrs, A_ptrs[1], B_ptrs[1],
958
861k
                      w, params->sgr.s0, BITDEPTH_MAX);
959
861k
        sgr_finish2(&dst, stride, A_ptrs, B_ptrs,
960
861k
                    w, 2, params->sgr.w0 HIGHBD_TAIL_SUFFIX);
961
861k
    } while (--h > 0);
962
963
35.3k
    if (!(edges & LR_HAVE_BOTTOM))
964
4.30k
        goto vert_2;
965
966
31.0k
    sgr_box5_row_h(sumsq_ptrs[3], sum_ptrs[3], NULL, lpf_bottom, w, edges);
967
31.0k
    lpf_bottom += PXSTRIDE(stride);
968
31.0k
    sgr_box5_row_h(sumsq_ptrs[4], sum_ptrs[4], NULL, lpf_bottom, w, edges);
969
970
40.0k
output_2:
971
40.0k
    sgr_box5_vert(sumsq_ptrs, sum_ptrs, A_ptrs[1], B_ptrs[1],
972
40.0k
                  w, params->sgr.s0, BITDEPTH_MAX);
973
40.0k
    sgr_finish2(&dst, stride, A_ptrs, B_ptrs,
974
40.0k
                w, 2, params->sgr.w0 HIGHBD_TAIL_SUFFIX);
975
40.0k
    return;
976
977
8.94k
vert_2:
978
    // Duplicate the last row twice more
979
8.94k
    sumsq_ptrs[3] = sumsq_ptrs[2];
980
8.94k
    sumsq_ptrs[4] = sumsq_ptrs[2];
981
8.94k
    sum_ptrs[3] = sum_ptrs[2];
982
8.94k
    sum_ptrs[4] = sum_ptrs[2];
983
8.94k
    goto output_2;
984
985
6.90k
odd:
986
    // Copy the last row as padding once
987
6.90k
    sumsq_ptrs[4] = sumsq_ptrs[3];
988
6.90k
    sum_ptrs[4] = sum_ptrs[3];
989
990
6.90k
    sgr_box5_vert(sumsq_ptrs, sum_ptrs, A_ptrs[1], B_ptrs[1],
991
6.90k
                  w, params->sgr.s0, BITDEPTH_MAX);
992
6.90k
    sgr_finish2(&dst, stride, A_ptrs, B_ptrs,
993
6.90k
                w, 2, params->sgr.w0 HIGHBD_TAIL_SUFFIX);
994
995
10.0k
output_1:
996
    // Duplicate the last row twice more
997
10.0k
    sumsq_ptrs[3] = sumsq_ptrs[2];
998
10.0k
    sumsq_ptrs[4] = sumsq_ptrs[2];
999
10.0k
    sum_ptrs[3] = sum_ptrs[2];
1000
10.0k
    sum_ptrs[4] = sum_ptrs[2];
1001
1002
10.0k
    sgr_box5_vert(sumsq_ptrs, sum_ptrs, A_ptrs[1], B_ptrs[1],
1003
10.0k
                  w, params->sgr.s0, BITDEPTH_MAX);
1004
    // Output only one row
1005
10.0k
    sgr_finish2(&dst, stride, A_ptrs, B_ptrs,
1006
10.0k
                w, 1, params->sgr.w0 HIGHBD_TAIL_SUFFIX);
1007
10.0k
    return;
1008
1009
3.14k
vert_1:
1010
    // Copy the last row as padding once
1011
3.14k
    sumsq_ptrs[4] = sumsq_ptrs[3];
1012
3.14k
    sum_ptrs[4] = sum_ptrs[3];
1013
1014
3.14k
    sgr_box5_vert(sumsq_ptrs, sum_ptrs, A_ptrs[1], B_ptrs[1],
1015
3.14k
                  w, params->sgr.s0, BITDEPTH_MAX);
1016
3.14k
    rotate(A_ptrs, B_ptrs, 2);
1017
1018
3.14k
    goto output_1;
1019
6.90k
}
1020
1021
static void sgr_mix_c(pixel *dst, const ptrdiff_t stride,
1022
                      const pixel (*left)[4], const pixel *lpf,
1023
                      const int w, int h,
1024
                      const LooprestorationParams *const params,
1025
                      const enum LrEdgeFlags edges HIGHBD_DECL_SUFFIX)
1026
118k
{
1027
118k
    ALIGN_STK_16(int32_t, sumsq5_buf, BUF_STRIDE * 5 + 16,);
1028
118k
    ALIGN_STK_16(coef, sum5_buf, BUF_STRIDE * 5 + 16,);
1029
118k
    int32_t *sumsq5_ptrs[5], *sumsq5_rows[5];
1030
118k
    coef *sum5_ptrs[5], *sum5_rows[5];
1031
711k
    for (int i = 0; i < 5; i++) {
1032
593k
        sumsq5_rows[i] = &sumsq5_buf[i * BUF_STRIDE];
1033
593k
        sum5_rows[i] = &sum5_buf[i * BUF_STRIDE];
1034
593k
    }
1035
118k
    ALIGN_STK_16(int32_t, sumsq3_buf, BUF_STRIDE * 3 + 16,);
1036
118k
    ALIGN_STK_16(coef, sum3_buf, BUF_STRIDE * 3 + 16,);
1037
118k
    int32_t *sumsq3_ptrs[3], *sumsq3_rows[3];
1038
118k
    coef *sum3_ptrs[3], *sum3_rows[3];
1039
474k
    for (int i = 0; i < 3; i++) {
1040
355k
        sumsq3_rows[i] = &sumsq3_buf[i * BUF_STRIDE];
1041
355k
        sum3_rows[i] = &sum3_buf[i * BUF_STRIDE];
1042
355k
    }
1043
1044
118k
    ALIGN_STK_16(int32_t, A5_buf, BUF_STRIDE * 2 + 16,);
1045
118k
    ALIGN_STK_16(coef, B5_buf, BUF_STRIDE * 2 + 16,);
1046
118k
    int32_t *A5_ptrs[2];
1047
118k
    coef *B5_ptrs[2];
1048
355k
    for (int i = 0; i < 2; i++) {
1049
237k
        A5_ptrs[i] = &A5_buf[i * BUF_STRIDE];
1050
237k
        B5_ptrs[i] = &B5_buf[i * BUF_STRIDE];
1051
237k
    }
1052
118k
    ALIGN_STK_16(int32_t, A3_buf, BUF_STRIDE * 4 + 16,);
1053
118k
    ALIGN_STK_16(coef, B3_buf, BUF_STRIDE * 4 + 16,);
1054
118k
    int32_t *A3_ptrs[4];
1055
118k
    coef *B3_ptrs[4];
1056
593k
    for (int i = 0; i < 4; i++) {
1057
474k
        A3_ptrs[i] = &A3_buf[i * BUF_STRIDE];
1058
474k
        B3_ptrs[i] = &B3_buf[i * BUF_STRIDE];
1059
474k
    }
1060
118k
    const pixel *src = dst;
1061
118k
    const pixel *lpf_bottom = lpf + 6*PXSTRIDE(stride);
1062
1063
118k
    if (edges & LR_HAVE_TOP) {
1064
81.3k
        sumsq5_ptrs[0] = sumsq5_rows[0];
1065
81.3k
        sumsq5_ptrs[1] = sumsq5_rows[0];
1066
81.3k
        sumsq5_ptrs[2] = sumsq5_rows[1];
1067
81.3k
        sumsq5_ptrs[3] = sumsq5_rows[2];
1068
81.3k
        sumsq5_ptrs[4] = sumsq5_rows[3];
1069
81.3k
        sum5_ptrs[0] = sum5_rows[0];
1070
81.3k
        sum5_ptrs[1] = sum5_rows[0];
1071
81.3k
        sum5_ptrs[2] = sum5_rows[1];
1072
81.3k
        sum5_ptrs[3] = sum5_rows[2];
1073
81.3k
        sum5_ptrs[4] = sum5_rows[3];
1074
1075
81.3k
        sumsq3_ptrs[0] = sumsq3_rows[0];
1076
81.3k
        sumsq3_ptrs[1] = sumsq3_rows[1];
1077
81.3k
        sumsq3_ptrs[2] = sumsq3_rows[2];
1078
81.3k
        sum3_ptrs[0] = sum3_rows[0];
1079
81.3k
        sum3_ptrs[1] = sum3_rows[1];
1080
81.3k
        sum3_ptrs[2] = sum3_rows[2];
1081
1082
81.3k
        sgr_box35_row_h(sumsq3_rows[0], sum3_rows[0],
1083
81.3k
                        sumsq5_rows[0], sum5_rows[0],
1084
81.3k
                        NULL, lpf, w, edges);
1085
81.3k
        lpf += PXSTRIDE(stride);
1086
81.3k
        sgr_box35_row_h(sumsq3_rows[1], sum3_rows[1],
1087
81.3k
                        sumsq5_rows[1], sum5_rows[1],
1088
81.3k
                        NULL, lpf, w, edges);
1089
1090
81.3k
        sgr_box35_row_h(sumsq3_rows[2], sum3_rows[2],
1091
81.3k
                        sumsq5_rows[2], sum5_rows[2],
1092
81.3k
                        left, src, w, edges);
1093
81.3k
        left++;
1094
81.3k
        src += PXSTRIDE(stride);
1095
1096
81.3k
        sgr_box3_vert(sumsq3_ptrs, sum3_ptrs, A3_ptrs[3], B3_ptrs[3],
1097
81.3k
                      w, params->sgr.s1, BITDEPTH_MAX);
1098
81.3k
        rotate(A3_ptrs, B3_ptrs, 4);
1099
1100
81.3k
        if (--h <= 0)
1101
2.06k
            goto vert_1;
1102
1103
79.2k
        sgr_box35_row_h(sumsq3_ptrs[2], sum3_ptrs[2],
1104
79.2k
                        sumsq5_rows[3], sum5_rows[3],
1105
79.2k
                        left, src, w, edges);
1106
79.2k
        left++;
1107
79.2k
        src += PXSTRIDE(stride);
1108
79.2k
        sgr_box5_vert(sumsq5_ptrs, sum5_ptrs, A5_ptrs[1], B5_ptrs[1],
1109
79.2k
                      w, params->sgr.s0, BITDEPTH_MAX);
1110
79.2k
        rotate(A5_ptrs, B5_ptrs, 2);
1111
79.2k
        sgr_box3_vert(sumsq3_ptrs, sum3_ptrs, A3_ptrs[3], B3_ptrs[3],
1112
79.2k
                      w, params->sgr.s1, BITDEPTH_MAX);
1113
79.2k
        rotate(A3_ptrs, B3_ptrs, 4);
1114
1115
79.2k
        if (--h <= 0)
1116
1.79k
            goto vert_2;
1117
1118
        // ptrs are rotated by 2; both [3] and [4] now point at rows[0]; set
1119
        // one of them to point at the previously unused rows[4].
1120
77.5k
        sumsq5_ptrs[3] = sumsq5_rows[4];
1121
77.5k
        sum5_ptrs[3] = sum5_rows[4];
1122
77.5k
    } else {
1123
37.2k
        sumsq5_ptrs[0] = sumsq5_rows[0];
1124
37.2k
        sumsq5_ptrs[1] = sumsq5_rows[0];
1125
37.2k
        sumsq5_ptrs[2] = sumsq5_rows[0];
1126
37.2k
        sumsq5_ptrs[3] = sumsq5_rows[0];
1127
37.2k
        sumsq5_ptrs[4] = sumsq5_rows[0];
1128
37.2k
        sum5_ptrs[0] = sum5_rows[0];
1129
37.2k
        sum5_ptrs[1] = sum5_rows[0];
1130
37.2k
        sum5_ptrs[2] = sum5_rows[0];
1131
37.2k
        sum5_ptrs[3] = sum5_rows[0];
1132
37.2k
        sum5_ptrs[4] = sum5_rows[0];
1133
1134
37.2k
        sumsq3_ptrs[0] = sumsq3_rows[0];
1135
37.2k
        sumsq3_ptrs[1] = sumsq3_rows[0];
1136
37.2k
        sumsq3_ptrs[2] = sumsq3_rows[0];
1137
37.2k
        sum3_ptrs[0] = sum3_rows[0];
1138
37.2k
        sum3_ptrs[1] = sum3_rows[0];
1139
37.2k
        sum3_ptrs[2] = sum3_rows[0];
1140
1141
37.2k
        sgr_box35_row_h(sumsq3_rows[0], sum3_rows[0],
1142
37.2k
                        sumsq5_rows[0], sum5_rows[0],
1143
37.2k
                        left, src, w, edges);
1144
37.2k
        left++;
1145
37.2k
        src += PXSTRIDE(stride);
1146
1147
37.2k
        sgr_box3_vert(sumsq3_ptrs, sum3_ptrs, A3_ptrs[3], B3_ptrs[3],
1148
37.2k
                      w, params->sgr.s1, BITDEPTH_MAX);
1149
37.2k
        rotate(A3_ptrs, B3_ptrs, 4);
1150
1151
37.2k
        if (--h <= 0)
1152
6.58k
            goto vert_1;
1153
1154
30.6k
        sumsq5_ptrs[4] = sumsq5_rows[1];
1155
30.6k
        sum5_ptrs[4] = sum5_rows[1];
1156
1157
30.6k
        sumsq3_ptrs[2] = sumsq3_rows[1];
1158
30.6k
        sum3_ptrs[2] = sum3_rows[1];
1159
1160
30.6k
        sgr_box35_row_h(sumsq3_rows[1], sum3_rows[1],
1161
30.6k
                        sumsq5_rows[1], sum5_rows[1],
1162
30.6k
                        left, src, w, edges);
1163
30.6k
        left++;
1164
30.6k
        src += PXSTRIDE(stride);
1165
1166
30.6k
        sgr_box5_vert(sumsq5_ptrs, sum5_ptrs, A5_ptrs[1], B5_ptrs[1],
1167
30.6k
                      w, params->sgr.s0, BITDEPTH_MAX);
1168
30.6k
        rotate(A5_ptrs, B5_ptrs, 2);
1169
30.6k
        sgr_box3_vert(sumsq3_ptrs, sum3_ptrs, A3_ptrs[3], B3_ptrs[3],
1170
30.6k
                      w, params->sgr.s1, BITDEPTH_MAX);
1171
30.6k
        rotate(A3_ptrs, B3_ptrs, 4);
1172
1173
30.6k
        if (--h <= 0)
1174
3.90k
            goto vert_2;
1175
1176
26.7k
        sumsq5_ptrs[3] = sumsq5_rows[2];
1177
26.7k
        sumsq5_ptrs[4] = sumsq5_rows[3];
1178
26.7k
        sum5_ptrs[3] = sum5_rows[2];
1179
26.7k
        sum5_ptrs[4] = sum5_rows[3];
1180
1181
26.7k
        sumsq3_ptrs[2] = sumsq3_rows[2];
1182
26.7k
        sum3_ptrs[2] = sum3_rows[2];
1183
1184
26.7k
        sgr_box35_row_h(sumsq3_rows[2], sum3_rows[2],
1185
26.7k
                        sumsq5_rows[2], sum5_rows[2],
1186
26.7k
                        left, src, w, edges);
1187
26.7k
        left++;
1188
26.7k
        src += PXSTRIDE(stride);
1189
1190
26.7k
        sgr_box3_vert(sumsq3_ptrs, sum3_ptrs, A3_ptrs[3], B3_ptrs[3],
1191
26.7k
                      w, params->sgr.s1, BITDEPTH_MAX);
1192
26.7k
        rotate(A3_ptrs, B3_ptrs, 4);
1193
1194
26.7k
        if (--h <= 0)
1195
2.30k
            goto odd;
1196
1197
24.4k
        sgr_box35_row_h(sumsq3_ptrs[2], sum3_ptrs[2],
1198
24.4k
                        sumsq5_rows[3], sum5_rows[3],
1199
24.4k
                        left, src, w, edges);
1200
24.4k
        left++;
1201
24.4k
        src += PXSTRIDE(stride);
1202
1203
24.4k
        sgr_box5_vert(sumsq5_ptrs, sum5_ptrs, A5_ptrs[1], B5_ptrs[1],
1204
24.4k
                      w, params->sgr.s0, BITDEPTH_MAX);
1205
24.4k
        sgr_box3_vert(sumsq3_ptrs, sum3_ptrs, A3_ptrs[3], B3_ptrs[3],
1206
24.4k
                      w, params->sgr.s1, BITDEPTH_MAX);
1207
24.4k
        sgr_finish_mix(&dst, stride, A5_ptrs, B5_ptrs, A3_ptrs, B3_ptrs,
1208
24.4k
                       w, 2, params->sgr.w0, params->sgr.w1
1209
24.4k
                       HIGHBD_TAIL_SUFFIX);
1210
1211
24.4k
        if (--h <= 0)
1212
2.95k
            goto vert_2;
1213
1214
        // ptrs are rotated by 2; both [3] and [4] now point at rows[0]; set
1215
        // one of them to point at the previously unused rows[4].
1216
21.5k
        sumsq5_ptrs[3] = sumsq5_rows[4];
1217
21.5k
        sum5_ptrs[3] = sum5_rows[4];
1218
21.5k
    }
1219
1220
2.12M
    do {
1221
2.12M
        sgr_box35_row_h(sumsq3_ptrs[2], sum3_ptrs[2],
1222
2.12M
                        sumsq5_ptrs[3], sum5_ptrs[3],
1223
2.12M
                        left, src, w, edges);
1224
2.12M
        left++;
1225
2.12M
        src += PXSTRIDE(stride);
1226
1227
2.12M
        sgr_box3_vert(sumsq3_ptrs, sum3_ptrs, A3_ptrs[3], B3_ptrs[3],
1228
2.12M
                      w, params->sgr.s1, BITDEPTH_MAX);
1229
2.12M
        rotate(A3_ptrs, B3_ptrs, 4);
1230
1231
2.12M
        if (--h <= 0)
1232
13.1k
            goto odd;
1233
1234
2.11M
        sgr_box35_row_h(sumsq3_ptrs[2], sum3_ptrs[2],
1235
2.11M
                        sumsq5_ptrs[4], sum5_ptrs[4],
1236
2.11M
                        left, src, w, edges);
1237
2.11M
        left++;
1238
2.11M
        src += PXSTRIDE(stride);
1239
1240
2.11M
        sgr_box5_vert(sumsq5_ptrs, sum5_ptrs, A5_ptrs[1], B5_ptrs[1],
1241
2.11M
                      w, params->sgr.s0, BITDEPTH_MAX);
1242
2.11M
        sgr_box3_vert(sumsq3_ptrs, sum3_ptrs, A3_ptrs[3], B3_ptrs[3],
1243
2.11M
                      w, params->sgr.s1, BITDEPTH_MAX);
1244
2.11M
        sgr_finish_mix(&dst, stride, A5_ptrs, B5_ptrs, A3_ptrs, B3_ptrs,
1245
2.11M
                       w, 2, params->sgr.w0, params->sgr.w1
1246
2.11M
                       HIGHBD_TAIL_SUFFIX);
1247
2.11M
    } while (--h > 0);
1248
1249
85.9k
    if (!(edges & LR_HAVE_BOTTOM))
1250
10.8k
        goto vert_2;
1251
1252
75.1k
    sgr_box35_row_h(sumsq3_ptrs[2], sum3_ptrs[2],
1253
75.1k
                    sumsq5_ptrs[3], sum5_ptrs[3],
1254
75.1k
                    NULL, lpf_bottom, w, edges);
1255
75.1k
    lpf_bottom += PXSTRIDE(stride);
1256
75.1k
    sgr_box3_vert(sumsq3_ptrs, sum3_ptrs, A3_ptrs[3], B3_ptrs[3],
1257
75.1k
                  w, params->sgr.s1, BITDEPTH_MAX);
1258
75.1k
    rotate(A3_ptrs, B3_ptrs, 4);
1259
1260
75.1k
    sgr_box35_row_h(sumsq3_ptrs[2], sum3_ptrs[2],
1261
75.1k
                    sumsq5_ptrs[4], sum5_ptrs[4],
1262
75.1k
                    NULL, lpf_bottom, w, edges);
1263
1264
94.5k
output_2:
1265
94.5k
    sgr_box5_vert(sumsq5_ptrs, sum5_ptrs, A5_ptrs[1], B5_ptrs[1],
1266
94.5k
                  w, params->sgr.s0, BITDEPTH_MAX);
1267
94.5k
    sgr_box3_vert(sumsq3_ptrs, sum3_ptrs, A3_ptrs[3], B3_ptrs[3],
1268
94.5k
                  w, params->sgr.s1, BITDEPTH_MAX);
1269
94.5k
    sgr_finish_mix(&dst, stride, A5_ptrs, B5_ptrs, A3_ptrs, B3_ptrs,
1270
94.5k
                   w, 2, params->sgr.w0, params->sgr.w1
1271
94.5k
                   HIGHBD_TAIL_SUFFIX);
1272
94.5k
    return;
1273
1274
19.4k
vert_2:
1275
    // Duplicate the last row twice more
1276
19.4k
    sumsq5_ptrs[3] = sumsq5_ptrs[2];
1277
19.4k
    sumsq5_ptrs[4] = sumsq5_ptrs[2];
1278
19.4k
    sum5_ptrs[3] = sum5_ptrs[2];
1279
19.4k
    sum5_ptrs[4] = sum5_ptrs[2];
1280
1281
19.4k
    sumsq3_ptrs[2] = sumsq3_ptrs[1];
1282
19.4k
    sum3_ptrs[2] = sum3_ptrs[1];
1283
19.4k
    sgr_box3_vert(sumsq3_ptrs, sum3_ptrs, A3_ptrs[3], B3_ptrs[3],
1284
19.4k
                  w, params->sgr.s1, BITDEPTH_MAX);
1285
19.4k
    rotate(A3_ptrs, B3_ptrs, 4);
1286
1287
19.4k
    sumsq3_ptrs[2] = sumsq3_ptrs[1];
1288
19.4k
    sum3_ptrs[2] = sum3_ptrs[1];
1289
1290
19.4k
    goto output_2;
1291
1292
15.4k
odd:
1293
    // Copy the last row as padding once
1294
15.4k
    sumsq5_ptrs[4] = sumsq5_ptrs[3];
1295
15.4k
    sum5_ptrs[4] = sum5_ptrs[3];
1296
1297
15.4k
    sumsq3_ptrs[2] = sumsq3_ptrs[1];
1298
15.4k
    sum3_ptrs[2] = sum3_ptrs[1];
1299
1300
15.4k
    sgr_box5_vert(sumsq5_ptrs, sum5_ptrs, A5_ptrs[1], B5_ptrs[1],
1301
15.4k
                  w, params->sgr.s0, BITDEPTH_MAX);
1302
15.4k
    sgr_box3_vert(sumsq3_ptrs, sum3_ptrs, A3_ptrs[3], B3_ptrs[3],
1303
15.4k
                  w, params->sgr.s1, BITDEPTH_MAX);
1304
15.4k
    sgr_finish_mix(&dst, stride, A5_ptrs, B5_ptrs, A3_ptrs, B3_ptrs,
1305
15.4k
                   w, 2, params->sgr.w0, params->sgr.w1
1306
15.4k
                   HIGHBD_TAIL_SUFFIX);
1307
1308
24.0k
output_1:
1309
    // Duplicate the last row twice more
1310
24.0k
    sumsq5_ptrs[3] = sumsq5_ptrs[2];
1311
24.0k
    sumsq5_ptrs[4] = sumsq5_ptrs[2];
1312
24.0k
    sum5_ptrs[3] = sum5_ptrs[2];
1313
24.0k
    sum5_ptrs[4] = sum5_ptrs[2];
1314
1315
24.0k
    sumsq3_ptrs[2] = sumsq3_ptrs[1];
1316
24.0k
    sum3_ptrs[2] = sum3_ptrs[1];
1317
1318
24.0k
    sgr_box5_vert(sumsq5_ptrs, sum5_ptrs, A5_ptrs[1], B5_ptrs[1],
1319
24.0k
                  w, params->sgr.s0, BITDEPTH_MAX);
1320
24.0k
    sgr_box3_vert(sumsq3_ptrs, sum3_ptrs, A3_ptrs[3], B3_ptrs[3],
1321
24.0k
                  w, params->sgr.s1, BITDEPTH_MAX);
1322
24.0k
    rotate(A3_ptrs, B3_ptrs, 4);
1323
    // Output only one row
1324
24.0k
    sgr_finish_mix(&dst, stride, A5_ptrs, B5_ptrs, A3_ptrs, B3_ptrs,
1325
24.0k
                   w, 1, params->sgr.w0, params->sgr.w1
1326
24.0k
                   HIGHBD_TAIL_SUFFIX);
1327
24.0k
    return;
1328
1329
8.65k
vert_1:
1330
    // Copy the last row as padding once
1331
8.65k
    sumsq5_ptrs[4] = sumsq5_ptrs[3];
1332
8.65k
    sum5_ptrs[4] = sum5_ptrs[3];
1333
1334
8.65k
    sumsq3_ptrs[2] = sumsq3_ptrs[1];
1335
8.65k
    sum3_ptrs[2] = sum3_ptrs[1];
1336
1337
8.65k
    sgr_box5_vert(sumsq5_ptrs, sum5_ptrs, A5_ptrs[1], B5_ptrs[1],
1338
8.65k
                  w, params->sgr.s0, BITDEPTH_MAX);
1339
8.65k
    rotate(A5_ptrs, B5_ptrs, 2);
1340
8.65k
    sgr_box3_vert(sumsq3_ptrs, sum3_ptrs, A3_ptrs[3], B3_ptrs[3],
1341
8.65k
                  w, params->sgr.s1, BITDEPTH_MAX);
1342
8.65k
    rotate(A3_ptrs, B3_ptrs, 4);
1343
1344
8.65k
    goto output_1;
1345
15.4k
}
1346
1347
#if HAVE_ASM
1348
#if ARCH_AARCH64 || ARCH_ARM
1349
#include "src/arm/looprestoration.h"
1350
#elif ARCH_LOONGARCH64
1351
#include "src/loongarch/looprestoration.h"
1352
#elif ARCH_PPC64LE
1353
#include "src/ppc/looprestoration.h"
1354
#elif ARCH_X86
1355
#include "src/x86/looprestoration.h"
1356
#endif
1357
#endif
1358
1359
COLD void bitfn(dav1d_loop_restoration_dsp_init)(Dav1dLoopRestorationDSPContext *const c,
1360
                                                 const int bpc)
1361
103k
{
1362
103k
    c->wiener[0] = c->wiener[1] = wiener_c;
1363
103k
    c->sgr[0] = sgr_5x5_c;
1364
103k
    c->sgr[1] = sgr_3x3_c;
1365
103k
    c->sgr[2] = sgr_mix_c;
1366
1367
#if HAVE_ASM
1368
#if ARCH_AARCH64 || ARCH_ARM
1369
    loop_restoration_dsp_init_arm(c, bpc);
1370
#elif ARCH_LOONGARCH64
1371
    loop_restoration_dsp_init_loongarch(c, bpc);
1372
#elif ARCH_PPC64LE
1373
    loop_restoration_dsp_init_ppc(c, bpc);
1374
#elif ARCH_X86
1375
    loop_restoration_dsp_init_x86(c, bpc);
1376
#endif
1377
#endif
1378
103k
}
dav1d_loop_restoration_dsp_init_8bpc
Line
Count
Source
1361
47.1k
{
1362
47.1k
    c->wiener[0] = c->wiener[1] = wiener_c;
1363
47.1k
    c->sgr[0] = sgr_5x5_c;
1364
47.1k
    c->sgr[1] = sgr_3x3_c;
1365
47.1k
    c->sgr[2] = sgr_mix_c;
1366
1367
#if HAVE_ASM
1368
#if ARCH_AARCH64 || ARCH_ARM
1369
    loop_restoration_dsp_init_arm(c, bpc);
1370
#elif ARCH_LOONGARCH64
1371
    loop_restoration_dsp_init_loongarch(c, bpc);
1372
#elif ARCH_PPC64LE
1373
    loop_restoration_dsp_init_ppc(c, bpc);
1374
#elif ARCH_X86
1375
    loop_restoration_dsp_init_x86(c, bpc);
1376
#endif
1377
#endif
1378
47.1k
}
dav1d_loop_restoration_dsp_init_16bpc
Line
Count
Source
1361
56.3k
{
1362
56.3k
    c->wiener[0] = c->wiener[1] = wiener_c;
1363
56.3k
    c->sgr[0] = sgr_5x5_c;
1364
56.3k
    c->sgr[1] = sgr_3x3_c;
1365
56.3k
    c->sgr[2] = sgr_mix_c;
1366
1367
#if HAVE_ASM
1368
#if ARCH_AARCH64 || ARCH_ARM
1369
    loop_restoration_dsp_init_arm(c, bpc);
1370
#elif ARCH_LOONGARCH64
1371
    loop_restoration_dsp_init_loongarch(c, bpc);
1372
#elif ARCH_PPC64LE
1373
    loop_restoration_dsp_init_ppc(c, bpc);
1374
#elif ARCH_X86
1375
    loop_restoration_dsp_init_x86(c, bpc);
1376
#endif
1377
#endif
1378
56.3k
}