blit
Loading...
Searching...
No Matches
phase_align.c
Go to the documentation of this file.
1/*
2 * SPDX-FileCopyrightText: 2025, Roy Ratcliffe, Northumberland, United Kingdom
3 * SPDX-License-Identifier: MIT
4 */
12#include <blit/phase_align.h>
13
14/*
15 * The pre-fetch functions prepare the phase alignment structure for the next byte
16 * fetch. The fetch functions retrieve the next byte from the phase alignment
17 * structure, applying the appropriate shift based on the alignment.
18 */
19static void prefetch(struct blit_phase_align *align);
20static void prefetch_left_shift(struct blit_phase_align *align);
21
22/*
23 * MISRA-C compliance for rule 8.4: static functions should be declared before
24 * use. The functions `fetch_left_shift`, `fetch`, and `fetch_right_shift` are
25 * declared before they are defined to ensure that they can be used within the
26 * `phase_align_start` and `phase_align_fetch` functions without any issues.
27 * This is necessary to avoid implicit function declarations, which can lead to
28 * undefined behavior and is against the C11 standard.
29 */
30static blit_scanline_t fetch_left_shift(struct blit_phase_align *align);
31static blit_scanline_t fetch(struct blit_phase_align *align);
32static blit_scanline_t fetch_right_shift(struct blit_phase_align *align);
33
34/*
35 * Decide how to fetch the source bits. There are three phase-align functions to
36 * choose from, based on how the bits are out of phase. The destination
37 * alignment is x & 7, i.e. how many bits from the left side of the byte.
38 * Expression x_store & 7 gives the source alignment. The sign and magnitude of
39 * the difference between the alignments determines the direction and amount of
40 * shift.
41 *
42 * Note that only the least significant three bits of x are used since the
43 * output is always a byte (8 bits). The shift value is calculated based on the
44 * difference between the destination x and the source x_store. The output
45 * stream appears as a sequence of bytes returned by the phase_align_fetch
46 * function, where each byte is shifted according to the specified shift value.
47 */
48void blit_phase_align_start(struct blit_phase_align *align, int x, int x_store,
49 const blit_scanline_t *store) {
50 align->store = store + (x_store >> 3);
51 int shift = (x & 7) - (x_store & 7);
52 if (shift < 0) {
53 align->prefetch = &prefetch_left_shift;
54 align->fetch = &fetch_left_shift;
55 align->shift = -shift;
56 align->carry = *align->store;
57 } else if (shift == 0) {
58 align->prefetch = &prefetch;
59 align->fetch = &fetch;
60 /*
61 * Shift and carry are not used when there is no shift.
62 * Be tidy and set them to zero.
63 */
64 align->shift = 0;
65 align->carry = 0x00U;
66 } else {
67 /*
68 * Carry starts off as undefined for right shifts. Make it zero so that
69 * the first byte fetched does not have any undefined overflow from the
70 * previous non-byte.
71 */
72 align->prefetch = &prefetch;
73 align->fetch = &fetch_right_shift;
74 align->shift = shift;
75 align->carry = 0x00U;
76 }
77}
78
80 (*align->prefetch)(align);
81}
82
84 return (*align->fetch)(align);
85}
86
87static void prefetch(struct blit_phase_align *align) { (void)align; }
88
89static void prefetch_left_shift(struct blit_phase_align *align) {
90 align->carry = *align->store;
91}
92
99static blit_scanline_t fetch_left_shift(struct blit_phase_align *align) {
100 const blit_scanline_t lo = *++align->store; /* pre-increment */
101 const blit_scanline_t hi = align->carry; /* carry is the previous value */
102 align->carry = lo; /* store the current value as carry for the next call */
103 return (hi << align->shift) | (lo >> (8 - align->shift));
104}
105
111static blit_scanline_t fetch(struct blit_phase_align *align) {
112 return *align->store++;
113}
114
121static blit_scanline_t fetch_right_shift(struct blit_phase_align *align) {
122 const uint8_t lo = *align->store++; /* post-increment */
123 const uint8_t hi = align->carry; /* carry is the previous value */
124 align->carry = lo; /* store the current value as carry for the next call */
125 return (hi << (8 - align->shift)) | (lo >> align->shift);
126}
void blit_phase_align_prefetch(struct blit_phase_align *align)
Prefetches the next byte into the alignment structure.
Definition phase_align.c:79
void blit_phase_align_start(struct blit_phase_align *align, int x, int x_store, const blit_scanline_t *store)
Initialises the phase alignment structure.
Definition phase_align.c:48
blit_scanline_t blit_phase_align_fetch(struct blit_phase_align *align)
Fetches the next byte from the phase alignment structure.
Definition phase_align.c:83
Phase alignment for 8-bit bytes.
uint8_t blit_scanline_t
Type definition for a scanline element.
Definition scan.h:24
Phase alignment structure.
Definition phase_align.h:32
blit_scanline_t(* fetch)(struct blit_phase_align *align)
Fetch the next byte with appropriate shifting.
Definition phase_align.h:40
void(* prefetch)(struct blit_phase_align *align)
Prefetch the next byte into the alignment structure.
Definition phase_align.h:36
const blit_scanline_t * store
Pointer to the data being processed.
Definition phase_align.h:44
blit_scanline_t carry
Overflow from the previous byte fetch.
Definition phase_align.h:52
int shift
Number of bits to shift the data.
Definition phase_align.h:48