12to11/tearing_control.c
hujianwei 4c7b4a2c5a Check in new files for tearing control protocol
* tearing-control-v1.xml:
* tearing_control.c:
* tests/tearing_control_test.c: New files.
2022-11-19 06:28:50 +00:00

220 lines
5 KiB
C
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/* Wayland compositor running on top of an 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 <stdio.h>
#include "compositor.h"
#include "tearing-control-v1.h"
typedef struct _TearingControl TearingControl;
struct _TearingControl
{
/* The associated surface. NULL when detached. */
Surface *surface;
/* The associated resource. */
struct wl_resource *resource;
};
/* The tearing control manager. */
static struct wl_global *tearing_control_manager_global;
static void
DestroyTearingControl (struct wl_client *client, struct wl_resource *resource)
{
TearingControl *control;
control = wl_resource_get_user_data (resource);
if (control->surface)
{
/* Reset the presentation hint. */
control->surface->pending_state.presentation_hint
= PresentationHintVsync;
control->surface->pending_state.pending
|= PendingPresentationHint;
}
wl_resource_destroy (resource);
}
static void
SetPresentationHint (struct wl_client *client, struct wl_resource *resource,
uint32_t hint)
{
TearingControl *control;
control = wl_resource_get_user_data (resource);
if (control->surface)
{
switch (hint)
{
case WP_TEARING_CONTROL_V1_PRESENTATION_HINT_ASYNC:
control->surface->pending_state.presentation_hint
= PresentationHintAsync;
break;
default:
control->surface->pending_state.presentation_hint
= PresentationHintVsync;
break;
}
control->surface->pending_state.pending |= PendingPresentationHint;
}
}
static const struct wp_tearing_control_v1_interface control_impl =
{
.destroy = DestroyTearingControl,
.set_presentation_hint = SetPresentationHint,
};
static void
HandleResourceDestroy (struct wl_resource *resource)
{
TearingControl *control, **reference;
control = wl_resource_get_user_data (resource);
/* If the surface is still attached to the tearing control, remove
it from the surface. */
if (control->surface)
{
reference
= XLSurfaceFindClientData (control->surface,
TearingControlData);
XLAssert (reference != NULL);
*reference = NULL;
}
XLFree (control);
}
static void
FreeTearingControlData (void *data)
{
TearingControl **control;
control = data;
if (!*control)
return;
/* Detach the surface from the tearing control. */
(*control)->surface = NULL;
}
static void
Destroy (struct wl_client *client, struct wl_resource *resource)
{
wl_resource_destroy (resource);
}
static void
GetTearingControl (struct wl_client *client, struct wl_resource *resource,
uint32_t id, struct wl_resource *surface_resource)
{
Surface *surface;
TearingControl **control;
surface = wl_resource_get_user_data (surface_resource);
control = XLSurfaceGetClientData (surface, TearingControlData,
sizeof *control,
FreeTearingControlData);
#define ControlExists \
WP_TEARING_CONTROL_MANAGER_V1_ERROR_TEARING_CONTROL_EXISTS
if (*control)
{
/* A tearing control resource already exists for this
surface. */
wl_resource_post_error (resource, ControlExists,
"a wp_tearing_control_v1 resource already exists"
" for the specified surface");
return;
}
#undef ControlExists
(*control) = XLCalloc (1, sizeof **control);
(*control)->resource
= wl_resource_create (client,
&wp_tearing_control_v1_interface,
wl_resource_get_version (resource), id);
if (!(*control)->resource)
{
XLFree (*control);
(*control) = NULL;
wl_resource_post_no_memory (resource);
return;
}
(*control)->surface = surface;
wl_resource_set_implementation ((*control)->resource, &control_impl,
(*control), HandleResourceDestroy);
}
static const struct wp_tearing_control_manager_v1_interface manager_impl =
{
.destroy = Destroy,
.get_tearing_control = GetTearingControl,
};
static void
HandleBind (struct wl_client *client, void *data,
uint32_t version, uint32_t id)
{
struct wl_resource *resource;
resource = wl_resource_create (client,
&wp_tearing_control_manager_v1_interface,
version, id);
if (!resource)
{
wl_client_post_no_memory (client);
return;
}
wl_resource_set_implementation (resource, &manager_impl,
NULL, NULL);
}
void
XLInitTearingControl (void)
{
tearing_control_manager_global
= wl_global_create (compositor.wl_display,
&wp_tearing_control_manager_v1_interface,
1, NULL, HandleBind);
}