aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drmtools.c61
-rw-r--r--drmtools.h2
-rw-r--r--fb-gui.c2
-rw-r--r--fbi.c4
-rw-r--r--fbpdf.c21
-rw-r--r--gfx.h4
6 files changed, 59 insertions, 35 deletions
diff --git a/drmtools.c b/drmtools.c
index ac501d5..4ba3dfd 100644
--- a/drmtools.c
+++ b/drmtools.c
@@ -25,11 +25,12 @@ static drmModeConnector *conn = NULL;
static drmModeEncoder *enc = NULL;
static drmModeModeInfo *mode = NULL;
static drmModeCrtc *scrtc = NULL;
-static uint32_t fb_id;
-/* dumb fb */
-static struct drm_mode_create_dumb creq;
-static uint8_t *fbmem;
+struct drmfb {
+ uint32_t id;
+ struct drm_mode_create_dumb creq;
+ uint8_t *mem;
+} fb1, fb2, *fbc;
/* ------------------------------------------------------------------ */
@@ -141,23 +142,24 @@ static int drm_init_dev(const char *dev, const char *output)
return 0;
}
-static int drm_init_fb(void)
+static int drm_init_fb(struct drmfb *fb)
{
struct drm_mode_map_dumb mreq;
int rc;
/* create framebuffer */
- memset(&creq, 0, sizeof(creq));
- creq.width = mode->hdisplay;
- creq.height = mode->vdisplay;
- creq.bpp = 32;
- rc = drmIoctl(fd, DRM_IOCTL_MODE_CREATE_DUMB, &creq);
+ memset(&fb->creq, 0, sizeof(fb->creq));
+ fb->creq.width = mode->hdisplay;
+ fb->creq.height = mode->vdisplay;
+ fb->creq.bpp = 32;
+ rc = drmIoctl(fd, DRM_IOCTL_MODE_CREATE_DUMB, &fb->creq);
if (rc < 0) {
fprintf(stderr, "drm: DRM_IOCTL_MODE_CREATE_DUMB: %s\n", strerror(errno));
return -1;
}
- rc = drmModeAddFB(fd, creq.width, creq.height, 24, 32, creq.pitch,
- creq.handle, &fb_id);
+ rc = drmModeAddFB(fd, fb->creq.width, fb->creq.height,
+ 24, 32, fb->creq.pitch,
+ fb->creq.handle, &fb->id);
if (rc < 0) {
fprintf(stderr, "drm: drmModeAddFB() failed\n");
return -1;
@@ -165,25 +167,26 @@ static int drm_init_fb(void)
/* map framebuffer */
memset(&mreq, 0, sizeof(mreq));
- mreq.handle = creq.handle;
+ mreq.handle = fb->creq.handle;
rc = drmIoctl(fd, DRM_IOCTL_MODE_MAP_DUMB, &mreq);
if (rc < 0) {
fprintf(stderr, "drm: DRM_IOCTL_MODE_MAP_DUMB: %s\n", strerror(errno));
return -1;
}
- fbmem = mmap(0, creq.size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, mreq.offset);
- if (fbmem == MAP_FAILED) {
+ fb->mem = mmap(0, fb->creq.size, PROT_READ | PROT_WRITE, MAP_SHARED,
+ fd, mreq.offset);
+ if (fb->mem == MAP_FAILED) {
fprintf(stderr, "drm: framebuffer mmap: %s\n", strerror(errno));
return -1;
}
return 0;
}
-static int drm_show_fb(void)
+static int drm_show_fb(struct drmfb *fb)
{
int rc;
- rc = drmModeSetCrtc(fd, enc->crtc_id, fb_id, 0, 0,
+ rc = drmModeSetCrtc(fd, enc->crtc_id, fb->id, 0, 0,
&conn->connector_id, 1,
&conn->modes[0]);
if (rc < 0) {
@@ -197,15 +200,17 @@ static int drm_show_fb(void)
static void drm_restore_display(void)
{
- drm_show_fb();
+ drm_show_fb(fbc);
}
-static void drm_flush_display(void)
+static void drm_flush_display(bool second)
{
- drmModeDirtyFB(fd, fb_id, 0, 0);
+ fbc = second ? &fb2 : &fb1;
+ drm_show_fb(fbc);
+ drmModeDirtyFB(fd, fbc->id, 0, 0);
}
-gfxstate *drm_init(const char *device, const char *output)
+gfxstate *drm_init(const char *device, const char *output, bool pageflip)
{
gfxstate *gfx;
char dev[64];
@@ -219,9 +224,9 @@ gfxstate *drm_init(const char *device, const char *output)
if (drm_init_dev(dev, output) < 0)
return NULL;
- if (drm_init_fb() < 0)
+ if (drm_init_fb(&fb1) < 0)
return NULL;
- if (drm_show_fb() < 0)
+ if (drm_show_fb(&fb1) < 0)
return NULL;
/* prepare gfx */
@@ -230,8 +235,8 @@ gfxstate *drm_init(const char *device, const char *output)
gfx->hdisplay = mode->hdisplay;
gfx->vdisplay = mode->vdisplay;
- gfx->stride = creq.pitch;
- gfx->mem = fbmem;
+ gfx->stride = fb1.creq.pitch;
+ gfx->mem = fb1.mem;
gfx->rlen = 8;
gfx->glen = 8;
@@ -246,6 +251,12 @@ gfxstate *drm_init(const char *device, const char *output)
gfx->restore_display = drm_restore_display;
gfx->cleanup_display = drm_cleanup_display;
gfx->flush_display = drm_flush_display;
+
+ if (pageflip) {
+ if (drm_init_fb(&fb2) == 0) {
+ gfx->mem2 = fb2.mem;
+ }
+ }
return gfx;
}
diff --git a/drmtools.h b/drmtools.h
index 3c733a6..cbb6afb 100644
--- a/drmtools.h
+++ b/drmtools.h
@@ -1,2 +1,2 @@
-gfxstate *drm_init(const char *device, const char *output);
+gfxstate *drm_init(const char *device, const char *output, bool pageflip);
void drm_info(const char *device);
diff --git a/fb-gui.c b/fb-gui.c
index 022d06d..3665f2c 100644
--- a/fb-gui.c
+++ b/fb-gui.c
@@ -102,7 +102,7 @@ void shadow_render(gfxstate *gfx)
sdirty[i] = 0;
}
if (gfx->flush_display)
- gfx->flush_display();
+ gfx->flush_display(false);
}
void shadow_clear_lines(int first, int last)
diff --git a/fbi.c b/fbi.c
index 75f0afe..d45b52c 100644
--- a/fbi.c
+++ b/fbi.c
@@ -1478,14 +1478,14 @@ int main(int argc, char *argv[])
if (device) {
/* device specified */
if (strncmp(device, "/dev/d", 6) == 0) {
- gfx = drm_init(device, output);
+ gfx = drm_init(device, output, false);
} else {
framebuffer = true;
gfx = fb_init(device, mode, GET_VT());
}
} else {
/* try drm first, failing that fb */
- gfx = drm_init(NULL, output);
+ gfx = drm_init(NULL, output, false);
if (!gfx) {
framebuffer = true;
gfx = fb_init(NULL, mode, GET_VT());
diff --git a/fbpdf.c b/fbpdf.c
index dee8c03..2d20d7f 100644
--- a/fbpdf.c
+++ b/fbpdf.c
@@ -42,7 +42,8 @@
gfxstate *gfx;
int debug;
PopplerDocument *doc;
-cairo_surface_t *surface;
+cairo_surface_t *surface1;
+cairo_surface_t *surface2;
PopplerPage *page;
double pw, ph; /* pdf page size */
@@ -119,9 +120,12 @@ static void page_fit_width(void)
static void page_render(void)
{
+ static bool second;
cairo_t *context;
- context = cairo_create(surface);
+ if (surface2)
+ second = !second;
+ context = cairo_create(second ? surface2 : surface1);
cairo_set_source_rgb(context, 1, 1, 1);
cairo_paint(context);
@@ -133,7 +137,7 @@ static void page_render(void)
cairo_destroy(context);
if (gfx->flush_display)
- gfx->flush_display();
+ gfx->flush_display(second);
}
/* ---------------------------------------------------------------------- */
@@ -210,7 +214,7 @@ int main(int argc, char *argv[])
}
/* gfx init */
- gfx = drm_init(NULL, NULL);
+ gfx = drm_init(NULL, NULL, true);
if (!gfx) {
framebuffer = true;
gfx = fb_init(NULL, NULL, 0);
@@ -231,11 +235,18 @@ int main(int argc, char *argv[])
}
}
- surface = cairo_image_surface_create_for_data(gfx->mem,
+ surface1 = cairo_image_surface_create_for_data(gfx->mem,
CAIRO_FORMAT_ARGB32,
gfx->hdisplay,
gfx->vdisplay,
gfx->stride);
+ if (gfx->mem2) {
+ surface2 = cairo_image_surface_create_for_data(gfx->mem2,
+ CAIRO_FORMAT_ARGB32,
+ gfx->hdisplay,
+ gfx->vdisplay,
+ gfx->stride);
+ }
tty_raw();
diff --git a/gfx.h b/gfx.h
index b328d49..16d25fa 100644
--- a/gfx.h
+++ b/gfx.h
@@ -1,3 +1,4 @@
+#include <stdbool.h>
#include <inttypes.h>
typedef struct gfxstate gfxstate;
@@ -8,6 +9,7 @@ struct gfxstate {
uint32_t vdisplay;
uint32_t stride;
uint8_t *mem;
+ uint8_t *mem2;
uint32_t bits_per_pixel;
uint32_t rlen, glen, blen, tlen;
@@ -16,5 +18,5 @@ struct gfxstate {
/* calls */
void (*restore_display)(void);
void (*cleanup_display)(void);
- void (*flush_display)(void);
+ void (*flush_display)(bool second);
};