]> rtime.felk.cvut.cz Git - l4.git/blob - l4/pkg/l4con/server/src/pslim.c
Update
[l4.git] / l4 / pkg / l4con / server / src / pslim.c
1
2 /**
3  * \file        con/server/src/pslim.c
4  * \brief       implementation of pSLIM protocol
5  *
6  * \date        2001
7  * \author      Christian Helmuth <ch12@os.inf.tu-dresden.de>
8  *              Frank Mehnert <fm3@os.inf.tu-dresden.de> */
9 /*
10  * (c) 2003-2009 Author(s)
11  *     economic rights: Technische Universität Dresden (Germany)
12  *
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.
16  */
17
18 #include <stdlib.h>
19 #include <string.h>             /* needed for memmove */
20
21 #include <l4/sys/cache.h>
22 #include <l4/libgfxbitmap/bitmap.h>
23
24 /* local includes */
25 #include "main.h"
26 #include "l4con.h"
27 #include "pslim.h"
28 #include "con_hw/init.h"
29 #include "con_yuv2rgb/yuv2rgb.h"
30
31 /* private types */
32 /** offsets in pmap[] and bmap[] */
33 struct pslim_offset
34 {
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 */
39 };
40
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*,
53                            l4_uint8_t mode);
54
55 /* clipping */
56
57 static inline int
58 clip_rect(struct l4con_vc *vc, int from_user, l4con_pslim_rect_t *rect)
59 {
60   int max_x = vc->xres;
61   int max_y = vc->yres;
62
63   if (from_user)
64     {
65       rect->x += vc->client_xofs;
66       rect->y += vc->client_yofs;
67       max_x    = vc->client_xres;
68       max_y    = vc->client_yres;
69     }
70
71   if ((rect->x > max_x) || (rect->y > max_y))
72     /* not in the frame buffer */
73     return 0;
74   if (rect->x < 0)
75     {
76       if (-rect->x >= rect->w)
77         /* not visible - left of border */
78         return 0;
79       /* clip left */
80       rect->w += rect->x;
81       rect->x  = 0;
82     }
83   if (rect->y < 0)
84     {
85       if (-rect->y >= rect->h)
86         /* not visible - above border */
87         return 0;
88       /* clip top */
89       rect->h += rect->y;
90       rect->y  = 0;
91     }
92   if ((rect->x + rect->w) > max_x)
93     /* clip right */
94     rect->w = max_x - rect->x;
95   if ((rect->y + rect->h) > max_y)
96     /* clip bottom */
97     rect->h = max_y - rect->y;
98
99   /* something is visible */
100   return 1;
101 }
102
103 static inline int
104 clip_rect_offset(struct l4con_vc *vc, int from_user,
105                  l4con_pslim_rect_t *rect, struct pslim_offset *offset)
106 {
107   int max_x = vc->xres;
108   int max_y = vc->yres;
109
110   if (from_user)
111     {
112       rect->x += vc->client_xofs;
113       rect->y += vc->client_yofs;
114       max_x    = vc->client_xres;
115       max_y    = vc->client_yres;
116     }
117
118   if ((rect->x > max_x) || (rect->y > max_y))
119     /* not in the frame buffer */
120     return 0;
121   if (rect->x < 0)
122     {
123       if (-rect->x > rect->w)
124         /* not visible - left of border */
125         return 0;
126       /* clip left */
127       rect->w           += rect->x;
128       offset->preskip_x  = -rect->x;
129       rect->x            = 0;
130     }
131   if (rect->y < 0)
132     {
133       if (-rect->y > rect->h)
134         /* not visible - above border */
135         return 0;
136       /* clip top */
137       rect->h           += rect->y;
138       offset->preskip_y  = -rect->y;
139       rect->y            = 0;
140     }
141   if ((rect->x + rect->w) > max_x)
142     {
143       /* clip right */
144       offset->endskip_x  = rect->x + rect->w - max_x;
145       rect->w = max_x - rect->x;
146     }
147   if ((rect->y + rect->h) > max_y)
148     /* clip bottom */
149     rect->h = max_y - rect->y;
150
151   /* something is visible */
152   return 1;
153 }
154
155 static inline int
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)
158 {
159   int max_x = vc->xres;
160   int max_y = vc->yres;
161
162   if (from_user)
163     {
164       rect->x += vc->client_xofs;
165       rect->y += vc->client_yofs;
166       max_x    = vc->client_xres;
167       max_y    = vc->client_yres;
168     }
169
170   /* clip source rectangle */
171   if ((rect->x > max_x) || (rect->y > max_y))
172     /* not in the frame buffer */
173     return 0;
174   if (rect->x < 0)
175     {
176       if (-rect->x > rect->w)
177         /* not visible - left of border */
178         return 0;
179       /* clip left */
180       rect->w += rect->x;
181       *dx     -= rect->x;
182       rect->x  = 0;
183     }
184   if (rect->y < 0)
185     {
186       if (-rect->y > rect->h)
187         /* not visible - above border */
188         return 0;
189       /* clip top */
190       rect->h += rect->y;
191       *dy     -= rect->y;
192       rect->y  = 0;
193     }
194   if ((rect->x + rect->w) > max_x)
195     /* clip right */
196     rect->w = max_x - rect->x;
197   if ((rect->y + rect->h) > max_y)
198     /* clip bottom */
199     rect->h = max_y - rect->y;
200
201   /* clip destination rectangle */
202   if ((*dx > max_x) || (*dy > max_y))
203     /* not in the frame buffer */
204     return 0;
205   if (*dx < 0)
206     {
207       if (-*dx > rect->w)
208         /* not visible - left of border */
209         return 0;
210       /* clip left */
211       rect->w += *dx;
212       rect->x -= *dx;
213       *dx = 0;
214     }
215   if (*dy < 0)
216     {
217       if (-*dy > rect->h)
218         /* not visible - above border */
219         return 0;
220       /* clip top */
221       rect->h += *dy;
222       rect->y -= *dy;
223       *dy = 0;
224     }
225   if ((*dx + rect->w) > max_x)
226     /* clip right */
227     rect->w = max_x - *dx;
228   if ((*dy + rect->h) > max_y)
229     /* clip bottom */
230     rect->h = max_y - *dy;
231
232   /* something is visible */
233   return 1;
234 }
235
236 void
237 sw_fill(struct l4con_vc *vc, int x, int y, int w, int h, unsigned color)
238 {
239   l4_uint8_t *vfb = (l4_uint8_t*) vc->fb;
240
241   /* wait for any pending acceleration operation */
242   vc->do_sync();
243
244   {
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);
250   }
251
252   /* force redraw of changed screen content (needed by VMware) */
253   if (vc->do_drty)
254     vc->do_drty(x, y, w, h);
255 }
256
257 static inline void
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)
261 {
262   l4_uint8_t *vfb = (l4_uint8_t*) vc->fb;
263   l4re_video_view_info_t vvi;
264
265   /* wait for any pending acceleration operation */
266   vc->do_sync();
267
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);
273
274   /* force redraw of changed screen content (needed by VMware) */
275   if (vc->do_drty)
276     vc->do_drty(x, y, w, h);
277 }
278
279 static inline void
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)
283 {
284   l4_uint8_t *vfb = (l4_uint8_t*) vc->fb;
285   l4_uint32_t bytepp = vc->bytes_per_pixel;
286   l4_uint32_t pwidth;
287   l4re_video_view_info_t vvi;
288
289   if (!pmap)
290     {
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;
295     }
296   else
297     {
298       pwidth = bytepp * (w + offset->endskip_x);
299       pmap  += bytepp * offset->preskip_y *
300                         (w + offset->preskip_x + offset->endskip_x);
301     }
302
303   /* wait for any pending acceleration operation */
304   vc->do_sync();
305
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);
311
312   /* force redraw of changed screen content (needed by VMware) */
313   if (vc->do_drty)
314     vc->do_drty(x+xoffs, y+yoffs, w, h);
315 }
316
317 void
318 sw_copy(struct l4con_vc *vc, int x, int y, int w, int h, int dx, int dy)
319 {
320   l4_uint8_t *vfb = (l4_uint8_t*) vc->fb;
321   l4re_video_view_info_t vvi;
322
323   /* wait for any pending acceleration operation */
324   vc->do_sync();
325
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);
330
331   /* force redraw of changed screen content (needed by VMware) */
332   if (vc->do_drty)
333     vc->do_drty(dx, dy, w, h);
334 }
335
336 static inline void
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)
340 {
341   (void)scale; (void)offset; (void)mode;
342   /* wait for any pending acceleration operation */
343   vc->do_sync();
344
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);
348
349   /* force redraw of changed screen content (needed by VMware) */
350   if (vc->do_drty)
351     vc->do_drty(x, y, w, h);
352 }
353
354 /* SVGAlib calls this: FILLBOX */
355 void
356 pslim_fill(struct l4con_vc *vc, int from_user,
357            l4con_pslim_rect_t *rect, l4con_pslim_color_t color)
358 {
359   if (!clip_rect(vc, from_user, rect))
360     /* nothing visible */
361     return;
362
363   if (!rect->w || !rect->h)
364     /* nothing todo */
365     return;
366
367   vc->do_fill(vc, rect->x+vc->pan_xofs, rect->y+vc->pan_yofs,
368                   rect->w, rect->h, color);
369 }
370
371 /* SVGAlib calls this:  ACCEL_PUTBITMAP (mode 2)
372                         PBM - images (mode 1)           */
373 void
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,
376            l4_uint8_t mode)
377 {
378   struct pslim_offset offset = {0,0,0};
379
380   if (!clip_rect_offset(vc, from_user, rect, &offset))
381     /* nothing visible */
382     return;
383
384   if (!rect->w || !rect->h)
385     /* nothing todo */
386     return;
387
388   sw_bmap(vc, rect->x+vc->pan_xofs, rect->y+vc->pan_yofs, rect->w, rect->h,
389               bmap, fgc, bgc, &offset, mode);
390 }
391
392
393 /* SVGAlib calls this:  PUTBOX  (and knows about masked boxes!) */
394 void
395 pslim_set(struct l4con_vc *vc, int from_user, l4con_pslim_rect_t *rect,
396           void* pmap)
397 {
398   struct pslim_offset offset = {0,0,0};
399
400   if (!clip_rect_offset(vc, from_user, rect, &offset))
401     /* nothing visible */
402     return;
403
404   if (!rect->w || !rect->h)
405     /* nothing todo */
406     return;
407
408   sw_set(vc, rect->x, rect->y, rect->w, rect->h,
409              vc->pan_xofs, vc->pan_yofs, (l4_uint8_t*) pmap, &offset);
410 }
411
412 /* SVGAlib calls this:  COPYBOX */
413 void
414 pslim_copy(struct l4con_vc *vc, int from_user, l4con_pslim_rect_t *rect,
415            l4_int16_t dx, l4_int16_t dy)
416 {
417   if (!clip_rect_dxy(vc, from_user, rect, &dx, &dy))
418     /* nothing visible */
419     return;
420
421   if (!rect->w || !rect->h)
422     /* nothing todo */
423     return;
424
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);
427 }
428
429 /* COLOR-SPACE CONVERT and (optional) SCALE
430  *
431  * mode ... Specifies the resolution of chrominance data
432  *
433  *      Code     Meaning
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
438  */
439 void
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)
442 {
443   struct pslim_offset offset = {0,0,0};
444
445   if (!clip_rect_offset(vc, from_user, rect, &offset))
446     /* nothing visible */
447     return;
448
449   if (!rect->w || !rect->h)
450     /* nothing todo */
451     return;
452
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);
455 }