]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/dev/vt/hw/fb/vt_fb.c
MFC @ r259205 in preparation for some SVM updates. (for real this time)
[FreeBSD/FreeBSD.git] / sys / dev / vt / hw / fb / vt_fb.c
1 /*-
2  * Copyright (c) 2013 The FreeBSD Foundation
3  * All rights reserved.
4  *
5  * This software was developed by Aleksandr Rybalko under sponsorship from the
6  * FreeBSD Foundation.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27  * SUCH DAMAGE.
28  *
29  * $FreeBSD$
30  */
31
32 #include <sys/cdefs.h>
33 __FBSDID("$FreeBSD$");
34
35 #include <sys/param.h>
36 #include <sys/systm.h>
37 #include <sys/malloc.h>
38 #include <sys/queue.h>
39 #include <sys/fbio.h>
40 #include <dev/vt/vt.h>
41 #include <dev/vt/hw/fb/vt_fb.h>
42 #include <dev/vt/colors/vt_termcolors.h>
43
44 static struct vt_driver vt_fb_driver = {
45         .vd_init = vt_fb_init,
46         .vd_blank = vt_fb_blank,
47         .vd_bitbltchr = vt_fb_bitbltchr,
48         .vd_postswitch = vt_fb_postswitch,
49         .vd_priority = VD_PRIORITY_GENERIC+10,
50 };
51
52 void
53 vt_fb_blank(struct vt_device *vd, term_color_t color)
54 {
55         struct fb_info *info;
56         uint32_t c;
57         u_int o;
58
59         info = vd->vd_softc;
60         c = info->fb_cmap[color];
61
62         switch (FBTYPE_GET_BYTESPP(info)) {
63         case 1:
64                 for (o = 0; o < info->fb_stride; o++)
65                         info->wr1(info, o, c);
66                 break;
67         case 2:
68                 for (o = 0; o < info->fb_stride; o += 2)
69                         info->wr2(info, o, c);
70                 break;
71         case 3:
72                 /* line 0 */
73                 for (o = 0; o < info->fb_stride; o += 3) {
74                         info->wr1(info, o, (c >> 16) & 0xff);
75                         info->wr1(info, o + 1, (c >> 8) & 0xff);
76                         info->wr1(info, o + 2, c & 0xff);
77                 }
78                 break;
79         case 4:
80                 for (o = 0; o < info->fb_stride; o += 4)
81                         info->wr4(info, o, c);
82                 break;
83         default:
84                 /* panic? */
85                 return;
86         }
87         /* Copy line0 to all other lines. */
88         /* XXX will copy with borders. */
89         for (o = info->fb_stride; o < info->fb_size; o += info->fb_stride) {
90                 info->copy(info, o, 0, info->fb_stride);
91         }
92 }
93
94 void
95 vt_fb_bitbltchr(struct vt_device *vd, const uint8_t *src, const uint8_t *mask,
96     int bpl, vt_axis_t top, vt_axis_t left, unsigned int width,
97     unsigned int height, term_color_t fg, term_color_t bg)
98 {
99         struct fb_info *info;
100         uint32_t fgc, bgc, cc, o;
101         int c, l, bpp;
102         u_long line;
103         uint8_t b, m;
104         const uint8_t *ch;
105
106         info = vd->vd_softc;
107         bpp = FBTYPE_GET_BYTESPP(info);
108         fgc = info->fb_cmap[fg];
109         bgc = info->fb_cmap[bg];
110         b = m = 0;
111         if (bpl == 0)
112                 bpl = (width + 7) >> 3; /* Bytes per sorce line. */
113
114         /* Don't try to put off screen pixels */
115         if (((left + width) > info->fb_width) || ((top + height) >
116             info->fb_height))
117                 return;
118
119         line = (info->fb_stride * top) + (left * bpp);
120         for (l = 0; l < height; l++) {
121                 ch = src;
122                 for (c = 0; c < width; c++) {
123                         if (c % 8 == 0)
124                                 b = *ch++;
125                         else
126                                 b <<= 1;
127                         if (mask != NULL) {
128                                 if (c % 8 == 0)
129                                         m = *mask++;
130                                 else
131                                         m <<= 1;
132                                 /* Skip pixel write, if mask has no bit set. */
133                                 if ((m & 0x80) == 0)
134                                         continue;
135                         }
136                         o = line + (c * bpp);
137                         cc = b & 0x80 ? fgc : bgc;
138
139                         switch(bpp) {
140                         case 1:
141                                 info->wr1(info, o, cc);
142                                 break;
143                         case 2:
144                                 info->wr2(info, o, cc);
145                                 break;
146                         case 3:
147                                 /* Packed mode, so unaligned. Byte access. */
148                                 info->wr1(info, o, (cc >> 16) & 0xff);
149                                 info->wr1(info, o + 1, (cc >> 8) & 0xff);
150                                 info->wr1(info, o + 2, cc & 0xff);
151                                 break;
152                         case 4:
153                                 info->wr4(info, o, cc);
154                                 break;
155                         default:
156                                 /* panic? */
157                                 break;
158                         }
159                 }
160                 line += info->fb_stride;
161                 src += bpl;
162         }
163 }
164
165 void
166 vt_fb_postswitch(struct vt_device *vd)
167 {
168         struct fb_info *info;
169
170         info = vd->vd_softc;
171
172         if (info->enter != NULL)
173                 info->enter(info->fb_priv);
174 }
175
176 static int
177 vt_fb_init_cmap(uint32_t *cmap, int depth)
178 {
179
180         switch (depth) {
181         case 8:
182                 return (vt_generate_vga_palette(cmap, COLOR_FORMAT_RGB,
183                     0x7, 5, 0x7, 2, 0x3, 0));
184         case 15:
185                 return (vt_generate_vga_palette(cmap, COLOR_FORMAT_RGB,
186                     0x1f, 10, 0x1f, 5, 0x1f, 0));
187         case 16:
188                 return (vt_generate_vga_palette(cmap, COLOR_FORMAT_RGB,
189                     0x1f, 11, 0x3f, 5, 0x1f, 0));
190         case 24:
191         case 32: /* Ignore alpha. */
192                 return (vt_generate_vga_palette(cmap, COLOR_FORMAT_RGB,
193                     0xff, 0, 0xff, 8, 0xff, 16));
194         default:
195                 return (1);
196         }
197 }
198
199 int
200 vt_fb_init(struct vt_device *vd)
201 {
202         struct fb_info *info;
203         int err;
204
205         info = vd->vd_softc;
206         vd->vd_height = info->fb_height;
207         vd->vd_width = info->fb_width;
208
209         if (info->fb_cmsize <= 0) {
210                 err = vt_fb_init_cmap(info->fb_cmap, FBTYPE_GET_BPP(info));
211                 if (err)
212                         return (CN_DEAD);
213                 info->fb_cmsize = 16;
214         }
215
216         /* Clear the screen. */
217         vt_fb_blank(vd, TC_BLACK);
218
219         /* Wakeup screen. KMS need this. */
220         vt_fb_postswitch(vd);
221
222         return (CN_INTERNAL);
223 }
224
225 int
226 vt_fb_attach(struct fb_info *info)
227 {
228
229         vt_allocate(&vt_fb_driver, info);
230
231         return (0);
232 }
233
234 void
235 vt_fb_resume(void)
236 {
237
238         vt_resume();
239 }
240
241 void
242 vt_fb_suspend(void)
243 {
244
245         vt_suspend();
246 }