mirror of
https://gitlab.freedesktop.org/plymouth/plymouth.git
synced 2026-05-08 13:38:45 +02:00
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:
parent
655b1b2646
commit
9b396fafeb
5 changed files with 308 additions and 561 deletions
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
@ -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 */
|
||||
|
|
@ -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 */
|
||||
Loading…
Add table
Reference in a new issue