source: mainline/uspace/drv/fb/kfb/port.c@ 4c25c2fb

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

Kfb should unmap the frame buffer when client connection is terminated.

  • Property mode set to 100644
File size: 8.3 KB
Line 
1/*
2 * Copyright (c) 2006 Jakub Vana
3 * Copyright (c) 2006 Ondrej Palkovsky
4 * Copyright (c) 2008 Martin Decky
5 * Copyright (c) 2011 Petr Koupy
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 kfb
33 * @{
34 */
35/**
36 * @file
37 */
38
39#include <abi/fb/visuals.h>
40#include <stddef.h>
41#include <stdint.h>
42#include <errno.h>
43
44#include <malloc.h>
45#include <mem.h>
46#include <as.h>
47#include <align.h>
48
49#include <sysinfo.h>
50#include <ddi.h>
51
52#include <adt/list.h>
53
54#include <io/mode.h>
55#include <io/pixelmap.h>
56#include <io/chargrid.h>
57
58#include <pixconv.h>
59
60#include <graph.h>
61
62#include "kfb.h"
63#include "port.h"
64
65#define FB_POS(x, y) ((y) * kfb.scanline + (x) * kfb.pixel_bytes)
66
67typedef struct {
68 sysarg_t paddr;
69 sysarg_t width;
70 sysarg_t height;
71 size_t offset;
72 size_t scanline;
73 visual_t visual;
74
75 pixel2visual_t pixel2visual;
76 visual2pixel_t visual2pixel;
77 visual_mask_t visual_mask;
78 size_t pixel_bytes;
79
80 size_t size;
81 uint8_t *addr;
82} kfb_t;
83
84static kfb_t kfb;
85
86static vslmode_list_element_t pixel_mode;
87
88static int kfb_claim(visualizer_t *vs)
89{
90 return physmem_map(kfb.paddr + kfb.offset,
91 ALIGN_UP(kfb.size, PAGE_SIZE) >> PAGE_WIDTH,
92 AS_AREA_READ | AS_AREA_WRITE, (void *) &kfb.addr);
93}
94
95static int kfb_yield(visualizer_t *vs)
96{
97 int rc;
98
99 if (vs->mode_set) {
100 vs->ops.handle_damage = NULL;
101 }
102
103 rc = physmem_unmap(kfb.addr);
104 if (rc != EOK)
105 return rc;
106
107 kfb.addr = NULL;
108 return EOK;
109}
110
111static int kfb_handle_damage_pixels(visualizer_t *vs,
112 sysarg_t x0, sysarg_t y0, sysarg_t width, sysarg_t height,
113 sysarg_t x_offset, sysarg_t y_offset)
114{
115 pixelmap_t *map = &vs->cells;
116
117 if (x_offset == 0 && y_offset == 0) {
118 /* Faster damage routine ignoring offsets. */
119 for (sysarg_t y = y0; y < height + y0; ++y) {
120 pixel_t *pixel = pixelmap_pixel_at(map, x0, y);
121 for (sysarg_t x = x0; x < width + x0; ++x) {
122 kfb.pixel2visual(kfb.addr + FB_POS(x, y), *pixel++);
123 }
124 }
125 } else {
126 for (sysarg_t y = y0; y < height + y0; ++y) {
127 for (sysarg_t x = x0; x < width + x0; ++x) {
128 kfb.pixel2visual(kfb.addr + FB_POS(x, y),
129 *pixelmap_pixel_at(map,
130 (x + x_offset) % map->width,
131 (y + y_offset) % map->height));
132 }
133 }
134 }
135
136 return EOK;
137}
138
139static int kfb_change_mode(visualizer_t *vs, vslmode_t new_mode)
140{
141 vs->ops.handle_damage = kfb_handle_damage_pixels;
142 return EOK;
143}
144
145static int kfb_suspend(visualizer_t *vs)
146{
147 return EOK;
148}
149
150static int kfb_wakeup(visualizer_t *vs)
151{
152 return EOK;
153}
154
155static visualizer_ops_t kfb_ops = {
156 .claim = kfb_claim,
157 .yield = kfb_yield,
158 .change_mode = kfb_change_mode,
159 .handle_damage = NULL,
160 .suspend = kfb_suspend,
161 .wakeup = kfb_wakeup
162};
163
164static void graph_vsl_connection(ipc_callid_t iid, ipc_call_t *icall, void *arg)
165{
166 visualizer_t *vsl;
167 int rc;
168
169 vsl = (visualizer_t *) ddf_fun_data_get((ddf_fun_t *)arg);
170 graph_visualizer_connection(vsl, iid, icall, NULL);
171
172 if (kfb.addr != NULL) {
173 rc = physmem_unmap(kfb.addr);
174 if (rc == EOK)
175 kfb.addr = NULL;
176 }
177}
178
179int port_init(ddf_dev_t *dev)
180{
181 sysarg_t present;
182 int rc = sysinfo_get_value("fb", &present);
183 if (rc != EOK)
184 present = false;
185
186 if (!present)
187 return ENOENT;
188
189 sysarg_t kind;
190 rc = sysinfo_get_value("fb.kind", &kind);
191 if (rc != EOK)
192 kind = (sysarg_t) -1;
193
194 if (kind != 1)
195 return EINVAL;
196
197 sysarg_t paddr;
198 rc = sysinfo_get_value("fb.address.physical", &paddr);
199 if (rc != EOK)
200 return rc;
201
202 sysarg_t offset;
203 rc = sysinfo_get_value("fb.offset", &offset);
204 if (rc != EOK)
205 offset = 0;
206
207 sysarg_t width;
208 rc = sysinfo_get_value("fb.width", &width);
209 if (rc != EOK)
210 return rc;
211
212 sysarg_t height;
213 rc = sysinfo_get_value("fb.height", &height);
214 if (rc != EOK)
215 return rc;
216
217 sysarg_t scanline;
218 rc = sysinfo_get_value("fb.scanline", &scanline);
219 if (rc != EOK)
220 return rc;
221
222 sysarg_t visual;
223 rc = sysinfo_get_value("fb.visual", &visual);
224 if (rc != EOK)
225 return rc;
226
227 kfb.width = width;
228 kfb.height = height;
229 kfb.paddr = paddr;
230 kfb.offset = offset;
231 kfb.scanline = scanline;
232 kfb.visual = visual;
233
234 switch (visual) {
235 case VISUAL_INDIRECT_8:
236 kfb.pixel2visual = pixel2bgr_323;
237 kfb.visual2pixel = bgr_323_2pixel;
238 kfb.visual_mask = visual_mask_323;
239 kfb.pixel_bytes = 1;
240 break;
241 case VISUAL_RGB_5_5_5_LE:
242 kfb.pixel2visual = pixel2rgb_555_le;
243 kfb.visual2pixel = rgb_555_le_2pixel;
244 kfb.visual_mask = visual_mask_555;
245 kfb.pixel_bytes = 2;
246 break;
247 case VISUAL_RGB_5_5_5_BE:
248 kfb.pixel2visual = pixel2rgb_555_be;
249 kfb.visual2pixel = rgb_555_be_2pixel;
250 kfb.visual_mask = visual_mask_555;
251 kfb.pixel_bytes = 2;
252 break;
253 case VISUAL_RGB_5_6_5_LE:
254 kfb.pixel2visual = pixel2rgb_565_le;
255 kfb.visual2pixel = rgb_565_le_2pixel;
256 kfb.visual_mask = visual_mask_565;
257 kfb.pixel_bytes = 2;
258 break;
259 case VISUAL_RGB_5_6_5_BE:
260 kfb.pixel2visual = pixel2rgb_565_be;
261 kfb.visual2pixel = rgb_565_be_2pixel;
262 kfb.visual_mask = visual_mask_565;
263 kfb.pixel_bytes = 2;
264 break;
265 case VISUAL_RGB_8_8_8:
266 kfb.pixel2visual = pixel2rgb_888;
267 kfb.visual2pixel = rgb_888_2pixel;
268 kfb.visual_mask = visual_mask_888;
269 kfb.pixel_bytes = 3;
270 break;
271 case VISUAL_BGR_8_8_8:
272 kfb.pixel2visual = pixel2bgr_888;
273 kfb.visual2pixel = bgr_888_2pixel;
274 kfb.visual_mask = visual_mask_888;
275 kfb.pixel_bytes = 3;
276 break;
277 case VISUAL_RGB_8_8_8_0:
278 kfb.pixel2visual = pixel2rgb_8880;
279 kfb.visual2pixel = rgb_8880_2pixel;
280 kfb.visual_mask = visual_mask_8880;
281 kfb.pixel_bytes = 4;
282 break;
283 case VISUAL_RGB_0_8_8_8:
284 kfb.pixel2visual = pixel2rgb_0888;
285 kfb.visual2pixel = rgb_0888_2pixel;
286 kfb.visual_mask = visual_mask_0888;
287 kfb.pixel_bytes = 4;
288 break;
289 case VISUAL_BGR_0_8_8_8:
290 kfb.pixel2visual = pixel2bgr_0888;
291 kfb.visual2pixel = bgr_0888_2pixel;
292 kfb.visual_mask = visual_mask_0888;
293 kfb.pixel_bytes = 4;
294 break;
295 case VISUAL_BGR_8_8_8_0:
296 kfb.pixel2visual = pixel2bgr_8880;
297 kfb.visual2pixel = bgr_8880_2pixel;
298 kfb.visual_mask = visual_mask_8880;
299 kfb.pixel_bytes = 4;
300 break;
301 default:
302 return EINVAL;
303 }
304
305 kfb.size = scanline * height;
306 kfb.addr = AS_AREA_ANY;
307
308 ddf_fun_t *fun_vs = ddf_fun_create(dev, fun_exposed, "vsl0");
309 if (fun_vs == NULL) {
310 as_area_destroy(kfb.addr);
311 return ENOMEM;
312 }
313 ddf_fun_set_conn_handler(fun_vs, &graph_vsl_connection);
314
315 visualizer_t *vs = ddf_fun_data_alloc(fun_vs, sizeof(visualizer_t));
316 if (vs == NULL) {
317 as_area_destroy(kfb.addr);
318 return ENOMEM;
319 }
320 graph_init_visualizer(vs);
321
322 pixel_mode.mode.index = 0;
323 pixel_mode.mode.version = 0;
324 pixel_mode.mode.refresh_rate = 0;
325 pixel_mode.mode.screen_aspect.width = width;
326 pixel_mode.mode.screen_aspect.height = height;
327 pixel_mode.mode.screen_width = width;
328 pixel_mode.mode.screen_height = height;
329 pixel_mode.mode.cell_aspect.width = 1;
330 pixel_mode.mode.cell_aspect.height = 1;
331 pixel_mode.mode.cell_visual.pixel_visual = visual;
332
333 link_initialize(&pixel_mode.link);
334 list_append(&pixel_mode.link, &vs->modes);
335
336 vs->def_mode_idx = 0;
337
338 vs->ops = kfb_ops;
339 vs->dev_ctx = NULL;
340
341 rc = ddf_fun_bind(fun_vs);
342 if (rc != EOK) {
343 list_remove(&pixel_mode.link);
344 ddf_fun_destroy(fun_vs);
345 as_area_destroy(kfb.addr);
346 return rc;
347 }
348
349 vs->reg_svc_handle = ddf_fun_get_handle(fun_vs);
350 ddf_fun_add_to_category(fun_vs, "visualizer");
351
352 return EOK;
353}
354
355/** @}
356 */
Note: See TracBrowser for help on using the repository browser.