File Index
Files and directories
Sign in
FILE

fb_draw.h

File preview with syntax highlighting.

linux-6.19.14/drivers/video/fbdev/core/fb_draw.h C
  1/* SPDX-License-Identifier: GPL-2.0
  2 *
  3 *  Various common functions used by the framebuffer drawing code
  4 *
  5 *	Copyright (C)  2025 Zsolt Kajtar (soci@c64.rulez.org)
  6 */
  7#ifndef _FB_DRAW_H
  8#define _FB_DRAW_H
  9
 10/* swap bytes in a long, independent of word size */
 11#define swab_long _swab_long(BITS_PER_LONG)
 12#define _swab_long(x) __swab_long(x)
 13#define __swab_long(x) swab##x
 14
 15/* move the address pointer by the number of words */
 16static inline void fb_address_move_long(struct fb_address *adr, int offset)
 17{
 18	adr->address += offset * (BITS_PER_LONG / BITS_PER_BYTE);
 19}
 20
 21/* move the address pointer forward with the number of bits */
 22static inline void fb_address_forward(struct fb_address *adr, unsigned int offset)
 23{
 24	unsigned int bits = (unsigned int)adr->bits + offset;
 25
 26	adr->bits = bits & (BITS_PER_LONG - 1u);
 27	adr->address += (bits & ~(BITS_PER_LONG - 1u)) / BITS_PER_BYTE;
 28}
 29
 30/* move the address pointer backwards with the number of bits */
 31static inline void fb_address_backward(struct fb_address *adr, unsigned int offset)
 32{
 33	int bits = adr->bits - (int)offset;
 34
 35	adr->bits = bits & (BITS_PER_LONG - 1);
 36	if (bits < 0)
 37		adr->address -= (adr->bits - bits) / BITS_PER_BYTE;
 38	else
 39		adr->address += (bits - adr->bits) / BITS_PER_BYTE;
 40}
 41
 42/* compose pixels based on mask */
 43static inline unsigned long fb_comp(unsigned long set, unsigned long unset, unsigned long mask)
 44{
 45	return ((set ^ unset) & mask) ^ unset;
 46}
 47
 48/* framebuffer read-modify-write access for replacing bits in the mask */
 49static inline void fb_modify_offset(unsigned long val, unsigned long mask,
 50				    int offset, const struct fb_address *dst)
 51{
 52	fb_write_offset(fb_comp(val, fb_read_offset(offset, dst), mask), offset, dst);
 53}
 54
 55/*
 56 * get current palette, if applicable for visual
 57 *
 58 * The pseudo color table entries (and colors) are right justified and in the
 59 * same byte order as it's expected to be placed into a native ordered
 60 * framebuffer memory. What that means:
 61 *
 62 * Expected bytes in framebuffer memory (in native order):
 63 * RR GG BB RR GG BB RR GG BB ...
 64 *
 65 * Pseudo palette entry on little endian arch:
 66 * RR | GG << 8 | BB << 16
 67 *
 68 * Pseudo palette entry on a big endian arch:
 69 * RR << 16 | GG << 8 | BB
 70 */
 71static inline const u32 *fb_palette(struct fb_info *info)
 72{
 73	return (info->fix.visual == FB_VISUAL_TRUECOLOR ||
 74		info->fix.visual == FB_VISUAL_DIRECTCOLOR) ? info->pseudo_palette : NULL;
 75}
 76
 77/* move pixels right on screen when framebuffer is in native order */
 78static inline unsigned long fb_right(unsigned long value, int index)
 79{
 80#ifdef __LITTLE_ENDIAN
 81	return value << index;
 82#else
 83	return value >> index;
 84#endif
 85}
 86
 87/* move pixels left on screen when framebuffer is in native order */
 88static inline unsigned long fb_left(unsigned long value, int index)
 89{
 90#ifdef __LITTLE_ENDIAN
 91	return value >> index;
 92#else
 93	return value << index;
 94#endif
 95}
 96
 97/* reversal options */
 98struct fb_reverse {
 99	bool byte, pixel;
100};
101
102/* reverse bits of each byte in a long */
103static inline unsigned long fb_reverse_bits_long(unsigned long val)
104{
105#if defined(CONFIG_HAVE_ARCH_BITREVERSE) && BITS_PER_LONG == 32
106	return bitrev8x4(val);
107#else
108	val = fb_comp(val >> 1, val << 1, ~0UL / 3);
109	val = fb_comp(val >> 2, val << 2, ~0UL / 5);
110	return fb_comp(val >> 4, val << 4, ~0UL / 17);
111#endif
112}
113
114/* apply byte and bit reversals as necessary */
115static inline unsigned long fb_reverse_long(unsigned long val,
116					    struct fb_reverse reverse)
117{
118	if (reverse.pixel)
119		val = fb_reverse_bits_long(val);
120	return reverse.byte ? swab_long(val) : val;
121}
122
123/* calculate a pixel mask for the given reversal */
124static inline unsigned long fb_pixel_mask(int index, struct fb_reverse reverse)
125{
126#ifdef FB_REV_PIXELS_IN_BYTE
127	if (reverse.byte)
128		return reverse.pixel ? fb_left(~0UL, index) : swab_long(fb_right(~0UL, index));
129	else
130		return reverse.pixel ? swab_long(fb_left(~0UL, index)) : fb_right(~0UL, index);
131#else
132	return reverse.byte ? swab_long(fb_right(~0UL, index)) : fb_right(~0UL, index);
133#endif
134}
135
136
137/*
138 * initialise reversals based on info
139 *
140 * Normally the first byte is the low byte on little endian and in the high
141 * on big endian. If it's the other way around then that's reverse byte order.
142 *
143 * Normally the first pixel is the LSB on little endian and the MSB on big
144 * endian. If that's not the case that's reverse pixel order.
145 */
146static inline struct fb_reverse fb_reverse_init(struct fb_info *info)
147{
148	struct fb_reverse reverse;
149#ifdef __LITTLE_ENDIAN
150	reverse.byte = fb_be_math(info) != 0;
151#else
152	reverse.byte = fb_be_math(info) == 0;
153#endif
154#ifdef FB_REV_PIXELS_IN_BYTE
155	reverse.pixel = info->var.bits_per_pixel < BITS_PER_BYTE
156		&& (info->var.nonstd & FB_NONSTD_REV_PIX_IN_B);
157#else
158	reverse.pixel = false;
159#endif
160	return reverse;
161}
162
163#endif /* FB_DRAW_H */
~/ Read-only file preview.