mirror of
https://github.com/genodelabs/genode.git
synced 2024-12-19 21:57:55 +00:00
259b127f96
This patch adds two new painters located at gems/include/polygon_gfx. Both painters draw convex polygons with an arbirary number of points. The shaded-polygon painter interpolates the color and alpha values whereas the textured-polygon painter applies a texture to the polygon. The painters are accompanied by simplistic 3D routines located at gems/include/nano3d/ and a corresponding example (gems/run/nano3d.run).
147 lines
3.9 KiB
C++
147 lines
3.9 KiB
C++
/*
|
|
* \brief Functor for painting textured polygons
|
|
* \author Norman Feske
|
|
* \date 2015-06-29
|
|
*/
|
|
|
|
/*
|
|
* Copyright (C) 2015 Genode Labs GmbH
|
|
*
|
|
* This file is part of the Genode OS framework, which is distributed
|
|
* under the terms of the GNU General Public License version 2.
|
|
*/
|
|
|
|
#ifndef _INCLUDE__POLYGON_GFX__TEXTURED_POLYGON_PAINTER_H_
|
|
#define _INCLUDE__POLYGON_GFX__TEXTURED_POLYGON_PAINTER_H_
|
|
|
|
#include <os/surface.h>
|
|
#include <os/texture.h>
|
|
#include <polygon_gfx/polygon_painter_base.h>
|
|
#include <polygon_gfx/texturize_rgba.h>
|
|
|
|
namespace Polygon { class Textured_painter; }
|
|
|
|
|
|
class Polygon::Textured_painter : public Polygon::Painter_base
|
|
{
|
|
private:
|
|
|
|
/**
|
|
* Edge attribute IDs
|
|
*/
|
|
enum Edge_attr { ATTR_X, ATTR_U, ATTR_V, NUM_ATTR };
|
|
|
|
Edge_buffers<NUM_ATTR> _edges;
|
|
|
|
public:
|
|
|
|
/**
|
|
* Polygon point used for textured polygons
|
|
*/
|
|
struct Point : Point_base
|
|
{
|
|
int u = 0, v = 0;
|
|
|
|
Point() { }
|
|
Point(int x, int y, int u, int v) : Point_base(x, y), u(u), v(v) { }
|
|
|
|
enum { NUM_EDGE_ATTRIBUTES = NUM_ATTR };
|
|
|
|
inline int edge_attr(int id) const
|
|
{
|
|
switch (id) {
|
|
default:
|
|
case ATTR_X: return Point_base::edge_attr(id);
|
|
case ATTR_U: return u;
|
|
case ATTR_V: return v;
|
|
}
|
|
}
|
|
|
|
inline void edge_attr(int id, int value)
|
|
{
|
|
switch (id) {
|
|
case ATTR_X: Point_base::edge_attr(id, value); return;
|
|
case ATTR_U: u = value; return;
|
|
case ATTR_V: v = value; return;
|
|
}
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Constructor
|
|
*
|
|
* \param alloc allocator used for allocating edge buffers
|
|
* \param max_height maximum size of polygon to draw, used to dimension
|
|
* the edge buffers
|
|
*/
|
|
Textured_painter(Genode::Allocator &alloc, unsigned max_height)
|
|
:
|
|
_edges(alloc, max_height)
|
|
{ }
|
|
|
|
/**
|
|
* Draw textured polygon
|
|
*
|
|
* \param points Array of polygon points
|
|
* \param num_points Number of polygon points
|
|
*
|
|
* The pixel surface and the alpha surface must have the same
|
|
* dimensions.
|
|
*/
|
|
template <typename PT, typename AT>
|
|
void paint(Genode::Surface<PT> &pixel_surface,
|
|
Genode::Surface<AT> &alpha_surface,
|
|
Point const points[], unsigned num_points,
|
|
Genode::Texture<PT> const &texture)
|
|
{
|
|
Point clipped[2*max_points_clipped(num_points)];
|
|
num_points = clip_polygon<Point>(points, num_points, clipped,
|
|
pixel_surface.clip());
|
|
|
|
Rect const bbox = bounding_box(clipped, num_points, pixel_surface.size());
|
|
|
|
fill_edge_buffers(_edges, clipped, num_points);
|
|
|
|
int * const x_l_edge = _edges.left (ATTR_X);
|
|
int * const x_r_edge = _edges.right(ATTR_X);
|
|
int * const u_l_edge = _edges.left (ATTR_U);
|
|
int * const u_r_edge = _edges.right(ATTR_U);
|
|
int * const v_l_edge = _edges.left (ATTR_V);
|
|
int * const v_r_edge = _edges.right(ATTR_V);
|
|
|
|
unsigned const src_w = texture.size().w();
|
|
PT const *src_pixel = texture.pixel();
|
|
unsigned char const *src_alpha = texture.alpha();
|
|
|
|
/* calculate begin of destination scanline */
|
|
unsigned const dst_w = pixel_surface.size().w();
|
|
PT *dst_pixel = pixel_surface.addr() + dst_w*bbox.y1();
|
|
AT *dst_alpha = alpha_surface.addr() + dst_w*bbox.y1();
|
|
|
|
for (int y = bbox.y1(); y < bbox.y2(); y++) {
|
|
|
|
/*
|
|
* Read left and right texture coordinates (u,v) from
|
|
* corresponding edge buffers.
|
|
*/
|
|
Genode::Point<> const l_texpos(u_l_edge[y], v_l_edge[y]);
|
|
Genode::Point<> const r_texpos(u_r_edge[y], v_r_edge[y]);
|
|
|
|
int const x_l = x_l_edge[y];
|
|
int const x_r = x_r_edge[y];
|
|
|
|
if (x_l < x_r)
|
|
texturize_rgba(l_texpos, r_texpos,
|
|
dst_pixel + x_l, (unsigned char *)dst_alpha + x_l,
|
|
x_r - x_l, src_pixel, src_alpha, src_w);
|
|
|
|
dst_pixel += dst_w;
|
|
dst_alpha += dst_w;
|
|
}
|
|
|
|
pixel_surface.flush_pixels(bbox);
|
|
}
|
|
};
|
|
|
|
#endif /* _INCLUDE__POLYGON_GFX__TEXTURED_POLYGON_PAINTER_H_ */
|