forked from 12to11/12to11
Check in new files for dma-buf tests
* tests/argb8888_implicit.dump: * tests/argb8888_linear.dump: * tests/dmabuf_test.c: New files.
This commit is contained in:
parent
b0815b0b8c
commit
ec30b855b6
3 changed files with 735 additions and 0 deletions
BIN
tests/argb8888_implicit.dump
Normal file
BIN
tests/argb8888_implicit.dump
Normal file
Binary file not shown.
BIN
tests/argb8888_linear.dump
Normal file
BIN
tests/argb8888_linear.dump
Normal file
Binary file not shown.
735
tests/dmabuf_test.c
Normal file
735
tests/dmabuf_test.c
Normal file
|
@ -0,0 +1,735 @@
|
||||||
|
/* Tests for the Wayland compositor running on the X server.
|
||||||
|
|
||||||
|
Copyright (C) 2022 to various contributors.
|
||||||
|
|
||||||
|
This file is part of 12to11.
|
||||||
|
|
||||||
|
12to11 is free software: you can redistribute it and/or modify it
|
||||||
|
under the terms of the GNU General Public License as published by the
|
||||||
|
Free Software Foundation, either version 3 of the License, or (at your
|
||||||
|
option) any later version.
|
||||||
|
|
||||||
|
12to11 is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with 12to11. If not, see <https://www.gnu.org/licenses/>. */
|
||||||
|
|
||||||
|
#include <xf86drm.h>
|
||||||
|
#include <gbm.h>
|
||||||
|
#include <drm/drm_fourcc.h>
|
||||||
|
|
||||||
|
#include <sys/mman.h>
|
||||||
|
#include <sys/fcntl.h>
|
||||||
|
|
||||||
|
#include "test_harness.h"
|
||||||
|
#include "linux-dmabuf-unstable-v1.h"
|
||||||
|
|
||||||
|
/* N.B. that this test will have to be adjusted once multiple devices
|
||||||
|
are fully supported. */
|
||||||
|
|
||||||
|
enum test_kind
|
||||||
|
{
|
||||||
|
ARGB8888_KIND,
|
||||||
|
ARGB8888_LINEAR_KIND,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const char *test_names[] =
|
||||||
|
{
|
||||||
|
"argb8888",
|
||||||
|
"argb8888_linear",
|
||||||
|
};
|
||||||
|
|
||||||
|
#define LAST_TEST ARGB8888_LINEAR_KIND
|
||||||
|
|
||||||
|
struct test_params_data
|
||||||
|
{
|
||||||
|
/* The buffer. */
|
||||||
|
struct wl_buffer *buffer;
|
||||||
|
|
||||||
|
/* Flag that indicates completion. */
|
||||||
|
bool complete;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct test_feedback_tranche
|
||||||
|
{
|
||||||
|
/* The next tranche (with higher priority). */
|
||||||
|
struct test_feedback_tranche *next;
|
||||||
|
|
||||||
|
/* Array of indices into the format-modifier table. */
|
||||||
|
uint16_t *indices;
|
||||||
|
|
||||||
|
/* Number of format-modifier pairs supported. */
|
||||||
|
int n_indices;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct test_feedback_data
|
||||||
|
{
|
||||||
|
/* The device node of the main device. */
|
||||||
|
dev_t device;
|
||||||
|
|
||||||
|
/* The file descriptor of the format-modifier table. */
|
||||||
|
int fd;
|
||||||
|
|
||||||
|
/* The size of the format-modifier table. */
|
||||||
|
uint32_t format_table_size;
|
||||||
|
|
||||||
|
/* List of tranches. */
|
||||||
|
struct test_feedback_tranche *tranches;
|
||||||
|
|
||||||
|
/* Whether or not a tranche is being recorded. */
|
||||||
|
bool recording_tranche;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct format_modifier_pair
|
||||||
|
{
|
||||||
|
/* See the documentation of
|
||||||
|
zwp_linux_dmabuf_feedback_v1::format_table for more details. */
|
||||||
|
uint32_t format;
|
||||||
|
uint32_t padding;
|
||||||
|
uint64_t modifier;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* The display. */
|
||||||
|
static struct test_display *display;
|
||||||
|
|
||||||
|
/* The dmabuf interface. */
|
||||||
|
static struct zwp_linux_dmabuf_v1 *linux_dmabuf_v1;
|
||||||
|
|
||||||
|
/* Test interfaces. */
|
||||||
|
static struct test_interface test_interfaces[] =
|
||||||
|
{
|
||||||
|
{ "zwp_linux_dmabuf_v1", &linux_dmabuf_v1,
|
||||||
|
&zwp_linux_dmabuf_v1_interface, 4, },
|
||||||
|
};
|
||||||
|
|
||||||
|
/* The test surface window. */
|
||||||
|
static Window test_surface_window;
|
||||||
|
|
||||||
|
/* The test surface and Wayland surface. */
|
||||||
|
static struct test_surface *test_surface;
|
||||||
|
static struct wl_surface *wayland_surface;
|
||||||
|
|
||||||
|
/* The GBM device. */
|
||||||
|
static struct gbm_device *gbm_device;
|
||||||
|
|
||||||
|
/* The format-modifier table. */
|
||||||
|
static struct format_modifier_pair *modifier_table;
|
||||||
|
|
||||||
|
/* List of tranches. */
|
||||||
|
static struct test_feedback_tranche *feedback_tranches;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* Forward declarations. */
|
||||||
|
static void submit_frame_callback (struct wl_surface *, enum test_kind);
|
||||||
|
static void submit_surface_damage (struct wl_surface *, int, int, int, int);
|
||||||
|
static struct wl_buffer *create_rainbow_buffer (uint32_t, uint64_t,
|
||||||
|
uint32_t, uint32_t,
|
||||||
|
uint32_t);
|
||||||
|
static bool is_format_supported (uint32_t, uint64_t);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
verify_single_step (enum test_kind kind)
|
||||||
|
{
|
||||||
|
switch (kind)
|
||||||
|
{
|
||||||
|
case ARGB8888_KIND:
|
||||||
|
verify_image_data (display, test_surface_window,
|
||||||
|
"argb8888_implicit.dump");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ARGB8888_LINEAR_KIND:
|
||||||
|
verify_image_data (display, test_surface_window,
|
||||||
|
"argb8888_linear.dump");
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (kind == LAST_TEST)
|
||||||
|
test_complete ();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_single_step (enum test_kind kind)
|
||||||
|
{
|
||||||
|
struct wl_buffer *buffer;
|
||||||
|
|
||||||
|
test_log ("running test step: %s", test_names[kind]);
|
||||||
|
|
||||||
|
switch (kind)
|
||||||
|
{
|
||||||
|
case ARGB8888_KIND:
|
||||||
|
buffer = create_rainbow_buffer (GBM_FORMAT_ARGB8888,
|
||||||
|
DRM_FORMAT_MOD_INVALID,
|
||||||
|
0xffff0000,
|
||||||
|
0xff00ff00,
|
||||||
|
0xff0000ff);
|
||||||
|
|
||||||
|
if (!buffer)
|
||||||
|
report_test_failure ("failed to create ARGB8888 buffer");
|
||||||
|
|
||||||
|
wl_surface_attach (wayland_surface, buffer, 0, 0);
|
||||||
|
submit_surface_damage (wayland_surface, 0, 0,
|
||||||
|
INT_MAX, INT_MAX);
|
||||||
|
submit_frame_callback (wayland_surface, kind);
|
||||||
|
wl_surface_commit (wayland_surface);
|
||||||
|
wl_buffer_destroy (buffer);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ARGB8888_LINEAR_KIND:
|
||||||
|
|
||||||
|
if (!is_format_supported (DRM_FORMAT_ARGB8888,
|
||||||
|
DRM_FORMAT_MOD_LINEAR))
|
||||||
|
{
|
||||||
|
test_log ("skipping ARGB888 with linear modifier as"
|
||||||
|
" that is not supported");
|
||||||
|
test_complete ();
|
||||||
|
}
|
||||||
|
|
||||||
|
buffer = create_rainbow_buffer (GBM_FORMAT_ARGB8888,
|
||||||
|
DRM_FORMAT_MOD_LINEAR,
|
||||||
|
0xffff0000,
|
||||||
|
0xff00ff00,
|
||||||
|
0xff0000ff);
|
||||||
|
|
||||||
|
if (!buffer)
|
||||||
|
report_test_failure ("failed to create ARGB8888 buffer"
|
||||||
|
" with linear storage format");
|
||||||
|
|
||||||
|
wl_surface_attach (wayland_surface, buffer, 0, 0);
|
||||||
|
submit_surface_damage (wayland_surface, 0, 0,
|
||||||
|
INT_MAX, INT_MAX);
|
||||||
|
submit_frame_callback (wayland_surface, kind);
|
||||||
|
wl_surface_commit (wayland_surface);
|
||||||
|
wl_buffer_destroy (buffer);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_next_step (enum test_kind kind)
|
||||||
|
{
|
||||||
|
switch (kind)
|
||||||
|
{
|
||||||
|
case ARGB8888_KIND:
|
||||||
|
test_single_step (ARGB8888_LINEAR_KIND);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
handle_test_surface_mapped (void *data, struct test_surface *surface,
|
||||||
|
uint32_t xid, const char *display_string)
|
||||||
|
{
|
||||||
|
/* Sleep for 1 second to ensure that the window is exposed and
|
||||||
|
redirected. */
|
||||||
|
sleep (1);
|
||||||
|
|
||||||
|
/* Start the test. */
|
||||||
|
test_surface_window = xid;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct test_surface_listener test_surface_listener =
|
||||||
|
{
|
||||||
|
handle_test_surface_mapped,
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
handle_wl_callback_done (void *data, struct wl_callback *callback,
|
||||||
|
uint32_t callback_data)
|
||||||
|
{
|
||||||
|
enum test_kind kind;
|
||||||
|
|
||||||
|
/* kind is not a pointer. It is an enum test_kind stuffed into a
|
||||||
|
pointer. */
|
||||||
|
kind = (intptr_t) data;
|
||||||
|
|
||||||
|
wl_callback_destroy (callback);
|
||||||
|
verify_single_step (kind);
|
||||||
|
|
||||||
|
/* Now run the next test in this sequence. */
|
||||||
|
test_next_step (kind);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct wl_callback_listener wl_callback_listener =
|
||||||
|
{
|
||||||
|
handle_wl_callback_done,
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
submit_frame_callback (struct wl_surface *surface, enum test_kind kind)
|
||||||
|
{
|
||||||
|
struct wl_callback *callback;
|
||||||
|
|
||||||
|
callback = wl_surface_frame (surface);
|
||||||
|
wl_callback_add_listener (callback, &wl_callback_listener,
|
||||||
|
(void *) (intptr_t) kind);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
submit_surface_damage (struct wl_surface *surface, int x, int y, int width,
|
||||||
|
int height)
|
||||||
|
{
|
||||||
|
test_log ("damaging surface by %d, %d, %d, %d", x, y, width,
|
||||||
|
height);
|
||||||
|
|
||||||
|
wl_surface_damage (surface, x, y, width, height);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
handle_feedback_done (void *data,
|
||||||
|
struct zwp_linux_dmabuf_feedback_v1 *feedback)
|
||||||
|
{
|
||||||
|
struct test_feedback_data *test_data;
|
||||||
|
|
||||||
|
test_data = data;
|
||||||
|
|
||||||
|
if (test_data->recording_tranche)
|
||||||
|
report_test_failure ("done received while recording tranche");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
handle_feedback_format_table (void *data,
|
||||||
|
struct zwp_linux_dmabuf_feedback_v1 *feedback,
|
||||||
|
int32_t fd, uint32_t size)
|
||||||
|
{
|
||||||
|
struct test_feedback_data *test_data;
|
||||||
|
|
||||||
|
test_data = data;
|
||||||
|
|
||||||
|
test_data->fd = fd;
|
||||||
|
test_data->format_table_size = size;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
handle_feedback_main_device (void *data,
|
||||||
|
struct zwp_linux_dmabuf_feedback_v1 *feedback,
|
||||||
|
struct wl_array *device)
|
||||||
|
{
|
||||||
|
struct test_feedback_data *test_data;
|
||||||
|
|
||||||
|
test_data = data;
|
||||||
|
|
||||||
|
if (device->size != sizeof test_data->device)
|
||||||
|
report_test_failure ("got incorrect array size for dev_t");
|
||||||
|
|
||||||
|
memcpy (&test_data->device, device->data, device->size);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
handle_feedback_tranche_done (void *data,
|
||||||
|
struct zwp_linux_dmabuf_feedback_v1 *feedback)
|
||||||
|
{
|
||||||
|
struct test_feedback_data *test_data;
|
||||||
|
|
||||||
|
test_data = data;
|
||||||
|
|
||||||
|
if (!test_data->recording_tranche)
|
||||||
|
report_test_failure ("tranche_done received but not recording tranche");
|
||||||
|
|
||||||
|
test_data->recording_tranche = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
handle_feedback_tranche_target_device (void *data,
|
||||||
|
struct zwp_linux_dmabuf_feedback_v1 *feedback,
|
||||||
|
struct wl_array *device)
|
||||||
|
{
|
||||||
|
/* Nothing to do here. */
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
handle_feedback_tranche_formats (void *data,
|
||||||
|
struct zwp_linux_dmabuf_feedback_v1 *feedback,
|
||||||
|
struct wl_array *indices)
|
||||||
|
{
|
||||||
|
struct test_feedback_data *test_data;
|
||||||
|
struct test_feedback_tranche *tranche;
|
||||||
|
|
||||||
|
test_data = data;
|
||||||
|
|
||||||
|
if (!test_data->recording_tranche)
|
||||||
|
{
|
||||||
|
/* Start recording a new tranche. */
|
||||||
|
tranche = calloc (1, sizeof *tranche);
|
||||||
|
|
||||||
|
if (!tranche)
|
||||||
|
report_test_failure ("failed to allocate tranche");
|
||||||
|
|
||||||
|
tranche->next = test_data->tranches;
|
||||||
|
test_data->tranches = tranche;
|
||||||
|
test_data->recording_tranche = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
tranche = test_data->tranches;
|
||||||
|
|
||||||
|
if (tranche->indices)
|
||||||
|
free (tranche->indices);
|
||||||
|
|
||||||
|
if (indices->size % sizeof (uint16_t))
|
||||||
|
report_test_failure ("invalid tranche size: %zu", indices->size);
|
||||||
|
|
||||||
|
#ifdef __GNUC__
|
||||||
|
#pragma GCC diagnostic push
|
||||||
|
#pragma GCC diagnostic ignored "-Wanalyzer-malloc-leak"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
tranche->indices = malloc (indices->size);
|
||||||
|
tranche->n_indices = indices->size / sizeof (uint16_t);
|
||||||
|
|
||||||
|
if (!tranche->indices)
|
||||||
|
report_test_failure ("failed to allocate tranche indices");
|
||||||
|
|
||||||
|
memcpy (tranche->indices, indices->data, indices->size);
|
||||||
|
|
||||||
|
#ifdef __GNUC__
|
||||||
|
#pragma GCC diagnostic pop
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
handle_feedback_tranche_flags (void *data,
|
||||||
|
struct zwp_linux_dmabuf_feedback_v1 *feedback,
|
||||||
|
uint32_t flags)
|
||||||
|
{
|
||||||
|
/* Nothing to do here. */
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct zwp_linux_dmabuf_feedback_v1_listener feedback_listener =
|
||||||
|
{
|
||||||
|
handle_feedback_done,
|
||||||
|
handle_feedback_format_table,
|
||||||
|
handle_feedback_main_device,
|
||||||
|
handle_feedback_tranche_done,
|
||||||
|
handle_feedback_tranche_target_device,
|
||||||
|
handle_feedback_tranche_formats,
|
||||||
|
handle_feedback_tranche_flags,
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static int
|
||||||
|
open_device (dev_t device)
|
||||||
|
{
|
||||||
|
drmDevicePtr device_ptr;
|
||||||
|
int fd;
|
||||||
|
|
||||||
|
if (drmGetDeviceFromDevId (device, 0, &device_ptr) < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
fd = -1;
|
||||||
|
|
||||||
|
if (device_ptr->available_nodes & (1 << DRM_NODE_RENDER))
|
||||||
|
/* Open the render node if available. */
|
||||||
|
fd = open (device_ptr->nodes[DRM_NODE_RENDER], O_RDWR);
|
||||||
|
|
||||||
|
/* Free the device. */
|
||||||
|
drmFreeDevice (&device_ptr);
|
||||||
|
|
||||||
|
/* Return the file descriptor. */
|
||||||
|
return fd;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
open_surface (void)
|
||||||
|
{
|
||||||
|
struct zwp_linux_dmabuf_feedback_v1 *feedback;
|
||||||
|
struct test_feedback_data data;
|
||||||
|
struct test_feedback_tranche *tranche;
|
||||||
|
int fd, i;
|
||||||
|
|
||||||
|
feedback
|
||||||
|
= zwp_linux_dmabuf_v1_get_default_feedback (linux_dmabuf_v1);
|
||||||
|
|
||||||
|
if (!feedback)
|
||||||
|
report_test_failure ("failed to create dmabuf feedback");
|
||||||
|
|
||||||
|
memset (&data, 0, sizeof data);
|
||||||
|
data.fd = -1;
|
||||||
|
|
||||||
|
zwp_linux_dmabuf_feedback_v1_add_listener (feedback, &feedback_listener,
|
||||||
|
&data);
|
||||||
|
wl_display_roundtrip (display->display);
|
||||||
|
|
||||||
|
/* Now verify that everything required arrived. */
|
||||||
|
if (!data.device || data.fd < 0
|
||||||
|
|| (data.format_table_size
|
||||||
|
% sizeof (struct format_modifier_pair))
|
||||||
|
|| !data.tranches)
|
||||||
|
report_test_failure ("received invalid parameters from feedback");
|
||||||
|
|
||||||
|
/* Open the provided node. */
|
||||||
|
fd = open_device (data.device);
|
||||||
|
|
||||||
|
if (fd < 0)
|
||||||
|
report_test_failure ("failed to open device");
|
||||||
|
|
||||||
|
gbm_device = gbm_create_device (fd);
|
||||||
|
|
||||||
|
if (!gbm_device)
|
||||||
|
report_test_failure ("failed to open device");
|
||||||
|
|
||||||
|
/* Now try to map the format-modifier table and verify the validity
|
||||||
|
of each tranche. */
|
||||||
|
modifier_table = mmap (NULL, data.format_table_size, PROT_READ,
|
||||||
|
MAP_PRIVATE, data.fd, 0);
|
||||||
|
|
||||||
|
if (modifier_table == (void *) -1)
|
||||||
|
report_test_failure ("failed to map modifier table");
|
||||||
|
|
||||||
|
for (tranche = data.tranches; tranche; tranche = tranche->next)
|
||||||
|
{
|
||||||
|
for (i = 0; i < tranche->n_indices; ++i)
|
||||||
|
{
|
||||||
|
if (tranche->indices[i]
|
||||||
|
>= data.format_table_size / sizeof *modifier_table)
|
||||||
|
report_test_failure ("tranche index %"PRIu16" extends outside"
|
||||||
|
" bounds of format modifier table",
|
||||||
|
tranche->indices[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
zwp_linux_dmabuf_feedback_v1_destroy (feedback);
|
||||||
|
feedback_tranches = data.tranches;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
is_format_supported (uint32_t format, uint64_t modifier)
|
||||||
|
{
|
||||||
|
struct test_feedback_tranche *tranche;
|
||||||
|
int i;
|
||||||
|
struct format_modifier_pair pair;
|
||||||
|
|
||||||
|
/* Loop through each tranche, looking for a matching entry in the
|
||||||
|
targets table. */
|
||||||
|
for (tranche = feedback_tranches; tranche; tranche = tranche->next)
|
||||||
|
{
|
||||||
|
for (i = 0; i < tranche->n_indices; ++i)
|
||||||
|
{
|
||||||
|
pair = modifier_table[i];
|
||||||
|
|
||||||
|
if (pair.format == format
|
||||||
|
&& pair.modifier == modifier)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
handle_params_created (void *data,
|
||||||
|
struct zwp_linux_buffer_params_v1 *params,
|
||||||
|
struct wl_buffer *buffer)
|
||||||
|
{
|
||||||
|
struct test_params_data *params_data;
|
||||||
|
|
||||||
|
params_data = data;
|
||||||
|
params_data->complete = true;
|
||||||
|
params_data->buffer = buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
handle_params_failed (void *data,
|
||||||
|
struct zwp_linux_buffer_params_v1 *params)
|
||||||
|
{
|
||||||
|
struct test_params_data *params_data;
|
||||||
|
|
||||||
|
params_data = data;
|
||||||
|
|
||||||
|
if (params_data->buffer)
|
||||||
|
report_test_failure ("buffer set but failed sent!");
|
||||||
|
|
||||||
|
params_data->complete = false;
|
||||||
|
params_data->buffer = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct zwp_linux_buffer_params_v1_listener params_listener =
|
||||||
|
{
|
||||||
|
handle_params_created,
|
||||||
|
handle_params_failed,
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* Create a 200x200 buffer in some 32 bpp format. Fill it with three
|
||||||
|
colors: red, green, and blue. */
|
||||||
|
|
||||||
|
static struct wl_buffer *
|
||||||
|
create_rainbow_buffer (uint32_t format, uint64_t modifier,
|
||||||
|
uint32_t red_pixel, uint32_t green_pixel,
|
||||||
|
uint32_t blue_pixel)
|
||||||
|
{
|
||||||
|
struct gbm_bo *buffer_object;
|
||||||
|
void *map_data;
|
||||||
|
char *buffer_data, *line;
|
||||||
|
uint32_t stride;
|
||||||
|
int i, fd;
|
||||||
|
struct zwp_linux_buffer_params_v1 *params;
|
||||||
|
struct test_params_data data;
|
||||||
|
|
||||||
|
/* map_data must be NULL when it is first given to gbm_bo_map. */
|
||||||
|
map_data = NULL;
|
||||||
|
|
||||||
|
if (!is_format_supported (format, modifier))
|
||||||
|
report_test_failure ("the specified format %8"PRIx32" with modifier"
|
||||||
|
" 0x%16"PRIx64" is not supported",
|
||||||
|
format, modifier);
|
||||||
|
|
||||||
|
if (modifier != DRM_FORMAT_MOD_INVALID)
|
||||||
|
buffer_object
|
||||||
|
= gbm_bo_create_with_modifiers2 (gbm_device, 500, 500, format,
|
||||||
|
&modifier, 1,
|
||||||
|
GBM_BO_USE_RENDERING);
|
||||||
|
else
|
||||||
|
buffer_object = gbm_bo_create (gbm_device, 500, 500, format,
|
||||||
|
GBM_BO_USE_RENDERING);
|
||||||
|
|
||||||
|
if (!buffer_object)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
buffer_data = gbm_bo_map (buffer_object, 0, 0, 500, 500,
|
||||||
|
GBM_BO_TRANSFER_WRITE, &stride,
|
||||||
|
&map_data);
|
||||||
|
|
||||||
|
if (!buffer_data)
|
||||||
|
goto error_1;
|
||||||
|
|
||||||
|
line = malloc (stride);
|
||||||
|
|
||||||
|
if (!line)
|
||||||
|
goto error_2;
|
||||||
|
|
||||||
|
/* Fill the line with the red pixel, and then fill the first 166
|
||||||
|
rows with it. buffer_data may not be suitably aligned, so use
|
||||||
|
memcpy. */
|
||||||
|
for (i = 0; i < 500; ++i)
|
||||||
|
memcpy (line + i * 4, &red_pixel, sizeof red_pixel);
|
||||||
|
|
||||||
|
for (i = 0; i < 166; ++i)
|
||||||
|
memcpy (buffer_data + stride * i, line, 4 * 500);
|
||||||
|
|
||||||
|
/* Repeat with the green pixel. */
|
||||||
|
for (i = 0; i < 500; ++i)
|
||||||
|
memcpy (line + i * 4, &green_pixel, sizeof green_pixel);
|
||||||
|
|
||||||
|
for (i = 166; i < 332; ++i)
|
||||||
|
memcpy (buffer_data + stride * i, line, 4 * 500);
|
||||||
|
|
||||||
|
/* Finally with the blue pixel. */
|
||||||
|
for (i = 0; i < 500; ++i)
|
||||||
|
memcpy (line + i * 4, &blue_pixel, sizeof blue_pixel);
|
||||||
|
|
||||||
|
for (i = 332; i < 500; ++i)
|
||||||
|
memcpy (buffer_data + stride * i, line, 4 * 500);
|
||||||
|
|
||||||
|
free (line);
|
||||||
|
|
||||||
|
/* Now, export the buffer. */
|
||||||
|
fd = gbm_bo_get_fd (buffer_object);
|
||||||
|
|
||||||
|
if (fd < 1)
|
||||||
|
goto error_2;
|
||||||
|
|
||||||
|
params = zwp_linux_dmabuf_v1_create_params (linux_dmabuf_v1);
|
||||||
|
|
||||||
|
if (!params)
|
||||||
|
goto error_3;
|
||||||
|
|
||||||
|
zwp_linux_buffer_params_v1_add (params, fd, 0,
|
||||||
|
gbm_bo_get_offset (buffer_object, 0),
|
||||||
|
gbm_bo_get_stride (buffer_object),
|
||||||
|
modifier >> 32,
|
||||||
|
modifier & 0xffffffff);
|
||||||
|
zwp_linux_buffer_params_v1_create (params, 500, 500, format, 0);
|
||||||
|
|
||||||
|
/* Now, wait for either success or failure. */
|
||||||
|
zwp_linux_buffer_params_v1_add_listener (params, ¶ms_listener,
|
||||||
|
&data);
|
||||||
|
data.complete = false;
|
||||||
|
data.buffer = NULL;
|
||||||
|
|
||||||
|
while (!data.complete)
|
||||||
|
{
|
||||||
|
if (wl_display_dispatch (display->display) == -1)
|
||||||
|
die ("wl_display_dispatch");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!data.buffer)
|
||||||
|
goto error_4;
|
||||||
|
|
||||||
|
/* Otherwise, the buffer has been created. Return it now. */
|
||||||
|
|
||||||
|
zwp_linux_buffer_params_v1_destroy (params);
|
||||||
|
close (fd);
|
||||||
|
gbm_bo_unmap (buffer_object, map_data);
|
||||||
|
gbm_bo_destroy (buffer_object);
|
||||||
|
|
||||||
|
return data.buffer;
|
||||||
|
|
||||||
|
error_4:
|
||||||
|
zwp_linux_buffer_params_v1_destroy (params);
|
||||||
|
error_3:
|
||||||
|
close (fd);
|
||||||
|
error_2:
|
||||||
|
gbm_bo_unmap (buffer_object, map_data);
|
||||||
|
error_1:
|
||||||
|
gbm_bo_destroy (buffer_object);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
run_test (void)
|
||||||
|
{
|
||||||
|
if (!make_test_surface (display, &wayland_surface,
|
||||||
|
&test_surface))
|
||||||
|
report_test_failure ("failed to create test surface");
|
||||||
|
|
||||||
|
/* Open the test surface. */
|
||||||
|
open_surface ();
|
||||||
|
|
||||||
|
test_surface_add_listener (test_surface, &test_surface_listener,
|
||||||
|
NULL);
|
||||||
|
test_single_step (ARGB8888_KIND);
|
||||||
|
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
if (wl_display_dispatch (display->display) == -1)
|
||||||
|
die ("wl_display_dispatch");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
main (void)
|
||||||
|
{
|
||||||
|
test_init ();
|
||||||
|
display = open_test_display (test_interfaces,
|
||||||
|
ARRAYELTS (test_interfaces));
|
||||||
|
|
||||||
|
if (!display)
|
||||||
|
report_test_failure ("failed to open display");
|
||||||
|
|
||||||
|
run_test ();
|
||||||
|
}
|
Loading…
Add table
Reference in a new issue