Allow the user to manually specify format modifiers

* 12to11.conf (DRMFOURCCH): New variable.
* 12to11.man: Document new resource.
* Imakefile (GENHEADERS): Add
drm_modifiers.h.:(drm_modifiers.h): New target.
(cleandir): Clean up.
* compositor.h: Update prototypes.
* fns.c (TransformBox): Move to transform.c.
* frame_clock.c (PostEndFrame): Use 200 us, since 100 us is not
always enough.
* picture_renderer.c (struct _DrmModifierName): New structure.
(known_modifiers): New array.
(AddAdditionalModifier, ParseAdditionalModifiers)
(InitAdditionalModifiers): New functions.
(InitRenderFuncs): Call them.
(ApplyInverseTransform): Accept buffer width and height instead
of PictureBuffer.  Move to transform.c.
(MaybeApplyTransform): Adjust calls.
(FindSupportedModifiers, InitDrmFormats): Stop adding the linear
format by default, and let the user specify it instead.
* subcompositor.c (InvertTransform): Move to transform.c.
* svnignore.txt: Add new generated header.
* transform.c (ApplyInverseTransform, TransformBox)
(InvertTransform): Move some functions here as they will be used
in the EGL backend.
This commit is contained in:
hujianwei 2022-10-26 06:48:59 +00:00
parent 8e4391f941
commit 0b5d44537b
10 changed files with 381 additions and 177 deletions

View file

@ -10,6 +10,7 @@
XCBLIB = -lX11-xcb
PIXMAN = -lpixman-1
DRM = -ldrm
DRMFOURCCH = $(INCROOT)/drm/drm_fourcc.h
DRMINCLUDES = -I$(INCROOT)/drm
PIXMANINCLUDES = -I$(INCROOT)/pixman-1
XPRESENTLIB = -lXpresent

View file

