source: mainline/uspace/srv/hid/output/port/ddev.c@ 1382446

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 1382446 was 1382446, checked in by Jiri Svoboda <jiri@…>, 5 years ago

Display device backend for output server

This provides console on a grahpical device, similar to the old kfb
backend. It talks to the userspace kfb driver, instead of mapping
the kfb directly. You can get graphical console by configuring
CONFIG_FB=y and CONFIG_WINSYS=n

  • Property mode set to 100644
File size: 8.0 KB
Line 
1/*
2 * Copyright (c) 2020 Jiri Svoboda
3 * Copyright (c) 2008 Martin Decky
4 * Copyright (c) 2006 Jakub Vana
5 * Copyright (c) 2006 Ondrej Palkovsky
6 * All rights reserved.
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 *
12 * - Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * - Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 * - The name of the author may not be used to endorse or promote products
18 * derived from this software without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
21 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
22 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
23 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
24 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
25 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
29 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 */
31
32/** @addtogroup output
33 * @{
34 */
35
36#include <ddev.h>
37#include <errno.h>
38#include <fbfont/font-8x16.h>
39#include <gfx/bitmap.h>
40#include <gfx/color.h>
41#include <gfx/coord.h>
42#include <gfx/context.h>
43#include <gfx/render.h>
44#include <io/chargrid.h>
45#include <io/pixelmap.h>
46#include <stdlib.h>
47#include "../output.h"
48#include "ddev.h"
49
50#define KFB_DDEV_NAME "devices/\\virt\\kfb\\kfb"
51
52typedef struct {
53 gfx_context_t *gc;
54
55 sysarg_t cols;
56 sysarg_t rows;
57
58 uint8_t style_normal;
59 uint8_t style_inverted;
60
61 gfx_bitmap_t *bitmap;
62 pixelmap_t pixelmap;
63 gfx_rect_t dirty;
64
65 sysarg_t curs_col;
66 sysarg_t curs_row;
67 bool curs_visible;
68} output_ddev_t;
69
70static pixel_t color_table[16] = {
71 [COLOR_BLACK] = 0x000000,
72 [COLOR_BLUE] = 0x0000f0,
73 [COLOR_GREEN] = 0x00f000,
74 [COLOR_CYAN] = 0x00f0f0,
75 [COLOR_RED] = 0xf00000,
76 [COLOR_MAGENTA] = 0xf000f0,
77 [COLOR_YELLOW] = 0xf0f000,
78 [COLOR_WHITE] = 0xf0f0f0,
79
80 [COLOR_BLACK + 8] = 0x000000,
81 [COLOR_BLUE + 8] = 0x0000ff,
82 [COLOR_GREEN + 8] = 0x00ff00,
83 [COLOR_CYAN + 8] = 0x00ffff,
84 [COLOR_RED + 8] = 0xff0000,
85 [COLOR_MAGENTA + 8] = 0xff00ff,
86 [COLOR_YELLOW + 8] = 0xffff00,
87 [COLOR_WHITE + 8] = 0xffffff,
88};
89
90static void attrs_rgb(char_attrs_t attrs, pixel_t *bgcolor, pixel_t *fgcolor)
91{
92 switch (attrs.type) {
93 case CHAR_ATTR_STYLE:
94 switch (attrs.val.style) {
95 case STYLE_NORMAL:
96 *bgcolor = color_table[COLOR_WHITE];
97 *fgcolor = color_table[COLOR_BLACK];
98 break;
99 case STYLE_EMPHASIS:
100 *bgcolor = color_table[COLOR_WHITE];
101 *fgcolor = color_table[COLOR_RED];
102 break;
103 case STYLE_INVERTED:
104 *bgcolor = color_table[COLOR_BLACK];
105 *fgcolor = color_table[COLOR_WHITE];
106 break;
107 case STYLE_SELECTED:
108 *bgcolor = color_table[COLOR_RED];
109 *fgcolor = color_table[COLOR_WHITE];
110 break;
111 }
112 break;
113 case CHAR_ATTR_INDEX:
114 *bgcolor = color_table[(attrs.val.index.bgcolor & 7) |
115 ((attrs.val.index.attr & CATTR_BRIGHT) ? 8 : 0)];
116 *fgcolor = color_table[(attrs.val.index.fgcolor & 7) |
117 ((attrs.val.index.attr & CATTR_BRIGHT) ? 8 : 0)];
118 break;
119 case CHAR_ATTR_RGB:
120 *bgcolor = attrs.val.rgb.bgcolor;
121 *fgcolor = attrs.val.rgb.fgcolor;
122 break;
123 }
124}
125
126/** Draw the character at the specified position.
127 *
128 * @param field Character field.
129 * @param col Horizontal screen position.
130 * @param row Vertical screen position.
131 *
132 */
133static void draw_char(output_ddev_t *ddev, charfield_t *field,
134 sysarg_t col, sysarg_t row)
135{
136 pixel_t fgcolor;
137 pixel_t bgcolor;
138 pixel_t pcolor;
139 pixel_t tmp;
140 gfx_rect_t rect;
141 gfx_rect_t ndrect;
142 gfx_coord_t x, y;
143 bool inverted;
144 uint32_t glyph;
145
146 fgcolor = bgcolor = 0;
147 attrs_rgb(field->attrs, &bgcolor, &fgcolor);
148
149 inverted = (col == ddev->curs_col) && (row == ddev->curs_row) &&
150 ddev->curs_visible;
151
152 if (inverted) {
153 /* Swap foreground and background colors */
154 tmp = bgcolor;
155 bgcolor = fgcolor;
156 fgcolor = tmp;
157 }
158
159 rect.p0.x = FONT_WIDTH * col;
160 rect.p0.y = FONT_SCANLINES * row;
161 rect.p1.x = FONT_WIDTH * (col + 1);
162 rect.p1.y = FONT_SCANLINES * (row + 1);
163
164 glyph = fb_font_glyph(field->ch, NULL);
165
166 for (y = 0; y < FONT_SCANLINES; y++) {
167 for (x = 0; x < FONT_WIDTH; x++) {
168 pcolor = fb_font[glyph][y] & (1 << (7 - x)) ?
169 fgcolor : bgcolor;
170 pixelmap_put_pixel(&ddev->pixelmap,
171 rect.p0.x + x, rect.p0.y + y, pcolor);
172 }
173 }
174
175 /* Compute new dirty rectangle */
176 gfx_rect_envelope(&ddev->dirty, &rect, &ndrect);
177 ddev->dirty = ndrect;
178}
179
180static errno_t output_ddev_yield(outdev_t *dev)
181{
182 return EOK;
183}
184
185static errno_t output_ddev_claim(outdev_t *dev)
186{
187 return EOK;
188}
189
190static void output_ddev_get_dimensions(outdev_t *dev, sysarg_t *cols, sysarg_t *rows)
191{
192 output_ddev_t *ddev = (output_ddev_t *) dev->data;
193
194 *cols = ddev->cols;
195 *rows = ddev->rows;
196}
197
198static console_caps_t output_ddev_get_caps(outdev_t *dev)
199{
200 return (CONSOLE_CAP_STYLE | CONSOLE_CAP_INDEXED | CONSOLE_CAP_RGB);
201}
202
203static void output_ddev_char_update(outdev_t *dev, sysarg_t col, sysarg_t row)
204{
205 output_ddev_t *ddev = (output_ddev_t *) dev->data;
206
207 charfield_t *field =
208 chargrid_charfield_at(dev->backbuf, col, row);
209
210 draw_char(ddev, field, col, row);
211}
212
213static void output_ddev_cursor_update(outdev_t *dev, sysarg_t prev_col,
214 sysarg_t prev_row, sysarg_t col, sysarg_t row, bool visible)
215{
216 output_ddev_t *ddev = (output_ddev_t *) dev->data;
217
218 ddev->curs_col = col;
219 ddev->curs_row = row;
220 ddev->curs_visible = visible;
221
222 output_ddev_char_update(dev, prev_col, prev_row);
223 output_ddev_char_update(dev, col, row);
224}
225
226static void output_ddev_flush(outdev_t *dev)
227{
228 output_ddev_t *ddev = (output_ddev_t *) dev->data;
229
230 (void) gfx_bitmap_render(ddev->bitmap, &ddev->dirty, NULL);
231
232 ddev->dirty.p0.x = 0;
233 ddev->dirty.p0.y = 0;
234 ddev->dirty.p1.x = 0;
235 ddev->dirty.p1.y = 0;
236}
237
238static outdev_ops_t output_ddev_ops = {
239 .yield = output_ddev_yield,
240 .claim = output_ddev_claim,
241 .get_dimensions = output_ddev_get_dimensions,
242 .get_caps = output_ddev_get_caps,
243 .cursor_update = output_ddev_cursor_update,
244 .char_update = output_ddev_char_update,
245 .flush = output_ddev_flush
246};
247
248errno_t output_ddev_init(void)
249{
250 ddev_t *dd = NULL;
251 output_ddev_t *ddev = NULL;
252 ddev_info_t info;
253 gfx_coord2_t dims;
254 gfx_context_t *gc;
255 gfx_bitmap_params_t params;
256 gfx_bitmap_alloc_t alloc;
257 gfx_bitmap_t *bitmap = NULL;
258 errno_t rc;
259
260 ddev = calloc(1, sizeof(output_ddev_t));
261 if (ddev == NULL)
262 return ENOMEM;
263
264 rc = ddev_open(KFB_DDEV_NAME, &dd);
265 if (rc != EOK) {
266 printf("Error opening display device '%s'.", KFB_DDEV_NAME);
267 goto error;
268 }
269
270 rc = ddev_get_info(dd, &info);
271 if (rc != EOK) {
272 printf("Error getting information for display device '%s'.",
273 KFB_DDEV_NAME);
274 goto error;
275 }
276
277 rc = ddev_get_gc(dd, &gc);
278 if (rc != EOK) {
279 printf("Error getting device context for '%s'.", KFB_DDEV_NAME);
280 goto error;
281 }
282
283 gfx_bitmap_params_init(&params);
284 params.rect = info.rect;
285
286 rc = gfx_bitmap_create(gc, &params, NULL, &bitmap);
287 if (rc != EOK) {
288 printf("Error creating screen bitmap.\n");
289 goto error;
290 }
291
292 rc = gfx_bitmap_get_alloc(bitmap, &alloc);
293 if (rc != EOK) {
294 printf("Error getting bitmap allocation info.\n");
295 goto error;
296 }
297
298 gfx_rect_dims(&info.rect, &dims);
299
300 ddev->gc = gc;
301 ddev->cols = dims.x / FONT_WIDTH;
302 ddev->rows = dims.y / FONT_SCANLINES;
303 ddev->bitmap = bitmap;
304 ddev->pixelmap.width = dims.x;
305 ddev->pixelmap.height = dims.y;
306 ddev->pixelmap.data = alloc.pixels;
307
308 outdev_t *dev = outdev_register(&output_ddev_ops, (void *) ddev);
309 if (dev == NULL) {
310 rc = EINVAL;
311 goto error;
312 }
313
314 return EOK;
315error:
316 if (dd != NULL)
317 ddev_close(dd);
318 if (bitmap != NULL)
319 gfx_bitmap_destroy(bitmap);
320 free(ddev);
321 return rc;
322}
323
324/** @}
325 */
Note: See TracBrowser for help on using the repository browser.