From b8e79deb5b362cf572a31be7cba75a6c6f602358 Mon Sep 17 00:00:00 2001 From: epoch Date: Sat, 3 Feb 2018 22:35:44 -0600 Subject: framebuffer support --- src/graphics_cs_fb.c | 577 +++++++++++++++++++++++++++++++++++++++++++++++++++ src/graphics_fb.h | 44 ++++ src/hackvr_fb.c | 1 + 3 files changed, 622 insertions(+) create mode 100644 src/graphics_cs_fb.c create mode 100644 src/graphics_fb.h create mode 120000 src/hackvr_fb.c (limited to 'src') diff --git a/src/graphics_cs_fb.c b/src/graphics_cs_fb.c new file mode 100644 index 0000000..9885bd6 --- /dev/null +++ b/src/graphics_cs_fb.c @@ -0,0 +1,577 @@ +#define _POSIX_C_SOURCE 200809L //for fileno and strdup +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "config.h" +#include "common.h" +#include "graphics_c3.h"//not needed? +#include "graphics_fb.h" +#include "graphics_cs.h" + +//typedef float real; //think this conflicts? + +//TODO: will have to make some pixmaps get resized when the window does. +//for now set them to be as big as you think you'll ever resize the window to. + +//#define SKYRULE 90 +//#define SKYW (WIDTH*5) +//#define SKYH (HEIGHT/2) + +//Pixmap skypixmap; +//char sky[SKYH][SKYW]; + +extern struct global global; +extern struct gra_global gra_global; +struct fb_global fb_global; + +#ifdef GRAPHICAL + +/* +struct plane { + c3_t p; + real xr; + real yr; + real zr; +} + +void calculate_shape_color(c3_s_t s,real d) { +//given: at least 3 points on a plane. +//needed: angles of the plane. +// + xa= + ya= + za= + for(i=0;i<;i++) { + s.p.x + } +} +*/ + +void set_luminosity_color(int lum) {//need to come up with a good range for this. + fb_global.current_color=((200-lum) << 16) | ((200-lum) << 8) | lum; +} + +void draw_cs_point(int x,int y) {//this should write to a backbuffer then I can memcopy it over. + unsigned int i=y * fb_global.info.xres + x; + if(x > fb_global.info.xres) return; + if(y > fb_global.info.yres) return; + if(i > fb_global.fblen) return; + switch(fb_global.draw_mode) { + case DRAW_MODE_COPY: + fb_global.backbuf[i]=fb_global.current_color; + break; + case DRAW_MODE_OR: + fb_global.backbuf[i] |= fb_global.current_color; + break; + case DRAW_MODE_AND: + fb_global.backbuf[i] &= fb_global.current_color; + break; + case DRAW_MODE_CLEAR: + fb_global.backbuf[i]=0; + break; + default: + printf("# derp. unknown draw_mode %d\n",fb_global.draw_mode); + break; + } +} + +void draw_cs_line(cs_t p1,cs_t p2) {//error somewhere in here. derp... + int x,y; + real m; + int b; + int xd,yd; + if(p1.x == p2.x) { + for(y=min(p1.y,p2.y);y= max(p1.y,p2.y)-min(p1.y,p2.y)) { //loop over x. like normal math. :P y=mx+b stuff. + m=((real)(p1.y-p2.y))/((real)(p1.x-p2.x)); + b=(int)((real)p1.y - (m * (real)p1.x)); + for(x=p1.x;x!=p2.x;x+=xd) { + y=(int)(m * (real)x + (real)b); + draw_cs_point(x,y); + } + } else { //loop over y + m=((real)(p1.x-p2.x))/((real)(p1.y-p2.y)); + b=(int)((real)p1.x - (m * (real)p1.y)); + for(y=p1.y;y!=p2.y;y+=yd) { + x=(int)(m * (real)y + (real)b); + draw_cs_point(x,y); + } + } + //now for the fun part. +} + +void draw_cs_text(cs_t p,char *text) { +/* char t[256]; + int direction,ascent,descent; + XFontStruct *font=XLoadQueryFont(x11_global.dpy,"fixed"); + XCharStruct overall; + snprintf(t,sizeof(t)-1,"%s",text); + XTextExtents(font,text,strlen(text),&direction,&ascent,&descent,&overall); + XDrawString(x11_global.dpy,x11_global.backbuffer,x11_global.backgc,p.x,p.y+(descent+ascent),text,strlen(text));*/ +} + +void draw_cs_shape(cs_s_t s) {//this is implemented as draw_cs_line... hrm. it could be moved up to graphics.c? probl no. + //test in here whether a mouse click is within this shape's... bounding box? sure. + cs_s_t bb;//bounding box + int minx=s.p[0].x; + int miny=s.p[0].y; + int maxx=s.p[0].x; + int maxy=s.p[0].y; + int h; + int i;//all cs shapes can have 1, 2, or 3+ points. guess I gotta do that logic here too. + switch(s.len) { + case 1: + //circle + h=max(s.p[0].x,s.p[1].x)-min(s.p[0].x,s.p[1].x); + //XDrawArc(x11_global.dpy,x11_global.backbuffer,x11_global.backgc,s.p[0].x-h,s.p[0].y-h,h*2,h*2,0,360*64); + break; + default: + for(i=0;imaxx)?s.p[i].x:maxx; + maxy=(s.p[i].y>maxy)?s.p[i].y:maxy; + draw_cs_line(s.p[i],s.p[(i+1)%(s.len+(s.len==1))]); + } + if(gra_global.mousex >= minx && + gra_global.mousey >= miny && + gra_global.mousex <= maxx && + gra_global.mousey <= maxy) { + if(gra_global.buttonpressed) {//if we're inside the bounding box let's make SOMETHING happen. + printf("%s action %s\n",global.user,s.id); + } + if(!strncmp(s.id,"term",4)) { + gra_global.input_mode=1; + } + bb.id=strdup("boundingbox"); + bb.len=4; + bb.p[0].x=minx; + bb.p[0].y=miny; + bb.p[1].x=minx; + bb.p[1].y=maxy; + bb.p[2].x=maxx; + bb.p[2].y=maxy; + bb.p[3].x=maxx; + bb.p[3].y=miny; + draw_cs_filled_shape(bb); + free(bb.id); + } + break; + } +} + +int x_from_y(cs_t p1,cs_t p2,int y) {//get the value of x given a y within a line. + real m; + int b; + int x; +// y=mx+b MAGIC + if(p1.x == p2.x) return p1.x;//if this happens then we have a verticle line and can just shortcut this shit. + if(p1.y == p2.y) {//if this happens we have a horizontal line we're trying to find the X of based on a 'y' that probably isn't in the line... + return 0; + }//return p1.x;//WE SHOULD NOT GET HERE. fuck if I know. +// y=mx+b +// y-b=mx +// x=(y-b)/m +// b=y-mx + m=((real)(p1.y-p2.y))/((real)(p1.x-p2.x)); + b=(int)((real)p1.y - (m * (real)p1.x)); + x=(int)(((real)(y-b))/m); + if(!x) printf("x == %d y=%d m=%f b=%d\n",x,y,m,b); + return x; +} + +void draw_cs_filled_shape(cs_s_t s) {//no circle handling atm. and only convex polygons. + int maxmax=0; + int minmin=0; + cs_t p1; + cs_t p2; + int i; + int y; + for(i=0;i s.p[maxmax].y || (s.p[i].y==s.p[maxmax].y && s.p[i].x > s.p[maxmax].x)) maxmax=i; + } + int a1=minmin; + int a2=(minmin+1)%s.len; + int b1=minmin; + int b2=(minmin+s.len-1)%s.len; + for(y=s.p[minmin].y;ymin_aspect.x=AR_W*(gra_global.split_screen / (gra_global.red_and_blue ? gra_global.split_screen : 1)); + //hints->min_aspect.y=AR_H; + //hints->max_aspect.x=AR_W*(gra_global.split_screen / (gra_global.red_and_blue ? gra_global.split_screen : 1)); + //hints->max_aspect.y=AR_H; + //hints->flags |= PAspect; + //XSetWMNormalHints(x11_global.dpy,x11_global.w,hints); + //XFree(hints); +} + +void set_demands_attention() { + //XWMHints *hints=XGetWMHints(x11_global.dpy,x11_global.w); + //if(!hints) hints=XAllocWMHints(); + //hints->flags |= XUrgencyHint; + //XSetWMHints(x11_global.dpy,x11_global.w,hints); + //XFree(hints); +} + +#endif + +int graphics_sub_init() { + int i; + int x,y; + fb_global.fb=open("/dev/fb0",O_RDWR); + fb_global.kb=open("/dev/input/event0",O_RDWR); + memset(fb_global.keystate,0,sizeof(fb_global.keystate)); + fcntl(fb_global.kb,F_SETFL,O_NONBLOCK); + assert(fb_global.fb > 0); + assert( 0 == ioctl(fb_global.fb,FBIOGET_VSCREENINFO,&fb_global.info)); + fb_global.fblen = 4 * fb_global.info.xres * fb_global.info.yres; + fb_global.buf = mmap(NULL,fb_global.fblen,PROT_READ | PROT_WRITE,MAP_SHARED, fb_global.fb,0); + fb_global.backbuf = malloc(fb_global.fblen); + assert(fb_global.buf != MAP_FAILED); + //now... how to generate 200 greys.... + //heh. + for(x=0;x>(4*(1-(i%2)))) % 16]; + line2[i]=0; + printf("%s data %s\n",global.user,line2); + break; + } + + //then do stuff based on what keystates are set. + //... loop over the whole array? + //have an array of deltas? + //what sets mask? + char motionnotify=0; + unsigned int mask; + if(global.beep) { + global.beep=0; + XBell(x11_global.dpy,1000); + set_demands_attention(); + } + while(XPending(x11_global.dpy)) {//these are taking too long? + XNextEvent(x11_global.dpy, &e); +// fprintf(stderr,"# handling event with type: %d\n",e.type); + switch(e.type) { +// case Expose: +// if(e.xexpose.count == 0) redraw=1; +// break; + case MotionNotify: + if(global.debug >= 2) fprintf(stderr,"# MotionNotify\n"); + motionnotify=1; + break; + case ButtonPress: + if(global.debug >= 2) fprintf(stderr,"# ButtonPress\n"); + redraw=1; + gra_global.buttonpressed=e.xbutton.button;//what's this for? mouse? + break; + case ButtonRelease: + if(global.debug >= 2) fprintf(stderr,"# ButtonRelease\n"); + redraw=1; + gra_global.buttonpressed=0;//what's this for??? + break; + case ConfigureNotify: + if(global.debug >= 2) fprintf(stderr,"# ConfigureNotify\n"); + redraw=1; + XGetGeometry(x11_global.dpy,x11_global.w,&root,&global.x,&global.y,&gra_global.width,&gra_global.height,&gra_global.border_width,&gra_global.depth); + if(gra_global.height * AR_W / AR_H != gra_global.width / (gra_global.split_screen / (gra_global.red_and_blue ? gra_global.split_screen : 1))) { + // height / AR_H * AR_W = width / (ss / (rab ? ss : 1)) + if(global.debug >= 2) { + fprintf(stderr,"# %d != %d for some reason. probably your WM not respecting aspect ratio hints or calculating based on them differently. (would cause an off-by-one or so)\n",gra_global.height * AR_W / AR_H , gra_global.width / (gra_global.split_screen / (gra_global.red_and_blue ? gra_global.split_screen : 1))); + } + if(gra_global.width / (gra_global.red_and_blue ? 1 : gra_global.split_screen) * AR_H / AR_W < gra_global.height) { + gra_global.height=gra_global.width / (gra_global.red_and_blue ? 1 : gra_global.split_screen) * AR_H / AR_W; + } else { + gra_global.width=gra_global.height * AR_W / AR_H * (gra_global.red_and_blue ? 1 : gra_global.split_screen); + } + } + gra_global.mapxoff=gra_global.width/(gra_global.split_screen / (gra_global.red_and_blue ? gra_global.split_screen : 1))/2; + gra_global.mapyoff=gra_global.height/2; + break; + case KeyPress: + if(global.debug >= 2) fprintf(stderr,"# KeyPress\n"); + redraw=1; + x11_keypress_handler(&e.xkey,gra_global.mousex,gra_global.mousey); + break; + default: +// fprintf(stderr,"# received unknown event with type: %d\n",e.type); + break; + } + } + if(motionnotify) { + XQueryPointer(x11_global.dpy,x11_global.w,&root,&child,&gra_global.rmousex,&gra_global.rmousey,&gra_global.mousex,&gra_global.mousey,&mask); + redraw=1; + } +*/ + if(redraw || world_changed) { + gra_global.input_mode=0; + draw_screen();//includes its own flip. + } + return 1;//redraw; +} diff --git a/src/graphics_fb.h b/src/graphics_fb.h new file mode 100644 index 0000000..d6e8d7c --- /dev/null +++ b/src/graphics_fb.h @@ -0,0 +1,44 @@ +#ifndef _HACKVR_GRAPHICS_FB_H_ +#define _HACKVR_GRAPHICS_FB_H_ + +//find this with trial and error or X11 log or... I don't care. +#define FB_KEYB "/dev/input/event0" + +#include + +#define DRAW_MODE_CLEAR 0x0 +#define DRAW_MODE_AND 0x1 +#define DRAW_MODE_COPY 0x3 +#define DRAW_MODE_OR 0x7 + +struct fb_global { + int fb; + int kb; + int draw_mode; + unsigned int current_color; + unsigned int *backbuf; + struct fb_var_screeninfo info; + unsigned int *buf; + unsigned int fblen; + char keystate[KEY_MAX/8+1]; +}; + +#endif +#if 0 +#define GXclear 0x0 /* 0 */ +#define GXand 0x1 /* src AND dst */ +#define GXandReverse 0x2 /* src AND NOT dst */ +#define GXcopy 0x3 /* src */ +#define GXandInverted 0x4 /* NOT src AND dst */ +#define GXnoop 0x5 /* dst */ +#define GXxor 0x6 /* src XOR dst */ +#define GXor 0x7 /* src OR dst */ +#define GXnor 0x8 /* NOT src AND NOT dst */ +#define GXequiv 0x9 /* NOT src XOR dst */ +#define GXinvert 0xa /* NOT dst */ +#define GXorReverse 0xb /* src OR NOT dst */ +#define GXcopyInverted 0xc /* NOT src */ +#define GXorInverted 0xd /* NOT src OR dst */ +#define GXnand 0xe /* NOT src OR NOT dst */ +#define GXset 0xf /* 1 */ +#endif diff --git a/src/hackvr_fb.c b/src/hackvr_fb.c new file mode 120000 index 0000000..e4c9ddd --- /dev/null +++ b/src/hackvr_fb.c @@ -0,0 +1 @@ +hackvr.c \ No newline at end of file -- cgit v1.2.3