*/
#include <xf86drm.h>
+#include <dlfcn.h>
#include "util/u_memory.h"
#include "util/u_inlines.h"
#include "util/u_format.h"
return format;
}
+static int convert_to_fourcc(int format)
+{
+ switch(format) {
+ case __DRI_IMAGE_FORMAT_RGB565:
+ format = __DRI_IMAGE_FOURCC_RGB565;
+ break;
+ case __DRI_IMAGE_FORMAT_ARGB8888:
+ format = __DRI_IMAGE_FOURCC_ARGB8888;
+ break;
+ case __DRI_IMAGE_FORMAT_XRGB8888:
+ format = __DRI_IMAGE_FOURCC_XRGB8888;
+ break;
+ case __DRI_IMAGE_FORMAT_ABGR8888:
+ format = __DRI_IMAGE_FOURCC_ABGR8888;
+ break;
+ case __DRI_IMAGE_FORMAT_XBGR8888:
+ format = __DRI_IMAGE_FOURCC_XBGR8888;
+ break;
+ default:
+ return -1;
+ }
+ return format;
+}
+
/**
* DRI2 flush extension.
*/
* may occur as the stvis->color_format.
*/
switch(format) {
- case PIPE_FORMAT_B8G8R8A8_UNORM:
+ case PIPE_FORMAT_BGRA8888_UNORM:
depth = 32;
break;
- case PIPE_FORMAT_B8G8R8X8_UNORM:
+ case PIPE_FORMAT_BGRX8888_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_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;
/* Image specific variables */
struct __DRIimageList images;
/* Dri2 specific variables */
- __DRIbuffer *buffers;
+ __DRIbuffer *buffers = NULL;
struct winsys_handle whandle;
unsigned num_buffers = statts_count;
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.
pf = PIPE_FORMAT_B5G6R5_UNORM;
break;
case __DRI_IMAGE_FORMAT_XRGB8888:
- pf = PIPE_FORMAT_B8G8R8X8_UNORM;
+ pf = PIPE_FORMAT_BGRX8888_UNORM;
break;
case __DRI_IMAGE_FORMAT_ARGB8888:
- pf = PIPE_FORMAT_B8G8R8A8_UNORM;
+ pf = PIPE_FORMAT_BGRA8888_UNORM;
break;
case __DRI_IMAGE_FORMAT_ABGR8888:
- pf = PIPE_FORMAT_R8G8B8A8_UNORM;
+ pf = PIPE_FORMAT_RGBA8888_UNORM;
break;
default:
pf = PIPE_FORMAT_NONE;
pf = PIPE_FORMAT_B5G6R5_UNORM;
break;
case __DRI_IMAGE_FORMAT_XRGB8888:
- pf = PIPE_FORMAT_B8G8R8X8_UNORM;
+ pf = PIPE_FORMAT_BGRX8888_UNORM;
break;
case __DRI_IMAGE_FORMAT_ARGB8888:
- pf = PIPE_FORMAT_B8G8R8A8_UNORM;
+ pf = PIPE_FORMAT_BGRA8888_UNORM;
break;
case __DRI_IMAGE_FORMAT_ABGR8888:
- pf = PIPE_FORMAT_R8G8B8A8_UNORM;
+ pf = PIPE_FORMAT_RGBA8888_UNORM;
break;
default:
pf = PIPE_FORMAT_NONE;
return GL_FALSE;
*value = image->dri_components;
return GL_TRUE;
+ case __DRI_IMAGE_ATTRIB_FOURCC:
+ *value = convert_to_fourcc(image->dri_format);
+ return GL_TRUE;
+ case __DRI_IMAGE_ATTRIB_NUM_PLANES:
+ *value = 1;
+ return GL_TRUE;
default:
return GL_FALSE;
}
/* The extension is modified during runtime if DRI_PRIME is detected */
static __DRIimageExtension dri2ImageExtension = {
- .base = { __DRI_IMAGE, 10 },
+ .base = { __DRI_IMAGE, 11 },
.createImageFromName = dri2_create_image_from_name,
.createImageFromRenderbuffer = dri2_create_image_from_renderbuffer,
.getCapabilities = dri2_get_capabilities,
};
+
+static bool
+dri2_is_opencl_interop_loaded_locked(struct dri_screen *screen)
+{
+ return screen->opencl_dri_event_add_ref &&
+ screen->opencl_dri_event_release &&
+ screen->opencl_dri_event_wait &&
+ screen->opencl_dri_event_get_fence;
+}
+
+static bool
+dri2_load_opencl_interop(struct dri_screen *screen)
+{
+#if defined(RTLD_DEFAULT)
+ bool success;
+
+ pipe_mutex_lock(screen->opencl_func_mutex);
+
+ if (dri2_is_opencl_interop_loaded_locked(screen)) {
+ pipe_mutex_unlock(screen->opencl_func_mutex);
+ return true;
+ }
+
+ screen->opencl_dri_event_add_ref =
+ dlsym(RTLD_DEFAULT, "opencl_dri_event_add_ref");
+ screen->opencl_dri_event_release =
+ dlsym(RTLD_DEFAULT, "opencl_dri_event_release");
+ screen->opencl_dri_event_wait =
+ dlsym(RTLD_DEFAULT, "opencl_dri_event_wait");
+ screen->opencl_dri_event_get_fence =
+ dlsym(RTLD_DEFAULT, "opencl_dri_event_get_fence");
+
+ success = dri2_is_opencl_interop_loaded_locked(screen);
+ pipe_mutex_unlock(screen->opencl_func_mutex);
+ return success;
+#else
+ return false;
+#endif
+}
+
+struct dri2_fence {
+ struct dri_screen *driscreen;
+ struct pipe_fence_handle *pipe_fence;
+ void *cl_event;
+};
+
+static void *
+dri2_create_fence(__DRIcontext *_ctx)
+{
+ struct pipe_context *ctx = dri_context(_ctx)->st->pipe;
+ struct dri2_fence *fence = CALLOC_STRUCT(dri2_fence);
+
+ if (!fence)
+ return NULL;
+
+ ctx->flush(ctx, &fence->pipe_fence, 0);
+
+ if (!fence->pipe_fence) {
+ FREE(fence);
+ return NULL;
+ }
+
+ fence->driscreen = dri_screen(_ctx->driScreenPriv);
+ return fence;
+}
+
+static void *
+dri2_get_fence_from_cl_event(__DRIscreen *_screen, intptr_t cl_event)
+{
+ struct dri_screen *driscreen = dri_screen(_screen);
+ struct dri2_fence *fence;
+
+ if (!dri2_load_opencl_interop(driscreen))
+ return NULL;
+
+ fence = CALLOC_STRUCT(dri2_fence);
+ if (!fence)
+ return NULL;
+
+ fence->cl_event = (void*)cl_event;
+
+ if (!driscreen->opencl_dri_event_add_ref(fence->cl_event)) {
+ free(fence);
+ return NULL;
+ }
+
+ fence->driscreen = driscreen;
+ return fence;
+}
+
+static void
+dri2_destroy_fence(__DRIscreen *_screen, void *_fence)
+{
+ struct dri_screen *driscreen = dri_screen(_screen);
+ struct pipe_screen *screen = driscreen->base.screen;
+ struct dri2_fence *fence = (struct dri2_fence*)_fence;
+
+ if (fence->pipe_fence)
+ screen->fence_reference(screen, &fence->pipe_fence, NULL);
+ else if (fence->cl_event)
+ driscreen->opencl_dri_event_release(fence->cl_event);
+ else
+ assert(0);
+
+ FREE(fence);
+}
+
+static GLboolean
+dri2_client_wait_sync(__DRIcontext *_ctx, void *_fence, unsigned flags,
+ uint64_t timeout)
+{
+ struct dri2_fence *fence = (struct dri2_fence*)_fence;
+ struct dri_screen *driscreen = fence->driscreen;
+ struct pipe_screen *screen = driscreen->base.screen;
+
+ /* No need to flush. The context was flushed when the fence was created. */
+
+ if (fence->pipe_fence)
+ return screen->fence_finish(screen, fence->pipe_fence, timeout);
+ else if (fence->cl_event) {
+ struct pipe_fence_handle *pipe_fence =
+ driscreen->opencl_dri_event_get_fence(fence->cl_event);
+
+ if (pipe_fence)
+ return screen->fence_finish(screen, pipe_fence, timeout);
+ else
+ return driscreen->opencl_dri_event_wait(fence->cl_event, timeout);
+ }
+ else {
+ assert(0);
+ return false;
+ }
+}
+
+static void
+dri2_server_wait_sync(__DRIcontext *_ctx, void *_fence, unsigned flags)
+{
+ /* AFAIK, no driver currently supports parallel context execution. */
+}
+
+static __DRI2fenceExtension dri2FenceExtension = {
+ .base = { __DRI2_FENCE, 1 },
+
+ .create_fence = dri2_create_fence,
+ .get_fence_from_cl_event = dri2_get_fence_from_cl_event,
+ .destroy_fence = dri2_destroy_fence,
+ .client_wait_sync = dri2_client_wait_sync,
+ .server_wait_sync = dri2_server_wait_sync
+};
+
+static const __DRIrobustnessExtension dri2Robustness = {
+ .base = { __DRI2_ROBUSTNESS, 1 }
+};
+
/*
* Backend function init_screen.
*/
&dri2RendererQueryExtension.base,
&dri2ConfigQueryExtension.base,
&dri2ThrottleExtension.base,
+ &dri2FenceExtension.base,
+ NULL
+};
+
+static const __DRIextension *dri_robust_screen_extensions[] = {
+ &driTexBufferExtension.base,
+ &dri2FlushExtension.base,
+ &dri2ImageExtension.base,
+ &dri2RendererQueryExtension.base,
+ &dri2ConfigQueryExtension.base,
+ &dri2ThrottleExtension.base,
+ &dri2FenceExtension.base,
+ &dri2Robustness.base,
NULL
};
screen->sPriv = sPriv;
screen->fd = sPriv->fd;
+ pipe_mutex_init(screen->opencl_func_mutex);
sPriv->driverPrivate = (void *)screen;
-#if GALLIUM_STATIC_TARGETS
- pscreen = dd_create_screen(screen->fd);
-
- 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, dup(screen->fd))) {
+ pscreen = pipe_loader_create_screen(screen->dev);
throttle_ret = pipe_loader_configuration(screen->dev, DRM_CONF_THROTTLE);
dmabuf_ret = pipe_loader_configuration(screen->dev, DRM_CONF_SHARE_FD);
}
-#endif // GALLIUM_STATIC_TARGETS
if (throttle_ret && throttle_ret->val.val_int != -1) {
screen->throttling_enabled = TRUE;
}
}
- sPriv->extensions = dri_screen_extensions;
+ if (pscreen && 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;
/* dri_init_screen_helper checks pscreen for us */
-#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
if (!configs)
goto fail;
return configs;
fail:
dri_destroy_screen_helper(screen);
-#if !GALLIUM_STATIC_TARGETS
if (screen->dev)
pipe_loader_release(&screen->dev, 1);
-#endif // !GALLIUM_STATIC_TARGETS
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;
sPriv->driverPrivate = (void *)screen;
- pscreen = kms_swrast_create_screen(screen->fd);
+ if (pipe_loader_sw_probe_kms(&screen->dev, dup(screen->fd)))
+ pscreen = pipe_loader_create_screen(screen->dev);
if (drmGetCap(sPriv->fd, DRM_CAP_PRIME, &cap) == 0 &&
(cap & DRM_PRIME_CAP_IMPORT)) {
return configs;
fail:
dri_destroy_screen_helper(screen);
+ if (screen->dev)
+ pipe_loader_release(&screen->dev, 1);
FREE(screen);
#endif // GALLIUM_SOFTPIPE
-#endif // GALLIUM_STATIC_TARGETS
return NULL;
}