forked from 12to11/12to11
Fix and implement transforms in the EGL renderer
* 12to11.c (XLMain): Initialize Xlib threads. * compositor.h: Update prototype of ApplyInverseTransform. * egl.c (ComputeTransformMatrix): Handle transforms. (Composite): Ensure textures if none were generated. (FinishRender): Take callback and data and return NULL key. (UpdateBuffer): Handle transforms by uploading everything. Suboptimal! (IsBufferOpaque): New function. (egl_buffer_funcs): Add it. * picture_renderer.c (MaybeApplyTransform): Add some comments. * subcompositor.c (TransformBufferDamage): Avoid inverting damage. (ViewDamageBuffer): Directly apply untransformed buffer damage. (ApplyUntransformedDamage): New function. * transform.c (MatrixRotate): Fix minor row ordering error. (ApplyInverseTransform): Adjust accordingly.
This commit is contained in:
parent
b8d26761c1
commit
e001d7cf69
6 changed files with 112 additions and 84 deletions
3
12to11.c
3
12to11.c
|
@ -185,6 +185,9 @@ XLMain (int argc, char **argv)
|
|||
exit (1);
|
||||
}
|
||||
|
||||
/* Initialize Xlib threads. */
|
||||
XInitThreads ();
|
||||
|
||||
/* Call XGetDefault with some dummy values to have the resource
|
||||
database set up. */
|
||||
XrmInitialize ();
|
||||
|
|
|
@ -1711,7 +1711,7 @@ extern void MatrixRotate (Matrix *, float, float, float);
|
|||
extern void MatrixMirrorHorizontal (Matrix *, float);
|
||||
|
||||
extern void ApplyInverseTransform (int, int, Matrix *,
|
||||
BufferTransform, Bool);
|
||||
BufferTransform);
|
||||
extern void TransformBox (pixman_box32_t *, BufferTransform, int, int);
|
||||
extern BufferTransform InvertTransform (BufferTransform);
|
||||
|
||||
|
|
56
egl.c
56
egl.c
|
@ -35,9 +35,6 @@ along with 12to11. If not, see <https://www.gnu.org/licenses/>. */
|
|||
|
||||
#include "linux-dmabuf-unstable-v1.h"
|
||||
|
||||
/* TODO: implement buffer transforms. This renderer is currently
|
||||
broken. */
|
||||
|
||||
/* These are flags for the DrmFormats. */
|
||||
|
||||
enum
|
||||
|
@ -1365,6 +1362,24 @@ ComputeTransformMatrix (EglBuffer *buffer, DrawParams *params)
|
|||
= (float) (1.0 / params->scale);
|
||||
}
|
||||
|
||||
/* Set the rotation. */
|
||||
if (params->flags & TransformSet)
|
||||
{
|
||||
/* Apply the inverse transform. */
|
||||
|
||||
ApplyInverseTransform (1, 1, &buffer->matrix,
|
||||
params->transform);
|
||||
|
||||
/* Since the rotation happened inside the texture coordinate
|
||||
system, scale u and v correctly if dimensions changed. */
|
||||
|
||||
if (RotatesDimensions (params->transform))
|
||||
MatrixScale (&buffer->matrix, ((float) buffer->width
|
||||
/ (float) buffer->height),
|
||||
((float) buffer->height
|
||||
/ (float) buffer->width));
|
||||
}
|
||||
|
||||
/* Set the offsets. */
|
||||
if (params->flags & OffsetSet)
|
||||
MatrixTranslate (&buffer->matrix,
|
||||
|
@ -1379,6 +1394,10 @@ ComputeTransformMatrix (EglBuffer *buffer, DrawParams *params)
|
|||
(float) (params->crop_height / params->stretch_height));
|
||||
}
|
||||
|
||||
/* Forward declaration. */
|
||||
|
||||
static void EnsureTexture (EglBuffer *);
|
||||
|
||||
static void
|
||||
Composite (RenderBuffer buffer, RenderTarget target,
|
||||
Operation op, int src_x, int src_y, int x, int y,
|
||||
|
@ -1396,9 +1415,10 @@ Composite (RenderBuffer buffer, RenderTarget target,
|
|||
|
||||
if (egl_buffer->u.type != SinglePixelBuffer)
|
||||
{
|
||||
/* Assert that a texture was generated, since UpdateBuffer should
|
||||
be called before the buffer is ever used. */
|
||||
XLAssert (egl_buffer->flags & IsTextureGenerated);
|
||||
/* If no texture was generated, upload the buffer contents
|
||||
now. */
|
||||
if (!(egl_buffer->flags & IsTextureGenerated))
|
||||
EnsureTexture (egl_buffer);
|
||||
|
||||
/* Get the texturing target. */
|
||||
tex_target = GetTextureTarget (egl_buffer);
|
||||
|
@ -1504,8 +1524,9 @@ Composite (RenderBuffer buffer, RenderTarget target,
|
|||
glBindTexture (tex_target, 0);
|
||||
}
|
||||
|
||||
static void
|
||||
FinishRender (RenderTarget target, pixman_region32_t *damage)
|
||||
static RenderCompletionKey
|
||||
FinishRender (RenderTarget target, pixman_region32_t *damage,
|
||||
RenderCompletionFunc callback, void *data)
|
||||
{
|
||||
EglTarget *egl_target;
|
||||
EGLint *rects;
|
||||
|
@ -1538,6 +1559,8 @@ FinishRender (RenderTarget target, pixman_region32_t *damage)
|
|||
ISwapBuffersWithDamage (egl_display, egl_target->surface,
|
||||
rects, nboxes);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int
|
||||
|
@ -1965,7 +1988,8 @@ BufferFromSinglePixel (uint32_t red, uint32_t green, uint32_t blue,
|
|||
buffer->u.single_pixel.a = alpha / (float) 0xffffffff;
|
||||
|
||||
/* An alpha channel is present. */
|
||||
buffer->flags |= HasAlpha;
|
||||
if (buffer->u.single_pixel.a < 1)
|
||||
buffer->flags |= HasAlpha;
|
||||
|
||||
/* Return the buffer. */
|
||||
return (RenderBuffer) (void *) buffer;
|
||||
|
@ -2465,7 +2489,7 @@ UpdateBuffer (RenderBuffer buffer, pixman_region32_t *damage,
|
|||
/* No texture has been generated, so just create one and maybe
|
||||
upload the contents. */
|
||||
EnsureTexture (egl_buffer);
|
||||
else if (!damage)
|
||||
else if (!damage || params->flags & TransformSet)
|
||||
/* Upload all the contents to the buffer's texture if the buffer
|
||||
type requires manual updates. Buffers backed by EGLImages do
|
||||
not appear to need updates, since updates to the EGLImage are
|
||||
|
@ -2522,6 +2546,17 @@ CanReleaseNow (RenderBuffer buffer)
|
|||
return rc;
|
||||
}
|
||||
|
||||
static Bool
|
||||
IsBufferOpaque (RenderBuffer buffer)
|
||||
{
|
||||
EglBuffer *egl_buffer;
|
||||
|
||||
egl_buffer = buffer.pointer;
|
||||
|
||||
/* Return whether or not the buffer has no alpha channel. */
|
||||
return !(egl_buffer->flags & HasAlpha);
|
||||
}
|
||||
|
||||
static BufferFuncs egl_buffer_funcs =
|
||||
{
|
||||
.get_drm_formats = GetDrmFormats,
|
||||
|
@ -2537,6 +2572,7 @@ static BufferFuncs egl_buffer_funcs =
|
|||
.free_single_pixel_buffer = FreeSinglePixelBuffer,
|
||||
.update_buffer_for_damage = UpdateBufferForDamage,
|
||||
.can_release_now = CanReleaseNow,
|
||||
.is_buffer_opaque = IsBufferOpaque,
|
||||
.init_buffer_funcs = InitBufferFuncs,
|
||||
};
|
||||
|
||||
|
|
|
@ -1549,6 +1549,8 @@ MaybeApplyTransform (PictureBuffer *buffer, DrawParams *params)
|
|||
{
|
||||
MatrixIdentity (&ftransform);
|
||||
|
||||
/* The buffer transform must always be applied first. */
|
||||
|
||||
if (params->flags & TransformSet)
|
||||
ApplyInverseTransform (buffer->width, buffer->height,
|
||||
&ftransform, params->transform,
|
||||
|
@ -1557,6 +1559,7 @@ MaybeApplyTransform (PictureBuffer *buffer, DrawParams *params)
|
|||
/* Note that these must be applied in the right order. First,
|
||||
the scale is applied. Then, the offset, and finally the
|
||||
stretch. */
|
||||
|
||||
if (params->flags & ScaleSet)
|
||||
MatrixScale (&ftransform, 1.0 / GetScale (params),
|
||||
1.0 / GetScale (params));
|
||||
|
|
|
@ -1775,8 +1775,10 @@ ViewFree (View *view)
|
|||
XLFree (view);
|
||||
}
|
||||
|
||||
/* Forward declaration. */
|
||||
/* Forward declarations. */
|
||||
|
||||
static void ApplyBufferDamage (View *, pixman_region32_t *);
|
||||
static void ApplyUntransformedDamage (View *, pixman_region32_t *);
|
||||
|
||||
void
|
||||
ViewDamage (View *view, pixman_region32_t *damage)
|
||||
|
@ -1823,10 +1825,6 @@ TransformBufferDamage (pixman_region32_t *damage,
|
|||
View *view)
|
||||
{
|
||||
int width, height;
|
||||
BufferTransform inverse;
|
||||
|
||||
/* Invert the transform. */
|
||||
inverse = InvertTransform (view->transform);
|
||||
|
||||
/* Calculate the width and height of the buffer after the
|
||||
transform. */
|
||||
|
@ -1834,7 +1832,8 @@ TransformBufferDamage (pixman_region32_t *damage,
|
|||
height = XLBufferHeight (view->buffer);
|
||||
|
||||
/* Transform the damage. */
|
||||
XLTransformRegion (damage, source, inverse, width, height);
|
||||
XLTransformRegion (damage, source, view->transform,
|
||||
width, height);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -1905,8 +1904,11 @@ ViewDamageBuffer (View *view, pixman_region32_t *damage)
|
|||
}
|
||||
|
||||
/* Damage the view. */
|
||||
ViewDamage (view, &temp);
|
||||
pixman_region32_union (&view->damage, &view->damage, &temp);
|
||||
pixman_region32_fini (&temp);
|
||||
|
||||
/* Apply the untransformed damage directly. */
|
||||
ApplyUntransformedDamage (view, damage);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2145,6 +2147,19 @@ ApplyBufferDamage (View *view, pixman_region32_t *damage)
|
|||
RenderUpdateBufferForDamage (buffer, damage, ¶ms);
|
||||
}
|
||||
|
||||
static void
|
||||
ApplyUntransformedDamage (View *view, pixman_region32_t *buffer_damage)
|
||||
{
|
||||
RenderBuffer buffer;
|
||||
DrawParams params;
|
||||
|
||||
buffer = XLRenderBufferFromBuffer (view->buffer);
|
||||
params.flags = 0;
|
||||
|
||||
/* Upload the buffer contents. */
|
||||
RenderUpdateBufferForDamage (buffer, buffer_damage, ¶ms);
|
||||
}
|
||||
|
||||
void
|
||||
SubcompositorSetOpaqueCallback (Subcompositor *subcompositor,
|
||||
void (*opaque_changed) (Subcompositor *,
|
||||
|
|
103
transform.c
103
transform.c
|
@ -153,8 +153,8 @@ MatrixRotate (Matrix *transform, float theta, float x, float y)
|
|||
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, 0, 1) = -sinf (theta);
|
||||
Index (temp, 1, 0) = sinf (theta);
|
||||
Index (temp, 1, 1) = cosf (theta);
|
||||
|
||||
MatrixMultiply (copy, temp, transform);
|
||||
|
@ -232,15 +232,18 @@ MatrixExport (Matrix *transform, XTransform *xtransform)
|
|||
|
||||
void
|
||||
ApplyInverseTransform (int buffer_width, int buffer_height, Matrix *matrix,
|
||||
BufferTransform transform, Bool cartesian)
|
||||
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. CARTESIAN
|
||||
specifies whether or not an actual cartesian coordinate system is
|
||||
being used. */
|
||||
/* Wayland buffer transforms are somewhat confusing. They are
|
||||
actually applied in reverse, so a counterclockwise rotation would
|
||||
actually be applied clockwise, and so on.
|
||||
|
||||
The fact that matrix maps from destination coordinates to buffer
|
||||
coordinates makes things easier: as the inverse of the inverse of
|
||||
a transform is itself, transforms are just applied in that
|
||||
order. */
|
||||
|
||||
width = buffer_width;
|
||||
height = buffer_height;
|
||||
|
@ -251,89 +254,57 @@ ApplyInverseTransform (int buffer_width, int buffer_height, Matrix *matrix,
|
|||
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);
|
||||
}
|
||||
|
||||
/* CounterClockwise90. Rotate the buffer contents 90 degrees
|
||||
clockwise. IOW, rotate the destination by 90 degrees
|
||||
counterclockwise, which is 270 degrees clockwise. */
|
||||
MatrixRotate (matrix, M_PI * 1.5, 0, 0);
|
||||
MatrixTranslate (matrix, -height, 0);
|
||||
break;
|
||||
|
||||
case CounterClockwise180:
|
||||
/* Apply clockwise 180 degree rotation around the center. */
|
||||
/* CounterClockwise180. It's 180 degrees. 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);
|
||||
}
|
||||
|
||||
/* CounterClockwise270. Rotate the buffer contents 270 degrees
|
||||
clockwise. IOW, rotate the destination by 270 degrees
|
||||
counterclockwise, which is 90 degrees clockwise. */
|
||||
MatrixRotate (matrix, M_PI * 0.5, 0, 0);
|
||||
MatrixTranslate (matrix, 0, -width);
|
||||
break;
|
||||
|
||||
case Flipped:
|
||||
/* Apply horizontal flip. */
|
||||
/* 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. */
|
||||
/* Flipped90. Apply a flip but otherwise treat this the same as
|
||||
CounterClockwise90. */
|
||||
MatrixRotate (matrix, M_PI * 1.5, 0, 0);
|
||||
MatrixTranslate (matrix, -height, 0);
|
||||
MatrixMirrorHorizontal (matrix, height);
|
||||
break;
|
||||
|
||||
case Flipped180:
|
||||
/* Apply horizontal flip. */
|
||||
MatrixMirrorHorizontal (matrix, width);
|
||||
|
||||
/* Apply clockwise 180 degree rotation around the center. */
|
||||
/* Flipped180. Apply a flip and treat this the same as
|
||||
CounterClockwise180. */
|
||||
MatrixRotate (matrix, M_PI, width / 2.0f, height / 2.0f);
|
||||
MatrixMirrorHorizontal (matrix, width);
|
||||
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. */
|
||||
/* Flipped270. Apply a flip and treat this the same as
|
||||
CounterClockwise270. */
|
||||
MatrixRotate (matrix, M_PI * 0.5, 0, 0);
|
||||
MatrixTranslate (matrix, 0, -width);
|
||||
MatrixMirrorHorizontal (matrix, height);
|
||||
break;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
|
|
Loading…
Add table
Reference in a new issue