l4re-base-25.08.0

This commit is contained in:
2025-09-12 15:55:45 +02:00
commit d959eaab98
37938 changed files with 9382688 additions and 0 deletions

View File

@@ -0,0 +1,3 @@
Provides: mag-gfx
Requires: l4sys libstdc++-headers libc l4re
Maintainer: warg@os.inf.tu-dresden.de

View File

@@ -0,0 +1,7 @@
PKGDIR ?= .
L4DIR ?= $(PKGDIR)/../..
TARGET = include lib
include $(L4DIR)/mk/subdir.mk
lib: include

View File

@@ -0,0 +1,18 @@
PKGDIR ?= ..
L4DIR ?= $(PKGDIR)/../..
EXTRA_TARGET := \
blit \
canvas \
clip_guard \
factory \
font \
geometry \
gfx_colors \
mem_canvas \
mem_factory \
mem_texture \
texture
include $(L4DIR)/mk/include.mk

View File

@@ -0,0 +1,19 @@
// vi:ft=cpp
/*
* (c) 2010 Alexander Warg <warg@os.inf.tu-dresden.de>
* economic rights: Technische Universität Dresden (Germany)
*
* This file is part of TUD:OS and distributed under the terms of the
* GNU General Public License 2.
* Please see the COPYING-GPL-2 file for details.
*/
#pragma once
namespace Mag_gfx { namespace Blit {
void blit(void const *src, unsigned src_w,
void *dst, unsigned dst_w,
int w, int h);
}}

View File

@@ -0,0 +1,57 @@
// vi:ft=cpp
/*
* (c) 2010 Alexander Warg <warg@os.inf.tu-dresden.de>
* economic rights: Technische Universität Dresden (Germany)
*
* This file is part of TUD:OS and distributed under the terms of the
* GNU General Public License 2.
* Please see the COPYING-GPL-2 file for details.
*/
#pragma once
#include <l4/mag-gfx/geometry>
#include <l4/mag-gfx/gfx_colors>
namespace Mag_gfx {
class Font;
class Pixel_info;
class Texture;
class Canvas
{
protected:
Rect _clip;
Area _size;
Canvas(Area const &sz) : _clip(Point(0,0), sz), _size(sz) {}
virtual void flush_pixels(Rect const &) {}
public:
enum Mix_mode { Solid, Mixed, Masked, Alpha };
void set_clipping(Rect const &c)
{ _clip = Rect(Point(0,0), _size) & c; }
Rect const &clip() const { return _clip; }
bool clip_valid() const { return _clip.valid(); }
Area const &size() const { return _size; }
virtual ~Canvas() {}
virtual Pixel_info const *type() const = 0;
virtual void draw_box(Rect const &rect, Rgba32::Color color) = 0;
virtual void draw_string(Point const &pos, Font const *f, Rgba32::Color color, char const *str, unsigned len = -1) = 0;
virtual void draw_texture(Texture const *src, Rgb32::Color mix_color, Point const &pos, Mix_mode mode) = 0;
virtual void draw_texture_scaled(Texture const *src, Area const &size, Rgb32::Color mix_color, Point const &pos, Mix_mode mode) = 0;
virtual void *buffer() const = 0;
virtual void buffer(void *buffer) = 0;
virtual int bytes_per_line() const = 0;
void draw_rect(Rect const &r, Rgba32::Color color, int width = 1);
};
}

View File

@@ -0,0 +1,43 @@
// vi:ft=cpp
/*
* (c) 2010 Alexander Warg <warg@os.inf.tu-dresden.de>
* economic rights: Technische Universität Dresden (Germany)
*
* This file is part of TUD:OS and distributed under the terms of the
* GNU General Public License 2.
* Please see the COPYING-GPL-2 file for details.
*/
#pragma once
#include <l4/mag-gfx/canvas>
namespace Mag_gfx {
class Clip_guard
{
private:
Canvas *_c;
Rect _o;
Clip_guard(Clip_guard const &);
void operator = (Clip_guard const &);
public:
Clip_guard() : _c(0), _o() {}
Clip_guard(Canvas *canvas, Rect const &n)
: _c(canvas), _o(_c->clip())
{ _c->set_clipping(_o & n); }
void init(Canvas *c, Rect const &n)
{
_c = c;
_o = c->clip();
_c->set_clipping(_o & n);
}
~Clip_guard() { _c->set_clipping(_o); }
};
}

View File

@@ -0,0 +1,65 @@
// vi:ft=cpp
/*
* (c) 2010 Alexander Warg <warg@os.inf.tu-dresden.de>
* economic rights: Technische Universität Dresden (Germany)
*
* This file is part of TUD:OS and distributed under the terms of the
* GNU General Public License 2.
* Please see the COPYING-GPL-2 file for details.
*/
#pragma once
#include <l4/mag-gfx/geometry>
#include <l4/mag-gfx/gfx_colors>
namespace Mag_gfx {
class Canvas;
class Texture;
class Factory
{
public:
class Set
{
private:
Factory *_scrs[10];
public:
Factory *find(L4Re::Video::Pixel_info const &pi)
{
for (unsigned i = 0; i < sizeof(_scrs)/sizeof(_scrs[0]); ++i)
if (_scrs[i] && *_scrs[i]->pixel_info() == pi)
return _scrs[i];
return 0;
}
bool add(Factory *f)
{
for (unsigned i = 0; i < sizeof(_scrs)/sizeof(_scrs[0]); ++i)
if (!_scrs[i])
{
_scrs[i] = f;
return true;
}
return false;
}
};
static Set set;
virtual Pixel_info const *pixel_info() = 0;
virtual Canvas *create_canvas(void *pixels, Area const &size, unsigned bpl) = 0;
virtual Texture *create_texture(Area const &size, void *buffer = 0,
bool alpha = false) = 0;
virtual unsigned long get_texture_size(Area const &size,
bool alpha = false) = 0;
virtual ~Factory() {}
};
}

View File

@@ -0,0 +1,79 @@
// vi:ft=cpp
/*
* (c) 2010 Adam Lackorzynski <adam@os.inf.tu-dresden.de>,
* Alexander Warg <warg@os.inf.tu-dresden.de>
* economic rights: Technische Universität Dresden (Germany)
*
* This file is part of TUD:OS and distributed under the terms of the
* GNU General Public License 2.
* Please see the COPYING-GPL-2 file for details.
*/
#pragma once
#include <l4/sys/types.h>
#include <l4/mag-gfx/geometry>
namespace Mag_gfx {
class Font
{
public:
unsigned char const *img;
l4_int32_t const *wtab, *otab;
int w, h;
explicit Font(void const *_ttf)
{
char const *ttf = (char const *)_ttf;
otab = (l4_int32_t const *)ttf;
wtab = (l4_int32_t const *)(ttf + 1024);
w = *(l4_int32_t const *)(ttf + 2048);
h = *(l4_int32_t const *)(ttf + 2052);
img = (unsigned char const *)(ttf + 2056);
}
/**
* Calculate width of string when printed with the font
*/
int str_w(char const *_str) const
{
if (!_str)
return 0;
unsigned char const *str = (unsigned char const *)_str;
int res = 0;
for (; *str; ++str)
res += wtab[*str];
return res;
}
int str_w(char const *_str, int len) const
{
if (!_str)
return 0;
unsigned char const *str = (unsigned char const *)_str;
int res = 0;
for (; *str && len; ++str, --len)
res += wtab[*str];
return res;
}
/**
* Calculate height of string when printed with the font
*/
int str_h(char const *) const { return h; }
int str_h(char const *, int) const { return h; }
Area str_sz(char const *s) const
{ return Area(str_w(s), str_h(s)); }
Area str_sz(char const *s, int l) const
{ return Area(str_w(s, l), str_h(s, l)); }
};
}

View File

