st/egl: Generalize wayland backend a bit
This commit is contained in:
parent
aaa3c0d6de
commit
34fd282b27
|
@ -0,0 +1,303 @@
|
|||
/*
|
||||
* Mesa 3-D graphics library
|
||||
* Version: 7.11
|
||||
*
|
||||
* Copyright (C) 2011 Benjamin Franzke <benjaminfranzke@googlemail.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "util/u_memory.h"
|
||||
#include "util/u_inlines.h"
|
||||
|
||||
#include "pipe/p_compiler.h"
|
||||
#include "pipe/p_screen.h"
|
||||
#include "pipe/p_context.h"
|
||||
#include "pipe/p_state.h"
|
||||
#include "state_tracker/drm_driver.h"
|
||||
|
||||
#include "egllog.h"
|
||||
#include <errno.h>
|
||||
|
||||
#include "native_wayland.h"
|
||||
|
||||
/* see get_drm_screen_name */
|
||||
#include <radeon_drm.h>
|
||||
#include "radeon/drm/radeon_drm_public.h"
|
||||
|
||||
#include <wayland-client.h>
|
||||
#include "wayland-drm-client-protocol.h"
|
||||
#include "wayland-egl-priv.h"
|
||||
|
||||
#include <xf86drm.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
struct wayland_drm_display {
|
||||
struct wayland_display base;
|
||||
|
||||
struct native_event_handler *event_handler;
|
||||
|
||||
struct wl_drm *wl_drm;
|
||||
int fd;
|
||||
char *device_name;
|
||||
boolean authenticated;
|
||||
};
|
||||
|
||||
static INLINE struct wayland_drm_display *
|
||||
wayland_drm_display(const struct native_display *ndpy)
|
||||
{
|
||||
return (struct wayland_drm_display *) ndpy;
|
||||
}
|
||||
|
||||
static void
|
||||
sync_callback(void *data)
|
||||
{
|
||||
int *done = data;
|
||||
|
||||
*done = 1;
|
||||
}
|
||||
|
||||
static void
|
||||
force_roundtrip(struct wl_display *display)
|
||||
{
|
||||
int done = 0;
|
||||
|
||||
wl_display_sync_callback(display, sync_callback, &done);
|
||||
wl_display_iterate(display, WL_DISPLAY_WRITABLE);
|
||||
while (!done)
|
||||
wl_display_iterate(display, WL_DISPLAY_READABLE);
|
||||
}
|
||||
|
||||
static void
|
||||
wayland_drm_display_destroy(struct native_display *ndpy)
|
||||
{
|
||||
struct wayland_drm_display *drmdpy = wayland_drm_display(ndpy);
|
||||
|
||||
if (drmdpy->fd)
|
||||
close(drmdpy->fd);
|
||||
if (drmdpy->wl_drm)
|
||||
wl_drm_destroy(drmdpy->wl_drm);
|
||||
if (drmdpy->device_name)
|
||||
FREE(drmdpy->device_name);
|
||||
if (drmdpy->base.config)
|
||||
FREE(drmdpy->base.config);
|
||||
|
||||
ndpy_uninit(ndpy);
|
||||
|
||||
FREE(drmdpy);
|
||||
}
|
||||
|
||||
static struct wl_buffer *
|
||||
wayland_create_drm_buffer(struct wayland_display *display,
|
||||
struct wayland_surface *surface,
|
||||
enum native_attachment attachment)
|
||||
{
|
||||
struct wayland_drm_display *drmdpy = (struct wayland_drm_display *) display;
|
||||
struct pipe_screen *screen = drmdpy->base.base.screen;
|
||||
struct pipe_resource *resource;
|
||||
struct winsys_handle wsh;
|
||||
uint width, height;
|
||||
struct wl_visual *visual;
|
||||
|
||||
resource = resource_surface_get_single_resource(surface->rsurf, attachment);
|
||||
resource_surface_get_size(surface->rsurf, &width, &height);
|
||||
|
||||
wsh.type = DRM_API_HANDLE_TYPE_SHARED;
|
||||
screen->resource_get_handle(screen, resource, &wsh);
|
||||
|
||||
pipe_resource_reference(&resource, NULL);
|
||||
|
||||
switch (surface->type) {
|
||||
case WL_WINDOW_SURFACE:
|
||||
visual = surface->win->visual;
|
||||
break;
|
||||
case WL_PIXMAP_SURFACE:
|
||||
visual = surface->pix->visual;
|
||||
break;
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return wl_drm_create_buffer(drmdpy->wl_drm, wsh.handle,
|
||||
width, height, wsh.stride, visual);
|
||||
}
|
||||
|
||||
static const char *
|
||||
get_drm_screen_name(int fd, drmVersionPtr version)
|
||||
{
|
||||
const char *name = version->name;
|
||||
|
||||
if (name && !strcmp(name, "radeon")) {
|
||||
int chip_id;
|
||||
struct drm_radeon_info info;
|
||||
|
||||
memset(&info, 0, sizeof(info));
|
||||
info.request = RADEON_INFO_DEVICE_ID;
|
||||
info.value = pointer_to_intptr(&chip_id);
|
||||
if (drmCommandWriteRead(fd, DRM_RADEON_INFO, &info, sizeof(info)) != 0)
|
||||
return NULL;
|
||||
|
||||
name = is_r3xx(chip_id) ? "r300" : "r600";
|
||||
}
|
||||
|
||||
return name;
|
||||
}
|
||||
|
||||
static void
|
||||
drm_handle_device(void *data, struct wl_drm *drm, const char *device)
|
||||
{
|
||||
struct wayland_drm_display *drmdpy = data;
|
||||
drm_magic_t magic;
|
||||
|
||||
drmdpy->device_name = strdup(device);
|
||||
if (!drmdpy->device_name)
|
||||
return;
|
||||
|
||||
drmdpy->fd = open(drmdpy->device_name, O_RDWR);
|
||||
if (drmdpy->fd == -1) {
|
||||
_eglLog(_EGL_WARNING, "wayland-egl: could not open %s (%s)",
|
||||
drmdpy->device_name, strerror(errno));
|
||||
return;
|
||||
}
|
||||
|
||||
drmGetMagic(drmdpy->fd, &magic);
|
||||
wl_drm_authenticate(drmdpy->wl_drm, magic);
|
||||
}
|
||||
|
||||
static void
|
||||
drm_handle_authenticated(void *data, struct wl_drm *drm)
|
||||
{
|
||||
struct wayland_drm_display *drmdpy = data;
|
||||
|
||||
drmdpy->authenticated = true;
|
||||
}
|
||||
|
||||
static const struct wl_drm_listener drm_listener = {
|
||||
drm_handle_device,
|
||||
drm_handle_authenticated
|
||||
};
|
||||
|
||||
static boolean
|
||||
wayland_drm_display_init_screen(struct native_display *ndpy)
|
||||
{
|
||||
struct wayland_drm_display *drmdpy = wayland_drm_display(ndpy);
|
||||
drmVersionPtr version;
|
||||
const char *driver_name;
|
||||
uint32_t id;
|
||||
|
||||
id = wl_display_get_global(drmdpy->base.dpy, "wl_drm", 1);
|
||||
if (id == 0)
|
||||
wl_display_iterate(drmdpy->base.dpy, WL_DISPLAY_READABLE);
|
||||
id = wl_display_get_global(drmdpy->base.dpy, "wl_drm", 1);
|
||||
if (id == 0)
|
||||
return FALSE;
|
||||
|
||||
drmdpy->wl_drm = wl_drm_create(drmdpy->base.dpy, id, 1);
|
||||
if (!drmdpy->wl_drm)
|
||||
return FALSE;
|
||||
|
||||
wl_drm_add_listener(drmdpy->wl_drm, &drm_listener, drmdpy);
|
||||
force_roundtrip(drmdpy->base.dpy);
|
||||
if (drmdpy->fd == -1)
|
||||
return FALSE;
|
||||
|
||||
force_roundtrip(drmdpy->base.dpy);
|
||||
if (!drmdpy->authenticated)
|
||||
return FALSE;
|
||||
|
||||
version = drmGetVersion(drmdpy->fd);
|
||||
if (!version) {
|
||||
_eglLog(_EGL_WARNING, "invalid fd %d", drmdpy->fd);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* FIXME: share this with native_drm or egl_dri2 */
|
||||
driver_name = get_drm_screen_name(drmdpy->fd, version);
|
||||
|
||||
drmdpy->base.base.screen =
|
||||
drmdpy->event_handler->new_drm_screen(&drmdpy->base.base,
|
||||
driver_name, drmdpy->fd);
|
||||
drmFreeVersion(version);
|
||||
|
||||
if (!drmdpy->base.base.screen) {
|
||||
_eglLog(_EGL_WARNING, "failed to create DRM screen");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static struct pipe_resource *
|
||||
wayland_drm_display_import_buffer(struct native_display *ndpy,
|
||||
const struct pipe_resource *templ,
|
||||
void *buf)
|
||||
{
|
||||
return ndpy->screen->resource_from_handle(ndpy->screen,
|
||||
templ, (struct winsys_handle *) buf);
|
||||
}
|
||||
|
||||
static boolean
|
||||
wayland_drm_display_export_buffer(struct native_display *ndpy,
|
||||
struct pipe_resource *res,
|
||||
void *buf)
|
||||
{
|
||||
return ndpy->screen->resource_get_handle(ndpy->screen,
|
||||
res, (struct winsys_handle *) buf);
|
||||
}
|
||||
|
||||
static struct native_display_buffer wayland_drm_display_buffer = {
|
||||
wayland_drm_display_import_buffer,
|
||||
wayland_drm_display_export_buffer
|
||||
};
|
||||
|
||||
struct wayland_display *
|
||||
wayland_create_drm_display(struct wl_display *dpy,
|
||||
struct native_event_handler *event_handler,
|
||||
void *user_data)
|
||||
{
|
||||
struct wayland_drm_display *drmdpy;
|
||||
|
||||
drmdpy = CALLOC_STRUCT(wayland_drm_display);
|
||||
if (!drmdpy)
|
||||
return NULL;
|
||||
|
||||
drmdpy->event_handler = event_handler;
|
||||
drmdpy->base.base.user_data = user_data;
|
||||
|
||||
drmdpy->base.dpy = dpy;
|
||||
if (!drmdpy->base.dpy) {
|
||||
wayland_drm_display_destroy(&drmdpy->base.base);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!wayland_drm_display_init_screen(&drmdpy->base.base)) {
|
||||
wayland_drm_display_destroy(&drmdpy->base.base);
|
||||
return NULL;
|
||||
}
|
||||
drmdpy->base.base.destroy = wayland_drm_display_destroy;
|
||||
drmdpy->base.base.buffer = &wayland_drm_display_buffer;
|
||||
|
||||
drmdpy->base.create_buffer = wayland_create_drm_buffer;
|
||||
|
||||
return &drmdpy->base;
|
||||
}
|
||||
|
||||
/* vim: set sw=3 ts=8 sts=3 expandtab: */
|
|
@ -31,25 +31,10 @@
|
|||
#include "pipe/p_context.h"
|
||||
#include "pipe/p_state.h"
|
||||
#include "state_tracker/drm_driver.h"
|
||||
|
||||
#include "egllog.h"
|
||||
#include <errno.h>
|
||||
|
||||
#include "native_wayland.h"
|
||||
|
||||
/* see get_drm_screen_name */
|
||||
#include <radeon_drm.h>
|
||||
#include "radeon/drm/radeon_drm_public.h"
|
||||
|
||||
#include <wayland-client.h>
|
||||
#include "wayland-drm-client-protocol.h"
|
||||
#include "wayland-egl-priv.h"
|
||||
|
||||
#include <xf86drm.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
static struct native_event_handler *wayland_event_handler;
|
||||
|
||||
static void
|
||||
|
@ -113,12 +98,12 @@ wayland_display_get_param(struct native_display *ndpy,
|
|||
int val;
|
||||
|
||||
switch (param) {
|
||||
case NATIVE_PARAM_USE_NATIVE_BUFFER:
|
||||
case NATIVE_PARAM_PRESERVE_BUFFER:
|
||||
case NATIVE_PARAM_MAX_SWAP_INTERVAL:
|
||||
default:
|
||||
val = 0;
|
||||
break;
|
||||
case NATIVE_PARAM_USE_NATIVE_BUFFER:
|
||||
case NATIVE_PARAM_PRESERVE_BUFFER:
|
||||
case NATIVE_PARAM_MAX_SWAP_INTERVAL:
|
||||
default:
|
||||
val = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
return val;
|
||||
|
@ -134,48 +119,6 @@ wayland_display_is_pixmap_supported(struct native_display *ndpy,
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
wayland_display_destroy(struct native_display *ndpy)
|
||||
{
|
||||
struct wayland_display *display = wayland_display(ndpy);
|
||||
|
||||
if (display->fd)
|
||||
close(display->fd);
|
||||
if (display->wl_drm)
|
||||
wl_drm_destroy(display->wl_drm);
|
||||
if (display->device_name)
|
||||
FREE(display->device_name);
|
||||
if (display->config)
|
||||
FREE(display->config);
|
||||
|
||||
ndpy_uninit(ndpy);
|
||||
|
||||
FREE(display);
|
||||
}
|
||||
|
||||
|
||||
static struct wl_buffer *
|
||||
wayland_create_buffer(struct wayland_surface *surface,
|
||||
enum native_attachment attachment)
|
||||
{
|
||||
struct wayland_display *display = surface->display;
|
||||
struct pipe_resource *resource;
|
||||
struct winsys_handle wsh;
|
||||
uint width, height;
|
||||
|
||||
resource = resource_surface_get_single_resource(surface->rsurf, attachment);
|
||||
resource_surface_get_size(surface->rsurf, &width, &height);
|
||||
|
||||
wsh.type = DRM_API_HANDLE_TYPE_SHARED;
|
||||
display->base.screen->resource_get_handle(display->base.screen, resource, &wsh);
|
||||
|
||||
pipe_resource_reference(&resource, NULL);
|
||||
|
||||
return wl_drm_create_buffer(display->wl_drm, wsh.handle,
|
||||
width, height,
|
||||
wsh.stride, surface->win->visual);
|
||||
}
|
||||
|
||||
static void
|
||||
wayland_pixmap_destroy(struct wl_egl_pixmap *egl_pixmap)
|
||||
{
|
||||
|
@ -188,7 +131,7 @@ wayland_pixmap_destroy(struct wl_egl_pixmap *egl_pixmap)
|
|||
wl_buffer_destroy(egl_pixmap->buffer);
|
||||
egl_pixmap->buffer = NULL;
|
||||
}
|
||||
|
||||
|
||||
egl_pixmap->driver_private = NULL;
|
||||
egl_pixmap->destroy = NULL;
|
||||
}
|
||||
|
@ -196,26 +139,16 @@ wayland_pixmap_destroy(struct wl_egl_pixmap *egl_pixmap)
|
|||
static void
|
||||
wayland_pixmap_surface_initialize(struct wayland_surface *surface)
|
||||
{
|
||||
struct native_display *ndpy = &surface->display->base;
|
||||
struct pipe_resource *resource;
|
||||
struct winsys_handle wsh;
|
||||
struct wayland_display *display = wayland_display(&surface->display->base);
|
||||
const enum native_attachment front_natt = NATIVE_ATTACHMENT_FRONT_LEFT;
|
||||
|
||||
if (surface->pix->buffer != NULL)
|
||||
return;
|
||||
|
||||
resource = resource_surface_get_single_resource(surface->rsurf, front_natt);
|
||||
|
||||
wsh.type = DRM_API_HANDLE_TYPE_SHARED;
|
||||
ndpy->screen->resource_get_handle(ndpy->screen, resource, &wsh);
|
||||
|
||||
surface->pix->buffer =
|
||||
wl_drm_create_buffer(surface->display->wl_drm, wsh.handle,
|
||||
surface->pix->width, surface->pix->height,
|
||||
wsh.stride, surface->pix->visual);
|
||||
|
||||
surface->pix->destroy = wayland_pixmap_destroy;
|
||||
surface->pix->driver_private = resource;
|
||||
surface->pix->buffer = display->create_buffer(display, surface, front_natt);
|
||||
surface->pix->destroy = wayland_pixmap_destroy;
|
||||
surface->pix->driver_private =
|
||||
resource_surface_get_single_resource(surface->rsurf, front_natt);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -237,11 +170,11 @@ wayland_window_surface_handle_resize(struct wayland_surface *surface)
|
|||
struct pipe_resource *front_resource;
|
||||
const enum native_attachment front_natt = NATIVE_ATTACHMENT_FRONT_LEFT;
|
||||
int i;
|
||||
|
||||
|
||||
front_resource = resource_surface_get_single_resource(surface->rsurf,
|
||||
front_natt);
|
||||
if (resource_surface_set_size(surface->rsurf,
|
||||
surface->win->width, surface->win->height)) {
|
||||
surface->win->width, surface->win->height)) {
|
||||
|
||||
if (surface->pending_resource)
|
||||
force_roundtrip(display->dpy);
|
||||
|
@ -328,17 +261,19 @@ wayland_surface_swap_buffers(struct native_surface *nsurf)
|
|||
|
||||
if (surface->type == WL_WINDOW_SURFACE) {
|
||||
resource_surface_swap_buffers(surface->rsurf,
|
||||
NATIVE_ATTACHMENT_FRONT_LEFT, NATIVE_ATTACHMENT_BACK_LEFT, FALSE);
|
||||
NATIVE_ATTACHMENT_FRONT_LEFT,
|
||||
NATIVE_ATTACHMENT_BACK_LEFT, FALSE);
|
||||
|
||||
wayland_buffers_swap(surface->buffer, WL_BUFFER_FRONT, WL_BUFFER_BACK);
|
||||
|
||||
if (surface->buffer[WL_BUFFER_FRONT] == NULL)
|
||||
surface->buffer[WL_BUFFER_FRONT] =
|
||||
wayland_create_buffer(surface, NATIVE_ATTACHMENT_FRONT_LEFT);
|
||||
display->create_buffer(display, surface,
|
||||
NATIVE_ATTACHMENT_FRONT_LEFT);
|
||||
|
||||
wl_surface_attach(surface->win->surface, surface->buffer[WL_BUFFER_FRONT],
|
||||
surface->dx, surface->dy);
|
||||
|
||||
|
||||
resource_surface_get_size(surface->rsurf,
|
||||
(uint *) &surface->win->attached_width,
|
||||
(uint *) &surface->win->attached_height);
|
||||
|
@ -348,7 +283,8 @@ wayland_surface_swap_buffers(struct native_surface *nsurf)
|
|||
|
||||
surface->sequence_number++;
|
||||
wayland_event_handler->invalid_surface(&display->base,
|
||||
&surface->base, surface->sequence_number);
|
||||
&surface->base,
|
||||
surface->sequence_number);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
@ -408,6 +344,8 @@ wayland_surface_destroy(struct native_surface *nsurf)
|
|||
FREE(surface);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static struct native_surface *
|
||||
wayland_create_pixmap_surface(struct native_display *ndpy,
|
||||
EGLNativePixmapType pix,
|
||||
|
@ -417,6 +355,8 @@ wayland_create_pixmap_surface(struct native_display *ndpy,
|
|||
struct wayland_surface *surface;
|
||||
struct wl_egl_pixmap *egl_pixmap = (struct wl_egl_pixmap *) pix;
|
||||
enum native_attachment natt = NATIVE_ATTACHMENT_FRONT_LEFT;
|
||||
uint bind = PIPE_BIND_RENDER_TARGET | PIPE_BIND_SAMPLER_VIEW |
|
||||
PIPE_BIND_DISPLAY_TARGET | PIPE_BIND_SCANOUT;
|
||||
|
||||
surface = CALLOC_STRUCT(wayland_surface);
|
||||
if (!surface)
|
||||
|
@ -434,15 +374,13 @@ wayland_create_pixmap_surface(struct native_display *ndpy,
|
|||
surface->color_format = PIPE_FORMAT_B8G8R8A8_UNORM;
|
||||
|
||||
surface->attachment_mask = (1 << NATIVE_ATTACHMENT_FRONT_LEFT);
|
||||
|
||||
|
||||
surface->rsurf = resource_surface_create(display->base.screen,
|
||||
surface->color_format,
|
||||
PIPE_BIND_RENDER_TARGET | PIPE_BIND_SAMPLER_VIEW |
|
||||
PIPE_BIND_DISPLAY_TARGET | PIPE_BIND_SCANOUT);
|
||||
surface->color_format, bind);
|
||||
|
||||
if (!surface->rsurf) {
|
||||
FREE(surface);
|
||||
return NULL;
|
||||
FREE(surface);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
resource_surface_set_size(surface->rsurf,
|
||||
|
@ -461,6 +399,7 @@ wayland_create_pixmap_surface(struct native_display *ndpy,
|
|||
return &surface->base;
|
||||
}
|
||||
|
||||
|
||||
static struct native_surface *
|
||||
wayland_create_window_surface(struct native_display *ndpy,
|
||||
EGLNativeWindowType win,
|
||||
|
@ -469,6 +408,8 @@ wayland_create_window_surface(struct native_display *ndpy,
|
|||
struct wayland_display *display = wayland_display(ndpy);
|
||||
struct wayland_config *config = wayland_config(nconf);
|
||||
struct wayland_surface *surface;
|
||||
uint bind = PIPE_BIND_RENDER_TARGET | PIPE_BIND_SAMPLER_VIEW |
|
||||
PIPE_BIND_DISPLAY_TARGET | PIPE_BIND_SCANOUT;
|
||||
|
||||
surface = CALLOC_STRUCT(wayland_surface);
|
||||
if (!surface)
|
||||
|
@ -486,16 +427,14 @@ wayland_create_window_surface(struct native_display *ndpy,
|
|||
surface->buffer[WL_BUFFER_FRONT] = NULL;
|
||||
surface->buffer[WL_BUFFER_BACK] = NULL;
|
||||
surface->attachment_mask = (1 << NATIVE_ATTACHMENT_FRONT_LEFT) |
|
||||
(1 << NATIVE_ATTACHMENT_BACK_LEFT);
|
||||
(1 << NATIVE_ATTACHMENT_BACK_LEFT);
|
||||
|
||||
surface->rsurf = resource_surface_create(display->base.screen,
|
||||
surface->color_format,
|
||||
PIPE_BIND_RENDER_TARGET | PIPE_BIND_SAMPLER_VIEW |
|
||||
PIPE_BIND_DISPLAY_TARGET | PIPE_BIND_SCANOUT);
|
||||
surface->color_format, bind);
|
||||
|
||||
if (!surface->rsurf) {
|
||||
FREE(surface);
|
||||
return NULL;
|
||||
FREE(surface);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
surface->base.destroy = wayland_surface_destroy;
|
||||
|
@ -506,178 +445,36 @@ wayland_create_window_surface(struct native_display *ndpy,
|
|||
return &surface->base;
|
||||
}
|
||||
|
||||
static const char *
|
||||
get_drm_screen_name(int fd, drmVersionPtr version)
|
||||
{
|
||||
const char *name = version->name;
|
||||
|
||||
if (name && !strcmp(name, "radeon")) {
|
||||
int chip_id;
|
||||
struct drm_radeon_info info;
|
||||
|
||||
memset(&info, 0, sizeof(info));
|
||||
info.request = RADEON_INFO_DEVICE_ID;
|
||||
info.value = pointer_to_intptr(&chip_id);
|
||||
if (drmCommandWriteRead(fd, DRM_RADEON_INFO, &info, sizeof(info)) != 0)
|
||||
return NULL;
|
||||
|
||||
name = is_r3xx(chip_id) ? "r300" : "r600";
|
||||
}
|
||||
|
||||
return name;
|
||||
}
|
||||
|
||||
static void
|
||||
drm_handle_device(void *data, struct wl_drm *drm, const char *device)
|
||||
{
|
||||
struct wayland_display *display = data;
|
||||
drm_magic_t magic;
|
||||
|
||||
display->device_name = strdup(device);
|
||||
if (!display->device_name)
|
||||
return;
|
||||
|
||||
display->fd = open(display->device_name, O_RDWR);
|
||||
if (display->fd == -1) {
|
||||
_eglLog(_EGL_WARNING, "wayland-egl: could not open %s (%s)",
|
||||
display->device_name, strerror(errno));
|
||||
return;
|
||||
}
|
||||
|
||||
drmGetMagic(display->fd, &magic);
|
||||
wl_drm_authenticate(display->wl_drm, magic);
|
||||
}
|
||||
|
||||
static void
|
||||
drm_handle_authenticated(void *data, struct wl_drm *drm)
|
||||
{
|
||||
struct wayland_display *display = data;
|
||||
|
||||
display->authenticated = true;
|
||||
}
|
||||
|
||||
static const struct wl_drm_listener drm_listener = {
|
||||
drm_handle_device,
|
||||
drm_handle_authenticated
|
||||
};
|
||||
|
||||
static boolean
|
||||
wayland_display_init_screen(struct native_display *ndpy)
|
||||
{
|
||||
struct wayland_display *display = wayland_display(ndpy);
|
||||
drmVersionPtr version;
|
||||
const char *driver_name;
|
||||
uint32_t id;
|
||||
|
||||
id = wl_display_get_global(display->dpy, "wl_drm", 1);
|
||||
if (id == 0)
|
||||
wl_display_iterate(display->dpy, WL_DISPLAY_READABLE);
|
||||
id = wl_display_get_global(display->dpy, "wl_drm", 1);
|
||||
if (id == 0)
|
||||
return FALSE;
|
||||
|
||||
display->wl_drm = wl_drm_create(display->dpy, id, 1);
|
||||
if (!display->wl_drm)
|
||||
return FALSE;
|
||||
|
||||
wl_drm_add_listener(display->wl_drm, &drm_listener, display);
|
||||
force_roundtrip(display->dpy);
|
||||
if (display->fd == -1)
|
||||
return FALSE;
|
||||
|
||||
force_roundtrip(display->dpy);
|
||||
if (!display->authenticated)
|
||||
return FALSE;
|
||||
|
||||
version = drmGetVersion(display->fd);
|
||||
if (!version) {
|
||||
_eglLog(_EGL_WARNING, "invalid fd %d", display->fd);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* FIXME: share this with native_drm or egl_dri2 */
|
||||
driver_name = get_drm_screen_name(display->fd, version);
|
||||
|
||||
display->base.screen =
|
||||
wayland_event_handler->new_drm_screen(&display->base,
|
||||
driver_name, display->fd);
|
||||
drmFreeVersion(version);
|
||||
|
||||
if (!display->base.screen) {
|
||||
_eglLog(_EGL_WARNING, "failed to create DRM screen");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
wayland_set_event_handler(struct native_event_handler *event_handler)
|
||||
native_set_event_handler(struct native_event_handler *event_handler)
|
||||
{
|
||||
wayland_event_handler = event_handler;
|
||||
}
|
||||
|
||||
static struct pipe_resource *
|
||||
wayland_display_import_buffer(struct native_display *ndpy,
|
||||
const struct pipe_resource *templ,
|
||||
void *buf)
|
||||
{
|
||||
return ndpy->screen->resource_from_handle(ndpy->screen,
|
||||
templ, (struct winsys_handle *) buf);
|
||||
}
|
||||
|
||||
static boolean
|
||||
wayland_display_export_buffer(struct native_display *ndpy,
|
||||
struct pipe_resource *res,
|
||||
void *buf)
|
||||
{
|
||||
return ndpy->screen->resource_get_handle(ndpy->screen,
|
||||
res, (struct winsys_handle *) buf);
|
||||
}
|
||||
|
||||
static struct native_display_buffer wayland_display_buffer = {
|
||||
wayland_display_import_buffer,
|
||||
wayland_display_export_buffer
|
||||
};
|
||||
|
||||
static struct native_display *
|
||||
wayland_display_create(void *dpy, boolean use_sw, void *user_data)
|
||||
native_create_display(void *dpy, boolean use_sw, void *user_data)
|
||||
{
|
||||
struct wayland_display *display;
|
||||
struct wayland_display *display = NULL;
|
||||
|
||||
display = CALLOC_STRUCT(wayland_display);
|
||||
display = wayland_create_drm_display((struct wl_display *) dpy,
|
||||
wayland_event_handler,
|
||||
user_data);
|
||||
if (!display)
|
||||
return NULL;
|
||||
|
||||
display->base.user_data = user_data;
|
||||
|
||||
display->dpy = dpy;
|
||||
if (!display->dpy) {
|
||||
wayland_display_destroy(&display->base);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!wayland_display_init_screen(&display->base)) {
|
||||
wayland_display_destroy(&display->base);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
display->base.destroy = wayland_display_destroy;
|
||||
display->base.get_param = wayland_display_get_param;
|
||||
display->base.get_configs = wayland_display_get_configs;
|
||||
display->base.is_pixmap_supported = wayland_display_is_pixmap_supported;
|
||||
display->base.create_window_surface = wayland_create_window_surface;
|
||||
display->base.create_pixmap_surface = wayland_create_pixmap_surface;
|
||||
display->base.buffer = &wayland_display_buffer;
|
||||
|
||||
return &display->base;
|
||||
}
|
||||
|
||||
static const struct native_platform wayland_platform = {
|
||||
"wayland", /* name */
|
||||
wayland_set_event_handler,
|
||||
wayland_display_create
|
||||
native_set_event_handler,
|
||||
native_create_display
|
||||
};
|
||||
|
||||
const struct native_platform *
|
||||
|
@ -685,3 +482,5 @@ native_get_wayland_platform(void)
|
|||
{
|
||||
return &wayland_platform;
|
||||
}
|
||||
|
||||
/* vim: set sw=3 ts=8 sts=3 expandtab: */
|
||||
|
|
|
@ -33,17 +33,18 @@
|
|||
#include "common/native_helper.h"
|
||||
|
||||
#include "wayland-egl-priv.h"
|
||||
#include "wayland-drm-client-protocol.h"
|
||||
|
||||
struct wayland_surface;
|
||||
|
||||
struct wayland_display {
|
||||
struct native_display base;
|
||||
|
||||
struct wayland_config *config;
|
||||
struct wl_display *dpy;
|
||||
struct wl_drm *wl_drm;
|
||||
int fd;
|
||||
char *device_name;
|
||||
boolean authenticated;
|
||||
|
||||
struct wl_buffer *(*create_buffer)(struct wayland_display *display,
|
||||
struct wayland_surface *surface,
|
||||
enum native_attachment attachment);
|
||||
};
|
||||
|
||||
enum wayland_buffer_type {
|
||||
|
@ -78,7 +79,7 @@ struct wayland_surface {
|
|||
};
|
||||
|
||||
struct wayland_config {
|
||||
struct native_config base;
|
||||
struct native_config base;
|
||||
};
|
||||
|
||||
static INLINE struct wayland_display *
|
||||
|
@ -99,4 +100,9 @@ wayland_config(const struct native_config *nconf)
|
|||
return (struct wayland_config *) nconf;
|
||||
}
|
||||
|
||||
struct wayland_display *
|
||||
wayland_create_drm_display(struct wl_display *display,
|
||||
struct native_event_handler *event_handler,
|
||||
void *user_data);
|
||||
|
||||
#endif /* _NATIVE_WAYLAND_H_ */
|
||||
|
|
Loading…
Reference in New Issue