Rev 1128 |
Go to most recent revision |
Blame |
Compare with Previous |
Last modification |
View Log
| RSS feed
/*
* Project: S.Ha.R.K.
*
* Coordinators:
* Giorgio Buttazzo <giorgio@sssup.it>
* Paolo Gai <pj@gandalf.sssup.it>
*
* Authors :
* Giacomo Guidi <giacomo@gandalf.sssup.it>
*
*
* ReTiS Lab (Scuola Superiore S.Anna - Pisa - Italy)
*
* http://www.sssup.it
* http://retis.sssup.it
* http://shark.sssup.it
*/
#include <drivers/vga.h>
#include <drivers/keyb.h>
#include <GL/osmesa.h>
#include <GL/glut.h>
#include <ports/png.h>
#include <math.h>
#include <stdlib.h>
#include <assert.h>
#include <kernel/log.h>
#include <kernel/kern.h>
#include <stdio.h>
#ifndef M_PI
#define M_PI 3.14159265
#endif
#define WIDTH 640
#define HEIGHT 480
#define BYTES_PP 2 //BytesPerPixel
#define INITSTR G640x480x64K //SVGAlib standard mode definitions
#define CARD NV3 //Video driver (Supported SAVAGE, NV3, R128 from SVGALib)
#define DEG2RAD (3.14159/180.0)
static GLint ImgWidth
= 0, ImgHeight
= 0;
static GLenum ImgFormat
= 0;
static GLubyte
*Image
= NULL
;
#define MAX_OBJECTS 2
static GLint table_list
;
static GLint objects_list
[MAX_OBJECTS
];
static GLfloat xrot
, yrot
;
static GLfloat spin
;
OSMesaContext ctx
;
unsigned char *rgb_565_buf
= NULL
; //RGB 16 bpp Buffer
unsigned char *video_buf
= NULL
; //Video Buffer
unsigned long int VMEMLONG
= WIDTH
* HEIGHT
* BYTES_PP
/ 4; // Used by copy_videomem_16to16
unsigned long int RGB565MEM
= WIDTH
* HEIGHT
* BYTES_PP
; // Total video mem
unsigned long int PERIOD_REFRESH
= 80000; //fps = 20
unsigned long int PERIOD_DISEGNA
= 80000;
unsigned long int WCET_REFRESH
, WCET_DISEGNA
;
TASK refesh
(void);
TASK disegna
(void);
PID refresh_PID
, disegna_PID
;
void read_png_file
(char *file_name
, GLubyte
**buffer
, GLint
*width
, GLint
*height
, png_byte
*color_type
)
{
int y
;
png_byte bit_depth
;
png_structp png_ptr
;
png_infop info_ptr
;
int number_of_passes
;
png_bytep
* row_pointers
;
char header
[8]; // 8 is the maximum size that can be checked
/* open file and test for it being a png */
FILE
*fp
= fopen(file_name
, "rb");
if (!fp
) {
cprintf
("[read_png_file] File %s could not be opened for reading", file_name
);
sys_end
();
}
fread(header
, 1, 8, fp
);
if (png_sig_cmp
(header
, 0, 8))
cprintf
("[read_png_file] File %s is not recognized as a PNG file", file_name
);
/* initialize stuff */
png_ptr
= png_create_read_struct
(PNG_LIBPNG_VER_STRING
, NULL
, NULL
, NULL
);
if (!png_ptr
)
cprintf
("[read_png_file] png_create_read_struct failed");
info_ptr
= png_create_info_struct
(png_ptr
);
if (!info_ptr
)
cprintf
("[read_png_file] png_create_info_struct failed");
png_init_io
(png_ptr
, fp
);
png_set_sig_bytes
(png_ptr
, 8);
png_read_info
(png_ptr
, info_ptr
);
*width
= info_ptr
->width
;
*height
= info_ptr
->height
;
*color_type
= info_ptr
->color_type
;
bit_depth
= info_ptr
->bit_depth
;
number_of_passes
= png_set_interlace_handling
(png_ptr
);
cprintf
("Open PNG W: %d H: %d CT: %d BD: %d\n",*width
,*height
,*color_type
,bit_depth
);
png_read_update_info
(png_ptr
, info_ptr
);
row_pointers
= (png_bytep
*) malloc(sizeof(png_bytep
) * info_ptr
->height
);
for (y
=0; y
<info_ptr
->height
; y
++)
row_pointers
[y
] = (png_byte
*) malloc(info_ptr
->rowbytes
);
png_read_image
(png_ptr
, row_pointers
);
if(info_ptr
->color_type
== PNG_COLOR_TYPE_RGB
) {
*buffer
= malloc(info_ptr
->height
* info_ptr
->rowbytes
);
for(y
=0; y
<info_ptr
->height
; y
++)
memcpy(*buffer
+y
*info_ptr
->rowbytes
,row_pointers
[y
],info_ptr
->rowbytes
);
}
fclose(fp
);
}
static void make_table
( void )
{
static GLfloat table_mat
[] = { 1.0, 1.0, 1.0, 0.6 };
static GLfloat gray
[] = { 0.4, 0.4, 0.4, 1.0 };
table_list
= glGenLists
(1);
glNewList
( table_list
, GL_COMPILE
);
/* load table's texture */
glMaterialfv
( GL_FRONT
, GL_AMBIENT_AND_DIFFUSE
, table_mat
);
/* glMaterialfv( GL_FRONT, GL_EMISSION, gray );*/
glMaterialfv
( GL_FRONT
, GL_DIFFUSE
, table_mat
);
glMaterialfv
( GL_FRONT
, GL_AMBIENT
, gray
);
/* draw textured square for the table */
glPushMatrix
();
glScalef
( 4.0, 4.0, 4.0 );
glBegin
( GL_POLYGON
);
glNormal3f
( 0.0, 1.0, 0.0 );
glTexCoord2f
( 0.0, 0.0 ); glVertex3f
( 1.0, 0.0, -1.0 );
glTexCoord2f
( 1.0, 0.0 ); glVertex3f
( 1.0, 0.0, 1.0 );
glTexCoord2f
( 1.0, 1.0 ); glVertex3f
( -1.0, 0.0, 1.0 );
glTexCoord2f
( 0.0, 1.0 ); glVertex3f
( -1.0, 0.0, -1.0 );
glEnd
();
glPopMatrix
();
glDisable
( GL_TEXTURE_2D
);
glEndList
();
}
static void make_objects
( void )
{
GLUquadricObj
*q
;
static GLfloat cyan
[] = { 0.0, 1.0, 1.0, 1.0 };
static GLfloat green
[] = { 0.2, 1.0, 0.2, 1.0 };
static GLfloat black
[] = { 0.0, 0.0, 0.0, 0.0 };
q
= gluNewQuadric
();
gluQuadricDrawStyle
( q
, GLU_FILL
);
gluQuadricNormals
( q
, GLU_SMOOTH
);
objects_list
[0] = glGenLists
(1);
glNewList
( objects_list
[0], GL_COMPILE
);
glMaterialfv
( GL_FRONT
, GL_AMBIENT_AND_DIFFUSE
, cyan
);
glMaterialfv
( GL_FRONT
, GL_EMISSION
, black
);
gluCylinder
( q
, 0.5, 0.5, 1.0, 15, 1 );
glEndList
();
objects_list
[1] = glGenLists
(1);
glNewList
( objects_list
[1], GL_COMPILE
);
glMaterialfv
( GL_FRONT
, GL_AMBIENT_AND_DIFFUSE
, green
);
glMaterialfv
( GL_FRONT
, GL_EMISSION
, black
);
gluCylinder
( q
, 1.5, 0.0, 2.5, 15, 1 );
glEndList
();
}
static void gl_init
( void )
{
png_byte img_color
;
GLfloat yAspect
= 2.5;
GLfloat xAspect
= yAspect
* (float) WIDTH
/ (float) HEIGHT
;
//Create the OSMesa Context
ctx
= OSMesaCreateContext
(OSMESA_RGB_565
, NULL
);
//Make Current Context
OSMesaMakeCurrent
(ctx
, rgb_565_buf
, GL_UNSIGNED_SHORT_5_6_5
, WIDTH
, HEIGHT
);
read_png_file
("test.png",&Image
,&ImgWidth
,&ImgHeight
,&img_color
);
if (img_color
== PNG_COLOR_TYPE_RGB
&& Image
!= NULL
)
ImgFormat
= GL_RGB
;
else {
cprintf
("Texture Load Falied !!\n");
sys_end
();
}
make_table
();
make_objects
();
gluBuild2DMipmaps
(GL_TEXTURE_2D
, 3, ImgWidth
, ImgHeight
,
ImgFormat
, GL_UNSIGNED_BYTE
, Image
);
glTexParameteri
( GL_TEXTURE_2D
, GL_TEXTURE_WRAP_S
, GL_REPEAT
);
glTexParameteri
( GL_TEXTURE_2D
, GL_TEXTURE_WRAP_T
, GL_REPEAT
);
glTexParameteri
( GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_NEAREST
);
glTexParameteri
( GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_NEAREST
);
xrot
= 30.0;
yrot
= 50.0;
spin
= 0.0;
glShadeModel
( GL_FLAT
);
glEnable
( GL_LIGHT0
);
glEnable
( GL_LIGHTING
);
glClearColor
( 0.5, 0.5, 0.9, 0.0 );
glEnable
( GL_NORMALIZE
);
glViewport
(0, 0, WIDTH
, HEIGHT
);
glMatrixMode
(GL_PROJECTION
);
glLoadIdentity
();
glFrustum
( -xAspect
, xAspect
, yAspect
, -yAspect
, 10.0, 30.0 );
glMatrixMode
(GL_MODELVIEW
);
glLoadIdentity
();
}
static void draw_objects
( GLfloat eyex
, GLfloat eyey
, GLfloat eyez
)
{
(void) eyex
;
(void) eyey
;
(void) eyez
;
#ifndef USE_ZBUFFER
if (eyex
<0.5) {
#endif
glPushMatrix
();
glTranslatef
( 1.0, 1.5, 0.0 );
glRotatef
( spin
, 1.0, 0.5, 0.0 );
glRotatef
( 0.5*spin
, 0.0, 0.5, 1.0 );
glCallList
( objects_list
[0] );
glPopMatrix
();
glPushMatrix
();
glTranslatef
( -1.0, 0.85+3.0*fabs( cos(0.01*spin
) ), 0.0 );
glRotatef
( 0.5*spin
, 0.0, 0.5, 1.0 );
glRotatef
( spin
, 1.0, 0.5, 0.0 );
glScalef
( 0.5, 0.5, 0.5 );
glCallList
( objects_list
[1] );
glPopMatrix
();
#ifndef USE_ZBUFFER
}
else {
glPushMatrix
();
glTranslatef
( -1.0, 0.85+3.0*fabs( cos(0.01*spin
) ), 0.0 );
glRotatef
( 0.5*spin
, 0.0, 0.5, 1.0 );
glRotatef
( spin
, 1.0, 0.5, 0.0 );
glScalef
( 0.5, 0.5, 0.5 );
glCallList
( objects_list
[1] );
glPopMatrix
();
glPushMatrix
();
glTranslatef
( 1.0, 1.5, 0.0 );
glRotatef
( spin
, 1.0, 0.5, 0.0 );
glRotatef
( 0.5*spin
, 0.0, 0.5, 1.0 );
glCallList
( objects_list
[0] );
glPopMatrix
();
}
#endif
}
static void draw_table
( void )
{
glCallList
( table_list
);
}
static void draw
( void )
{
static GLfloat light_pos
[] = { 0.0, 20.0, 0.0, 1.0 };
GLfloat dist
= 20.0;
GLfloat eyex
, eyey
, eyez
;
glClear
( GL_COLOR_BUFFER_BIT
| GL_DEPTH_BUFFER_BIT
| GL_STENCIL_BUFFER_BIT
);
eyex
= dist
* cos(yrot
*DEG2RAD
) * cos(xrot
*DEG2RAD
);
eyez
= dist
* sin(yrot
*DEG2RAD
) * cos(xrot
*DEG2RAD
);
eyey
= dist
* sin(xrot
*DEG2RAD
);
/* view from top */
glPushMatrix
();
gluLookAt
( eyex
, eyey
, eyez
, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0 );
glLightfv
( GL_LIGHT0
, GL_POSITION
, light_pos
);
/* draw table into stencil planes */
glDisable
( GL_DEPTH_TEST
);
glEnable
( GL_STENCIL_TEST
);
glStencilFunc
( GL_ALWAYS
, 1, 0xffffffff );
glStencilOp
( GL_REPLACE
, GL_REPLACE
, GL_REPLACE
);
glColorMask
( GL_FALSE
, GL_FALSE
, GL_FALSE
, GL_FALSE
);
draw_table
();
glColorMask
( GL_TRUE
, GL_TRUE
, GL_TRUE
, GL_TRUE
);
glEnable
( GL_DEPTH_TEST
);
/* render view from below (reflected viewport) */
/* only draw where stencil==1 */
if (eyey
>0.0) {
glPushMatrix
();
glStencilFunc
( GL_EQUAL
, 1, 0xffffffff ); /* draw if ==1 */
glStencilOp
( GL_KEEP
, GL_KEEP
, GL_KEEP
);
glScalef
( 1.0, -1.0, 1.0 );
/* Reposition light in reflected space. */
glLightfv
(GL_LIGHT0
, GL_POSITION
, light_pos
);
draw_objects
(eyex
, eyey
, eyez
);
glPopMatrix
();
/* Restore light's original unreflected position. */
glLightfv
(GL_LIGHT0
, GL_POSITION
, light_pos
);
}
glDisable
( GL_STENCIL_TEST
);
glEnable
( GL_BLEND
);
glBlendFunc
( GL_SRC_ALPHA
, GL_ONE_MINUS_SRC_ALPHA
);
glEnable
( GL_TEXTURE_2D
);
draw_table
();
glDisable
( GL_TEXTURE_2D
);
glDisable
( GL_BLEND
);
/* view from top */
glPushMatrix
();
draw_objects
(eyex
, eyey
, eyez
);
glPopMatrix
();
glPopMatrix
();
glFinish
();
}
static int screen
(int mode
)
{
vga_modeinfo
*minf
;
vga_setmode
(mode
,CARD
);
minf
= vga_getmodeinfo
(mode
);
if(! (minf
->flags
& CAPABLE_LINEAR
)){
vga_setmode
(TEXT
,CARD
);
printk
(KERN_INFO
"The mode %d is not capable of linear\n",mode
);
return 1;
}
vga_setpage
(0);
if(vga_setlinearaddressing
() == -1) {
vga_setmode
(TEXT
,CARD
);
printk
(KERN_INFO
"Could not set linear addressing for mode %d\n",mode
);
return 1;
}
video_buf
= vga_getgraphmem
();
rgb_565_buf
= malloc(RGB565MEM
);
grx_setbuffer
(rgb_565_buf
, WIDTH
, HEIGHT
); //Init of RGB16 version of grx functions
//created to work with Mesa buffer
return 0;
}
void program_end
(void *arg
)
{
OSMesaDestroyContext
(ctx
);
free(rgb_565_buf
);
vga_setmode
(TEXT
,CARD
);
sys_end
();
}
void program_key_end
(KEY_EVT
*k
)
{
sys_end
();
}
TASK refresh
(void)
{
while(1) {
copy_videomem_16to16
(rgb_565_buf
, video_buf
, VMEMLONG
);
task_endcycle
();
}
sys_end
();
}
TASK disegna
(void)
{
char text
[100];
TIME disegna_TIME
, refresh_TIME
;
while(1) {
jet_gettable
(refresh_PID
, &refresh_TIME
, 1);
jet_gettable
(disegna_PID
, &disegna_TIME
, 1);
spin
+= 2.0;
yrot
+= 3.0;
draw
();
sprintf(text
,"Hard Task Refresh PER:%6d us EX:%6d us",(int)PERIOD_REFRESH
,(int)refresh_TIME
);
grx_text
(text
,10,5,rgb16
(0,0,255),0);
sprintf(text
,"Hard Task Draw PER:%6d us EX:%6d us",(int)PERIOD_DISEGNA
,(int)disegna_TIME
);
grx_text
(text
,10,15,rgb16
(0,0,255),0);
task_endcycle
();
}
sys_end
();
}
int main
(int argc
, char *argv
[])
{
HARD_TASK_MODEL ht_refresh
, ht_disegna
;
sys_atrunlevel
(program_end
,NULL
, RUNLEVEL_BEFORE_EXIT
);
WCET_REFRESH
=((long int) PERIOD_REFRESH
* (0.20));
WCET_DISEGNA
=((long int) PERIOD_DISEGNA
* (0.70));
hard_task_default_model
(ht_refresh
);
hard_task_def_wcet
(ht_refresh
,WCET_REFRESH
);
hard_task_def_mit
(ht_refresh
,PERIOD_REFRESH
);
hard_task_def_usemath
(ht_refresh
);
hard_task_def_group
(ht_refresh
,1);
hard_task_def_ctrl_jet
(ht_refresh
);
refresh_PID
= task_create
("refresh", refresh
, &ht_refresh
, NULL
);
if (refresh_PID
== -1) {
sys_end
();
exit(4);
}
hard_task_default_model
(ht_disegna
);
hard_task_def_mit
(ht_disegna
,PERIOD_DISEGNA
);
hard_task_def_wcet
(ht_disegna
,WCET_DISEGNA
);
hard_task_def_group
(ht_disegna
,1);
hard_task_def_ctrl_jet
(ht_disegna
);
hard_task_def_usemath
(ht_disegna
);
hard_task_def_stack
(ht_disegna
, 60000);
disegna_PID
= task_create
("disegna", disegna
, &ht_disegna
, NULL
);
if (disegna_PID
== -1) {
sys_end
();
exit(4);
}
{
KEY_EVT k
;
k.
flag = ALTL_BIT
;
k.
scan = KEY_C
;
k.
ascii = 'c';
keyb_hook
(k
,program_key_end
);
}
if (screen
(INITSTR
)) {
printk
(KERN_INFO
"Graphical initialization failed !!\n");
sys_end
();
}
memset(rgb_565_buf
, 0, RGB565MEM
);
gl_init
();
group_activate
(1);
return 0;
}