3 * \file con/server/src/pslim.c
4 * \brief implementation of pSLIM protocol
7 * \author Christian Helmuth <ch12@os.inf.tu-dresden.de>
8 * Frank Mehnert <fm3@os.inf.tu-dresden.de> */
10 * (c) 2003-2009 Author(s)
11 * economic rights: Technische Universität Dresden (Germany)
13 * This file is part of TUD:OS and distributed under the terms of the
14 * GNU General Public License 2.
15 * Please see the COPYING-GPL-2 file for details.
19 #include <string.h> /* needed for memmove */
21 #include <l4/sys/cache.h>
22 #include <l4/libgfxbitmap/bitmap.h>
28 #include "con_hw/init.h"
29 #include "con_yuv2rgb/yuv2rgb.h"
32 /** offsets in pmap[] and bmap[] */
35 l4_uint32_t preskip_x; /**< skip pixels at beginning of line */
36 l4_uint32_t preskip_y; /**< skip lines */
37 l4_uint32_t endskip_x; /**< skip pixels at end of line */
38 /* word_t endskip_y; */ /* snip lines */
41 /* all pslim_*-functions call the vc->g_mode specific functions */
42 static inline void sw_bmap(struct l4con_vc*, l4_int16_t, l4_int16_t,
43 l4_uint32_t, l4_uint32_t,
44 l4_uint8_t *bmap, l4_uint32_t fgc, l4_uint32_t bgc,
45 struct pslim_offset*, l4_uint8_t mode);
46 static inline void sw_set(struct l4con_vc*, l4_int16_t, l4_int16_t,
47 l4_uint32_t, l4_uint32_t, l4_uint32_t, l4_uint32_t,
48 l4_uint8_t *pmap, struct pslim_offset*);
49 static inline void sw_cscs(struct l4con_vc*, l4_int16_t, l4_int16_t,
50 l4_uint32_t, l4_uint32_t,
51 l4_uint8_t *y, l4_uint8_t *u, l4_uint8_t *v,
52 l4_uint32_t scale, struct pslim_offset*,
58 clip_rect(struct l4con_vc *vc, int from_user, l4con_pslim_rect_t *rect)
65 rect->x += vc->client_xofs;
66 rect->y += vc->client_yofs;
67 max_x = vc->client_xres;
68 max_y = vc->client_yres;
71 if ((rect->x > max_x) || (rect->y > max_y))
72 /* not in the frame buffer */
76 if (-rect->x >= rect->w)
77 /* not visible - left of border */
85 if (-rect->y >= rect->h)
86 /* not visible - above border */
92 if ((rect->x + rect->w) > max_x)
94 rect->w = max_x - rect->x;
95 if ((rect->y + rect->h) > max_y)
97 rect->h = max_y - rect->y;
99 /* something is visible */
104 clip_rect_offset(struct l4con_vc *vc, int from_user,
105 l4con_pslim_rect_t *rect, struct pslim_offset *offset)
107 int max_x = vc->xres;
108 int max_y = vc->yres;
112 rect->x += vc->client_xofs;
113 rect->y += vc->client_yofs;
114 max_x = vc->client_xres;
115 max_y = vc->client_yres;
118 if ((rect->x > max_x) || (rect->y > max_y))
119 /* not in the frame buffer */
123 if (-rect->x > rect->w)
124 /* not visible - left of border */
128 offset->preskip_x = -rect->x;
133 if (-rect->y > rect->h)
134 /* not visible - above border */
138 offset->preskip_y = -rect->y;
141 if ((rect->x + rect->w) > max_x)
144 offset->endskip_x = rect->x + rect->w - max_x;
145 rect->w = max_x - rect->x;
147 if ((rect->y + rect->h) > max_y)
149 rect->h = max_y - rect->y;
151 /* something is visible */
156 clip_rect_dxy(struct l4con_vc *vc, int from_user,
157 l4con_pslim_rect_t *rect, l4_int16_t *dx, l4_int16_t *dy)
159 int max_x = vc->xres;
160 int max_y = vc->yres;
164 rect->x += vc->client_xofs;
165 rect->y += vc->client_yofs;
166 max_x = vc->client_xres;
167 max_y = vc->client_yres;
170 /* clip source rectangle */
171 if ((rect->x > max_x) || (rect->y > max_y))
172 /* not in the frame buffer */
176 if (-rect->x > rect->w)
177 /* not visible - left of border */
186 if (-rect->y > rect->h)
187 /* not visible - above border */
194 if ((rect->x + rect->w) > max_x)
196 rect->w = max_x - rect->x;
197 if ((rect->y + rect->h) > max_y)
199 rect->h = max_y - rect->y;
201 /* clip destination rectangle */
202 if ((*dx > max_x) || (*dy > max_y))
203 /* not in the frame buffer */
208 /* not visible - left of border */
218 /* not visible - above border */
225 if ((*dx + rect->w) > max_x)
227 rect->w = max_x - *dx;
228 if ((*dy + rect->h) > max_y)
230 rect->h = max_y - *dy;
232 /* something is visible */
237 sw_fill(struct l4con_vc *vc, int x, int y, int w, int h, unsigned color)
239 l4_uint8_t *vfb = (l4_uint8_t*) vc->fb;
241 /* wait for any pending acceleration operation */
245 l4re_video_view_info_t vvi;
246 vvi.bytes_per_line = vc->bytes_per_line;
247 vvi.pixel_info.bytes_per_pixel = vc->bytes_per_pixel;
248 vvi.pixel_info.r.size = vc->bpp;
249 gfxbitmap_fill(vfb, &vvi, x, y, w, h, color);
252 /* force redraw of changed screen content (needed by VMware) */
254 vc->do_drty(x, y, w, h);
258 sw_bmap(struct l4con_vc *vc, l4_int16_t x, l4_int16_t y, l4_uint32_t w,
259 l4_uint32_t h, l4_uint8_t *bmap, l4_uint32_t fgc, l4_uint32_t bgc,
260 struct pslim_offset* offset, l4_uint8_t mode)
262 l4_uint8_t *vfb = (l4_uint8_t*) vc->fb;
263 l4re_video_view_info_t vvi;
265 /* wait for any pending acceleration operation */
268 vvi.bytes_per_line = vc->bytes_per_line;
269 vvi.pixel_info.bytes_per_pixel = vc->bytes_per_pixel;
270 vvi.pixel_info.r.size = vc->bpp;
271 gfxbitmap_bmap(vfb, &vvi, x, y, w, h, bmap, fgc, bgc,
272 (struct gfxbitmap_offset *)offset, mode);
274 /* force redraw of changed screen content (needed by VMware) */
276 vc->do_drty(x, y, w, h);
280 sw_set(struct l4con_vc *vc, l4_int16_t x, l4_int16_t y, l4_uint32_t w,
281 l4_uint32_t h, l4_uint32_t xoffs, l4_uint32_t yoffs,
282 l4_uint8_t *pmap, struct pslim_offset* offset)
284 l4_uint8_t *vfb = (l4_uint8_t*) vc->fb;
285 l4_uint32_t bytepp = vc->bytes_per_pixel;
287 l4re_video_view_info_t vvi;
291 /* copy from direct mapped framebuffer of client */
292 /* bwidth may be different from xres*bytepp: e.g. VMware */
293 pwidth = vc->bytes_per_line;
294 pmap = vc->vfb + y*pwidth + x*bytepp;
298 pwidth = bytepp * (w + offset->endskip_x);
299 pmap += bytepp * offset->preskip_y *
300 (w + offset->preskip_x + offset->endskip_x);
303 /* wait for any pending acceleration operation */
306 vvi.bytes_per_line = vc->bytes_per_line;
307 vvi.pixel_info.bytes_per_pixel = vc->bytes_per_pixel;
308 vvi.pixel_info.r.size = vc->bpp;
309 gfxbitmap_set(vfb, &vvi, x, y, w, h, xoffs, yoffs, pmap,
310 (struct gfxbitmap_offset *)offset, pwidth);
312 /* force redraw of changed screen content (needed by VMware) */
314 vc->do_drty(x+xoffs, y+yoffs, w, h);
318 sw_copy(struct l4con_vc *vc, int x, int y, int w, int h, int dx, int dy)
320 l4_uint8_t *vfb = (l4_uint8_t*) vc->fb;
321 l4re_video_view_info_t vvi;
323 /* wait for any pending acceleration operation */
326 vvi.bytes_per_line = vc->bytes_per_line;
327 vvi.pixel_info.bytes_per_pixel = vc->bytes_per_pixel;
328 vvi.pixel_info.r.size = vc->bpp;
329 gfxbitmap_copy(vfb, vfb, &vvi, x, y, w, h, dx, dy);
331 /* force redraw of changed screen content (needed by VMware) */
333 vc->do_drty(dx, dy, w, h);
337 sw_cscs(struct l4con_vc *vc, l4_int16_t x, l4_int16_t y, l4_uint32_t w,
338 l4_uint32_t h, l4_uint8_t *Y, l4_uint8_t *U, l4_uint8_t *V,
339 l4_uint32_t scale, struct pslim_offset* offset, l4_uint8_t mode)
341 (void)scale; (void)offset; (void)mode;
342 /* wait for any pending acceleration operation */
345 /* we exchange U and V here because of video format 420 */
346 (*yuv2rgb_render)(vc->fb+y*vc->bytes_per_line+x*vc->bytes_per_pixel,
347 Y, U, V, w, h, vc->bytes_per_line, w, w/2);
349 /* force redraw of changed screen content (needed by VMware) */
351 vc->do_drty(x, y, w, h);
354 /* SVGAlib calls this: FILLBOX */
356 pslim_fill(struct l4con_vc *vc, int from_user,
357 l4con_pslim_rect_t *rect, l4con_pslim_color_t color)
359 if (!clip_rect(vc, from_user, rect))
360 /* nothing visible */
363 if (!rect->w || !rect->h)
367 vc->do_fill(vc, rect->x+vc->pan_xofs, rect->y+vc->pan_yofs,
368 rect->w, rect->h, color);
371 /* SVGAlib calls this: ACCEL_PUTBITMAP (mode 2)
372 PBM - images (mode 1) */
374 pslim_bmap(struct l4con_vc *vc, int from_user, l4con_pslim_rect_t *rect,
375 l4con_pslim_color_t fgc, l4con_pslim_color_t bgc, void* bmap,
378 struct pslim_offset offset = {0,0,0};
380 if (!clip_rect_offset(vc, from_user, rect, &offset))
381 /* nothing visible */
384 if (!rect->w || !rect->h)
388 sw_bmap(vc, rect->x+vc->pan_xofs, rect->y+vc->pan_yofs, rect->w, rect->h,
389 bmap, fgc, bgc, &offset, mode);
393 /* SVGAlib calls this: PUTBOX (and knows about masked boxes!) */
395 pslim_set(struct l4con_vc *vc, int from_user, l4con_pslim_rect_t *rect,
398 struct pslim_offset offset = {0,0,0};
400 if (!clip_rect_offset(vc, from_user, rect, &offset))
401 /* nothing visible */
404 if (!rect->w || !rect->h)
408 sw_set(vc, rect->x, rect->y, rect->w, rect->h,
409 vc->pan_xofs, vc->pan_yofs, (l4_uint8_t*) pmap, &offset);
412 /* SVGAlib calls this: COPYBOX */
414 pslim_copy(struct l4con_vc *vc, int from_user, l4con_pslim_rect_t *rect,
415 l4_int16_t dx, l4_int16_t dy)
417 if (!clip_rect_dxy(vc, from_user, rect, &dx, &dy))
418 /* nothing visible */
421 if (!rect->w || !rect->h)
425 vc->do_copy(vc, rect->x+vc->pan_xofs, rect->y+vc->pan_yofs, rect->w, rect->h,
426 dx+vc->pan_xofs, dy+vc->pan_yofs);
429 /* COLOR-SPACE CONVERT and (optional) SCALE
431 * mode ... Specifies the resolution of chrominance data
434 * ---- ------- ----------------------------------------
435 * PLN_420 4:2:0 half resolution in both dimensions (most common format)
436 * PLN_422 4:2:2 half resolution in horizontal direction
437 * PLN_444 4:4:4 full resolution
440 pslim_cscs(struct l4con_vc *vc, int from_user, l4con_pslim_rect_t *rect,
441 void* y, void* u, void *v, l4_uint8_t mode, l4_uint32_t scale)
443 struct pslim_offset offset = {0,0,0};
445 if (!clip_rect_offset(vc, from_user, rect, &offset))
446 /* nothing visible */
449 if (!rect->w || !rect->h)
453 sw_cscs(vc, rect->x+vc->pan_xofs, rect->y+vc->pan_yofs, rect->w, rect->h,
454 y, u, v, scale, &offset, mode);