diff --git a/12to11.c b/12to11.c index 02048e1..205ad02 100644 --- a/12to11.c +++ b/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 (); diff --git a/compositor.h b/compositor.h index 409b292..bea4905 100644 --- a/compositor.h +++ b/compositor.h @@ -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); diff --git a/egl.c b/egl.c index 73c711c..9a96693 100644 --- a/egl.c +++ b/egl.c @@ -35,9 +35,6 @@ along with 12to11. If not, see . */ #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, }; diff --git a/picture_renderer.c b/picture_renderer.c index 1954561..c10c064 100644 --- a/picture_renderer.c +++ b/picture_renderer.c @@ -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)); diff --git a/subcompositor.c b/subcompositor.c index 6718f71..df1986b 100644 --- a/subcompositor.c +++ b/subcompositor.c @@ -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 *, diff --git a/transform.c b/transform.c index 39b21ed..f1e2ef0 100644 --- a/transform.c +++ b/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