#include <sys/stat.h>
-#include <drm_fourcc.h>
-#include <tegra_drm.h>
+#include "drm-uapi/drm_fourcc.h"
+#include "drm-uapi/tegra_drm.h"
#include <xf86drm.h>
+#include "loader/loader.h"
#include "pipe/p_state.h"
#include "util/u_debug.h"
#include "util/u_inlines.h"
enum pipe_format format,
enum pipe_texture_target target,
unsigned sample_count,
+ unsigned storage_sample_count,
unsigned usage)
{
struct tegra_screen *screen = to_tegra_screen(pscreen);
return screen->gpu->is_format_supported(screen->gpu, format, target,
- sample_count, usage);
+ sample_count, storage_sample_count,
+ usage);
}
static boolean
return screen->gpu->can_create_resource(screen->gpu, template);
}
-static int tegra_open_render_node(void)
-{
- drmDevicePtr *devices, device;
- int err, render = -ENOENT, fd;
- unsigned int num, i;
-
- err = drmGetDevices2(0, NULL, 0);
- if (err < 0)
- return err;
-
- num = err;
-
- devices = calloc(num, sizeof(*devices));
- if (!devices)
- return -ENOMEM;
-
- err = drmGetDevices2(0, devices, num);
- if (err < 0) {
- render = err;
- goto free;
- }
-
- for (i = 0; i < num; i++) {
- device = devices[i];
-
- if ((device->available_nodes & (1 << DRM_NODE_RENDER)) &&
- (device->bustype == DRM_BUS_PLATFORM)) {
- drmVersionPtr version;
-
- fd = open(device->nodes[DRM_NODE_RENDER], O_RDWR | O_CLOEXEC);
- if (fd < 0)
- continue;
-
- version = drmGetVersion(fd);
- if (!version) {
- close(fd);
- continue;
- }
-
- if (strcmp(version->name, "nouveau") != 0) {
- close(fd);
- continue;
- }
-
- drmFreeVersion(version);
- render = fd;
- break;
- }
- }
-
- drmFreeDevices(devices, num);
-
-free:
- free(devices);
- return render;
-}
-
static int tegra_screen_import_resource(struct tegra_screen *screen,
struct tegra_resource *resource)
{
- unsigned usage = PIPE_HANDLE_USAGE_READ;
struct winsys_handle handle;
boolean status;
int fd, err;
memset(&handle, 0, sizeof(handle));
handle.modifier = DRM_FORMAT_MOD_INVALID;
- handle.type = DRM_API_HANDLE_TYPE_FD;
+ handle.type = WINSYS_HANDLE_TYPE_FD;
status = screen->gpu->resource_get_handle(screen->gpu, NULL, resource->gpu,
- &handle, usage);
+ &handle, 0);
if (!status)
return -EINVAL;
const struct pipe_resource *template)
{
struct tegra_screen *screen = to_tegra_screen(pscreen);
+ uint64_t modifier = DRM_FORMAT_MOD_INVALID;
struct tegra_resource *resource;
int err;
if (!resource)
return NULL;
- resource->gpu = screen->gpu->resource_create(screen->gpu, template);
+ /*
+ * Applications that create scanout resources without modifiers are very
+ * unlikely to support modifiers at all. In that case the resources need
+ * to be created with a pitch-linear layout so that they can be properly
+ * shared with scanout hardware.
+ *
+ * Technically it is possible for applications to create resources without
+ * specifying a modifier but still query the modifier associated with the
+ * resource (e.g. using gbm_bo_get_modifier()) before handing it to the
+ * framebuffer creation API (such as the DRM_IOCTL_MODE_ADDFB2 IOCTL).
+ */
+ if (template->bind & PIPE_BIND_SCANOUT)
+ modifier = DRM_FORMAT_MOD_LINEAR;
+
+ resource->gpu = screen->gpu->resource_create_with_modifiers(screen->gpu,
+ template,
+ &modifier, 1);
if (!resource->gpu)
goto free;
* to pass buffers into Tegra DRM for display. In all other cases, return
* the Nouveau handle, assuming they will be used for sharing in DRI2/3.
*/
- if (handle->type == DRM_API_HANDLE_TYPE_KMS &&
+ if (handle->type == WINSYS_HANDLE_TYPE_KMS &&
presource->bind & PIPE_BIND_SCANOUT) {
handle->modifier = resource->modifier;
handle->handle = resource->handle;
int count)
{
struct tegra_screen *screen = to_tegra_screen(pscreen);
+ struct pipe_resource tmpl = *template;
struct tegra_resource *resource;
int err;
if (!resource)
return NULL;
+ /*
+ * Assume that resources created with modifiers will always be used for
+ * scanout. This is necessary because some of the APIs that are used to
+ * create resources with modifiers (e.g. gbm_bo_create_with_modifiers())
+ * can't pass along usage information. Adding that capability might be
+ * worth adding to remove this ambiguity. Not all future use-cases that
+ * involve modifiers may always be targetting scanout hardware.
+ */
+ tmpl.bind |= PIPE_BIND_SCANOUT;
+
resource->gpu = screen->gpu->resource_create_with_modifiers(screen->gpu,
- template,
+ &tmpl,
modifiers,
count);
if (!resource->gpu)
screen->fd = fd;
- screen->gpu_fd = tegra_open_render_node();
+ screen->gpu_fd = loader_open_render_node("nouveau");
if (screen->gpu_fd < 0) {
if (errno != ENOENT)
fprintf(stderr, "failed to open GPU device: %s\n", strerror(errno));