@@ -0,0 +1,342 @@
// vi:ft=cpp
/*
* (c) 2010 Alexander Warg <warg@os.inf.tu-dresden.de>
* economic rights: Technische Universität Dresden (Germany)
*
* This file is part of TUD:OS and distributed under the terms of the
* GNU General Public License 2.
* Please see the COPYING-GPL-2 file for details.
*/
#pragma once
#include <algorithm>
namespace Mag_gfx {
class Vector_2d_base
{
protected:
int _x, _y;
Vector_2d_base(int x, int y) : _x(x), _y(y) {}
};
template< typename R >
class Vector_2d : public Vector_2d_base
{
public:
Vector_2d(int x, int y) : Vector_2d_base(x, y) {}
explicit Vector_2d(Vector_2d_base const &o) : Vector_2d_base(o) {}
R operator + (R const &o) const
{ return R(_x + o._x, _y + o._y); }
R operator - (R const &o) const
{ return R(_x - o._x, _y - o._y); }
bool operator == (R const &o) const
{ return _x == o._x && _y == o._y; }
R &operator += (R const &o)
{ _x += o._x; _y += o._y; return *static_cast<R*>(this); }
R &operator -= (R const &o)
{ _x -= o._x; _y -= o._y; return *static_cast<R*>(this); }
bool operator != (R const &o) const
{ return !operator == (o); }
bool operator >= (R const &o) const
{ return _x >= o._x && _y >= o._y; }
bool operator <= (R const &o) const
{ return _x <= o._x && _y <= o._y; }
bool operator < (R const &o) const
{ return _x < o._x && _y < o._y; }
R max(R const &o) const
{ return R(std::max<int>(_x, o._x), std::max<int>(_y, o._y)); }
R min(R const &o) const
{ return R(std::min<int>(_x, o._x), std::min<int>(_y, o._y)); }
R operator / (int d) const
{ return R(_x / d, _y / d); }
R operator * (int d) const
{ return R(_x * d, _y * d); }
R operator / (R const &o) const
{ return R(_x / o._x, _y / o._y); }
R operator * (R const &o) const
{ return R(_x * o._x, _y * o._y); }
};
class Point : public Vector_2d<Point>
{
private:
typedef Vector_2d<Point> B;
public:
Point(int x, int y) : B(x, y) {}
Point() : B(0, 0) {}
explicit Point(Vector_2d_base const &o) : B(o) {}
int x() const { return _x; }
int y() const { return _y; }
void x(int x) { _x = x; }
void y(int y) { _y = y; }
};
class Area : public Vector_2d<Area>
{
private:
typedef Vector_2d<Area> B;
public:
enum { Max_w = 0x100000, Max_h = Max_w };
Area(int w, int h) : B(w, h) {}
Area() : B(0, 0) {}
int w() const { return _x; }
int h() const { return _y; }
void w(int w) { _x = w; }
void h(int h) { _y = h; }
bool valid() const { return _x > 0 && _y > 0; }
int pixels() const { return _x * _y; }
Area grow(Point const &diff) const
{ return Area(_x + diff.x(), _y + diff.y()); }
};
class Rect
{
private:
Point _p1, _p2;
public:
Rect(Point const &p1, Point const &p2) : _p1(p1), _p2(p2) {}
Rect(Point const &p1, Area const &a)
: _p1(p1), _p2(p1.x() + a.w() - 1, p1.y() + a.h() - 1)
{}
explicit Rect(Area const &a) : _p1(0, 0), _p2(a.w() - 1, a.h() - 1) {}
Rect() {}
Rect(const Rect &r) : _p1(r._p1), _p2(r._p2) {}
Rect operator = (Rect const &o) { _p1 = o._p1; _p2 = o._p2; return *this; }
bool operator == (Rect const &o) const
{ return _p1 == o._p1 && _p2 == o._p2; }
bool operator != (Rect const &o) const
{ return !operator == (o); }
Point const &p1() const { return _p1; }
Point const &p2() const { return _p2; }
int x1() const { return _p1.x(); }
int y1() const { return _p1.y(); }
int x2() const { return _p2.x(); }
int y2() const { return _p2.y(); }
void x1(int v) { _p1.x(v); }
void y1(int v) { _p1.y(v); }
void x2(int v) { _p2.x(v); }
void y2(int v) { _p2.y(v); }
int w() const { return x2() - x1() + 1; }
int h() const { return y2() - y1() + 1; }
Area area() const { return Area(w(), h()); }
bool valid() const { return x1() <= x2() && y1() <= y2(); }
bool fits(Area const &a) const { return w() >= a.w() && h() >= a.h(); }
/** intersection */
Rect operator & (Rect const &o) const
{
return Rect(Point(std::max(x1(), o.x1()), std::max(y1(), o.y1())),
Point(std::min(x2(), o.x2()), std::min(y2(), o.y2())));
}
Rect &operator &= (Rect const &o)
{
*this = *this & o;
return *this;
}
Rect operator | (Rect const &o) const
{
return Rect(Point(std::min(x1(), o.x1()), std::min(y1(), o.y1())),
Point(std::max(x2(), o.x2()), std::max(y2(), o.y2())));
}
Rect &operator |= (Rect const &o)
{
*this = *this | o;
return *this;
}
Rect grow(int x) const
{ return Rect(Point(x1() - x, y1() - x), Point(x2() + x, y2() + x)); }
Rect top(int h) const
{
Rect n = *this;
n._p2 = Point(_p2.x(), _p1.y() + h - 1);
return n;
}
Rect left(int w) const
{
Rect n = *this;
n._p2 = Point(_p1.x() + w - 1, _p2.y());
return n;
}
Rect bottom(int h) const
{
Rect n = *this;
n._p1 = Point(_p1.x(), _p2.y() - h + 1);
return n;
}
Rect right(int w) const
{
Rect n = *this;
n._p1 = Point(_p2.x() - w + 1, _p1.y());
return n;
}
Rect offset(int _x1, int _y1, int _x2, int _y2) const
{ return Rect(Point(x1() + _x1, y1() + _y1), Point(x2() + _x2, y2() + _y2)); }
Point center(Area const &a) const
{ return Point((w() - a.w()) / 2, (h() - a.h()) / 2); }
bool contains(Point const &p) const
{ return p >= p1() && p <= p2(); }
bool contains(Rect const &o) const
{ return x1() <= o.x1() && y1() <= o.y1() && x2() >= o.x2() && y2() >= o.y2(); }
Rect operator - (Point const &p) const
{ return Rect(p1() - p, p2() - p); }
Rect operator + (Point const &p) const
{ return Rect(p1() + p, p2() + p); }
Rect &operator += (Point const &p)
{ _p1 += p; _p2 += p; return *this; }
Rect &operator -= (Point const &p)
{ _p1 -= p; _p2 -= p; return *this; }
Rect move_to(Point const &p1) const
{ return Rect(p1, area()); }
bool overlaps(Rect const &o) const
{
return o.x2() >= x1() && o.x1() <= x2()
&& o.y2() >= y1() && o.y1() <= y2();
}
};
struct Rect_tuple
{
Rect _r[4];
Rect_tuple() {}
Rect_tuple(Rect const &t, Rect const &l, Rect const &r, Rect const &b)
{ _r[0] = t; _r[1] = l; _r[2] = r; _r[3] = b; }
Rect const &operator [] (unsigned i) const { return _r[i]; }
Rect const &t() const { return _r[0]; }
Rect const &l() const { return _r[1]; }
Rect const &r() const { return _r[2]; }
Rect const &b() const { return _r[3]; }
};
inline
Rect_tuple operator - (Rect const &lh, Rect const &rh)
{
Rect re = rh & lh;
return Rect_tuple(
Rect(Point(lh.x1(), lh.y1()), Point(lh.x2(), re.y1() - 1)),
Rect(Point(lh.x1(), re.y1()), Point(re.x1() - 1, re.y2())),
Rect(Point(re.x2() + 1, re.y1()), Point(lh.x2(), re.y2())),
Rect(Point(lh.x1(), re.y2() + 1), Point(lh.x2(), lh.y2())));
}
template< typename E >
class Flags
{
private:
unsigned _v;
Flags(unsigned v, bool) : _v(v) {}
struct Private_bool;
public:
typedef E Enum;
Flags(int z = 0) : _v(z) {} //Private_bool const * = 0) : _v(0) {}
Flags(E e) : _v(e) {}
Flags(Flags const &o) : _v(o._v) {}
operator Private_bool * () const { return (Private_bool *)(long)_v; }
bool operator ! () const { return !_v; }
Flags operator | (Flags const &o) const { return Flags(_v | o._v, true); }
Flags operator | (Enum e) const { return Flags(_v | (unsigned)e, true); }
Flags &operator |= (Flags const &o) { _v |= o._v; return *this; }
Flags &operator |= (Enum e) { _v |= (unsigned)e; return *this; }
Flags operator & (Flags const &o) const { return Flags(_v & o._v, true); }
Flags operator & (Enum e) const { return Flags(_v & (unsigned)e, true); }
Flags &operator &= (Flags const &o) { _v &= o._v; return *this; }
Flags &operator &= (Enum e) { _v &= (unsigned)e; return *this; }
Flags operator ~ () const { return Flags(~_v, true); }
Flags &operator = (Flags const &o) { _v = o._v; return *this; }
unsigned value() const { return _v; }
};
enum Orientation
{
Horizontal = 0x1,
Horz = Horizontal,
Vertical = 0x2,
Vert = Vertical,
};
typedef Flags<Orientation> Orientations;
enum Alignment_flag
{
Align_left = 0x0001,
Align_right = 0x0002,
Align_h_center = 0x0004,
Align_justify = 0x0008,
Align_horizontal_m = Align_left | Align_right | Align_h_center,
Align_top = 0x0020,
Align_bottom = 0x0040,
Align_v_center = 0x0080,
Align_vertical_m = Align_top | Align_bottom | Align_v_center,
Align_center = Align_h_center | Align_v_center,
};
typedef Flags<Alignment_flag> Alignment;
}

