Commit graph

229 commits

Author SHA1 Message Date
Simon Ser
c94ab99ae2 render: rename wlr_renderer_get_formats
Rename wlr_renderer_get_formats to wlr_renderer_get_shm_texture_formats.
This makes it clear those formats are only suitable for shm import.
2020-11-30 11:08:44 +01:00
Simon Ser
49115e9d5d render: rename wlr_renderer_get_dmabuf_formats
Rename wlr_renderer_get_dmabuf_formats to
wlr_renderer_get_dmabuf_texture_formats. This makes it clear the formats
are only suitable for creating wlr_textures.
2020-11-30 11:08:44 +01:00
Simon Ser
5d008d9030 render: introduce wlr_renderer_get_dmabuf_render_formats
It describes which DMA-BUF formats can be used to render.
2020-11-30 11:08:44 +01:00
Simon Ser
61612ecb36 render: remove wlr_renderer_format_supported
Instead, callers can just use wlr_renderer_get_formats and iterate over
the list.

This function was unused in wlroots.
2020-11-30 11:08:44 +01:00
Simon Ser
c15ca3793e render: expand wlr_renderer_get{,_dmabuf}_formats docs
Make it clear formats returned are only suitable for import/sampling.
These formats can't be used to be rendered to.
2020-11-30 11:08:44 +01:00
Ilia Bozhinov
6284af121f texture: document that functions should not be called while rendering 2020-11-19 11:35:04 +01:00
Simon Ser
e18599b05e render/egl: stop including eglmesaext.h
This is a Mesa-specific header that was needed because some Wayland EGL
extensions were missing from the Khronos registry. Now that this has
been fixed [1] and Mesa [2] & glvnd [3] have sync'ed their headers, we
can drop this workaround.

