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