parent
3620295d17
commit
fcb6cbd5d0
@ -1,196 +0,0 @@ |
||||
#include <stdio.h> |
||||
#include <string.h> |
||||
#include <stdlib.h> |
||||
#include <stdint.h> |
||||
#include <i915_drm.h> |
||||
#include <sys/ioctl.h> |
||||
#include <sys/mman.h> |
||||
#include <fcntl.h> |
||||
#include <unistd.h> |
||||
#include <linux/fb.h> |
||||
|
||||
#include "wayland.h" |
||||
|
||||
struct lame_compositor { |
||||
struct wl_compositor base; |
||||
void *fb; |
||||
int32_t width, height, stride; |
||||
int gem_fd; |
||||
}; |
||||
|
||||
struct surface_data { |
||||
uint32_t handle; |
||||
int32_t width, height, stride; |
||||
}; |
||||
|
||||
void notify_surface_create(struct wl_compositor *compositor, |
||||
struct wl_surface *surface) |
||||
{ |
||||
struct surface_data *sd; |
||||
|
||||
sd = malloc(sizeof *sd); |
||||
if (sd == NULL) |
||||
return; |
||||
|
||||
sd->handle = 0; |
||||
wl_surface_set_data(surface, sd); |
||||
} |
||||
|
||||
void notify_surface_destroy(struct wl_compositor *compositor, |
||||
struct wl_surface *surface) |
||||
{ |
||||
struct lame_compositor *lc = (struct lame_compositor *) compositor; |
||||
struct surface_data *sd; |
||||
struct drm_gem_close close_arg; |
||||
int ret; |
||||
|
||||
sd = wl_surface_get_data(surface); |
||||
if (sd == NULL || sd->handle == 0) |
||||
return; |
||||
|
||||
close_arg.handle = sd->handle; |
||||
ret = ioctl(lc->gem_fd, DRM_IOCTL_GEM_CLOSE, &close_arg); |
||||
if (ret != 0) { |
||||
fprintf(stderr, "failed to gem_close handle %d: %m\n", sd->handle); |
||||
} |
||||
|
||||
free(sd); |
||||
} |
||||
|
||||
void notify_surface_attach(struct wl_compositor *compositor, |
||||
struct wl_surface *surface, uint32_t name,
|
||||
uint32_t width, uint32_t height, uint32_t stride) |
||||
{ |
||||
struct lame_compositor *lc = (struct lame_compositor *) compositor; |
||||
struct surface_data *sd; |
||||
struct drm_gem_open open_arg; |
||||
struct drm_gem_close close_arg; |
||||
int ret; |
||||
|
||||
sd = wl_surface_get_data(surface); |
||||
if (sd == NULL) |
||||
return; |
||||
|
||||
if (sd->handle != 0) { |
||||
close_arg.handle = sd->handle; |
||||
ret = ioctl(lc->gem_fd, DRM_IOCTL_GEM_CLOSE, &close_arg); |
||||
if (ret != 0) { |
||||
fprintf(stderr, "failed to gem_close name %d: %m\n", name); |
||||
} |
||||
} |
||||
|
||||
open_arg.name = name; |
||||
ret = ioctl(lc->gem_fd, DRM_IOCTL_GEM_OPEN, &open_arg); |
||||
if (ret != 0) { |
||||
fprintf(stderr, "failed to gem_open name %d, fd=%d: %m\n", name, lc->gem_fd); |
||||
return; |
||||
} |
||||
|
||||
sd->handle = open_arg.handle; |
||||
sd->width = width; |
||||
sd->height = height; |
||||
sd->stride = stride; |
||||
} |
||||
|
||||
void notify_surface_map(struct wl_compositor *compositor, |
||||
struct wl_surface *surface, struct wl_map *map) |
||||
{ |
||||
struct lame_compositor *lc = (struct lame_compositor *) compositor; |
||||
struct surface_data *sd; |
||||
struct drm_i915_gem_pread pread; |
||||
char *data, *dst; |
||||
uint32_t size; |
||||
int i; |
||||
|
||||
/* This part is where we actually copy the buffer to screen.
|
||||
* Needs to be part of the repaint loop, not in the notify_map |
||||
* handler. */ |
||||
|
||||
sd = wl_surface_get_data(surface); |
||||
if (sd == NULL) |
||||
return; |
||||
|
||||
size = sd->height * sd->stride; |
||||
data = malloc(size); |
||||
if (data == NULL) { |
||||
fprintf(stderr, "swap buffers malloc failed\n"); |
||||
return; |
||||
} |
||||
|
||||
pread.handle = sd->handle; |
||||
pread.pad = 0; |
||||
pread.offset = 0; |
||||
pread.size = size; |
||||
pread.data_ptr = (long) data; |
||||
|
||||
if (ioctl(lc->gem_fd, DRM_IOCTL_I915_GEM_PREAD, &pread)) { |
||||
fprintf(stderr, "gem pread failed"); |
||||
return; |
||||
} |
||||
|
||||
dst = lc->fb + lc->stride * map->y + map->x * 4; |
||||
for (i = 0; i < sd->height; i++) |
||||
memcpy(dst + lc->stride * i, data + sd->stride * i, sd->width * 4); |
||||
|
||||
free(data); |
||||
} |
||||
|
||||
struct wl_compositor_interface interface = { |
||||
notify_surface_create, |
||||
notify_surface_destroy, |
||||
notify_surface_attach, |
||||
notify_surface_map |
||||
}; |
||||
|
||||
static const char fb_device[] = "/dev/fb"; |
||||
static const char gem_device[] = "/dev/dri/card0"; |
||||
|
||||
struct wl_compositor * |
||||
wl_compositor_create(void) |
||||
{ |
||||
struct lame_compositor *lc; |
||||
struct fb_fix_screeninfo fix; |
||||
struct fb_var_screeninfo var; |
||||
int fd; |
||||
|
||||
lc = malloc(sizeof *lc); |
||||
if (lc == NULL) |
||||
return NULL; |
||||
|
||||
lc->base.interface = &interface; |
||||
|
||||
fd = open(fb_device, O_RDWR); |
||||
if (fd < 0) { |
||||
fprintf(stderr, "open %s failed: %m\n", fb_device); |
||||
return NULL; |
||||
} |
||||
|
||||
if (ioctl(fd, FBIOGET_FSCREENINFO, &fix) < 0) { |
||||
fprintf(stderr, "fb get fixed failed\n"); |
||||
return NULL; |
||||
} |
||||
|
||||
if (ioctl(fd, FBIOGET_VSCREENINFO, &var) < 0) { |
||||
fprintf(stderr, "fb get fixed failed\n"); |
||||
return NULL; |
||||
} |
||||
|
||||
lc->stride = fix.line_length; |
||||
lc->width = var.xres; |
||||
lc->height = var.yres; |
||||
lc->fb = mmap(NULL, lc->stride * lc->height, |
||||
PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); |
||||
close(fd); |
||||
if (lc->fb == MAP_FAILED) { |
||||
fprintf(stderr, "fb map failed\n"); |
||||
return NULL; |
||||
} |
||||
|
||||
lc->gem_fd = open(gem_device, O_RDWR); |
||||
if (lc->gem_fd < 0) { |
||||
fprintf(stderr, "failed to open drm device\n"); |
||||
return NULL; |
||||
} |
||||
|
||||
return &lc->base; |
||||
} |
Loading…
Reference in new issue