12to11/atoms.c
oldosfan 713eb811ea Add support for DRM leasing and significantly rework composition code
* 12to11.c (HandleCmdline): Improve messages printed during
-help.
(XLMain): Initialize DRM leasing.
* 12to11.man: Document changes.
* Imakefile (LOCAL_LIBRARIES): Add xcb-randr, xf86drm and
XPresent.
(SRCS): Add drm_lease.c.
(OBJS): Add drm_lease.o.
* atoms.c (names): Add CONNECTOR_ID.
(CONNECTOR_ID): New atom.
(XLInitAtoms): Intern CONNECTOR_ID.
* compositor.h (struct _RenderFuncs): Require event mask to be
passed to target_from_window.  New functions
`set_standard_event_mask', `present_to_window',
`cancel_presentation_callback', and `cancel_presentation'.
(struct _BufferFuncs): Move buffer release machinery here.
(enum _FrameMode): New enum.
* egl.c (TargetFromWindow, SetStandardEventMask,
egl_render_funcs): Adjust functions accordingly.
* frame_clock.c (struct _FrameClock): New fields
`end_frame_called' and `pending_sync_value'.
(HandleEndFrame, PostEndFrame, StartFrame, EndFrame): Clean up
frame synchronization code.  Do not end upon predicted
presentation time if EndFrame was not called in time.
(FreezeForValue): New function.
(XLFrameClockHandleFrameEvent): Defer actually freezing until
StartFrame happens.
(XLFrameClockGetFrameTime): New function.
* icon_surface.c (ReleaseBuffer): Use RenderWaitForIdle.
(RunFrameCallbacks, AfterFrame): Pass frame clock to callbacks.
Use frame time if available.
(XLGetIconSurface): Require wait_for_idle to work.
* output.c (change_hook): New hook.
(XLHandleOneXEventForOutputs): Run hook if set.
(XLOutputSetChangeFunction): New function.
(XLInitRROutputs): Select for RRResourceChangeNotify if
providers are supported.
* picture_renderer.c (struct _PresentRecord)
(struct _BufferActivityRecord, struct _IdleCallback)
(struct _PictureBuffer, struct _PictureTarget)
(struct _DrmFormatInfo, struct _DmaBufRecord)
(struct _PresentCompletionCallback): New record structures.
(all_formats, SendRoundtripMessage, FindBufferActivityRecord)
(RecordBufferActivity, RunIdleCallbacks, MaybeRunIdleCallbacks)
(UnlinkActivityRecord, HandleActivityEvent, InitRenderFuncs)
(TargetFromDrawable, TargetFromPixmap, TargetFromWindow)
(SetStandardEventMask, NoteTargetSize, PictureFromTarget)
(DestroyRenderTarget, FillBoxesWithTransparency)
(ServerRegionFromRegion, ClearRectangle, Composite)
(FindPresentRecord, AllocateRecord, PresentToWindow)
(CancelPresentationCallback, CancelPresentation)
(picture_render_funcs, FindSupportedModifiers, InitDrmFormats)
(PictFormatIsPresentable, BufferFromDmaBuf, FinishDmaBufRecord)
(BufferFromDmaBufAsync, BufferFromShm, BufferFromSinglePixel)
(FreeShmBuffer, FreeDmabufBuffer, FreeSinglePixelBuffer)
(AddIdleCallback, CancelIdleCallback, IsBufferIdle)
(IdleEventPredicate, WaitForIdle, SetNeedWaitForIdle)
(picture_buffer_funcs, HandlePresentCompleteNotify)
(HandlePresentIdleNotify, HandlePresentationEvent)
(HandleOneXEventForPictureRenderer, InitPictureRenderer): Allow
presenting pixmaps directly, and move buffer release tracking
machinery here.
* renderer.c (RenderTargetFromWindow): Update signature.
(RenderPresentToWindow, RenderCancelPresentationCallback)
(RenderCancelPresentation, RenderAddIdleCallback)
(RegisterStaticRenderer): New wrapper functions.
* run.c (HandleOneXEvent): Handle picture renderer events
earlier.
* seat.c (MaybeCreateCursor): Require wait_for_idle.
(ReleaseBuffer): Wait for buffer to become idle on each target
in the cursor ring.
* subcompositor.c (struct _Subcompositor): New callback
`note_frame'.
(SubcompositorSetNoteFrameCallback, NoViewsAfter)
(PresentCompletedCallback): New functions.
(SubcompositorUpdate): Try to present the buffer if possible,
and run completion callbacks.
(SubcompositorFree): Free presentation key.
* surface.c (XLSurfaceRunFrameCallbacksMs): New function.
* text_input.c: Improve commentary.
* xdg-shell.xml: Update from wayland-protocols.
* xdg_surface.c (struct _XdgRole): New fields `pending_frame',
`last_specified_serial'.
(struct _ReleaseLaterRecord): Replace free function with idle
callback key and xdg role pointers.
(RemoveRecord): Delete function.
(FreeRecords): Stop cancelling buffer destroy listener.
(ReleaseLaterExtBufferFunc): Delete function.
(RunFrameCallbacks): Use frame clock time if it is set.
(HandleReleaseLaterMessage): Delete function.
(BufferIdleCallback): New function.
(ReleaseLater): Delete function.
(XLHandleXEventForXdgSurfaces): Stop handling buffer release
events here.
(AckConfigure): Improve debug code and reject duplicate serials.
(Commit): Unfreeze earlier; also, in general...
(NoteFrame): Move frame handling implementation here.
(ReleaseBuffer, Subframe, EndSubframe, AfterFrame, ResizeForMap)
(SelectExtraEvents): Set standard event mask.
(XLGetXdgSurface, XLXdgRoleSendConfigure): ...Replace frame
clock logic with that in NoteFrame.
2022-10-12 12:53:09 +00:00

297 lines
8.3 KiB
C

/* 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 <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "compositor.h"
#define AtomTableSize 256
typedef struct _AtomTable AtomTable;
/* This is automatically generated by mime4.awk. */
Atom DirectTransferAtoms;
/* Simple hash table for atoms. */
struct _AtomTable
{
/* Atom array indexed by table size. */
Atom *atoms[AtomTableSize];
/* Atom name array indexed by table size. */
char **names[AtomTableSize];
/* Size of each array. */
ptrdiff_t atoms_length[AtomTableSize];
};
/* Array of all atom names. */
static const char *names[] =
{
"_NET_WM_OPAQUE_REGION",
"_XL_BUFFER_RELEASE",
"_NET_WM_SYNC_REQUEST_COUNTER",
"_NET_WM_FRAME_DRAWN",
"WM_DELETE_WINDOW",
"WM_PROTOCOLS",
"_NET_SUPPORTING_WM_CHECK",
"_NET_SUPPORTED",
"_NET_WM_SYNC_REQUEST",
"_MOTIF_WM_HINTS",
"_NET_WM_STATE_MAXIMIZED_VERT",
"_NET_WM_STATE_MAXIMIZED_HORZ",
"_NET_WM_STATE_FOCUSED",
"_NET_WM_STATE_FULLSCREEN",
"_NET_WM_STATE",
"_NET_WM_MOVERESIZE",
"_GTK_FRAME_EXTENTS",
"WM_TRANSIENT_FOR",
"_XL_DMA_BUF_CREATED",
"_GTK_SHOW_WINDOW_MENU",
"_NET_WM_ALLOWED_ACTIONS",
"_NET_WM_ACTION_FULLSCREEN",
"_NET_WM_ACTION_MAXIMIZE_HORZ",
"_NET_WM_ACTION_MAXIMIZE_VERT",
"_NET_WM_ACTION_MINIMIZE",
"INCR",
"CLIPBOARD",
"TARGETS",
"UTF8_STRING",
"_XL_SERVER_TIME_ATOM",
"MULTIPLE",
"TIMESTAMP",
"ATOM_PAIR",
"_NET_WM_NAME",
"WM_NAME",
"MANAGER",
"_XSETTINGS_SETTINGS",
"libinput Scroll Methods Available",
"XdndAware",
"XdndSelection",
"XdndTypeList",
"XdndActionCopy",
"XdndActionMove",
"XdndActionLink",
"XdndActionAsk",
"XdndActionPrivate",
"XdndActionList",
"XdndActionDescription",
"XdndProxy",
"XdndEnter",
"XdndPosition",
"XdndStatus",
"XdndLeave",
"XdndDrop",
"XdndFinished",
"_NET_WM_FRAME_TIMINGS",
"_NET_WM_BYPASS_COMPOSITOR",
"WM_STATE",
"_NET_WM_WINDOW_TYPE",
"_NET_WM_WINDOW_TYPE_MENU",
"_NET_WM_WINDOW_TYPE_DND",
"CONNECTOR_ID",
/* These are automatically generated from mime.txt. */
DirectTransferAtomNames
};
Atom _NET_WM_OPAQUE_REGION, _XL_BUFFER_RELEASE, _NET_WM_SYNC_REQUEST_COUNTER,
_NET_WM_FRAME_DRAWN, WM_DELETE_WINDOW, WM_PROTOCOLS,
_NET_SUPPORTING_WM_CHECK, _NET_SUPPORTED, _NET_WM_SYNC_REQUEST,
_MOTIF_WM_HINTS, _NET_WM_STATE_MAXIMIZED_VERT, _NET_WM_STATE_MAXIMIZED_HORZ,
_NET_WM_STATE_FOCUSED, _NET_WM_STATE_FULLSCREEN, _NET_WM_STATE,
_NET_WM_MOVERESIZE, _GTK_FRAME_EXTENTS, WM_TRANSIENT_FOR,
_XL_DMA_BUF_CREATED, _GTK_SHOW_WINDOW_MENU, _NET_WM_ALLOWED_ACTIONS,
_NET_WM_ACTION_FULLSCREEN, _NET_WM_ACTION_MAXIMIZE_HORZ,
_NET_WM_ACTION_MAXIMIZE_VERT, _NET_WM_ACTION_MINIMIZE, INCR, CLIPBOARD,
TARGETS, UTF8_STRING, _XL_SERVER_TIME_ATOM, MULTIPLE, TIMESTAMP, ATOM_PAIR,
_NET_WM_NAME, WM_NAME, MANAGER, _XSETTINGS_SETTINGS,
libinput_Scroll_Methods_Available, XdndAware, XdndSelection, XdndTypeList,
XdndActionCopy, XdndActionMove, XdndActionLink, XdndActionAsk,
XdndActionPrivate, XdndActionList, XdndActionDescription, XdndProxy,
XdndEnter, XdndPosition, XdndStatus, XdndLeave, XdndDrop, XdndFinished,
_NET_WM_FRAME_TIMINGS, _NET_WM_BYPASS_COMPOSITOR, WM_STATE,
_NET_WM_WINDOW_TYPE, _NET_WM_WINDOW_TYPE_MENU, _NET_WM_WINDOW_TYPE_DND,
CONNECTOR_ID;
XrmQuark resource_quark, app_quark, QString;
/* Hash table containing atoms. */
static AtomTable atom_table;
static unsigned int
HashAtomString (const char *string)
{
unsigned int i;
i = 3323198485ul;
for (; *string; ++string)
{
i ^= *string;
i *= 0x5bd1e995;
i ^= i >> 15;
}
return i;
}
Atom
InternAtom (const char *name)
{
Atom atom;
unsigned int hash;
ptrdiff_t bucket_length, i;
hash = HashAtomString (name) % AtomTableSize;
bucket_length = atom_table.atoms_length[hash];
for (i = 0; i < bucket_length; ++i)
{
if (!strcmp (atom_table.names[hash][i], name))
return atom_table.atoms[hash][i];
}
atom = XInternAtom (compositor.display, name, False);
atom_table.atoms_length[hash] = ++bucket_length;
atom_table.names[hash]
= XLRealloc (atom_table.names[hash],
bucket_length * sizeof *atom_table.names);
atom_table.atoms[hash]
= XLRealloc (atom_table.atoms[hash],
bucket_length * sizeof *atom_table.atoms);
atom_table.names[hash][bucket_length - 1] = XLStrdup (name);
atom_table.atoms[hash][bucket_length - 1] = atom;
return atom;
}
void
ProvideAtom (const char *name, Atom atom)
{
unsigned int hash;
ptrdiff_t bucket_length, i;
hash = HashAtomString (name) % AtomTableSize;
bucket_length = atom_table.atoms_length[hash];
for (i = 0; i < bucket_length; ++i)
{
if (!strcmp (atom_table.names[hash][i], name))
/* The atom already exists; there is no need to update it. */
return;
}
atom_table.atoms_length[hash] = ++bucket_length;
atom_table.names[hash]
= XLRealloc (atom_table.names[hash],
bucket_length * sizeof *atom_table.names);
atom_table.atoms[hash]
= XLRealloc (atom_table.atoms[hash],
bucket_length * sizeof *atom_table.atoms);
atom_table.names[hash][bucket_length - 1] = XLStrdup (name);
atom_table.atoms[hash][bucket_length - 1] = atom;
}
void
XLInitAtoms (void)
{
Atom atoms[ArrayElements (names)];
if (!XInternAtoms (compositor.display, (char **) names,
ArrayElements (names), False,
atoms))
{
fprintf (stderr, "Failed to intern X atoms\n");
exit (1);
}
_NET_WM_OPAQUE_REGION = atoms[0];
_XL_BUFFER_RELEASE = atoms[1];
_NET_WM_SYNC_REQUEST_COUNTER = atoms[2];
_NET_WM_FRAME_DRAWN = atoms[3];
WM_DELETE_WINDOW = atoms[4];
WM_PROTOCOLS = atoms[5];
_NET_SUPPORTING_WM_CHECK = atoms[6];
_NET_SUPPORTED = atoms[7];
_NET_WM_SYNC_REQUEST = atoms[8];
_MOTIF_WM_HINTS = atoms[9];
_NET_WM_STATE_MAXIMIZED_VERT = atoms[10];
_NET_WM_STATE_MAXIMIZED_HORZ = atoms[11];
_NET_WM_STATE_FOCUSED = atoms[12];
_NET_WM_STATE_FULLSCREEN = atoms[13];
_NET_WM_STATE = atoms[14];
_NET_WM_MOVERESIZE = atoms[15];
_GTK_FRAME_EXTENTS = atoms[16];
WM_TRANSIENT_FOR = atoms[17];
_XL_DMA_BUF_CREATED = atoms[18];
_GTK_SHOW_WINDOW_MENU = atoms[19];
_NET_WM_ALLOWED_ACTIONS = atoms[20];
_NET_WM_ACTION_FULLSCREEN = atoms[21];
_NET_WM_ACTION_MAXIMIZE_HORZ = atoms[22];
_NET_WM_ACTION_MAXIMIZE_VERT = atoms[23];
_NET_WM_ACTION_MINIMIZE = atoms[24];
INCR = atoms[25];
CLIPBOARD = atoms[26];
TARGETS = atoms[27];
UTF8_STRING = atoms[28];
_XL_SERVER_TIME_ATOM = atoms[29];
MULTIPLE = atoms[30];
TIMESTAMP = atoms[31];
ATOM_PAIR = atoms[32];
_NET_WM_NAME = atoms[33];
WM_NAME = atoms[34];
MANAGER = atoms[35];
_XSETTINGS_SETTINGS = atoms[36];
libinput_Scroll_Methods_Available = atoms[37];
XdndAware = atoms[38];
XdndSelection = atoms[39];
XdndTypeList = atoms[40];
XdndActionCopy = atoms[41];
XdndActionMove = atoms[42];
XdndActionLink = atoms[43];
XdndActionAsk = atoms[44];
XdndActionPrivate = atoms[45];
XdndActionList = atoms[46];
XdndActionDescription = atoms[47];
XdndProxy = atoms[48];
XdndEnter = atoms[49];
XdndPosition = atoms[50];
XdndStatus = atoms[51];
XdndLeave = atoms[52];
XdndDrop = atoms[53];
XdndFinished = atoms[54];
_NET_WM_FRAME_TIMINGS = atoms[55];
_NET_WM_BYPASS_COMPOSITOR = atoms[56];
WM_STATE = atoms[57];
_NET_WM_WINDOW_TYPE = atoms[58];
_NET_WM_WINDOW_TYPE_MENU = atoms[59];
_NET_WM_WINDOW_TYPE_DND = atoms[60];
CONNECTOR_ID = atoms[61];
/* This is automatically generated. */
DirectTransferAtomInit (atoms, 62);
/* Now, initialize quarks. */
resource_quark = XrmPermStringToQuark (compositor.resource_name);
app_quark = XrmPermStringToQuark (compositor.app_name);
QString = XrmPermStringToQuark ("String");
}