@ -160,6 +160,23 @@ the first process exits.
The number of seconds the protocol translator waits between
invocations of the command specified in \fBidleIntervalCommand\fP.
Defaults to 60.
.TP
.B additionalModifiersOfScreen\fP\fINUMBER\fP (class \fBAdditionalModifiers\fP)
A comma-separated list of additional DRM modifiers that can be applied
to each format. These modifiers must be specified by their names
inside the `drm_fourcc.h' system header, and should be used if your X
graphics driver fails to report which modifiers are available.
\fINUMBER\fP should be replaced with the number of the screen on which
the protocol translator is running.
On 9th Generation Intel systems, for example, you may want to set this
to:
.IP
.in +4
.EX
\fB12to11.AdditionalModifiers: I915_FORMAT_MOD_X_TILED,DRM_FORMAT_MOD_LINEAR\fP
.EE
.in
.IP
.SH ENVIRONMENT
Several environment variables exist that modify the behavior of the

View file

@ -39,7 +39,7 @@ OBJS = 12to11.o run.o alloc.o fns.o output.o compositor.o \
time.o relative_pointer.o keyboard_shortcuts_inhibit.o \
idle_inhibit.o process.o fence_ring.o
GENHEADERS = transfer_atoms.h
GENHEADERS = transfer_atoms.h drm_modifiers.h
#ifdef HaveEglSupport
@ -98,6 +98,9 @@ transfer_atoms.h: short_types.txt mime0.awk mime1.awk mime2.awk mime3.awk \
awk -f mime3.awk short_types.txt >> $@
awk -f mime4.awk short_types.txt >> $@
drm_modifiers.h: modifiers.awk $(DRMFOURCCH)
awk -f modifiers.awk $(DRMFOURCCH) > $@
/* Now, define generated files. */
#define ScannerTarget(name) @@\
@ -134,8 +137,7 @@ $(OBJS): $(GENHEADERS)
depend:: $(GENHEADERS) $(SRCS)
cleandir::
$(RM) $(GENHEADERS) $(GENSRCS) transfer_atoms.h short_types.txt \
12to11.tar.gz
$(RM) $(GENHEADERS) $(GENSRCS) short_types.txt 12to11.tar.gz
/* Undefine _BSD_SOURCE and _SVID_SOURCE, since both are deprecated
and are also superseeded by _GNU_SOURCE. */

View file

@ -1695,6 +1695,11 @@ extern void MatrixExport (Matrix *, XTransform *);
extern void MatrixRotate (Matrix *, float, float, float);
extern void MatrixMirrorHorizontal (Matrix *, float);
extern void ApplyInverseTransform (int, int, Matrix *,
BufferTransform, Bool);
extern void TransformBox (pixman_box32_t *, BufferTransform, int, int);
extern BufferTransform InvertTransform (BufferTransform);
/* Defined in wp_viewporter.c. */
extern void XLInitWpViewporter (void);

65
fns.c
View file

@ -403,71 +403,6 @@ XLExtendRegion (pixman_region32_t *dst, pixman_region32_t *src,
XLFree (dst_rects);
}
static void
TransformBox (pixman_box32_t *box, BufferTransform transform,
int width, int height)
{
pixman_box32_t work;
switch (transform)
{
case Normal:
work = *box;
break;
case CounterClockwise90:
work.x1 = height - box->y2;
work.y1 = box->x1;
work.x2 = height - box->y1;
work.y2 = box->x2;
break;
case CounterClockwise180:
work.x1 = width - box->x2;
work.y1 = height - box->y2;
work.x2 = width - box->x1;
work.y2 = height - box->y1;
break;
case CounterClockwise270:
work.x1 = box->y1;
work.y1 = width - box->x2;
work.x2 = box->y2;
work.y2 = width - box->x1;
break;
case Flipped:
work.x1 = width - box->x2;
work.y1 = box->y1;
work.x2 = width - box->x1;
work.y2 = box->y2;
break;
case Flipped90:
work.x1 = box->y1;
work.y1 = box->x1;
work.x2 = box->y2;
work.y2 = box->x2;
break;
case Flipped180:
work.x1 = box->x1;
work.y1 = height - box->y2;
work.x2 = box->x2;
work.y2 = height - box->y1;
break;
case Flipped270:
work.x1 = height - box->y2;
work.y1 = width - box->x2;
work.x2 = height - box->y1;
work.y2 = width - box->x1;
break;
}
*box = work;
}
void
XLTransformRegion (pixman_region32_t *dst, pixman_region32_t *src,
BufferTransform transform, int width, int height)

View file

@ -353,9 +353,9 @@ PostEndFrame (FrameClock *clock)
/* The vertical blanking period itself can't actually be computed
based on available data. However, frame_delay must be inside the
vertical blanking period for it to make any sense, so use it to
compute the deadline instead. Add about 100 us to the frame
compute the deadline instead. Add about 200 us to the frame
delay to compensate for the roundtrip time. */
target -= clock->frame_delay - 100;
target -= clock->frame_delay - 200;
/* Add the remainder of now if it was probably truncated by the
compositor. */

View file

@ -26,6 +26,7 @@ along with 12to11. If not, see <https://www.gnu.org/licenses/>. */
#include <drm_fourcc.h>
#include "compositor.h"
#include "drm_modifiers.h"
#include <xcb/dri3.h>
@ -37,6 +38,7 @@ along with 12to11. If not, see <https://www.gnu.org/licenses/>. */
typedef struct _DrmFormatInfo DrmFormatInfo;
typedef struct _DmaBufRecord DmaBufRecord;
typedef struct _DrmModifierName DrmModifierName;
typedef struct _PictureBuffer PictureBuffer;
typedef struct _PictureTarget PictureTarget;
@ -46,6 +48,15 @@ typedef struct _BufferActivityRecord BufferActivityRecord;
typedef struct _IdleCallback IdleCallback;
typedef struct _PresentCompletionCallback PresentCompletionCallback;
struct _DrmModifierName
{
/* The modifier name. */
const char *name;
/* The modifier code. */
uint64_t modifier;
};
/* Structure describing an expected PresentIdleNotify from the X
server. */
@ -277,6 +288,12 @@ struct _DmaBufRecord
short width, height;
};
/* Number of format modifiers specified by the user. */
static int num_specified_modifiers;
/* Array of user-specified format modifiers. */
static uint64_t *user_specified_modifiers;
/* Hash table mapping between presentation windows and targets. */
static XLAssocTable *xid_table;
@ -360,6 +377,13 @@ static DrmFormatInfo all_formats[] =
},
};
/* Array of all known DRM modifier names. */
static DrmModifierName known_modifiers[] =
{
/* Generated from drm_fourcc.h. */
DrmModifiersList
};
/* DRM formats reported to the caller. */
static DrmFormat *drm_formats;
@ -741,6 +765,112 @@ InitSynchronizedPresentation (void)
use_direct_presentation = True;
}
static void
AddAdditionalModifier (const char *name)
{
int i, j;
for (i = 0; i < ArrayElements (known_modifiers) - 1; ++i)
{
if (!strcmp (known_modifiers[i].name, name))
{
/* The modifier was found. See if it already exists. */
for (j = 0; j < num_specified_modifiers; ++j)
{
if (user_specified_modifiers[j]
== known_modifiers[i].modifier)
/* The modifier was already specified. */
return;
}
/* Otherwise, increment num_specified_modifiers. */
num_specified_modifiers++;
/* Make user_specified_modifiers big enough. */
user_specified_modifiers
= XLRealloc (user_specified_modifiers,
num_specified_modifiers
* sizeof *user_specified_modifiers);
/* And add the modifier. */
user_specified_modifiers[num_specified_modifiers - 1]
= known_modifiers[i].modifier;
return;
}
}
fprintf (stderr, "Unknown buffer format modifier: %s\n", name);
}
static void
ParseAdditionalModifiers (const char *string)
{
const char *end, *sep;
char *buffer;
end = string + strlen (string);
while (string < end)
{
/* Find the next comma. */
sep = strchr (string, ',');
if (!sep)
sep = end;
/* Copy the text between string and sep into buffer. */
buffer = alloca (sep - string + 1);
memcpy (buffer, string, sep - string);
buffer[sep - string] = '\0';
/* Add this modifier. */
AddAdditionalModifier (buffer);
string = sep + 1;
}
}
static void
InitAdditionalModifiers (void)
{
XrmDatabase rdb;
XrmName namelist[3];
XrmClass classlist[3];
XrmValue value;
XrmRepresentation type;
char *name;
rdb = XrmGetDatabase (compositor.display);
if (!rdb)
return;
if (!asprintf (&name, "additionalModifiersOfScreen%d",
DefaultScreen (compositor.display)))
return;
namelist[1] = XrmStringToQuark (name);
free (name);
namelist[0] = app_quark;
namelist[2] = NULLQUARK;
classlist[1] = XrmStringToQuark ("AdditionalModifiers");
classlist[0] = resource_quark;
classlist[2] = NULLQUARK;
/* Enable the use of direct presentation if
*.UseDirectPresentation.*.useDirectPresentation is true. This is
still incomplete, as the features necessary for it to play nice
with frame synchronization have not yet been implemented in the X
server. */
if (XrmQGetResource (rdb, namelist, classlist,
&type, &value)
&& type == QString)
ParseAdditionalModifiers ((const char *) value.addr);
}
/* Forward declaration. */
static void AddRenderFlag (int);
@ -769,6 +899,9 @@ InitRenderFuncs (void)
presentation. */
InitSynchronizedPresentation ();
/* Find out what additional modifiers the user wants. */
InitAdditionalModifiers ();
if (use_direct_presentation)
AddRenderFlag (SupportsDirectPresent);
@ -1166,82 +1299,6 @@ CompareStretch (DrawParams *params, DrawParams *other)
return True;
}
static void
ApplyInverseTransform (PictureBuffer *buffer, Matrix *matrix,
BufferTransform transform)
{
float width, height;
/* Note that the transform is applied in reverse, meaning that a
counterclockwise rotation is done clockwise, etc, as TRANSFORM
transforms destination coordinates to source ones. */
width = buffer->width;
height = buffer->height;
switch (transform)
{
case Normal:
break;
case CounterClockwise90:
/* Apply clockwise 270 degree rotation around the origin. */
MatrixRotate (matrix, M_PI * 1.5, 0, 0);
/* Translate y by the width. */
MatrixTranslate (matrix, 0, -width);
break;
case CounterClockwise180:
/* Apply clockwise 180 degree rotation around the center. */
MatrixRotate (matrix, M_PI, width / 2.0f, height / 2.0f);
break;
case CounterClockwise270:
/* Apply clockwise 90 degree rotation around the origin. */
MatrixRotate (matrix, M_PI * 0.5, 0, 0);
/* Translate by the height. */
MatrixTranslate (matrix, -height, 0);
break;
case Flipped:
/* Apply horizontal flip. */
MatrixMirrorHorizontal (matrix, width);
break;
case Flipped90:
/* Apply horizontal flip. */
MatrixMirrorHorizontal (matrix, width);
/* Apply clockwise 90 degree rotation around the origin. */
MatrixRotate (matrix, M_PI * 0.5, 0, 0);
/* Translate by the height. */
MatrixTranslate (matrix, -height, 0);
break;
case Flipped180:
/* Apply horizontal flip. */
MatrixMirrorHorizontal (matrix, width);
/* Apply clockwise 180 degree rotation around the center. */
MatrixRotate (matrix, M_PI, width / 2.0f, height / 2.0f);
break;
case Flipped270:
/* Apply horizontal flip. */
MatrixMirrorHorizontal (matrix, width);
/* Apply clockwise 270 degree rotation around the origin. */
MatrixRotate (matrix, M_PI * 1.5, 0, 0);
/* Translate y by the width. */
MatrixTranslate (matrix, 0, -width);
break;
}
}
static void
MaybeApplyTransform (PictureBuffer *buffer, DrawParams *params)
{
@ -1268,8 +1325,9 @@ MaybeApplyTransform (PictureBuffer *buffer, DrawParams *params)
MatrixIdentity (&ftransform);
if (params->flags & TransformSet)
ApplyInverseTransform (buffer, &ftransform,
params->transform);
ApplyInverseTransform (buffer->width, buffer->height,
&ftransform, params->transform,
False);
/* Note that these must be applied in the right order. First,
the scale is applied. Then, the offset, and finally the
@ -1796,8 +1854,9 @@ FindSupportedModifiers (int *pair_count_return)
/* pair_count is the number of format-modifier pairs that
will be returned. First, add one for each implicit
modifier, and another one for the linear modifier. */
pair_count += 2;
modifier, and another one for each manually specified
modifier. */
pair_count += 1 + num_specified_modifiers;
}
}
@ -1844,7 +1903,7 @@ FindSupportedModifiers (int *pair_count_return)
static void
InitDrmFormats (void)
{
int pair_count, i, j, n;
int pair_count, i, j, n, k;
/* First, look up which formats are supported. */
if (!FindSupportedFormats ())
@ -1872,24 +1931,35 @@ InitDrmFormats (void)
drm_formats[n].drm_modifier = DRM_FORMAT_MOD_INVALID;
n++;
/* Check n < pair_count. */
XLAssert (n < pair_count);
/* And add all of the user-specified modifiers. */
for (j = 0; j < num_specified_modifiers; ++j)
{
/* Assert that n < pair_count. */
XLAssert (n < pair_count);
/* And the linear modifier. */
drm_formats[n].drm_format = all_formats[i].format_code;
drm_formats[n].drm_modifier = DRM_FORMAT_MOD_LINEAR;
n++;
drm_formats[n].drm_format = all_formats[i].format_code;
drm_formats[n].drm_modifier = user_specified_modifiers[j];
n++;
}
/* Now add every supported explicit modifier. */
for (j = 0; j < all_formats[i].n_supported_modifiers; ++i)
{
/* Ignore previously specified modifiers. */
if ((all_formats[i].supported_modifiers[j]
== DRM_FORMAT_MOD_INVALID)
|| (all_formats[i].supported_modifiers[j]
== DRM_FORMAT_MOD_LINEAR))
/* Ignore previously specified modifiers. */
== DRM_FORMAT_MOD_INVALID))
continue;
/* Ignore user-specified modifiers. */
for (k = 0; k < num_specified_modifiers; ++k)
{
if (user_specified_modifiers[k]
== all_formats[i].supported_modifiers[j])
continue;
}
/* Check n < pair_count. */
XLAssert (n < pair_count);

View file

@ -1632,22 +1632,6 @@ GetContentScale (int scale)
return -scale + 1;
}
static BufferTransform
InvertTransform (BufferTransform transform)
{
switch (transform)
{
case CounterClockwise270:
return CounterClockwise90;
case CounterClockwise90:
return CounterClockwise270;
default:
return transform;
}
}
static int
BufferWidthAfterTransform (View *view)
{

View file

@ -13,3 +13,4 @@ Makefile
vgcore*
massif*
callgrind*
drm_modifiers.h

View file

@ -227,3 +227,192 @@ MatrixExport (Matrix *transform, XTransform *xtransform)
#undef Export
}
/* Various routines shared between renderers. */
void
ApplyInverseTransform (int buffer_width, int buffer_height, Matrix *matrix,
BufferTransform transform, Bool cartesian)
{
float width, height;
/* Note that the transform is applied in reverse, meaning that a
counterclockwise rotation is done clockwise, etc, as TRANSFORM
transforms destination coordinates to source ones. CARTESIAN
specifies whether or not an actual cartesian coordinate system is
being used. */
width = buffer_width;
height = buffer_height;
switch (transform)
{
case Normal:
break;
case CounterClockwise90:
if (!cartesian)
{
/* Apply clockwise 270 degree rotation around the
origin. */
MatrixRotate (matrix, M_PI * 1.5, 0, 0);
/* Translate y by the width. */
MatrixTranslate (matrix, 0, -width);
}
else
{
/* Apply clockwise 270 degree rotation around the
origin. */
MatrixRotate (matrix, M_PI * 0.5, 0, 1);
/* Translate by the width. */
MatrixTranslate (matrix, 0, width);
}
break;
case CounterClockwise180:
/* Apply clockwise 180 degree rotation around the center. */
MatrixRotate (matrix, M_PI, width / 2.0f, height / 2.0f);
break;
case CounterClockwise270:
if (!cartesian)
{
/* Apply clockwise 90 degree rotation around the origin. */
MatrixRotate (matrix, M_PI * 0.5, 0, 0);
/* Translate by the height. */
MatrixTranslate (matrix, -height, 0);
}
else
{
/* Apply clockwise 90 degree rotation around the origin. */
MatrixRotate (matrix, M_PI * 1.5, 0, 1);
/* Translate by the height. */
MatrixTranslate (matrix, -height, 0);
}
break;
case Flipped:
/* Apply horizontal flip. */
MatrixMirrorHorizontal (matrix, width);
break;
case Flipped90:
/* Apply horizontal flip. */
MatrixMirrorHorizontal (matrix, width);
/* Apply clockwise 90 degree rotation around the origin. */
MatrixRotate (matrix, M_PI * 0.5, 0, 0);
/* Translate by the height. */
MatrixTranslate (matrix, -height, 0);
break;
case Flipped180:
/* Apply horizontal flip. */
MatrixMirrorHorizontal (matrix, width);
/* Apply clockwise 180 degree rotation around the center. */
MatrixRotate (matrix, M_PI, width / 2.0f, height / 2.0f);
break;
case Flipped270:
/* Apply horizontal flip. */
MatrixMirrorHorizontal (matrix, width);
/* Apply clockwise 270 degree rotation around the origin. */
MatrixRotate (matrix, M_PI * 1.5, 0, 0);
/* Translate y by the width. */
MatrixTranslate (matrix, 0, -width);
break;
}
}
void
TransformBox (pixman_box32_t *box, BufferTransform transform,
int width, int height)
{
pixman_box32_t work;
switch (transform)
{
case Normal:
work = *box;
break;
case CounterClockwise90:
work.x1 = height - box->y2;
work.y1 = box->x1;
work.x2 = height - box->y1;
work.y2 = box->x2;
break;
case CounterClockwise180:
work.x1 = width - box->x2;
work.y1 = height - box->y2;
work.x2 = width - box->x1;
work.y2 = height - box->y1;
break;
case CounterClockwise270:
work.x1 = box->y1;
work.y1 = width - box->x2;
work.x2 = box->y2;
work.y2 = width - box->x1;
break;
case Flipped:
work.x1 = width - box->x2;
work.y1 = box->y1;
work.x2 = width - box->x1;
work.y2 = box->y2;
break;
case Flipped90:
work.x1 = box->y1;
work.y1 = box->x1;
work.x2 = box->y2;
work.y2 = box->x2;
break;
case Flipped180:
work.x1 = box->x1;
work.y1 = height - box->y2;
work.x2 = box->x2;
work.y2 = height - box->y1;
break;
case Flipped270:
work.x1 = height - box->y2;
work.y1 = width - box->x2;
work.x2 = height - box->y1;
work.y2 = width - box->x1;
break;
}
*box = work;
}
BufferTransform
InvertTransform (BufferTransform transform)
{
switch (transform)
{
case CounterClockwise270:
return CounterClockwise90;
case CounterClockwise90:
return CounterClockwise270;
default:
return transform;
}
}