View File

@@ -0,0 +1,633 @@
// vi:ft=cpp
/*
* (c) 2010 Alexander Warg <warg@os.inf.tu-dresden.de>
* economic rights: Technische Universität Dresden (Germany)
*
* This file is part of TUD:OS and distributed under the terms of the
* GNU General Public License 2.
* Please see the COPYING-GPL-2 file for details.
*/
#pragma once
#include <l4/sys/types.h>
#include <l4/re/video/colors>
namespace Mag_gfx
{
/*** PRIVATE Murx */
namespace _Local
{
/*** int-to-type template */
template< int X >
class IT
{};
/*** Conversion for a single color component */
template< typename From, typename To >
static inline typename To::Value convert_comp(typename From::Value c, IT<true> const &)
{
enum { Sh = From::Shift - To::Shift + From::Size - To::Size };
return ((c & From::Mask) >> Sh) & To::Mask;
}
template< typename From, typename To >
static inline typename To::Value convert_comp(typename From::Value c, IT<false> const &)
{
enum { Sh = From::Shift - To::Shift + From::Size - To::Size };
return (((typename To::Value)(c & From::Mask)) << -Sh) & To::Mask;
}
template< typename From, typename To >
static inline typename To::Value convert_comp(typename From::Value c)
{
enum { Sh = From::Shift - To::Shift + From::Size - To::Size };
return convert_comp<From, To>(c, IT<(Sh > 0)>());
}
/*** Trivial pixel type with a size of a native data type and size-alignment. */
template< typename T >
class Trivial_pixel
{
private:
T _v; /* refernece to video memory representation */
public:
typedef T Value;
enum { Bpp = sizeof(T) };
Trivial_pixel() {}
explicit Trivial_pixel(T v) : _v(v) {}
T v() const { return _v; }
} __attribute__((packed));
}
/*** Encapsulation of properties of a pixel */
/* A pixel occupies the given number of bytes in video memory and
* has a representation in a some machine useable type (byte, short,
* unsigned).
*/
template< int Bytes >
class Pixel_traits;
/*** Spezilization for 2byte */
template<>
class Pixel_traits<2>
{
public:
typedef _Local::Trivial_pixel<l4_uint16_t> Pixel;
};
/*** Spezialization for 4byte */
template<>
class Pixel_traits<4>
{
public:
typedef _Local::Trivial_pixel<l4_uint32_t> Pixel;
};
/*** Spezialization for 3byte */
template<>
class Pixel_traits<3>
{
public:
/*** Encapsulation for 3byte memory references */
/* Looks like a pointer to a native data type */
class Pixel
{
public:
enum { Bpp = 3 };
typedef l4_uint32_t Value;
private:
struct Data
{
l4_uint16_t s;
char b;
} __attribute__((packed));
Data _d;
Value get() const
{ return (Value)(_d.s) | ((l4_uint32_t)_d.b << 16); }
public:
Pixel() {}
explicit Pixel(Value c)
{
_d.s = (l4_uint16_t)c;
_d.b = c >> 16;
}
Value v() const { return get(); }
} __attribute__((packed));
};
class Factory;
class Pixel_info : public L4Re::Video::Pixel_info
{
public:
Factory *factory;
Pixel_info(char bytes, char r, char rs, char g, char gs,
char b, char bs, char a, char as)
: L4Re::Video::Pixel_info(bytes, r, rs, g, gs, b, bs, a, as)
{}
struct Color
{
int r, g, b, a;
Color(int r, int g, int b, int a = 0xffff) : r(r), g(g), b(b), a(a) {}
};
Color get(void const *d) const
{
unsigned v;
switch (bytes_per_pixel())
{
case 2:
v = *(unsigned short const *)d;
break;
case 3:
case 4:
v = *(unsigned const *)d;
break;
default:
v = 0;
break;
}
return Color(r().get(v), g().get(v), b().get(v), a().get(v));
}
void set(void *d, Color const &c) const
{
unsigned v = r().set(c.r) | g().set(c.g) | b().set(c.b) | a().set(c.a);
switch (bytes_per_pixel())
{
case 2:
*(unsigned short *)d = v;
break;
case 3:
{
char *_d = (char *)d;
_d[0] = v;
_d[1] = v >> 8;
_d[2] = v >> 16;
break;
}
case 4:
*(unsigned *)d = v;
break;
default:
break;
}
}
};
template<
typename PT,
int _Rshift, int _Rsize,
int _Gshift, int _Gsize,
int _Bshift, int _Bsize,
int _Ashift = 0, int _Asize = 0
>
struct Color_def
{
enum { Extra_alpha = 128 };
typedef typename PT::Pixel Pixel;
template< int _size, int _shift >
struct C { enum { Size = _size, Shift = _shift }; };
typedef C<_Rsize, _Rshift> R;
typedef C<_Gsize, _Gshift> G;
typedef C<_Bsize, _Bshift> B;
typedef C<_Asize, _Ashift> A;
};
namespace _Local {
template< template < class UT > class CT, typename CD, bool AC >
struct Alpha_traits;
template< template < class UT > class CT, typename CD >
struct Alpha_traits< CT, CD, true >
{
typedef CT< Color_def< Pixel_traits< CD::Pixel::Bpp >,
CD::R::Shift, CD::R::Size,
CD::G::Shift, CD::G::Size,
CD::B::Shift, CD::B::Size> > No_alpha;
typedef CT<CD> Alpha;
};
template< template < class UT > class CT, typename CD >
struct Alpha_traits< CT, CD, false >
{
typedef CT<CD> No_alpha;
typedef CT< Color_def< Pixel_traits< CD::Pixel::Bpp >,
CD::R::Shift, CD::R::Size,
CD::G::Shift, CD::G::Size,
CD::B::Shift, CD::B::Size> > Alpha;
};
}
/*** Encapsulation of color bit fields of any kind */
/* _Pixel must be the Pixel for the mode.
* _<X>shift and _<X>size is the bit shift and number of bits used for
* each color (and alpha)
*
* Local types are:
* Color the register representation of a color.
* Pixel the reference to a pixel in video memory.
* R,G,B,A the traits for the single components
* (define Shift, Size, and Mask for each color component)
* C_space the sorted representation of the color components,
* Used to find the uppermost, middle, and lowermost component
* of a pixel
*
* Static methods:
* blend does optimized alpha blending
*/
template< typename CD >
class Color_traits
{
public:
class Pixel : public CD::Pixel
{
public:
typedef Color_traits<CD> Traits;
Pixel() {}
explicit Pixel(typename CD::Pixel::Value v)
: CD::Pixel(v)
{}
} __attribute__((packed));
typedef Color_traits<CD> This;
enum
{
Bpp = CD::Pixel::Bpp,
Bpp_xalpha = Bpp + (CD::A::Size == 0),
Need_extra_alpha = (CD::A::Size == 0)
};
static int bytes_per_pixel(bool alpha) { return alpha ? Bpp_xalpha : Bpp; }
template< int _Shift, int _Size, typename _C = typename CD::Pixel::Value >
class Component
{
public:
typedef _C Value;
enum
{
Shift = _Shift,
Size = _Size,
Mask = ((1UL << Size) - 1) << Shift
};
static unsigned get(Value c)
{ return (c & Mask) >> Shift; }
};
typedef Component<CD::R::Shift, CD::R::Size> R;
typedef Component<CD::G::Shift, CD::G::Size> G;
typedef Component<CD::B::Shift, CD::B::Size> B;
typedef Component<CD::A::Shift, CD::A::Size> A;
/** Sorting template for color components. */
template<
typename _R,
typename _G,
typename _B,
bool _RG = ((unsigned)_R::Shift > (unsigned)_G::Shift),
bool _RB = ((unsigned)_R::Shift > (unsigned)_B::Shift),
bool _BG = ((unsigned)_B::Shift > (unsigned)_G::Shift)
>
class C_list;
template< typename _R, typename _G, typename _B >
class C_list<_R, _G, _B, true, true, true>
{
public:
typedef _R Msb;
typedef _B Mid;
typedef _G Lsb;
};
template< typename _R, typename _G, typename _B >
class C_list<_R, _G, _B, true, true, false>
{
public:
typedef _R Msb;
typedef _G Mid;
typedef _B Lsb;
};
template< typename _R, typename _G, typename _B >
class C_list<_R, _G, _B, true, false, true>
{
public:
typedef _B Msb;
typedef _R Mid;
typedef _G Lsb;
};
template< typename _R, typename _G, typename _B >
class C_list<_R, _G, _B, false, true, false>
{
public:
typedef _G Msb;
typedef _R Mid;
typedef _B Lsb;
};
template< typename _R, typename _G, typename _B >
class C_list<_R, _G, _B, false, false, false>
{
public:
typedef _G Msb;
typedef _B Mid;
typedef _R Lsb;
};
template< typename _R, typename _G, typename _B >
class C_list<_R, _G, _B, false, false, true>
{
public:
typedef _B Msb;
typedef _G Mid;
typedef _R Lsb;
};
class C_space : public C_list<R,G,B>
{
public:
enum
{
Mix_mask = (R::Mask | G::Mask | B::Mask)
& ~((1UL << R::Shift) | (1UL << G::Shift)
| (1UL << B::Shift))
};
};
public:
typedef typename _Local::Alpha_traits<Mag_gfx::Color_traits, CD, (A::Size > 0)>::No_alpha No_alpha;
typedef typename _Local::Alpha_traits<Mag_gfx::Color_traits, CD, (A::Size > 0)>::Alpha Alpha;
/** Encasulation for a color value of this color mode.
* The Color type is an efficient native representation of the color
* of a pixel for this color mode. It is designed to be kept in a
* machine register.
*/
class Color
{
public:
/** The value type (native data type to carry the color value. */
typedef typename CD::Pixel::Value Value;
/** The info for the red component of the color. */
typedef typename This::R R;
/** The info for the green component of the color. */
typedef typename This::G G;
/** The info for the blue component of the color. */
typedef typename This::B B;
/** The info for the alpha channel of the color. */
typedef typename This::A A;
/** Reference to the surrounding color traits. */
typedef This Traits;
enum { Mix_mask = C_space::Mix_mask };
enum { Amax = (1UL << A::Size) - 1 };
private:
Value _c;
static Value _m(unsigned v, int s, unsigned m)
{
if (s < 0)
return (v >> (-s)) & m;
else
return (v << s) & m;
}
public:
explicit Color(Value v) : _c(v) {}
Color() {}
Color(Pixel p) : _c(p.v()) {}
Color(Pixel_info::Color const &c)
: _c(_m(c.r, R::Shift - 16 + R::Size, R::Mask)
|_m(c.g, G::Shift - 16 + G::Size, G::Mask)
|_m(c.b, B::Shift - 16 + B::Size, B::Mask)
|_m(c.a, A::Shift - 16 + A::Size, A::Mask))
{}
Color(typename No_alpha::Color const &o)
: _c(o.v() | ((Value)Amax << A::Shift))
{}
Color(typename No_alpha::Color const &o, int a)
: _c(o.v() | ((Value)a << A::Shift))
{}
Color(int r, int g, int b, int a = Amax)
: _c((r << R::Shift) | (g << G::Shift) | (b << B::Shift)
| ((Value)a << A::Shift))
{}
int r() const { return (_c & R::Mask) >> R::Shift; }
int g() const { return (_c & G::Mask) >> G::Shift; }
int b() const { return (_c & B::Mask) >> B::Shift; }
int a() const
{ return A::Size != 0 ? (_c & A::Mask) >> A::Shift : (Value)Amax; }
Value v() const { return _c; }
//operator Value () const { return _c; }
operator Pixel () const { return Pixel(_c); }
Color operator + (Color const &o) const { return Color(_c + o._c); }
Color &operator =(const Color &) = default;
};
/** Blend color with alpha value (0-255).
* \param color The original color.
* \param alpha The alpha value (0 = Transparent, 255 = Opaque)
*/
static Color blend(Color color, int alpha)
{
enum
{
AMask = C_space::Msb::Mask | C_space::Lsb::Mask,
BMask = C_space::Mid::Mask,
Gap = C_space::Mid::Size,
AAs = 8 - Gap,
As = Gap,
Bs = 8
};
return Color(((((alpha >> AAs) * (color.v() & AMask)) >> As) & AMask)
| (((alpha * (color.v() & BMask)) >> Bs) & BMask));
}
/** Mix background and foreground color with alpha blending.
* \param bg The background color.
* \param fg the foreground color.
* \param alpha The alpha value of the foreground (0 = Transparent, 255 = Opaque)
*/
static Color mix(Color bg, Color fg, int alpha)
{
if (alpha == 255)
return fg;
else
return blend(bg, 256 - alpha) + blend(fg, alpha);
}
/** Calculate the avarage of two colors.
* \param c1 The first color.
* \param c2 The second color.
* \return The average value.
*/
static Color avr(Color c1, Color c2)
{
return Color(((c1.v() & Color::Mix_mask) >> 1) + ((c2.v() & Color::Mix_mask) >> 1));
}
/** Calculate the avarage of four colors.
* \param c1 The first color.
* \param c2 The second color.
* \param c3 The third color.
* \param c4 The fourth color.
* \return The average value.
*/
static Color avr(Color c1, Color c2, Color c3, Color c4)
{ return avr(avr(c1, c2), avr(c3, c4)); }
typedef Pixel_info const *Type;
/** Returns a pointer to the dynamic pixel info for the color mode. */
static Type type()
{
static Pixel_info pixel_info
(
CD::Pixel::Bpp,
CD::R::Size, CD::R::Shift,
CD::G::Size, CD::G::Shift,
CD::B::Size, CD::B::Shift,
CD::A::Size, CD::A::Shift
);
return &pixel_info;
}
/** Often used color black. */
static Color const Black;
/** Otfen used color White. */
static Color const White;
};
template< typename CD >
typename Color_traits<CD>::Color const Color_traits<CD>::Black(0);
template< typename CD >
typename Color_traits<CD>::Color const Color_traits<CD>::White(~0, ~0, ~0);
namespace _Local {
/* Provides:
* convert to convert a single color from one color space to another
* blit paints the given color to the given pixel, does color
* conversion if necessary, and considers alpha values if
* available
*/
template< typename From, typename To >
class Conv
{
public:
typedef typename To::Color T_color;
typedef typename To::Pixel T_pixel;
typedef typename From::Color F_color;
static T_color convert(F_color c)
{
typedef typename To::R TR;
typedef typename To::G TG;
typedef typename To::B TB;
typedef typename From::R FR;
typedef typename From::G FG;
typedef typename From::B FB;
return T_color(convert_comp<FR, TR>(c.v())
| convert_comp<FG, TG>(c.v())
| convert_comp<FB, TB>(c.v()));
}
static void blit(F_color c, T_pixel *d)
{
if (From::A::Size > 0)
*d = To::blend(convert(c), From::A::get(c))
+ To::blend(*d, 255 - From::A::get(c));
else
*d = convert(c);
}
};
/*** Specialized conversion if source and target color space are equal */
template< typename T >
class Conv<T,T>
{
public:
typedef typename T::Color T_color;
typedef typename T::Pixel T_pixel;
typedef typename T::Color F_color;
static T_color convert(F_color c) { return c; }
static void blit(F_color c, T_pixel *d)
{
if (T::A::Size > 0)
*d = T::blend(c, T::A::get(c)) + T::blend(*d, 255 - T::A::get(c));
else
*d = c;
}
};
} // _Local
template< typename C1, typename C2 >
C1 color_conv(C2 c)
{ return _Local::Conv<typename C2::Traits, typename C1::Traits>::convert(c); }
template< typename C >
C color_50(C const &c)
{ return C((c.v() & (typename C::Value)C::Mix_mask) >> 1); }
/*** Typical instances for color spaces */
typedef Color_traits<Color_def<Pixel_traits<2>, 10,5,5,5,0,5> > Rgb15;
typedef Color_traits<Color_def<Pixel_traits<2>, 0,5,5,5,10,5> > Bgr15;
typedef Color_traits<Color_def<Pixel_traits<2>, 11,5,5,6,0,5> > Rgb16;
typedef Color_traits<Color_def<Pixel_traits<2>, 0,5,5,6,11,5> > Bgr16;
typedef Color_traits<Color_def<Pixel_traits<3>, 16,8,8,8,0,8> > Rgb24;
typedef Color_traits<Color_def<Pixel_traits<4>, 16,8,8,8,0,8> > Rgb32;
typedef Color_traits<Color_def<Pixel_traits<4>, 0,8,8,8,16,8> > Bgr32;
typedef Color_traits<Color_def<Pixel_traits<4>, 16,8,8,8,0,8,24,8> > Rgba32;
}

