forked from 12to11/12to11

Note that the EGL renderer has been broken by these changes. * compositor.h (struct _RenderFuncs): Change arguments to `finish_render'. Add `cancel_completion_callback'. Remove `cancel_presentation'. (struct _BufferFuncs): Add `is_buffer_opaque'. * egl.c: Note that the EGL renderer is currently broken. * fence_ring.c (FenceFree, struct _Fence, GetFence, FenceAwait) (FenceToXFence): Repurpose fence code as a generic allocator of fences. * frame_clock.c (EndFrame): Adjust calculation of even value. * picture_renderer.c (struct _BufferActivityRecord): Remove `fence'. (struct _PictureBuffer): Remove unused field. (struct _PresentCompletionCallback): Remove unused fields linking it to the target. (struct _BackBuffer): New structure. (IsBufferBusy, SetBufferBusy, ClearBufferBusy): New macros. (struct _PictureTarget): Add back buffer and GC fields. (use_sync_fences): Remove variable. (RecordBufferActivity): Don't take fence. (UnlinkActivityRecord): Don't wait on fence. (FreeBackBuffer, FreeBackBuffers, CreateBackBuffer) (MakePresentationCallback, SwapBackBuffers) (SwapBackBuffersWithCopy, MaybeAwaitBuffer, GetNextBackBuffer) (EnsurePicture): New functions. (TargetFromDrawable): Don't create picture for window targets, and create GC for those. (NoteTargetSize): Free back buffers instead of creating presentation windows. (DestroyRenderTarget): Free back buffers. (ViewContainsExtents): Delete function. (FinishRender): Swap back buffers and handle callbacks. (CancelCompletionCallback): New function. (TargetAge): Implement accordingly. (PresentToWindow, CancelPresentationCallback): Present to the regular window instead of a separate ``presentation window''. (CancelPresentation): Remove function. (picture_render_funcs): Add CancelCompletionCallback; remove NeverAges and CancelPresentation. (BufferFromDmaBuf, FinishDmaBufRecord, BufferFromShm): Set opaque flag accordingly. (IsBufferOpaque): New function. (picture_buffer_funcs): Add IsBufferOpaque. (HandlePresentCompleteNotify, HandlePresentIdleNotify): Handle back buffer release. * renderer.c (RenderFinishRender, RenderCancelCompletionCallback) (RenderCancelPresentation, RenderIsBufferOpaque): Adjust accordingly. * seat.c (InterpolateAxes): Fix NULL-pointer dereference. * subcompositor.c (SetFrozen, IsFrozen): Get rid of unused state. (struct _View): Cache the width and height. Add cull_region field. (struct _Subcompositor): Add `render_key' field. (ViewAfterSizeUpdate): Set cached width and height. (ViewAttachBuffer): Correctly handle size changes. (ViewDamage): Apply buffer damage. (ViewDamageBuffer): use ViewDamage. (ApplyBufferDamage): New function.:(FillBoxesWithTransparency, ViewContainsExtents, IntersectBoxes): Delete unused functions. (RenderCompletedCallback): New function. (NoViewsAfter): Delete function. (SkipSlug): New slug. (SubcompositorUpdateAncillary, TryPresent, AnyParentUnmapped) (DoCull, DrawBackground, CompositeSingleView, InitBackground) (SubcompositorComposite1, SubcompositorComposite): New functions. Implement new redisplay logic here. (SubcompositorUpdate, CopyRegion): New function. (SubcompositorExpose, SubcompositorFree): Clear render callback if set. (SubcompositorLookupView): Use cached width and height. (SubcompositorFreeze, SubcompositorUnfreeze): Remove unused functions. * time.c (InitTime): Fix use of uninitialized value initializing the Sync extension. * transform.c (TransformBox): Pacify compiler warning.
419 lines
10 KiB
C
419 lines
10 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/>. */
|
|
|
|
/* Generic 3x3 matrix transform code. */
|
|
|
|
#include <string.h>
|
|
#include <stdio.h>
|
|
|
|
#include "compositor.h"
|
|
|
|
#include <X11/extensions/Xrender.h>
|
|
|
|
/* These macros make column major order easier to reason about for C
|
|
folks. */
|
|
#define Index(matrix, row, column) \
|
|
((matrix)[(column) * 3 + (row)])
|
|
|
|
#define MultiplySub(a, b, a_row, a_column, b_row, b_column) \
|
|
(Index (a, a_row, a_column) * Index (b, b_row, b_column))
|
|
|
|
#if 0
|
|
|
|
static void
|
|
MatrixPrint (Matrix *matrix)
|
|
{
|
|
fprintf (stderr,
|
|
"%4f %4f %4f\n"
|
|
"%4f %4f %4f\n"
|
|
"%4f %4f %4f\n\n",
|
|
(double) Index (*matrix, 0, 0),
|
|
(double) Index (*matrix, 0, 1),
|
|
(double) Index (*matrix, 0, 2),
|
|
(double) Index (*matrix, 1, 0),
|
|
(double) Index (*matrix, 1, 1),
|
|
(double) Index (*matrix, 1, 2),
|
|
(double) Index (*matrix, 2, 0),
|
|
(double) Index (*matrix, 2, 1),
|
|
(double) Index (*matrix, 2, 2));
|
|
}
|
|
|
|
#endif
|
|
|
|
void
|
|
MatrixMultiply (Matrix a, Matrix b, Matrix *product)
|
|
{
|
|
Index (*product, 0, 0) = (MultiplySub (a, b, 0, 0, 0, 0)
|
|
+ MultiplySub (a, b, 0, 1, 1, 0)
|
|
+ MultiplySub (a, b, 0, 2, 2, 0));
|
|
Index (*product, 0, 1) = (MultiplySub (a, b, 0, 0, 0, 1)
|
|
+ MultiplySub (a, b, 0, 1, 1, 1)
|
|
+ MultiplySub (a, b, 0, 2, 2, 1));
|
|
Index (*product, 0, 2) = (MultiplySub (a, b, 0, 0, 0, 2)
|
|
+ MultiplySub (a, b, 0, 1, 1, 2)
|
|
+ MultiplySub (a, b, 0, 2, 2, 2));
|
|
|
|
Index (*product, 1, 0) = (MultiplySub (a, b, 1, 0, 0, 0)
|
|
+ MultiplySub (a, b, 1, 1, 1, 0)
|
|
+ MultiplySub (a, b, 1, 2, 2, 0));
|
|
Index (*product, 1, 1) = (MultiplySub (a, b, 1, 0, 0, 1)
|
|
+ MultiplySub (a, b, 1, 1, 1, 1)
|
|
+ MultiplySub (a, b, 1, 2, 2, 1));
|
|
Index (*product, 1, 2) = (MultiplySub (a, b, 1, 0, 0, 2)
|
|
+ MultiplySub (a, b, 1, 1, 1, 2)
|
|
+ MultiplySub (a, b, 1, 2, 2, 2));
|
|
|
|
Index (*product, 2, 0) = (MultiplySub (a, b, 2, 0, 0, 0)
|
|
+ MultiplySub (a, b, 2, 1, 1, 0)
|
|
+ MultiplySub (a, b, 2, 2, 2, 0));
|
|
Index (*product, 2, 1) = (MultiplySub (a, b, 2, 0, 0, 1)
|
|
+ MultiplySub (a, b, 2, 1, 1, 1)
|
|
+ MultiplySub (a, b, 2, 2, 2, 1));
|
|
Index (*product, 2, 2) = (MultiplySub (a, b, 2, 0, 0, 2)
|
|
+ MultiplySub (a, b, 2, 1, 1, 2)
|
|
+ MultiplySub (a, b, 2, 2, 2, 2));
|
|
}
|
|
|
|
void
|
|
MatrixIdentity (Matrix *matrix)
|
|
{
|
|
memset (matrix, 0, sizeof *matrix);
|
|
|
|
Index (*matrix, 0, 0) = 1.0f;
|
|
Index (*matrix, 1, 1) = 1.0f;
|
|
Index (*matrix, 2, 2) = 1.0f;
|
|
}
|
|
|
|
void
|
|
MatrixTranslate (Matrix *transform, float tx, float ty)
|
|
{
|
|
Matrix temp, copy;
|
|
|
|
MatrixIdentity (&temp);
|
|
memcpy (copy, transform, sizeof copy);
|
|
|
|
/* Set the tx and ty. */
|
|
Index (temp, 0, 2) = tx;
|
|
Index (temp, 1, 2) = ty;
|
|
|
|
/* Multiply it with the transform. */
|
|
MatrixMultiply (copy, temp, transform);
|
|
}
|
|
|
|
void
|
|
MatrixScale (Matrix *transform, float sx, float sy)
|
|
{
|
|
Matrix temp, copy;
|
|
|
|
MatrixIdentity (&temp);
|
|
memcpy (copy, transform, sizeof copy);
|
|
|
|
/* Set the scale factors. */
|
|
Index (temp, 0, 0) = sx;
|
|
Index (temp, 1, 1) = sy;
|
|
|
|
/* Multiply it with the transform. */
|
|
MatrixMultiply (copy, temp, transform);
|
|
}
|
|
|
|
void
|
|
MatrixRotate (Matrix *transform, float theta, float x, float y)
|
|
{
|
|
Matrix temp, copy;
|
|
|
|
/* Translate the matrix to x, y, and then perform rotation by the
|
|
given angle in radians and translate back. As the transform is
|
|
being performed in the X coordinate system, the given angle
|
|
describes a clockwise rotation. */
|
|
|
|
MatrixIdentity (&temp);
|
|
memcpy (copy, transform, sizeof copy);
|
|
|
|
Index (temp, 0, 2) = x;
|
|
Index (temp, 1, 2) = y;
|
|
|
|
MatrixMultiply (copy, temp, transform);
|
|
MatrixIdentity (&temp);
|
|
memcpy (copy, transform, sizeof copy);
|
|
|
|
Index (temp, 0, 0) = cosf (theta);
|
|
Index (temp, 0, 1) = sinf (theta);
|
|
Index (temp, 1, 0) = -sinf (theta);
|
|
Index (temp, 1, 1) = cosf (theta);
|
|
|
|
MatrixMultiply (copy, temp, transform);
|
|
MatrixIdentity (&temp);
|
|
memcpy (copy, transform, sizeof copy);
|
|
|
|
Index (temp, 0, 2) = -x;
|
|
Index (temp, 1, 2) = -y;
|
|
|
|
MatrixMultiply (copy, temp, transform);
|
|
}
|
|
|
|
void
|
|
MatrixMirrorHorizontal (Matrix *transform, float width)
|
|
{
|
|
Matrix temp, copy;
|
|
|
|
/* Scale the matrix by -1, and then apply a tx of width, in effect
|
|
flipping the image horizontally. */
|
|
|
|
MatrixIdentity (&temp);
|
|
memcpy (copy, transform, sizeof copy);
|
|
|
|
Index (temp, 0, 0) = -1.0f;
|
|
Index (temp, 0, 2) = width;
|
|
|
|
MatrixMultiply (copy, temp, transform);
|
|
}
|
|
|
|
void
|
|
MatrixExport (Matrix *transform, XTransform *xtransform)
|
|
{
|
|
/* M1 M2 M3 X
|
|
M4 M5 M6 * Y
|
|
M7 M8 M9 Z
|
|
|
|
=
|
|
|
|
M1*X + M2*Y + M3*1 = X1
|
|
M4*X + M5*Y + M6*1 = Y1
|
|
M7*X + M8*Y + M9*1 = Z1 (Only on some drivers)
|
|
|
|
where
|
|
|
|
M1 = matrix[0][0]
|
|
M2 = matrix[0][1]
|
|
M3 = matrix[0][2]
|
|
M4 = matrix[1][0]
|
|
M5 = matrix[1][1]
|
|
M6 = matrix[1][2]
|
|
M7 = matrix[2][0]
|
|
M8 = matrix[2][1]
|
|
M9 = matrix[2][2] */
|
|
|
|
#define Export(row, column) \
|
|
xtransform->matrix[row][column] \
|
|
= XDoubleToFixed (Index (*transform, row, column))
|
|
|
|
Export (0, 0);
|
|
Export (0, 1);
|
|
Export (0, 2);
|
|
|
|
Export (1, 0);
|
|
Export (1, 1);
|
|
Export (1, 2);
|
|
|
|
Export (2, 0);
|
|
Export (2, 1);
|
|
Export (2, 2);
|
|
|
|
#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:
|
|
default:
|
|
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;
|
|
}
|
|
}
|