Add new buffer scale tests

* 12to11-test.xml (test_manager): <error>: New errors
`scale_lock_exists' and `invalid_scale'.
(test_manager): <get_test_surface>: Reword documentation.
(test_manager): <get_scale_lock>: New request.
(test_scale_lock): New interface.

* compositor.h: Update prototypes.
* output.c (HandleScaleSettingChange): New function.  Ignore
scale changes while scale is locked.
(XLInitRROutputs): Initialize real output scale.
* test.c (DestroyScaleLock, SetScale, GetScaleLock): New
functions.
(test_manager_impl): Add new implementation.
* tests/Imakefile (SYSTEM_LIBRARIES): Add MathLibrary.
(SRCS7, OBJS7): Add scale_test.c/.o.
(PROGRAMS): Add scale_test.
(scale_test): New program target.
* tests/run_tests.sh (standard_tests): Add scale_test.
* tests/svnignore.txt: Add scale_test.
* tests/test_harness.c (exit_with_code): New function.
(open_test_display): Initialize scale.
(report_test_failure): Call it instead of just exit.
(test_set_scale): New function.
(test_complete): Call exit_with_code.
* tests/test_harness.h (struct test_display): New field
`scale_lock'.
This commit is contained in:
hujianwei 2022-11-05 08:18:18 +00:00
parent fa29286c98
commit 21aa7494cd
9 changed files with 233 additions and 17 deletions

View file

@ -33,25 +33,46 @@
<enum name="error"> <enum name="error">
<entry name="role_present" value="1" <entry name="role_present" value="1"
summary="given wl_surface has/had another role"/> summary="given wl_surface has/had another role"/>
<entry name="scale_lock_exists" value="2"
summary="another client has already locked the scale"/>
<entry name="invalid_scale" value="3"
summary="the specified scale is invalid"/>
</enum> </enum>
<request name="get_test_surface"> <request name="get_test_surface">
<description summary="obtain test surface role"> <description summary="obtain test surface role">
Get a test_surface object for a particular surface. If a role Get a test_surface object for a particular surface. If a role
was already attached to this surface, or a role of a different was already attached to this surface, or a role of a different
type was previously attached, a role_present error is issued. type was previously attached, post a role_present error.
The window is created immediately after get_test_surface is Create the window immediately after get_test_surface is
called. It is mapped once a commit request with a non-nil called; the window is mapped once a commit request with a
buffer is made. non-nil buffer is made.
Once the window associated with the test_surface object is Once the window associated with the test_surface object is
mapped, a mapped event is sent. mapped, send a mapped event.
</description> </description>
<arg name="id" type="new_id" interface="test_surface"/> <arg name="id" type="new_id" interface="test_surface"/>
<arg name="surface" type="object" interface="wl_surface"/> <arg name="surface" type="object" interface="wl_surface"/>
</request> </request>
<request name="get_scale_lock">
<description summary="obtain scale lock">
Create a new test_scale_lock object. As long as this object
exists, set the global output scale to the scale specified in
this request (or in a subsequent test_scale_lock.set_scale
request.)
If a test_scale_lock object already exists, generate a
scale_lock_exists error.
If the scale is invalid (by being less than 0), post an
invalid_scale error.
</description>
<arg name="id" type="new_id" interface="test_scale_lock"/>
<arg name="global_scale" type="uint"/>
</request>
<event name="display_string"> <event name="display_string">
<description summary="X server name"> <description summary="X server name">
The display_string event sends the name of the X display to The display_string event sends the name of the X display to
@ -74,8 +95,8 @@
<request name="destroy" type="destructor"> <request name="destroy" type="destructor">
<description summary="destroy role"> <description summary="destroy role">
This request destroys the test_surface role. Subsequently, Destroy the test_surface role. Subsequently, get_test_surface
get_test_surface can be called again with its surface. can be called again with its surface.
</description> </description>
</request> </request>
@ -94,4 +115,29 @@
<arg name="display_string" type="string"/> <arg name="display_string" type="string"/>
</event> </event>
</interface> </interface>
<interface name="test_scale_lock" version="1">
<description summary="test scale lock">
A scale lock resource represents the "lock" a client holds on
the global output scale. While it still exists, the scale for
every output will be whatever was specified when the lock was
created or by the last set_scale request.
</description>
<request name="destroy" type="destructor">
<description summary="destroy scale lock">
Destroy the specified scale lock, restore the actual scale of
each output, and let clients call get_scale_lock again.
</description>
</request>
<request name="set_scale">
<description summary="set the global output scale">
Set the scale of each output to the specified scale, and
resize all surfaces accordingly. If the scale is invalid,
post an invalid_scale error.
</description>
<arg name="scale" type="uint"/>
</request>
</interface>
</protocol> </protocol>

View file

@ -1206,6 +1206,7 @@ extern void XLRemoveScaleChangeCallback (void *);
extern void XLClearOutputs (Surface *); extern void XLClearOutputs (Surface *);
extern void XLOutputSetChangeFunction (void (*) (Time)); extern void XLOutputSetChangeFunction (void (*) (Time));
extern void XLGetMaxOutputBounds (int *, int *, int *, int *); extern void XLGetMaxOutputBounds (int *, int *, int *, int *);
extern void XLOutputHandleScaleChange (int);
/* Defined in atoms.c. */ /* Defined in atoms.c. */
@ -1799,6 +1800,8 @@ extern void XLInitPointerGestures (void);
/* Defined in test.c. */ /* Defined in test.c. */
extern int locked_output_scale;
extern void XLInitTest (void); extern void XLInitTest (void);
extern Bool XLHandleOneXEventForTest (XEvent *); extern Bool XLHandleOneXEventForTest (XEvent *);

View file

@ -98,6 +98,9 @@ static ScaleChangeCallback scale_callbacks;
/* The scale factor currently applied on a global basis. */ /* The scale factor currently applied on a global basis. */
int global_scale_factor; int global_scale_factor;
/* The current real scale factor. */
static int real_scale_factor;
/* Function run upon any kind of XRandR notify event. */ /* Function run upon any kind of XRandR notify event. */
static void (*change_hook) (Time); static void (*change_hook) (Time);
@ -1035,6 +1038,19 @@ HandleScaleChange (int scale)
RunScaleChangeCallbacks (); RunScaleChangeCallbacks ();
} }
static void
HandleScaleSettingChange (int scale)
{
real_scale_factor = scale;
/* If the scale factor is locked, just return. */
if (locked_output_scale)
return;
/* Otherwise, update the scale. */
HandleScaleChange (scale);
}
void * void *
XLAddScaleChangeCallback (void *data, void (*func) (void *, int)) XLAddScaleChangeCallback (void *data, void (*func) (void *, int))
{ {
@ -1142,6 +1158,18 @@ XLGetMaxOutputBounds (int *x_min, int *y_min, int *x_max,
*y_max = y2; *y_max = y2;
} }
void
XLOutputHandleScaleChange (int new_scale)
{
/* If the value is not -1, just use the new scale.
Otherwise, use the current non-locked scale. */
if (new_scale != -1)
HandleScaleChange (new_scale);
else
HandleScaleChange (real_scale_factor);
}
void void
XLInitRROutputs (void) XLInitRROutputs (void)
{ {
@ -1179,7 +1207,10 @@ XLInitRROutputs (void)
factor was specified for debugging. */ factor was specified for debugging. */
if (!ApplyEnvironment ("GLOBAL_SCALE", &global_scale_factor)) if (!ApplyEnvironment ("GLOBAL_SCALE", &global_scale_factor))
XLListenToIntegerSetting ("Gdk/WindowScalingFactor", XLListenToIntegerSetting ("Gdk/WindowScalingFactor",
HandleScaleChange); HandleScaleSettingChange);
/* Set the real scale factor. */
real_scale_factor = global_scale_factor;
/* Initialize the scale change callback list sentinel node. */ /* Initialize the scale change callback list sentinel node. */
scale_callbacks.next = &scale_callbacks; scale_callbacks.next = &scale_callbacks;
@ -1204,4 +1235,3 @@ XLInitRROutputs (void)
all_outputs = BuildOutputTree (); all_outputs = BuildOutputTree ();
MakeGlobalsForOutputTree (all_outputs); MakeGlobalsForOutputTree (all_outputs);
} }

92
test.c
View file

@ -60,6 +60,11 @@ struct _TestSurface
int bounds_width, bounds_height; int bounds_width, bounds_height;
}; };
/* The locked output scale. N.B. that a test_scale_lock is not an
actual resource, and just represents the state of this
variable. */
int locked_output_scale;
/* The test surface manager global. */ /* The test surface manager global. */
static struct wl_global *test_manager_global; static struct wl_global *test_manager_global;
@ -348,6 +353,47 @@ HandleResourceDestroy (struct wl_resource *resource)
DestroyBacking (test); DestroyBacking (test);
} }
static void
DestroyScaleLock (struct wl_client *client, struct wl_resource *resource)
{
wl_resource_destroy (resource);
}
static void
SetScale (struct wl_client *client, struct wl_resource *resource,
uint32_t scale)
{
/* If the scale is invalid, reject it. */
if (!scale)
{
wl_resource_post_error (resource, TEST_MANAGER_ERROR_INVALID_SCALE,
"scale of 0 specified");
return;
}
/* Set the scale. As there can only be one lock at any given
time, there is no need to check the resource data. */
locked_output_scale = scale;
XLOutputHandleScaleChange (scale);
}
static const struct test_scale_lock_interface scale_lock_impl =
{
.destroy = DestroyScaleLock,
.set_scale = SetScale,
};
static void
HandleScaleLockResourceDestroy (struct wl_resource *resource)
{
/* There is no resource data associated with scale locks. Just
unlock the scale. */
locked_output_scale = 0;
XLOutputHandleScaleChange (-1);
}
static void static void
GetTestSurface (struct wl_client *client, struct wl_resource *resource, GetTestSurface (struct wl_client *client, struct wl_resource *resource,
uint32_t id, struct wl_resource *surface_resource) uint32_t id, struct wl_resource *surface_resource)
@ -451,9 +497,55 @@ GetTestSurface (struct wl_client *client, struct wl_resource *resource,
abort (); abort ();
} }
static void
GetScaleLock (struct wl_client *client, struct wl_resource *resource,
uint32_t id, uint32_t scale)
{
struct wl_resource *lock_resource;
if (!scale)
{
wl_resource_post_error (resource, TEST_MANAGER_ERROR_INVALID_SCALE,
"scale of 0 specified");
return;
}
if (locked_output_scale)
{
/* The scale is already locked, so don't create another
lock. */
wl_resource_post_error (resource, TEST_MANAGER_ERROR_SCALE_LOCK_EXISTS,
"a scale lock already exists (another test is"
" already running?)");
return;
}
lock_resource = wl_resource_create (client, &test_scale_lock_interface,
wl_resource_get_version (resource),
id);
if (!lock_resource)
{
wl_resource_post_no_memory (resource);
return;
}
/* Now, set the locked scale. */
locked_output_scale = scale;
/* And update the global scale factor if need be. */
if (scale != global_scale_factor)
XLOutputHandleScaleChange (scale);
/* And resource implementation. */
wl_resource_set_implementation (lock_resource, &scale_lock_impl,
NULL, HandleScaleLockResourceDestroy);
}
static const struct test_manager_interface test_manager_impl = static const struct test_manager_interface test_manager_impl =
{ {
.get_test_surface = GetTestSurface, .get_test_surface = GetTestSurface,
.get_scale_lock = GetScaleLock,
}; };

View file

@ -2,6 +2,7 @@
12TO11ROOT = .. 12TO11ROOT = ..
DEPLIBS = $(DEPXLIB) DEPLIBS = $(DEPXLIB)
SYS_LIBRARIES = MathLibrary
LOCAL_LIBRARIES = $(WAYLAND_CLIENT) $(XLIB) $(PNG) LOCAL_LIBRARIES = $(WAYLAND_CLIENT) $(XLIB) $(PNG)
COMMONOBJS = test_harness.o COMMONOBJS = test_harness.o
COMMONSRCS = test_harness.c COMMONSRCS = test_harness.c
@ -35,7 +36,9 @@ ScannerTarget(viewporter)
OBJS5 = $(COMMONSRCS) viewporter_test.o OBJS5 = $(COMMONSRCS) viewporter_test.o
SRCS6 = $(COMMONSRCS) subsurface_test.c SRCS6 = $(COMMONSRCS) subsurface_test.c
OBJS6 = $(COMMONSRCS) subsurface_test.o OBJS6 = $(COMMONSRCS) subsurface_test.o
PROGRAMS = imgview simple_test damage_test transform_test viewporter_test subsurface_test SRCS7 = $(COMMONSRCS) scale_test.c
OBJS7 = $(COMMONSRCS) scale_test.o
PROGRAMS = imgview simple_test damage_test transform_test viewporter_test subsurface_test scale_test
/* Make all objects depend on HEADER. */ /* Make all objects depend on HEADER. */
$(OBJS1): $(HEADER) $(OBJS1): $(HEADER)
@ -49,7 +52,9 @@ NormalProgramTarget(damage_test,$(OBJS3),NullParameter,$(LOCAL_LIBRARIES),NullPa
NormalProgramTarget(transform_test,$(OBJS4),NullParameter,$(LOCAL_LIBRARIES),NullParameter) NormalProgramTarget(transform_test,$(OBJS4),NullParameter,$(LOCAL_LIBRARIES),NullParameter)
NormalProgramTarget(viewporter_test,$(OBJS5),NullParameter,$(LOCAL_LIBRARIES),NullParameter) NormalProgramTarget(viewporter_test,$(OBJS5),NullParameter,$(LOCAL_LIBRARIES),NullParameter)
NormalProgramTarget(subsurface_test,$(OBJS6),NullParameter,$(LOCAL_LIBRARIES),NullParameter) NormalProgramTarget(subsurface_test,$(OBJS6),NullParameter,$(LOCAL_LIBRARIES),NullParameter)
NormalProgramTarget(scale_test,$(OBJS7),NullParameter,$(LOCAL_LIBRARIES),NullParameter)
DependTarget3($(SRCS1),$(SRCS2),$(SRCS3)) DependTarget3($(SRCS1),$(SRCS2),$(SRCS3))
DependTarget3($(SRCS4),$(SRCS5),$(SRCS6)) DependTarget3($(SRCS4),$(SRCS5),$(SRCS6))
DependTarget3($(SRCS7),NullParameter,NullParameter)
all:: $(PROGRAMS) all:: $(PROGRAMS)

View file

@ -21,14 +21,11 @@
pushd "$(dirname $0)" pushd "$(dirname $0)"
declare -a standard_tests=( declare -a standard_tests=(
simple_test damage_test transform_test viewporter_test simple_test damage_test transform_test viewporter_test
subsurface_test subsurface_test scale_test
) )
make -C . "${standard_tests[@]}" make -C . "${standard_tests[@]}"
# Run tandard tests, meaning those that should be run with a
# GLOBAL_SCALE of 1 and an OUTPUT_SCALE of 1.
export GLOBAL_SCALE=1 export GLOBAL_SCALE=1
export OUTPUT_SCALE=1 export OUTPUT_SCALE=1
exec 3< <(stdbuf -oL ../12to11 -printsocket) exec 3< <(stdbuf -oL ../12to11 -printsocket)

View file

@ -6,6 +6,7 @@ damage_test
transform_test transform_test
viewporter_test viewporter_test
subsurface_test subsurface_test
scale_test
imgview imgview
reject.dump reject.dump
Makefile Makefile

View file

@ -45,6 +45,9 @@ along with 12to11. If not, see <https://www.gnu.org/licenses/>. */
/* Whether or not to write image data instead of verifying it. */ /* Whether or not to write image data instead of verifying it. */
static bool write_image_data_instead; static bool write_image_data_instead;
/* The test display. */
static struct test_display *display;
static void static void
handle_test_manager_display_string (void *data, struct test_manager *manager, handle_test_manager_display_string (void *data, struct test_manager *manager,
const char *display_string) const char *display_string)
@ -154,10 +157,29 @@ die (const char *reason)
exit (1); exit (1);
} }
/* This should be called when a test failed due to a non-IO error. It
destroys the scale lock and synchronizes with the compositor so
that by the time the next test is run, the current test's scale
lock will have been released. */
static void __attribute__ ((noreturn))
exit_with_code (int code)
{
if (display)
{
test_scale_lock_destroy (display->scale_lock);
wl_display_roundtrip (display->display);
}
exit (code);
}
struct test_display * struct test_display *
open_test_display (struct test_interface *interfaces, int num_interfaces) open_test_display (struct test_interface *interfaces, int num_interfaces)
{ {
struct test_display *display; if (display)
/* The display was already opened. */
return display;
display = malloc (sizeof *display); display = malloc (sizeof *display);
@ -191,8 +213,17 @@ open_test_display (struct test_interface *interfaces, int num_interfaces)
if (!test_manager_check (display)) if (!test_manager_check (display))
goto error_3; goto error_3;
/* And try to set up the scale lock. */
display->scale_lock
= test_manager_get_scale_lock (display->test_manager, 1);
if (!display->scale_lock)
goto error_4;
return display; return display;
error_4:
XFree (display->pixmap_formats);
error_3: error_3:
if (display->x_display) if (display->x_display)
XCloseDisplay (display->x_display); XCloseDisplay (display->x_display);
@ -200,6 +231,7 @@ open_test_display (struct test_interface *interfaces, int num_interfaces)
wl_display_disconnect (display->display); wl_display_disconnect (display->display);
error_1: error_1:
free (display); free (display);
display = NULL;
return NULL; return NULL;
} }
@ -325,7 +357,7 @@ report_test_failure (const char *format, ...)
fputs ("\n", stderr); fputs ("\n", stderr);
va_end (ap); va_end (ap);
exit (1); exit_with_code (1);
} }
void __attribute__ ((format (gnu_printf, 1, 2))) void __attribute__ ((format (gnu_printf, 1, 2)))
@ -766,6 +798,12 @@ verify_image_data (struct test_display *display, Window window,
test_log ("verified image data"); test_log ("verified image data");
} }
void
test_set_scale (struct test_display *display, int scale)
{
test_scale_lock_set_scale (display->scale_lock, scale);
}
void void
test_init (void) test_init (void)
{ {
@ -777,5 +815,5 @@ void __attribute__ ((noreturn))
test_complete (void) test_complete (void)
{ {
test_log ("test ran successfully"); test_log ("test ran successfully");
exit (0); exit_with_code (0);
} }

View file

@ -51,6 +51,9 @@ struct test_display
struct wl_shm *shm; struct wl_shm *shm;
struct test_manager *test_manager; struct test_manager *test_manager;
/* The test scale lock. */
struct test_scale_lock *scale_lock;
/* Test interfaces. */ /* Test interfaces. */
struct test_interface *interfaces; struct test_interface *interfaces;
@ -119,6 +122,7 @@ extern unsigned char *load_image_data (const char *,
extern void verify_image_data (struct test_display *, Window, const char *); extern void verify_image_data (struct test_display *, Window, const char *);
extern void test_init (void); extern void test_init (void);
extern void test_complete (void) __attribute__ ((noreturn)); extern void test_complete (void) __attribute__ ((noreturn));
extern void test_set_scale (struct test_display *, int);
#define ARRAYELTS(arr) (sizeof (arr) / sizeof (arr)[0]) #define ARRAYELTS(arr) (sizeof (arr) / sizeof (arr)[0])