View File

@@ -0,0 +1,451 @@
// vi:ft=cpp
/*
* (c) 2010 Alexander Warg <warg@os.inf.tu-dresden.de>
* economic rights: Technische Universität Dresden (Germany)
*
* This file is part of TUD:OS and distributed under the terms of the
* GNU General Public License 2.
* Please see the COPYING-GPL-2 file for details.
*/
#pragma once
#include <l4/mag-gfx/canvas>
#include <l4/mag-gfx/mem_texture>
#include <l4/mag-gfx/font>
#include <l4/mag-gfx/blit>
namespace Mag_gfx {
namespace Mem {
template< typename PT >
class Canvas : public Mag_gfx::Canvas
{
public:
typedef PT Pixel_traits;
typedef typename PT::Pixel Pixel;
typedef typename PT::Color Color;
private:
char *_pixels;
Pixel_info const *_type;
int _bpl;
public:
Canvas(void *pixels, Area const &size, unsigned bpl)
: Mag_gfx::Canvas(size), _pixels((char *)pixels), _type(PT::type()), _bpl(bpl)
{}
Pixel_info const *type() const { return _type; }
void *buffer() const { return _pixels; }
void buffer(void *buf) { _pixels = (char *)buf; }
int bytes_per_line() const { return _bpl; }
private:
template< typename CT >
void _draw_box(char *dst_line, int _w, int h, CT color, int a);
template< typename CT >
void __draw_string(Point const &p, Font const *font,
typename CT::Color color,
char const *_str, unsigned len);
bool _draw_alpha_texture(Texture<Pixel_traits> const *texture,
Pixel const *src, char *dst, int offset,
int h, int w, int src_w);
public:
void draw_box(Rect const &rect, Rgba32::Color color)
{
Rect const clipped = _clip & rect;
if (!clipped.valid() || color.a() == 0)
return;
char *dst_line = _pixels + _bpl*clipped.y1() + sizeof(Pixel)*clipped.x1();
if (color.a() >= 255)
_draw_box(dst_line, clipped.w(), clipped.h(), Rgb32::Color(color.v()), 0);
else
_draw_box(dst_line, clipped.w(), clipped.h(), color, color.a());
flush_pixels(clipped);
}
void draw_string(Point const &p, Font const *font, Rgba32::Color color,
char const *_str, unsigned len)
{
if (color.a() != Rgba32::Color::Amax)
__draw_string<Rgba32>(p, font, color, _str, len);
else
__draw_string<Rgb32>(p, font, Rgb32::Color(color.v()), _str, len);
}
void draw_texture(Mag_gfx::Texture const *texture, Rgb32::Color mix_color,
Point const &pos, Mix_mode mode);
void draw_texture_scaled(Mag_gfx::Texture const *texture, Area const &size,
Rgb32::Color mix_color, Point const &pos,
Mix_mode mode);
};
template< typename PT>
template< typename CT >
void
Canvas<PT>::_draw_box(char *dst_line, int _w, int h, CT color, int a)
{
Color const c = color_conv<Color>(color);
for (; h--; dst_line += _bpl)
{
int w;
Pixel *dst = reinterpret_cast<Pixel*>(dst_line);
for (w = _w; w--; dst++)
if (CT::A::Size == 0)
*dst = c;
else
*dst = Color::Traits::mix(*dst, c, a);
}
}
template< typename PT>
template< typename CT >
void
Canvas<PT>::__draw_string(Point const &p, Font const *font,
typename CT::Color color,
char const *_str, unsigned len)
{
enum { Alphas = CT::A::Size };
const unsigned char *str = (const unsigned char *)_str;
int x = p.x(), y = p.y();
if (!str || !font)
return;
unsigned char const *src = font->img;
int d, h = font->str_h(_str);
/* check top clipping */
if ((d = _clip.y1() - y) > 0)
{
src += d * font->w;
y += d;
h -= d;
}
/* check bottom clipping */
if ((d = y + h - 1 - _clip.y2()) > 0)
h -= d;
if (h < 1)
return;
/* skip hidden glyphs */
for ( ; *str && len && (x + font->wtab[*str] < _clip.x1()); --len)
x += font->wtab[*str++];
int x_start = x;
char *dst = _pixels + y * _bpl;
Color pix = color_conv<Color>(color);
int alpha = 255;
if (Alphas != 0)
alpha = color.a() << (8 - Alphas);
/* draw glyphs */
for ( ; *str && len && (x <= _clip.x2()); ++str, --len)
{
int w = font->wtab[*str];
int start = std::max(0, _clip.x1() - x);
int end = std::min(w - 1, _clip.x2() - x);
char *d = dst + x * sizeof(Pixel);
unsigned char const *s = src + font->otab[*str];
for (int j = 0; j < h; ++j, s += font->w, d += _bpl)
for (int i = start; i <= end; ++i)
if (s[i])
{
Pixel *p = reinterpret_cast<Pixel *>(d) + i;
*p = Pixel_traits::mix(*p, pix, (alpha * s[i]) >> 8);
}
x += w;
}
flush_pixels(Rect(Point(x_start, y), Area(x - x_start + 1, h)));
}
template<typename PT>
bool
Canvas<PT>::_draw_alpha_texture(Texture<Pixel_traits> const *texture,
Pixel const *src, char *dst, int offset,
int h, int w, int src_w)
{
typedef typename Pixel_traits::Pixel Pixel;
bool xa = Pixel_traits::A::Size == 0 && texture->extra_alpha();
if (!xa && Pixel_traits::A::Size == 0)
return false;
unsigned char const *ab;
if (xa)
ab = texture->alpha_buffer() + offset;
for (int j = h; j--; src += src_w, dst += _bpl)
{
Pixel *dp = reinterpret_cast<Pixel*>(dst);
Pixel const *s = src;
unsigned char const *sab = ab;
for (int i = w; i--; ++s, ++dp)
{
int alpha;
if (!xa)
alpha = Color(*s).a() << (8 - Pixel_traits::A::Size);
else
alpha = *sab++;
if (alpha < 255)
*dp = Pixel_traits::mix(*dp, *s, alpha);
else if (alpha > 0)
*dp = *s;
}
if (xa)
ab += src_w;
}
return true;
}
template<typename PT>
void
Canvas<PT>::draw_texture(Mag_gfx::Texture const *texture,
Rgb32::Color mix_color, Point const &pos,
Mix_mode mode)
{
Rect const clipped = _clip & Rect(pos, texture->size());
if (!clipped.valid())
return;
int src_w = texture->size().w();
Texture<Pixel_traits> const *txt;
txt = static_cast<Texture<Pixel_traits> const *>(texture);
Pixel const *src = txt->pixels()
+ (clipped.y1() - pos.y()) * src_w
+ clipped.x1() - pos.x();
char *dst = _pixels + clipped.y1() * _bpl + clipped.x1() * sizeof(Pixel);
char *d;
int i, j;
Pixel const *s;
Color mix_pixel = color_conv<Color>(mix_color);
switch (mode)
{
case Alpha:
if (_draw_alpha_texture(txt, src, dst,
(clipped.y1() - pos.y()) * src_w + clipped.x1() - pos.x(),
clipped.h(), clipped.w(), src_w))
break;
// Fall through to solid!
/* FALLTHRU */
case Solid:
// for (j = clipped.h(); j--; src += src_w, dst += _bpl)
// for (i = clipped.w(), s = src, d = dst; i--; ++s, d += sizeof(Pixel))
// *reinterpret_cast<Pixel*>(d) = *s;
Blit::blit(src, src_w * sizeof(Pixel),
dst, _bpl, clipped.w() * sizeof(Pixel), clipped.h());
break;
case Mixed:
mix_pixel = color_50(mix_pixel);
for (j = clipped.h(); j--; src += src_w, dst += _bpl)
for (i = clipped.w(), s = src, d = dst; i--; ++s, d += sizeof(Pixel))
*reinterpret_cast<Pixel*>(d) = color_50(Color(*s)) + mix_pixel;
break;
case Masked:
for (j = clipped.h(); j--; src += src_w, dst += _bpl)
for (i = clipped.w(), s = src, d = dst; i--; ++s, d += sizeof(Pixel))
if (s->v())
*reinterpret_cast<Pixel*>(d) = *s;
break;
}
flush_pixels(clipped);
}
template< typename Pixel, typename Op >
inline
void
draw_loop(Area const &area, unsigned const *cb, unsigned const *rb,
unsigned bpl,
char const *src, char *dst, Op const &op)
{
char const *s;
char *d;
int i, j;
for (j = area.h(); j--; dst += bpl)
for (i = area.w(), s = src + rb[j], d = dst; i--; d += sizeof(Pixel))
op(reinterpret_cast<Pixel*>(d), reinterpret_cast<Pixel const *>(s + cb[i]));
}
namespace {
static inline void
calc_xscale_buffer(unsigned dx, unsigned dy, unsigned s, unsigned w, unsigned sbpp, unsigned *sb)
{
int f = dx / 2;
unsigned y = 0;
unsigned x = 0;
for (x = 0; x < s; ++x)
{
f = f - dy;
if (f < 0)
{
y += sbpp;
f = f + dx;
}
}
for (x = w; x--;)
{
f = f - dy;
sb[x] = y;
if (f < 0)
{
y += sbpp;
f = f + dx;
}
}
}
static inline void
calc_yscale_buffer(unsigned dx, unsigned dy, unsigned s, unsigned w, unsigned sbpp, unsigned *sb)
{
int f = dx / 2;
unsigned y = 0;
unsigned x = 0;
unsigned xv = 0;
for (x = 0; y < s && x < dx; ++x)
{
f = f - dy;
if (f < 0)
{
f = f + dx;
if (y >= s)
break;
++y;
}
xv += sbpp;
}
y = w - 1;
sb[y] = xv;
if (!y)
return;
for (;x < dx; ++x)
{
f = f - dy;
if (f < 0)
{
f = f + dx;
--y;
sb[y] = xv;
if (y == 0)
return;
}
xv += sbpp;
}
}
template< typename Pixel >
struct Solid_copy
{ void operator () (Pixel *d, Pixel const *s) const { *d = *s; } };
template< typename Pixel, typename Color >
struct Mix_50_copy
{
Color mix_pixel;
Mix_50_copy(Rgb32::Color mix_color)
: mix_pixel(color_conv<Color>(mix_color))
{}
void operator () (Pixel *d, Pixel const *s) const
{ *d = color_50(Color(*s)) + mix_pixel; }
};
template< typename Pixel >
struct Masked_copy
{
void operator () (Pixel *d, Pixel const *s) const
{
if (s->v()) *d = *s;
}
};
}
template<typename PT>
void
Canvas<PT>::draw_texture_scaled(Mag_gfx::Texture const *texture,
Area const &size,
Rgb32::Color mix_color, Point const &pos,
Mix_mode mode)
{
Rect const clipped = _clip & Rect(pos, size); //texture->size());
if (!clipped.valid())
return;
Point tl_offs = clipped.p1() - pos;
unsigned *col_buf = (unsigned*)alloca(sizeof(unsigned) * clipped.w());
unsigned *row_buf = (unsigned*)alloca(sizeof(unsigned) * clipped.h());
Area ts = texture->size();
if (size.w() > ts.w())
calc_xscale_buffer(size.w(), ts.w(), tl_offs.x(), clipped.w(), sizeof(Pixel), col_buf);
else
calc_yscale_buffer(ts.w(), size.w(), tl_offs.x(), clipped.w(), sizeof(Pixel), col_buf);
if (size.h() > ts.h())
calc_xscale_buffer(size.h(), ts.h(), tl_offs.y(), clipped.h(), ts.w() * sizeof(Pixel), row_buf);
else
calc_yscale_buffer(ts.h(), size.h(), tl_offs.y(), clipped.h(), ts.w() * sizeof(Pixel), row_buf);
char const *src = (char const *)texture->pixels();
char *dst = _pixels + clipped.y1() * _bpl + clipped.x1() * sizeof(Pixel);
Mix_50_copy<Pixel, Color> mix_copy(mix_color);
switch (mode)
{
case Alpha:
#if 0
if (_draw_alpha_texture(txt, src, dst,
(clipped.y1() - pos.y()) * src_w + clipped.x1() - pos.x(),
clipped.h(), clipped.w(), src_w))
break;
#endif
// Fall through to solid!
case Solid:
draw_loop<Pixel>(clipped.area(), col_buf, row_buf, _bpl, src, dst, Solid_copy<Pixel>());
break;
case Mixed:
draw_loop<Pixel>(clipped.area(), col_buf, row_buf, _bpl, src, dst, mix_copy);
break;
case Masked:
draw_loop<Pixel>(clipped.area(), col_buf, row_buf, _bpl, src, dst, Masked_copy<Pixel>());
break;
}
flush_pixels(clipped);
}
}}

