]> rtime.felk.cvut.cz Git - l4.git/blob - l4/pkg/mag-gfx/include/gfx_colors
update
[l4.git] / l4 / pkg / mag-gfx / include / gfx_colors
1 // vi:ft=cpp
2 /*
3  * (c) 2010 Alexander Warg <warg@os.inf.tu-dresden.de>
4  *     economic rights: Technische Universität Dresden (Germany)
5  *
6  * This file is part of TUD:OS and distributed under the terms of the
7  * GNU General Public License 2.
8  * Please see the COPYING-GPL-2 file for details.
9  */
10 #pragma once
11
12 #include <l4/sys/types.h>
13 #include <l4/re/video/colors>
14
15
16 namespace Mag_gfx
17 {
18
19 /*** PRIVATE Murx */
20 namespace _Local
21 {
22
23   /*** int-to-type template */
24   template< int X >
25   class IT
26   {};
27
28   /*** Conversion for a single color component */
29   template< typename From, typename To >
30   static inline typename To::Value convert_comp(typename From::Value c, IT<true> const &)
31   {
32     enum { Sh = From::Shift - To::Shift + From::Size - To::Size };
33     return ((c & From::Mask) >> Sh) & To::Mask;
34   }
35
36   template< typename From, typename To >
37   static inline typename To::Value convert_comp(typename From::Value c, IT<false> const &)
38   {
39     enum { Sh = From::Shift - To::Shift + From::Size - To::Size };
40     return (((typename To::Value)(c & From::Mask)) << -Sh) & To::Mask;
41   }
42
43   template< typename From, typename To >
44   static inline typename To::Value convert_comp(typename From::Value c)
45   {
46     enum { Sh = From::Shift - To::Shift + From::Size - To::Size };
47     return convert_comp<From, To>(c, IT<(Sh > 0)>());
48   }
49
50
51   /*** Trivial pixel type with a size of a native data type and size-alignment. */
52   template< typename T >
53   class Trivial_pixel
54   {
55   private:
56     T _v; /* refernece to video memory representation */
57   public:
58     typedef T Value;
59     enum { Bpp = sizeof(T) };
60
61     Trivial_pixel() {}
62     explicit Trivial_pixel(T v) : _v(v) {}
63
64     T v() const { return _v; }
65   } __attribute__((packed));
66 }
67
68 /*** Encapsulation of properties of a pixel */
69 /* A pixel occupies the given number of bytes in video memory and
70  * has a representation in a some machine useable type (byte, short,
71  * unsigned).
72  */
73 template< int Bytes >
74 class Pixel_traits;
75
76 /*** Spezilization for 2byte */
77 template<>
78 class Pixel_traits<2>
79 {
80 public:
81   typedef _Local::Trivial_pixel<l4_uint16_t> Pixel;
82 };
83
84 /*** Spezialization for 4byte */
85 template<>
86 class Pixel_traits<4>
87 {
88 public:
89   typedef _Local::Trivial_pixel<l4_uint32_t> Pixel;
90 };
91
92
93 /*** Spezialization for 3byte */
94 template<>
95 class Pixel_traits<3>
96 {
97 public:
98   /*** Encapsulation for 3byte memory references */
99   /* Looks like a pointer to a native data type  */
100   class Pixel
101   {
102   public:
103     enum { Bpp = 3 };
104     typedef l4_uint32_t Value;
105
106   private:
107     char _b[3];
108     Value get() const 
109     { return (Value)(*(l4_uint16_t const *)_b) | ((l4_uint32_t)_b[2] << 16); }
110
111   public:
112     Pixel() {}
113
114     explicit Pixel(Value c)
115     {
116       *(l4_uint16_t*)_b = (l4_uint16_t)c;
117       _b[2] = c >> 16;
118     }
119
120     Value v() const { return get(); }
121   } __attribute__((packed));
122 };
123
124 class Factory;
125
126 struct Pixel_info : public L4Re::Video::Pixel_info
127 {
128   Factory *factory;
129
130   Pixel_info(char bytes, char r, char rs, char g, char gs,
131              char b, char bs, char a, char as)
132   : L4Re::Video::Pixel_info(bytes, r, rs, g, gs, b, bs, a, as)
133   {}
134
135   struct Color
136   {
137     int r, g, b, a;
138     Color(int r, int g, int b, int a = 0xffff) : r(r), g(g), b(b), a(a) {}
139   };
140
141   Color get(void const *d) const
142   {
143     unsigned v;
144     switch (bytes_per_pixel())
145       {
146       case 2:
147         v = *(unsigned short const *)d;
148         break;
149
150       case 3:
151       case 4:
152         v = *(unsigned const *)d;
153         break;
154
155       default:
156         v = 0;
157         break;
158       }
159     return Color(r().get(v), g().get(v), b().get(v), a().get(v));
160   }
161
162   void set(void *d, Color const &c) const
163   {
164     unsigned v = r().set(c.r) | g().set(c.g) | b().set(c.b) | a().set(c.a);
165     switch (bytes_per_pixel())
166       {
167       case 2:
168         *(unsigned short *)d = v;
169         break;
170
171       case 3:
172           {
173             char *_d = (char *)d;
174             _d[0] = v;
175             _d[1] = v >> 8; 
176             _d[2] = v >> 16; 
177             break;
178           }
179       case 4:
180         *(unsigned *)d = v;
181         break;
182
183       default:
184         break;
185       }
186   }
187 };
188
189
190 template<
191         typename PT,
192         int _Rshift, int _Rsize,
193         int _Gshift, int _Gsize,
194         int _Bshift, int _Bsize,
195         int _Ashift = 0, int _Asize = 0
196 >
197 struct Color_def
198 {
199   enum { Extra_alpha = 128 };
200   typedef typename PT::Pixel Pixel;
201   template< int _size, int _shift >
202   struct C { enum { Size = _size, Shift = _shift }; };
203
204   typedef C<_Rsize, _Rshift> R;
205   typedef C<_Gsize, _Gshift> G;
206   typedef C<_Bsize, _Bshift> B;
207   typedef C<_Asize, _Ashift> A;
208
209 };
210
211 namespace _Local {
212   template< template < class UT > class CT, typename CD, bool AC >
213   struct Alpha_traits;
214
215   template< template < class UT > class CT, typename CD >
216   struct Alpha_traits< CT, CD, true >
217   {
218     typedef CT< Color_def< Pixel_traits< CD::Pixel::Bpp >,
219             CD::R::Shift, CD::R::Size,
220             CD::G::Shift, CD::G::Size,
221             CD::B::Shift, CD::B::Size> > No_alpha;
222
223     typedef CT<CD> Alpha;
224   };
225
226   template< template < class UT > class CT, typename CD >
227   struct Alpha_traits< CT, CD, false >
228   {
229     typedef CT<CD> No_alpha;
230     typedef CT< Color_def<  Pixel_traits< CD::Pixel::Bpp >,
231             CD::R::Shift, CD::R::Size,
232             CD::G::Shift, CD::G::Size,
233             CD::B::Shift, CD::B::Size> > Alpha;
234   };
235 }
236
237 /*** Encapsulation of color bit fields of any kind */
238 /* _Pixel                 must be the Pixel for the mode.
239  * _<X>shift and _<X>size is the bit shift and number of bits used for
240  *                        each color (and alpha)
241  *
242  * Local types are:
243  *   Color   the register representation of a color.
244  *   Pixel   the reference to a pixel in video memory.
245  *   R,G,B,A the traits for the single components
246  *           (define Shift, Size, and Mask for each color component)
247  *   C_space the sorted representation of the color components,
248  *           Used to find the uppermost, middle, and lowermost component
249  *           of a pixel
250  *
251  * Static methods:
252  *   blend   does optimized alpha blending
253  */
254 template< typename CD >
255 class Color_traits
256 {
257 public:
258   class Pixel : public CD::Pixel
259   {
260   public:
261     typedef Color_traits<CD> Traits;
262
263     Pixel() {}
264
265     explicit Pixel(typename CD::Pixel::Value v)
266     : CD::Pixel(v)
267     {}
268   } __attribute__((packed));
269
270   typedef Color_traits<CD> This;
271   enum
272   {
273     Bpp = CD::Pixel::Bpp,
274     Bpp_xalpha = Bpp + (CD::A::Size == 0),
275     Need_extra_alpha = (CD::A::Size == 0)
276   };
277
278   static int bytes_per_pixel(bool alpha) { return alpha ? Bpp_xalpha : Bpp; }
279
280   template< int _Shift, int _Size, typename _C = typename CD::Pixel::Value >
281   class Component
282   {
283   public:
284     typedef _C Value;
285     enum
286     {
287       Shift = _Shift,
288       Size  = _Size,
289       Mask  = ((1UL << Size) - 1) << Shift
290     };
291
292     static unsigned get(Value c)
293     { return (c & Mask) >> Shift; }
294   };
295
296   typedef Component<CD::R::Shift, CD::R::Size> R;
297   typedef Component<CD::G::Shift, CD::G::Size> G;
298   typedef Component<CD::B::Shift, CD::B::Size> B;
299   typedef Component<CD::A::Shift, CD::A::Size> A;
300
301   /** Sorting template for color components. */
302   template<
303     typename _R,
304     typename _G,
305     typename _B,
306     bool _RG = ((unsigned)_R::Shift > (unsigned)_G::Shift),
307     bool _RB = ((unsigned)_R::Shift > (unsigned)_B::Shift),
308     bool _BG = ((unsigned)_B::Shift > (unsigned)_G::Shift)
309   >
310   class C_list;
311
312   template< typename _R, typename _G, typename _B >
313   class C_list<_R, _G, _B, true, true, true>
314   {
315   public:
316     typedef _R Msb;
317     typedef _B Mid;
318     typedef _G Lsb;
319   };
320
321   template< typename _R, typename _G, typename _B >
322   class C_list<_R, _G, _B, true, true, false>
323   {
324   public:
325     typedef _R Msb;
326     typedef _G Mid;
327     typedef _B Lsb;
328   };
329
330   template< typename _R, typename _G, typename _B >
331   class C_list<_R, _G, _B, true, false, true>
332   {
333   public:
334     typedef _B Msb;
335     typedef _R Mid;
336     typedef _G Lsb;
337   };
338
339   template< typename _R, typename _G, typename _B >
340   class C_list<_R, _G, _B, false, true, false>
341   {
342   public:
343     typedef _G Msb;
344     typedef _R Mid;
345     typedef _B Lsb;
346   };
347
348   template< typename _R, typename _G, typename _B >
349   class C_list<_R, _G, _B, false, false, false>
350   {
351   public:
352     typedef _G Msb;
353     typedef _B Mid;
354     typedef _R Lsb;
355   };
356
357   template< typename _R, typename _G, typename _B >
358   class C_list<_R, _G, _B, false, false, true>
359   {
360   public:
361     typedef _B Msb;
362     typedef _G Mid;
363     typedef _R Lsb;
364   };
365
366   class C_space : public C_list<R,G,B>
367   {
368   public:
369     enum
370     {
371       Mix_mask = (R::Mask | G::Mask | B::Mask)
372                  & ~((1UL << R::Shift) | (1UL << G::Shift) 
373                       | (1UL << B::Shift))
374     };
375   };
376
377 public:
378   typedef typename _Local::Alpha_traits<Mag_gfx::Color_traits, CD, (A::Size > 0)>::No_alpha No_alpha;
379   typedef typename _Local::Alpha_traits<Mag_gfx::Color_traits, CD, (A::Size > 0)>::Alpha Alpha;
380
381   /** Encasulation for a color value of this color mode.
382    * The Color type is an efficient native representation of the color
383    * of a pixel for this color mode.  It is designed to be kept in a
384    * machine register.
385    */
386   class Color
387   {
388   public:
389     /** The value type (native data type to carry the color value. */
390     typedef typename CD::Pixel::Value Value;
391
392     /** The info for the red component of the color. */
393     typedef typename This::R R;
394
395     /** The info for the green component of the color. */
396     typedef typename This::G G;
397
398     /** The info for the blue component of the color. */
399     typedef typename This::B B;
400
401     /** The info for the alpha channel of the color. */
402     typedef typename This::A A;
403
404     /** Reference to the surrounding color traits. */
405     typedef This Traits;
406
407     enum { Mix_mask = C_space::Mix_mask };
408     enum { Amax     = (1UL << A::Size) - 1 };
409
410   private:
411     Value _c;
412
413     static Value _m(unsigned v, int s, unsigned m)
414     {
415       if (s < 0)
416         return (v >> (-s)) & m;
417       else
418         return (v << s) & m;
419     }
420
421   public:
422
423     explicit Color(Value v) : _c(v) {}
424     Color() {}
425     Color(Pixel p) : _c(p.v()) {}
426     Color(Pixel_info::Color const &c)
427     : _c(_m(c.r, R::Shift - 16 + R::Size, R::Mask)
428         |_m(c.g, G::Shift - 16 + G::Size, G::Mask)
429         |_m(c.b, B::Shift - 16 + B::Size, B::Mask)
430         |_m(c.a, A::Shift - 16 + A::Size, A::Mask))
431     {}
432
433     Color(typename No_alpha::Color const &o)
434     : _c(o.v() | ((Value)Amax << A::Shift))
435     {}
436
437     Color(typename No_alpha::Color const &o, int a)
438     : _c(o.v() | ((Value)a << A::Shift))
439     {}
440
441     Color(int r, int g, int b, int a = Amax)
442     : _c((r << R::Shift) | (g << G::Shift) | (b << B::Shift) 
443          | ((Value)a << A::Shift))
444     {}
445
446     int r() const { return (_c & R::Mask) >> R::Shift; }
447     int g() const { return (_c & G::Mask) >> G::Shift; }
448     int b() const { return (_c & B::Mask) >> B::Shift; }
449     int a() const { return A::Size ? (_c & A::Mask) >> A::Shift : (Value)Amax; }
450
451     Value v() const { return _c; }
452     //operator Value () const { return _c; }
453     operator Pixel () const { return Pixel(_c); }
454
455     Color operator + (Color const &o) const { return Color(_c + o._c); }
456   };
457
458   /** Blend color with alpha value (0-255).
459    * \param color The original color.
460    * \param alpha The alpha value (0 = Transparent, 255 = Opaque)
461    */
462   static Color blend(Color color, int alpha)
463   {
464     enum
465     {
466       AMask = C_space::Msb::Mask | C_space::Lsb::Mask,
467       BMask = C_space::Mid::Mask,
468       Gap   = C_space::Mid::Size,
469       AAs   = 8 - Gap,
470       As    = Gap,
471       Bs    = 8
472     };
473
474     return Color(((((alpha >> AAs) * (color.v() & AMask)) >> As) & AMask)
475            | (((alpha * (color.v() & BMask)) >> Bs) & BMask));
476   }
477
478   /** Mix background and foreground color with alpha blending.
479    * \param bg The background color.
480    * \param fg the foreground color.
481    * \param alpha The alpha value of the foreground (0 = Transparent, 255 = Opaque)
482    */
483   static Color mix(Color bg, Color fg, int alpha)
484   {
485     if (alpha == 255)
486       return fg;
487     else
488       return blend(bg, 256 - alpha) + blend(fg, alpha);
489   }
490
491   /** Calculate the avarage of two colors.
492    * \param c1 The first color.
493    * \param c2 The second color.
494    * \return The average value.
495    */
496   static Color avr(Color c1, Color c2)
497   {
498     return Color(((c1.v() & Color::Mix_mask) >> 1) + ((c2.v() & Color::Mix_mask) >> 1));
499   }
500
501   /** Calculate the avarage of four colors.
502    * \param c1 The first color.
503    * \param c2 The second color.
504    * \param c3 The third color.
505    * \param c4 The fourth color.
506    * \return The average value.
507    */
508   static Color avr(Color c1, Color c2, Color c3, Color c4)
509   { return avr(avr(c1, c2), avr(c3, c4)); }
510
511   typedef Pixel_info const *Type;
512   /** Returns a pointer to the dynamic pixel info for the color mode. */
513   static Type type()
514   {
515     static Pixel_info pixel_info
516       (
517         CD::Pixel::Bpp,
518         CD::R::Size, CD::R::Shift,
519         CD::G::Size, CD::G::Shift,
520         CD::B::Size, CD::B::Shift,
521         CD::A::Size, CD::A::Shift
522       );
523
524     return &pixel_info;
525   }
526
527   /** Often used color black. */
528   static Color const Black;
529
530   /** Otfen used color White. */
531   static Color const White;
532 };
533
534
535 template< typename CD >
536 typename Color_traits<CD>::Color const Color_traits<CD>::Black(0);
537
538 template< typename CD >
539 typename Color_traits<CD>::Color const Color_traits<CD>::White(~0, ~0, ~0);
540
541
542
543 namespace _Local {
544
545   /* Provides:
546    *   convert   to convert a single color from one color space to another
547    *   blit      paints the given color to the given pixel, does color
548    *             conversion if necessary, and considers alpha values if
549    *             available
550    */
551   template< typename From, typename To >
552   class Conv
553   {
554   public:
555     typedef typename To::Color T_color;
556     typedef typename To::Pixel T_pixel;
557     typedef typename From::Color F_color;
558
559     static T_color convert(F_color c)
560     {
561       typedef typename To::R TR;
562       typedef typename To::G TG;
563       typedef typename To::B TB;
564       typedef typename From::R FR;
565       typedef typename From::G FG;
566       typedef typename From::B FB;
567       return T_color(convert_comp<FR, TR>(c.v())
568           | convert_comp<FG, TG>(c.v())
569           | convert_comp<FB, TB>(c.v()));
570     }
571
572     static void blit(F_color c, T_pixel *d)
573     {
574       if (From::A::Size > 0)
575         *d = To::blend(convert(c), From::A::get(c))
576           + To::blend(*d, 255 - From::A::get(c));
577       else
578         *d = convert(c);
579     }
580
581   };
582
583   /*** Specialized conversion if source and target color space are equal */
584   template< typename T >
585   class Conv<T,T>
586   {
587   public:
588     typedef typename T::Color T_color;
589     typedef typename T::Pixel T_pixel;
590     typedef typename T::Color F_color;
591
592     static T_color convert(F_color c) { return c; }
593     static void blit(F_color c, T_pixel *d)
594     {
595       if (T::A::Size > 0)
596         *d = T::blend(c, T::A::get(c)) + T::blend(*d, 255 - T::A::get(c));
597       else
598         *d = c;
599     }
600   };
601
602 } // _Local
603
604 template< typename C1, typename C2 >
605 C1 color_conv(C2 c)
606 { return _Local::Conv<typename C2::Traits, typename C1::Traits>::convert(c); }
607
608 template< typename C >
609 C color_50(C const &c)
610 { return C((c.v() & (typename C::Value)C::Mix_mask) >> 1); }
611
612
613 /*** Typical instances for color spaces */
614 typedef Color_traits<Color_def<Pixel_traits<2>, 10,5,5,5,0,5> >      Rgb15;
615 typedef Color_traits<Color_def<Pixel_traits<2>, 0,5,5,5,10,5> >      Bgr15;
616 typedef Color_traits<Color_def<Pixel_traits<2>, 11,5,5,6,0,5> >      Rgb16;
617 typedef Color_traits<Color_def<Pixel_traits<2>, 0,5,5,6,11,5> >      Bgr16;
618 typedef Color_traits<Color_def<Pixel_traits<3>, 16,8,8,8,0,8> >      Rgb24;
619 typedef Color_traits<Color_def<Pixel_traits<4>, 16,8,8,8,0,8> >      Rgb32;
620 typedef Color_traits<Color_def<Pixel_traits<4>, 0,8,8,8,16,8> >      Bgr32;
621 typedef Color_traits<Color_def<Pixel_traits<4>, 16,8,8,8,0,8,24,8> > Rgba32;
622
623 }