mirror of
https://github.com/genodelabs/genode.git
synced 2025-06-24 09:46:44 +00:00
Polygon drawing and rudimentary 3D routines
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).
This commit is contained in:
committed by
Christian Helmuth
parent
c74a4fbbe2
commit
259b127f96
146
repos/gems/include/polygon_gfx/textured_polygon_painter.h
Normal file
146
repos/gems/include/polygon_gfx/textured_polygon_painter.h
Normal file
@ -0,0 +1,146 @@
|
||||
/*
|
||||
* \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_ */
|
Reference in New Issue
Block a user