View File

@@ -0,0 +1,60 @@
// vi:ft=cpp
/*
* (c) 2010 Alexander Warg <warg@os.inf.tu-dresden.de>
* economic rights: Technische Universität Dresden (Germany)
*
* This file is part of TUD:OS and distributed under the terms of the
* GNU General Public License 2.
* Please see the COPYING-GPL-2 file for details.
*/
#pragma once
#include <l4/mag-gfx/factory>
#include <l4/mag-gfx/mem_canvas>
#include <l4/mag-gfx/mem_texture>
namespace Mag_gfx {
namespace Mem {
template< typename Pixel_traits >
class Factory : public virtual Mag_gfx::Factory
{
private:
Pixel_info const *_pi;
public:
typedef typename Pixel_traits::R R;
typedef typename Pixel_traits::G G;
typedef typename Pixel_traits::B B;
typedef typename Pixel_traits::A A;
Pixel_info const *pixel_info() { return _pi; }
Factory() : _pi(Pixel_traits::type())
{
const_cast<Pixel_info *>(Pixel_traits::type())->factory = this;
set.add(this);
}
Mag_gfx::Canvas *create_canvas(void *pixels, Area const &size, unsigned bpl)
{ return new Canvas<Pixel_traits>(pixels, size, bpl); }
Mag_gfx::Texture *create_texture(Area const &size, void *buffer,
bool alpha = false)
{
typedef typename Pixel_traits::Pixel Pixel;
alpha &= Pixel_traits::Need_extra_alpha;
Pixel *b = (Pixel*)buffer;
if (!b)
b = (Pixel*)malloc(size.pixels() * Pixel_traits::bytes_per_pixel(alpha));
return new Texture<Pixel_traits>(b, size, alpha);
}
unsigned long get_texture_size(Area const &sz, bool alpha = false)
{
alpha &= Pixel_traits::Need_extra_alpha;
return sz.pixels() * Pixel_traits::bytes_per_pixel(alpha);
}
};
}}

