diff --git a/12to11.conf b/12to11.conf index cb7f974..220e48f 100644 --- a/12to11.conf +++ b/12to11.conf @@ -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 diff --git a/12to11.man b/12to11.man index dd7c83b..2a4fb56 100644 --- a/12to11.man +++ b/12to11.man @@ -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 diff --git a/Imakefile b/Imakefile index 59363eb..a6db4f9 100644 --- a/Imakefile +++ b/Imakefile @@ -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. */ diff --git a/compositor.h b/compositor.h index 7916b37..b8ebee1 100644 --- a/compositor.h +++ b/compositor.h @@ -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); diff --git a/fns.c b/fns.c index ca3e44d..0fad5e7 100644 --- a/fns.c +++ b/fns.c @@ -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) diff --git a/frame_clock.c b/frame_clock.c index 70e92e1..48933a5 100644 --- a/frame_clock.c +++ b/frame_clock.c @@ -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. */ diff --git a/picture_renderer.c b/picture_renderer.c index b16cffd..8aafd29 100644 --- a/picture_renderer.c +++ b/picture_renderer.c @@ -26,6 +26,7 @@ along with 12to11. If not, see . */ #include #include "compositor.h" +#include "drm_modifiers.h" #include @@ -37,6 +38,7 @@ along with 12to11. If not, see . */ 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); diff --git a/subcompositor.c b/subcompositor.c index 0d7e151..be55614 100644 --- a/subcompositor.c +++ b/subcompositor.c @@ -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) { diff --git a/svnignore.txt b/svnignore.txt index 3d21340..905b3bd 100644 --- a/svnignore.txt +++ b/svnignore.txt @@ -13,3 +13,4 @@ Makefile vgcore* massif* callgrind* +drm_modifiers.h diff --git a/transform.c b/transform.c index a11493e..6e3b268 100644 --- a/transform.c +++ b/transform.c @@ -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; + } +}