honey

very old unfinished project. tracking so i dont lose it
git clone git://moonbender.net/honey
Log | Files | Refs | README

xdraw.c (5888B)


      1 #include <math.h>
      2 #include <stdio.h>
      3 
      4 #include <sys/ipc.h>
      5 #include <sys/shm.h>
      6 
      7 #include <xcb/xcb.h>
      8 #include <xcb/shm.h>
      9 #include <xcb/xcb_image.h>
     10 
     11 #include "xdraw.h"
     12 #include "common.h"
     13 
     14 extern uint8_t running;
     15 
     16 //window vars
     17 uint8_t WindowResize = 0;
     18 uint16_t WWidth = XREZ;
     19 uint16_t WHeight = YREZ;
     20 uint16_t RWidth = XREZ;
     21 uint16_t RHeight = YREZ;
     22 
     23 //xcb vars
     24 xcb_connection_t *c;
     25 xcb_screen_t *screen;
     26 xcb_drawable_t win;
     27 xcb_gcontext_t gc;
     28 xcb_colormap_t colormap;
     29 
     30 //shm vars
     31 xcb_shm_segment_info_t shinfo;
     32 uint32_t* bb;
     33 xcb_pixmap_t bbpix;
     34 
     35 
     36 //the color palette buffer
     37 xcb_alloc_color_reply_t *colors[256];
     38 
     39 //for detecting when the window's closed
     40 xcb_intern_atom_reply_t *delete_reply;
     41 
     42 void InitWindow()
     43 {
     44 	if (!XREZ || !YREZ)
     45 	{
     46 		running = 0;
     47 	}
     48 
     49 	c = xcb_connect (NULL, NULL);
     50 	
     51 	screen = xcb_setup_roots_iterator(xcb_get_setup(c)).data;
     52 
     53 	//create window
     54 	win = xcb_generate_id(c);
     55 	uint32_t mask = XCB_CW_BACK_PIXEL | 
     56 			XCB_CW_EVENT_MASK;  
     57 	uint32_t winvals[2];
     58 	winvals[0] = 	screen->black_pixel;
     59 	winvals[1] = 	XCB_EVENT_MASK_EXPOSURE | 
     60 			XCB_EVENT_MASK_KEY_PRESS |
     61 			XCB_EVENT_MASK_STRUCTURE_NOTIFY |
     62 			XCB_EVENT_MASK_POINTER_MOTION |
     63 			XCB_EVENT_MASK_BUTTON_MOTION |
     64 			XCB_EVENT_MASK_BUTTON_2_MOTION;
     65 	xcb_create_window (	c,
     66 						XCB_COPY_FROM_PARENT,
     67 						win,
     68 						screen->root,
     69 						0, 0,
     70 						150, 150,
     71 						10,
     72 						XCB_WINDOW_CLASS_INPUT_OUTPUT,
     73 						screen->root_visual,
     74 						mask, winvals );
     75 	gc = xcb_generate_id(c);
     76 
     77 	//create graphics context
     78 	mask = XCB_GC_FOREGROUND | XCB_GC_GRAPHICS_EXPOSURES;
     79 	uint32_t gcvals[2];
     80 	gcvals[0] =	screen->white_pixel;
     81 	gcvals[1] =	0;
     82 	xcb_create_gc (	c,
     83 					gc,
     84 					win,
     85 					mask,
     86 					gcvals );
     87 					
     88 	colormap = screen->default_colormap;
     89 
     90 	for (int i = 0; i < 256; i++)
     91 	{
     92 		colors[i] = NULL;
     93 	}
     94 
     95 	//set up to detect when the window is closed
     96 	xcb_intern_atom_cookie_t protocol_cookie = 
     97 		xcb_intern_atom(c, 1, 12, "WM_PROTOCOLS");
     98 	xcb_intern_atom_reply_t *protocol_reply =
     99 		xcb_intern_atom_reply(c, protocol_cookie, 0);
    100 	xcb_intern_atom_cookie_t delete_cookie =
    101 		xcb_intern_atom(c, 0, 16, "WM_DELETE_WINDOW");
    102 	delete_reply = xcb_intern_atom_reply( c, delete_cookie, 0);
    103 	xcb_change_property (	c,
    104 							XCB_PROP_MODE_REPLACE,
    105 							win,
    106 							(*protocol_reply).atom,
    107 							4, 32, 1,
    108 							&(*delete_reply).atom	);
    109 	free(protocol_reply);
    110 
    111 
    112 	xcb_map_window(c, win);
    113 
    114 	//Shm stuff
    115 	xcb_shm_query_version_reply_t* shreply;
    116 
    117 	shreply = xcb_shm_query_version_reply(	c,
    118 											xcb_shm_query_version(c),
    119 											NULL	);
    120 
    121 	if(!shreply || !shreply->shared_pixmaps)
    122 	{
    123 		printf("Shm error\n");
    124 		running = 0;
    125 	}
    126 
    127 	shinfo.shmid = shmget(	IPC_PRIVATE, 
    128 							1920*1080*4, //todo: change to screen size
    129 							IPC_CREAT | 0600	);
    130 	shinfo.shmaddr = shmat(shinfo.shmid, 0, 0);
    131 	shinfo.shmseg = xcb_generate_id(c);
    132 	xcb_shm_attach(c, shinfo.shmseg, shinfo.shmid, 0);
    133 	shmctl(shinfo.shmid, IPC_RMID, 0);
    134 	bb = (uint32_t*)shinfo.shmaddr;
    135 
    136 
    137 	bbpix = xcb_generate_id(c);
    138 	xcb_shm_create_pixmap	(	c, bbpix, win,
    139 								1920, 1080,
    140 								screen->root_depth,
    141 								shinfo.shmseg, 0	);
    142 	xcb_flush(c);
    143 }
    144 
    145 void LoadPalette(uint32_t *pal)
    146 {
    147 	for (int i = 0; i < 256; ++i)
    148 	{
    149 		if (colors[i])
    150 		{
    151 			free(colors[i]);
    152 		}
    153 		uint32_t col = *(pal + i);
    154 		int blue = (col & 0xff) * 257;
    155 		int green = ((col >> 8) & 0xff) * 257;
    156 		int red = ((col >> 16) & 0xff) * 257;
    157 		xcb_alloc_color_cookie_t coogie = xcb_alloc_color (	c,
    158 															colormap,
    159 															red,
    160 															green,
    161 															blue	);
    162 		colors[i] = xcb_alloc_color_reply(c, coogie, NULL);
    163 	}	
    164 }
    165 
    166 //Update the width and height of the actual drawing area
    167 void UpdateRScreen()
    168 {
    169 	//preserve aspect ratio
    170 	float ratio;
    171 
    172 	ratio = (float)XREZ / (float)YREZ;
    173 
    174 	if ((WWidth)  > (WHeight * ratio))
    175 	{
    176 		RHeight = WHeight;
    177 		RWidth = (uint16_t)(RHeight * ratio);
    178 	}
    179 	else
    180 	{
    181 		RWidth = WWidth;
    182 		RHeight = (uint16_t)(RWidth / ratio);
    183 	}
    184 }
    185 
    186 void DrawPixel(uint16_t x, uint16_t y, uint8_t color)
    187 {
    188 	if (color)
    189 	{
    190 		bb[y * 1920 + x] = colors[color]->pixel;
    191 	}
    192 }
    193 
    194 //Draw to the screen
    195 void DrawBuffer(uint8_t* buf)
    196 {
    197 	UpdateRScreen();
    198 
    199 	double xratio = XREZ / (double)RWidth;
    200 	double yratio = YREZ / (double)RHeight;
    201 	double px, py;
    202 	for (int i = 0; i < RHeight; i++)
    203 	{
    204 		for (int j = 0; j < RWidth; j++)
    205 		{
    206 			uint8_t color;
    207 			px = floor(j * xratio);
    208 			py = floor(i * yratio);
    209 			color = *(buf + (uint32_t)((py * XREZ) + px));
    210 			//draw to backbuffer
    211 			DrawPixel(j, i, color);
    212 		}
    213 	}
    214 	xcb_copy_area	(	c, bbpix, win, gc,
    215 						0, 0, 0, 0,
    216 						RWidth, RHeight	);
    217 	xcb_flush(c);
    218 }
    219 
    220 void HandleEvents()
    221 {
    222 	xcb_generic_event_t *e;
    223 	xcb_configure_notify_event_t *confevent;
    224 	xcb_motion_notify_event_t *motionevent;
    225 	WindowResize = 0;
    226 	e = xcb_poll_for_event(c);
    227 	if (e)
    228 	{
    229 		switch(e->response_type & ~0x80)
    230 		{
    231 			//close
    232 			case XCB_CLIENT_MESSAGE:
    233 				if ((*(xcb_client_message_event_t*)e).data.data32[0]
    234 					== (*delete_reply).atom)
    235 				{
    236 					running = 0;
    237 					free(delete_reply);
    238 				}
    239 				break;
    240 			//TODO: Pause rendering while the window is resizing?
    241 			case XCB_CONFIGURE_NOTIFY:
    242 				confevent = (xcb_configure_notify_event_t*)e;
    243 				if ( 	(	(confevent->width > 0) && 
    244 							(WWidth != confevent->width) ) ||
    245 						(	(confevent->height > 0) &&
    246 							(WHeight !=	confevent->height) ) )
    247 				{
    248 					WindowResize = 1;
    249 					WWidth = confevent->width;
    250 					WHeight = confevent->height;
    251 				}
    252 				break;
    253 			case XCB_MOTION_NOTIFY:
    254 				motionevent = (xcb_motion_notify_event_t*)e;
    255 				uint32_t x, y;
    256 				x = (uint32_t)motionevent->event_x;
    257 				y = (uint32_t)motionevent->event_y;
    258 				UpdateCursor(x, y);
    259 				if ( motionevent->state & XCB_BUTTON_MASK_2 )
    260 				{
    261 					Mouse2Pressed();
    262 				}
    263 				break;
    264 		}
    265 	}
    266 	free(e);
    267 
    268 }
    269 
    270 void Cleanup()
    271 {
    272 	for (int i = 0; i < 256; ++i)
    273 	{
    274 		free(colors[i]);
    275 	}
    276 	xcb_shm_detach(c, shinfo.shmseg);
    277 	shmdt(shinfo.shmaddr);
    278 	
    279 	xcb_free_pixmap(c, bbpix);
    280 
    281 	xcb_destroy_window(c, win);
    282 	xcb_disconnect(c);
    283 }