Reviewed-by: Ander Conselvan de Oliveira <conselvan2@gmail.com>tags/mesa-9.2-rc1
@@ -320,7 +320,7 @@ static struct dri2_extension_match dri2_driver_extensions[] = { | |||
static struct dri2_extension_match dri2_core_extensions[] = { | |||
{ __DRI2_FLUSH, 1, offsetof(struct dri2_egl_display, flush) }, | |||
{ __DRI_TEX_BUFFER, 2, offsetof(struct dri2_egl_display, tex_buffer) }, | |||
{ __DRI_IMAGE, 1, offsetof(struct dri2_egl_display, image) }, | |||
{ __DRI_IMAGE, 7, offsetof(struct dri2_egl_display, image) }, | |||
{ NULL, 0, 0 } | |||
}; | |||
@@ -1498,7 +1498,7 @@ dri2_export_drm_image_mesa(_EGLDriver *drv, _EGLDisplay *disp, _EGLImage *img, | |||
#ifdef HAVE_WAYLAND_PLATFORM | |||
static void | |||
dri2_wl_reference_buffer(void *user_data, uint32_t name, | |||
dri2_wl_reference_buffer(void *user_data, uint32_t name, int fd, | |||
struct wl_drm_buffer *buffer) | |||
{ | |||
_EGLDisplay *disp = user_data; | |||
@@ -1506,13 +1506,24 @@ dri2_wl_reference_buffer(void *user_data, uint32_t name, | |||
__DRIimage *img; | |||
int i, dri_components = 0; | |||
img = dri2_dpy->image->createImageFromNames(dri2_dpy->dri_screen, | |||
buffer->buffer.width, | |||
buffer->buffer.height, | |||
buffer->format, (int*)&name, 1, | |||
buffer->stride, | |||
buffer->offset, | |||
NULL); | |||
if (fd == -1) | |||
img = dri2_dpy->image->createImageFromNames(dri2_dpy->dri_screen, | |||
buffer->buffer.width, | |||
buffer->buffer.height, | |||
buffer->format, | |||
(int*)&name, 1, | |||
buffer->stride, | |||
buffer->offset, | |||
NULL); | |||
else | |||
img = dri2_dpy->image->createImageFromFds(dri2_dpy->dri_screen, | |||
buffer->buffer.width, | |||
buffer->buffer.height, | |||
buffer->format, | |||
&fd, 1, | |||
buffer->stride, | |||
buffer->offset, | |||
NULL); | |||
if (img == NULL) | |||
return; | |||
@@ -1550,6 +1561,8 @@ dri2_bind_wayland_display_wl(_EGLDriver *drv, _EGLDisplay *disp, | |||
struct wl_display *wl_dpy) | |||
{ | |||
struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); | |||
int ret, flags = 0; | |||
uint64_t cap; | |||
(void) drv; | |||
@@ -1559,9 +1572,13 @@ dri2_bind_wayland_display_wl(_EGLDriver *drv, _EGLDisplay *disp, | |||
wl_drm_callbacks.authenticate = | |||
(int(*)(void *, uint32_t)) dri2_dpy->authenticate; | |||
ret = drmGetCap(dri2_dpy->fd, DRM_CAP_PRIME, &cap); | |||
if (ret == 0 && cap == (DRM_PRIME_CAP_IMPORT | DRM_PRIME_CAP_EXPORT)) | |||
flags |= WAYLAND_DRM_PRIME; | |||
dri2_dpy->wl_server_drm = | |||
wayland_drm_init(wl_dpy, dri2_dpy->device_name, | |||
&wl_drm_callbacks, disp); | |||
&wl_drm_callbacks, disp, flags); | |||
if (!dri2_dpy->wl_server_drm) | |||
return EGL_FALSE; |
@@ -132,6 +132,7 @@ struct dri2_egl_display | |||
struct wl_event_queue *wl_queue; | |||
int authenticated; | |||
int formats; | |||
uint32_t capabilities; | |||
#endif | |||
int (*authenticate) (_EGLDisplay *disp, uint32_t id); |
@@ -451,6 +451,46 @@ static const struct wl_callback_listener frame_listener = { | |||
wayland_frame_callback | |||
}; | |||
static void | |||
create_wl_buffer(struct dri2_egl_surface *dri2_surf) | |||
{ | |||
struct dri2_egl_display *dri2_dpy = | |||
dri2_egl_display(dri2_surf->base.Resource.Display); | |||
int fd; | |||
if (dri2_surf->current->wl_buffer != NULL) | |||
return; | |||
if (dri2_dpy->capabilities & WL_DRM_CAPABILITY_PRIME) { | |||
dri2_dpy->image->queryImage(dri2_surf->current->dri_image, | |||
__DRI_IMAGE_ATTRIB_FD, &fd); | |||
dri2_surf->current->wl_buffer = | |||
wl_drm_create_prime_buffer(dri2_dpy->wl_drm, | |||
fd, | |||
dri2_surf->base.Width, | |||
dri2_surf->base.Height, | |||
dri2_surf->format, | |||
0, dri2_surf->current->pitch, | |||
0, 0, | |||
0, 0); | |||
close(fd); | |||
} else { | |||
dri2_surf->current->wl_buffer = | |||
wl_drm_create_buffer(dri2_dpy->wl_drm, | |||
dri2_surf->current->name, | |||
dri2_surf->base.Width, | |||
dri2_surf->base.Height, | |||
dri2_surf->current->pitch, | |||
dri2_surf->format); | |||
} | |||
wl_proxy_set_queue((struct wl_proxy *) dri2_surf->current->wl_buffer, | |||
dri2_dpy->wl_queue); | |||
wl_buffer_add_listener(dri2_surf->current->wl_buffer, | |||
&wl_buffer_listener, dri2_surf); | |||
} | |||
/** | |||
* Called via eglSwapBuffers(), drv->API.SwapBuffers(). | |||
*/ | |||
@@ -488,19 +528,7 @@ dri2_swap_buffers(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *draw) | |||
dri2_surf->current = dri2_surf->back; | |||
dri2_surf->back = NULL; | |||
if (dri2_surf->current->wl_buffer == NULL) { | |||
dri2_surf->current->wl_buffer = | |||
wl_drm_create_buffer(dri2_dpy->wl_drm, | |||
dri2_surf->current->name, | |||
dri2_surf->base.Width, | |||
dri2_surf->base.Height, | |||
dri2_surf->current->pitch, | |||
dri2_surf->format); | |||
wl_proxy_set_queue((struct wl_proxy *) dri2_surf->current->wl_buffer, | |||
dri2_dpy->wl_queue); | |||
wl_buffer_add_listener(dri2_surf->current->wl_buffer, | |||
&wl_buffer_listener, dri2_surf); | |||
} | |||
create_wl_buffer(dri2_surf); | |||
wl_surface_attach(dri2_surf->wl_win->surface, | |||
dri2_surf->current->wl_buffer, | |||
@@ -629,6 +657,14 @@ drm_handle_format(void *data, struct wl_drm *drm, uint32_t format) | |||
} | |||
} | |||
static void | |||
drm_handle_capabilities(void *data, struct wl_drm *drm, uint32_t value) | |||
{ | |||
struct dri2_egl_display *dri2_dpy = data; | |||
dri2_dpy->capabilities = value; | |||
} | |||
static void | |||
drm_handle_authenticated(void *data, struct wl_drm *drm) | |||
{ | |||
@@ -640,7 +676,8 @@ drm_handle_authenticated(void *data, struct wl_drm *drm) | |||
static const struct wl_drm_listener drm_listener = { | |||
drm_handle_device, | |||
drm_handle_format, | |||
drm_handle_authenticated | |||
drm_handle_authenticated, | |||
drm_handle_capabilities | |||
}; | |||
static void | |||
@@ -649,9 +686,11 @@ registry_handle_global(void *data, struct wl_registry *registry, uint32_t name, | |||
{ | |||
struct dri2_egl_display *dri2_dpy = data; | |||
if (version > 1) | |||
version = 2; | |||
if (strcmp(interface, "wl_drm") == 0) { | |||
dri2_dpy->wl_drm = | |||
wl_registry_bind(registry, name, &wl_drm_interface, 1); | |||
wl_registry_bind(registry, name, &wl_drm_interface, version); | |||
wl_drm_add_listener(dri2_dpy->wl_drm, &drm_listener, dri2_dpy); | |||
} | |||
} |
@@ -31,6 +31,7 @@ | |||
#include <stdlib.h> | |||
#include <string.h> | |||
#include <stddef.h> | |||
#include <unistd.h> | |||
#include <wayland-server.h> | |||
#include "wayland-drm.h" | |||
@@ -41,6 +42,7 @@ struct wl_drm { | |||
void *user_data; | |||
char *device_name; | |||
uint32_t flags; | |||
struct wayland_drm_callbacks *callbacks; | |||
}; | |||
@@ -67,7 +69,8 @@ const static struct wl_buffer_interface drm_buffer_interface = { | |||
static void | |||
create_buffer(struct wl_client *client, struct wl_resource *resource, | |||
uint32_t id, uint32_t name, int32_t width, int32_t height, | |||
uint32_t id, uint32_t name, int fd, | |||
int32_t width, int32_t height, | |||
uint32_t format, | |||
int32_t offset0, int32_t stride0, | |||
int32_t offset1, int32_t stride1, | |||
@@ -93,7 +96,7 @@ create_buffer(struct wl_client *client, struct wl_resource *resource, | |||
buffer->offset[2] = offset2; | |||
buffer->stride[2] = stride2; | |||
drm->callbacks->reference_buffer(drm->user_data, name, buffer); | |||
drm->callbacks->reference_buffer(drm->user_data, name, fd, buffer); | |||
if (buffer->driver_buffer == NULL) { | |||
wl_resource_post_error(resource, | |||
WL_DRM_ERROR_INVALID_NAME, | |||
@@ -131,7 +134,7 @@ drm_create_buffer(struct wl_client *client, struct wl_resource *resource, | |||
} | |||
create_buffer(client, resource, id, | |||
name, width, height, format, 0, stride, 0, 0, 0, 0); | |||
name, -1, width, height, format, 0, stride, 0, 0, 0, 0); | |||
} | |||
static void | |||
@@ -159,10 +162,24 @@ drm_create_planar_buffer(struct wl_client *client, | |||
return; | |||
} | |||
create_buffer(client, resource, id, name, width, height, format, | |||
create_buffer(client, resource, id, name, -1, width, height, format, | |||
offset0, stride0, offset1, stride1, offset2, stride2); | |||
} | |||
static void | |||
drm_create_prime_buffer(struct wl_client *client, | |||
struct wl_resource *resource, | |||
uint32_t id, int fd, | |||
int32_t width, int32_t height, uint32_t format, | |||
int32_t offset0, int32_t stride0, | |||
int32_t offset1, int32_t stride1, | |||
int32_t offset2, int32_t stride2) | |||
{ | |||
create_buffer(client, resource, id, 0, fd, width, height, format, | |||
offset0, stride0, offset1, stride1, offset2, stride2); | |||
close(fd); | |||
} | |||
static void | |||
drm_authenticate(struct wl_client *client, | |||
struct wl_resource *resource, uint32_t id) | |||
@@ -180,7 +197,8 @@ drm_authenticate(struct wl_client *client, | |||
const static struct wl_drm_interface drm_interface = { | |||
drm_authenticate, | |||
drm_create_buffer, | |||
drm_create_planar_buffer | |||
drm_create_planar_buffer, | |||
drm_create_prime_buffer | |||
}; | |||
static void | |||
@@ -188,6 +206,7 @@ bind_drm(struct wl_client *client, void *data, uint32_t version, uint32_t id) | |||
{ | |||
struct wl_drm *drm = data; | |||
struct wl_resource *resource; | |||
uint32_t capabilities; | |||
resource = wl_client_add_object(client, &wl_drm_interface, | |||
&drm_interface, id, data); | |||
@@ -204,11 +223,19 @@ bind_drm(struct wl_client *client, void *data, uint32_t version, uint32_t id) | |||
wl_resource_post_event(resource, WL_DRM_FORMAT, WL_DRM_FORMAT_NV12); | |||
wl_resource_post_event(resource, WL_DRM_FORMAT, WL_DRM_FORMAT_NV16); | |||
wl_resource_post_event(resource, WL_DRM_FORMAT, WL_DRM_FORMAT_YUYV); | |||
capabilities = 0; | |||
if (drm->flags & WAYLAND_DRM_PRIME) | |||
capabilities |= WL_DRM_CAPABILITY_PRIME; | |||
if (version >= 2) | |||
wl_resource_post_event(resource, WL_DRM_CAPABILITIES, capabilities); | |||
} | |||
struct wl_drm * | |||
wayland_drm_init(struct wl_display *display, char *device_name, | |||
struct wayland_drm_callbacks *callbacks, void *user_data) | |||
struct wayland_drm_callbacks *callbacks, void *user_data, | |||
uint32_t flags) | |||
{ | |||
struct wl_drm *drm; | |||
@@ -218,6 +245,7 @@ wayland_drm_init(struct wl_display *display, char *device_name, | |||
drm->device_name = strdup(device_name); | |||
drm->callbacks = callbacks; | |||
drm->user_data = user_data; | |||
drm->flags = flags; | |||
wl_display_add_global(display, &wl_drm_interface, drm, bind_drm); | |||
@@ -82,15 +82,18 @@ struct wl_drm_buffer { | |||
struct wayland_drm_callbacks { | |||
int (*authenticate)(void *user_data, uint32_t id); | |||
void (*reference_buffer)(void *user_data, uint32_t name, | |||
void (*reference_buffer)(void *user_data, uint32_t name, int fd, | |||
struct wl_drm_buffer *buffer); | |||
void (*release_buffer)(void *user_data, struct wl_drm_buffer *buffer); | |||
}; | |||
enum { WAYLAND_DRM_PRIME = 0x01 }; | |||
struct wl_drm * | |||
wayland_drm_init(struct wl_display *display, char *device_name, | |||
struct wayland_drm_callbacks *callbacks, void *user_data); | |||
struct wayland_drm_callbacks *callbacks, void *user_data, | |||
uint32_t flags); | |||
void | |||
wayland_drm_uninit(struct wl_drm *drm); |
@@ -29,7 +29,7 @@ | |||
<!-- drm support. This object is created by the server and published | |||
using the display's global event. --> | |||
<interface name="wl_drm" version="1"> | |||
<interface name="wl_drm" version="2"> | |||
<enum name="error"> | |||
<entry name="authenticate_fail" value="0"/> | |||
<entry name="invalid_format" value="1"/> | |||
@@ -135,6 +135,22 @@ | |||
<arg name="stride2" type="int"/> | |||
</request> | |||
<!-- Create a wayland buffer for the prime fd. Use for regular and planar | |||
buffers. Pass 0 for offset and stride for unused planes. --> | |||
<request name="create_prime_buffer" since="2"> | |||
<arg name="id" type="new_id" interface="wl_buffer"/> | |||
<arg name="name" type="fd"/> | |||
<arg name="width" type="int"/> | |||
<arg name="height" type="int"/> | |||
<arg name="format" type="uint"/> | |||
<arg name="offset0" type="int"/> | |||
<arg name="stride0" type="int"/> | |||
<arg name="offset1" type="int"/> | |||
<arg name="stride1" type="int"/> | |||
<arg name="offset2" type="int"/> | |||
<arg name="stride2" type="int"/> | |||
</request> | |||
<!-- Notification of the path of the drm device which is used by | |||
the server. The client should use this device for creating | |||
local buffers. Only buffers created from this device should | |||
@@ -150,6 +166,17 @@ | |||
<!-- Raised if the authenticate request succeeded --> | |||
<event name="authenticated"/> | |||
<enum name="capability" since="2"> | |||
<description summary="wl_drm capability bitmask"> | |||
Bitmask of capabilities. | |||
</description> | |||
<entry name="prime" value="1" summary="wl_drm prime available"/> | |||
</enum> | |||
<event name="capabilities"> | |||
<arg name="value" type="uint"/> | |||
</event> | |||
</interface> | |||
</protocol> |