mirror of
https://gitlab.freedesktop.org/wayland/weston
synced 2024-09-06 18:05:39 +00:00
![Pekka Paalanen](/assets/img/avatar_default.png)
We are growing more tests that need to handle buffers, both just images and wl_buffers. Particularly the screenshooting facility needs these. Currently everything is in struct surface, which contains more than we need. It is a bit messy. Create a new struct buffer to encapsulate the image representation, the wl_buffer, and enough information to tear it all down (munmap) so we don't have to leak everything. Some tests might start doing things in loops, and leaking would accumulate. Instead of inventing our own image representation, use pixman_image_t. It is a well-tested library worth using, and we already rely on it in other places. This makes the tests depend on Pixman, which requires the fix for building buffer-count, which would otherwise not find pixman.h. The new create_shm_buffer_a8r8g8b8() creates an image with an explicit format, and pixman_image_t keeps track of it. And stride and size and data. This implementation is still a little hacky due to calling create_shm_buffer(). A very new thing is buffer_destroy(). Previously we didn't really free any buffers. It is not a problem when the process will exit soon anyway, but it may become a problem if tests start iterating things. Manual memset() on a image is converted to a pixman action, just to show how to do it properly with pixman. Stride and pixel format assumptions still linger all around, but those are for another patch. Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.co.uk> Reviewed-by: Daniel Stone <daniels@collabora.com>
554 lines
18 KiB
C
554 lines
18 KiB
C
/*
|
|
* Copyright © 2014, 2016 Collabora, Ltd.
|
|
*
|
|
* 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, sublicense, 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
|
|
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
|
* 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 "config.h"
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <assert.h>
|
|
#include <time.h>
|
|
|
|
#include "shared/helpers.h"
|
|
#include "shared/xalloc.h"
|
|
#include "weston-test-client-helper.h"
|
|
#include "viewporter-client-protocol.h"
|
|
|
|
static struct wp_viewporter *
|
|
get_viewporter(struct client *client)
|
|
{
|
|
struct global *g;
|
|
struct global *global_wpr = NULL;
|
|
static struct wp_viewporter *wpr;
|
|
|
|
if (wpr)
|
|
return wpr;
|
|
|
|
wl_list_for_each(g, &client->global_list, link) {
|
|
if (strcmp(g->interface, wp_viewporter_interface.name))
|
|
continue;
|
|
|
|
if (global_wpr)
|
|
assert(0 && "multiple wp_viewporter objects");
|
|
|
|
global_wpr = g;
|
|
}
|
|
|
|
assert(global_wpr && "no wp_viewporter found");
|
|
|
|
assert(global_wpr->version == 1);
|
|
|
|
wpr = wl_registry_bind(client->wl_registry, global_wpr->name,
|
|
&wp_viewporter_interface, 1);
|
|
assert(wpr);
|
|
|
|
return wpr;
|
|
}
|
|
|
|
static struct wp_viewport *
|
|
create_viewport(struct client *client)
|
|
{
|
|
struct wp_viewporter *viewporter;
|
|
struct wp_viewport *viewport;
|
|
|
|
viewporter = get_viewporter(client);
|
|
viewport = wp_viewporter_get_viewport(viewporter,
|
|
client->surface->wl_surface);
|
|
assert(viewport);
|
|
|
|
return viewport;
|
|
}
|
|
|
|
static void
|
|
set_source(struct wp_viewport *vp, int x, int y, int w, int h)
|
|
{
|
|
wp_viewport_set_source(vp, wl_fixed_from_int(x), wl_fixed_from_int(y),
|
|
wl_fixed_from_int(w), wl_fixed_from_int(h));
|
|
}
|
|
|
|
TEST(test_viewporter_double_create)
|
|
{
|
|
struct wp_viewporter *viewporter;
|
|
struct client *client;
|
|
|
|
client = create_client_and_test_surface(100, 50, 123, 77);
|
|
|
|
viewporter = get_viewporter(client);
|
|
wp_viewporter_get_viewport(viewporter, client->surface->wl_surface);
|
|
wp_viewporter_get_viewport(viewporter, client->surface->wl_surface);
|
|
|
|
expect_protocol_error(client, &wp_viewporter_interface,
|
|
WP_VIEWPORTER_ERROR_VIEWPORT_EXISTS);
|
|
}
|
|
|
|
struct bad_source_rect_args {
|
|
int x, y, w, h;
|
|
};
|
|
|
|
static const struct bad_source_rect_args bad_source_rect_args[] = {
|
|
{ -5, 0, 20, 10 },
|
|
{ 0, -5, 20, 10 },
|
|
{ 5, 6, 0, 10 },
|
|
{ 5, 6, 20, 0 },
|
|
{ 5, 6, -20, 10 },
|
|
{ 5, 6, 20, -10 },
|
|
{ -1, -1, 20, 10 },
|
|
{ 5, 6, -1, -1 },
|
|
};
|
|
|
|
TEST_P(test_viewporter_bad_source_rect, bad_source_rect_args)
|
|
{
|
|
const struct bad_source_rect_args *args = data;
|
|
struct client *client;
|
|
struct wp_viewport *vp;
|
|
|
|
client = create_client_and_test_surface(100, 50, 123, 77);
|
|
|
|
vp = create_viewport(client);
|
|
|
|
fprintf(stderr, "wp_viewport.set_source x=%d, y=%d, w=%d, h=%d\n",
|
|
args->x, args->y, args->w, args->h);
|
|
set_source(vp, args->x, args->y, args->w, args->h);
|
|
|
|
expect_protocol_error(client, &wp_viewport_interface,
|
|
WP_VIEWPORT_ERROR_BAD_VALUE);
|
|
}
|
|
|
|
TEST(test_viewporter_unset_source_rect)
|
|
{
|
|
struct client *client;
|
|
struct wp_viewport *vp;
|
|
|
|
client = create_client_and_test_surface(100, 50, 123, 77);
|
|
|
|
vp = create_viewport(client);
|
|
set_source(vp, -1, -1, -1, -1);
|
|
wl_surface_commit(client->surface->wl_surface);
|
|
|
|
client_roundtrip(client);
|
|
}
|
|
|
|
struct bad_destination_args {
|
|
int w, h;
|
|
};
|
|
|
|
static const struct bad_destination_args bad_destination_args[] = {
|
|
{ 0, 10 },
|
|
{ 20, 0 },
|
|
{ -20, 10 },
|
|
{ -1, 10 },
|
|
{ 20, -10 },
|
|
{ 20, -1 },
|
|
};
|
|
|
|
TEST_P(test_viewporter_bad_destination_size, bad_destination_args)
|
|
{
|
|
const struct bad_destination_args *args = data;
|
|
struct client *client;
|
|
struct wp_viewport *vp;
|
|
|
|
client = create_client_and_test_surface(100, 50, 123, 77);
|
|
|
|
vp = create_viewport(client);
|
|
|
|
fprintf(stderr, "wp_viewport.set_destination w=%d, h=%d\n",
|
|
args->w, args->h);
|
|
wp_viewport_set_destination(vp, args->w, args->h);
|
|
|
|
expect_protocol_error(client, &wp_viewport_interface,
|
|
WP_VIEWPORT_ERROR_BAD_VALUE);
|
|
}
|
|
|
|
TEST(test_viewporter_unset_destination_size)
|
|
{
|
|
struct client *client;
|
|
struct wp_viewport *vp;
|
|
|
|
client = create_client_and_test_surface(100, 50, 123, 77);
|
|
|
|
vp = create_viewport(client);
|
|
wp_viewport_set_destination(vp, -1, -1);
|
|
wl_surface_commit(client->surface->wl_surface);
|
|
|
|
client_roundtrip(client);
|
|
}
|
|
|
|
struct nonint_destination_args {
|
|
wl_fixed_t w, h;
|
|
};
|
|
|
|
static const struct nonint_destination_args nonint_destination_args[] = {
|
|
#define F(i,f) ((i) * 256 + (f))
|
|
{ F(20, 0), F(10, 1) },
|
|
{ F(20, 0), F(10, -1) },
|
|
{ F(20, 1), F(10, 0) },
|
|
{ F(20, -1), F(10, 0) },
|
|
{ F(20, 128), F(10, 128) },
|
|
#undef F
|
|
};
|
|
|
|
TEST_P(test_viewporter_non_integer_destination_size, nonint_destination_args)
|
|
{
|
|
const struct nonint_destination_args *args = data;
|
|
struct client *client;
|
|
struct wp_viewport *vp;
|
|
|
|
client = create_client_and_test_surface(100, 50, 123, 77);
|
|
|
|
vp = create_viewport(client);
|
|
|
|
fprintf(stderr, "non-integer size w=%f, h=%f\n",
|
|
wl_fixed_to_double(args->w), wl_fixed_to_double(args->h));
|
|
wp_viewport_set_source(vp, 5, 6, args->w, args->h);
|
|
wp_viewport_set_destination(vp, -1, -1);
|
|
wl_surface_commit(client->surface->wl_surface);
|
|
|
|
expect_protocol_error(client, &wp_viewport_interface,
|
|
WP_VIEWPORT_ERROR_BAD_SIZE);
|
|
}
|
|
|
|
struct source_buffer_args {
|
|
wl_fixed_t x, y;
|
|
wl_fixed_t w, h;
|
|
int buffer_scale;
|
|
enum wl_output_transform buffer_transform;
|
|
};
|
|
|
|
static int
|
|
get_surface_width(struct surface *surface,
|
|
int buffer_scale,
|
|
enum wl_output_transform buffer_transform)
|
|
{
|
|
switch (buffer_transform) {
|
|
case WL_OUTPUT_TRANSFORM_NORMAL:
|
|
case WL_OUTPUT_TRANSFORM_180:
|
|
case WL_OUTPUT_TRANSFORM_FLIPPED:
|
|
case WL_OUTPUT_TRANSFORM_FLIPPED_180:
|
|
return surface->width / buffer_scale;
|
|
case WL_OUTPUT_TRANSFORM_90:
|
|
case WL_OUTPUT_TRANSFORM_270:
|
|
case WL_OUTPUT_TRANSFORM_FLIPPED_90:
|
|
case WL_OUTPUT_TRANSFORM_FLIPPED_270:
|
|
return surface->height / buffer_scale;
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
|
|
static int
|
|
get_surface_height(struct surface *surface,
|
|
int buffer_scale,
|
|
enum wl_output_transform buffer_transform)
|
|
{
|
|
switch (buffer_transform) {
|
|
case WL_OUTPUT_TRANSFORM_NORMAL:
|
|
case WL_OUTPUT_TRANSFORM_180:
|
|
case WL_OUTPUT_TRANSFORM_FLIPPED:
|
|
case WL_OUTPUT_TRANSFORM_FLIPPED_180:
|
|
return surface->height / buffer_scale;
|
|
case WL_OUTPUT_TRANSFORM_90:
|
|
case WL_OUTPUT_TRANSFORM_270:
|
|
case WL_OUTPUT_TRANSFORM_FLIPPED_90:
|
|
case WL_OUTPUT_TRANSFORM_FLIPPED_270:
|
|
return surface->width / buffer_scale;
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
|
|
static void
|
|
setup_source_vs_buffer(struct client *client,
|
|
const struct source_buffer_args *args)
|
|
{
|
|
struct wl_surface *surf;
|
|
struct wp_viewport *vp;
|
|
|
|
surf = client->surface->wl_surface;
|
|
vp = create_viewport(client);
|
|
|
|
fprintf(stderr, "surface %dx%d\n",
|
|
get_surface_width(client->surface,
|
|
args->buffer_scale, args->buffer_transform),
|
|
get_surface_height(client->surface,
|
|
args->buffer_scale, args->buffer_transform));
|
|
fprintf(stderr, "source x=%f, y=%f, w=%f, h=%f; "
|
|
"buffer scale=%d, transform=%d\n",
|
|
wl_fixed_to_double(args->x), wl_fixed_to_double(args->y),
|
|
wl_fixed_to_double(args->w), wl_fixed_to_double(args->h),
|
|
args->buffer_scale, args->buffer_transform);
|
|
|
|
wl_surface_set_buffer_scale(surf, args->buffer_scale);
|
|
wl_surface_set_buffer_transform(surf, args->buffer_transform);
|
|
wl_surface_attach(surf, client->surface->buffer->proxy, 0, 0);
|
|
wp_viewport_set_source(vp, args->x, args->y, args->w, args->h);
|
|
wp_viewport_set_destination(vp, 99, 99);
|
|
wl_surface_commit(surf);
|
|
}
|
|
|
|
/* buffer dimensions */
|
|
#define WIN_W 124
|
|
#define WIN_H 78
|
|
|
|
/* source rect base size */
|
|
#define SRC_W 20
|
|
#define SRC_H 10
|
|
|
|
/* margin */
|
|
#define MRG 10
|
|
/* epsilon of wl_fixed_t */
|
|
#define EPS 1
|
|
|
|
TEST(test_viewporter_source_buffer_params)
|
|
{
|
|
const int max_scale = 2;
|
|
|
|
/* buffer_scale requirement */
|
|
assert(WIN_W % max_scale == 0);
|
|
assert(WIN_H % max_scale == 0);
|
|
|
|
/* source rect must fit inside regardless of scale and transform */
|
|
assert(SRC_W < WIN_W / max_scale);
|
|
assert(SRC_H < WIN_H / max_scale);
|
|
assert(SRC_W < WIN_H / max_scale);
|
|
assert(SRC_H < WIN_W / max_scale);
|
|
|
|
/* If buffer scale was ignored, source rect should be inside instead */
|
|
assert(WIN_W / max_scale + SRC_W + MRG < WIN_W);
|
|
assert(WIN_H / max_scale + SRC_H + MRG < WIN_H);
|
|
assert(WIN_W / max_scale + SRC_H + MRG < WIN_W);
|
|
assert(WIN_H / max_scale + SRC_W + MRG < WIN_H);
|
|
}
|
|
|
|
static const struct source_buffer_args bad_source_buffer_args[] = {
|
|
#define F(i) ((i) * 256)
|
|
|
|
/* Flush right-top, but epsilon too far right. */
|
|
{ F(WIN_W - SRC_W) + EPS, F(0), F(SRC_W), F(SRC_H), 1, WL_OUTPUT_TRANSFORM_NORMAL },
|
|
{ F(WIN_W - SRC_W), F(0), F(SRC_W) + EPS, F(SRC_H), 1, WL_OUTPUT_TRANSFORM_NORMAL },
|
|
/* Flush left-bottom, but epsilon too far down. */
|
|
{ F(0), F(WIN_H - SRC_H) + EPS, F(SRC_W), F(SRC_H), 1, WL_OUTPUT_TRANSFORM_NORMAL },
|
|
{ F(0), F(WIN_H - SRC_H), F(SRC_W), F(SRC_H) + EPS, 1, WL_OUTPUT_TRANSFORM_NORMAL },
|
|
/* Completely outside on the right. */
|
|
{ F(WIN_W + MRG), F(0), F(SRC_W), F(SRC_H), 1, WL_OUTPUT_TRANSFORM_NORMAL },
|
|
/* Competely outside on the bottom. */
|
|
{ F(0), F(WIN_H + MRG), F(SRC_W), F(SRC_H), 1, WL_OUTPUT_TRANSFORM_NORMAL },
|
|
|
|
/*
|
|
* buffer_scale=2, so the surface size will be halved.
|
|
* If buffer_scale was not taken into account, these would all be inside.
|
|
* These are the same as above, but adapted to buffer_scale=2.
|
|
*/
|
|
{ F(WIN_W / 2 - SRC_W) + EPS, F(0), F(SRC_W), F(SRC_H), 2, WL_OUTPUT_TRANSFORM_NORMAL },
|
|
{ F(WIN_W / 2 - SRC_W), F(0), F(SRC_W) + EPS, F(SRC_H), 2, WL_OUTPUT_TRANSFORM_NORMAL },
|
|
|
|
{ F(0), F(WIN_H / 2 - SRC_H) + EPS, F(SRC_W), F(SRC_H), 2, WL_OUTPUT_TRANSFORM_NORMAL },
|
|
{ F(0), F(WIN_H / 2 - SRC_H), F(SRC_W), F(SRC_H) + EPS, 2, WL_OUTPUT_TRANSFORM_NORMAL },
|
|
|
|
{ F(WIN_W / 2 + MRG), F(0), F(SRC_W), F(SRC_H), 2, WL_OUTPUT_TRANSFORM_NORMAL },
|
|
|
|
{ F(0), F(WIN_H / 2 + MRG), F(SRC_W), F(SRC_H), 2, WL_OUTPUT_TRANSFORM_NORMAL },
|
|
|
|
/* Exceeding bottom-right corner by epsilon: */
|
|
/* non-dimension-swapping transforms */
|
|
{ F(WIN_W - SRC_W), F(WIN_H - SRC_H), F(SRC_W), F(SRC_H) + EPS, 1, WL_OUTPUT_TRANSFORM_FLIPPED_180 },
|
|
{ F(WIN_W - SRC_W), F(WIN_H - SRC_H) + EPS, F(SRC_W), F(SRC_H), 1, WL_OUTPUT_TRANSFORM_FLIPPED },
|
|
{ F(WIN_W - SRC_W), F(WIN_H - SRC_H), F(SRC_W) + EPS, F(SRC_H), 1, WL_OUTPUT_TRANSFORM_180 },
|
|
|
|
/* dimension-swapping transforms */
|
|
{ F(WIN_H - SRC_W) + EPS, F(WIN_W - SRC_H), F(SRC_W), F(SRC_H), 1, WL_OUTPUT_TRANSFORM_90 },
|
|
{ F(WIN_H - SRC_W), F(WIN_W - SRC_H) + EPS, F(SRC_W), F(SRC_H), 1, WL_OUTPUT_TRANSFORM_270 },
|
|
{ F(WIN_H - SRC_W), F(WIN_W - SRC_H), F(SRC_W) + EPS, F(SRC_H), 1, WL_OUTPUT_TRANSFORM_FLIPPED_90 },
|
|
{ F(WIN_H - SRC_W), F(WIN_W - SRC_H), F(SRC_W), F(SRC_H) + EPS, 1, WL_OUTPUT_TRANSFORM_FLIPPED_270 },
|
|
|
|
/* non-dimension-swapping transforms, buffer_scale=2 */
|
|
{ F(WIN_W / 2 - SRC_W), F(WIN_H / 2 - SRC_H) + EPS, F(SRC_W), F(SRC_H), 2, WL_OUTPUT_TRANSFORM_FLIPPED_180 },
|
|
{ F(WIN_W / 2 - SRC_W), F(WIN_H / 2 - SRC_H), F(SRC_W) + EPS, F(SRC_H), 2, WL_OUTPUT_TRANSFORM_FLIPPED },
|
|
{ F(WIN_W / 2 - SRC_W), F(WIN_H / 2 - SRC_H), F(SRC_W), F(SRC_H) + EPS, 2, WL_OUTPUT_TRANSFORM_180 },
|
|
|
|
/* dimension-swapping transforms, buffer_scale=2 */
|
|
{ F(WIN_H / 2 - SRC_W) + EPS, F(WIN_W / 2 - SRC_H), F(SRC_W), F(SRC_H), 2, WL_OUTPUT_TRANSFORM_90 },
|
|
{ F(WIN_H / 2 - SRC_W), F(WIN_W / 2 - SRC_H) + EPS, F(SRC_W), F(SRC_H), 2, WL_OUTPUT_TRANSFORM_270 },
|
|
{ F(WIN_H / 2 - SRC_W), F(WIN_W / 2 - SRC_H), F(SRC_W) + EPS, F(SRC_H), 2, WL_OUTPUT_TRANSFORM_FLIPPED_90 },
|
|
{ F(WIN_H / 2 - SRC_W), F(WIN_W / 2 - SRC_H), F(SRC_W), F(SRC_H) + EPS, 2, WL_OUTPUT_TRANSFORM_FLIPPED_270 },
|
|
|
|
#undef F
|
|
};
|
|
|
|
TEST_P(test_viewporter_source_outside_buffer, bad_source_buffer_args)
|
|
{
|
|
const struct source_buffer_args *args = data;
|
|
struct client *client;
|
|
|
|
client = create_client_and_test_surface(100, 50, WIN_W, WIN_H);
|
|
setup_source_vs_buffer(client, args);
|
|
|
|
expect_protocol_error(client, &wp_viewport_interface,
|
|
WP_VIEWPORT_ERROR_OUT_OF_BUFFER);
|
|
}
|
|
|
|
static const struct source_buffer_args good_source_buffer_args[] = {
|
|
#define F(i) ((i) * 256)
|
|
|
|
/* top-left, top-right, bottom-left, and bottom-right corner */
|
|
{ F(0), F(0), F(SRC_W), F(SRC_H), 1, WL_OUTPUT_TRANSFORM_NORMAL },
|
|
{ F(WIN_W - SRC_W), F(0), F(SRC_W), F(SRC_H), 1, WL_OUTPUT_TRANSFORM_NORMAL },
|
|
{ F(0), F(WIN_H - SRC_H), F(SRC_W), F(SRC_H), 1, WL_OUTPUT_TRANSFORM_NORMAL },
|
|
{ F(WIN_W - SRC_W), F(WIN_H - SRC_H), F(SRC_W), F(SRC_H), 1, WL_OUTPUT_TRANSFORM_NORMAL },
|
|
|
|
/* buffer_scale=2, so the surface size will be halved */
|
|
{ F(0), F(0), F(SRC_W), F(SRC_H), 2, WL_OUTPUT_TRANSFORM_NORMAL },
|
|
{ F(WIN_W / 2 - SRC_W), F(0), F(SRC_W), F(SRC_H), 2, WL_OUTPUT_TRANSFORM_NORMAL },
|
|
{ F(0), F(WIN_H / 2 - SRC_H), F(SRC_W), F(SRC_H), 2, WL_OUTPUT_TRANSFORM_NORMAL },
|
|
{ F(WIN_W / 2 - SRC_W), F(WIN_H / 2 - SRC_H), F(SRC_W), F(SRC_H), 2, WL_OUTPUT_TRANSFORM_NORMAL },
|
|
|
|
/* with half pixel offset */
|
|
{ F(WIN_W / 2 - SRC_W) + 128, F(WIN_H / 2 - SRC_H) + 128, F(SRC_W) - 128, F(SRC_H) - 128, 2, WL_OUTPUT_TRANSFORM_NORMAL },
|
|
|
|
/* Flushed to bottom-right corner: */
|
|
/* non-dimension-swapping transforms */
|
|
{ F(WIN_W - SRC_W), F(WIN_H - SRC_H), F(SRC_W), F(SRC_H), 1, WL_OUTPUT_TRANSFORM_FLIPPED_180 },
|
|
{ F(WIN_W - SRC_W), F(WIN_H - SRC_H), F(SRC_W), F(SRC_H), 1, WL_OUTPUT_TRANSFORM_FLIPPED },
|
|
{ F(WIN_W - SRC_W), F(WIN_H - SRC_H), F(SRC_W), F(SRC_H), 1, WL_OUTPUT_TRANSFORM_180 },
|
|
|
|
/* dimension-swapping transforms */
|
|
{ F(WIN_H - SRC_W), F(WIN_W - SRC_H), F(SRC_W), F(SRC_H), 1, WL_OUTPUT_TRANSFORM_90 },
|
|
{ F(WIN_H - SRC_W), F(WIN_W - SRC_H), F(SRC_W), F(SRC_H), 1, WL_OUTPUT_TRANSFORM_270 },
|
|
{ F(WIN_H - SRC_W), F(WIN_W - SRC_H), F(SRC_W), F(SRC_H), 1, WL_OUTPUT_TRANSFORM_FLIPPED_90 },
|
|
{ F(WIN_H - SRC_W), F(WIN_W - SRC_H), F(SRC_W), F(SRC_H), 1, WL_OUTPUT_TRANSFORM_FLIPPED_270 },
|
|
|
|
/* non-dimension-swapping transforms, buffer_scale=2 */
|
|
{ F(WIN_W / 2 - SRC_W), F(WIN_H / 2 - SRC_H), F(SRC_W), F(SRC_H), 2, WL_OUTPUT_TRANSFORM_FLIPPED_180 },
|
|
{ F(WIN_W / 2 - SRC_W), F(WIN_H / 2 - SRC_H), F(SRC_W), F(SRC_H), 2, WL_OUTPUT_TRANSFORM_FLIPPED },
|
|
{ F(WIN_W / 2 - SRC_W), F(WIN_H / 2 - SRC_H), F(SRC_W), F(SRC_H), 2, WL_OUTPUT_TRANSFORM_180 },
|
|
|
|
/* dimension-swapping transforms, buffer_scale=2 */
|
|
{ F(WIN_H / 2 - SRC_W), F(WIN_W / 2 - SRC_H), F(SRC_W), F(SRC_H), 2, WL_OUTPUT_TRANSFORM_90 },
|
|
{ F(WIN_H / 2 - SRC_W), F(WIN_W / 2 - SRC_H), F(SRC_W), F(SRC_H), 2, WL_OUTPUT_TRANSFORM_270 },
|
|
{ F(WIN_H / 2 - SRC_W), F(WIN_W / 2 - SRC_H), F(SRC_W), F(SRC_H), 2, WL_OUTPUT_TRANSFORM_FLIPPED_90 },
|
|
{ F(WIN_H / 2 - SRC_W), F(WIN_W / 2 - SRC_H), F(SRC_W), F(SRC_H), 2, WL_OUTPUT_TRANSFORM_FLIPPED_270 },
|
|
|
|
#undef F
|
|
};
|
|
|
|
TEST_P(test_viewporter_source_inside_buffer, good_source_buffer_args)
|
|
{
|
|
const struct source_buffer_args *args = data;
|
|
struct client *client;
|
|
|
|
client = create_client_and_test_surface(100, 50, WIN_W, WIN_H);
|
|
setup_source_vs_buffer(client, args);
|
|
client_roundtrip(client);
|
|
}
|
|
|
|
#undef WIN_W
|
|
#undef WIN_H
|
|
#undef SRC_W
|
|
#undef SRC_H
|
|
#undef MRG
|
|
#undef EPS
|
|
|
|
TEST(test_viewporter_outside_null_buffer)
|
|
{
|
|
struct client *client;
|
|
struct wp_viewport *vp;
|
|
struct wl_surface *surf;
|
|
|
|
client = create_client_and_test_surface(100, 50, 123, 77);
|
|
surf = client->surface->wl_surface;
|
|
|
|
/* If buffer is NULL, does not matter what the source rect is. */
|
|
vp = create_viewport(client);
|
|
wl_surface_attach(surf, NULL, 0, 0);
|
|
set_source(vp, 1000, 1000, 20, 10);
|
|
wp_viewport_set_destination(vp, 99, 99);
|
|
wl_surface_commit(surf);
|
|
client_roundtrip(client);
|
|
|
|
/* Try again, with all old values. */
|
|
wl_surface_commit(surf);
|
|
client_roundtrip(client);
|
|
|
|
/* Try once more with old NULL buffer. */
|
|
set_source(vp, 1200, 1200, 20, 10);
|
|
wl_surface_commit(surf);
|
|
client_roundtrip(client);
|
|
|
|
/* When buffer comes back, source rect matters again. */
|
|
wl_surface_attach(surf, client->surface->buffer->proxy, 0, 0);
|
|
wl_surface_commit(surf);
|
|
expect_protocol_error(client, &wp_viewport_interface,
|
|
WP_VIEWPORT_ERROR_OUT_OF_BUFFER);
|
|
}
|
|
|
|
TEST(test_viewporter_no_surface_set_source)
|
|
{
|
|
struct client *client;
|
|
struct wp_viewport *vp;
|
|
|
|
client = create_client_and_test_surface(100, 50, 123, 77);
|
|
vp = create_viewport(client);
|
|
wl_surface_destroy(client->surface->wl_surface);
|
|
client->surface->wl_surface = NULL;
|
|
|
|
/* But the wl_surface does not exist anymore. */
|
|
set_source(vp, 1000, 1000, 20, 10);
|
|
|
|
expect_protocol_error(client, &wp_viewport_interface,
|
|
WP_VIEWPORT_ERROR_NO_SURFACE);
|
|
}
|
|
|
|
TEST(test_viewporter_no_surface_set_destination)
|
|
{
|
|
struct client *client;
|
|
struct wp_viewport *vp;
|
|
|
|
client = create_client_and_test_surface(100, 50, 123, 77);
|
|
vp = create_viewport(client);
|
|
wl_surface_destroy(client->surface->wl_surface);
|
|
client->surface->wl_surface = NULL;
|
|
|
|
/* But the wl_surface does not exist anymore. */
|
|
wp_viewport_set_destination(vp, 99, 99);
|
|
|
|
expect_protocol_error(client, &wp_viewport_interface,
|
|
WP_VIEWPORT_ERROR_NO_SURFACE);
|
|
}
|
|
|
|
TEST(test_viewporter_no_surface_destroy)
|
|
{
|
|
struct client *client;
|
|
struct wp_viewport *vp;
|
|
|
|
client = create_client_and_test_surface(100, 50, 123, 77);
|
|
vp = create_viewport(client);
|
|
wl_surface_destroy(client->surface->wl_surface);
|
|
client->surface->wl_surface = NULL;
|
|
|
|
/* But the wl_surface does not exist anymore. */
|
|
wp_viewport_destroy(vp);
|
|
|
|
client_roundtrip(client);
|
|
}
|