View File

@@ -0,0 +1,171 @@
// vi:ft=cpp
/*
* (c) 2010 Alexander Warg <warg@os.inf.tu-dresden.de>
* economic rights: Technische Universität Dresden (Germany)
*
* This file is part of TUD:OS and distributed under the terms of the
* GNU General Public License 2.
* Please see the COPYING-GPL-2 file for details.
*/
#pragma once
#include <l4/mag-gfx/texture>
#include <cstring>
namespace Mag_gfx {
namespace Mem {
template< typename PT >
class Texture : public Mag_gfx::Texture
{
public:
typedef PT Pixel_traits;
typedef typename PT::Pixel Pixel;
typedef typename PT::Color Color;
public:
Texture(Pixel *pixels, Area const &size, bool xalpha = false)
: Mag_gfx::Texture(PT::type(), pixels, size, xalpha)
{}
bool alloc_buffer(Area const &size)
{
if (_pixels)
return false;
_size = size;
_pixels = malloc(_size.pixels() * (sizeof(Pixel) + (extra_alpha() ? 1 :0)));
return _pixels;
}
Pixel const *pixels() const
{ return (Pixel const *)Mag_gfx::Texture::pixels(); }
Pixel *pixels()
{ return (Pixel *)Mag_gfx::Texture::pixels(); }
unsigned char const *alpha_buffer() const
{
return extra_alpha()
? reinterpret_cast<unsigned char const *>(pixels() + size().pixels())
: 0;
}
unsigned char *alpha_buffer()
{
return extra_alpha()
? reinterpret_cast<unsigned char *>(pixels() + size().pixels())
: 0;
}
void blit(Mag_gfx::Texture const *o, int start_line = 0)
{
Pixel *dst = pixels();
if (start_line >= size().h())
return;
dst += size().w() * start_line;
int const w = std::min(size().w(), o->size().w());
int const h = std::min(size().h() - start_line, o->size().h());
if (o->type() == type())
{
int const ow = o->size().w();
Pixel const *src = reinterpret_cast<Pixel const *>(o->pixels());
for (int i = 0; i < h; ++i, dst += size().w(), src += ow)
memcpy(dst, src, size().w() * sizeof(Pixel));
if (extra_alpha())
memset(alpha_buffer() + size().w() * start_line, ~0, size().w() * h);
}
else
{
#if 0
printf("texture convert: %dx%d %d(%d):%d(%d):%d(%d):%d(%d) -> %dx%d %d(%d):%d(%d):%d(%d):%d(%d)\n",
(int)o->size().w(), (int)o->size().h(),
(int)o->type()->r.si, (int)o->type()->r.sh,
(int)o->type()->g.si, (int)o->type()->g.sh,
(int)o->type()->b.si, (int)o->type()->b.sh,
(int)o->type()->a.si, (int)o->type()->a.sh,
(int)size().w(), (int)size().h(),
(int)type()->r.si, (int)type()->r.sh,
(int)type()->g.si, (int)type()->g.sh,
(int)type()->b.si, (int)type()->b.sh,
(int)type()->a.si, (int)type()->a.sh);
#endif
int const ow = o->size().w() * o->type()->bytes_per_pixel();
int const op = o->type()->bytes_per_pixel();
char const *src = reinterpret_cast<char const *>(o->pixels());
unsigned char *ab = alpha_buffer();
bool const xa = ab;
ab += size().w() * start_line;
for (int i = 0; i < h; i++, dst += size().w(), src += ow)
{
for (int y = 0; y < w; y++)
{
Mag_gfx::Pixel_info::Color c = o->type()->get(src + y*op);
dst[y] = Color(c);
if (xa)
ab[y] = c.a >> 8;
}
if (xa)
ab += size().w();
}
}
}
void blit_line(void const *_src, Pixel_info const *st, int line, unsigned *offset_buffer)
{
Pixel *dst = pixels();
if (line >= size().h())
return;
dst += size().w() * line;
char const *src = (char const *)_src;
if (st == type())
{
for (int i = 0; i < size().w(); ++i, ++dst)
*dst = *(Pixel const *)(src + offset_buffer[i]);
if (extra_alpha())
memset(alpha_buffer() + size().w() * line, ~0, size().w());
}
else
{
#if 0
printf("texture convert: %dx%d %d(%d):%d(%d):%d(%d):%d(%d) -> %dx%d %d(%d):%d(%d):%d(%d):%d(%d)\n",
(int)o->size().w(), (int)o->size().h(),
(int)o->type()->r.si, (int)o->type()->r.sh,
(int)o->type()->g.si, (int)o->type()->g.sh,
(int)o->type()->b.si, (int)o->type()->b.sh,
(int)o->type()->a.si, (int)o->type()->a.sh,
(int)size().w(), (int)size().h(),
(int)type()->r.si, (int)type()->r.sh,
(int)type()->g.si, (int)type()->g.sh,
(int)type()->b.si, (int)type()->b.sh,
(int)type()->a.si, (int)type()->a.sh);
#endif
unsigned char *ab = alpha_buffer();
bool const xa = ab;
ab += size().w() * line;
for (int y = 0; y < size().w(); y++)
{
Mag_gfx::Pixel_info::Color c = st->get(src + offset_buffer[y]);
dst[y] = Color(c);
if (xa)
ab[y] = c.a >> 8;
}
}
}
};
}}

