Hi Axel,
Thanks for the comments. Inlines.
On 05/11/2016 11:57 AM, Axel Davy wrote:
Hi,
Do you have some local branch to review all at once (it is a bit hard
to follow with the patches) ?
The sequences of patches are based on existing vl/dri required
functions, also follows vaapi and then vdpau.
I don't have local branch, but I am going to attach vl_winsys_dri3.c
file, that might be easier.
From a quick looks, it seems you inspired from the loader dri3 code.
That is quite inspiring. I do learn a lot from loader dri3 code. I
should honor it in the commit message. Thanks.
There is also another implementation you can inspire from:
https://github.com/iXit/wine/blob/master/dlls/d3d9-nine/dri3.c
Probably not much more you can get from it.
I haven't checked the code yet, so I don't know if that applies,
something I have noticed on my tonga with games, is that (non-vsynced)
apps that get around 45 fps fell like 15 fps (above 50 or below 35 is
fine).
I guess this is due to the fact the screen buffer swap waits the
buffer has finished rendering to execute the swap, and some bad timing
when hitting 45 fps.
I am using Tonga as well for the development, I haven't hit this, but
definitely that's something to be considered, I will try more video clips.
In fact for this specific case with gallium nine, I noticed the
problem disappear when using thread_submit=true.
thread_submit is an option that was designed for DRI_PRIME case in
mind: the driver spawns a thread that will wait the buffers we want to
present are finished rendering before sending them. That solves all
the sync issues a DRI_PRIME configuration can have.
I think in the case of the problem described, sending buffers that are
finished rendering prevents the screen buffer swap to have to wait
another vblank the buffer is rendered.
I guess for video, you really don't want to hit the bad scenario
described. I'm not sure if you can possibly have the issue or not, but
that may be something to consider. In all cases, that seems a good
thing to look at if wanting to implement a good DRI_PRIME support,
granting it is possible: I don't know the user API, but if the user
has guarantee for example the updated content will be copied to some
pixmap after some call, you cannot delay the presentation for that case.
Like said, definitely keep this in mind. File attached.
Thanks,
Leo
Axel
On 11/05/2016 17:06, Leo Liu wrote :
This series implement DRI3 supports for VA-API and VDPAU. It implements
supports for DRI3 Open, PixmapFromBuffer, BufferFromPixmap, and for
PRESENT including PresentPixmap, PresentNotifyMSC, PresentIdleNotify,
PresentConfigureNotify and PresentCompleteNotify.
It has been tested with player mpv and vlc with various clips from
480p to 4K with framerate from 24 to 60. Also includes window mode
and fullscreen w/wo compositing manager. The test also includes VA-API
glx extension.
There's still some future work like DRI_PRIME different GPU support
to be added.
Leo Liu (14):
vl: add DRI3 support infrastructure
vl/dri3: implement dri3 screen create and destroy
vl/dri3: set drawable geometry
vl/dri3: register present events
vl/dri3: implement flushing for queued events
vl/dri3: add back buffers support
vl/dri3: implement function for flush frontbuffer
vl/dri3: implement funciton for get dirty area
vl/dri3: add support for resizing
vl/dri3: implement DRI3 BufferFromPixmap
st/va: add dri3 support
vl/dri3: handle PresentCompleteNotify event
vl/dri3: implement functions for get and set timestamp
st/vdpau: add dri3 support
configure.ac | 7 +-
src/gallium/auxiliary/Makefile.sources | 5 +
src/gallium/auxiliary/vl/vl_winsys.h | 5 +
src/gallium/auxiliary/vl/vl_winsys_dri3.c | 703
++++++++++++++++++++++++++++++
src/gallium/state_trackers/va/context.c | 6 +-
src/gallium/state_trackers/vdpau/device.c | 6 +-
6 files changed, 729 insertions(+), 3 deletions(-)
create mode 100644 src/gallium/auxiliary/vl/vl_winsys_dri3.c
/**************************************************************************
*
* Copyright 2016 Advanced Micro Devices, Inc.
* All Rights Reserved.
*
* 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, sub license, 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 (including the
* next paragraph) 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 NON-INFRINGEMENT.
* IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS 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 <fcntl.h>
#include <X11/Xlib-xcb.h>
#include <X11/xshmfence.h>
#include <xcb/dri3.h>
#include <xcb/present.h>
#include "loader.h"
#include "pipe/p_screen.h"
#include "pipe/p_state.h"
#include "pipe-loader/pipe_loader.h"
#include "util/u_memory.h"
#include "util/u_inlines.h"
#include "vl/vl_compositor.h"
#include "vl/vl_winsys.h"
#define BACK_BUFFER_NUM 3
struct vl_dri3_buffer
{
struct pipe_resource *texture;
uint32_t pixmap;
uint32_t sync_fence;
struct xshmfence *shm_fence;
bool busy;
uint32_t width, height, pitch;
};
struct vl_dri3_screen
{
struct vl_screen base;
xcb_connection_t *conn;
xcb_drawable_t drawable;
uint32_t width, height, depth;
xcb_special_event_t *special_event;
struct vl_dri3_buffer *back_buffers[BACK_BUFFER_NUM];
int cur_back;
struct u_rect dirty_areas[BACK_BUFFER_NUM];
struct vl_dri3_buffer *front_buffer;
bool is_pixmap;
uint32_t send_msc_serial, recv_msc_serial;
uint64_t send_sbc, recv_sbc;
int64_t last_ust, ns_frame, last_msc, next_msc;
bool flushed;
};
static void
dri3_free_front_buffer(struct vl_dri3_screen *scrn,
struct vl_dri3_buffer *buffer)
{
xcb_sync_destroy_fence(scrn->conn, buffer->sync_fence);
xshmfence_unmap_shm(buffer->shm_fence);
FREE(buffer);
}
static void
dri3_free_back_buffer(struct vl_dri3_screen *scrn,
struct vl_dri3_buffer *buffer)
{
xcb_free_pixmap(scrn->conn, buffer->pixmap);
xcb_sync_destroy_fence(scrn->conn, buffer->sync_fence);
xshmfence_unmap_shm(buffer->shm_fence);
pipe_resource_reference(&buffer->texture, NULL);
FREE(buffer);
}
static void
dri3_handle_stamps(struct vl_dri3_screen *scrn, uint64_t ust, uint64_t msc)
{
int64_t ust_ns = ust * 1000;
if (scrn->last_ust && (ust_ns > scrn->last_ust) &&
scrn->last_msc && (msc > scrn->last_msc))
scrn->ns_frame = (ust_ns - scrn->last_ust) / (msc - scrn->last_msc);
scrn->last_ust = ust_ns;
scrn->last_msc = msc;
}
static void
dri3_handle_present_event(struct vl_dri3_screen *scrn,
xcb_present_generic_event_t *ge)
{
switch (ge->evtype) {
case XCB_PRESENT_CONFIGURE_NOTIFY: {
xcb_present_configure_notify_event_t *ce = (void *) ge;
scrn->width = ce->width;
scrn->height = ce->height;
break;
}
case XCB_PRESENT_COMPLETE_NOTIFY: {
xcb_present_complete_notify_event_t *ce = (void *) ge;
if (ce->kind == XCB_PRESENT_COMPLETE_KIND_PIXMAP) {
scrn->recv_sbc = (scrn->send_sbc & 0xffffffff00000000LL) | ce->serial;
if (scrn->recv_sbc > scrn->send_sbc)
scrn->recv_sbc -= 0x100000000;
dri3_handle_stamps(scrn, ce->ust, ce->msc);
} else if (ce->kind == XCB_PRESENT_COMPLETE_KIND_NOTIFY_MSC) {
scrn->recv_msc_serial = ce->serial;
dri3_handle_stamps(scrn, ce->ust, ce->msc);
}
break;
}
case XCB_PRESENT_EVENT_IDLE_NOTIFY: {
xcb_present_idle_notify_event_t *ie = (void *) ge;
int b;
for (b = 0; b < BACK_BUFFER_NUM; b++) {
struct vl_dri3_buffer *buf = scrn->back_buffers[b];
if (buf && buf->pixmap == ie->pixmap) {
buf->busy = false;
break;
}
}
break;
}
}
free(ge);
}
static void
dri3_flush_present_events(struct vl_dri3_screen *scrn)
{
if (scrn->special_event) {
xcb_generic_event_t *ev;
while ((ev = xcb_poll_for_special_event(
scrn->conn, scrn->special_event)) != NULL)
dri3_handle_present_event(scrn, (xcb_present_generic_event_t *)ev);
}
}
static bool
dri3_wait_present_events(struct vl_dri3_screen *scrn)
{
if (scrn->special_event) {
xcb_generic_event_t *ev;
ev = xcb_wait_for_special_event(scrn->conn, scrn->special_event);
if (!ev)
return false;
dri3_handle_present_event(scrn, (xcb_present_generic_event_t *)ev);
return true;
}
return false;
}
static int
dri3_find_back(struct vl_dri3_screen *scrn)
{
int b;
for (;;) {
for (b = 0; b < BACK_BUFFER_NUM; b++) {
int id = (b + scrn->cur_back) % BACK_BUFFER_NUM;
struct vl_dri3_buffer *buffer = scrn->back_buffers[id];
if (!buffer || !buffer->busy)
return id;
}
xcb_flush(scrn->conn);
if (!dri3_wait_present_events(scrn))
return -1;
}
}
static struct vl_dri3_buffer *
dri3_alloc_back_buffer(struct vl_dri3_screen *scrn)
{
struct vl_dri3_buffer *buffer;
xcb_pixmap_t pixmap;
xcb_sync_fence_t sync_fence;
struct xshmfence *shm_fence;
int buffer_fd, fence_fd;
struct pipe_resource templ;
struct winsys_handle whandle;
unsigned usage;
buffer = CALLOC_STRUCT(vl_dri3_buffer);
if (!buffer)
return NULL;
fence_fd = xshmfence_alloc_shm();
if (fence_fd < 0)
goto free_buffer;
shm_fence = xshmfence_map_shm(fence_fd);
if (!shm_fence)
goto close_fd;
memset(&templ, 0, sizeof(templ));
templ.bind = PIPE_BIND_RENDER_TARGET | PIPE_BIND_SAMPLER_VIEW |
PIPE_BIND_SCANOUT | PIPE_BIND_SHARED;
templ.format = PIPE_FORMAT_B8G8R8X8_UNORM;
templ.target = PIPE_TEXTURE_2D;
templ.last_level = 0;
templ.width0 = scrn->width;
templ.height0 = scrn->height;
templ.depth0 = 1;
templ.array_size = 1;
buffer->texture = scrn->base.pscreen->resource_create(scrn->base.pscreen,
&templ);
if (!buffer->texture)
goto unmap_shm;
memset(&whandle, 0, sizeof(whandle));
whandle.type= DRM_API_HANDLE_TYPE_FD;
usage = PIPE_HANDLE_USAGE_EXPLICIT_FLUSH | PIPE_HANDLE_USAGE_READ;
scrn->base.pscreen->resource_get_handle(scrn->base.pscreen,
buffer->texture, &whandle,
usage);
buffer_fd = whandle.handle;
buffer->pitch = whandle.stride;
xcb_dri3_pixmap_from_buffer(scrn->conn,
(pixmap = xcb_generate_id(scrn->conn)),
scrn->drawable,
0,
scrn->width, scrn->height, buffer->pitch,
scrn->depth, 32,
buffer_fd);
xcb_dri3_fence_from_fd(scrn->conn,
pixmap,
(sync_fence = xcb_generate_id(scrn->conn)),
false,
fence_fd);
buffer->pixmap = pixmap;
buffer->sync_fence = sync_fence;
buffer->shm_fence = shm_fence;
buffer->width = scrn->width;
buffer->height = scrn->height;
xshmfence_trigger(buffer->shm_fence);
return buffer;
unmap_shm:
xshmfence_unmap_shm(shm_fence);
close_fd:
close(fence_fd);
free_buffer:
FREE(buffer);
return NULL;
}
static struct vl_dri3_buffer *
dri3_get_back_buffer(struct vl_dri3_screen *scrn)
{
struct vl_dri3_buffer *buffer;
struct pipe_resource *texture = NULL;
assert(scrn);
scrn->cur_back = dri3_find_back(scrn);
if (scrn->cur_back < 0)
return NULL;
buffer = scrn->back_buffers[scrn->cur_back];
if (!buffer || buffer->width != scrn->width ||
buffer->height != scrn->height) {
struct vl_dri3_buffer *new_buffer;
new_buffer = dri3_alloc_back_buffer(scrn);
if (!new_buffer)
return NULL;
if (buffer)
dri3_free_back_buffer(scrn, buffer);
vl_compositor_reset_dirty_area(&scrn->dirty_areas[scrn->cur_back]);
buffer = new_buffer;
scrn->back_buffers[scrn->cur_back] = buffer;
}
pipe_resource_reference(&texture, buffer->texture);
xcb_flush(scrn->conn);
xshmfence_await(buffer->shm_fence);
return buffer;
}
static bool
dri3_set_drawable(struct vl_dri3_screen *scrn, Drawable drawable)
{
xcb_get_geometry_cookie_t geom_cookie;
xcb_get_geometry_reply_t *geom_reply;
xcb_void_cookie_t cookie;
xcb_generic_error_t *error;
xcb_present_event_t peid;
bool ret = true;
assert(drawable);
if (scrn->drawable == drawable)
return true;
scrn->drawable = drawable;
geom_cookie = xcb_get_geometry(scrn->conn, scrn->drawable);
geom_reply = xcb_get_geometry_reply(scrn->conn, geom_cookie, NULL);
if (!geom_reply)
return false;
scrn->width = geom_reply->width;
scrn->height = geom_reply->height;
scrn->depth = geom_reply->depth;
free(geom_reply);
if (scrn->special_event) {
xcb_unregister_for_special_event(scrn->conn, scrn->special_event);
scrn->special_event = NULL;
}
scrn->is_pixmap = false;
peid = xcb_generate_id(scrn->conn);
cookie =
xcb_present_select_input_checked(scrn->conn, peid, scrn->drawable,
XCB_PRESENT_EVENT_MASK_CONFIGURE_NOTIFY |
XCB_PRESENT_EVENT_MASK_COMPLETE_NOTIFY |
XCB_PRESENT_EVENT_MASK_IDLE_NOTIFY);
error = xcb_request_check(scrn->conn, cookie);
if (error) {
if (error->error_code != BadWindow)
ret = false;
else
scrn->is_pixmap = true;
free(error);
} else
scrn->special_event =
xcb_register_for_special_xge(scrn->conn, &xcb_present_id, peid, 0);
dri3_flush_present_events(scrn);
return ret;
}
static struct vl_dri3_buffer *
dri3_get_front_buffer(struct vl_dri3_screen *scrn)
{
xcb_dri3_buffer_from_pixmap_cookie_t bp_cookie;
xcb_dri3_buffer_from_pixmap_reply_t *bp_reply;
xcb_sync_fence_t sync_fence;
struct xshmfence *shm_fence;
int fence_fd, *fds;
struct winsys_handle whandle;
struct pipe_resource templ, *texture = NULL;
if (scrn->front_buffer) {
pipe_resource_reference(&texture, scrn->front_buffer->texture);
return scrn->front_buffer;
}
scrn->front_buffer = CALLOC_STRUCT(vl_dri3_buffer);
if (!scrn->front_buffer)
return NULL;
fence_fd = xshmfence_alloc_shm();
if (fence_fd < 0)
goto free_buffer;
shm_fence = xshmfence_map_shm(fence_fd);
if (!shm_fence)
goto close_fd;
bp_cookie = xcb_dri3_buffer_from_pixmap(scrn->conn, scrn->drawable);
bp_reply = xcb_dri3_buffer_from_pixmap_reply(scrn->conn, bp_cookie, NULL);
if (!bp_reply)
goto unmap_shm;
fds = xcb_dri3_buffer_from_pixmap_reply_fds(scrn->conn, bp_reply);
if (fds[0] < 0)
goto free_reply;
memset(&whandle, 0, sizeof(whandle));
whandle.type = DRM_API_HANDLE_TYPE_FD;
whandle.handle = (unsigned)fds[0];
whandle.stride = bp_reply->stride;
memset(&templ, 0, sizeof(templ));
templ.bind = PIPE_BIND_RENDER_TARGET | PIPE_BIND_SAMPLER_VIEW;
templ.format = PIPE_FORMAT_B8G8R8X8_UNORM;
templ.target = PIPE_TEXTURE_2D;
templ.last_level = 0;
templ.width0 = bp_reply->width;
templ.height0 = bp_reply->height;
templ.depth0 = 1;
templ.array_size = 1;
scrn->front_buffer->texture =
scrn->base.pscreen->resource_from_handle(scrn->base.pscreen,
&templ, &whandle,
PIPE_HANDLE_USAGE_READ_WRITE);
close(fds[0]);
if (!scrn->front_buffer->texture)
goto free_reply;
xcb_dri3_fence_from_fd(scrn->conn,
scrn->drawable,
(sync_fence = xcb_generate_id(scrn->conn)),
false,
fence_fd);
pipe_resource_reference(&texture, scrn->front_buffer->texture);
scrn->front_buffer->pixmap = scrn->drawable;
scrn->front_buffer->width = bp_reply->width;
scrn->front_buffer->height = bp_reply->height;
scrn->front_buffer->shm_fence = shm_fence;
scrn->front_buffer->sync_fence = sync_fence;
free(bp_reply);
return scrn->front_buffer;
free_reply:
free(bp_reply);
unmap_shm:
xshmfence_unmap_shm(shm_fence);
close_fd:
close(fence_fd);
free_buffer:
FREE(scrn->front_buffer);
return NULL;
}
static void
vl_dri3_flush_frontbuffer(struct pipe_screen *screen,
struct pipe_resource *resource,
unsigned level, unsigned layer,
void *context_private, struct pipe_box *sub_box)
{
struct vl_dri3_screen *scrn = (struct vl_dri3_screen *)context_private;
uint32_t options = XCB_PRESENT_OPTION_NONE;
struct vl_dri3_buffer *back;
back = scrn->back_buffers[scrn->cur_back];
if (!back)
return;
if (scrn->flushed) {
while (scrn->special_event && scrn->recv_sbc < scrn->send_sbc)
if (!dri3_wait_present_events(scrn))
return;
}
xshmfence_reset(back->shm_fence);
back->busy = true;
xcb_present_pixmap(scrn->conn,
scrn->drawable,
back->pixmap,
(uint32_t)(++scrn->send_sbc),
0, 0, 0, 0,
None, None,
back->sync_fence,
options,
scrn->next_msc,
0, 0, 0, NULL);
xcb_flush(scrn->conn);
scrn->flushed = true;
return;
}
static struct pipe_resource *
vl_dri3_screen_texture_from_drawable(struct vl_screen *vscreen, void *drawable)
{
struct vl_dri3_screen *scrn = (struct vl_dri3_screen *)vscreen;
struct vl_dri3_buffer *buffer;
assert(scrn);
if (!dri3_set_drawable(scrn, (Drawable)drawable))
return NULL;
if (scrn->flushed) {
while (scrn->special_event && scrn->recv_sbc < scrn->send_sbc)
if (!dri3_wait_present_events(scrn))
return NULL;
}
scrn->flushed = false;
buffer = (scrn->is_pixmap) ?
dri3_get_front_buffer(scrn) :
dri3_get_back_buffer(scrn);
if (!buffer)
return NULL;
return buffer->texture;
}
static struct u_rect *
vl_dri3_screen_get_dirty_area(struct vl_screen *vscreen)
{
struct vl_dri3_screen *scrn = (struct vl_dri3_screen *)vscreen;
assert(scrn);
return &scrn->dirty_areas[scrn->cur_back];
}
static uint64_t
vl_dri3_screen_get_timestamp(struct vl_screen *vscreen, void *drawable)
{
struct vl_dri3_screen *scrn = (struct vl_dri3_screen *)vscreen;
assert(scrn);
if (!dri3_set_drawable(scrn, (Drawable)drawable))
return 0;
if (!scrn->last_ust) {
xcb_present_notify_msc(scrn->conn,
scrn->drawable,
++scrn->send_msc_serial,
0, 0, 0);
xcb_flush(scrn->conn);
while (scrn->special_event &&
scrn->send_msc_serial > scrn->recv_msc_serial) {
if (!dri3_wait_present_events(scrn))
return 0;
}
}
return scrn->last_ust;
}
static void
vl_dri3_screen_set_next_timestamp(struct vl_screen *vscreen, uint64_t stamp)
{
struct vl_dri3_screen *scrn = (struct vl_dri3_screen *)vscreen;
assert(scrn);
if (stamp && scrn->last_ust && scrn->ns_frame && scrn->last_msc)
scrn->next_msc = ((int64_t)stamp - scrn->last_ust + scrn->ns_frame/2) /
scrn->ns_frame + scrn->last_msc;
else
scrn->next_msc = 0;
}
static void *
vl_dri3_screen_get_private(struct vl_screen *vscreen)
{
return vscreen;
}
static void
vl_dri3_screen_destroy(struct vl_screen *vscreen)
{
struct vl_dri3_screen *scrn = (struct vl_dri3_screen *)vscreen;
int i;
assert(vscreen);
dri3_flush_present_events(scrn);
if (scrn->front_buffer) {
dri3_free_front_buffer(scrn, scrn->front_buffer);
scrn->front_buffer = NULL;
return;
}
for (i = 0; i < BACK_BUFFER_NUM; ++i) {
if (scrn->back_buffers[i]) {
dri3_free_back_buffer(scrn, scrn->back_buffers[i]);
scrn->back_buffers[i] = NULL;
}
}
if (scrn->special_event)
xcb_unregister_for_special_event(scrn->conn, scrn->special_event);
scrn->base.pscreen->destroy(scrn->base.pscreen);
pipe_loader_release(&scrn->base.dev, 1);
FREE(scrn);
return;
}
struct vl_screen *
vl_dri3_screen_create(Display *display, int screen)
{
struct vl_dri3_screen *scrn;
const xcb_query_extension_reply_t *extension;
xcb_dri3_open_cookie_t open_cookie;
xcb_dri3_open_reply_t *open_reply;
xcb_get_geometry_cookie_t geom_cookie;
xcb_get_geometry_reply_t *geom_reply;
int is_different_gpu;
int fd;
assert(display);
scrn = CALLOC_STRUCT(vl_dri3_screen);
if (!scrn)
return NULL;
scrn->conn = XGetXCBConnection(display);
if (!scrn->conn)
goto free_screen;
xcb_prefetch_extension_data(scrn->conn , &xcb_dri3_id);
xcb_prefetch_extension_data(scrn->conn, &xcb_present_id);
extension = xcb_get_extension_data(scrn->conn, &xcb_dri3_id);
if (!(extension && extension->present))
goto free_screen;
extension = xcb_get_extension_data(scrn->conn, &xcb_present_id);
if (!(extension && extension->present))
goto free_screen;
open_cookie = xcb_dri3_open(scrn->conn, RootWindow(display, screen), None);
open_reply = xcb_dri3_open_reply(scrn->conn, open_cookie, NULL);
if (!open_reply)
goto free_screen;
if (open_reply->nfd != 1) {
free(open_reply);
goto free_screen;
}
fd = xcb_dri3_open_reply_fds(scrn->conn, open_reply)[0];
if (fd < 0) {
free(open_reply);
goto free_screen;
}
fcntl(fd, F_SETFD, FD_CLOEXEC);
free(open_reply);
fd = loader_get_user_preferred_fd(fd, &is_different_gpu);
/* TODO support different GPU */
if (is_different_gpu)
goto free_screen;
geom_cookie = xcb_get_geometry(scrn->conn, RootWindow(display, screen));
geom_reply = xcb_get_geometry_reply(scrn->conn, geom_cookie, NULL);
if (!geom_reply)
goto free_screen;
/* TODO support depth other than 24 */
if (geom_reply->depth != 24) {
free(geom_reply);
goto free_screen;
}
free(geom_reply);
if (pipe_loader_drm_probe_fd(&scrn->base.dev, fd))
scrn->base.pscreen = pipe_loader_create_screen(scrn->base.dev);
if (!scrn->base.pscreen)
goto release_pipe;
scrn->base.destroy = vl_dri3_screen_destroy;
scrn->base.texture_from_drawable = vl_dri3_screen_texture_from_drawable;
scrn->base.get_dirty_area = vl_dri3_screen_get_dirty_area;
scrn->base.get_timestamp = vl_dri3_screen_get_timestamp;
scrn->base.set_next_timestamp = vl_dri3_screen_set_next_timestamp;
scrn->base.get_private = vl_dri3_screen_get_private;
scrn->base.pscreen->flush_frontbuffer = vl_dri3_flush_frontbuffer;
return &scrn->base;
release_pipe:
if (scrn->base.dev)
pipe_loader_release(&scrn->base.dev, 1);
fd = -1;
close(fd);
free_screen:
FREE(scrn);
return NULL;
}
_______________________________________________
mesa-dev mailing list
mesa-dev@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/mesa-dev