summaryrefslogtreecommitdiffstats
path: root/src/glx
Commit message (Collapse)AuthorAgeFilesLines
* glx: Drop CRAY support.Matt Turner2015-10-052-102/+0
| | | | | | It couldn't have worked anyway. There were calls to undefined functions. Reviewed-by: Emil Velikov <[email protected]>
* glx: Don't hard-code the name "libGL.so.1" in driOpenDriver (v3)Kyle Brenneman2015-10-022-1/+6
| | | | | | | | | | | | | | | | Add a macro GL_LIB_NAME to hold the filename that configure comes up with based on the --with-gl-lib-name and --enable-mangling options. In driOpenDriver, use the GL_LIB_NAME macro instead of hard-coding "libGL.so.1". v2: Add an #ifndef/#define for GL_LIB_NAME so that non-autoconf builds will work. v3: Fix the library filename in the Makefile. Signed-off-by: Kyle Brenneman <[email protected]> Reviewed-by: Emil Velikov <[email protected]> Cc: "10.6 11.0" <[email protected]>
* glx: Fix build errors with --enable-mangling (v2)Kyle Brenneman2015-10-022-2/+12
| | | | | | | | | | | | | | | Rearranged the GLX_ALIAS macro in glextensions.h so that it will pick up the renames from glx_mangle.h. Fixed the alias attribute for glXGetProcAddress when USE_MGL_NAMESPACE is defined. v2: Add a comment clarifying why GLX_ALIAS needs two macros. Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=55552 Signed-off-by: Kyle Brenneman <[email protected]> Cc: "10.6 11.0" <[email protected]> Reviewed-by: Emil Velikov <[email protected]>
* glxl/tests: Use X11_INCLUDES instead of X11_CFLAGSJon TURNEY2015-09-071-1/+1
| | | | | | | | | | | X11_CFLAGS is undefined, so these tests will fail to build if x11proto is installed in a non-standard location. (See also commits 35189d76, bc93c3798, 54b028ba, d901d7e08, etc.) Signed-off-by: Jon TURNEY <[email protected]> Reviewed-by: Matt Turner <[email protected]> Reviewed-by: Emil Velikov <[email protected]>
* mesa/glx: Resolve GCC sign-compare warning.Rhys Kidd2015-08-181-1/+1
| | | | | | | | | | mesa/src/glx/dri_common_query_renderer.c: In function 'dri2_convert_glx_query_renderer_attribs': mesa/src/glx/dri_common_query_renderer.c:61:18: warning: comparison between signed and unsigned integer expressions [-Wsign-compare] for (i = 0; i < ARRAY_SIZE(query_renderer_map); i++) ^ Signed-off-by: Rhys Kidd <[email protected]> Reviewed-by: Thomas Helland <[email protected]>
* mesa/glx: Resolve GCC sign-compare warning.Rhys Kidd2015-08-181-2/+1
| | | | | | | | | | mesa/src/glx/dri_common.c: In function 'scalarEqual': mesa/src/glx/dri_common.c:259:18: warning: comparison between signed and unsigned integer expressions [-Wsign-compare] for (i = 0; i < ARRAY_SIZE(attribMap); i++) ^ Signed-off-by: Rhys Kidd <[email protected]> Reviewed-by: Thomas Helland <[email protected]>
* glx: Fix __glXWireToEvent for BufferSwapCompleteAdam Jackson2015-08-181-0/+3
| | | | | | | | | | | | | | | | | | | In the DRI2 path this event is magically synthesized from the corresponding DRI2 event, but with Present, the server sends us the event itself. The DRI2 path fills in the serial number, send_event, and display fields of the XEvent struct that the app sees, but the Present path did not. This is likely related to a class of crashes seen in gtk/clutter apps: https://bugzilla.redhat.com/attachment.cgi?id=1032631 Note that the crashing instruction is looking up the lock_fns slot in the Display *, and %rdi (holding the Display *) is 0x1. Cc: [email protected] Signed-off-by: Adam Jackson <[email protected]> Reviewed-by: Eric Anholt <[email protected]>
* glx: Use _mesa_lroundevenf() in glPixelStoref().Matt Turner2015-08-041-12/+13
| | | | | | Functional change in which way half-way cases are rounded from towards positive-infinity to even. The spec says "the passed value is rounded to the nearest integer". Removes another case of bad half-up rounding.
* glx: Fix missing bit decl for EXT_texture_integerAdam Jackson2015-07-311-0/+1
| | | | | | | | | | | | Missing from: commit b15aba940a3b6fc7c9bebc692968e7e9b72b9f29 Author: Adam Jackson <[email protected]> Date: Tue Jul 21 11:43:42 2015 -0400 glx: Fix image size computation for EXT_texture_integer (v2) Signed-off-by: Adam Jackson <[email protected]>
* glx: Fix image size computation for EXT_texture_integer (v2)Adam Jackson2015-07-312-0/+11
| | | | | | | | | | | Without this this extension basically can't work in indirect contexts, TexImage2D will compute the image size as 0 and we'll send no image data to the server. v2: Add EXT_texture_integer to the client extension list too (Ian) Reviewed-by: Eric Anholt <[email protected]> Signed-off-by: Adam Jackson <[email protected]>
* Revert "Match swrast modes more loosely."Marek Olšák2015-07-231-58/+1
| | | | | | This reverts commit f3728a16c9c6a02fc1f44b8069b0060e2358f22e. It broke glxgears on radeonsi. The window was just black.
* Match swrast modes more loosely.Tom Hughes2015-07-231-1/+58
| | | | | | https://bugs.freedesktop.org/show_bug.cgi?id=90817 Reviewed-by: Jose Fonseca <[email protected]>
* dri3_open: don't leak the replyGuillaume Desmottes2015-07-111-0/+2
| | | | | | Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=90073 Signed-off-by: Guillaume Desmottes <[email protected]> Reviewed-by: Emil Velikov <[email protected]>
* glx: Use loader_open_device() helperDerek Foreman2015-06-231-9/+1
| | | | | | | | | We've moved the open with CLOEXEC idiom into a helper function, so call it instead of duplicating the code here. Signed-off-by: Derek Foreman <[email protected]> Reviewed-by: Kristian Høgsberg <[email protected]> Reviewed-by: Emil Velikov <[email protected]>
* glx: fix Scons buildBrian Paul2015-05-221-1/+1
| | | | | | Replace -h with --header-tag as was done for the Makefile build. Reviewed-by: Dylan Baker <[email protected]>
* glx/dri3: Add additional check for gpu offloading caseAxel Davy2015-05-111-0/+5
| | | | | | | | | | | | | | | Checks blitImage is implemented. Initially having the __DRIimageExtension extension at version 9 at least meant blitImage was supported. However some implementation do advertise version >= 9 without implementing it. CC: 10.5 <[email protected]> Reviewed-by: Dave Airlie <[email protected]> Reviewed-by: Daniel Stone <[email protected]> Signed-off-by: Axel Davy <[email protected]>
* glx: report which DRI version is used when in verbose debug modeMartin Peres2015-05-072-0/+4
| | | | | | | | This should make it more obvious in bug reports while also removing any sort of guesswork for developers. Reviewed-by: Kenneth Graunke <[email protected]> Signed-off-by: Martin Peres <[email protected]>
* glx: Massive update of comments in struct extension_infoIan Romanick2015-04-291-4/+65
| | | | | | | | | In response to another patch, Emil asked for some clarification how this stuff works. Rather than just reply to the e-mail, I decided to update the exlanation in the code. Signed-off-by: Ian Romanick <[email protected]> Cc: Emil Velikov <[email protected]>
* Fix a few typosZoë Blade2015-04-277-12/+12
| | | | Reviewed-by: Francisco Jerez <[email protected]>
* glx: Create proper server dependency for GLX_EXT_create_context_es2_profileIan Romanick2015-04-151-11/+1
| | | | | | | | | | | | | | | | | | | | Previously GLX_EXT_create_context_es2_profile was marked as "direct only" so that it would not depend on server support. Since the extension required functions that are part of GLX_ARB_create_context_profile, support for the EXT was disabled if the ARB was not supported. This was complete rubbish. If the server supported the ARB but not the EXT, sending a request with GLX_CONTEXT_ES2_PROFILE_BIT_EXT would result in GLXBadProfileARB. Instead of the misguided hack, make GLX_EXT_create_context_es2_profile properly depend on server support by not marking it as "direct only." Signed-off-by: Ian Romanick <[email protected]> Acked-by: José Fonseca <[email protected]> Reviewed-by: Chad Versace <[email protected]> Cc: Emil Velikov <[email protected]>
* glx: replace __FUNCTION__ with __func__Marius Predut2015-04-141-2/+2
| | | | | | | | Consistently just use C99's __func__ everywhere. No functional changes. Acked-by: Matt Turner <[email protected]> Signed-off-by: Marius Predut <[email protected]>
* glx: Include util/macros.h instead of redefining PRINTFLIKE.Jose Fonseca2015-04-131-6/+1
| | | | Reviewed-by: Roland Scheidegger <[email protected]>
* glx: Handle out-of-sequence swap completion events correctly. (v2)Mario Kleiner2015-03-171-2/+7
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | The code for emitting INTEL_swap_events swap completion events needs to translate from 32-Bit sbc on the wire to 64-Bit sbc for the events and handle wraparound accordingly. It assumed that events would be sent by the server in the order their corresponding swap requests were emitted from the client, iow. sbc count should be always increasing. This was correct for DRI2. This is not always the case under the DRI3/Present backend, where the Present extension can execute presents and send out completion events in a different order than the submission order of the present requests, due to client code specifying targetMSC target vblank counts which are not strictly monotonically increasing. This confused the wraparound handling. This patch fixes the problem by handling 32-Bit wraparound in both directions. As long as successive swap completion events real 64-Bit sbc's don't differ by more than 2^30, this should be able to do the right thing. How this is supposed to work: awire->sbc contains the low 32-Bits of the true 64-Bit sbc of the current swap event, transmitted over the wire. glxDraw->lastEventSbc contains the low 32-Bits of the 64-Bit sbc of the most recently processed swap event. glxDraw->eventSbcWrap is a 64-Bit offset which tracks the upper 32-Bits of the current sbc. The final 64-Bit output sbc aevent->sbc is computed from the sum of awire->sbc and glxDraw->eventSbcWrap. Under DRI3/Present, swap completion events can be received slightly out of order due to non-monotic targetMsc specified by client code, e.g., present request submission: Submission sbc: 1 2 3 targetMsc: 10 11 9 Reception of completion events: Completion sbc: 3 1 2 The completion sequence 3, 1, 2 would confuse the old wraparound handling made for DRI2 as 1 < 3 --> Assumes a 32-Bit wraparound has happened when it hasn't. The client can queue multiple present requests, in the case of Mesa up to n requests for n-buffered rendering, e.g., n = 2-4 in the current Mesa GLX DRI3/Present implementation. In the case of direct Pixmap presents via xcb_present_pixmap() the number n is limited by the amount of memory available. We reasonably assume that the number of outstanding requests n is much less than 2 billion due to memory contraints and common sense. Therefore while the order of received sbc's can be a bit scrambled, successive 64-Bit sbc's won't deviate by much, a given sbc may be a few counts lower or higher than the previous received sbc. Therefore any large difference between the incoming awire->sbc and the last recorded glxDraw->lastEventSbc will be due to 32-Bit wraparound and we need to adapt glxDraw->eventSbcWrap accordingly to adjust the upper 32-Bits of the sbc. Two cases, correponding to the two if-statements in the patch: a) Previous sbc event was below the last 2^32 boundary, in the previous glxDraw->eventSbcWrap epoch, the new sbc event is in the next 2^32 epoch, therefore the low 32-Bit awire->sbc wrapped around to zero, or close to zero --> awire->sbc is apparently much lower than the glxDraw->lastEventSbc recorded for the previous epoch --> We need to increment glxDraw->eventSbcWrap by 2^32 to adjust the current epoch to be one higher than the previous one. --> Case a) also handles the old DRI2 behaviour. b) Previous sbc event was above closest 2^32 boundary, but now a late event from the previous 2^32 epoch arrives, with a true sbc that belongs to the previous 2^32 segment, so the awire->sbc of this late event has a high count close to 2^32, whereas glxDraw->lastEventSbc is closer to zero --> awire->sbc is much greater than glXDraw->lastEventSbc. --> We need to decrement glxDraw->eventSbcWrap by 2^32 to adjust the current epoch back to the previous lower epoch of this late completion event. We assume such a wraparound to a higher (a) epoch or lower (b) epoch has happened if awire->sbc and glxDraw->lastEventSbc differ by more than 2^30 counts, as such a difference can only happen on wraparound, or if somehow 2^30 present requests would be pending for a given drawable inside the server, which is rather unlikely. v2: Explain the reason for this patch and the new wraparound handling much more extensive in commit message, no code change wrt. initial version. Cc: "10.3 10.4 10.5" <[email protected]> Signed-off-by: Mario Kleiner <[email protected]> Reviewed-by: Michel Dänzer <[email protected]>
* glx: remove support for non-multithreaded platformsEmil Velikov2015-03-113-29/+2
| | | | | | | | | Implicitly required for a while, although commit 9385c592c68 (mapi: remove u_thread.h) was the one that put the final nail on the coffin. Signed-off-by: Emil Velikov <[email protected]> Reviewed-by: Brian Paul <[email protected]>
* glx: remove final reference to THREADSEmil Velikov2015-03-111-4/+0
| | | | | | | | Left over from commit 18db13f5865(mapi: THREADS was always defined, remove it) Signed-off-by: Emil Velikov <[email protected]> Reviewed-by: Brian Paul <[email protected]>
* Revert "glx: remove final reference to THREADS"Emil Velikov2015-03-061-0/+4
| | | | | | This reverts commit 8b15a883e0ba72c9156d7192a798bb272e0bc528. Not meant to go in yet. Lacking review.
* Revert "glx: remove support for non-multithreaded platforms"Emil Velikov2015-03-063-2/+29
| | | | | | This reverts commit 38591295cd4b68f89f257b20f476f98de3772a47. Not meant to go in yet. Lacking review.
* glx: remove unneeded ifdef _WIN32 guardEmil Velikov2015-03-061-2/+0
| | | | | | | The C99 header exists on other platforms as well. Signed-off-by: Emil Velikov <[email protected]> Reviewed-by: Brian Paul <[email protected]>
* glx: remove support for non-multithreaded platformsEmil Velikov2015-03-063-29/+2
| | | | | | | | Implicitly required for a while, although commit 9385c592c68 (mapi: remove u_thread.h) was the one that put the final nail on the coffin. Signed-off-by: Emil Velikov <[email protected]>
* glx: remove final reference to THREADSEmil Velikov2015-03-061-4/+0
| | | | | | | Left over from commit 18db13f5865(mapi: THREADS was always defined, remove it) Signed-off-by: Emil Velikov <[email protected]>
* Fix invalid extern "C" around header inclusion.Mark Janes2015-03-052-2/+8
| | | | | | | | | | | System headers may contain C++ declarations, which cannot be given C linkage. For this reason, include statements should never occur inside extern "C". This patch moves the C linkage statements to enclose only the declarations within a single header. Reviewed-by: Jose Fonseca <[email protected]>
* glx/tests: add -I src/ to fix make checkBrian Paul2015-03-041-0/+1
| | | | Reviewed-by: Ian Romanick <[email protected]>
* glx: use ARRAY_SIZE from macros.hBrian Paul2015-03-043-1/+3
| | | | Reviewed-by: Jose Fonseca <[email protected]>
* glx: Fix returned values of GLX_RENDERER_PREFERRED_PROFILE_MESAAndreas Boll2015-02-251-6/+30
| | | | | | | | | | | | | | | | | | | | | | | | | | If the renderer supports the core profile the query returned incorrectly 0x8 as value, because it was using (1U << __DRI_API_OPENGL_CORE) for the returned value. The same happened with the compatibility profile. It returned 0x1 (1U << __DRI_API_OPENGL) instead of 0x2. Internal DRI defines: dri_interface.h: #define __DRI_API_OPENGL 0 dri_interface.h: #define __DRI_API_OPENGL_CORE 3 Those two bits are supposed for internal usage only and should be translated to GLX_CONTEXT_CORE_PROFILE_BIT_ARB (0x1) for a preferred core context profile and GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB (0x2) for a preferred compatibility context profile. This patch implements the above translation in the glx module. v2: Fix the incorrect behavior in the glx module Cc: "10.3 10.4 10.5" <[email protected]> Signed-off-by: Andreas Boll <[email protected]> Reviewed-by: Ian Romanick <[email protected]>
* glx: do not leak the dri2 extension informationEmil Velikov2015-02-181-1/+2
| | | | | | | | | | | | The XExtensionInfo is allocated dynamically (if the pointer is NULL) in the XEXT_GENERATE_FIND_DISPLAY macro. On the other hand the macro XEXT_GENERATE_CLOSE_DISPLAY does not check/free the memory. Follow the example set by dri1 and appledri, and use a static variable. Spotted while hunting "still reachable" leaks in Waffle. Signed-off-by: Emil Velikov <[email protected]>
* darwin: build fixJeremy Huddleston Sequoia2015-02-101-0/+5
| | | | | | | | | xfont.c:237:14: error: implicit declaration of function 'GetGLXDRIDrawable' is invalid in C99 [-Werror,-Wimplicit-function-declaration] glxdraw = GetGLXDRIDrawable(CC->currentDpy, CC->currentDrawable); ^ Fixes regression from 291be28476ea60c6fb1eb2a882e2e25def5d3735 Signed-off-by: Jeremy Huddleston Sequoia <[email protected]>
* darwin: build fixJeremy Huddleston Sequoia2015-02-101-0/+1
| | | | | | ../../../src/mesa/main/compiler.h:47:10: fatal error: 'util/macros.h' file not found Signed-off-by: Jeremy Huddleston Sequoia <[email protected]>
* mesa: remove support for GCC older than 3.3.0Timothy Arceri2014-12-171-1/+1
| | | | | | | | | GCC >=3.3 has been required since 9aa3aa71386394725ce88df463d6183f62777ee5 Signed-off-by: Timothy Arceri <[email protected]> Reviewed-By: Jose Fonseca <[email protected]> Reviewed-by: Ian Romanick <[email protected]> Reviewed-by: Matt Turner <[email protected]>
* glx: remove __glXstrdup()Juha-Pekka Heikkila2014-12-162-20/+0
| | | | | | | I didn't find this being used anywhere Signed-off-by: Juha-Pekka Heikkila <[email protected]> Reviewed-by: Matt Turner <[email protected]>
* glx/dri3: Don't fail on glXSwapBuffersMscOML(dpy, window, 0, 0, 0) (v2)Mario Kleiner2014-12-141-2/+15
| | | | | | | | | | | | | | | | | | | | | | | | | | glXSwapBuffersMscOML() with target_msc=divisor=remainder=0 gets translated into target_msc=divisor=0 but remainder=1 by the mesa api. This is done for server DRI2 where there needs to be a way to tell the server-side DRI2ScheduleSwap implementation if a call to glXSwapBuffers() or glXSwapBuffersMscOML(dpy,window,0,0,0) was done. remainder = 1 was (ab)used as a flag to tell the server to select proper semantic. The DRI3/Present backend ignored this signalling, treated any target_msc=0 as glXSwapBuffers() request, and called xcb_present_pixmap with invalid divisor=0, remainder=1 combo. The present extension responded kindly to this with a BadValue error and dropped the request, but mesa's DRI3/Present backend doesn't check for error codes. From there on stuff went downhill quickly for the calling OpenGL client... This patch fixes the problem. v2: Change comments to be more clear, with reference to relevant spec, as suggested by Eric Anholt. Cc: "10.3 10.4" <[email protected]> Signed-off-by: Mario Kleiner <[email protected]> Reviewed-by: Axel Davy <[email protected]> Reviewed-by: Eric Anholt <[email protected]>
* glx/dri3: Request non-vsynced Present for swapinterval zero. (v3)Mario Kleiner2014-12-141-1/+13
| | | | | | | | | | | | | | | | | | | | | | Restores proper immediate tearing swap behaviour for OpenGL bufferswap under DRI3/Present. Cc: "10.3 10.4" <[email protected]> v2: Add Frank Binns signed off by for his original earlier patch from April 2014, which is identical to this one, and Chris Wilsons reviewed tag from May 2014 for that patch, ergo also for this one. v3: Incorporate comment about triple buffering as suggested by Axel Davy, and reference to relevant spec provided by Eric Anholt. Signed-off-by: Frank Binns <[email protected]> Signed-off-by: Mario Kleiner <[email protected]> Reviewed-by: Chris Wilson <[email protected]> Reviewed-by: Axel Davy <[email protected]> Reviewed-by: Eric Anholt <[email protected]>
* glx/dri3: Track separate (ust, msc) for PresentPixmap vs. PresentNotifyMsc (v2)Mario Kleiner2014-12-142-5/+11
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Prevent calls to glXGetSyncValuesOML() and glXWaitForMscOML() from overwriting the (ust,msc) values of the last successfull swapbuffers call (PresentPixmapCompleteNotify event), as glXWaitForSbcOML() relies on those values corresponding to the most recent completed swap, not to whatever was last returned from the server. Problematic call sequence without this patch would have been, e.g., glXSwapBuffers() ... wait ... swap completes -> PresentPixmapComplete event -> (ust,msc) updated to reflect swap completion time and count. ... wait for at least 1 video refresh cycle/vblank increment. glXGetSyncValuesOML() -> PresentNotifyMsc event overwrites (ust,msc) of swap completion with (ust,msc) of most recent vblank glXWaitForSbcOML() -> Returns sbc of last completed swap but (ust,msc) of last completed vblank, not of last completed swap. -> Client is confused. Do this by tracking a separate set of (ust, msc) for the dri3_wait_for_msc() call than for the dri3_wait_for_sbc() call. This makes the glXWaitForSbcOML() call robust again and restores consistent behaviour with the DRI2 implementation. Fixes applications originally written and tested against DRI2 which also rely on this not regressing under DRI3/Present, e.g., Neuro-Science software like Psychtoolbox-3. This patch fixes the problem. v2: Rename vblank_msc/ust to notify_msc/ust as suggested by Axel Davy for better clarity. Cc: "10.3 10.4" <[email protected]> Signed-off-by: Mario Kleiner <[email protected]> Reviewed-by: Axel Davy <[email protected]>
* glx/dri3: Fix glXWaitForSbcOML() to handle targetSBC==0 correctly. (v2)Mario Kleiner2014-12-141-0/+9
| | | | | | | | | | | | | | | | | | | | | | | targetSBC == 0 is a special case, which asks the function to block until all pending OpenGL bufferswap requests have completed. Currently the function just falls through for targetSBC == 0, returning bogus results. This breaks applications originally written and tested against DRI2 which also rely on this not regressing under DRI3/Present, e.g., Neuro-Science software like Psychtoolbox-3. This patch fixes the problem. v2: Simplify as suggested by Axel Davy. Add comments proposed by Eric Anholt. Cc: "10.3 10.4" <[email protected]> Signed-off-by: Mario Kleiner <[email protected]> Reviewed-by: Axel Davy <[email protected]> Reviewed-by: Eric Anholt <[email protected]>
* mesa: Add notes/readme files to distribution.Matt Turner2014-12-121-0/+2
|
* mesa: Add scons files to distribution.Matt Turner2014-12-121-0/+2
|
* glx/apple: Add headers to distribution.Matt Turner2014-12-121-1/+10
|
* glx/tests: Add headers to distribution.Matt Turner2014-12-121-0/+2
|
* glx: Add headers to distribution.Matt Turner2014-12-121-3/+21
|
* glx: Alphabetize source lists.Matt Turner2014-12-121-40/+40
| | | | And remove absurd tab-space-space indentation.
* glx/dri3: Implement LIBGL_SHOW_FPS=1 for DRI3/Present.Kenneth Graunke2014-10-292-2/+36
| | | | | | | | | | | | | | | v2: Use the UST value provided in the PRESENT_COMPLETE_NOTIFY event rather than gettimeofday(), which gives us the presentation time instead of the time when SwapBuffers was called. Suggested by Keith Packard. This relies on the fact that the X DRI3/Present implementations use microseconds for UST. v3: Properly ignore PresentCompleteKindMSCNotify; multiply in 64 bits (caught by Keith Packard). Signed-off-by: Kenneth Graunke <[email protected]> Reviewed-by: Keith Packard <[email protected]> [v3] Reviewed-by: Marek Olšák <[email protected]> [v1]