View File

@@ -0,0 +1,44 @@
// vi:ft=cpp
/*
* (c) 2010 Alexander Warg <warg@os.inf.tu-dresden.de>
* economic rights: Technische Universität Dresden (Germany)
*
* This file is part of TUD:OS and distributed under the terms of the
* GNU General Public License 2.
* Please see the COPYING-GPL-2 file for details.
*/
#pragma once
#include <l4/mag-gfx/geometry>
#include <l4/mag-gfx/gfx_colors>
namespace Mag_gfx {
class Texture
{
protected:
Area _size;
void *_pixels;
Pixel_info const *_type;
bool _extra_alpha;
Texture(Pixel_info const *type, void *pixels, Area const &size, bool xalpha)
: _size(size), _pixels(pixels), _type(type), _extra_alpha(xalpha) {}
public:
Pixel_info const *type() const { return _type; }
Area const &size() const { return _size; }
void size(Area const &s) { _size = s; }
void *pixels() { return _pixels; }
void const *pixels() const { return _pixels; }
void pixels(void *pixels) { _pixels = pixels; }
virtual void blit(Texture const *src, int start_line = 0) = 0;
virtual void blit_line(void const *src, Pixel_info const *st, int line, unsigned *offset_buffer) = 0;
bool extra_alpha() const { return _extra_alpha; }
virtual ~Texture() {}
};
}

