Browse Source

Major refactoring, got working with color changes

master
Wesley Kerfoot 5 years ago
parent
commit
4c824098ee
  1. 264
      blit_xcb.c

264
blit_xcb.c

@ -1,5 +1,3 @@
#include <GL/gl.h>
#include <GL/glx.h>
#include <X11/Xlib-xcb.h> /* for XGetXCBConnection, link with libX11-xcb */ #include <X11/Xlib-xcb.h> /* for XGetXCBConnection, link with libX11-xcb */
#include <X11/Xlib.h> #include <X11/Xlib.h>
#include <assert.h> #include <assert.h>
@ -8,14 +6,18 @@
#include <time.h> #include <time.h>
#include <unistd.h> #include <unistd.h>
#include <xcb/xcb.h> #include <xcb/xcb.h>
#include <xcb/xcb.h>
typedef struct {
unsigned short r;
unsigned short g;
unsigned short b;
} color_t;
xcb_alloc_color_reply_t* xcb_alloc_color_reply_t*
getColor(xcb_connection_t*, getColorFromCmap(xcb_connection_t*,
xcb_colormap_t, xcb_colormap_t,
unsigned short, color_t);
unsigned short,
unsigned short);
/* Macro definition to parse X server events /* Macro definition to parse X server events
* The ~0x80 is needed to get the lower 7 bits * The ~0x80 is needed to get the lower 7 bits
@ -33,7 +35,6 @@ getColor(xcb_connection_t*,
* Figure out what resources need to be free'd and figure out a strategy for allocating things better * Figure out what resources need to be free'd and figure out a strategy for allocating things better
* Figure out a better way of managing the event loop than nanosleep? (clock_nanosleep maybe) * Figure out a better way of managing the event loop than nanosleep? (clock_nanosleep maybe)
* Figure out which events we need to actually be handling * Figure out which events we need to actually be handling
* Figure out how to resize dynamically (See handmade hero videos for tips)
* Figure out good strategy for only copying changed pixels to window * Figure out good strategy for only copying changed pixels to window
* Figure out what allocations can fail and what to do if they fail * Figure out what allocations can fail and what to do if they fail
*/ */
@ -111,20 +112,18 @@ allocateColorMap(xcb_connection_t *display,
} }
xcb_alloc_color_reply_t* xcb_alloc_color_reply_t*
getColor(xcb_connection_t *display, getColorFromCmap(xcb_connection_t *display,
xcb_colormap_t colormap, xcb_colormap_t colormap,
unsigned short red, color_t color) {
unsigned short green, /* Allocate a color in the color map */
unsigned short blue) {
/* Return a new xcb color structure */
/* Initialize it with RGB */ /* Initialize it with RGB */
xcb_alloc_color_reply_t *reply = xcb_alloc_color_reply(display, xcb_alloc_color_reply_t *reply = xcb_alloc_color_reply(display,
xcb_alloc_color(display, xcb_alloc_color(display,
colormap, colormap,
red, color.r,
green, color.g,
blue), color.b),
NULL); NULL);
/* TODO, make sure colors get free'd after they're used? /* TODO, make sure colors get free'd after they're used?
@ -149,19 +148,15 @@ static xcb_gcontext_t
getGC(xcb_connection_t *display, getGC(xcb_connection_t *display,
xcb_screen_t *screen, xcb_screen_t *screen,
xcb_colormap_t colormap, xcb_colormap_t colormap,
unsigned short r, color_t color) {
unsigned short g,
unsigned short b) {
xcb_drawable_t window = screen->root; xcb_drawable_t window = screen->root;
xcb_gcontext_t foreground = xcb_generate_id(display); xcb_gcontext_t foreground = xcb_generate_id(display);
xcb_alloc_color_reply_t *xcolor = getColor(display, xcb_alloc_color_reply_t *xcolor = getColorFromCmap(display,
colormap, colormap,
r, color);
g,
b);
uint32_t mask = XCB_GC_FOREGROUND | XCB_GC_GRAPHICS_EXPOSURES; uint32_t mask = XCB_GC_FOREGROUND | XCB_GC_GRAPHICS_EXPOSURES;
uint32_t values[2] = {xcolor->pixel, 0}; uint32_t values[2] = {xcolor->pixel, 0};
@ -175,35 +170,36 @@ getGC(xcb_connection_t *display,
return foreground; return foreground;
} }
static xcb_pixmap_t static xcb_void_cookie_t
allocatePixmap(xcb_connection_t *display, updateGCColor(xcb_connection_t *display,
xcb_screen_t *screen, xcb_gcontext_t gc,
xcb_window_t window, xcb_colormap_t colormap,
uint32_t width, color_t color) {
uint32_t height) { /* https://www.x.org/releases/X11R7.6/doc/libxcb/tutorial/index.html#changegc */
xcb_pixmap_t pixmapId = xcb_generate_id(display);
xcb_create_pixmap(display,
screen->root_depth,
pixmapId,
window,
width,
height);
return pixmapId; xcb_alloc_color_reply_t *xcolor = getColorFromCmap(display,
colormap,
color);
uint32_t mask = XCB_GC_FOREGROUND | XCB_GC_GRAPHICS_EXPOSURES;
uint32_t values[2] = {xcolor->pixel, 0};
return xcb_change_gc(display,
gc,
mask,
values);
} }
xcb_point_t* xcb_point_t*
genPoints(uint16_t width, genPoints(uint16_t width,
uint16_t height) { uint16_t height) {
/* Fills the entire screen with pixels */
xcb_point_t *points = malloc( sizeof(xcb_point_t) * height * width); xcb_point_t *points = malloc( sizeof(xcb_point_t) * height * width);
xcb_point_t point; xcb_point_t point;
int i = 0; int i = 0;
printf("width = %d, height = %d\n", width, height);
for (uint16_t x = 0; x < width; x++) { for (uint16_t x = 0; x < width; x++) {
for(uint16_t y = 0; y < height; y++) { for(uint16_t y = 0; y < height; y++) {
point.x = x; point.x = x;
@ -218,17 +214,101 @@ genPoints(uint16_t width,
return points; return points;
} }
void
displayBuffer(xcb_pixmap_t pixmap_buffer,
xcb_connection_t *display,
xcb_window_t window,
xcb_gcontext_t gc,
xcb_expose_event_t *event) {
/* Note that x = 0, y = 0, is the top left of the screen */
xcb_copy_area(display,
pixmap_buffer,
window,
gc,
0, /* top left x coord */
0, /* top left y coord */
event->x, /* top left x coord of dest*/
event->y, /* top left y coord of dest*/
event->width, /* pixel width of source */
event->height /* pixel height of source */
);
xcb_flush(display);
}
void
writePixmap(xcb_pixmap_t pixmap_buffer,
color_t color,
xcb_colormap_t colormap,
xcb_point_t *points,
xcb_gcontext_t gc,
xcb_connection_t *display,
xcb_window_t window,
xcb_expose_event_t *event) {
printf("Drawing pixmap\nr = %u, g = %u, b = %u\n", color.r, color.g, color.b);
updateGCColor(display,
gc,
colormap,
color);
xcb_poly_point(display,
XCB_COORD_MODE_ORIGIN, /* Coordinate mode, usually set to XCB_COORD_MODE_ORIGIN */
pixmap_buffer,
gc,
event->width*event->height,
points);
displayBuffer(pixmap_buffer,
display,
window,
gc,
event);
}
xcb_pixmap_t
getPixmap(xcb_connection_t *display,
xcb_screen_t *screen,
xcb_window_t window,
uint16_t window_width,
uint16_t window_height) {
/* Allocate a pixmap we will be blitting to the window */
xcb_pixmap_t pixmapId = xcb_generate_id(display);
xcb_create_pixmap(display,
screen->root_depth,
pixmapId,
window,
window_width,
window_height);
return pixmapId;
}
static color_t
color(unsigned short r,
unsigned short g,
unsigned short b) {
/* Initialize an RGB color struct */
color_t color;
color.r = r;
color.g = g;
color.b = b;
return color;
}
int int
main(void) { main(void) {
uint16_t window_width = 500;
uint16_t window_height = 500;
/* Open up the display */ /* Open up the display */
xcb_connection_t *display = getDisplay(); xcb_connection_t *display = getDisplay();
/* Get a handle to the screen */ /* Get a handle to the screen */
xcb_screen_t *screen = getScreen(display); xcb_screen_t *screen = getScreen(display);
uint16_t window_height = screen->height_in_pixels;
uint16_t window_width = screen->width_in_pixels;
/* Create a window */ /* Create a window */
xcb_window_t window = getWindow(display, xcb_window_t window = getWindow(display,
screen, screen,
@ -248,15 +328,25 @@ main(void) {
struct timespec req = genSleep(0, 20000000); struct timespec req = genSleep(0, 20000000);
struct timespec rem = genSleep(0, 0); struct timespec rem = genSleep(0, 0);
color_t draw_color = color(0, 0, 0);
xcb_generic_event_t *event; xcb_generic_event_t *event;
xcb_expose_event_t *expose; xcb_expose_event_t *expose;
xcb_gcontext_t gc = getGC(display, xcb_gcontext_t gc = getGC(display,
screen, screen,
colormap, colormap,
0, draw_color);
0xffff,
0); /* The pixmap that acts as our backbuffer */
xcb_pixmap_t pixmap_buffer = getPixmap(display,
screen,
window,
window_width,
window_height);
int was_exposed = 0;
while (1) { while (1) {
event = xcb_poll_for_event(display); event = xcb_poll_for_event(display);
@ -267,59 +357,24 @@ main(void) {
case XCB_EXPOSE: { case XCB_EXPOSE: {
expose = (xcb_expose_event_t *)event; expose = (xcb_expose_event_t *)event;
window_width = expose->width;
window_height = expose->height;
printf("Window %u exposed. Region to be redrawn at location (%u,%u), with dimension (%u,%u)\n", printf("Window %u exposed. Region to be redrawn at location (%u,%u), with dimension (%u,%u)\n",
expose->window, expose->x, expose->window, expose->x,
expose->y, expose->y,
expose->width, expose->width,
expose->height); expose->height);
window_width = expose->width;
window_height = expose->height;
/*
* One important note should be made:
* it is possible to create pixmaps with different depths on the same screen.
* When we perform copy operations (a pixmap onto a window, etc),
* we should make sure that both source and target have the same depth.
* If they have a different depth, the operation will fail.
* The exception to this is if we copy a specific bit plane of the source pixmap using xcb_copy_plane().
* In such an event, we can copy a specific plane to the target window
* (in actuality, setting a specific bit in the color of each pixel copied).
* This can be used to generate strange graphic effects in a window, but that is beyond the scope of this tutorial.
*/
/* Allocate a pixmap we will be blitting to the window */
xcb_pixmap_t pixmap = allocatePixmap(display,
screen,
window,
window_width,
window_height);
xcb_point_t *points = genPoints(window_width, window_height); xcb_point_t *points = genPoints(window_width, window_height);
writePixmap(pixmap_buffer,
xcb_poly_point (display, /* The connection to the X server */ draw_color,
XCB_COORD_MODE_ORIGIN, /* Coordinate mode, usually set to XCB_COORD_MODE_ORIGIN */ colormap,
pixmap, /* The drawable on which we want to draw the point(s) */ points,
gc, /* The Graphic Context we use to draw the point(s) */ gc,
window_width*window_height, /* The number of points */ display,
points); /* An array of points */ window,
expose);
xcb_copy_area(display, was_exposed = 1;
pixmap,
window,
gc,
0, /* top left x coord */
0, /* top left y coord */
0, /* top left x coord of dest*/
0, /* top left y coord of dest*/
window_width, /* pixel width of source */
window_height /* pixel height of source */
);
xcb_flush(display);
free(points);
xcb_free_pixmap(display, pixmap);
break; break;
} }
@ -331,10 +386,29 @@ main(void) {
free(event); free(event);
} }
} }
if (was_exposed) {
xcb_point_t *points = genPoints(window_width, window_height);
writePixmap(pixmap_buffer,
draw_color,
colormap,
points,
gc,
display,
window,
expose);
}
draw_color.r += 100;
/* General strategy for writing to buffer
* Function should take point(s), color, and write it
*/
nanosleep(&req, &rem); nanosleep(&req, &rem);
} }
xcb_free_pixmap(display, pixmap_buffer);
xcb_disconnect(display); xcb_disconnect(display);
return 0; return 0;

Loading…
Cancel
Save