xref: /netbsd-src/usr.sbin/tpctl/fb.c (revision ae2cfe2a2af819811b0e023828295e674bc2444f)
1*ae2cfe2aSjmcneill /*	$NetBSD: fb.c,v 1.5 2017/08/27 02:19:08 jmcneill Exp $	*/
2b8ce6e82Stakemura 
3b8ce6e82Stakemura /*-
4b8ce6e82Stakemura  * Copyright (c) 2002 TAKEMRUA Shin
5b8ce6e82Stakemura  * All rights reserved.
6b8ce6e82Stakemura  *
7b8ce6e82Stakemura  * Redistribution and use in source and binary forms, with or without
8b8ce6e82Stakemura  * modification, are permitted provided that the following conditions
9b8ce6e82Stakemura  * are met:
10b8ce6e82Stakemura  * 1. Redistributions of source code must retain the above copyright
11b8ce6e82Stakemura  *    notice, this list of conditions and the following disclaimer.
12b8ce6e82Stakemura  * 2. Redistributions in binary form must reproduce the above copyright
13b8ce6e82Stakemura  *    notice, this list of conditions and the following disclaimer in the
14b8ce6e82Stakemura  *    documentation and/or other materials provided with the distribution.
155d1469bdSmartin  * 3. Neither the name of The NetBSD Foundation nor the names of its
165d1469bdSmartin  *    contributors may be used to endorse or promote products derived
175d1469bdSmartin  *    from this software without specific prior written permission.
18b8ce6e82Stakemura  *
19b8ce6e82Stakemura  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20b8ce6e82Stakemura  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21b8ce6e82Stakemura  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22b8ce6e82Stakemura  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23b8ce6e82Stakemura  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24b8ce6e82Stakemura  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25b8ce6e82Stakemura  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26b8ce6e82Stakemura  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27b8ce6e82Stakemura  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28b8ce6e82Stakemura  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29b8ce6e82Stakemura  * POSSIBILITY OF SUCH DAMAGE.
30b8ce6e82Stakemura  */
31b8ce6e82Stakemura 
3299b1f08dSuwe #include <string.h>
33b8ce6e82Stakemura #include <stdio.h>
34b8ce6e82Stakemura #include <unistd.h>
35b8ce6e82Stakemura #include <stdlib.h>
36b8ce6e82Stakemura #include <sys/ioctl.h>
37b8ce6e82Stakemura #include <sys/fcntl.h>
38b8ce6e82Stakemura #include <sys/mman.h>
39b8ce6e82Stakemura 
40b8ce6e82Stakemura #include "tpctl.h"
41b8ce6e82Stakemura 
42b8ce6e82Stakemura #ifndef lint
43b8ce6e82Stakemura #include <sys/cdefs.h>
44*ae2cfe2aSjmcneill __RCSID("$NetBSD: fb.c,v 1.5 2017/08/27 02:19:08 jmcneill Exp $");
45b8ce6e82Stakemura #endif /* not lint */
46b8ce6e82Stakemura 
47b8ce6e82Stakemura #define INVALID_CACHE -1
48b8ce6e82Stakemura #define ALIGN(a, n)	((typeof(a))(((int)(a) + (n) - 1) / (n) * (n)))
49b8ce6e82Stakemura #define ABS(a)		((a) < 0 ? -(a) : (a))
50b8ce6e82Stakemura #define SWAP(a, b)	do {				\
51b8ce6e82Stakemura 		typeof(a) tmp;				\
52b8ce6e82Stakemura 		tmp = (a); (a) = (b); (b) = tmp;	\
53b8ce6e82Stakemura 	} while(0)
54b8ce6e82Stakemura #define bitsizeof(t)	(sizeof(t) * 8)
55b8ce6e82Stakemura 
56b8ce6e82Stakemura int
fb_dispmode(struct fb * fb,int dispmode)57b8ce6e82Stakemura fb_dispmode(struct fb *fb, int dispmode)
58b8ce6e82Stakemura {
59b8ce6e82Stakemura 
60b8ce6e82Stakemura 	if (fb->dispmode != dispmode) {
61b8ce6e82Stakemura 	    if (ioctl(fb->fd, WSDISPLAYIO_SMODE, &dispmode) < 0)
62b8ce6e82Stakemura 		return (-1);
63b8ce6e82Stakemura 	    fb->dispmode = dispmode;
64b8ce6e82Stakemura 	}
65b8ce6e82Stakemura 
66b8ce6e82Stakemura 	return (0);
67b8ce6e82Stakemura }
68b8ce6e82Stakemura 
69b8ce6e82Stakemura int
fb_init(struct fb * fb,int fd)70b8ce6e82Stakemura fb_init(struct fb *fb, int fd)
71b8ce6e82Stakemura {
72*ae2cfe2aSjmcneill 	struct wsdisplay_fbinfo fbinfo;
73*ae2cfe2aSjmcneill 	u_int linebytes;
74b8ce6e82Stakemura 	int y;
75b8ce6e82Stakemura 	size_t size;
76b8ce6e82Stakemura 
77b8ce6e82Stakemura 	fb->fd = fd;
78b8ce6e82Stakemura 	fb->linecache_y = INVALID_CACHE;
79b8ce6e82Stakemura 	fb->conf.hf_conf_index = HPCFB_CURRENT_CONFIG;
80b8ce6e82Stakemura 	if (ioctl(fb->fd, WSDISPLAYIO_GMODE, &fb->dispmode) < 0)
81b8ce6e82Stakemura 		return (-1);
82*ae2cfe2aSjmcneill 	if (ioctl(fb->fd, HPCFBIO_GCONF, &fb->conf) < 0) {
83*ae2cfe2aSjmcneill 		if (ioctl(fb->fd, WSDISPLAYIO_GINFO, &fbinfo) < 0 ||
84*ae2cfe2aSjmcneill 		    ioctl(fb->fd, WSDISPLAYIO_LINEBYTES, &linebytes) < 0)
85b8ce6e82Stakemura 			return (-1);
86*ae2cfe2aSjmcneill 		memset(&fb->conf, 0, sizeof(fb->conf));
87*ae2cfe2aSjmcneill 		fb->conf.hf_width = fbinfo.width;
88*ae2cfe2aSjmcneill 		fb->conf.hf_height = fbinfo.height;
89*ae2cfe2aSjmcneill 		fb->conf.hf_bytes_per_line = linebytes;
90*ae2cfe2aSjmcneill 		fb->conf.hf_nplanes = 1;
91*ae2cfe2aSjmcneill 		fb->conf.hf_bytes_per_plane = fbinfo.height * linebytes;
92*ae2cfe2aSjmcneill 		fb->conf.hf_pack_width = fbinfo.depth;
93*ae2cfe2aSjmcneill 		fb->conf.hf_pixels_per_pack = 1;
94*ae2cfe2aSjmcneill 		fb->conf.hf_pixel_width = 1;
95*ae2cfe2aSjmcneill 		fb->conf.hf_access_flags = HPCFB_ACCESS_STATIC |
96*ae2cfe2aSjmcneill 		    HPCFB_ACCESS_BYTE | HPCFB_ACCESS_WORD | HPCFB_ACCESS_DWORD;
97*ae2cfe2aSjmcneill 	}
98b8ce6e82Stakemura 
99b8ce6e82Stakemura 	if (fb_dispmode(fb, WSDISPLAYIO_MODE_MAPPED) < 0)
100b8ce6e82Stakemura 		return (-1);
101b8ce6e82Stakemura 
102b8ce6e82Stakemura 	size = (size_t)fb->conf.hf_bytes_per_line * fb->conf.hf_height;
103b8ce6e82Stakemura 	size += fb->conf.hf_offset;
104b8ce6e82Stakemura 	size = ALIGN(size, getpagesize());
105b8ce6e82Stakemura 	fb->baseaddr = mmap(0, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd,0);
106b8ce6e82Stakemura 	if (fb->baseaddr == MAP_FAILED)
107b8ce6e82Stakemura 		return (-1);
108b8ce6e82Stakemura 	fb->baseaddr += fb->conf.hf_offset;
109b8ce6e82Stakemura 
110b8ce6e82Stakemura 	size = ALIGN(fb->conf.hf_bytes_per_line, 16);
111b8ce6e82Stakemura 	fb->linecache = (fb_pixel_t*)malloc(size);
112b8ce6e82Stakemura 	if (fb->linecache == NULL)
113b8ce6e82Stakemura 		return (-1);
114b8ce6e82Stakemura 	fb->workbuf = (fb_pixel_t*)malloc(size);
115b8ce6e82Stakemura 	if (fb->workbuf == NULL)
116b8ce6e82Stakemura 		return (-1);
117b8ce6e82Stakemura 
118b8ce6e82Stakemura 	if (fb->conf.hf_access_flags & HPCFB_ACCESS_REVERSE) {
119b8ce6e82Stakemura 		fb->white = 0;
120b8ce6e82Stakemura 		fb->black = ~0;
121b8ce6e82Stakemura 	} else {
122b8ce6e82Stakemura 		fb->white = ~0;
123b8ce6e82Stakemura 		fb->black = 0;
124b8ce6e82Stakemura 	}
125b8ce6e82Stakemura 
126b8ce6e82Stakemura 	/*
127b8ce6e82Stakemura 	 * clear screen
128b8ce6e82Stakemura 	 */
129b8ce6e82Stakemura 	for (y = 0; y < fb->conf.hf_height; y++) {
130b8ce6e82Stakemura 		fb_getline(fb, y);
131b8ce6e82Stakemura 		memset(fb->linecache, fb->black,
132b8ce6e82Stakemura 		    ALIGN(fb->conf.hf_bytes_per_line, 16));
133b8ce6e82Stakemura 		fb_putline(fb, y);
134b8ce6e82Stakemura 	}
135b8ce6e82Stakemura 
136b8ce6e82Stakemura 	return (0);
137b8ce6e82Stakemura }
138b8ce6e82Stakemura 
139b8ce6e82Stakemura static void
__fb_swap_workbuf(struct fb * fb)140b8ce6e82Stakemura __fb_swap_workbuf(struct fb *fb)
141b8ce6e82Stakemura {
142b8ce6e82Stakemura 	int i, n;
143b8ce6e82Stakemura 
144b8ce6e82Stakemura 	n = ALIGN(fb->conf.hf_bytes_per_line, 16) / sizeof(fb_pixel_t);
145b8ce6e82Stakemura 	if (fb->conf.hf_order_flags & HPCFB_REVORDER_BYTE) {
146b8ce6e82Stakemura 		for (i = 0; i < n; i++)
147b8ce6e82Stakemura 			fb->workbuf[i] =
148b8ce6e82Stakemura 			    ((fb->workbuf[i] << 8) & 0xff00ff00) |
149b8ce6e82Stakemura 			    ((fb->workbuf[i] >> 8) & 0x00ff00ff);
150b8ce6e82Stakemura 	}
151b8ce6e82Stakemura 	if (fb->conf.hf_order_flags & HPCFB_REVORDER_WORD) {
152b8ce6e82Stakemura 		for (i = 0; i < n; i++)
153b8ce6e82Stakemura 			fb->workbuf[i] =
154b8ce6e82Stakemura 			    ((fb->workbuf[i] << 16) & 0xffff0000) |
155b8ce6e82Stakemura 			    ((fb->workbuf[i] >> 16) & 0x0000ffff);
156b8ce6e82Stakemura 	}
157b8ce6e82Stakemura 	if (fb->conf.hf_order_flags & HPCFB_REVORDER_DWORD) {
158b8ce6e82Stakemura 		for (i = 0; i < n; i += 2) {
159b8ce6e82Stakemura 			fb_pixel_t tmp;
160b8ce6e82Stakemura 			tmp = fb->workbuf[i];
161b8ce6e82Stakemura 			fb->workbuf[i] = fb->workbuf[i + 1];
162b8ce6e82Stakemura 			fb->workbuf[i + 1] = tmp;
163b8ce6e82Stakemura 		}
164b8ce6e82Stakemura 	}
165b8ce6e82Stakemura 	if (fb->conf.hf_order_flags & HPCFB_REVORDER_QWORD) {
166b8ce6e82Stakemura 		for (i = 0; i < n; i += 4) {
167b8ce6e82Stakemura 			fb_pixel_t tmp;
168b8ce6e82Stakemura 			tmp = fb->workbuf[i + 0];
169b8ce6e82Stakemura 			fb->workbuf[i + 0] = fb->workbuf[i + 2];
170b8ce6e82Stakemura 			fb->workbuf[i + 2] = tmp;
171b8ce6e82Stakemura 			tmp = fb->workbuf[i + 1];
172b8ce6e82Stakemura 			fb->workbuf[i + 1] = fb->workbuf[i + 3];
173b8ce6e82Stakemura 			fb->workbuf[i + 3] = tmp;
174b8ce6e82Stakemura 		}
175b8ce6e82Stakemura 	}
176b8ce6e82Stakemura }
177b8ce6e82Stakemura 
178b8ce6e82Stakemura static void
__fb_put_pixel(struct fb * fb,fb_pixel_t pixel,int width,int x)179b8ce6e82Stakemura __fb_put_pixel(struct fb *fb, fb_pixel_t pixel, int width, int x)
180b8ce6e82Stakemura {
181b8ce6e82Stakemura 	fb_pixel_t mask = (1 << width) - 1;
182b8ce6e82Stakemura 
183b8ce6e82Stakemura 	x -= (bitsizeof(fb_pixel_t) - width);
184b8ce6e82Stakemura 	if (x < 0) {
185b8ce6e82Stakemura 		pixel <<= -x;
186b8ce6e82Stakemura 		mask <<= -x;
187b8ce6e82Stakemura 		fb->linecache[0] = (fb->linecache[0]&~mask) | (pixel&~mask);
188b8ce6e82Stakemura 	} else {
189b8ce6e82Stakemura 		fb_pixel_t *dst = &fb->linecache[x / bitsizeof(fb_pixel_t)];
190b8ce6e82Stakemura 		x %= bitsizeof(fb_pixel_t);
191b8ce6e82Stakemura 		*dst = (*dst & ~(mask>>x)) | ((pixel>>x) & (mask>>x));
192b8ce6e82Stakemura 		dst++;
193b8ce6e82Stakemura 		if (x == 0)
194b8ce6e82Stakemura 			return;
195b8ce6e82Stakemura 		x = bitsizeof(fb_pixel_t) - x;
196b8ce6e82Stakemura 		*dst = (*dst & ~(mask<<x)) | ((pixel<<x) & (mask<<x));
197b8ce6e82Stakemura 	}
198b8ce6e82Stakemura }
199b8ce6e82Stakemura 
200b8ce6e82Stakemura void
fb_getline(struct fb * fb,int y)201b8ce6e82Stakemura fb_getline(struct fb *fb, int y)
202b8ce6e82Stakemura {
203b8ce6e82Stakemura 	int i, n;
204b8ce6e82Stakemura 	unsigned char *src;
205b8ce6e82Stakemura 	fb_pixel_t *dst;
206b8ce6e82Stakemura 
207b8ce6e82Stakemura 	src = fb->baseaddr + fb->conf.hf_bytes_per_line * y;
208b8ce6e82Stakemura 	dst = fb->workbuf;
209b8ce6e82Stakemura 	n = ALIGN(fb->conf.hf_bytes_per_line, 16) / sizeof(fb_pixel_t);
210b8ce6e82Stakemura 	for (i = 0; i < n; i++) {
211b8ce6e82Stakemura 		*dst++ = ((fb_pixel_t)src[0] << 24) |
212b8ce6e82Stakemura 		    ((fb_pixel_t)src[1] << 16) |
213b8ce6e82Stakemura 		    ((fb_pixel_t)src[2] << 8) |
214b8ce6e82Stakemura 		    ((fb_pixel_t)src[3] << 0);
215b8ce6e82Stakemura 		src += 4;
216b8ce6e82Stakemura 	}
217b8ce6e82Stakemura 
218b8ce6e82Stakemura 	__fb_swap_workbuf(fb);
219b8ce6e82Stakemura 	memcpy(fb->linecache, fb->workbuf, n * sizeof(fb_pixel_t));
220b8ce6e82Stakemura }
221b8ce6e82Stakemura 
222b8ce6e82Stakemura void
fb_putline(struct fb * fb,int y)223b8ce6e82Stakemura fb_putline(struct fb *fb, int y)
224b8ce6e82Stakemura {
225b8ce6e82Stakemura 	int i, n;
226b8ce6e82Stakemura 	unsigned char *dst;
227b8ce6e82Stakemura 	fb_pixel_t *src;
228b8ce6e82Stakemura 
229b8ce6e82Stakemura 	src = fb->workbuf;
230b8ce6e82Stakemura 	dst = fb->baseaddr + fb->conf.hf_bytes_per_line * y;
231b8ce6e82Stakemura 	n = ALIGN(fb->conf.hf_bytes_per_line, 16) / sizeof(fb_pixel_t);
232b8ce6e82Stakemura 	memcpy(fb->workbuf, fb->linecache, n * sizeof(fb_pixel_t));
233b8ce6e82Stakemura 	__fb_swap_workbuf(fb);
234b8ce6e82Stakemura 	for (i = 0; i < n; i++) {
235b8ce6e82Stakemura 		*dst++ = (*src >> 24) & 0xff;
236b8ce6e82Stakemura 		*dst++ = (*src >> 16) & 0xff;
237b8ce6e82Stakemura 		*dst++ = (*src >>  8) & 0xff;
238b8ce6e82Stakemura 		*dst++ = (*src >>  0) & 0xff;
239b8ce6e82Stakemura 		src++;
240b8ce6e82Stakemura 	}
241b8ce6e82Stakemura }
242b8ce6e82Stakemura 
243b8ce6e82Stakemura void
fb_fetchline(struct fb * fb,int y)244b8ce6e82Stakemura fb_fetchline(struct fb *fb, int y)
245b8ce6e82Stakemura {
246b8ce6e82Stakemura 	if (fb->linecache_y == y)
247b8ce6e82Stakemura 		return;
248b8ce6e82Stakemura 	fb_getline(fb, y);
249b8ce6e82Stakemura 	fb->linecache_y = y;
250b8ce6e82Stakemura }
251b8ce6e82Stakemura 
252b8ce6e82Stakemura void
fb_flush(struct fb * fb)253b8ce6e82Stakemura fb_flush(struct fb *fb)
254b8ce6e82Stakemura {
255b8ce6e82Stakemura 	if (fb->linecache_y != INVALID_CACHE)
256b8ce6e82Stakemura 		fb_putline(fb, fb->linecache_y);
257b8ce6e82Stakemura }
258b8ce6e82Stakemura 
259b8ce6e82Stakemura void
fb_drawpixel(struct fb * fb,int x,int y,fb_pixel_t pixel)260b8ce6e82Stakemura fb_drawpixel(struct fb *fb, int x, int y, fb_pixel_t pixel)
261b8ce6e82Stakemura {
262b8ce6e82Stakemura 	int pack;
263b8ce6e82Stakemura 
264b8ce6e82Stakemura 	if (fb->conf.hf_access_flags & HPCFB_ACCESS_Y_TO_X)
265b8ce6e82Stakemura 		SWAP(x, y);
266b8ce6e82Stakemura 	if (fb->conf.hf_access_flags & HPCFB_ACCESS_R_TO_L)
267b8ce6e82Stakemura 		x = fb->conf.hf_width - x - 1;
268b8ce6e82Stakemura 	if (fb->conf.hf_access_flags & HPCFB_ACCESS_B_TO_T)
269b8ce6e82Stakemura 		y = fb->conf.hf_height - y - 1;
270b8ce6e82Stakemura 
271b8ce6e82Stakemura 	if (x < 0 || y < 0 || fb->conf.hf_width <= x || fb->conf.hf_height < y)
272b8ce6e82Stakemura 		return;
273b8ce6e82Stakemura 
274b8ce6e82Stakemura 	pack = x / fb->conf.hf_pixels_per_pack;
275b8ce6e82Stakemura 	x %= fb->conf.hf_pixels_per_pack;
276b8ce6e82Stakemura 	if (fb->conf.hf_access_flags & HPCFB_ACCESS_LSB_TO_MSB)
277b8ce6e82Stakemura 		x = fb->conf.hf_pixels_per_pack - x - 1;
278b8ce6e82Stakemura 	x *= fb->conf.hf_pixel_width;
279b8ce6e82Stakemura 	if (fb->conf.hf_access_flags & HPCFB_ACCESS_PACK_BLANK)
280b8ce6e82Stakemura 		x += (fb->conf.hf_pack_width -
281b8ce6e82Stakemura 		    fb->conf.hf_pixel_width * fb->conf.hf_pixels_per_pack);
282b8ce6e82Stakemura 	x += pack * fb->conf.hf_pack_width;
283b8ce6e82Stakemura 
284b8ce6e82Stakemura 	if (fb->linecache_y != y) {
285b8ce6e82Stakemura 		fb_flush(fb);
286b8ce6e82Stakemura 		fb_fetchline(fb, y);
287b8ce6e82Stakemura 	}
288b8ce6e82Stakemura 
289b8ce6e82Stakemura 	__fb_put_pixel(fb, pixel, fb->conf.hf_pixel_width, x);
290b8ce6e82Stakemura }
291b8ce6e82Stakemura 
292b8ce6e82Stakemura void
fb_drawline(struct fb * fb,int x0,int y0,int x1,int y1,fb_pixel_t pixel)293b8ce6e82Stakemura fb_drawline(struct fb *fb, int x0, int y0, int x1, int y1, fb_pixel_t pixel)
294b8ce6e82Stakemura {
295b8ce6e82Stakemura 	int i, dx, dy, d, incdec;
296b8ce6e82Stakemura 
297b8ce6e82Stakemura 	dx = ABS(x1 - x0);
298b8ce6e82Stakemura 	dy = ABS(y1 - y0);
299b8ce6e82Stakemura 	if (dx < dy) {
300b8ce6e82Stakemura 		if (y1 < y0) {
301b8ce6e82Stakemura 			SWAP(x0, x1);
302b8ce6e82Stakemura 			SWAP(y0, y1);
303b8ce6e82Stakemura 		}
304b8ce6e82Stakemura 		if (x0 < x1)
305b8ce6e82Stakemura 			incdec = 1;
306b8ce6e82Stakemura 		else
307b8ce6e82Stakemura 			incdec = -1;
308b8ce6e82Stakemura 		d = -dy;
309b8ce6e82Stakemura 		dx *= 2;
310b8ce6e82Stakemura 		dy *= 2;
311b8ce6e82Stakemura 		for (i = y0; i <= y1; i++) {
312b8ce6e82Stakemura 			fb_drawpixel(fb, x0, i, pixel);
313b8ce6e82Stakemura 			d += dx;
314b8ce6e82Stakemura 			if (0 <= d) {
315b8ce6e82Stakemura 				d -= dy;
316b8ce6e82Stakemura 				x0 += incdec;
317b8ce6e82Stakemura 			}
318b8ce6e82Stakemura 		}
319b8ce6e82Stakemura 	} else {
320b8ce6e82Stakemura 		if (x1 < x0) {
321b8ce6e82Stakemura 			SWAP(x0, x1);
322b8ce6e82Stakemura 			SWAP(y0, y1);
323b8ce6e82Stakemura 		}
324b8ce6e82Stakemura 		if (y0 < y1)
325b8ce6e82Stakemura 			incdec = 1;
326b8ce6e82Stakemura 		else
327b8ce6e82Stakemura 			incdec = -1;
328b8ce6e82Stakemura 		d = -dx;
329b8ce6e82Stakemura 		dx *= 2;
330b8ce6e82Stakemura 		dy *= 2;
331b8ce6e82Stakemura 		for (i = x0; i <= x1; i++) {
332b8ce6e82Stakemura 			fb_drawpixel(fb, i, y0, pixel);
333b8ce6e82Stakemura 			d += dy;
334b8ce6e82Stakemura 			if (0 <= d) {
335b8ce6e82Stakemura 				d -= dx;
336b8ce6e82Stakemura 				y0 += incdec;
337b8ce6e82Stakemura 			}
338b8ce6e82Stakemura 		}
339b8ce6e82Stakemura 	}
340b8ce6e82Stakemura }
341