View File

@@ -0,0 +1,10 @@
PKGDIR ?= ..
L4DIR ?= $(PKGDIR)/../..
TARGET = libmag-gfx.a libmag-gfx.so
SRC_CC = canvas.cc factory.cc
BLIT_CC_x86 = blit-x86.cc
BLIT_CC_generic = blit.cc
SRC_CC += $(firstword $(BLIT_CC_$(ARCH)) $(BLIT_CC_generic))
include $(L4DIR)/mk/lib.mk

View File

@@ -0,0 +1,162 @@
/*
* \brief Blitting function for x86
* \author Norman Feske
* \date 2007-10-09
*/
/*
* (c) 2007 Author(s)
* economic rights: Technische Universität Dresden (Germany)
*
* This file is part of TUD:OS and distributed under the terms of the
* GNU General Public License 2.
* Please see the COPYING-GPL-2 file for details.
*/
#include <l4/mag-gfx/blit>
namespace Mag_gfx { namespace Blit {
/***************
** Utilities **
***************/
/**
* Copy single 16bit column
*/
static inline void copy_unaligned_column(char const *src, int src_w,
char *dst, int dst_w, int w, int h)
{
typedef struct { char x[3]; } __attribute__((packed)) _3byte;
switch (w)
{
case 1:
for (; h-- > 0; src += src_w, dst += dst_w)
*(char *)dst = *(char const *)src;
break;
case 2:
for (; h-- > 0; src += src_w, dst += dst_w)
*(short *)dst = *(short const *)src;
break;
case 3:
for (; h-- > 0; src += src_w, dst += dst_w)
*(_3byte *)dst = *(_3byte const *)src;
break;
}
}
/**
* Copy pixel block 32bit-wise
*
* \param src Source address
* \param dst 32bit-aligned destination address
* \param w Number of 32bit words to copy per line
* \param h Number of lines to copy
* \param src_w Width of source buffer in bytes
* \param dst_w Width of destination buffer in bytes
*/
static inline void copy_block_32bit(char const *src, int src_w,
char *dst, int dst_w,
int w, int h)
{
long d0, d1, d2;
asm volatile ("cld; mov %%ds, %%ax; mov %%ax, %%es" : : : "eax");
for (; h--; src += src_w, dst += dst_w )
asm volatile ("rep movsl"
: "=S" (d0), "=D" (d1), "=c" (d2)
: "S" (src), "D" (dst), "c" (w));
}
/**
* Copy 32byte chunks via MMX
*/
static inline void copy_32byte_chunks(void const *src, void *dst, int size)
{
asm volatile (
"emms \n\t"
"xor %%ecx,%%ecx \n\t"
".align 16 \n\t"
"0: \n\t"
"movq (%%esi,%%ecx,8),%%mm0 \n\t"
"movq 8(%%esi,%%ecx,8),%%mm1 \n\t"
"movq 16(%%esi,%%ecx,8),%%mm2 \n\t"
"movq 24(%%esi,%%ecx,8),%%mm3 \n\t"
"movntq %%mm0,(%%edi,%%ecx,8) \n\t"
"movntq %%mm1,8(%%edi,%%ecx,8) \n\t"
"movntq %%mm2,16(%%edi,%%ecx,8) \n\t"
"movntq %%mm3,24(%%edi,%%ecx,8) \n\t"
"add $4,%%ecx \n\t"
"dec %0 \n\t"
"jnz 0b \n\t"
"sfence \n\t"
"emms \n\t"
: "=r" (size)
: "S" (src), "D" (dst), "0" (size)
: "ecx", "memory", "cc"
);
}
/**
* Copy block with a size of multiple of 32 bytes
*
* \param w Width in 32 byte chunks to copy per line
* \param h Number of lines of copy
*/
static inline void copy_block_32byte(char const *src, int src_w,
char *dst, int dst_w,
int w, int h)
{
if (w)
for (int i = h; i--; src += src_w, dst += dst_w)
copy_32byte_chunks(src, dst, w);
}
/***********************
** Library interface **
***********************/
void blit(void const *s, unsigned src_w,
void *d, unsigned dst_w,
int w, int h)
{
char const *src = (char const *)s;
char *dst = (char *)d;
if (w <= 0 || h <= 0) return;
/* copy unaligned column */
if (w && ((long)dst & 3)) {
copy_unaligned_column(src, src_w, dst, dst_w, w & 3, h);
src += w & 3; dst += w & 3; w &= ~3;
}
/* now, we are on a 32bit aligned destination address */
/* copy 32byte chunks */
if (w >> 5) {
copy_block_32byte(src, src_w, dst, dst_w, w >> 5, h);
src += w & ~31;
dst += w & ~31;
w = w & 31;
}
/* copy 32bit chunks */
if (w >> 2) {
copy_block_32bit(src, src_w, dst, dst_w, w >> 2, h);
src += w & ~3;
dst += w & ~3;
w = w & 3;
}
/* handle trailing row */
if (w)
copy_unaligned_column(src, src_w, dst, dst_w, w, h);
}
}}

View File

@@ -0,0 +1,31 @@
/*
* \brief Generic blitting function
* \author Norman Feske
* \date 2007-10-10
*/
/*
* (c) 2007 Author(s)
* economic rights: Technische Universität Dresden (Germany)
*
* This file is part of TUD:OS and distributed under the terms of the
* GNU General Public License 2.
* Please see the COPYING-GPL-2 file for details.
*/
#include <l4/mag-gfx/blit>
#include <cstring>
namespace Mag_gfx { namespace Blit {
void blit(void const *s, unsigned src_w,
void *d, unsigned dst_w,
int w, int h)
{
char const *src = (char const *)s;
char *dst = (char *)d;
for (int i = h; i--; src += src_w, dst += dst_w)
memcpy(dst, src, w);
}
}}

View File

@@ -0,0 +1,28 @@
/*
* (c) 2009 Alexander Warg <warg@os.inf.tu-dresden.de>
* economic rights: Technische Universität Dresden (Germany)
*
* This file is part of TUD:OS and distributed under the terms of the
* GNU General Public License 2.
* Please see the COPYING-GPL-2 file for details.
*/
#include <l4/mag-gfx/canvas>
namespace Mag_gfx {
void
Canvas::draw_rect(Rect const &r, Rgba32::Color color, int width)
{
Rect_tuple t;
if (width > 0)
t = r - r.offset(width, width, -width, -width);
else
t = r.offset(width, width, -width, -width) - r;
draw_box(t[0], color);
draw_box(t[1], color);
draw_box(t[2], color);
draw_box(t[3], color);
}
}

View File

@@ -0,0 +1,11 @@
/*
* (c) 2009 Alexander Warg <warg@os.inf.tu-dresden.de>
* economic rights: Technische Universität Dresden (Germany)
*
* This file is part of TUD:OS and distributed under the terms of the
* GNU General Public License 2.
* Please see the COPYING-GPL-2 file for details.
*/
#include <l4/mag-gfx/factory>
Mag_gfx::Factory::Set Mag_gfx::Factory::set;