1 /* $NetBSD: fb.c,v 1.2 2003/07/08 23:33:50 uwe Exp $ */
4 * Copyright (c) 2002 TAKEMRUA Shin
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of The NetBSD Foundation nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
36 #include <sys/ioctl.h>
37 #include <sys/fcntl.h>
43 #include <sys/cdefs.h>
44 __RCSID("$NetBSD: fb.c,v 1.2 2003/07/08 23:33:50 uwe Exp $");
47 #define INVALID_CACHE -1
48 #define ALIGN(a, n) ((typeof(a))(((int)(a) + (n) - 1) / (n) * (n)))
49 #define ABS(a) ((a) < 0 ? -(a) : (a))
50 #define SWAP(a, b) do { \
52 tmp = (a); (a) = (b); (b) = tmp; \
54 #define bitsizeof(t) (sizeof(t) * 8)
57 fb_dispmode(struct fb
*fb
, int dispmode
)
60 if (fb
->dispmode
!= dispmode
) {
61 if (ioctl(fb
->fd
, WSDISPLAYIO_SMODE
, &dispmode
) < 0)
63 fb
->dispmode
= dispmode
;
70 fb_init(struct fb
*fb
, int fd
)
76 fb
->linecache_y
= INVALID_CACHE
;
77 fb
->conf
.hf_conf_index
= HPCFB_CURRENT_CONFIG
;
78 if (ioctl(fb
->fd
, WSDISPLAYIO_GMODE
, &fb
->dispmode
) < 0)
80 if (ioctl(fb
->fd
, HPCFBIO_GCONF
, &fb
->conf
) < 0)
83 if (fb_dispmode(fb
, WSDISPLAYIO_MODE_MAPPED
) < 0)
86 size
= (size_t)fb
->conf
.hf_bytes_per_line
* fb
->conf
.hf_height
;
87 size
+= fb
->conf
.hf_offset
;
88 size
= ALIGN(size
, getpagesize());
89 fb
->baseaddr
= mmap(0, size
, PROT_READ
| PROT_WRITE
, MAP_SHARED
, fd
,0);
90 if (fb
->baseaddr
== MAP_FAILED
)
92 fb
->baseaddr
+= fb
->conf
.hf_offset
;
94 size
= ALIGN(fb
->conf
.hf_bytes_per_line
, 16);
95 fb
->linecache
= (fb_pixel_t
*)malloc(size
);
96 if (fb
->linecache
== NULL
)
98 fb
->workbuf
= (fb_pixel_t
*)malloc(size
);
99 if (fb
->workbuf
== NULL
)
102 if (fb
->conf
.hf_access_flags
& HPCFB_ACCESS_REVERSE
) {
113 for (y
= 0; y
< fb
->conf
.hf_height
; y
++) {
115 memset(fb
->linecache
, fb
->black
,
116 ALIGN(fb
->conf
.hf_bytes_per_line
, 16));
124 __fb_swap_workbuf(struct fb
*fb
)
128 n
= ALIGN(fb
->conf
.hf_bytes_per_line
, 16) / sizeof(fb_pixel_t
);
129 if (fb
->conf
.hf_order_flags
& HPCFB_REVORDER_BYTE
) {
130 for (i
= 0; i
< n
; i
++)
132 ((fb
->workbuf
[i
] << 8) & 0xff00ff00) |
133 ((fb
->workbuf
[i
] >> 8) & 0x00ff00ff);
135 if (fb
->conf
.hf_order_flags
& HPCFB_REVORDER_WORD
) {
136 for (i
= 0; i
< n
; i
++)
138 ((fb
->workbuf
[i
] << 16) & 0xffff0000) |
139 ((fb
->workbuf
[i
] >> 16) & 0x0000ffff);
141 if (fb
->conf
.hf_order_flags
& HPCFB_REVORDER_DWORD
) {
142 for (i
= 0; i
< n
; i
+= 2) {
144 tmp
= fb
->workbuf
[i
];
145 fb
->workbuf
[i
] = fb
->workbuf
[i
+ 1];
146 fb
->workbuf
[i
+ 1] = tmp
;
149 if (fb
->conf
.hf_order_flags
& HPCFB_REVORDER_QWORD
) {
150 for (i
= 0; i
< n
; i
+= 4) {
152 tmp
= fb
->workbuf
[i
+ 0];
153 fb
->workbuf
[i
+ 0] = fb
->workbuf
[i
+ 2];
154 fb
->workbuf
[i
+ 2] = tmp
;
155 tmp
= fb
->workbuf
[i
+ 1];
156 fb
->workbuf
[i
+ 1] = fb
->workbuf
[i
+ 3];
157 fb
->workbuf
[i
+ 3] = tmp
;
163 __fb_put_pixel(struct fb
*fb
, fb_pixel_t pixel
, int width
, int x
)
165 fb_pixel_t mask
= (1 << width
) - 1;
167 x
-= (bitsizeof(fb_pixel_t
) - width
);
171 fb
->linecache
[0] = (fb
->linecache
[0]&~mask
) | (pixel
&~mask
);
173 fb_pixel_t
*dst
= &fb
->linecache
[x
/ bitsizeof(fb_pixel_t
)];
174 x
%= bitsizeof(fb_pixel_t
);
175 *dst
= (*dst
& ~(mask
>>x
)) | ((pixel
>>x
) & (mask
>>x
));
179 x
= bitsizeof(fb_pixel_t
) - x
;
180 *dst
= (*dst
& ~(mask
<<x
)) | ((pixel
<<x
) & (mask
<<x
));
185 fb_getline(struct fb
*fb
, int y
)
191 src
= fb
->baseaddr
+ fb
->conf
.hf_bytes_per_line
* y
;
193 n
= ALIGN(fb
->conf
.hf_bytes_per_line
, 16) / sizeof(fb_pixel_t
);
194 for (i
= 0; i
< n
; i
++) {
195 *dst
++ = ((fb_pixel_t
)src
[0] << 24) |
196 ((fb_pixel_t
)src
[1] << 16) |
197 ((fb_pixel_t
)src
[2] << 8) |
198 ((fb_pixel_t
)src
[3] << 0);
202 __fb_swap_workbuf(fb
);
203 memcpy(fb
->linecache
, fb
->workbuf
, n
* sizeof(fb_pixel_t
));
207 fb_putline(struct fb
*fb
, int y
)
214 dst
= fb
->baseaddr
+ fb
->conf
.hf_bytes_per_line
* y
;
215 n
= ALIGN(fb
->conf
.hf_bytes_per_line
, 16) / sizeof(fb_pixel_t
);
216 memcpy(fb
->workbuf
, fb
->linecache
, n
* sizeof(fb_pixel_t
));
217 __fb_swap_workbuf(fb
);
218 for (i
= 0; i
< n
; i
++) {
219 *dst
++ = (*src
>> 24) & 0xff;
220 *dst
++ = (*src
>> 16) & 0xff;
221 *dst
++ = (*src
>> 8) & 0xff;
222 *dst
++ = (*src
>> 0) & 0xff;
228 fb_fetchline(struct fb
*fb
, int y
)
230 if (fb
->linecache_y
== y
)
237 fb_flush(struct fb
*fb
)
239 if (fb
->linecache_y
!= INVALID_CACHE
)
240 fb_putline(fb
, fb
->linecache_y
);
244 fb_drawpixel(struct fb
*fb
, int x
, int y
, fb_pixel_t pixel
)
248 if (fb
->conf
.hf_access_flags
& HPCFB_ACCESS_Y_TO_X
)
250 if (fb
->conf
.hf_access_flags
& HPCFB_ACCESS_R_TO_L
)
251 x
= fb
->conf
.hf_width
- x
- 1;
252 if (fb
->conf
.hf_access_flags
& HPCFB_ACCESS_B_TO_T
)
253 y
= fb
->conf
.hf_height
- y
- 1;
255 if (x
< 0 || y
< 0 || fb
->conf
.hf_width
<= x
|| fb
->conf
.hf_height
< y
)
258 pack
= x
/ fb
->conf
.hf_pixels_per_pack
;
259 x
%= fb
->conf
.hf_pixels_per_pack
;
260 if (fb
->conf
.hf_access_flags
& HPCFB_ACCESS_LSB_TO_MSB
)
261 x
= fb
->conf
.hf_pixels_per_pack
- x
- 1;
262 x
*= fb
->conf
.hf_pixel_width
;
263 if (fb
->conf
.hf_access_flags
& HPCFB_ACCESS_PACK_BLANK
)
264 x
+= (fb
->conf
.hf_pack_width
-
265 fb
->conf
.hf_pixel_width
* fb
->conf
.hf_pixels_per_pack
);
266 x
+= pack
* fb
->conf
.hf_pack_width
;
268 if (fb
->linecache_y
!= y
) {
273 __fb_put_pixel(fb
, pixel
, fb
->conf
.hf_pixel_width
, x
);
277 fb_drawline(struct fb
*fb
, int x0
, int y0
, int x1
, int y1
, fb_pixel_t pixel
)
279 int i
, dx
, dy
, d
, incdec
;
295 for (i
= y0
; i
<= y1
; i
++) {
296 fb_drawpixel(fb
, x0
, i
, pixel
);
315 for (i
= x0
; i
<= x1
; i
++) {
316 fb_drawpixel(fb
, i
, y0
, pixel
);