[1]: https://github.com/KhronosGroup/EGL-Registry/pull/95
[2]: https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/4953
[3]: https://gitlab.freedesktop.org/glvnd/libglvnd/-/merge_requests/225
2020-11-19 00:42:09 +01:00
Simon Ser
eb8360bda3 render: introduce wlr_renderer_get_drm_fd 2020-11-15 22:54:07 +01:00
Simon Ser
c8d95acc37 render/egl: introduce wlr_egl_dup_drm_fd 2020-11-15 22:54:07 +01:00
Simon Ser
c88c54fb38 render: introduce wlr_renderer_bind_buffer 2020-11-15 22:48:42 +01:00
Isaac Freund
0724b3c453 Use uint32_t in wlr_renderer_begin signature
This matches the signature of wlr_renderer_impl.begin
2020-11-11 11:01:46 +01:00
Simon Ser
f0ddcd361e
render: define EGL_NO_PLATFORM_SPECIFIC_TYPES (#2452)
This avoids Xlib.h inclusion via EGL headers. See [1] for discussion.

This change is based on a Weston commit [2].

[1]: https://github.com/KhronosGroup/EGL-Registry/pull/111
[2]: https://gitlab.freedesktop.org/wayland/weston/commit/526765ddfdfd
2020-11-02 10:51:52 +01:00
Tudor Brindus
0f9b2bfa64 render/dmabuf: use bitmask for wlr_dmabuf_attributes_flags 2020-10-31 23:15:21 +01:00
Simon Ser
26af316b3b render/gles2: make wlr_gles2_texture_from_* private
These functions are unused by compositors (see e.g. [1]) and prevent
wlr_gles2_texture from accessing wlr_gles2_renderer state. This is an
issue for proper teardown [2] and for accessing GLES2 extensions.

[1]: https://github.com/swaywm/wlroots/pull/1962#issuecomment-569511830
[2]: https://github.com/swaywm/wlroots/pull/1962
2020-07-28 06:59:07 -06:00
Simon Ser
315bf08733 render: add wlr_render_subtexture_with_matrix
This renders only a subset of the texture, instead of the full texture.
2020-06-17 09:10:54 -06:00
Andri Yngvason
b64a8a7f98 render: Add wlr_renderer_blit_dmabuf() 2020-06-08 20:49:41 +02:00
Andri Yngvason
11b598fe33 render: egl: Add utility functions for saving/restoring context 2020-06-08 20:49:41 +02:00
Simon Ser
a3ba82885c render: choose DMA-BUF texture target via eglQueryDmaBufModifiersEXT
EGL_EXT_image_dma_buf_import_modifiers tells us whether we should use
GL_TEXTURE_2D or GL_TEXTURE_EXTERNAL_OES. Using the right texture target
can fix some failures and/or improve performance on some drivers.

This does the same as a Weston commit [1].

[1]: https://gitlab.freedesktop.org/wayland/weston/commit/40c519a3e613

Closes: https://github.com/swaywm/wlroots/issues/2173
2020-06-06 08:59:38 +02:00
Simon Ser
1edc42157b render/egl: introduce wlr_egl_unset_current
This function can be called after wlr_egl_make_current to cleanup the
EGL context. This avoids having lingering EGL contexts that make things
work by chance.

Closes: https://github.com/swaywm/wlroots/issues/2197
2020-05-19 14:56:20 +02:00
Julien Olivain
c2288a7b88
render/egl: include EGL/eglmesaext.h only if present
This patch will make the EGL renderer work on any EGL/GLESv2 driver
providing the EGL_WL_bind_wayland_display extensions.

Mesa used to declare provisional EGL_WL_bind_wayland_display directly
in <EGL/eglext.h>. Then, all unofficial extensions were moved to
<EGL/eglmesaext.h>, to have a cleaner implementation. See:
ab7bb10a2a

The extension was then approved at Khronos Group, and reached the
official <EGL/eglext.h>. See:
https://www.khronos.org/registry/EGL/extensions/WL/EGL_WL_bind_wayland_display.txt
aa9b63f3ab

In order to make sure the renderer will work on any version of any
implementation providing the extension, only include the mesa-specific
header if it's present.

Signed-off-by: Julien Olivain <juju@cotds.org>
2020-05-11 08:58:30 +02:00
Simon Ser
06f4c3945d render/texture: add width and height fields
Instead of requiring compositors to call wlr_texture_get_size each time
they want to access the texture's size, expose this information as
wlr_texture fields.
2020-04-28 21:45:14 +02:00
Simon Ser
5dc3a9c754 render/gles2: add wlr_gles2_renderer_check_ext 2020-04-22 22:40:54 +02:00
Simon Ser
6787ff521b render/egl: make config attribs const
wlr_egl_init is not allowed to mutate these attribs.
2020-04-09 00:15:25 +00:00
Isaac Freund
c682d97841 Return failure of wlr_renderer_init_wl_display()
This makes it easier for the user of this library to properly handle
failure of this function.

The signature of wlr_renderer_impl.init_wl_display was also modified to
allow for proper error propagation.
2020-03-23 15:19:16 +01:00
Simon Ser
7f2bd0b211 render: unconditionally disable implicit X11 includes
Even if the X11 backend or Xwayland is enabled, we don't rely on
EGL/egl.h including Xlib headers.
2020-01-24 21:33:12 +00:00
Simon Ser
346b43e937 render: guard rendering operations between begin() and end()
Add a wlr_renderer.rendering bool, set it to true between
wlr_renderer_begin() and wlr_renderer_end(). Assert we're rendering when
calling functions that render.
2019-12-31 08:07:44 -07:00
Scott Anderson
cff1c2f740 meson: Various improvements
Bumps minimum version to 0.51.0

- Remove all intermediate static libraries.
  They serve no purpose and are just add a bunch of boilerplate for
  managing dependencies and options. It's now managed as a list of
  files which are compiled into libwlroots directly.

- Use install_subdir instead of installing headers individually.
  I've changed my mind since I did that. Listing them out is annoying as
  hell, and it's easy to forget to do it.

- Add not_found_message for all of our optional dependencies that have a
  meson option. It gives some hints about what option to pass and what
  the optional dependency is for.

- Move all backend subdirectories into their own meson.build. This
keeps some of the backend-specific build logic (especially rdp and
session) more neatly separated off.

- Don't overlink example clients with code they're not using.
  This was done by merging the protocol dictionaries and setting some
  variables containing the code and client header file.
  Example clients now explicitly mention what extension protocols they
  want to link to.

- Split compositor example logic from client example logic.

- Minor formatting changes
2019-12-23 07:48:29 -05:00
Simon Ser
515679e4fe Refactor EGL/GL API loading
Remove glapi.sh code generation, replace it with hand-written loading
code that checks extension strings before calling eglGetProcAddress.

The GLES2 renderer still uses global state because of:

- {PUSH,POP}_GLES2_DEBUG macros
- wlr_gles2_texture_from_* taking a wlr_egl instead of the renderer
2019-12-20 01:03:34 +00:00
Drew DeVault
4c9423278a Introduce wlr_renderer_get_egl 2019-11-11 19:10:10 +01:00
Simon Ser
447835afc1 render/gles2: provide public API to access GL texture
Prior to this commit, compositors needed to render the texture to an
intermediate off-screen buffer using wlr_renderer APIs if they wanted to
use a custom rendering path (e.g. render to a 3D scene).

A new wlr_gles2_texture_get_attribs exposes the GL texture target and ID
so that compositors can render wlr_textures with their own shaders. An
example of a compositor doing so is available at [1].

[1]: 3db905b784/src/render.c (L227)
2019-11-07 14:24:03 -05:00
Simon Ser
eaa98f6aff render: remove EGL includes from wlr_texture.h 2019-11-06 11:30:57 -05:00
Danilo Spinella
41cbb80e25 Add new define EGL_NO_X11 for newer mesa library
Define both MESA_EGL_NO_X11_HEADERS and EGL_NO_X11 for
backward combatibility.
2019-10-16 16:29:25 +03:00
Simon Ser
ca45f4490c Remove all wayland-server.h includes
The documentation for wayland-server.h says:

> Use of this header file is discouraged. Prefer including
> wayland-server-core.h instead, which does not include the server protocol
> header and as such only defines the library PI, excluding the deprecated API
> below.

Replacing wayland-server.h with wayland-server-core.h allows us to drop the
WL_HIDE_DEPRECATED declaration.
2019-07-27 15:49:32 -04:00
Simon Ser
6dbdf5db34 render/dmabuf: add wlr_dmabuf_attributes_copy 2019-06-07 09:06:11 -04:00
Simon Ser
e516ea4c79 backend/drm: check format when scanning out DMA-BUF 2019-06-07 09:06:11 -04:00
emersion
e42178d03f
render: switch wlr_renderer to wlr_drm_format_set 2019-04-01 19:18:04 +03:00
Scott Anderson
c01b81c99c
render: introduce wlr_drm_format_set
This types adds a container for formats + modifiers.

A list that is of [format [modifier]] was chosen instead of
[format modifer] because that is how GBM accepts them.

Co-Authored-By: emersion <contact@emersion.fr>
2019-04-01 19:15:56 +03:00
emersion
75371d2c88
Require libdrm >= 2.4.95 2019-01-29 19:33:38 +01:00
Jente Hidskes
ed5296c6cf Protect against redefining MESA_EGL_NO_X11_HEADERS 2018-12-22 19:05:19 +01:00
Ilia Bozhinov
fb5691b6cc output: add wlr_output_preferred_read_format()
The read format is dependent on the output, so we first need to make it
current. This fixes a race condition in wlr-screencopy-v1 where a dmabuf
client would cause EGL_NO_SURFACE to be bound at the time when
screencopy needs to query for the preferred format, causing GL errors.
2018-11-24 10:54:25 +01:00
emersion
51bfdd620e
Use #if instead of #ifdef for wlroots config data
This prevents some annoying issues when e.g. not including wlr/config.h or
making a typo in the guard name.
2018-11-12 10:12:46 +01:00
Cedric Sodhi
beefec3326 Tell Mesa not to attempt X11 headers
If no X11 related things are being built, tell Mesa's eglplatform.h not to attempt inclusion of associated X11 header.
2018-11-09 21:25:23 +01:00
emersion
62d646f2b8
render/gles2: remove assumptions about supported formats
We were assuming GL_BGRA_EXT was always supported.

We now check that it's supported for rendering. We fail if it isn't because
this format is specified as "always supported" by the Wayland protocol.

We also check if it's supported for reading pixels. A new preferred_read_format
function returns the preferred format that can be used to read pixels. This is
used by the screencopy protocol.
2018-11-04 09:00:51 +01:00
emersion
b42fc4f2b1
render: on Wayland, make eglSwapBuffers non-blocking 2018-10-28 09:58:20 +01:00
nyorain
cb03a41a3b Use enum wl_shm_format for gles2 texture formats
Also rephrase the write_pixels comment.
2018-10-16 09:35:28 +02:00
nyorain
cd28637187 Remove fmt parameter from wlr_texture_write_pixels
It's not allowed to change the format of a texture so remove
the confusing parameter.
2018-10-15 23:56:56 +02:00
nyorain
affbfb6a28 Support older wlr_linux_dmabuf_v1 clients
If a client uses an older version of the dmabuf protocol, use the
`formats` event instead of `modifiers` (since that didn't exist in older
versions).
With a bit of necessary guessing, support dmabuf importing even when
EGL_EXT_image_dma_buf_import_modifiers isn't present instead of
failing up front.
2018-10-12 23:07:45 +02:00
Scott Anderson
fd3fa760d3 Revert "Revert "Merge pull request #1194 from ascent12/meson_feature""
This reverts commit 9c886f20b9.
2018-08-24 19:35:02 +12:00
Drew DeVault
9c886f20b9 Revert "Merge pull request #1194 from ascent12/meson_feature"
This breaks wlroots when used as a meson subproject.

This reverts commit dea311992e, reversing
changes made to 6db9c4b746.
2018-08-23 21:00:58 -04:00
Scott Anderson
51892e0d74 Install headers explicitly 2018-08-22 21:16:16 +12:00
Drew DeVault
211ae764fd Initial pass on API stability guarantees
This introduces -DWLR_USE_UNSTABLE and adds information regarding the
stability status to all headers. I started with a conservative set of
headers to mark as stable:

- types/wlr_matrix.h
- util/edges.h
- util/log.h
- util/region.h
- xcursor.h
2018-07-29 19:20:34 -04:00
emersion
c4915d1492 render: add wlr_texture_is_opaque 2018-07-12 23:35:33 +01:00
emersion
2b9cbaddf3
screencopy: add support for frame flags 2018-06-30 22:18:03 +01:00
emersion
57548b557a
Merge branch 'master' into screencontent 2018-06-17 14:49:18 +01:00
Vincent Vanlaer
f1a62a3200 Rename egl.exts to match the extension names 2018-06-09 19:11:51 +02:00
Vincent Vanlaer
5ec6d8230d Split eglSwapBuffersWithDamage feature detection
Detecting whether eglSwapBuffersWithDamageEXT or
eglSwapBuffersWithDamageKHR is used should be based on the extension
string, not only on the availability of the function.
2018-06-09 11:39:14 +02:00
emersion
457bfcab19
render/egl: only request high priority context on DRM 2018-06-08 00:17:45 +01:00
emersion
d425edc96c
render/egl: consistent extension checking 2018-06-08 00:06:34 +01:00
emersion
cbfe0e834a
Request a high priority EGL context 2018-06-08 00:06:34 +01:00
emersion
21928cbe61
Merge branch 'master' into screencontent 2018-05-31 12:33:27 +01:00
emersion
135721118a
render: remove wlr_renderer_check_import_dmabuf
It's possible to implement it outside the renderer, by creating a
texture and destroying it right away. This reduces the API surface
of the renderer.
2018-05-30 17:08:15 +01:00
emersion
28020ff577
Only allow one modifier per DMA-BUF, split attributes struct in render/ 2018-05-30 09:29:12 +01:00
emersion
5ba1a9af56
render: add wlr_texture_to_dmabuf 2018-05-29 18:47:17 +01:00
emersion
6eb4b5b54d
Merge pull request #993 from emersion/bind-wl-drm-in-renderer
render: bind wl_drm in renderer
2018-05-25 13:54:16 +01:00
Ilia Bozhinov
24cf70ae96 backends: implement custom EGL and renderer initialization
Compositors now have more control over how the backend creates its
renderer. Currently all backends create an EGL/GLES2 renderer, so
the necessary attributes for creating the context are passed to a
user-provided callback function. It is responsible for initializing
provided wlr_egl and to return a renderer. On fail, return 0.

Fixes #987
2018-05-25 14:56:52 +03:00
emersion
41130fe54b
render: bind wl_drm in renderer 2018-05-21 19:07:08 +01:00
emersion
449f06556a
Destroy wlr_surface with wlr_renderer 2018-04-26 00:11:36 +01:00
emersion
018b82c01e
render/egl: allow passing NULL to surface and image destructors 2018-04-25 08:28:48 +01:00
emersion
eaed6bd03b
render/egl: add wlr_egl_destroy_surface 2018-04-24 23:44:43 +01:00
emersion
70d820be25
Add wlr_renderer_init_wl_shm to advertize supported renderer formats 2018-04-20 23:58:30 +01:00
emersion
d2ebbd103c
backend: remove wlr_backend_get_egl 2018-04-08 11:00:56 -04:00
emersion
f3f61bed3e
Untie wlr_gles2_renderer and wlr_gles2_texture 2018-04-01 16:07:50 -04:00
emersion
a7bb48b404
render/egl: add wlr_egl_create_image_from_wl_drm
This allows external renderers and potential future GL-based
renderers to re-use this function.
2018-03-31 23:20:00 -04:00
emersion
33a2eb4b77
Untie wlr_backend from wlr_renderer 2018-03-31 18:49:43 -04:00
Tony Crisci
330ee08126
Merge pull request #744 from emersion/texture-redesign
Redesign wlr_texture
2018-03-28 00:14:57 -04:00
Drew DeVault
13edb19a6c Fix issue starting up client EGL on X11 backend 2018-03-27 18:51:38 -04:00
emersion
c42fd1018b
render: remove GL calls from wlr_egl 2018-03-27 17:02:48 -04:00
emersion
adf4fb08dd
Merge branch 'master' into texture-redesign 2018-03-26 19:13:13 -04:00
emersion
793c3b3047
render: add simple functions to render rectangles and ellipses 2018-03-26 12:41:51 -04:00
emersion
c63d94483b
Redesign wlr_texture
- Textures are now immutable (apart from those created from raw
  pixels), no more invalid textures
- Move all wl_drm stuff in wlr_renderer
- Most of wlr_texture fields are now private
- Remove some duplicated DMA-BUF code in the DRM backend
- Add more assertions
- Stride is now always given as bytes rather than pixels
- Drop wl_shm functions

Fun fact: this patch has been written 10,000 meters up in the air.
2018-03-24 23:48:32 -04:00
emersion
a854c2f246
Merge branch 'master' into gles2-renderer-redesign 2018-03-23 00:55:55 +01:00
emersion
b1f93bc5cc
render/egl: use EGL_KHR_debug 2018-03-21 10:42:43 +01:00
emersion
3581573bdc
render/gles2: make wlr_renderer_begin take viewport size
This allows raw GL calls outside wlr_renderer to be removed.
2018-03-21 07:37:09 +01:00
emersion
95e86e675a
render/gles2: remove global state, use OpenGL debug extension 2018-03-20 19:14:33 +01:00
emersion
c41de2d1be
render: split render.h into wlr_renderer.h and wlr_texture.h 2018-03-19 23:16:29 +01:00
emersion
876f07e9f1
renderer: replace wlr_texture_get_matrix by wlr_render_texture 2018-03-15 19:31:02 +01:00
emersion
8b58e1a3ad
Merge branch 'master' into matrix-redesign 2018-03-15 15:48:09 +01:00
emersion
824a95ad19
matrix: use 2D matrices 2018-03-15 15:33:58 +01:00
Guido Günther
14cdb6153f Add initial linux_dmabuf protocol support
Tested with

    ./weston-simple-dmabuf-drm
    ./weston-simple-dmabuf-drm --import-immediate=1
    ./weston-simple-dmabuf-drm --y-inverted=1
    (and combinations)

Supports only single plane XRGB dmabufs for now.
2018-03-15 12:40:18 +01:00
emersion
d26b67cb06
matrix: unify API, don't use array pointers 2018-03-15 11:10:56 +01:00
emersion
b6a3f240c7
matrix: move to types/ 2018-03-15 09:11:27 +01:00
Guido Günther
d08792bfff Add alpha to wlr_render_with_matrix
so we can use the alpha channel to e.g. blend in textures
2018-02-25 13:47:48 +01:00
emersion
c2e1474010
Reformat all #include directives 2018-02-12 21:29:23 +01:00
emersion
bf6d245400
Swap buffers with damage 2018-02-09 22:54:14 +01:00
emersion
ddb1779f9f
render: make wlr_renderer_clear take a float[4] for the color 2018-02-03 09:32:02 +01:00
emersion
51c22d39a4
Merge remote-tracking branch 'upstream/master' into output-damage 2018-01-29 23:24:09 +01:00
Tony Crisci
ed5b1fdedd
Merge pull request #580 from emersion/screenshooter-renderer-backport
Backport screenshooter fixes from the renderer redesign v1
2018-01-29 17:13:23 -05:00
emersion
6281deb90f
Merge remote-tracking branch 'upstream/master' into output-damage 2018-01-24 14:48:01 +01:00
emersion
4fa90b0511
Backport screenshooter fixes from the renderer redesign v1
This backports some changes to #319 to fix the screenshooter data
format. This also adds wlr_backend_get_renderer which will be
useful to support multiple renderers.
2018-01-23 22:06:54 +01:00
emersion
415a2b7c56
render: add wlr_renderer_clear and wlr_renderer_scissor 2018-01-22 16:42:22 +01:00
Tony Crisci
85a6939cf2 rename matrix model box to project box 2018-01-21 19:03:10 -05:00
Tony Crisci
d13114520a move matrix model code to matrix.h 2018-01-21 15:53:42 -05:00
emersion
0365b587f0
output: add damage tracking via buffer age 2018-01-21 00:06:35 +01:00
emersion
b99d1f4fcc
Refactor wlr_egl_init to accept config_attribs 2017-12-17 23:51:04 +01:00
Drew DeVault
23fb663ea4
Merge pull request #453 from emersion/surface-transform
Add surface transforms support
2017-12-14 14:43:04 -05:00
emersion
18eb1eee3f
Listen to display destroy in xwayland, rename wlr_egl_free 2017-12-08 00:59:37 +01:00
emersion
f4754ad1a2
Fix surface transforms 2017-11-30 23:58:12 +01:00
Scott Anderson
9b984253e2 Move egl.h to render/egl.h 2017-10-22 10:36:07 +13:00
emersion
0ce3135304
Move read_pixels from output to renderer 2017-10-08 02:11:56 +02:00
Scott Anderson
009c3747a8 Multi-GPU DRM 2017-10-01 22:29:25 +13:00
emersion
427bdb5b55
Use more consistent include guard names 2017-09-23 10:26:01 +02:00
Dominique Martinet
f24b3df980 wlr renderer/texture: rename init to create when it does alloc 2017-08-19 08:33:31 +02:00
Tony Crisci
72a33b736f implement texture get buffer size 2017-08-15 07:36:50 -04:00
Drew DeVault
de6f32c84e Refactor away wlr_renderer_state 2017-08-14 08:37:50 -04:00
Drew DeVault
94e6e6334b Refactor out wlr_texture_state 2017-08-14 08:25:26 -04:00
Drew DeVault
c24351681f Refactor EGL handling 2017-08-10 22:15:37 -04:00
nyorain
67369173aa Implement drm (egl) buffer attaching 2017-08-10 10:59:58 +02:00
Drew DeVault
4de930542f Implement partial texture uploads 2017-08-09 22:17:40 -04:00
nyorain
e167f41fde Rename wlr_surface -> wlr_texture; attach -> upload 2017-08-08 18:25:16 +02:00
Scott Anderson
1db97a9af9 Updated DRM cursor rendering 2017-08-06 21:38:40 +12:00
Drew DeVault
8920b5d607 Merge branch 'wlcore' 2017-06-29 16:00:24 -04:00
Scott Anderson
0cd94f0cf0 Added software cursor fallback 2017-06-26 17:34:15 +12:00
Drew DeVault
5a2796266f Support wl_shm pixel formats in gles2 renderer 2017-06-23 14:25:55 -04:00
Drew DeVault
2aafb5dd19 Add wlcore/wl_shm (WIP) 2017-06-23 13:41:07 -04:00
Drew DeVault
b18209c904 Switch to GLES2
Closes #13
2017-06-23 11:38:45 -04:00
Drew DeVault
fd91244e83 Update everyone to use new headers 2017-06-21 10:27:45 -04:00
Drew DeVault
2443a070e7 Add colored quad and ellipse rendering primitives 2017-06-15 15:31:13 -04:00
Drew DeVault
cd6a40d816 Further improvements to rendering subsystem 2017-06-08 15:52:42 -04:00
Drew DeVault
fc1dc1b5b0 Use constant VBO for quad, add matrix stuff 2017-06-07 21:35:07 -04:00