2
* SPL - The SPL Programming Language
3
* Copyright (C) 2006 Clifford Wolf <clifford@clifford.at>
4
* Copyright (C) 2007 Raphael Langerhorst <raphael@raphael.g-system.at>
6
* This program is free software; you can redistribute it and/or modify
7
* it under the terms of the GNU General Public License as published by
8
* the Free Software Foundation; either version 2 of the License, or
9
* (at your option) any later version.
11
* This program is distributed in the hope that it will be useful,
12
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
* GNU General Public License for more details.
16
* You should have received a copy of the GNU General Public License
17
* along with this program; if not, write to the Free Software
18
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20
* mod_epfb.c: Hardware Accelerated Raster Graphics Engine on EP9315.
26
* This Module provides hardware accelerated graphics on EP9315 processors.
27
* It is tailored for the NetBSD/evbarm architecture.
28
* If compiling fails, make sure that the file epio.h is in include path.
37
#include <sys/ioctl.h>
44
extern void SPL_ABI(spl_mod_epfb_init)(struct spl_vm *vm, struct spl_module *mod, int restore);
45
extern void SPL_ABI(spl_mod_epfb_done)(struct spl_vm *vm, struct spl_module *mod);
49
// FONT BITMAPS TAKEN FROM L3D (raster/ras3_sw.cc)
51
// L3D realtime 3D library, explained in book "Linux 3D Graphics Programming"
52
// Copyright (C) 2000 Norman Lin
53
// Contact: nlin@linux3dgraphicsprogramming.org (alt. nlin@geocities.com)
55
// This program is free software; you can redistribute it and/or
56
// modify it under the terms of the GNU General Public License
57
// as published by the Free Software Foundation; either version 2
58
// of the License, or (at your option) any later version.
60
// This program is distributed in the hope that it will be useful,
61
// but WITHOUT ANY WARRANTY; without even the implied warranty of
62
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
63
// GNU General Public License for more details.
65
// You should have received a copy of the GNU General Public License along
66
// with this program; if not, write to the Free Software Foundation, Inc.,
67
// 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
69
///////////////////////////////////////////////////////////////////////////
72
static const unsigned char period[] =
73
{0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
75
static const unsigned char space[] =
76
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
78
static const unsigned char digits[][13] = {
79
{0x0,0x0, 0x18,0x3C,0x66,0xC3,0xC3,0xC3,0xC3,0xC3,0x66,0x3C,0x18},
80
{0x0,0x0, 0x7F,0x7F,0xC,0xC,0xC,0xC,0xC,0xC,0x6C,0x3C,0xC},
81
{0x0,0x0, 0xFF,0xFF,0xC0,0x60,0x30,0x18,0xC,0x6,0xC6,0x66,0x3C},
82
{0x0,0x0, 0x7E,0xC3,0x3,0x6,0xC,0x38,0xC,0x6,0x3,0xC3,0x7E},
83
{0x0,0x0, 0x6,0x6,0x6,0x6,0xFF,0xFF,0xC6,0xC6,0x66,0x36,0x1E},
84
{0x0,0x0, 0x7E,0xFF,0xC3,0x3,0x3,0xFF,0xFE,0xC0,0xC0,0xC0,0xFE},
85
{0x0,0x0, 0x7E,0xFF,0xC3,0xC3,0xC3,0xFF,0xFE,0xC0,0xC0,0xC0,0x7E},
86
{0x0,0x0, 0x60,0x60,0x60,0x60,0x30,0x18,0xC,0x6,0x3,0x3,0xFF},
87
{0x0,0x0, 0x7E,0xFF,0xC3,0xC3,0xC3,0x7E,0xC3,0xC3,0xC3,0xC3,0x7E},
88
{0x0,0x0, 0x7E,0xFF,0xC3,0x3,0x3,0x7F,0xC3,0xC3,0xC3,0xC3,0x7E}
92
static const unsigned char upper_case_letters[][13] = {
93
{0x00, 0x00, 0xc3, 0xc3, 0xc3, 0xc3, 0xff, 0xc3, 0xc3, 0xc3, 0x66, 0x3c, 0x18},
94
{0x00, 0x00, 0xfe, 0xc7, 0xc3, 0xc3, 0xc7, 0xfe, 0xc7, 0xc3, 0xc3, 0xc7, 0xfe},
95
{0x00, 0x00, 0x7e, 0xe7, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xe7, 0x7e},
96
{0x00, 0x00, 0xfc, 0xce, 0xc7, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc7, 0xce, 0xfc},
97
{0x00, 0x00, 0xff, 0xc0, 0xc0, 0xc0, 0xc0, 0xfc, 0xc0, 0xc0, 0xc0, 0xc0, 0xff},
98
{0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xfc, 0xc0, 0xc0, 0xc0, 0xff},
99
{0x00, 0x00, 0x7e, 0xe7, 0xc3, 0xc3, 0xcf, 0xc0, 0xc0, 0xc0, 0xc0, 0xe7, 0x7e},
100
{0x00, 0x00, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xff, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3},
101
{0x00, 0x00, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x7e},
102
{0x00, 0x00, 0x7c, 0xee, 0xc6, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06},
103
{0x00, 0x00, 0xc3, 0xc6, 0xcc, 0xd8, 0xf0, 0xe0, 0xf0, 0xd8, 0xcc, 0xc6, 0xc3},
104
{0x00, 0x00, 0xff, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0},
105
{0x00, 0x00, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xdb, 0xff, 0xff, 0xe7, 0xc3},
106
{0x00, 0x00, 0xc7, 0xc7, 0xcf, 0xcf, 0xdf, 0xdb, 0xfb, 0xf3, 0xf3, 0xe3, 0xe3},
107
{0x00, 0x00, 0x7e, 0xe7, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xe7, 0x7e},
108
{0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xfe, 0xc7, 0xc3, 0xc3, 0xc7, 0xfe},
109
{0x00, 0x00, 0x3f, 0x6e, 0xdf, 0xdb, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0x66, 0x3c},
110
{0x00, 0x00, 0xc3, 0xc6, 0xcc, 0xd8, 0xf0, 0xfe, 0xc7, 0xc3, 0xc3, 0xc7, 0xfe},
111
{0x00, 0x00, 0x7e, 0xe7, 0x03, 0x03, 0x07, 0x7e, 0xe0, 0xc0, 0xc0, 0xe7, 0x7e},
112
{0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xff},
113
{0x00, 0x00, 0x7e, 0xe7, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3},
114
{0x00, 0x00, 0x18, 0x3c, 0x3c, 0x66, 0x66, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3},
115
{0x00, 0x00, 0xc3, 0xe7, 0xff, 0xff, 0xdb, 0xdb, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3},
116
{0x00, 0x00, 0xc3, 0x66, 0x66, 0x3c, 0x3c, 0x18, 0x3c, 0x3c, 0x66, 0x66, 0xc3},
117
{0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x3c, 0x66, 0x66, 0xc3},
118
{0x00, 0x00, 0xff, 0xc0, 0xc0, 0x60, 0x30, 0x7e, 0x0c, 0x06, 0x03, 0x03, 0xff}
121
/* lower case letters added by raphael */
122
static const unsigned char lower_case_letters[][13] = {
123
{0x00, 0x00, 0x7f, 0xc3, 0xc3, 0xc3, 0xc7, 0x7b, 0x00, 0x00, 0x00, 0x00, 0x00}, // a
124
{0x00, 0x00, 0xff, 0xc3, 0xc3, 0xc3, 0xc3, 0xfe, 0xc0, 0xc0, 0xc0, 0xc0, 0x00}, // b
125
{0x00, 0x00, 0x7e, 0xc3, 0xc0, 0xc0, 0xc3, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00}, // c
126
{0x00, 0x00, 0x7f, 0xc3, 0xc3, 0xc3, 0xc3, 0x7f, 0x03, 0x03, 0x03, 0x03, 0x00}, // d
127
{0x00, 0x00, 0x7e, 0xc0, 0xc0, 0xff, 0xc2, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00}, // e
128
{0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3e, 0x18, 0x1a, 0x1e, 0x00}, // f
129
{0xfe, 0x03, 0x7f, 0xc3, 0xc3, 0xc3, 0xc3, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00}, // g
130
{0x00, 0x00, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xfe, 0xc0, 0xc0, 0xc0, 0xc0, 0x00}, // h
131
{0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00}, // i
132
{0x30, 0x58, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00}, // j
133
{0x00, 0x00, 0xc3, 0xc6, 0xcc, 0xd8, 0xf0, 0xd8, 0xcc, 0xc6, 0xc0, 0xc0, 0x00}, // k
134
{0x00, 0x00, 0x1c, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00}, // l
135
{0x00, 0x00, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00}, // m
136
{0x00, 0x00, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00}, // n
137
{0x00, 0x00, 0x7e, 0xc3, 0xc3, 0xc3, 0xc3, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00}, // o
138
{0xc0, 0xc0, 0xff, 0xc3, 0xc3, 0xc3, 0xc3, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00}, // p
139
{0x03, 0x03, 0x7f, 0xc3, 0xc3, 0xc3, 0xc3, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00}, // q
140
{0x00, 0x00, 0x30, 0x30, 0x30, 0x30, 0x38, 0x2e, 0x00, 0x00, 0x00, 0x00, 0x00}, // r
141
{0x00, 0x00, 0x1e, 0x23, 0x06, 0x08, 0x31, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00}, // s
142
{0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3e, 0x18, 0x18, 0x18, 0x00}, // t
143
{0x00, 0x00, 0x7f, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0x00, 0x00, 0x00, 0x00, 0x00}, // u
144
{0x00, 0x00, 0x18, 0x3c, 0x24, 0x66, 0x42, 0xc3, 0x00, 0x00, 0x00, 0x00, 0x00}, // v
145
{0x00, 0x00, 0x6d, 0xdb, 0xdb, 0xdb, 0xc3, 0xc3, 0x00, 0x00, 0x00, 0x00, 0x00}, // w
146
{0x00, 0x00, 0xc3, 0x66, 0x3c, 0x18, 0x3c, 0x66, 0xc3, 0x00, 0x00, 0x00, 0x00}, // x
147
{0x60, 0x30, 0x18, 0x3c, 0x24, 0x66, 0x42, 0xc3, 0x00, 0x00, 0x00, 0x00, 0x00}, // y
148
{0x00, 0x00, 0xff, 0xc0, 0x60, 0x18, 0x06, 0x03, 0xff, 0x00, 0x00, 0x00, 0x00} // z
151
unsigned char font_bitmaps[256][13];
153
void epfb_init_fontbitmaps()
155
//- create font bitmaps
158
for(i=0; i<26; i++) {
159
for(j=0; j<13; j++) {
160
font_bitmaps['A' + i][j] = upper_case_letters[i][j];
161
font_bitmaps['a' + i][j] = lower_case_letters[i][j];
165
for(i=0; i<10; i++) {
166
for(j=0; j<13; j++) {
167
font_bitmaps['0' + i][j] = digits[i][j];
171
for(j=0; j<13; j++) {
172
font_bitmaps[' '][j] = space[j];
175
for(j=0; j<13; j++) {
176
font_bitmaps['.'][j] = period[j];
181
void epfb_draw_text(int x, int y, const char *text, int col) {
183
#define FONT_Y_SIZE 13
184
#define FONT_X_SIZE 8
185
#define FONT_SPACING 2
189
struct epfb_pixelset pixel;
192
// raphael 2007-06-28: we need to start at Y_SIZE - 1 (font_y=1) and go to 0 (font_y == Y_SIZE)
193
for(font_y=1; font_y <= FONT_Y_SIZE; font_y++) {
195
pixel.y = y + font_y;
198
for(c=0; c<strlen(text); c++) {
200
for(font_x=0, current_bit=0x80;
201
font_x < FONT_X_SIZE;
202
font_x++, current_bit >>= 1)
204
if(font_bitmaps[text[c]][FONT_Y_SIZE-font_y] & current_bit)
205
ioctl(epfb_fd,EPFB_PIXELSET,&pixel);
208
pixel.x += FONT_SPACING;
214
// END OF FONT BITMAPS BY NORMAN LIN
216
static struct spl_node *handler_epfb_clear(struct spl_task *task, void *data)
218
if (ioctl(epfb_fd,EPFB_CLEAR)==-1)
219
spl_report(SPL_REPORT_RUNTIME|SPL_REPORT_WARNING, task, "clear ioctl failed\n");
224
* Set the colour of a single pixel on screen.
226
// builtin epfb_pixelset(x,y,col)
228
static struct spl_node *handler_epfb_pixelset(struct spl_task *task, void *data)
230
struct epfb_pixelset pixel;
231
pixel.x = spl_clib_get_int(task);
232
pixel.y = spl_clib_get_int(task);
233
pixel.col = spl_clib_get_int(task);
235
if (ioctl(epfb_fd,EPFB_PIXELSET,&pixel) == -1)
236
spl_report(SPL_REPORT_RUNTIME|SPL_REPORT_WARNING, task, "pixelset ioctl failed\n");
241
* Draw a line from (x1/y1) to (x2/y2) on screen.
243
// builtin epfb_linedraw(startx,starty,stopx,stopy,col)
245
static struct spl_node *handler_epfb_linedraw(struct spl_task *task, void *data)
247
struct epfb_linedraw line;
248
line.startx = spl_clib_get_int(task);
249
line.starty = spl_clib_get_int(task);
250
line.stopx = spl_clib_get_int(task);
251
line.stopy = spl_clib_get_int(task);
252
line.col = spl_clib_get_int(task);
254
if (ioctl(epfb_fd,EPFB_LINEDRAW,&line)==-1)
255
spl_report(SPL_REPORT_RUNTIME|SPL_REPORT_WARNING, task, "line draw ioctl failed\n");
260
* Rectangular blockfill from (x/y) with given width and height.
262
// builtin epfb_blockfill(x,y,width,height,col)
264
static struct spl_node *handler_epfb_blockfill(struct spl_task *task, void *data)
266
struct epfb_blockfill block;
267
block.startx = spl_clib_get_int(task);
268
block.starty = spl_clib_get_int(task);
269
block.width = spl_clib_get_int(task);
270
block.height = spl_clib_get_int(task);
273
if (block.height <= 0)
278
block.col = spl_clib_get_int(task);
280
if (ioctl(epfb_fd,EPFB_BLOCKFILL,&block)==-1)
281
spl_report(SPL_REPORT_RUNTIME|SPL_REPORT_WARNING, task, "block fill ioctl failed\n");
286
* Renders text at (x,y) with given colour.
288
// builtin epfb_drawtext(x,y,text,col)
290
static struct spl_node *handler_epfb_drawtext(struct spl_task *task, void *data)
292
int x = spl_clib_get_int(task);
293
int y = spl_clib_get_int(task);
294
char* text = spl_clib_get_string(task);
295
int col = spl_clib_get_int(task);
296
epfb_draw_text(x,y,text,col);
301
* Setup Hardware Cursor.
302
* The cursor must be enabled with [epfb_cursor_enable] as well.
303
* The cursor position can be specified with [epfb_cursor_moveto].
305
// builtin epfb_cursor_setup(width,height,col1,col2,blink1,blink2,blinkrate)
307
static struct spl_node *handler_epfb_cursor_setup(struct spl_task *task, void *data)
309
struct epfb_cursor_setup cursor;
310
cursor.width = spl_clib_get_int(task);
311
cursor.height = spl_clib_get_int(task);
312
cursor.col1 = spl_clib_get_int(task);
313
cursor.col2 = spl_clib_get_int(task);
314
cursor.blink1 = spl_clib_get_int(task);
315
cursor.blink2 = spl_clib_get_int(task);
316
cursor.blinkrate = spl_clib_get_int(task);
318
if (ioctl(epfb_fd,EPFB_CURSOR_SETUP,&cursor)==-1)
319
spl_report(SPL_REPORT_RUNTIME|SPL_REPORT_WARNING, task, "setting up cursor failed\n");
324
* Set pixel value for hardware cursor.
325
* The value must be in the range of 0 to 3 (00 to 11).
326
* 0 means transparent, 1 means invert of video stream,
327
* 2 means (blink) colour 1, 3 means (blink) colour 2.
329
// builtin epfb_cursor_pixel(x,y,value)
331
static struct spl_node *handler_epfb_cursor_pixel(struct spl_task *task, void *data)
333
struct epfb_cursor_pixelset pixel;
334
pixel.x = spl_clib_get_int(task);
335
pixel.y = spl_clib_get_int(task);
336
pixel.value = spl_clib_get_int(task);
337
if (ioctl(epfb_fd,EPFB_CURSOR_PIXELSET,&pixel)==-1)
338
spl_report(SPL_REPORT_RUNTIME|SPL_REPORT_WARNING, task, "failed setting cursor enable state\n");
343
* Enable or disable hardware cursor.
344
* 1 is enable, 0 is disable.
346
// builtin epfb_cursor_enable(enable)
348
static struct spl_node *handler_epfb_cursor_enable(struct spl_task *task, void *data)
350
int enable = spl_clib_get_int(task);
351
if (ioctl(epfb_fd,EPFB_CURSOR_ENABLE,&enable)==-1)
352
spl_report(SPL_REPORT_RUNTIME|SPL_REPORT_WARNING, task, "failed setting cursor enable state\n");
358
* Set Hardware Cursor Position on screen.
360
// builtin epfb_cursor_moveto(x,y)
362
static struct spl_node *handler_epfb_cursor_moveto(struct spl_task *task, void *data)
364
struct epfb_cursor_position pos;
365
pos.x = spl_clib_get_int(task);
366
pos.y = spl_clib_get_int(task);
367
if (ioctl(epfb_fd,EPFB_CURSOR_MOVETO,&pos)==-1)
368
spl_report(SPL_REPORT_RUNTIME|SPL_REPORT_WARNING, task, "setting cursor position failed\n");
373
* Get Hardware Cursor Position on screen.
375
// builtin epfb_cursor_position(x,y)
377
static struct spl_node *handler_epfb_cursor_position(struct spl_task *task, void *data)
379
struct epfb_cursor_position pos;
380
if (ioctl(epfb_fd,EPFB_CURSOR_POSITION,&pos)==-1)
382
spl_report(SPL_REPORT_RUNTIME|SPL_REPORT_WARNING, task, "getting cursor position failed\n");
386
struct spl_node* position = spl_get(0);
387
spl_create(task, position, "x", SPL_NEW_INT(pos.x), SPL_CREATE_LOCAL);
388
spl_create(task, position, "y", SPL_NEW_INT(pos.y), SPL_CREATE_LOCAL);
393
void SPL_ABI(spl_mod_epfb_init)(struct spl_vm *vm, struct spl_module *mod UNUSED, int restore UNUSED)
395
epfb_fd = open("/dev/epfb0",0,O_RDWR);
397
epfb_fd = open("/dev/epfb",0,O_RDWR);
400
// TODO: can we do SPL like error reporting here?
401
printf("Failed to open the EPFB device file at /dev/epfb and /dev/epfb0, cannot load epfb module.\n");
404
epfb_init_fontbitmaps();
406
// spl_clib_reg(vm, "epfb_output_status", handler_epfb_output_status, 0);
407
// spl_clib_reg(vm, "epfb_output_enable", handler_epfb_output_enable, 0);
408
// spl_clib_reg(vm, "epfb_info", handler_epfb_devinfo, 0);
409
spl_clib_reg(vm, "epfb_clear", handler_epfb_clear, 0);
410
spl_clib_reg(vm, "epfb_pixel", handler_epfb_pixelset, 0);
411
spl_clib_reg(vm, "epfb_line", handler_epfb_linedraw, 0);
412
spl_clib_reg(vm, "epfb_blockfill", handler_epfb_blockfill, 0);
413
spl_clib_reg(vm, "epfb_text", handler_epfb_drawtext, 0);
415
spl_clib_reg(vm, "epfb_cursor_setup", handler_epfb_cursor_setup, 0);
416
spl_clib_reg(vm, "epfb_cursor_pixel", handler_epfb_cursor_pixel, 0);
417
spl_clib_reg(vm, "epfb_cursor_enable", handler_epfb_cursor_enable, 0);
418
spl_clib_reg(vm, "epfb_cursor_moveto", handler_epfb_cursor_moveto, 0);
419
spl_clib_reg(vm, "epfb_cursor_position", handler_epfb_cursor_position, 0);
422
void SPL_ABI(spl_mod_epfb_done)(struct spl_vm *vm UNUSED, struct spl_module *mod UNUSED)