drm: merge ply-renderer-generic-driver.c to plugin.c

Now that we don't have several drivers, having the
backend/driver separation makes little sense.

This commit merges everything in plugin.c
This commit is contained in:
Ray Strode 2015-03-25 20:10:49 -04:00
parent 655b1b2646
commit 9b396fafeb
5 changed files with 308 additions and 561 deletions

View file

@ -16,12 +16,7 @@ drm_la_LDFLAGS = -module -avoid-version -export-dynamic
drm_la_LIBADD = $(PLYMOUTH_LIBS) $(DRM_LIBS) \
../../../libply/libply.la \
../../../libply-splash-core/libply-splash-core.la
drm_la_SOURCES = $(srcdir)/plugin.c \
$(srcdir)/ply-renderer-driver.h
drm_la_SOURCES += $(srcdir)/ply-renderer-generic-driver.h \
$(srcdir)/ply-renderer-generic-driver.c
drm_la_SOURCES = $(srcdir)/plugin.c
endif

View file

@ -58,8 +58,6 @@
#include "ply-renderer.h"
#include "ply-renderer-plugin.h"
#include "ply-renderer-driver.h"
#include "ply-renderer-generic-driver.h"
#define BYTES_PER_PIXEL (4)
@ -92,14 +90,27 @@ struct _ply_renderer_input_source
void *user_data;
};
typedef struct
{
uint32_t id;
uint32_t handle;
uint32_t width;
uint32_t height;
uint32_t row_stride;
void *map_address;
uint32_t map_size;
int map_count;
uint32_t added_fb : 1;
} ply_renderer_buffer_t;
struct _ply_renderer_backend
{
ply_event_loop_t *loop;
ply_terminal_t *terminal;
ply_renderer_driver_interface_t *driver_interface;
ply_renderer_driver_t *driver;
int device_fd;
char *device_name;
drmModeRes *resources;
@ -108,11 +119,14 @@ struct _ply_renderer_backend
ply_list_t *heads;
ply_hashtable_t *heads_by_connector_id;
ply_hashtable_t *buffers;
int32_t dither_red;
int32_t dither_green;
int32_t dither_blue;
uint32_t is_active : 1;
uint32_t requires_explicit_flushing : 1;
};
ply_renderer_plugin_interface_t *ply_renderer_backend_get_interface (void);
@ -125,6 +139,263 @@ static bool reset_scan_out_buffer_if_needed (ply_renderer_backend_t *backend,
static void flush_head (ply_renderer_backend_t *backend,
ply_renderer_head_t *head);
static bool
ply_renderer_buffer_map (ply_renderer_backend_t *backend,
ply_renderer_buffer_t *buffer)
{
struct drm_mode_map_dumb map_dumb_buffer_request;
void *map_address;
if (buffer->map_address != MAP_FAILED) {
buffer->map_count++;
return true;
}
memset (&map_dumb_buffer_request, 0, sizeof(struct drm_mode_map_dumb));
map_dumb_buffer_request.handle = buffer->handle;
if (drmIoctl (backend->device_fd, DRM_IOCTL_MODE_MAP_DUMB, &map_dumb_buffer_request) < 0) {
ply_trace ("Could not map GEM object %u: %m", buffer->handle);
return false;
}
map_address = mmap (0, buffer->map_size,
PROT_READ | PROT_WRITE, MAP_SHARED,
backend->device_fd, map_dumb_buffer_request.offset);
if (map_address == MAP_FAILED)
return false;
buffer->map_address = map_address;
buffer->map_count++;
return true;
}
static void
ply_renderer_buffer_unmap (ply_renderer_backend_t *backend,
ply_renderer_buffer_t *buffer)
{
buffer->map_count--;
assert (buffer->map_count >= 0);
}
static ply_renderer_buffer_t *
ply_renderer_buffer_new (ply_renderer_backend_t *backend,
uint32_t width,
uint32_t height)
{
ply_renderer_buffer_t *buffer;
struct drm_mode_create_dumb create_dumb_buffer_request;
buffer = calloc (1, sizeof(ply_renderer_buffer_t));
buffer->width = width;
buffer->height = height;
buffer->map_address = MAP_FAILED;
memset (&create_dumb_buffer_request, 0, sizeof(struct drm_mode_create_dumb));
create_dumb_buffer_request.width = width;
create_dumb_buffer_request.height = height;
create_dumb_buffer_request.bpp = 32;
create_dumb_buffer_request.flags = 0;
if (drmIoctl (backend->device_fd,
DRM_IOCTL_MODE_CREATE_DUMB,
&create_dumb_buffer_request) < 0) {
free (buffer);
ply_trace ("Could not allocate GEM object for frame buffer: %m");
return NULL;
}
buffer->handle = create_dumb_buffer_request.handle;
buffer->row_stride = create_dumb_buffer_request.pitch;
buffer->map_size = create_dumb_buffer_request.size;
ply_trace ("returning %ux%u buffer with stride %u",
width, height, buffer->row_stride);
return buffer;
}
static void
ply_renderer_buffer_free (ply_renderer_backend_t *backend,
ply_renderer_buffer_t *buffer)
{
struct drm_mode_destroy_dumb destroy_dumb_buffer_request;
if (buffer->added_fb)
drmModeRmFB (backend->device_fd, buffer->id);
if (buffer->map_address != MAP_FAILED) {
munmap (buffer->map_address, buffer->map_size);
buffer->map_address = MAP_FAILED;
}
memset (&destroy_dumb_buffer_request, 0, sizeof(struct drm_mode_destroy_dumb));
destroy_dumb_buffer_request.handle = buffer->handle;
if (drmIoctl (backend->device_fd,
DRM_IOCTL_MODE_DESTROY_DUMB,
&destroy_dumb_buffer_request) < 0)
ply_trace ("Could not deallocate GEM object %u: %m", buffer->handle);
free (buffer);
}
static ply_renderer_buffer_t *
get_buffer_from_id (ply_renderer_backend_t *backend,
uint32_t id)
{
static ply_renderer_buffer_t *buffer;
buffer = ply_hashtable_lookup (backend->buffers, (void *) (uintptr_t) id);
return buffer;
}
static bool
fetch_buffer (ply_renderer_backend_t *backend,
uint32_t buffer_id,
unsigned long *width,
unsigned long *height,
unsigned long *row_stride)
{
ply_renderer_buffer_t *buffer;
buffer = get_buffer_from_id (backend, buffer_id);
if (buffer == NULL) {
ply_trace ("could not fetch buffer %u", buffer_id);
return false;
}
if (width != NULL)
*width = buffer->width;
if (height != NULL)
*height = buffer->height;
if (row_stride != NULL)
*row_stride = buffer->row_stride;
ply_trace ("fetched %ux%u buffer with stride %u",
buffer->width, buffer->height, buffer->row_stride);
return true;
}
static uint32_t
create_buffer (ply_renderer_backend_t *backend,
unsigned long width,
unsigned long height,
unsigned long *row_stride)
{
ply_renderer_buffer_t *buffer;
buffer = ply_renderer_buffer_new (backend, width, height);
if (buffer == NULL) {
ply_trace ("Could not allocate GEM object for frame buffer: %m");
return 0;
}
if (drmModeAddFB (backend->device_fd, width, height,
24, 32, buffer->row_stride, buffer->handle,
&buffer->id) != 0) {
ply_trace ("Could not set up GEM object as frame buffer: %m");
ply_renderer_buffer_free (backend, buffer);
return 0;
}
*row_stride = buffer->row_stride;
buffer->added_fb = true;
ply_hashtable_insert (backend->buffers,
(void *) (uintptr_t) buffer->id,
buffer);
return buffer->id;
}
static bool
map_buffer (ply_renderer_backend_t *backend,
uint32_t buffer_id)
{
ply_renderer_buffer_t *buffer;
buffer = get_buffer_from_id (backend, buffer_id);
assert (buffer != NULL);
return ply_renderer_buffer_map (backend, buffer);
}
static void
unmap_buffer (ply_renderer_backend_t *backend,
uint32_t buffer_id)
{
ply_renderer_buffer_t *buffer;
buffer = get_buffer_from_id (backend, buffer_id);
assert (buffer != NULL);
ply_renderer_buffer_unmap (backend, buffer);
}
static char *
begin_flush (ply_renderer_backend_t *backend,
uint32_t buffer_id)
{
ply_renderer_buffer_t *buffer;
buffer = get_buffer_from_id (backend, buffer_id);
assert (buffer != NULL);
return buffer->map_address;
}
static void
end_flush (ply_renderer_backend_t *backend,
uint32_t buffer_id)
{
ply_renderer_buffer_t *buffer;
buffer = get_buffer_from_id (backend, buffer_id);
assert (buffer != NULL);
if (backend->requires_explicit_flushing) {
struct drm_clip_rect flush_area;
int ret;
flush_area.x1 = 0;
flush_area.y1 = 0;
flush_area.x2 = buffer->width;
flush_area.y2 = buffer->height;
ret = drmModeDirtyFB (backend->device_fd, buffer->id, &flush_area, 1);
if (ret == -ENOSYS)
backend->requires_explicit_flushing = false;
}
}
static void
destroy_buffer (ply_renderer_backend_t *backend,
uint32_t buffer_id)
{
ply_renderer_buffer_t *buffer;
buffer = ply_hashtable_remove (backend->buffers,
(void *) (uintptr_t) buffer_id);
assert (buffer != NULL);
ply_renderer_buffer_free (backend, buffer);
}
static bool
ply_renderer_head_add_connector (ply_renderer_head_t *head,
drmModeConnector *connector,
@ -240,25 +511,21 @@ ply_renderer_head_map (ply_renderer_backend_t *backend,
assert (backend != NULL);
assert (backend->device_fd >= 0);
assert (backend->driver_interface != NULL);
assert (backend->driver != NULL);
assert (backend != NULL);
assert (head != NULL);
ply_trace ("Creating buffer for %ldx%ld renderer head", head->area.width, head->area.height);
head->scan_out_buffer_id =
backend->driver_interface->create_buffer (backend->driver,
head->area.width, head->area.height,
&head->row_stride);
head->scan_out_buffer_id = create_buffer (backend,
head->area.width, head->area.height,
&head->row_stride);
if (head->scan_out_buffer_id == 0)
return false;
ply_trace ("Mapping buffer for %ldx%ld renderer head", head->area.width, head->area.height);
if (!backend->driver_interface->map_buffer (backend->driver,
head->scan_out_buffer_id)) {
backend->driver_interface->destroy_buffer (backend->driver,
head->scan_out_buffer_id);
if (!map_buffer (backend, head->scan_out_buffer_id)) {
destroy_buffer (backend, head->scan_out_buffer_id);
head->scan_out_buffer_id = 0;
return false;
}
@ -270,8 +537,7 @@ ply_renderer_head_map (ply_renderer_backend_t *backend,
scan_out_set = reset_scan_out_buffer_if_needed (backend, head);
if (!scan_out_set && backend->is_active) {
backend->driver_interface->destroy_buffer (backend->driver,
head->scan_out_buffer_id);
destroy_buffer (backend, head->scan_out_buffer_id);
head->scan_out_buffer_id = 0;
return false;
}
@ -284,11 +550,9 @@ ply_renderer_head_unmap (ply_renderer_backend_t *backend,
ply_renderer_head_t *head)
{
ply_trace ("unmapping %ldx%ld renderer head", head->area.width, head->area.height);
backend->driver_interface->unmap_buffer (backend->driver,
head->scan_out_buffer_id);
unmap_buffer (backend, head->scan_out_buffer_id);
backend->driver_interface->destroy_buffer (backend->driver,
head->scan_out_buffer_id);
destroy_buffer (backend, head->scan_out_buffer_id);
head->scan_out_buffer_id = 0;
}
@ -374,6 +638,9 @@ create_backend (const char *device_name,
backend->heads = ply_list_new ();
backend->input_source.key_buffer = ply_buffer_new ();
backend->terminal = terminal;
backend->requires_explicit_flushing = true;
backend->buffers = ply_hashtable_new (ply_hashtable_direct_hash,
ply_hashtable_direct_compare);
return backend;
}
@ -385,6 +652,7 @@ destroy_backend (ply_renderer_backend_t *backend)
free_heads (backend);
free (backend->device_name);
ply_hashtable_free (backend->buffers);
free (backend);
}
@ -454,37 +722,21 @@ load_driver (ply_renderer_backend_t *backend)
return false;
}
backend->driver_interface = ply_renderer_generic_driver_get_interface (device_fd);
if (backend->driver_interface == NULL) {
close (device_fd);
return false;
}
backend->driver = backend->driver_interface->create_driver (device_fd);
if (backend->driver == NULL) {
close (device_fd);
return false;
}
backend->device_fd = device_fd;
return true;
}
static void
unload_driver (ply_renderer_backend_t *backend)
unload_backend (ply_renderer_backend_t *backend)
{
if (backend->driver == NULL)
if (backend == NULL)
return;
ply_trace ("unloading driver");
assert (backend->driver_interface != NULL);
ply_trace ("unloading backend");
backend->driver_interface->destroy_driver (backend->driver);
backend->driver = NULL;
backend->driver_interface = NULL;
destroy_backend (backend);
backend = NULL;
if (backend->device_fd >= 0) {
drmClose (backend->device_fd);
@ -537,7 +789,7 @@ close_device (ply_renderer_backend_t *backend)
backend);
}
unload_driver (backend);
unload_backend (backend);
}
static drmModeCrtc *
@ -743,7 +995,7 @@ has_32bpp_support (ply_renderer_backend_t *backend)
min_width = backend->resources->min_width;
min_height = backend->resources->min_height;
/* Some drivers set min_width/min_height to 0,
/* Some backends set min_width/min_height to 0,
* but 0x0 sized buffers don't work.
*/
if (min_width == 0)
@ -752,10 +1004,7 @@ has_32bpp_support (ply_renderer_backend_t *backend)
if (min_height == 0)
min_height = 1;
buffer_id = backend->driver_interface->create_buffer (backend->driver,
min_width,
min_height,
&row_stride);
buffer_id = create_buffer (backend, min_width, min_height, &row_stride);
if (buffer_id == 0) {
ply_trace ("Could not create minimal (%ux%u) 32bpp dummy buffer",
@ -764,8 +1013,7 @@ has_32bpp_support (ply_renderer_backend_t *backend)
return false;
}
backend->driver_interface->destroy_buffer (backend->driver,
buffer_id);
destroy_buffer (backend, buffer_id);
return true;
}
@ -842,15 +1090,11 @@ ply_renderer_head_set_scan_out_buffer_to_console (ply_renderer_backend_t *backen
char *map_address;
ply_rectangle_t area;
if (!backend->driver_interface->fetch_buffer (backend->driver,
head->console_buffer_id,
&width, &height, &row_stride))
if (!fetch_buffer (backend, head->console_buffer_id, &width, &height, &row_stride))
return false;
if (!backend->driver_interface->map_buffer (backend->driver,
head->console_buffer_id)) {
backend->driver_interface->destroy_buffer (backend->driver,
head->console_buffer_id);
if (!map_buffer (backend, head->console_buffer_id)) {
destroy_buffer (backend, head->console_buffer_id);
return false;
}
@ -879,25 +1123,20 @@ ply_renderer_head_set_scan_out_buffer_to_console (ply_renderer_backend_t *backen
}
ply_trace ("Drawing %s to console fb", should_set_to_black ? "black" : "screen contents");
map_address =
backend->driver_interface->begin_flush (backend->driver,
head->console_buffer_id);
map_address = begin_flush (backend, head->console_buffer_id);
flush_area ((char *) shadow_buffer, area.width * 4,
map_address, row_stride, &area);
backend->driver_interface->end_flush (backend->driver,
head->console_buffer_id);
end_flush (backend, head->console_buffer_id);
backend->driver_interface->unmap_buffer (backend->driver,
head->console_buffer_id);
unmap_buffer (backend, head->console_buffer_id);
ply_trace ("Setting scan out hardware to console fb");
ply_renderer_head_set_scan_out_buffer (backend,
head, head->console_buffer_id);
backend->driver_interface->destroy_buffer (backend->driver,
head->console_buffer_id);
destroy_buffer (backend, head->console_buffer_id);
if (pixel_buffer != NULL)
ply_pixel_buffer_free (pixel_buffer);
@ -988,9 +1227,7 @@ flush_head (ply_renderer_backend_t *backend,
updated_region = ply_pixel_buffer_get_updated_areas (pixel_buffer);
areas_to_flush = ply_region_get_sorted_rectangle_list (updated_region);
map_address =
backend->driver_interface->begin_flush (backend->driver,
head->scan_out_buffer_id);
map_address = begin_flush (backend, head->scan_out_buffer_id);
node = ply_list_get_first_node (areas_to_flush);
while (node != NULL) {
@ -1010,8 +1247,7 @@ flush_head (ply_renderer_backend_t *backend,
node = next_node;
}
backend->driver_interface->end_flush (backend->driver,
head->scan_out_buffer_id);
end_flush (backend, head->scan_out_buffer_id);
ply_region_clear (updated_region);
}

View file

@ -1,66 +0,0 @@
/* ply-renderer-driver.h
*
* Copyright (C) 2009 Red Hat, Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* Written By: Ray Strode <rstrode@redhat.com>
*/
#ifndef PLY_RENDERER_DRIVER_H
#define PLY_RENDERER_DRIVER_H
#include <stdbool.h>
#include <stdint.h>
#include "ply-list.h"
#include "ply-rectangle.h"
#include "ply-utils.h"
typedef struct _ply_renderer_driver ply_renderer_driver_t;
typedef struct
{
ply_renderer_driver_t * (*create_driver)(int device_fd);
void (*destroy_driver)(ply_renderer_driver_t *driver);
uint32_t (*create_buffer)(ply_renderer_driver_t *driver,
unsigned long width,
unsigned long height,
unsigned long *row_stride);
bool (*fetch_buffer)(ply_renderer_driver_t *driver,
uint32_t buffer_id,
unsigned long *width,
unsigned long *height,
unsigned long *row_stride);
bool (*map_buffer)(ply_renderer_driver_t *driver,
uint32_t buffer_id);
void (*unmap_buffer)(ply_renderer_driver_t *driver,
uint32_t buffer_id);
char * (*begin_flush)(ply_renderer_driver_t * driver,
uint32_t buffer_id);
void (*end_flush)(ply_renderer_driver_t *driver,
uint32_t buffer_id);
void (*destroy_buffer)(ply_renderer_driver_t *driver,
uint32_t buffer_id);
} ply_renderer_driver_interface_t;
#endif /* PLY_RENDERER_DRIVER_H */
/* vim: set ts=4 sw=4 et ai ci cino={.5s,^-2,+.5s,t0,g0,e-2,n-2,p2s,(0,=.5s,:.5s */

View file

@ -1,385 +0,0 @@
/* ply-renderer-generic-driver.c - interface to generic drm kms api
*
* Copyright (C) 2012 Red Hat, Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* Written by: Dave Airlie
* Based on other renderer drivers written by Ray Strode
*/
#include "config.h"
#include "ply-renderer-generic-driver.h"
#include <arpa/inet.h>
#include <assert.h>
#include <errno.h>
#include <fcntl.h>
#include <signal.h>
#include <string.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <values.h>
#include <unistd.h>
#include <drm.h>
#include <xf86drm.h>
#include <xf86drmMode.h>
#include "ply-hashtable.h"
#include "ply-logger.h"
#include "ply-renderer-driver.h"
typedef struct _ply_renderer_buffer ply_renderer_buffer_t;
struct _ply_renderer_buffer
{
uint32_t id;
uint32_t handle;
uint32_t width;
uint32_t height;
uint32_t row_stride;
void *map_address;
uint32_t map_size;
int map_count;
uint32_t added_fb : 1;
};
struct _ply_renderer_driver
{
int device_fd;
ply_hashtable_t *buffers;
uint32_t requires_explicit_flushing : 1;
};
static bool
ply_renderer_buffer_map (ply_renderer_driver_t *driver,
ply_renderer_buffer_t *buffer)
{
struct drm_mode_map_dumb map_dumb_buffer_request;
void *map_address;
if (buffer->map_address != MAP_FAILED) {
buffer->map_count++;
return true;
}
memset (&map_dumb_buffer_request, 0, sizeof(struct drm_mode_map_dumb));
map_dumb_buffer_request.handle = buffer->handle;
if (drmIoctl (driver->device_fd, DRM_IOCTL_MODE_MAP_DUMB, &map_dumb_buffer_request) < 0) {
ply_trace ("Could not map GEM object %u: %m", buffer->handle);
return false;
}
map_address = mmap (0, buffer->map_size,
PROT_READ | PROT_WRITE, MAP_SHARED,
driver->device_fd, map_dumb_buffer_request.offset);
if (map_address == MAP_FAILED)
return false;
buffer->map_address = map_address;
buffer->map_count++;
return true;
}
static void
ply_renderer_buffer_unmap (ply_renderer_driver_t *driver,
ply_renderer_buffer_t *buffer)
{
buffer->map_count--;
assert (buffer->map_count >= 0);
}
static ply_renderer_driver_t *
create_driver (int device_fd)
{
ply_renderer_driver_t *driver;
driver = calloc (1, sizeof(ply_renderer_driver_t));
driver->device_fd = device_fd;
driver->requires_explicit_flushing = true;
driver->buffers = ply_hashtable_new (ply_hashtable_direct_hash,
ply_hashtable_direct_compare);
return driver;
}
static void
destroy_driver (ply_renderer_driver_t *driver)
{
ply_hashtable_free (driver->buffers);
free (driver);
}
static ply_renderer_buffer_t *
ply_renderer_buffer_new (ply_renderer_driver_t *driver,
uint32_t width,
uint32_t height)
{
ply_renderer_buffer_t *buffer;
struct drm_mode_create_dumb create_dumb_buffer_request;
buffer = calloc (1, sizeof(ply_renderer_buffer_t));
buffer->width = width;
buffer->height = height;
buffer->map_address = MAP_FAILED;
memset (&create_dumb_buffer_request, 0, sizeof(struct drm_mode_create_dumb));
create_dumb_buffer_request.width = width;
create_dumb_buffer_request.height = height;
create_dumb_buffer_request.bpp = 32;
create_dumb_buffer_request.flags = 0;
if (drmIoctl (driver->device_fd,
DRM_IOCTL_MODE_CREATE_DUMB,
&create_dumb_buffer_request) < 0) {
free (buffer);
ply_trace ("Could not allocate GEM object for frame buffer: %m");
return NULL;
}
buffer->handle = create_dumb_buffer_request.handle;
buffer->row_stride = create_dumb_buffer_request.pitch;
buffer->map_size = create_dumb_buffer_request.size;
ply_trace ("returning %ux%u buffer with stride %u",
width, height, buffer->row_stride);
return buffer;
}
static void
ply_renderer_buffer_free (ply_renderer_driver_t *driver,
ply_renderer_buffer_t *buffer)
{
struct drm_mode_destroy_dumb destroy_dumb_buffer_request;
if (buffer->added_fb)
drmModeRmFB (driver->device_fd, buffer->id);
if (buffer->map_address != MAP_FAILED) {
munmap (buffer->map_address, buffer->map_size);
buffer->map_address = MAP_FAILED;
}
memset (&destroy_dumb_buffer_request, 0, sizeof(struct drm_mode_destroy_dumb));
destroy_dumb_buffer_request.handle = buffer->handle;
if (drmIoctl (driver->device_fd,
DRM_IOCTL_MODE_DESTROY_DUMB,
&destroy_dumb_buffer_request) < 0)
ply_trace ("Could not deallocate GEM object %u: %m", buffer->handle);
free (buffer);
}
static ply_renderer_buffer_t *
get_buffer_from_id (ply_renderer_driver_t *driver,
uint32_t id)
{
static ply_renderer_buffer_t *buffer;
buffer = ply_hashtable_lookup (driver->buffers, (void *) (uintptr_t) id);
return buffer;
}
static bool
fetch_buffer (ply_renderer_driver_t *driver,
uint32_t buffer_id,
unsigned long *width,
unsigned long *height,
unsigned long *row_stride)
{
ply_renderer_buffer_t *buffer;
buffer = get_buffer_from_id (driver, buffer_id);
if (buffer == NULL) {
ply_trace ("could not fetch buffer %u", buffer_id);
return false;
}
if (width != NULL)
*width = buffer->width;
if (height != NULL)
*height = buffer->height;
if (row_stride != NULL)
*row_stride = buffer->row_stride;
ply_trace ("fetched %ux%u buffer with stride %u",
buffer->width, buffer->height, buffer->row_stride);
return true;
}
static uint32_t
create_buffer (ply_renderer_driver_t *driver,
unsigned long width,
unsigned long height,
unsigned long *row_stride)
{
ply_renderer_buffer_t *buffer;
buffer = ply_renderer_buffer_new (driver, width, height);
if (buffer == NULL) {
ply_trace ("Could not allocate GEM object for frame buffer: %m");
return 0;
}
if (drmModeAddFB (driver->device_fd, width, height,
24, 32, buffer->row_stride, buffer->handle,
&buffer->id) != 0) {
ply_trace ("Could not set up GEM object as frame buffer: %m");
ply_renderer_buffer_free (driver, buffer);
return 0;
}
*row_stride = buffer->row_stride;
buffer->added_fb = true;
ply_hashtable_insert (driver->buffers,
(void *) (uintptr_t) buffer->id,
buffer);
return buffer->id;
}
static bool
map_buffer (ply_renderer_driver_t *driver,
uint32_t buffer_id)
{
ply_renderer_buffer_t *buffer;
buffer = get_buffer_from_id (driver, buffer_id);
assert (buffer != NULL);
return ply_renderer_buffer_map (driver, buffer);
}
static void
unmap_buffer (ply_renderer_driver_t *driver,
uint32_t buffer_id)
{
ply_renderer_buffer_t *buffer;
buffer = get_buffer_from_id (driver, buffer_id);
assert (buffer != NULL);
ply_renderer_buffer_unmap (driver, buffer);
}
static char *
begin_flush (ply_renderer_driver_t *driver,
uint32_t buffer_id)
{
ply_renderer_buffer_t *buffer;
buffer = get_buffer_from_id (driver, buffer_id);
assert (buffer != NULL);
return buffer->map_address;
}
static void
end_flush (ply_renderer_driver_t *driver,
uint32_t buffer_id)
{
ply_renderer_buffer_t *buffer;
buffer = get_buffer_from_id (driver, buffer_id);
assert (buffer != NULL);
if (driver->requires_explicit_flushing) {
struct drm_clip_rect flush_area;
int ret;
flush_area.x1 = 0;
flush_area.y1 = 0;
flush_area.x2 = buffer->width;
flush_area.y2 = buffer->height;
ret = drmModeDirtyFB (driver->device_fd, buffer->id, &flush_area, 1);
if (ret == -ENOSYS)
driver->requires_explicit_flushing = false;
}
}
static void
destroy_buffer (ply_renderer_driver_t *driver,
uint32_t buffer_id)
{
ply_renderer_buffer_t *buffer;
buffer = ply_hashtable_remove (driver->buffers,
(void *) (uintptr_t) buffer_id);
assert (buffer != NULL);
ply_renderer_buffer_free (driver, buffer);
}
ply_renderer_driver_interface_t *
ply_renderer_generic_driver_get_interface (int device_fd)
{
uint64_t supports_dumb_buffers;
static ply_renderer_driver_interface_t driver_interface =
{
.create_driver = create_driver,
.destroy_driver = destroy_driver,
.create_buffer = create_buffer,
.fetch_buffer = fetch_buffer,
.map_buffer = map_buffer,
.unmap_buffer = unmap_buffer,
.begin_flush = begin_flush,
.end_flush = end_flush,
.destroy_buffer = destroy_buffer,
};
if (drmGetCap (device_fd, DRM_CAP_DUMB_BUFFER, &supports_dumb_buffers) < 0)
return NULL;
if (!supports_dumb_buffers)
return NULL;
return &driver_interface;
}
/* vim: set ts=4 sw=4 et ai ci cino={.5s,^-2,+.5s,t0,g0,e-2,n-2,p2s, (0,=.5s,:.5s */

View file

@ -1,33 +0,0 @@
/* ply-renderer-generic-driver.h
*
* Copyright (C) 2012 Red Hat, Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* Written by: Dave Airlie
* Based on other renderer drivers written by Ray Strode
*/
#ifndef PLY_RENDERER_DUMB_DRIVER_H
#define PLY_RENDERER_DUMB_DRIVER_H
#include "ply-renderer-driver.h"
#ifndef PLY_HIDE_FUNCTION_DECLARATIONS
ply_renderer_driver_interface_t *ply_renderer_generic_driver_get_interface (int device_fd);
#endif
#endif /* PLY_RENDERER_GENERIC_DRIVER_H */
/* vim: set ts=4 sw=4 et ai ci cino={.5s,^-2,+.5s,t0,g0,e-2,n-2,p2s,(0,=.5s,:.5s */