*/
#include <xf86drm.h>
+#include <fcntl.h>
+#include "GL/mesa_glinterop.h"
#include "util/u_memory.h"
#include "util/u_inlines.h"
#include "util/u_format.h"
#include "util/u_debug.h"
#include "state_tracker/drm_driver.h"
+#include "state_tracker/st_cb_bufferobjects.h"
+#include "state_tracker/st_cb_fbo.h"
+#include "state_tracker/st_cb_texture.h"
#include "state_tracker/st_texture.h"
#include "state_tracker/st_context.h"
#include "pipe-loader/pipe_loader.h"
+#include "main/bufferobj.h"
#include "main/texobj.h"
#include "dri_screen.h"
#include "dri_context.h"
#include "dri_drawable.h"
+#include "dri_extensions.h"
#include "dri_query_renderer.h"
#include "dri2_buffer.h"
+#ifndef DRM_FORMAT_MOD_INVALID
+#define DRM_FORMAT_MOD_INVALID ((1ULL<<56) - 1)
+#endif
+
+static const int fourcc_formats[] = {
+ __DRI_IMAGE_FOURCC_ARGB8888,
+ __DRI_IMAGE_FOURCC_ABGR8888,
+ __DRI_IMAGE_FOURCC_SARGB8888,
+ __DRI_IMAGE_FOURCC_XRGB8888,
+ __DRI_IMAGE_FOURCC_XBGR8888,
+ __DRI_IMAGE_FOURCC_ARGB1555,
+ __DRI_IMAGE_FOURCC_RGB565,
+ __DRI_IMAGE_FOURCC_R8,
+ __DRI_IMAGE_FOURCC_R16,
+ __DRI_IMAGE_FOURCC_GR88,
+ __DRI_IMAGE_FOURCC_GR1616,
+ __DRI_IMAGE_FOURCC_YUV410,
+ __DRI_IMAGE_FOURCC_YUV411,
+ __DRI_IMAGE_FOURCC_YUV420,
+ __DRI_IMAGE_FOURCC_YUV422,
+ __DRI_IMAGE_FOURCC_YUV444,
+ __DRI_IMAGE_FOURCC_YVU410,
+ __DRI_IMAGE_FOURCC_YVU411,
+ __DRI_IMAGE_FOURCC_YVU420,
+ __DRI_IMAGE_FOURCC_YVU422,
+ __DRI_IMAGE_FOURCC_YVU444,
+ __DRI_IMAGE_FOURCC_NV12,
+ __DRI_IMAGE_FOURCC_NV16,
+ __DRI_IMAGE_FOURCC_YUYV
+};
+
static int convert_fourcc(int format, int *dri_components_p)
{
int dri_components;
format = __DRI_IMAGE_FORMAT_XBGR8888;
dri_components = __DRI_IMAGE_COMPONENTS_RGB;
break;
+ case __DRI_IMAGE_FOURCC_R8:
+ format = __DRI_IMAGE_FORMAT_R8;
+ dri_components = __DRI_IMAGE_COMPONENTS_R;
+ break;
+ case __DRI_IMAGE_FOURCC_GR88:
+ format = __DRI_IMAGE_FORMAT_GR88;
+ dri_components = __DRI_IMAGE_COMPONENTS_RG;
+ break;
+ /*
+ * For multi-planar YUV formats, we return the format of the first
+ * plane only. Since there is only one caller which supports multi-
+ * planar YUV it gets to figure out the remaining planes on it's
+ * own.
+ */
+ case __DRI_IMAGE_FOURCC_YUV420:
+ case __DRI_IMAGE_FOURCC_YVU420:
+ format = __DRI_IMAGE_FORMAT_R8;
+ dri_components = __DRI_IMAGE_COMPONENTS_Y_U_V;
+ break;
+ case __DRI_IMAGE_FOURCC_NV12:
+ format = __DRI_IMAGE_FORMAT_R8;
+ dri_components = __DRI_IMAGE_COMPONENTS_Y_UV;
+ break;
default:
return -1;
}
return format;
}
+/* NOTE this probably isn't going to do the right thing for YUV images
+ * (but I think the same can be said for intel_query_image()). I think
+ * only needed for exporting dmabuf's, so I think I won't loose much
+ * sleep over it.
+ */
static int convert_to_fourcc(int format)
{
switch(format) {
case __DRI_IMAGE_FORMAT_XBGR8888:
format = __DRI_IMAGE_FOURCC_XBGR8888;
break;
+ case __DRI_IMAGE_FORMAT_R8:
+ format = __DRI_IMAGE_FOURCC_R8;
+ break;
+ case __DRI_IMAGE_FORMAT_GR88:
+ format = __DRI_IMAGE_FOURCC_GR88;
+ break;
default:
return -1;
}
return format;
}
+static enum pipe_format dri2_format_to_pipe_format (int format)
+{
+ enum pipe_format pf;
+
+ switch (format) {
+ case __DRI_IMAGE_FORMAT_RGB565:
+ pf = PIPE_FORMAT_B5G6R5_UNORM;
+ break;
+ case __DRI_IMAGE_FORMAT_XRGB8888:
+ pf = PIPE_FORMAT_BGRX8888_UNORM;
+ break;
+ case __DRI_IMAGE_FORMAT_ARGB8888:
+ pf = PIPE_FORMAT_BGRA8888_UNORM;
+ break;
+ case __DRI_IMAGE_FORMAT_XBGR8888:
+ pf = PIPE_FORMAT_RGBX8888_UNORM;
+ break;
+ case __DRI_IMAGE_FORMAT_ABGR8888:
+ pf = PIPE_FORMAT_RGBA8888_UNORM;
+ break;
+ case __DRI_IMAGE_FORMAT_R8:
+ pf = PIPE_FORMAT_R8_UNORM;
+ break;
+ case __DRI_IMAGE_FORMAT_GR88:
+ pf = PIPE_FORMAT_RG88_UNORM;
+ break;
+ default:
+ pf = PIPE_FORMAT_NONE;
+ break;
+ }
+
+ return pf;
+}
+
+static enum pipe_format fourcc_to_pipe_format(int fourcc)
+{
+ enum pipe_format pf;
+
+ switch (fourcc) {
+ case __DRI_IMAGE_FOURCC_R8:
+ pf = PIPE_FORMAT_R8_UNORM;
+ break;
+ case __DRI_IMAGE_FOURCC_GR88:
+ pf = PIPE_FORMAT_RG88_UNORM;
+ break;
+ case __DRI_IMAGE_FOURCC_ARGB1555:
+ pf = PIPE_FORMAT_B5G5R5A1_UNORM;
+ break;
+ case __DRI_IMAGE_FOURCC_R16:
+ pf = PIPE_FORMAT_R16_UNORM;
+ break;
+ case __DRI_IMAGE_FOURCC_GR1616:
+ pf = PIPE_FORMAT_RG1616_UNORM;
+ break;
+ case __DRI_IMAGE_FOURCC_RGB565:
+ pf = PIPE_FORMAT_B5G6R5_UNORM;
+ break;
+ case __DRI_IMAGE_FOURCC_ARGB8888:
+ pf = PIPE_FORMAT_BGRA8888_UNORM;
+ break;
+ case __DRI_IMAGE_FOURCC_XRGB8888:
+ pf = PIPE_FORMAT_BGRX8888_UNORM;
+ break;
+ case __DRI_IMAGE_FOURCC_ABGR8888:
+ pf = PIPE_FORMAT_RGBA8888_UNORM;
+ break;
+ case __DRI_IMAGE_FOURCC_XBGR8888:
+ pf = PIPE_FORMAT_RGBX8888_UNORM;
+ break;
+
+ case __DRI_IMAGE_FOURCC_NV12:
+ pf = PIPE_FORMAT_NV12;
+ break;
+ case __DRI_IMAGE_FOURCC_YUYV:
+ pf = PIPE_FORMAT_YUYV;
+ break;
+ case __DRI_IMAGE_FOURCC_YUV420:
+ case __DRI_IMAGE_FOURCC_YVU420:
+ pf = PIPE_FORMAT_YV12;
+ break;
+
+ case __DRI_IMAGE_FOURCC_SARGB8888:
+ case __DRI_IMAGE_FOURCC_YUV410:
+ case __DRI_IMAGE_FOURCC_YUV411:
+ case __DRI_IMAGE_FOURCC_YUV422:
+ case __DRI_IMAGE_FOURCC_YUV444:
+ case __DRI_IMAGE_FOURCC_NV16:
+ case __DRI_IMAGE_FOURCC_YVU410:
+ case __DRI_IMAGE_FOURCC_YVU411:
+ case __DRI_IMAGE_FOURCC_YVU422:
+ case __DRI_IMAGE_FOURCC_YVU444:
+ default:
+ pf = PIPE_FORMAT_NONE;
+ }
+
+ return pf;
+}
+
/**
* DRI2 flush extension.
*/
dri2InvalidateDrawable(dPriv);
drawable->dPriv->lastStamp = drawable->dPriv->dri2.stamp;
+ drawable->texture_mask = 0;
p_atomic_inc(&drawable->base.stamp);
}
* may occur as the stvis->color_format.
*/
switch(format) {
- case PIPE_FORMAT_B8G8R8A8_UNORM:
+ case PIPE_FORMAT_BGRA8888_UNORM:
+ case PIPE_FORMAT_RGBA8888_UNORM:
depth = 32;
break;
- case PIPE_FORMAT_B8G8R8X8_UNORM:
+ case PIPE_FORMAT_BGRX8888_UNORM:
+ case PIPE_FORMAT_RGBX8888_UNORM:
depth = 24;
break;
case PIPE_FORMAT_B5G6R5_UNORM:
case PIPE_FORMAT_B5G6R5_UNORM:
image_format = __DRI_IMAGE_FORMAT_RGB565;
break;
- case PIPE_FORMAT_B8G8R8X8_UNORM:
+ case PIPE_FORMAT_BGRX8888_UNORM:
image_format = __DRI_IMAGE_FORMAT_XRGB8888;
break;
- case PIPE_FORMAT_B8G8R8A8_UNORM:
+ case PIPE_FORMAT_BGRA8888_UNORM:
image_format = __DRI_IMAGE_FORMAT_ARGB8888;
break;
- case PIPE_FORMAT_R8G8B8A8_UNORM:
+ case PIPE_FORMAT_RGBX8888_UNORM:
+ image_format = __DRI_IMAGE_FORMAT_XBGR8888;
+ break;
+ case PIPE_FORMAT_RGBA8888_UNORM:
image_format = __DRI_IMAGE_FORMAT_ABGR8888;
break;
default:
switch (format) {
case 32:
- pf = PIPE_FORMAT_B8G8R8A8_UNORM;
+ pf = PIPE_FORMAT_BGRA8888_UNORM;
break;
case 24:
- pf = PIPE_FORMAT_B8G8R8X8_UNORM;
+ pf = PIPE_FORMAT_BGRX8888_UNORM;
break;
case 16:
pf = PIPE_FORMAT_Z16_UNORM;
else
whandle.type = DRM_API_HANDLE_TYPE_KMS;
- screen->base.screen->resource_get_handle(screen->base.screen,
- buffer->resource, &whandle);
+ screen->base.screen->resource_get_handle(screen->base.screen, NULL,
+ buffer->resource, &whandle,
+ PIPE_HANDLE_USAGE_EXPLICIT_FLUSH | PIPE_HANDLE_USAGE_READ);
buffer->base.attachment = attachment;
buffer->base.name = whandle.handle;
templ.bind = bind;
whandle.handle = buf->name;
whandle.stride = buf->pitch;
+ whandle.offset = 0;
if (screen->can_share_buffer)
whandle.type = DRM_API_HANDLE_TYPE_SHARED;
else
whandle.type = DRM_API_HANDLE_TYPE_KMS;
drawable->textures[statt] =
screen->base.screen->resource_from_handle(screen->base.screen,
- &templ, &whandle);
+ &templ, &whandle,
+ PIPE_HANDLE_USAGE_EXPLICIT_FLUSH | PIPE_HANDLE_USAGE_READ);
assert(drawable->textures[statt]);
}
}
if (drawable->textures[statt]) {
templ.format = drawable->textures[statt]->format;
- templ.bind = drawable->textures[statt]->bind;
+ templ.bind = drawable->textures[statt]->bind & ~PIPE_BIND_SCANOUT;
templ.nr_samples = drawable->stvis.samples;
/* Try to reuse the resource.
static __DRIimage *
dri2_create_image_from_winsys(__DRIscreen *_screen,
int width, int height, int format,
- struct winsys_handle *whandle, int pitch,
+ int num_handles, struct winsys_handle *whandle,
void *loaderPrivate)
{
struct dri_screen *screen = dri_screen(_screen);
+ struct pipe_screen *pscreen = screen->base.screen;
__DRIimage *img;
struct pipe_resource templ;
unsigned tex_usage;
enum pipe_format pf;
+ int i;
tex_usage = PIPE_BIND_RENDER_TARGET | PIPE_BIND_SAMPLER_VIEW;
- switch (format) {
- case __DRI_IMAGE_FORMAT_RGB565:
- pf = PIPE_FORMAT_B5G6R5_UNORM;
- break;
- case __DRI_IMAGE_FORMAT_XRGB8888:
- pf = PIPE_FORMAT_B8G8R8X8_UNORM;
- break;
- case __DRI_IMAGE_FORMAT_ARGB8888:
- pf = PIPE_FORMAT_B8G8R8A8_UNORM;
- break;
- case __DRI_IMAGE_FORMAT_ABGR8888:
- pf = PIPE_FORMAT_R8G8B8A8_UNORM;
- break;
- default:
- pf = PIPE_FORMAT_NONE;
- break;
- }
+ pf = dri2_format_to_pipe_format (format);
if (pf == PIPE_FORMAT_NONE)
return NULL;
memset(&templ, 0, sizeof(templ));
templ.bind = tex_usage;
- templ.format = pf;
templ.target = screen->target;
templ.last_level = 0;
- templ.width0 = width;
- templ.height0 = height;
templ.depth0 = 1;
templ.array_size = 1;
- whandle->stride = pitch * util_format_get_blocksize(pf);
+ for (i = num_handles - 1; i >= 0; i--) {
+ struct pipe_resource *tex;
- img->texture = screen->base.screen->resource_from_handle(screen->base.screen,
- &templ, whandle);
- if (!img->texture) {
- FREE(img);
- return NULL;
+ /* TODO: something a lot less ugly */
+ switch (i) {
+ case 0:
+ templ.width0 = width;
+ templ.height0 = height;
+ templ.format = pf;
+ break;
+ case 1:
+ templ.width0 = width / 2;
+ templ.height0 = height / 2;
+ templ.format = (num_handles == 2) ?
+ PIPE_FORMAT_RG88_UNORM : /* NV12, etc */
+ PIPE_FORMAT_R8_UNORM; /* I420, etc */
+ break;
+ case 2:
+ templ.width0 = width / 2;
+ templ.height0 = height / 2;
+ templ.format = PIPE_FORMAT_R8_UNORM;
+ break;
+ default:
+ unreachable("too many planes!");
+ }
+
+ tex = pscreen->resource_from_handle(pscreen,
+ &templ, &whandle[i], PIPE_HANDLE_USAGE_READ_WRITE);
+ if (!tex) {
+ pipe_resource_reference(&img->texture, NULL);
+ FREE(img);
+ return NULL;
+ }
+
+ tex->next = img->texture;
+ img->texture = tex;
}
img->level = 0;
img->layer = 0;
img->dri_format = format;
+ img->use = 0;
img->loader_private = loaderPrivate;
return img;
int name, int pitch, void *loaderPrivate)
{
struct winsys_handle whandle;
+ enum pipe_format pf;
memset(&whandle, 0, sizeof(whandle));
whandle.type = DRM_API_HANDLE_TYPE_SHARED;
whandle.handle = name;
+ whandle.modifier = DRM_FORMAT_MOD_INVALID;
+
+ pf = dri2_format_to_pipe_format (format);
+ if (pf == PIPE_FORMAT_NONE)
+ return NULL;
+
+ whandle.stride = pitch * util_format_get_blocksize(pf);
return dri2_create_image_from_winsys(_screen, width, height, format,
- &whandle, pitch, loaderPrivate);
+ 1, &whandle, loaderPrivate);
}
static __DRIimage *
dri2_create_image_from_fd(__DRIscreen *_screen,
- int width, int height, int format,
- int fd, int pitch, void *loaderPrivate)
+ int width, int height, int fourcc,
+ uint64_t modifier, int *fds, int num_fds,
+ int *strides, int *offsets, unsigned *error,
+ int *dri_components, void *loaderPrivate)
{
- struct winsys_handle whandle;
+ struct winsys_handle whandles[3];
+ int format;
+ __DRIimage *img = NULL;
+ unsigned err = __DRI_IMAGE_ERROR_SUCCESS;
+ int expected_num_fds, i;
+
+ switch (fourcc) {
+ case __DRI_IMAGE_FOURCC_YUV420:
+ case __DRI_IMAGE_FOURCC_YVU420:
+ expected_num_fds = 3;
+ break;
+ case __DRI_IMAGE_FOURCC_NV12:
+ expected_num_fds = 2;
+ break;
+ default:
+ expected_num_fds = 1;
+ break;
+ }
- if (fd < 0)
- return NULL;
+ if (num_fds != expected_num_fds) {
+ err = __DRI_IMAGE_ERROR_BAD_MATCH;
+ goto exit;
+ }
- memset(&whandle, 0, sizeof(whandle));
- whandle.type = DRM_API_HANDLE_TYPE_FD;
- whandle.handle = (unsigned)fd;
+ format = convert_fourcc(fourcc, dri_components);
+ if (format == -1) {
+ err = __DRI_IMAGE_ERROR_BAD_MATCH;
+ goto exit;
+ }
- return dri2_create_image_from_winsys(_screen, width, height, format,
- &whandle, pitch, loaderPrivate);
+ memset(whandles, 0, sizeof(whandles));
+
+ for (i = 0; i < num_fds; i++) {
+ if (fds[i] < 0) {
+ err = __DRI_IMAGE_ERROR_BAD_ALLOC;
+ goto exit;
+ }
+
+ whandles[i].type = DRM_API_HANDLE_TYPE_FD;
+ whandles[i].handle = (unsigned)fds[i];
+ whandles[i].stride = (unsigned)strides[i];
+ whandles[i].offset = (unsigned)offsets[i];
+ whandles[i].modifier = modifier;
+ }
+
+ if (fourcc == __DRI_IMAGE_FOURCC_YVU420) {
+ /* convert to YUV420 by swapping 2nd and 3rd planes: */
+ struct winsys_handle tmp = whandles[1];
+ whandles[1] = whandles[2];
+ whandles[2] = tmp;
+ fourcc = __DRI_IMAGE_FOURCC_YUV420;
+ }
+
+ img = dri2_create_image_from_winsys(_screen, width, height, format,
+ num_fds, whandles, loaderPrivate);
+ if(img == NULL)
+ err = __DRI_IMAGE_ERROR_BAD_ALLOC;
+
+exit:
+ if (error)
+ *error = err;
+
+ return img;
}
static __DRIimage *
}
static __DRIimage *
-dri2_create_image(__DRIscreen *_screen,
- int width, int height, int format,
- unsigned int use, void *loaderPrivate)
+dri2_create_image_common(__DRIscreen *_screen,
+ int width, int height,
+ int format, unsigned int use,
+ const uint64_t *modifiers,
+ const unsigned count,
+ void *loaderPrivate)
{
struct dri_screen *screen = dri_screen(_screen);
__DRIimage *img;
unsigned tex_usage;
enum pipe_format pf;
+ /* createImageWithModifiers doesn't supply usage, and we should not get
+ * here with both modifiers and a usage flag.
+ */
+ assert(!(use && (modifiers != NULL)));
+
tex_usage = PIPE_BIND_RENDER_TARGET | PIPE_BIND_SAMPLER_VIEW;
+
if (use & __DRI_IMAGE_USE_SCANOUT)
tex_usage |= PIPE_BIND_SCANOUT;
if (use & __DRI_IMAGE_USE_SHARE)
tex_usage |= PIPE_BIND_CURSOR;
}
- switch (format) {
- case __DRI_IMAGE_FORMAT_RGB565:
- pf = PIPE_FORMAT_B5G6R5_UNORM;
- break;
- case __DRI_IMAGE_FORMAT_XRGB8888:
- pf = PIPE_FORMAT_B8G8R8X8_UNORM;
- break;
- case __DRI_IMAGE_FORMAT_ARGB8888:
- pf = PIPE_FORMAT_B8G8R8A8_UNORM;
- break;
- case __DRI_IMAGE_FORMAT_ABGR8888:
- pf = PIPE_FORMAT_R8G8B8A8_UNORM;
- break;
- default:
- pf = PIPE_FORMAT_NONE;
- break;
- }
+ pf = dri2_format_to_pipe_format (format);
if (pf == PIPE_FORMAT_NONE)
return NULL;
templ.depth0 = 1;
templ.array_size = 1;
- img->texture = screen->base.screen->resource_create(screen->base.screen, &templ);
+ if (modifiers)
+ img->texture =
+ screen->base.screen
+ ->resource_create_with_modifiers(screen->base.screen,
+ &templ,
+ modifiers,
+ count);
+ else
+ img->texture =
+ screen->base.screen->resource_create(screen->base.screen, &templ);
if (!img->texture) {
FREE(img);
return NULL;
img->layer = 0;
img->dri_format = format;
img->dri_components = 0;
+ img->use = use;
img->loader_private = loaderPrivate;
return img;
}
+static __DRIimage *
+dri2_create_image(__DRIscreen *_screen,
+ int width, int height, int format,
+ unsigned int use, void *loaderPrivate)
+{
+ return dri2_create_image_common(_screen, width, height, format, use,
+ NULL /* modifiers */, 0 /* count */,
+ loaderPrivate);
+}
+
+static __DRIimage *
+dri2_create_image_with_modifiers(__DRIscreen *dri_screen,
+ int width, int height, int format,
+ const uint64_t *modifiers,
+ const unsigned count,
+ void *loaderPrivate)
+{
+ return dri2_create_image_common(dri_screen, width, height, format,
+ 0 /* use */, modifiers, count,
+ loaderPrivate);
+}
+
static GLboolean
dri2_query_image(__DRIimage *image, int attrib, int *value)
{
struct winsys_handle whandle;
+ unsigned usage;
+
+ if (image->use & __DRI_IMAGE_USE_BACKBUFFER)
+ usage = PIPE_HANDLE_USAGE_EXPLICIT_FLUSH | PIPE_HANDLE_USAGE_READ;
+ else
+ usage = PIPE_HANDLE_USAGE_READ_WRITE;
+
memset(&whandle, 0, sizeof(whandle));
switch (attrib) {
case __DRI_IMAGE_ATTRIB_STRIDE:
whandle.type = DRM_API_HANDLE_TYPE_KMS;
image->texture->screen->resource_get_handle(image->texture->screen,
- image->texture, &whandle);
+ NULL, image->texture, &whandle, usage);
*value = whandle.stride;
return GL_TRUE;
+ case __DRI_IMAGE_ATTRIB_OFFSET:
+ whandle.type = DRM_API_HANDLE_TYPE_KMS;
+ image->texture->screen->resource_get_handle(image->texture->screen,
+ NULL, image->texture, &whandle, usage);
+ *value = whandle.offset;
+ return GL_TRUE;
case __DRI_IMAGE_ATTRIB_HANDLE:
whandle.type = DRM_API_HANDLE_TYPE_KMS;
image->texture->screen->resource_get_handle(image->texture->screen,
- image->texture, &whandle);
+ NULL, image->texture, &whandle, usage);
*value = whandle.handle;
return GL_TRUE;
case __DRI_IMAGE_ATTRIB_NAME:
whandle.type = DRM_API_HANDLE_TYPE_SHARED;
image->texture->screen->resource_get_handle(image->texture->screen,
- image->texture, &whandle);
+ NULL, image->texture, &whandle, usage);
*value = whandle.handle;
return GL_TRUE;
case __DRI_IMAGE_ATTRIB_FD:
whandle.type= DRM_API_HANDLE_TYPE_FD;
- image->texture->screen->resource_get_handle(image->texture->screen,
- image->texture, &whandle);
+ if (!image->texture->screen->resource_get_handle(image->texture->screen,
+ NULL, image->texture, &whandle, usage))
+ return GL_FALSE;
+
*value = whandle.handle;
return GL_TRUE;
case __DRI_IMAGE_ATTRIB_FORMAT:
case __DRI_IMAGE_ATTRIB_NUM_PLANES:
*value = 1;
return GL_TRUE;
+ case __DRI_IMAGE_ATTRIB_MODIFIER_UPPER:
+ whandle.type = DRM_API_HANDLE_TYPE_KMS;
+ image->texture->screen->resource_get_handle(image->texture->screen,
+ NULL, image->texture, &whandle, usage);
+ *value = (whandle.modifier >> 32) & 0xffffffff;
+ return GL_TRUE;
+ case __DRI_IMAGE_ATTRIB_MODIFIER_LOWER:
+ whandle.type = DRM_API_HANDLE_TYPE_KMS;
+ image->texture->screen->resource_get_handle(image->texture->screen,
+ NULL, image->texture, &whandle, usage);
+ *value = whandle.modifier & 0xffffffff;
+ return GL_TRUE;
default:
return GL_FALSE;
}
void *loaderPrivate)
{
__DRIimage *img;
- int stride, dri_components;
+ int dri_components;
+ struct winsys_handle whandle;
if (num_names != 1)
return NULL;
- if (offsets[0] != 0)
- return NULL;
format = convert_fourcc(format, &dri_components);
if (format == -1)
return NULL;
- /* Strides are in bytes not pixels. */
- stride = strides[0] /4;
+ memset(&whandle, 0, sizeof(whandle));
+ whandle.type = DRM_API_HANDLE_TYPE_SHARED;
+ whandle.handle = names[0];
+ whandle.stride = strides[0];
+ whandle.offset = offsets[0];
+ whandle.modifier = DRM_FORMAT_MOD_INVALID;
- img = dri2_create_image_from_name(screen, width, height, format,
- names[0], stride, loaderPrivate);
+ img = dri2_create_image_from_winsys(screen, width, height, format,
+ 1, &whandle, loaderPrivate);
if (img == NULL)
return NULL;
if (img == NULL)
return NULL;
+ if (img->texture->screen->resource_changed)
+ img->texture->screen->resource_changed(img->texture->screen,
+ img->texture);
+
/* set this to 0 for sub images. */
img->dri_components = 0;
return img;
void *loaderPrivate)
{
__DRIimage *img;
- int format, stride, dri_components;
-
- if (num_fds != 1)
- return NULL;
- if (offsets[0] != 0)
- return NULL;
-
- format = convert_fourcc(fourcc, &dri_components);
- if (format == -1)
- return NULL;
-
- /* Strides are in bytes not pixels. */
- stride = strides[0] /4;
+ int dri_components;
- img = dri2_create_image_from_fd(screen, width, height, format,
- fds[0], stride, loaderPrivate);
+ img = dri2_create_image_from_fd(screen, width, height, fourcc,
+ DRM_FORMAT_MOD_INVALID, fds, num_fds,
+ strides, offsets, NULL,
+ &dri_components, loaderPrivate);
if (img == NULL)
return NULL;
return img;
}
+static boolean
+dri2_query_dma_buf_formats(__DRIscreen *_screen, int max, int *formats,
+ int *count)
+{
+ struct dri_screen *screen = dri_screen(_screen);
+ struct pipe_screen *pscreen = screen->base.screen;
+ const unsigned bind = PIPE_BIND_RENDER_TARGET | PIPE_BIND_SAMPLER_VIEW;
+ int i, j;
+
+ for (i = 0, j = 0; (i < ARRAY_SIZE(fourcc_formats)) &&
+ (j < max || max == 0); i++) {
+ if (pscreen->is_format_supported(pscreen,
+ fourcc_to_pipe_format(
+ fourcc_formats[i]),
+ screen->target,
+ 0, bind)) {
+ if (j < max)
+ formats[j] = fourcc_formats[i];
+ j++;
+ }
+ }
+ *count = j;
+ return true;
+}
+
+static boolean
+dri2_query_dma_buf_modifiers(__DRIscreen *_screen, int fourcc, int max,
+ uint64_t *modifiers, unsigned int *external_only,
+ int *count)
+{
+ struct dri_screen *screen = dri_screen(_screen);
+ struct pipe_screen *pscreen = screen->base.screen;
+ enum pipe_format format = fourcc_to_pipe_format(fourcc);
+ const unsigned usage = PIPE_BIND_RENDER_TARGET | PIPE_BIND_SAMPLER_VIEW;
+
+ if (pscreen->query_dmabuf_modifiers != NULL &&
+ pscreen->is_format_supported(pscreen, format, screen->target, 0, usage)) {
+ pscreen->query_dmabuf_modifiers(pscreen, format, max, modifiers,
+ external_only, count);
+ return true;
+ }
+ return false;
+}
+
static __DRIimage *
dri2_from_dma_bufs(__DRIscreen *screen,
int width, int height, int fourcc,
void *loaderPrivate)
{
__DRIimage *img;
- int format, stride, dri_components;
+ int dri_components;
- if (num_fds != 1 || offsets[0] != 0) {
- *error = __DRI_IMAGE_ERROR_BAD_MATCH;
+ img = dri2_create_image_from_fd(screen, width, height, fourcc,
+ DRM_FORMAT_MOD_INVALID, fds, num_fds,
+ strides, offsets, error,
+ &dri_components, loaderPrivate);
+ if (img == NULL)
return NULL;
- }
- format = convert_fourcc(fourcc, &dri_components);
- if (format == -1) {
- *error = __DRI_IMAGE_ERROR_BAD_MATCH;
- return NULL;
- }
+ img->yuv_color_space = yuv_color_space;
+ img->sample_range = sample_range;
+ img->horizontal_siting = horizontal_siting;
+ img->vertical_siting = vertical_siting;
+ img->dri_components = dri_components;
+
+ *error = __DRI_IMAGE_ERROR_SUCCESS;
+ return img;
+}
- /* Strides are in bytes not pixels. */
- stride = strides[0] /4;
+static __DRIimage *
+dri2_from_dma_bufs2(__DRIscreen *screen,
+ int width, int height, int fourcc,
+ uint64_t modifier, int *fds, int num_fds,
+ int *strides, int *offsets,
+ enum __DRIYUVColorSpace yuv_color_space,
+ enum __DRISampleRange sample_range,
+ enum __DRIChromaSiting horizontal_siting,
+ enum __DRIChromaSiting vertical_siting,
+ unsigned *error,
+ void *loaderPrivate)
+{
+ __DRIimage *img;
+ int dri_components;
- img = dri2_create_image_from_fd(screen, width, height, format,
- fds[0], stride, loaderPrivate);
- if (img == NULL) {
- *error = __DRI_IMAGE_ERROR_BAD_ALLOC;
+ img = dri2_create_image_from_fd(screen, width, height, fourcc,
+ modifier, fds, num_fds, strides, offsets,
+ error, &dri_components, loaderPrivate);
+ if (img == NULL)
return NULL;
- }
img->yuv_color_space = yuv_color_space;
img->sample_range = sample_range;
screen = dri_screen(ctx->sPriv)->base.screen;
pipe->flush_resource(pipe, dst->texture);
ctx->st->flush(ctx->st, 0, &fence);
- (void) screen->fence_finish(screen, fence, PIPE_TIMEOUT_INFINITE);
+ (void) screen->fence_finish(screen, NULL, fence, PIPE_TIMEOUT_INFINITE);
screen->fence_reference(screen, &fence, NULL);
}
}
+static void *
+dri2_map_image(__DRIcontext *context, __DRIimage *image,
+ int x0, int y0, int width, int height,
+ unsigned int flags, int *stride, void **data)
+{
+ struct dri_context *ctx = dri_context(context);
+ struct pipe_context *pipe = ctx->st->pipe;
+ enum pipe_transfer_usage pipe_access = 0;
+ struct pipe_transfer *trans;
+ void *map;
+
+ if (!image || !data || *data)
+ return NULL;
+
+ if (flags & __DRI_IMAGE_TRANSFER_READ)
+ pipe_access |= PIPE_TRANSFER_READ;
+ if (flags & __DRI_IMAGE_TRANSFER_WRITE)
+ pipe_access |= PIPE_TRANSFER_WRITE;
+
+ map = pipe_transfer_map(pipe, image->texture,
+ 0, 0, pipe_access, x0, y0, width, height,
+ &trans);
+ if (map) {
+ *data = trans;
+ *stride = trans->stride;
+ }
+
+ return map;
+}
+
+static void
+dri2_unmap_image(__DRIcontext *context, __DRIimage *image, void *data)
+{
+ struct dri_context *ctx = dri_context(context);
+ struct pipe_context *pipe = ctx->st->pipe;
+
+ pipe_transfer_unmap(pipe, (struct pipe_transfer *)data);
+}
+
static void
dri2_destroy_image(__DRIimage *img)
{
/* The extension is modified during runtime if DRI_PRIME is detected */
static __DRIimageExtension dri2ImageExtension = {
- .base = { __DRI_IMAGE, 11 },
+ .base = { __DRI_IMAGE, 15 },
.createImageFromName = dri2_create_image_from_name,
.createImageFromRenderbuffer = dri2_create_image_from_renderbuffer,
.createImageFromDmaBufs = NULL,
.blitImage = dri2_blit_image,
.getCapabilities = dri2_get_capabilities,
+ .mapImage = dri2_map_image,
+ .unmapImage = dri2_unmap_image,
+};
+
+static const __DRIrobustnessExtension dri2Robustness = {
+ .base = { __DRI2_ROBUSTNESS, 1 }
+};
+
+static int
+dri2_interop_query_device_info(__DRIcontext *_ctx,
+ struct mesa_glinterop_device_info *out)
+{
+ struct pipe_screen *screen = dri_context(_ctx)->st->pipe->screen;
+
+ /* There is no version 0, thus we do not support it */
+ if (out->version == 0)
+ return MESA_GLINTEROP_INVALID_VERSION;
+
+ out->pci_segment_group = screen->get_param(screen, PIPE_CAP_PCI_GROUP);
+ out->pci_bus = screen->get_param(screen, PIPE_CAP_PCI_BUS);
+ out->pci_device = screen->get_param(screen, PIPE_CAP_PCI_DEVICE);
+ out->pci_function = screen->get_param(screen, PIPE_CAP_PCI_FUNCTION);
+
+ out->vendor_id = screen->get_param(screen, PIPE_CAP_VENDOR_ID);
+ out->device_id = screen->get_param(screen, PIPE_CAP_DEVICE_ID);
+
+ /* Instruct the caller that we support up-to version one of the interface */
+ out->version = 1;
+
+ return MESA_GLINTEROP_SUCCESS;
+}
+
+static int
+dri2_interop_export_object(__DRIcontext *_ctx,
+ struct mesa_glinterop_export_in *in,
+ struct mesa_glinterop_export_out *out)
+{
+ struct st_context_iface *st = dri_context(_ctx)->st;
+ struct pipe_screen *screen = st->pipe->screen;
+ struct gl_context *ctx = ((struct st_context *)st)->ctx;
+ struct pipe_resource *res = NULL;
+ struct winsys_handle whandle;
+ unsigned target, usage;
+ boolean success;
+
+ /* There is no version 0, thus we do not support it */
+ if (in->version == 0 || out->version == 0)
+ return MESA_GLINTEROP_INVALID_VERSION;
+
+ /* Validate the target. */
+ switch (in->target) {
+ case GL_TEXTURE_BUFFER:
+ case GL_TEXTURE_1D:
+ case GL_TEXTURE_2D:
+ case GL_TEXTURE_3D:
+ case GL_TEXTURE_RECTANGLE:
+ case GL_TEXTURE_1D_ARRAY:
+ case GL_TEXTURE_2D_ARRAY:
+ case GL_TEXTURE_CUBE_MAP_ARRAY:
+ case GL_TEXTURE_CUBE_MAP:
+ case GL_TEXTURE_2D_MULTISAMPLE:
+ case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
+ case GL_TEXTURE_EXTERNAL_OES:
+ case GL_RENDERBUFFER:
+ case GL_ARRAY_BUFFER:
+ target = in->target;
+ break;
+ case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
+ case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
+ case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
+ case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
+ case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
+ case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
+ target = GL_TEXTURE_CUBE_MAP;
+ break;
+ default:
+ return MESA_GLINTEROP_INVALID_TARGET;
+ }
+
+ /* Validate the simple case of miplevel. */
+ if ((target == GL_RENDERBUFFER || target == GL_ARRAY_BUFFER) &&
+ in->miplevel != 0)
+ return MESA_GLINTEROP_INVALID_MIP_LEVEL;
+
+ /* Validate the OpenGL object and get pipe_resource. */
+ mtx_lock(&ctx->Shared->Mutex);
+
+ if (target == GL_ARRAY_BUFFER) {
+ /* Buffer objects.
+ *
+ * The error checking is based on the documentation of
+ * clCreateFromGLBuffer from OpenCL 2.0 SDK.
+ */
+ struct gl_buffer_object *buf = _mesa_lookup_bufferobj(ctx, in->obj);
+
+ /* From OpenCL 2.0 SDK, clCreateFromGLBuffer:
+ * "CL_INVALID_GL_OBJECT if bufobj is not a GL buffer object or is
+ * a GL buffer object but does not have an existing data store or
+ * the size of the buffer is 0."
+ */
+ if (!buf || buf->Size == 0) {
+ mtx_unlock(&ctx->Shared->Mutex);
+ return MESA_GLINTEROP_INVALID_OBJECT;
+ }
+
+ res = st_buffer_object(buf)->buffer;
+ if (!res) {
+ /* this shouldn't happen */
+ mtx_unlock(&ctx->Shared->Mutex);
+ return MESA_GLINTEROP_INVALID_OBJECT;
+ }
+
+ out->buf_offset = 0;
+ out->buf_size = buf->Size;
+
+ buf->UsageHistory |= USAGE_DISABLE_MINMAX_CACHE;
+ } else if (target == GL_RENDERBUFFER) {
+ /* Renderbuffers.
+ *
+ * The error checking is based on the documentation of
+ * clCreateFromGLRenderbuffer from OpenCL 2.0 SDK.
+ */
+ struct gl_renderbuffer *rb = _mesa_lookup_renderbuffer(ctx, in->obj);
+
+ /* From OpenCL 2.0 SDK, clCreateFromGLRenderbuffer:
+ * "CL_INVALID_GL_OBJECT if renderbuffer is not a GL renderbuffer
+ * object or if the width or height of renderbuffer is zero."
+ */
+ if (!rb || rb->Width == 0 || rb->Height == 0) {
+ mtx_unlock(&ctx->Shared->Mutex);
+ return MESA_GLINTEROP_INVALID_OBJECT;
+ }
+
+ /* From OpenCL 2.0 SDK, clCreateFromGLRenderbuffer:
+ * "CL_INVALID_OPERATION if renderbuffer is a multi-sample GL
+ * renderbuffer object."
+ */
+ if (rb->NumSamples > 1) {
+ mtx_unlock(&ctx->Shared->Mutex);
+ return MESA_GLINTEROP_INVALID_OPERATION;
+ }
+
+ /* From OpenCL 2.0 SDK, clCreateFromGLRenderbuffer:
+ * "CL_OUT_OF_RESOURCES if there is a failure to allocate resources
+ * required by the OpenCL implementation on the device."
+ */
+ res = st_renderbuffer(rb)->texture;
+ if (!res) {
+ mtx_unlock(&ctx->Shared->Mutex);
+ return MESA_GLINTEROP_OUT_OF_RESOURCES;
+ }
+
+ out->internal_format = rb->InternalFormat;
+ out->view_minlevel = 0;
+ out->view_numlevels = 1;
+ out->view_minlayer = 0;
+ out->view_numlayers = 1;
+ } else {
+ /* Texture objects.
+ *
+ * The error checking is based on the documentation of
+ * clCreateFromGLTexture from OpenCL 2.0 SDK.
+ */
+ struct gl_texture_object *obj = _mesa_lookup_texture(ctx, in->obj);
+
+ if (obj)
+ _mesa_test_texobj_completeness(ctx, obj);
+
+ /* From OpenCL 2.0 SDK, clCreateFromGLTexture:
+ * "CL_INVALID_GL_OBJECT if texture is not a GL texture object whose
+ * type matches texture_target, if the specified miplevel of texture
+ * is not defined, or if the width or height of the specified
+ * miplevel is zero or if the GL texture object is incomplete."
+ */
+ if (!obj ||
+ obj->Target != target ||
+ !obj->_BaseComplete ||
+ (in->miplevel > 0 && !obj->_MipmapComplete)) {
+ mtx_unlock(&ctx->Shared->Mutex);
+ return MESA_GLINTEROP_INVALID_OBJECT;
+ }
+
+ /* From OpenCL 2.0 SDK, clCreateFromGLTexture:
+ * "CL_INVALID_MIP_LEVEL if miplevel is less than the value of
+ * levelbase (for OpenGL implementations) or zero (for OpenGL ES
+ * implementations); or greater than the value of q (for both OpenGL
+ * and OpenGL ES). levelbase and q are defined for the texture in
+ * section 3.8.10 (Texture Completeness) of the OpenGL 2.1
+ * specification and section 3.7.10 of the OpenGL ES 2.0."
+ */
+ if (in->miplevel < obj->BaseLevel || in->miplevel > obj->_MaxLevel) {
+ mtx_unlock(&ctx->Shared->Mutex);
+ return MESA_GLINTEROP_INVALID_MIP_LEVEL;
+ }
+
+ if (!st_finalize_texture(ctx, st->pipe, obj, 0)) {
+ mtx_unlock(&ctx->Shared->Mutex);
+ return MESA_GLINTEROP_OUT_OF_RESOURCES;
+ }
+
+ res = st_get_texobj_resource(obj);
+ if (!res) {
+ /* Incomplete texture buffer object? This shouldn't really occur. */
+ mtx_unlock(&ctx->Shared->Mutex);
+ return MESA_GLINTEROP_INVALID_OBJECT;
+ }
+
+ if (target == GL_TEXTURE_BUFFER) {
+ out->internal_format = obj->BufferObjectFormat;
+ out->buf_offset = obj->BufferOffset;
+ out->buf_size = obj->BufferSize == -1 ? obj->BufferObject->Size :
+ obj->BufferSize;
+
+ obj->BufferObject->UsageHistory |= USAGE_DISABLE_MINMAX_CACHE;
+ } else {
+ out->internal_format = obj->Image[0][0]->InternalFormat;
+ out->view_minlevel = obj->MinLevel;
+ out->view_numlevels = obj->NumLevels;
+ out->view_minlayer = obj->MinLayer;
+ out->view_numlayers = obj->NumLayers;
+ }
+ }
+
+ /* Get the handle. */
+ switch (in->access) {
+ case MESA_GLINTEROP_ACCESS_READ_WRITE:
+ usage = PIPE_HANDLE_USAGE_READ_WRITE;
+ break;
+ case MESA_GLINTEROP_ACCESS_READ_ONLY:
+ usage = PIPE_HANDLE_USAGE_READ;
+ break;
+ case MESA_GLINTEROP_ACCESS_WRITE_ONLY:
+ usage = PIPE_HANDLE_USAGE_WRITE;
+ break;
+ default:
+ usage = 0;
+ }
+
+ memset(&whandle, 0, sizeof(whandle));
+ whandle.type = DRM_API_HANDLE_TYPE_FD;
+
+ success = screen->resource_get_handle(screen, st->pipe, res, &whandle,
+ usage);
+ mtx_unlock(&ctx->Shared->Mutex);
+
+ if (!success)
+ return MESA_GLINTEROP_OUT_OF_HOST_MEMORY;
+
+ out->dmabuf_fd = whandle.handle;
+ out->out_driver_data_written = 0;
+
+ if (res->target == PIPE_BUFFER)
+ out->buf_offset += whandle.offset;
+
+ /* Instruct the caller that we support up-to version one of the interface */
+ in->version = 1;
+ out->version = 1;
+
+ return MESA_GLINTEROP_SUCCESS;
+}
+
+static const __DRI2interopExtension dri2InteropExtension = {
+ .base = { __DRI2_INTEROP, 1 },
+ .query_device_info = dri2_interop_query_device_info,
+ .export_object = dri2_interop_export_object
+};
+
+/**
+ * \brief the DRI2ConfigQueryExtension configQueryb method
+ */
+static int
+dri2GalliumConfigQueryb(__DRIscreen *sPriv, const char *var,
+ unsigned char *val)
+{
+ struct dri_screen *screen = dri_screen(sPriv);
+
+ if (!driCheckOption(&screen->optionCache, var, DRI_BOOL))
+ return dri2ConfigQueryExtension.configQueryb(sPriv, var, val);
+
+ *val = driQueryOptionb(&screen->optionCache, var);
+
+ return 0;
+}
+
+/**
+ * \brief the DRI2ConfigQueryExtension configQueryi method
+ */
+static int
+dri2GalliumConfigQueryi(__DRIscreen *sPriv, const char *var, int *val)
+{
+ struct dri_screen *screen = dri_screen(sPriv);
+
+ if (!driCheckOption(&screen->optionCache, var, DRI_INT) &&
+ !driCheckOption(&screen->optionCache, var, DRI_ENUM))
+ return dri2ConfigQueryExtension.configQueryi(sPriv, var, val);
+
+ *val = driQueryOptioni(&screen->optionCache, var);
+
+ return 0;
+}
+
+/**
+ * \brief the DRI2ConfigQueryExtension configQueryf method
+ */
+static int
+dri2GalliumConfigQueryf(__DRIscreen *sPriv, const char *var, float *val)
+{
+ struct dri_screen *screen = dri_screen(sPriv);
+
+ if (!driCheckOption(&screen->optionCache, var, DRI_FLOAT))
+ return dri2ConfigQueryExtension.configQueryf(sPriv, var, val);
+
+ *val = driQueryOptionf(&screen->optionCache, var);
+
+ return 0;
+}
+
+/**
+ * \brief the DRI2ConfigQueryExtension struct.
+ *
+ * We first query the driver option cache. Then the dri2 option cache.
+ */
+static const __DRI2configQueryExtension dri2GalliumConfigQueryExtension = {
+ .base = { __DRI2_CONFIG_QUERY, 1 },
+
+ .configQueryb = dri2GalliumConfigQueryb,
+ .configQueryi = dri2GalliumConfigQueryi,
+ .configQueryf = dri2GalliumConfigQueryf,
};
/*
&dri2FlushExtension.base,
&dri2ImageExtension.base,
&dri2RendererQueryExtension.base,
- &dri2ConfigQueryExtension.base,
+ &dri2GalliumConfigQueryExtension.base,
&dri2ThrottleExtension.base,
+ &dri2FenceExtension.base,
+ &dri2InteropExtension.base,
+ &dri2NoErrorExtension.base,
+ NULL
+};
+
+static const __DRIextension *dri_robust_screen_extensions[] = {
+ &driTexBufferExtension.base,
+ &dri2FlushExtension.base,
+ &dri2ImageExtension.base,
+ &dri2RendererQueryExtension.base,
+ &dri2GalliumConfigQueryExtension.base,
+ &dri2ThrottleExtension.base,
+ &dri2FenceExtension.base,
+ &dri2InteropExtension.base,
+ &dri2Robustness.base,
+ &dri2NoErrorExtension.base,
NULL
};
const __DRIconfig **configs;
struct dri_screen *screen;
struct pipe_screen *pscreen = NULL;
- const struct drm_conf_ret *throttle_ret = NULL;
- const struct drm_conf_ret *dmabuf_ret = NULL;
+ const struct drm_conf_ret *throttle_ret;
+ const struct drm_conf_ret *dmabuf_ret;
+ int fd;
screen = CALLOC_STRUCT(dri_screen);
if (!screen)
screen->sPriv = sPriv;
screen->fd = sPriv->fd;
+ (void) mtx_init(&screen->opencl_func_mutex, mtx_plain);
sPriv->driverPrivate = (void *)screen;
-#if GALLIUM_STATIC_TARGETS
- pscreen = dd_create_screen(screen->fd);
+ if (screen->fd < 0 || (fd = fcntl(screen->fd, F_DUPFD_CLOEXEC, 3)) < 0)
+ goto free_screen;
+
- throttle_ret = dd_configuration(DRM_CONF_THROTTLE);
- dmabuf_ret = dd_configuration(DRM_CONF_SHARE_FD);
-#else
- if (pipe_loader_drm_probe_fd(&screen->dev, screen->fd, false)) {
- pscreen = pipe_loader_create_screen(screen->dev, PIPE_SEARCH_DIR);
+ if (pipe_loader_drm_probe_fd(&screen->dev, fd)) {
+ unsigned flags =
+ dri_init_options_get_screen_flags(screen, screen->dev->driver_name);
- throttle_ret = pipe_loader_configuration(screen->dev, DRM_CONF_THROTTLE);
- dmabuf_ret = pipe_loader_configuration(screen->dev, DRM_CONF_SHARE_FD);
+ pscreen = pipe_loader_create_screen(screen->dev, flags);
}
-#endif // GALLIUM_STATIC_TARGETS
+
+ if (!pscreen)
+ goto release_pipe;
+
+ throttle_ret = pipe_loader_configuration(screen->dev, DRM_CONF_THROTTLE);
+ dmabuf_ret = pipe_loader_configuration(screen->dev, DRM_CONF_SHARE_FD);
if (throttle_ret && throttle_ret->val.val_int != -1) {
screen->throttling_enabled = TRUE;
screen->default_throttle_frames = throttle_ret->val.val_int;
}
+ if (pscreen->resource_create_with_modifiers)
+ dri2ImageExtension.createImageWithModifiers =
+ dri2_create_image_with_modifiers;
+
if (dmabuf_ret && dmabuf_ret->val.val_bool) {
uint64_t cap;
(cap & DRM_PRIME_CAP_IMPORT)) {
dri2ImageExtension.createImageFromFds = dri2_from_fds;
dri2ImageExtension.createImageFromDmaBufs = dri2_from_dma_bufs;
+ dri2ImageExtension.createImageFromDmaBufs2 = dri2_from_dma_bufs2;
+ dri2ImageExtension.queryDmaBufFormats = dri2_query_dma_buf_formats;
+ dri2ImageExtension.queryDmaBufModifiers =
+ dri2_query_dma_buf_modifiers;
}
}
- sPriv->extensions = dri_screen_extensions;
-
- /* dri_init_screen_helper checks pscreen for us */
+ if (pscreen->get_param(pscreen, PIPE_CAP_DEVICE_RESET_STATUS_QUERY)) {
+ sPriv->extensions = dri_robust_screen_extensions;
+ screen->has_reset_status_query = true;
+ }
+ else
+ sPriv->extensions = dri_screen_extensions;
-#if GALLIUM_STATIC_TARGETS
- configs = dri_init_screen_helper(screen, pscreen, dd_driver_name());
-#else
- configs = dri_init_screen_helper(screen, pscreen, screen->dev->driver_name);
-#endif // GALLIUM_STATIC_TARGETS
+ configs = dri_init_screen_helper(screen, pscreen);
if (!configs)
- goto fail;
+ goto destroy_screen;
screen->can_share_buffer = true;
screen->auto_fake_front = dri_with_format(sPriv);
screen->lookup_egl_image = dri2_lookup_egl_image;
return configs;
-fail:
+
+destroy_screen:
dri_destroy_screen_helper(screen);
-#if !GALLIUM_STATIC_TARGETS
+
+release_pipe:
if (screen->dev)
pipe_loader_release(&screen->dev, 1);
-#endif // !GALLIUM_STATIC_TARGETS
+ else
+ close(fd);
+
+free_screen:
FREE(screen);
return NULL;
}
static const __DRIconfig **
dri_kms_init_screen(__DRIscreen * sPriv)
{
-#if GALLIUM_STATIC_TARGETS
#if defined(GALLIUM_SOFTPIPE)
const __DRIconfig **configs;
struct dri_screen *screen;
struct pipe_screen *pscreen = NULL;
uint64_t cap;
+ int fd;
screen = CALLOC_STRUCT(dri_screen);
if (!screen)
sPriv->driverPrivate = (void *)screen;
- pscreen = kms_swrast_create_screen(screen->fd);
+ if (screen->fd < 0 || (fd = fcntl(screen->fd, F_DUPFD_CLOEXEC, 3)) < 0)
+ goto free_screen;
+
+ unsigned flags = dri_init_options_get_screen_flags(screen, "swrast");
+
+ if (pipe_loader_sw_probe_kms(&screen->dev, fd))
+ pscreen = pipe_loader_create_screen(screen->dev, flags);
+
+ if (!pscreen)
+ goto release_pipe;
+
+ if (pscreen->resource_create_with_modifiers)
+ dri2ImageExtension.createImageWithModifiers =
+ dri2_create_image_with_modifiers;
if (drmGetCap(sPriv->fd, DRM_CAP_PRIME, &cap) == 0 &&
(cap & DRM_PRIME_CAP_IMPORT)) {
dri2ImageExtension.createImageFromFds = dri2_from_fds;
dri2ImageExtension.createImageFromDmaBufs = dri2_from_dma_bufs;
+ dri2ImageExtension.createImageFromDmaBufs2 = dri2_from_dma_bufs2;
+ dri2ImageExtension.queryDmaBufFormats = dri2_query_dma_buf_formats;
+ dri2ImageExtension.queryDmaBufModifiers = dri2_query_dma_buf_modifiers;
}
sPriv->extensions = dri_screen_extensions;
- /* dri_init_screen_helper checks pscreen for us */
- configs = dri_init_screen_helper(screen, pscreen, "swrast");
+ configs = dri_init_screen_helper(screen, pscreen);
if (!configs)
- goto fail;
+ goto destroy_screen;
screen->can_share_buffer = false;
screen->auto_fake_front = dri_with_format(sPriv);
screen->lookup_egl_image = dri2_lookup_egl_image;
return configs;
-fail:
+
+destroy_screen:
dri_destroy_screen_helper(screen);
+
+release_pipe:
+ if (screen->dev)
+ pipe_loader_release(&screen->dev, 1);
+ else
+ close(fd);
+
+free_screen:
FREE(screen);
#endif // GALLIUM_SOFTPIPE
-#endif // GALLIUM_STATIC_TARGETS
return NULL;
}
&driImageDriverExtension.base,
&driDRI2Extension.base,
&gallium_config_options.base,
+ &dri2FenceExtension.base,
NULL
};