Created
August 13, 2012 19:54
-
-
Save magcius/3343639 to your computer and use it in GitHub Desktop.
Draw in a buffer we created ourselves
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* gcc -o drawinbuffer drawinbuffer.c $(pkg-config --cflags --libs glib-2.0 libdrm) */ | |
#include <glib.h> | |
#include <fcntl.h> | |
#include <stdlib.h> | |
#include <sys/mman.h> | |
#include <unistd.h> | |
#include <xf86drm.h> | |
#include <xf86drmMode.h> | |
int | |
main (int argc, char **argv) | |
{ | |
int i; | |
int fd; | |
drmModeRes *resources = NULL; | |
drmModeConnector *connector = NULL; | |
drmModeEncoder *encoder = NULL; | |
drmModeCrtc *crtc = NULL; | |
struct drm_mode_create_dumb create_dumb_buffer_request = { 0 }; | |
struct drm_mode_map_dumb map_dumb_buffer_request = { 0 }; | |
uint32_t buffer_id = 0; | |
unsigned char *pixels; | |
fd = open ("/dev/dri/card0", O_RDWR); | |
if (fd < 0) | |
{ | |
g_warning ("Unable to open DRI device"); | |
exit (1); | |
} | |
resources = drmModeGetResources (fd); | |
/* Find the first active connector to display on. */ | |
for (i = 0; i < resources->count_connectors; i++) | |
{ | |
connector = drmModeGetConnector (fd, resources->connectors[i]); | |
if (connector == NULL) | |
continue; | |
if (connector->connection == DRM_MODE_CONNECTED && | |
connector->count_modes > 0) | |
break; | |
drmModeFreeConnector(connector); | |
} | |
if (i == resources->count_connectors) | |
{ | |
g_warning ("Could not find an active connector"); | |
exit (1); | |
} | |
/* Find the CRTC. */ | |
encoder = drmModeGetEncoder (fd, connector->encoder_id); | |
crtc = drmModeGetCrtc (fd, encoder->crtc_id); | |
/* Create ourselves a new buffer on the card. */ | |
create_dumb_buffer_request.width = crtc->mode.hdisplay; | |
create_dumb_buffer_request.height = crtc->mode.vdisplay; | |
create_dumb_buffer_request.bpp = 32; | |
create_dumb_buffer_request.flags = 0; | |
if (drmIoctl (fd, DRM_IOCTL_MODE_CREATE_DUMB, | |
&create_dumb_buffer_request) < 0) | |
{ | |
g_warning ("Could not allocate frame buffer %m"); | |
exit (1); | |
} | |
/* Tell DRM that the buffer on the card is a framebuffer, | |
* and its properties. */ | |
if (drmModeAddFB (fd, | |
create_dumb_buffer_request.width, | |
create_dumb_buffer_request.height, | |
24, /* depth */ | |
create_dumb_buffer_request.bpp, | |
create_dumb_buffer_request.pitch, | |
create_dumb_buffer_request.handle, | |
&buffer_id) != 0) | |
{ | |
g_warning ("Could not tell DRM about frame buffer %m"); | |
exit (1); | |
} | |
/* Draw on the buffer */ | |
map_dumb_buffer_request.handle = create_dumb_buffer_request.handle; | |
if (drmIoctl (fd, DRM_IOCTL_MODE_MAP_DUMB, | |
&map_dumb_buffer_request) < 0) | |
{ | |
g_warning ("Could not map buffer %m"); | |
exit (1); | |
} | |
pixels = mmap (0, create_dumb_buffer_request.size, | |
PROT_READ | PROT_WRITE, MAP_SHARED, | |
fd, map_dumb_buffer_request.offset); | |
if (pixels == MAP_FAILED) | |
{ | |
g_warning ("Could not mmap buffer %m"); | |
exit (1); | |
} | |
{ | |
int x, y; | |
int stride = create_dumb_buffer_request.pitch; | |
/* Draw a red rectangle */ | |
for (y = 20; y < 100; y++) | |
{ | |
for (x = 20; x < 100; x++) | |
{ | |
unsigned char *ptr = &pixels[y * stride + x * 4]; | |
uint32_t *pixel = (uint32_t *) ptr; | |
/* ARGB */ | |
*pixel = 0xFFFF0000; | |
} | |
} | |
} | |
/* Set the CRTC to show this buffer for five seconds. */ | |
if (drmModeSetCrtc (fd, | |
crtc->crtc_id, | |
buffer_id, | |
0, 0, /* x, y */ | |
&connector->connector_id, 1, /* connector */ | |
&crtc->mode) != 0) | |
{ | |
g_warning ("Could not set CRTC to display buffer %m"); | |
exit (1); | |
} | |
sleep (5); | |
/* After five seconds, revert back to the old buffer. */ | |
/* The CRTC structure has all the information that we | |
* need to revert back to the old buffer. */ | |
if (drmModeSetCrtc (fd, | |
crtc->crtc_id, | |
crtc->buffer_id, | |
crtc->x, | |
crtc->y, | |
&connector->connector_id, 1, /* connector */ | |
&crtc->mode) != 0) | |
{ | |
g_warning ("Could not revert back to the old buffer"); | |
exit (1); | |
} | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment