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

Last change on this file was 09f41d3, checked in by Jiri Svoboda <jiri@…>, 10 months ago

Tetris should be able to detect screen cursor control capability

  • Property mode set to 100644
File size: 8.1 KB
Line 
1/*
2 * Copyright (c) 2024 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_CURSORCTL | CONSOLE_CAP_STYLE |
201 CONSOLE_CAP_INDEXED | CONSOLE_CAP_RGB);
202}
203
204static void output_ddev_char_update(outdev_t *dev, sysarg_t col, sysarg_t row)
205{
206 output_ddev_t *ddev = (output_ddev_t *) dev->data;
207
208 charfield_t *field =
209 chargrid_charfield_at(dev->backbuf, col, row);
210
211 draw_char(ddev, field, col, row);
212}
213
214static void output_ddev_cursor_update(outdev_t *dev, sysarg_t prev_col,
215 sysarg_t prev_row, sysarg_t col, sysarg_t row, bool visible)
216{
217 output_ddev_t *ddev = (output_ddev_t *) dev->data;
218
219 ddev->curs_col = col;
220 ddev->curs_row = row;
221 ddev->curs_visible = visible;
222
223 output_ddev_char_update(dev, prev_col, prev_row);
224 output_ddev_char_update(dev, col, row);
225}
226
227static void output_ddev_flush(outdev_t *dev)
228{
229 output_ddev_t *ddev = (output_ddev_t *) dev->data;
230
231 (void) gfx_bitmap_render(ddev->bitmap, &ddev->dirty, NULL);
232
233 ddev->dirty.p0.x = 0;
234 ddev->dirty.p0.y = 0;
235 ddev->dirty.p1.x = 0;
236 ddev->dirty.p1.y = 0;
237}
238
239static outdev_ops_t output_ddev_ops = {
240 .yield = output_ddev_yield,
241 .claim = output_ddev_claim,
242 .get_dimensions = output_ddev_get_dimensions,
243 .get_caps = output_ddev_get_caps,
244 .cursor_update = output_ddev_cursor_update,
245 .char_update = output_ddev_char_update,
246 .flush = output_ddev_flush
247};
248
249errno_t output_ddev_init(void)
250{
251 ddev_t *dd = NULL;
252 output_ddev_t *ddev = NULL;
253 ddev_info_t info;
254 gfx_coord2_t dims;
255 gfx_context_t *gc;
256 gfx_bitmap_params_t params;
257 gfx_bitmap_alloc_t alloc;
258 gfx_bitmap_t *bitmap = NULL;
259 errno_t rc;
260
261 ddev = calloc(1, sizeof(output_ddev_t));
262 if (ddev == NULL)
263 return ENOMEM;
264
265 rc = ddev_open(KFB_DDEV_NAME, &dd);
266 if (rc != EOK) {
267 printf("Error opening display device '%s'.", KFB_DDEV_NAME);
268 goto error;
269 }
270
271 rc = ddev_get_info(dd, &info);
272 if (rc != EOK) {
273 printf("Error getting information for display device '%s'.",
274 KFB_DDEV_NAME);
275 goto error;
276 }
277
278 rc = ddev_get_gc(dd, &gc);
279 if (rc != EOK) {
280 printf("Error getting device context for '%s'.", KFB_DDEV_NAME);
281 goto error;
282 }
283
284 gfx_bitmap_params_init(&params);
285 params.rect = info.rect;
286
287 rc = gfx_bitmap_create(gc, &params, NULL, &bitmap);
288 if (rc != EOK) {
289 printf("Error creating screen bitmap.\n");
290 goto error;
291 }
292
293 rc = gfx_bitmap_get_alloc(bitmap, &alloc);
294 if (rc != EOK) {
295 printf("Error getting bitmap allocation info.\n");
296 goto error;
297 }
298
299 gfx_rect_dims(&info.rect, &dims);
300
301 ddev->gc = gc;
302 ddev->cols = dims.x / FONT_WIDTH;
303 ddev->rows = dims.y / FONT_SCANLINES;
304 ddev->bitmap = bitmap;
305 ddev->pixelmap.width = dims.x;
306 ddev->pixelmap.height = dims.y;
307 ddev->pixelmap.data = alloc.pixels;
308
309 outdev_t *dev = outdev_register(&output_ddev_ops, (void *) ddev);
310 if (dev == NULL) {
311 rc = EINVAL;
312 goto error;
313 }
314
315 return EOK;
316error:
317 if (dd != NULL)
318 ddev_close(dd);
319 if (bitmap != NULL)
320 gfx_bitmap_destroy(bitmap);
321 free(ddev);
322 return rc;
323}
324
325/** @}
326 */
Note: See TracBrowser for help on using the repository browser.