Compare commits

...

78 Commits

Author SHA1 Message Date
Andrea Cavalli ea5e7c688e Test 2021-09-12 16:41:24 +02:00
Andrea Cavalli f5a4fe32db Test 2021-09-12 16:22:16 +02:00
Andrea Cavalli 672bba9ed0 Test 2021-09-12 16:08:21 +02:00
Andrea Cavalli d448ffcb05 Test 2021-09-12 16:05:52 +02:00
Andrea Cavalli 012d982d90 Test 2021-09-12 16:00:33 +02:00
Andrea Cavalli 6d2e5cd62e Change defaults 2021-09-12 15:57:52 +02:00
Andrea Cavalli e2d60a037c Change defaults 2021-09-12 15:44:42 +02:00
Andrea Cavalli 52687e0853 default 192DPI 2021-09-12 13:19:26 +02:00
Ryan Gonzalez 18f1ce0b6e xwayland: Clear output buffers on scale change 2021-08-23 13:21:28 -05:00
Ryan Gonzalez aa849658c5 xwayland: Allow controlling global output scale via properties
This adds a new property, _XWAYLAND_GLOBAL_OUTPUT_SCALE, to control the
global output scale from the compositor.
2021-08-23 13:21:28 -05:00
Christopher Snowhill b46a9bba29 xwayland: Fix cursor size, present scale, and present damage 2021-08-23 13:21:28 -05:00
Dario Nieuwenhuis fbc7cefc43 xwayland: Multi DPI support via global factor rescaling
To benefit from Wayland's multi DPI capabilities in XWayland a global scaling
factor is introduced, which is applied to all outputs.

The RandR size of an output is calculated by the (integer-)multiplication of
this global scaling factor with its logical size received via the xdg-output
protocol.

In other words the size of any RandR screen corresponds to the mode size of
its wl_output multiplied with the quotient of global scaling factor divided by
the compositor's internal output-dependent scaling factor.

HiDPI aware X clients can then provide Pixmaps enlarged by the global scaling
factor and the Wayland compositor is supposed to downscale these buffers on
outputs scaled by less than the global scaling factor.

A Wayland compositor needs to scale all X communication in its XWM part by the
global scaling factor, such that X windows have the correct geometry.

In summary:
* All positions in Wayland internal communication must be carried out by the
compositor in logical coordinates, i.e. in its compositor space.
* All positions in X internal communication are based on RandR sizes.
* All positions in Wayland to X communication must be multiplied by the global
scaling factor.
* All positions in X to Wayland communication must be divided by the global
scaling factor.

In order to not break compositors that do not support these transformations,
the global scaling factor is set to 1 by default, which behaves the same as
before.

[dirbaio@dirbaio.net: fix incorrect scaling in a few places]
[rymg19@gmail.com: minor style fixes]
Signed-off-by: Roman Gilg <subdiff@gmail.com>
Signed-off-by: Dario Nieuwenhuis <dirbaio@dirbaio.net>
2021-08-23 13:21:28 -05:00
Povilas Kanapickas 18d3131f9a meson: Implement developer documentation build
Signed-off-by: Povilas Kanapickas <povilas@radix.lt>
2021-08-20 10:26:07 +00:00
Povilas Kanapickas 722da1c62c meson: Add option to disable libdrm support
Signed-off-by: Povilas Kanapickas <povilas@radix.lt>
2021-08-20 07:11:44 +00:00
Adam Jackson 1f720dc9a3 dmx: Fix some redeclaration warnings from gcc 11
Of the form:

    ../hw/dmx/config/xdmxconfig.c:68:26: warning: redundant redeclaration of ‘dmxConfigEntry’ [-Wredundant-decls]
       68 | extern DMXConfigEntryPtr dmxConfigEntry;
          |                          ^~~~~~~~~~~~~~
2021-08-17 16:06:57 -04:00
Adam Jackson b49f0f9b32 xkb: Silence a warning from gcc 11
I get this:

    In function ‘TryCopyStr’,
        inlined from ‘CopyISOLockArgs’ at ../xkb/xkbtext.c:875:9:
    ../xkb/xkbtext.c:720:13: warning: ‘tbuf’ may be used uninitialized [-Wmaybe-uninitialized]
      720 |             strcat(to, from);
          |             ^~~~~~~~~~~~~~~~
    ../xkb/xkbtext.c: In function ‘CopyISOLockArgs’:
    <built-in>: note: by argument 1 of type ‘const char *’ to ‘__builtin_strlen’ declared here
    ../xkb/xkbtext.c:871:10: note: ‘tbuf’ declared here
      871 |     char tbuf[64];
          |          ^~~~

Just initialize tbuf so it definitely works.
2021-08-17 16:04:40 -04:00
Adam Jackson c1138d8ec8 xinput: Silence a warning from gcc 11
[45/388] Compiling C object Xi/liblibxserver_xi.a.p/xichangehierarchy.c.o
../Xi/xichangehierarchy.c:61:32: warning: argument 1 of type ‘int[256]’ with mismatched bound [-Warray-parameter=]
   61 | XISendDeviceHierarchyEvent(int flags[MAXDEVICES])
      |                            ~~~~^~~~~~~~~~~~~~~~~
In file included from ../Xi/xichangehierarchy.c:54:
../Xi/xichangehierarchy.h:42:37: note: previously declared as ‘int[]’
   42 | void XISendDeviceHierarchyEvent(int flags[]);
      |                                 ~~~~^~~~~~~
2021-08-17 16:02:44 -04:00
Adam Jackson f3a98334e6 selinux: Stop using security_context_t
This is apparently deprecated now and is and was always just char *.
2021-08-17 16:02:39 -04:00
Simon Ser 6f63873da5 xwayland: fix xdg_output leak
The xdg_output wasn't cleaned up when destroying the xwl_output.

Signed-off-by: Simon Ser <contact@emersion.fr>
2021-08-12 07:07:26 +00:00
Demi Marie Obenour 659260a0b7 More missing version checks in SProcs
The bug in XFixes was also found in GenericEvent and Damage.
2021-08-08 12:43:01 +00:00
Roman Gilg e4dabe8d93 Remove build-only include from public header
The dix-config.h file is not installed, but dix.h is. The include makes the
compilation of external drivers fail (for example the libinput driver).

The Xserver compilation also works without the include, so just remove it.

Signed-off-by: Roman Gilg <subdiff@gmail.com>
2021-08-07 14:26:26 +02:00
Demi Marie Obenour 31fb35a7af XFixes: add version check for byteswapped clients
The version check for byteswapped clients was missing.
2021-08-06 11:12:40 -04:00
Olivier Fourdan 7eba412072 xfree86: Move xf86CVTMode() function
The xf86CVTMode() was implemented in a standalone source file because it
was being used for both the xfree86 API and the standalone cvt utility.

Now that the cvt utility is removed (as part of libxcvt) we can move the
small xf86CVTMode() function with the rest of the xf86Modes sources.

Closes: https://gitlab.freedesktop.org/xorg/xserver/-/issues/1142
Signed-off-by: Olivier Fourdan <ofourdan@redhat.com>
Reviewed-by: Matt Turner <mattst88@gmail.com>
2021-08-06 11:29:29 +00:00
Olivier Fourdan f2781e9536 xfree86/cvt: Drop cvt utility
The cvt utility is now replaced by the standalone version found in
libxcvt, no need to build the one in xfree86 anymore.

Closes: https://gitlab.freedesktop.org/xorg/xserver/-/issues/1142
Signed-off-by: Olivier Fourdan <ofourdan@redhat.com>
Reviewed-by: Matt Turner <mattst88@gmail.com>
2021-08-06 11:29:29 +00:00
Olivier Fourdan f788289bdc xfree86: Use libxcvt
Replace the local implementation of the VESA CVT standard timing
modelines generator with the one from libxct to avoid code duplication.

Closes: https://gitlab.freedesktop.org/xorg/xserver/-/issues/1142
Signed-off-by: Olivier Fourdan <ofourdan@redhat.com>
Reviewed-by: Matt Turner <mattst88@gmail.com>
2021-08-06 11:29:29 +00:00
Olivier Fourdan 6ea2c001f9 xwayland: Use libxcvt
Xwayland is using a copy of the CVT generator found in Xorg.

Rather than duplicating the code within the xserver tree, use the
libxcvt implementation instead.

Closes: https://gitlab.freedesktop.org/xorg/xserver/-/issues/1142
Signed-off-by: Olivier Fourdan <ofourdan@redhat.com>
Reviewed-by: Matt Turner <mattst88@gmail.com>
2021-08-06 11:29:29 +00:00
Olivier Fourdan a4ab57cb74 build: Add dependency on libxcvt
libxcvt is a library providing a standalone version of the X server
implementation of the VESA CVT standard timing modelines generator.

Closes: https://gitlab.freedesktop.org/xorg/xserver/-/issues/1142
Signed-off-by: Olivier Fourdan <ofourdan@redhat.com>
Reviewed-by: Matt Turner <mattst88@gmail.com>
2021-08-06 11:29:29 +00:00
Olivier Fourdan 84897891e5 ci: Install libxcvt from git
Signed-off-by: Olivier Fourdan <ofourdan@redhat.com>
2021-08-06 11:29:29 +00:00
Demi Marie Obenour 5c2592cbb1 Add do-while loops to DIX macros
This ensures they will behave properly in conditionals and always
require a trailing semicolon.
2021-07-31 08:55:52 -04:00
Alex Richardson d83c84bd9d Mark the dixChangeWindowProperty() value argument as const
It is copied using memcpy() and not modified so we can add const. This
fixes a -Wincompatible-pointer-types-discards-qualifiers compiler warning
that was failing a -Werror XVnc build for me.

Signed-off-by: Alex Richardson <Alexander.Richardson@cl.cam.ac.uk>
2021-07-30 08:36:35 +00:00
Zoltán Böszörményi fb5322ce28 glamoregl: Initialize glamor on the main device
This allows e.g. an UDL device (driven by llvmpipe) to be automatically
set up with GPU acceleration via reverse PRIME.

The result is e.g.:

  # DISPLAY=:0.2 xrandr --listproviders
  Providers: number : 2
  Provider 0: id: 0xec cap: 0xf, Source Output, Sink Output, Source Offload, Sink Offload crtcs: 1 outputs: 1 associated providers: 1 name:modesetting
  Provider 1: id: 0x12c cap: 0xb, Source Output, Sink Output, Sink Offload crtcs: 2 outputs: 2 associated providers: 1 name:Intel

Signed-off-by: Zoltán Böszörményi <zboszor@gmail.com>
2021-07-30 00:27:39 +00:00
Zoltán Böszörményi f08bc32f5a xf86: Assign GPUs to screens according to configuration
If there is an explicit configuration, assign the RandR provider
of the GPUDevice to the screen it was specified for.

If there is no configuration (default case) the screen number is
still 0 so it doesn't change behaviour.

The result is e.g:

  # DISPLAY=:0.2 xrandr --listproviders
  Providers: number : 2
  Provider 0: id: 0xd2 cap: 0x2, Sink Output crtcs: 1 outputs: 1 associated providers: 0 name:modesetting
  Provider 1: id: 0xfd cap: 0xb, Source Output, Sink Output, Sink Offload crtcs: 2 outputs: 2 associated providers: 0 name:Intel

Signed-off-by: Zoltán Böszörményi <zboszor@gmail.com>
2021-07-30 00:27:39 +00:00
Zoltán Böszörményi cd567415cc xf86: Extract screen configuration matching into its own function
Signed-off-by: Zoltán Böszörményi <zboszor@gmail.com>
2021-07-30 00:27:39 +00:00
Boris-Barboris 16571b8926 Don't hardcode fps for fake screen
Currently, when main hardware screen is powered-off,
X server initializes fake screen's timer with
1 second update interval.

Streaming software like Nomachine or Vnc, as well as
desktop input automation suffers from it, since it
will forever be stuck on 1 fps until the display is
turned back on.

This commit adds command line option -fakescreenfps <int>
that allows the user to change the default fake screen
timer.

Signed-off-by: Baranin Alexander <ismailsiege@gmail.com>
2021-07-29 08:09:00 +00:00
Łukasz Spintzyk 8836b9d243 modesetting: unflip not possible when glamor is not set
This is fixing crashes of xfce when running under qemu
2021-07-22 13:24:21 +02:00
Łukasz Spintzyk d6c02ffd9c present: fallback get_crtc to return crtc belonging to screen with present extension
Since crtc can belong to secondary output that may not have present
extension enabled we should fallback to first enabled crtc or fake crtc.

Fix for issue xorg/xserver#1195
2021-07-20 08:10:46 +02:00
Michel Dänzer f6f2f203bc present: Drop flip_idler member from present_vblank_rec
It's redundant with the pixmap member of struct xwl_present_event.

Acked-by: Olivier Fourdan <ofourdan@redhat.com>
2021-07-09 16:20:56 +02:00
Michel Dänzer 212cfbcf68 xwayland/present: Use present_vblank_ptr instead of xwl_present_event*
Where the latter isn't really needed.

Acked-by: Olivier Fourdan <ofourdan@redhat.com>
2021-07-09 16:20:35 +02:00
Michel Dänzer fe8c7855f3 xwayland/present: Fold xwl_present_release_event into _free_event
The only difference was unhooking from the vblank.event_queue list,
which is already done by xwl_present_flip_notify_vblank in
xwl_present_msc_bump.
2021-07-09 16:20:20 +02:00
Michel Dänzer 31d2ebca77 xwayland/present: Drop target_msc member from struct xwl_present_event
Use present_vblank_rec::exec_msc instead.

Acked-by: Olivier Fourdan <ofourdan@redhat.com>
2021-07-09 16:20:04 +02:00
Michel Dänzer 495ec59664 xwayland/present: Drop pending member from struct xwl_present_event
We are handling two cases here: the active flip or the pending flip.

For the pending flip (event->pending == TRUE), we called
xwl_present_release_pixmap.

For the active flip (event->pending == FALSE), we called
xwl_present_release_event. However, xwl_present_flip_notify_vblank
already unhooked event->vblank.event_queue. So this was effectively the
same as calling xwl_present_release_pixmap.

Acked-by: Olivier Fourdan <ofourdan@redhat.com>
2021-07-09 16:19:30 +02:00
Michel Dänzer f73340445f xwayland/present: Drop list member from struct xwl_present_event
Use present_vblank_rec::event_queue instead.

The changes in xwl_present_execute shouldn't really be needed, since
we should never hit queue_vblank in present_execute_wait. But let's be
safe rather than sorry, plus this simplifies the code.

Acked-by: Olivier Fourdan <ofourdan@redhat.com>
2021-07-09 16:18:56 +02:00
Michel Dänzer aac31d2758 xwayland/present: Drop exec_queue member from struct xwl_present_window
Doesn't serve any purpose anymore.

Acked-by: Olivier Fourdan <ofourdan@redhat.com>
2021-07-09 16:18:47 +02:00
Michel Dänzer f8c086b214 xwayland/present: Fold xwl_present_event_notify into its caller
Can just call xwl_present_execute directly.

This allows dropping the window member from struct xwl_present_window as
well.

Acked-by: Olivier Fourdan <ofourdan@redhat.com>
2021-07-09 16:18:33 +02:00
Michel Dänzer c30f3d08ac xwayland/present: Use exec_queue for deferring completion events
We clear the vblank->pixmap field, so next time xwl_present_execute
falls through to present_execute_post.

Acked-by: Olivier Fourdan <ofourdan@redhat.com>
2021-07-09 16:18:07 +02:00
Michel Dänzer 4503c8d9ea xwayland/present: Fold xwl_present_idle_notify into its caller
Allows simplification by avoiding indirection.

Acked-by: Olivier Fourdan <ofourdan@redhat.com>
2021-07-09 16:17:55 +02:00
Michel Dänzer b2a06e0700 xwayland/present: Drop sync_flip member of struct xwl_present_window
The same information can be determined from the flip queue.

Acked-by: Olivier Fourdan <ofourdan@redhat.com>
2021-07-09 16:17:44 +02:00
Michel Dänzer fc53e3c536 xwaland/present: Drop flip_pending member of struct xwl_present_window
Use the first element of the flip_queue list for the same purpose.

Acked-by: Olivier Fourdan <ofourdan@redhat.com>
2021-07-09 16:17:23 +02:00
Michel Dänzer c592c66625 xwayland/present: Fold xwl_present_flip_notify into its callers
No need for them to be separate anymore.

Acked-by: Olivier Fourdan <ofourdan@redhat.com>
2021-07-09 16:17:15 +02:00
Michel Dänzer 4230176080 xwayland/present: Embed present_vblank_rec in xwl_present_event
This allows for various simplifications.

Use the pointer to the struct memory as the event ID. In contrast to
the SCMD code for Xorg (where pending DRM events cannot be cancelled),
this is safe here, because we can destroy pending Wayland callbacks. So
we can't get a callback with a stale pointer to freed memory.

Remove xwl_present_window::release_list in favour of
present_vblank_rec::window_list.

Remove xwl_present_event::xwl_present_window in favour of
present_vblank_rec::window.

xwl_present_free_event is never called for a NULL pointer anymore, no
need to check.

v2:
* Restore DestroyWindow wrapping order to make sure
  present_destroy_window doesn't call xwl_present_abort_vblank.

Acked-by: Olivier Fourdan <ofourdan@redhat.com>
2021-07-09 16:15:50 +02:00
Michel Dänzer 61cc5d96ed present: Refactor present_vblank_init helper ouf of _vblank_create
Allows embedding into another struct.

Acked-by: Olivier Fourdan <ofourdan@redhat.com>
2021-07-09 16:15:39 +02:00
Michel Dänzer 35f173ddb6 xwayland/present: Drop abort member of struct xwl_present_event
We can call xwl_present_free_event unconditionally from
xwl_present_abort_vblank, since the sync_callback is already destroyed
in xwl_present_cleanup.

Acked-by: Olivier Fourdan <ofourdan@redhat.com>
2021-07-09 16:15:10 +02:00
Michel Dänzer 0517460301 xwayland/present: Simplify calls to Xwayland-private functions
Change parameter types to what's really needed, or just fold the
function into its only caller.

Acked-by: Olivier Fourdan <ofourdan@redhat.com>
2021-07-09 16:14:56 +02:00
Michel Dänzer 490248ea70 xwayland/present: Rename present_wnmd_* functions to xwl_present_*
The WNMD indirection is gone.

Acked-by: Olivier Fourdan <ofourdan@redhat.com>
2021-07-09 16:14:47 +02:00
Michel Dänzer 0c0cbbc7cb present: Remove present_wnmd_info_rec
Doesn't serve any purpose anymore.

Acked-by: Olivier Fourdan <ofourdan@redhat.com>
2021-07-09 16:14:38 +02:00
Michel Dänzer 561c63d0f1 xwayland/present: Merge present_wnmd_flips_stop & xwl_present_flips_stop
Just use the latter instead of the former elsewhere. No need for them
to be separate anymore.

Acked-by: Olivier Fourdan <ofourdan@redhat.com>
2021-07-09 16:14:28 +02:00
Michel Dänzer a67f16fde1 xwayland/present: Fold present_wnmd_get_ust_msc into its callers
Just use xwl_present_get_ust_msc directly. No need for the indirection
anymore.

Acked-by: Olivier Fourdan <ofourdan@redhat.com>
2021-07-09 16:14:19 +02:00
Michel Dänzer 080c1ca3f5 xwayland/present: Fold present_wnmd_queue_vblank into its callers
Just use xwl_present_queue_vblank directly. No need for the indirection
anymore.

Acked-by: Olivier Fourdan <ofourdan@redhat.com>
2021-07-09 16:14:09 +02:00
Michel Dänzer c22887bc7a xwayland/present: Fold present_wnmd_get_crtc into present_wnmd_pixmap
And use xwl_present_get_crtc directly.

No need for them to be separate anymore.

Acked-by: Olivier Fourdan <ofourdan@redhat.com>
2021-07-09 16:13:59 +02:00
Michel Dänzer cb35ff596e xwayland/present: Fold present_wnmd_check_flip into its callers
Mainly into xwl_present_check_flip, and call that from
present_wnmd_check_flip_window.

No need for them to be separate anymore.

Acked-by: Olivier Fourdan <ofourdan@redhat.com>
2021-07-09 16:13:48 +02:00
Michel Dänzer 7b78cf6b3a xwayland/present: Simplify query_capabilities
No need for the WNMD indirection anymore.

Acked-by: Olivier Fourdan <ofourdan@redhat.com>
2021-07-09 16:13:39 +02:00
Michel Dänzer 244403ec87 xwayland/present: Fold present_wnmd_abort_vblank into its only caller
No need for them to be separate anymore.

Acked-by: Olivier Fourdan <ofourdan@redhat.com>
2021-07-09 16:13:32 +02:00
Michel Dänzer f7adbc2166 xwayland/present: Drop present_wnmd_flush in favour of xwl_present_flush
No need for the indirection anymore.

Acked-by: Olivier Fourdan <ofourdan@redhat.com>
2021-07-09 16:13:24 +02:00
Michel Dänzer 7fd114365d xwayland/present: Fold present_wnmd_flip into present_wnmd_execute
No need for the indirection anymore.

Acked-by: Olivier Fourdan <ofourdan@redhat.com>
2021-07-09 16:13:15 +02:00
Michel Dänzer 2e1dcd731f xwayland/present: Fold present_wnmd_screen_init into xwl_present_init
No need for them to be separate anymore.

Acked-by: Olivier Fourdan <ofourdan@redhat.com>
2021-07-09 16:13:04 +02:00
Michel Dänzer b6419359b6 present: Move present_wnmd.c contents to hw/xwayland/xwayland-present.c
This will allow eliminating indirections and making the Xwayland Present
code more efficient and easier to follow.

While this technically changes the Xorg video driver ABI, I don't know
of any drivers using the dropped present_wnmd_* symbols, and I doubt a
Xorg driver could make use of them as is anyway.

(As a bonus, Xorg no longer links any Xwayland specific Present code)

v2:
* Wrap DestroyWindow before initializing Present, so that
  present_destroy_window runs before xwl_present_cleanup. Avoids crash
  due to present_destroy_window calling xwl_present_* functions when
  xwl_present_window was already freed. (Olivier Fourdan)

Acked-by: Olivier Fourdan <ofourdan@redhat.com>
2021-07-09 16:11:22 +02:00
Michel Dänzer c35a716b02 present: Fold wnmd_init_mode_hooks into wnmd_screen_init
Preparation for moving WNMD code to hw/xwayland. No functional change
intended.

Acked-by: Olivier Fourdan <ofourdan@redhat.com>
2021-07-09 16:11:11 +02:00
Michel Dänzer 10bdd87fe4 present: Move present_wnmd_screen_init to present_wnmd.c
Now all WNMD code is in present_wnmd.c.

Acked-by: Olivier Fourdan <ofourdan@redhat.com>
2021-07-09 16:11:02 +02:00
Michel Dänzer b6d54b0f5d present: Dispatch clear_window_flip via present_screen_priv hook
Eliminates special cases in present_destroy_window.

Acked-by: Olivier Fourdan <ofourdan@redhat.com>
2021-07-09 16:10:54 +02:00
Michel Dänzer 93666ebe37 present: Remove create_event_id hook
Each present_vblank_create caller generates and sets the ID afterwards.

Acked-by: Olivier Fourdan <ofourdan@redhat.com>
2021-07-09 16:10:43 +02:00
Michel Dänzer 44f705a5b6 present: Pass capabilities to present_vblank_create by value
Preparation for moving WNMD code to hw/xwayland. No functional change
intended.

Acked-by: Olivier Fourdan <ofourdan@redhat.com>
2021-07-09 16:10:06 +02:00
Michel Dänzer 86e645bcfa xwayland/eglstream: Drop xwl_eglstream_set_window_pixmap
Not sure why we'd need to abandon a pending stream for a pixmap just
because it's no longer a window pixmap. Let's try not to.

Reviewed-by: Olivier Fourdan <ofourdan@redhat.com>
2021-07-09 15:51:43 +02:00
Michel Dänzer ba8763c27b xwayland/eglstream: Consolidate pending_cb destruction
Into a new xwl_eglstream_destroy_pending_stream helper.

Reviewed-by: Olivier Fourdan <ofourdan@redhat.com>
2021-07-09 15:50:57 +02:00
Michel Dänzer 204f10c29e xwayland: Call RRTellChanged if the RandR configuration may have changed
This makes sure RandR events are sent to interested clients as needed.
This was happening implicitly in some cases, but not in others, e.g. if
the root window size didn't change.

If this were to call RRTellChanged more often than necessary in some
cases, that should be harmless, as it only sends events if something
has actually changed since last time.

Should fix https://bugzilla.redhat.com/show_bug.cgi?id=1979892 .

v2:
* Call RRTellChanged at the very end of update_screen_size, just in
  case.

Reviewed-by: Olivier Fourdan <ofourdan@redhat.com>
2021-07-09 11:48:15 +02:00
Michel Dänzer a6d178b6af randr: Bail from RRTellChanged if there's no root window yet
This can happen if RRTellChanged is called during initialization.

Continuing in that case makes no sense conceptually:

* Any event sent over the wire requires a corresponding window.
* No root window probably means there can't be any clients which could
  receive the events.

In practice, it would result in a crash down the road due to
dereferencing the NULL ScreenRec::root pointer.

Reviewed-by: Olivier Fourdan <ofourdan@redhat.com>
2021-07-09 11:48:15 +02:00
Matt Turner 7e20c8b7b8 Build xz tarballs instead of bzip2
Signed-off-by: Matt Turner <mattst88@gmail.com>
2021-07-08 12:32:01 -07:00
Dave Airlie a955286869 glamor: add EXT_gpu_shader4 support
This enables a number of the GLSL 1.30 paths on GPUs that have
EXT_gpu_shader4 but don't have GLSL 1.30 exposed.

(Intel gen4/5 mainly)

Reviewed-by: Adam Jackson <ajax@redhat.com>
2021-07-07 08:42:09 +10:00
Dave Airlie a2f5b917f5 glamor: add glamor_glsl_has_ints wrapper
This should make adding gpu shader4 support cleaner

Reviewed-by: Adam Jackson <ajax@redhat.com>
2021-07-07 08:41:50 +10:00
77 changed files with 1443 additions and 2230 deletions

View File

@ -11,7 +11,7 @@ variables:
FDO_UPSTREAM_REPO: xorg/xserver
FDO_DISTRIBUTION_VERSION: buster-slim
FDO_DISTRIBUTION_EXEC: 'env FDO_CI_CONCURRENT=${FDO_CI_CONCURRENT} bash .gitlab-ci/debian-install.sh'
FDO_DISTRIBUTION_TAG: "2021-05-17"
FDO_DISTRIBUTION_TAG: "2021-07-09"
include:
- project: 'freedesktop/ci-templates'

View File

@ -107,6 +107,14 @@ apt-get install -y \
cd /root
# xserver requires libxcvt
git clone https://gitlab.freedesktop.org/xorg/lib//libxcvt.git --depth 1 --branch=libxcvt-0.1.0
cd libxcvt
meson _build
ninja -C _build -j${FDO_CI_CONCURRENT:-4} install
cd ..
rm -rf libxcvt
# xserver requires xorgproto >= 2021.4.99.2 for XI 2.3.99.1
git clone https://gitlab.freedesktop.org/xorg/proto/xorgproto.git --depth 1 --branch=xorgproto-2021.4.99.2
pushd xorgproto

View File

@ -138,9 +138,15 @@ ProcGEDispatch(ClientPtr client)
static int _X_COLD
SProcGEDispatch(ClientPtr client)
{
GEClientInfoPtr pGEClient = GEGetClient(client);
REQUEST(xGEReq);
if (stuff->ReqType >= GENumberRequests)
if (pGEClient->major_version >= ARRAY_SIZE(version_requests))
return BadRequest;
if (stuff->ReqType > version_requests[pGEClient->major_version])
return BadRequest;
return (*SProcGEVector[stuff->ReqType]) (client);
}

View File

@ -37,8 +37,8 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#define USE_SEL offsetof(SELinuxSubjectRec, sel_use_sid)
typedef struct {
security_context_t octx;
security_context_t dctx;
char *octx;
char *dctx;
CARD32 octx_len;
CARD32 dctx_len;
CARD32 id;
@ -48,10 +48,10 @@ typedef struct {
* Extension Dispatch
*/
static security_context_t
static char *
SELinuxCopyContext(char *ptr, unsigned len)
{
security_context_t copy = malloc(len + 1);
char *copy = malloc(len + 1);
if (!copy)
return NULL;
@ -84,7 +84,7 @@ static int
SELinuxSendContextReply(ClientPtr client, security_id_t sid)
{
SELinuxGetContextReply rep;
security_context_t ctx = NULL;
char *ctx = NULL;
int len = 0;
if (sid) {
@ -117,7 +117,7 @@ ProcSELinuxSetCreateContext(ClientPtr client, unsigned offset)
{
PrivateRec **privPtr = &client->devPrivates;
security_id_t *pSid;
security_context_t ctx = NULL;
char *ctx = NULL;
char *ptr;
int rc;
@ -165,7 +165,7 @@ ProcSELinuxGetCreateContext(ClientPtr client, unsigned offset)
static int
ProcSELinuxSetDeviceContext(ClientPtr client)
{
security_context_t ctx;
char *ctx;
security_id_t sid;
DeviceIntPtr dev;
SELinuxSubjectRec *subj;

View File

@ -114,7 +114,7 @@ SELinuxLabelClient(ClientPtr client)
int fd = XaceGetConnectionNumber(client);
SELinuxSubjectRec *subj;
SELinuxObjectRec *obj;
security_context_t ctx;
char *ctx;
subj = dixLookupPrivate(&client->devPrivates, subjectKey);
obj = dixLookupPrivate(&client->devPrivates, objectKey);
@ -169,7 +169,7 @@ SELinuxLabelInitial(void)
XaceScreenAccessRec srec;
SELinuxSubjectRec *subj;
SELinuxObjectRec *obj;
security_context_t ctx;
char *ctx;
void *unused;
/* Do the serverClient */
@ -773,7 +773,7 @@ SELinuxResourceState(CallbackListPtr *pcbl, void *unused, void *calldata)
subj = dixLookupPrivate(&wClient(pWin)->devPrivates, subjectKey);
if (subj->sid) {
security_context_t ctx;
char *ctx;
int rc = avc_sid_to_context_raw(subj->sid, &ctx);
if (rc < 0)
@ -791,7 +791,7 @@ SELinuxResourceState(CallbackListPtr *pcbl, void *unused, void *calldata)
obj = dixLookupPrivate(&pWin->devPrivates, objectKey);
if (obj->sid) {
security_context_t ctx;
char *ctx;
int rc = avc_sid_to_context_raw(obj->sid, &ctx);
if (rc < 0)
@ -847,7 +847,7 @@ void
SELinuxFlaskInit(void)
{
struct selinux_opt avc_option = { AVC_OPT_SETENFORCE, (char *) 0 };
security_context_t ctx;
char *ctx;
int ret = TRUE;
switch (selinuxEnforcingState) {

View File

@ -97,7 +97,7 @@ static int
SELinuxAtomToSIDLookup(Atom atom, SELinuxObjectRec * obj, int map, int polymap)
{
const char *name = NameForAtom(atom);
security_context_t ctx;
char *ctx;
int rc = Success;
obj->poly = 1;
@ -255,7 +255,7 @@ SELinuxEventToSID(unsigned type, security_id_t sid_of_window,
{
const char *name = LookupEventName(type);
security_id_t sid;
security_context_t ctx;
char *ctx;
type &= 127;
@ -291,7 +291,7 @@ SELinuxEventToSID(unsigned type, security_id_t sid_of_window,
int
SELinuxExtensionToSID(const char *name, security_id_t * sid_rtn)
{
security_context_t ctx;
char *ctx;
/* Look in the mappings of extension names to contexts */
if (selabel_lookup_raw(label_hnd, &ctx, name, SELABEL_X_EXT) < 0) {
@ -347,10 +347,10 @@ SELinuxTypeToClass(RESTYPE type)
return (security_class_t) (unsigned long) tmp;
}
security_context_t
char *
SELinuxDefaultClientLabel(void)
{
security_context_t ctx;
char *ctx;
if (selabel_lookup_raw(label_hnd, &ctx, "remote", SELABEL_X_CLIENT) < 0)
FatalError("SELinux: failed to look up remote-client context\n");

View File

@ -99,7 +99,7 @@ int
security_class_t SELinuxTypeToClass(RESTYPE type);
security_context_t SELinuxDefaultClientLabel(void);
char *SELinuxDefaultClientLabel(void);
void
SELinuxLabelInit(void);

View File

@ -39,6 +39,6 @@
int SProcXIChangeHierarchy(ClientPtr /* client */ );
int ProcXIChangeHierarchy(ClientPtr /* client */ );
void XISendDeviceHierarchyEvent(int flags[]);
void XISendDeviceHierarchyEvent(int flags[MAXDEVICES]);
#endif /* CHDEVHIER_H */

View File

@ -31,7 +31,7 @@ RELEASE_DATE="2021-07-05"
RELEASE_NAME="Carrot and Ginger Soup"
AC_CONFIG_SRCDIR([Makefile.am])
AC_CONFIG_MACRO_DIR([m4])
AM_INIT_AUTOMAKE([foreign dist-bzip2])
AM_INIT_AUTOMAKE([foreign dist-xz])
AC_USE_SYSTEM_EXTENSIONS
# Require xorg-macros minimum of 1.14 for XORG_COMPILER_BRAND in XORG_DEFAULT_OPTIONS
@ -758,6 +758,7 @@ LIBUDEV="libudev >= 143"
LIBSELINUX="libselinux >= 2.0.86"
LIBDBUS="dbus-1 >= 1.0"
LIBPIXMAN="pixman-1 >= 0.27.2"
LIBXCVT="libxcvt"
dnl Pixman is always required, but we separate it out so we can link
dnl specific modules against it
@ -765,7 +766,7 @@ PKG_CHECK_MODULES(PIXMAN, $LIBPIXMAN)
REQUIRED_LIBS="$REQUIRED_LIBS $LIBPIXMAN $LIBXFONT xau"
dnl Core modules for most extensions, et al.
SDK_REQUIRED_MODULES="$XPROTO $RANDRPROTO $RENDERPROTO $XEXTPROTO $INPUTPROTO $KBPROTO $FONTSPROTO $LIBPIXMAN"
SDK_REQUIRED_MODULES="$XPROTO $RANDRPROTO $RENDERPROTO $XEXTPROTO $INPUTPROTO $KBPROTO $FONTSPROTO $LIBPIXMAN $LIBXCVT"
# Make SDK_REQUIRED_MODULES available for inclusion in xorg-server.pc
AC_SUBST(SDK_REQUIRED_MODULES)
@ -1758,11 +1759,14 @@ fi
AC_MSG_RESULT([$XORG])
if test "x$XORG" = xyes; then
PKG_CHECK_MODULES([LIBXCVT], $LIBXCVT)
XORG_DDXINCS='-I$(top_srcdir)/hw/xfree86 -I$(top_srcdir)/hw/xfree86/include -I$(top_srcdir)/hw/xfree86/common'
XORG_OSINCS='-I$(top_srcdir)/hw/xfree86/os-support -I$(top_srcdir)/hw/xfree86/os-support/bus -I$(top_srcdir)/os'
XORG_INCS="$XORG_DDXINCS $XORG_OSINCS"
XORG_CFLAGS="$XORGSERVER_CFLAGS -DHAVE_XORG_CONFIG_H"
XORG_CFLAGS="$XORGSERVER_CFLAGS $LIBXCVT_CFLAGS -DHAVE_XORG_CONFIG_H"
XORG_LIBS="$COMPOSITE_LIB $FIXES_LIB $XEXT_LIB $DBE_LIB $RECORD_LIB $RANDR_LIB $RENDER_LIB $DAMAGE_LIB $DRI3_LIB $PRESENT_LIB $MIEXT_SYNC_LIB $MIEXT_DAMAGE_LIB $XI_LIB $XKB_LIB"
XORG_SYS_LIBS="$XORG_SYS_LIBS $LIBXCVT_LIBS"
dnl ==================================================================
dnl symbol visibility
@ -2347,8 +2351,10 @@ if test "x$XWAYLAND" = xyes; then
AC_SUBST(have_eglstream, "false")
fi
PKG_CHECK_MODULES([LIBXCVT], $LIBXCVT)
XWAYLAND_LIBS="$FB_LIB $FIXES_LIB $MI_LIB $XEXT_LIB $DBE_LIB $RECORD_LIB $GLX_LIBS $RANDR_LIB $RENDER_LIB $DAMAGE_LIB $DRI3_LIB $PRESENT_LIB $MIEXT_SYNC_LIB $MIEXT_DAMAGE_LIB $MIEXT_SHADOW_LIB $XI_LIB $XKB_LIB $XKB_STUB_LIB $COMPOSITE_LIB $MAIN_LIB $DIX_LIB $OS_LIB"
XWAYLAND_SYS_LIBS="$XWAYLANDMODULES_LIBS $GLX_SYS_LIBS"
XWAYLAND_SYS_LIBS="$XWAYLANDMODULES_LIBS $GLX_SYS_LIBS $LIBXCVT_LIBS"
AC_SUBST([XWAYLAND_LIBS])
AC_SUBST([XWAYLAND_SYS_LIBS])
@ -2482,7 +2488,6 @@ hw/xfree86/x86emu/Makefile
hw/xfree86/xkb/Makefile
hw/xfree86/utils/Makefile
hw/xfree86/utils/man/Makefile
hw/xfree86/utils/cvt/Makefile
hw/xfree86/utils/gtf/Makefile
hw/dmx/config/Makefile
hw/dmx/config/man/Makefile

View File

@ -561,7 +561,11 @@ static int _X_COLD
SProcDamageDispatch(ClientPtr client)
{
REQUEST(xDamageReq);
if (stuff->damageReqType >= XDamageNumberRequests)
DamageClientPtr pDamageClient = GetDamageClient(client);
if (pDamageClient->major_version >= ARRAY_SIZE(version_requests))
return BadRequest;
if (stuff->damageReqType > version_requests[pDamageClient->major_version])
return BadRequest;
return (*SProcDamageVector[stuff->damageReqType]) (client);
}

View File

@ -253,7 +253,7 @@ ProcChangeProperty(ClientPtr client)
int
dixChangeWindowProperty(ClientPtr pClient, WindowPtr pWin, Atom property,
Atom type, int format, int mode, unsigned long len,
void *value, Bool sendevent)
const void *value, Bool sendevent)
{
PropertyPtr pProp;
PropertyRec savedProp;

64
doc/dtrace/meson.build Normal file
View File

@ -0,0 +1,64 @@
if build_docs
basename = 'Xserver-DTrace'
input_xml = basename + '.xml'
custom_target(
basename + '.html',
output: basename + '.html',
input: [input_xml],
command: [xmlto] + docs_xmlto_search_flags + [
'-x', join_paths(doc_stylesheet_srcdir, 'xorg-xhtml.xsl'),
'--stringparam', 'target.database.document=' + join_paths(doc_sgml_path, 'X11/dbs/masterdb.html.xml'),
'--stringparam', 'current.docid=' + basename,
'-o', meson.current_build_dir(),
'xhtml-nochunks', '@INPUT0@'],
build_by_default: true,
install: true,
install_dir: join_paths(get_option('datadir'), 'doc/xorg-server'),
)
if build_docs_pdf
foreach format : ['ps', 'pdf']
output_fn = basename + '.' + format
custom_target(
output_fn,
output: output_fn,
input: [input_xml],
command: [xmlto] + docs_xmlto_search_flags + [
'-x', join_paths(doc_stylesheet_srcdir, 'xorg-fo.xsl'),
'--stringparam', 'img.src.path=' + meson.current_build_dir(),
'--stringparam', 'target.database.document=' + join_paths(doc_sgml_path, 'X11/dbs/masterdb.pdf.xml'),
'--stringparam', 'current.docid=' + basename,
'-o', meson.current_build_dir(),
'--with-fop', format, '@INPUT0@'],
build_by_default: true,
install: true,
install_dir: join_paths(get_option('datadir'), 'doc/xorg-server'),
)
endforeach
endif
foreach format_data : [['html', 'xorg-xhtml.xsl'], ['pdf', 'xorg-fo.xsl']]
format = format_data[0]
stylesheet = format_data[1]
output_fn = basename + '.' + format + '.db'
custom_target(
output_fn,
output: output_fn,
input: [input_xml],
command: [xsltproc] + docs_xslt_search_flags + [
'--stringparam', 'targets.filename', output_fn,
'--stringparam', 'collect.xref.targets', 'only',
'--stringparam', 'olink.base.uri', basename + '.' + format,
'--nonet',
'--output', join_paths(meson.current_build_dir(), output_fn),
'--xinclude', join_paths(doc_stylesheet_srcdir, stylesheet),
'@INPUT0@'],
build_by_default: true,
install: true,
install_dir: join_paths(get_option('datadir'), 'doc/xorg-server'),
)
endforeach
endif

39
doc/meson.build Normal file
View File

@ -0,0 +1,39 @@
if build_docs_devel
foreach basename : ['Xserver-spec', 'Xinput']
input_xml = basename + '.xml'
custom_target(
basename + '.html',
output: basename + '.html',
input: [input_xml],
command: [xmlto] + docs_xmlto_search_flags + [
'-x', join_paths(doc_stylesheet_srcdir, 'xorg-xhtml.xsl'),
'-o', meson.current_build_dir(),
'xhtml-nochunks', '@INPUT0@'],
build_by_default: true,
install: false,
)
if build_docs_pdf
foreach format : ['ps', 'pdf']
output_fn = basename + '.' + format
custom_target(
output_fn,
output: output_fn,
input: [input_xml],
command: [xmlto] + docs_xmlto_search_flags + [
'-x', join_paths(doc_stylesheet_srcdir, 'xorg-fo.xsl'),
'--stringparam', 'img.src.path=' + meson.current_build_dir(),
'-o', meson.current_build_dir(),
'--with-fop', format, '@INPUT0@'],
build_by_default: true,
install: false,
)
endforeach
endif
endforeach
endif
subdir('dtrace')

View File

@ -746,7 +746,7 @@ glamor_init(ScreenPtr screen, unsigned int flags)
* have instanced arrays, but this is not always the case.
* etnaviv offers GLSL 140 with OpenGL 2.1.
*/
if (glamor_priv->glsl_version >= 130 &&
if (glamor_glsl_has_ints(glamor_priv) &&
!epoxy_has_gl_extension("GL_ARB_instanced_arrays"))
glamor_priv->glsl_version = 120;
} else {
@ -772,6 +772,10 @@ glamor_init(ScreenPtr screen, unsigned int flags)
goto fail;
}
if (!glamor_priv->is_gles && glamor_priv->glsl_version == 120 &&
epoxy_has_gl_extension("GL_ARB_instanced_arrays"))
glamor_priv->use_gpu_shader4 = epoxy_has_gl_extension("GL_EXT_gpu_shader4");
glamor_priv->has_rw_pbo = FALSE;
if (!glamor_priv->is_gles)
glamor_priv->has_rw_pbo = TRUE;
@ -799,7 +803,7 @@ glamor_init(ScreenPtr screen, unsigned int flags)
epoxy_gl_version() >= 30 ||
epoxy_has_gl_extension("GL_NV_pack_subimage");
glamor_priv->has_dual_blend =
glamor_priv->glsl_version >= 130 &&
glamor_glsl_has_ints(glamor_priv) &&
epoxy_has_gl_extension("GL_ARB_blend_func_extended");
glamor_priv->has_clear_texture =
epoxy_gl_version() >= 44 ||

View File

@ -208,11 +208,6 @@ static const glamor_facet glamor_facet_composite_glyphs_120 = {
.locations = glamor_program_location_atlas,
};
static inline Bool
glamor_glyph_use_130(glamor_screen_private *glamor_priv) {
return glamor_priv->glsl_version >= 130;
}
static Bool
glamor_glyphs_init_facet(ScreenPtr screen)
{
@ -274,7 +269,7 @@ glamor_glyphs_flush(CARD8 op, PicturePtr src, PicturePtr dst,
box->y2 - box->y1);
box++;
if (glamor_glyph_use_130(glamor_priv))
if (glamor_glsl_has_ints(glamor_priv))
glDrawArraysInstanced(GL_TRIANGLE_STRIP, 0, 4, nglyph);
else
glamor_glDrawArrays_GL_QUADS(glamor_priv, nglyph);
@ -287,7 +282,7 @@ glamor_glyphs_flush(CARD8 op, PicturePtr src, PicturePtr dst,
glDisable(GL_SCISSOR_TEST);
if (glamor_glyph_use_130(glamor_priv)) {
if (glamor_glsl_has_ints(glamor_priv)) {
glVertexAttribDivisor(GLAMOR_VERTEX_SOURCE, 0);
glVertexAttribDivisor(GLAMOR_VERTEX_POS, 0);
}
@ -305,7 +300,7 @@ glamor_glyph_start(ScreenPtr screen, int count)
/* Set up the vertex buffers for the font and destination */
if (glamor_glyph_use_130(glamor_priv)) {
if (glamor_glsl_has_ints(glamor_priv)) {
v = glamor_get_vbo_space(screen, count * (6 * sizeof (GLshort)), &vbo_offset);
glEnableVertexAttribArray(GLAMOR_VERTEX_POS);
@ -439,7 +434,7 @@ glamor_composite_glyphs(CARD8 op,
/* First glyph in the current atlas?
*/
if (_X_UNLIKELY(glyphs_queued == 0)) {
if (glamor_glyph_use_130(glamor_priv))
if (glamor_glsl_has_ints(glamor_priv))
prog = glamor_setup_program_render(op, src, glyph_pict, dst,
glyphs_program,
&glamor_facet_composite_glyphs_130,
@ -458,7 +453,7 @@ glamor_composite_glyphs(CARD8 op,
*/
glyphs_queued++;
if (_X_LIKELY(glamor_glyph_use_130(glamor_priv))) {
if (_X_LIKELY(glamor_glsl_has_ints(glamor_priv))) {
v[0] = x - glyph->info.x;
v[1] = y - glyph->info.y;
v[2] = glyph_draw->width;

View File

@ -1060,9 +1060,14 @@ glamor_egl_init(ScrnInfoPtr scrn, int fd)
goto error;
}
if (strstr((const char *)renderer, "llvmpipe")) {
xf86DrvMsg(scrn->scrnIndex, X_INFO,
"Refusing to try glamor on llvmpipe\n");
goto error;
if (scrn->confScreen->num_gpu_devices)
xf86DrvMsg(scrn->scrnIndex, X_INFO,
"Allowing glamor on llvmpipe for PRIME\n");
else {
xf86DrvMsg(scrn->scrnIndex, X_INFO,
"Refusing to try glamor on llvmpipe\n");
goto error;
}
}
/*

View File

@ -47,7 +47,7 @@ glamor_font_get(ScreenPtr screen, FontPtr font)
unsigned long count;
char *bits;
if (glamor_priv->glsl_version < 130)
if (!glamor_glsl_has_ints(glamor_priv))
return NULL;
privates = FontGetPrivate(font, glamor_font_private_index);
@ -210,7 +210,7 @@ glamor_font_init(ScreenPtr screen)
{
glamor_screen_private *glamor_priv = glamor_get_screen_private(screen);
if (glamor_priv->glsl_version < 130)
if (!glamor_glsl_has_ints(glamor_priv))
return TRUE;
if (glamor_font_generation != serverGeneration) {

View File

@ -213,6 +213,7 @@ typedef struct glamor_screen_private {
Bool has_texture_swizzle;
Bool is_core_profile;
Bool can_copyplane;
Bool use_gpu_shader4;
int max_fbo_size;
struct glamor_format formats[33];

View File

@ -187,6 +187,7 @@ fs_location_vars(glamor_program_location locations)
static const char vs_template[] =
"%s" /* version */
"%s" /* exts */
"%s" /* defines */
"%s" /* prim vs_vars */
"%s" /* fill vs_vars */
@ -199,6 +200,7 @@ static const char vs_template[] =
static const char fs_template[] =
"%s" /* version */
"%s" /* exts */
GLAMOR_DEFAULT_PRECISION
"%s" /* defines */
"%s" /* prim fs_vars */
@ -262,6 +264,7 @@ glamor_build_program(ScreenPtr screen,
char *fs_prog_string;
GLint fs_prog, vs_prog;
Bool gpu_shader4 = FALSE;
if (!fill)
fill = &facet_null_fill;
@ -270,8 +273,14 @@ glamor_build_program(ScreenPtr screen,
flags |= fill->flags;
version = MAX(version, fill->version);
if (version > glamor_priv->glsl_version)
goto fail;
if (version > glamor_priv->glsl_version) {
if (version == 130 && !glamor_priv->use_gpu_shader4)
goto fail;
else {
version = 120;
gpu_shader4 = TRUE;
}
}
vs_vars = vs_location_vars(locations);
fs_vars = fs_location_vars(locations);
@ -291,6 +300,7 @@ glamor_build_program(ScreenPtr screen,
if (asprintf(&vs_prog_string,
vs_template,
str(version_string),
gpu_shader4 ? "#extension GL_EXT_gpu_shader4 : require\n" : "",
str(defines),
str(prim->vs_vars),
str(fill->vs_vars),
@ -302,6 +312,7 @@ glamor_build_program(ScreenPtr screen,
if (asprintf(&fs_prog_string,
fs_template,
str(version_string),
gpu_shader4 ? "#extension GL_EXT_gpu_shader4 : require\n#define texelFetch texelFetch2D\n#define uint unsigned int\n" : "",
str(defines),
str(prim->fs_vars),
str(fill->fs_vars),

View File

@ -69,7 +69,7 @@ glamor_poly_fill_rect_gl(DrawablePtr drawable,
glamor_bounds_union_rect(&bounds, &prect[i]);
}
if (glamor_priv->glsl_version >= 130) {
if (glamor_glsl_has_ints(glamor_priv)) {
prog = glamor_use_program_fill(pixmap, gc,
&glamor_priv->poly_fill_rect_program,
&glamor_facet_polyfillrect_130);
@ -151,7 +151,7 @@ glamor_poly_fill_rect_gl(DrawablePtr drawable,
scissor.y1 + off_y,
scissor.x2 - scissor.x1,
scissor.y2 - scissor.y1);
if (glamor_priv->glsl_version >= 130)
if (glamor_glsl_has_ints(glamor_priv))
glDrawArraysInstanced(GL_TRIANGLE_STRIP, 0, 4, nrect);
else {
glamor_glDrawArrays_GL_QUADS(glamor_priv, nrect);
@ -163,7 +163,7 @@ glamor_poly_fill_rect_gl(DrawablePtr drawable,
bail:
glDisable(GL_SCISSOR_TEST);
if (glamor_priv->glsl_version >= 130) {
if (glamor_glsl_has_ints(glamor_priv)) {
glVertexAttribDivisor(GLAMOR_VERTEX_SOURCE, 0);
glDisableVertexAttribArray(GLAMOR_VERTEX_SOURCE);
glVertexAttribDivisor(GLAMOR_VERTEX_POS, 0);

View File

@ -560,8 +560,8 @@ glamor_set_composite_texture(glamor_screen_private *glamor_priv, int unit,
case PictFilterGood:
case PictFilterBest:
case PictFilterBilinear:
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
break;
}

View File

@ -64,7 +64,7 @@ glamor_fill_spans_gl(DrawablePtr drawable,
glamor_make_current(glamor_priv);
if (glamor_priv->glsl_version >= 130) {
if (glamor_glsl_has_ints(glamor_priv)) {
prog = glamor_use_program_fill(pixmap, gc, &glamor_priv->fill_spans_program,
&glamor_facet_fillspans_130);
@ -134,7 +134,7 @@ glamor_fill_spans_gl(DrawablePtr drawable,
box->x2 - box->x1,
box->y2 - box->y1);
box++;
if (glamor_priv->glsl_version >= 130)
if (glamor_glsl_has_ints(glamor_priv))
glDrawArraysInstanced(GL_TRIANGLE_STRIP, 0, 4, n);
else {
glamor_glDrawArrays_GL_QUADS(glamor_priv, n);
@ -146,7 +146,7 @@ glamor_fill_spans_gl(DrawablePtr drawable,
bail:
glDisable(GL_SCISSOR_TEST);
if (glamor_priv->glsl_version >= 130)
if (glamor_glsl_has_ints(glamor_priv))
glVertexAttribDivisor(GLAMOR_VERTEX_POS, 0);
glDisableVertexAttribArray(GLAMOR_VERTEX_POS);

View File

@ -732,5 +732,9 @@ glamor_glDrawArrays_GL_QUADS(glamor_screen_private *glamor_priv, unsigned count)
}
}
static inline Bool
glamor_glsl_has_ints(glamor_screen_private *glamor_priv) {
return glamor_priv->glsl_version >= 130 || glamor_priv->use_gpu_shader4;
}
#endif

View File

@ -380,15 +380,15 @@ glamor_xv_render(glamor_port_private *port_priv, int id)
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, src_pixmap_priv[0]->fbo->tex);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, src_pixmap_priv[1]->fbo->tex);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
@ -397,8 +397,8 @@ glamor_xv_render(glamor_port_private *port_priv, int id)
case FOURCC_I420:
glActiveTexture(GL_TEXTURE2);
glBindTexture(GL_TEXTURE_2D, src_pixmap_priv[2]->fbo->tex);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
break;

View File

@ -72,7 +72,6 @@ typedef struct DMXConfigCmdStruct {
DMXConfigList *xinputs;
} DMXConfigCmd, *DMXConfigCmdPtr;
extern DMXConfigEntryPtr dmxConfigEntry;
static DMXConfigCmd dmxConfigCmd;
static int dmxDisplaysFromCommandLine;

View File

@ -65,7 +65,6 @@ extern FILE *yyin;
#define DMX_CANVAS_WIDTH 400
#define DMX_CANVAS_HEIGHT 500
extern DMXConfigEntryPtr dmxConfigEntry;
static DMXConfigVirtualPtr dmxConfigCurrent, dmxConfigNewVirtual;
static DMXConfigDisplayPtr dmxConfigCurrentDisplay, dmxConfigNewDisplay;
static int dmxConfigGrabbed, dmxConfigGrabbedFine;

37
hw/dmx/doc/meson.build Normal file
View File

@ -0,0 +1,37 @@
if build_docs_devel
foreach basename : ['dmx', 'scaled']
input_xml = basename + '.xml'
custom_target(
basename + '.html',
output: basename + '.html',
input: [input_xml],
command: [xmlto] + docs_xmlto_search_flags + [
'-x', join_paths(doc_stylesheet_srcdir, 'xorg-xhtml.xsl'),
'-o', meson.current_build_dir(),
'xhtml-nochunks', '@INPUT0@'],
build_by_default: true,
install: false,
)
if build_docs_pdf
foreach format : ['ps', 'pdf']
output_fn = basename + '.' + format
custom_target(
output_fn,
output: output_fn,
input: [input_xml],
command: [xmlto] + docs_xmlto_search_flags + [
'-x', join_paths(doc_stylesheet_srcdir, 'xorg-fo.xsl'),
'--stringparam', 'img.src.path=' + meson.current_build_dir(),
'-o', meson.current_build_dir(),
'--with-fop', format, '@INPUT0@'],
build_by_default: true,
install: false,
)
endforeach
endif
endforeach
endif

View File

@ -27,7 +27,7 @@ srcs = [
subdir('config')
subdir('input')
subdir('examples')
# XXX: subdir('doc')
subdir('doc')
# XXX: subdir('doxygen')
install_man(configure_file(

View File

@ -106,6 +106,37 @@ xf86CallDriverProbe(DriverPtr drv, Bool detect_only)
return foundScreen;
}
static screenLayoutPtr
xf86BusConfigMatch(ScrnInfoPtr scrnInfo, Bool is_gpu) {
screenLayoutPtr layout;
int i, j;
for (layout = xf86ConfigLayout.screens; layout->screen != NULL;
layout++) {
for (i = 0; i < scrnInfo->numEntities; i++) {
GDevPtr dev =
xf86GetDevFromEntity(scrnInfo->entityList[i],
scrnInfo->entityInstanceList[i]);
if (is_gpu) {
for (j = 0; j < layout->screen->num_gpu_devices; j++) {
if (dev == layout->screen->gpu_devices[j]) {
/* A match has been found */
return layout;
}
}
} else {
if (dev == layout->screen->device) {
/* A match has been found */
return layout;
}
}
}
}
return NULL;
}
/**
* @return TRUE if all buses are configured and set up correctly and FALSE
* otherwise.
@ -114,7 +145,7 @@ Bool
xf86BusConfig(void)
{
screenLayoutPtr layout;
int i, j;
int i;
/*
* 3 step probe to (hopefully) ensure that we always find at least 1
@ -170,27 +201,10 @@ xf86BusConfig(void)
*
*/
for (i = 0; i < xf86NumScreens; i++) {
for (layout = xf86ConfigLayout.screens; layout->screen != NULL;
layout++) {
Bool found = FALSE;
for (j = 0; j < xf86Screens[i]->numEntities; j++) {
GDevPtr dev =
xf86GetDevFromEntity(xf86Screens[i]->entityList[j],
xf86Screens[i]->entityInstanceList[j]);
if (dev == layout->screen->device) {
/* A match has been found */
xf86Screens[i]->confScreen = layout->screen;
found = TRUE;
break;
}
}
if (found)
break;
}
if (layout->screen == NULL) {
layout = xf86BusConfigMatch(xf86Screens[i], FALSE);
if (layout && layout->screen)
xf86Screens[i]->confScreen = layout->screen;
else {
/* No match found */
xf86Msg(X_ERROR,
"Screen %d deleted because of no matching config section.\n",
@ -199,9 +213,12 @@ xf86BusConfig(void)
}
}
/* bind GPU conf screen to protocol screen 0 */
for (i = 0; i < xf86NumGPUScreens; i++)
xf86GPUScreens[i]->confScreen = xf86Screens[0]->confScreen;
/* bind GPU conf screen to the configured protocol screen, or 0 if not configured */
for (i = 0; i < xf86NumGPUScreens; i++) {
layout = xf86BusConfigMatch(xf86GPUScreens[i], TRUE);
int scrnum = (layout && layout->screen) ? layout->screen->screennum : 0;
xf86GPUScreens[i]->confScreen = xf86Screens[scrnum]->confScreen;
}
/* If no screens left, return now. */
if (xf86NumScreens == 0) {

View File

@ -209,9 +209,11 @@ xf86AutoConfigOutputDevices(void)
if (!xf86Info.autoBindGPU)
return;
for (i = 0; i < xf86NumGPUScreens; i++)
for (i = 0; i < xf86NumGPUScreens; i++) {
int scrnum = xf86GPUScreens[i]->confScreen->screennum;
RRProviderAutoConfigGpuScreen(xf86ScrnToScreen(xf86GPUScreens[i]),
xf86ScrnToScreen(xf86Screens[0]));
xf86ScrnToScreen(xf86Screens[scrnum]));
}
}
static void
@ -689,8 +691,10 @@ InitOutput(ScreenInfo * pScreenInfo, int argc, char **argv)
}
}
for (i = 0; i < xf86NumGPUScreens; i++)
AttachUnboundGPU(xf86Screens[0]->pScreen, xf86GPUScreens[i]->pScreen);
for (i = 0; i < xf86NumGPUScreens; i++) {
int scrnum = xf86GPUScreens[i]->confScreen->screennum;
AttachUnboundGPU(xf86Screens[scrnum]->pScreen, xf86GPUScreens[i]->pScreen);
}
xf86AutoConfigOutputDevices();

View File

@ -608,7 +608,7 @@ xf86platformAddGPUDevices(DriverPtr drvp)
int
xf86platformAddDevice(int index)
{
int i, old_screens, scr_index;
int i, old_screens, scr_index, scrnum;
DriverPtr drvp = NULL;
screenLayoutPtr layout;
static const char *hotplug_driver_name = "modesetting";
@ -674,14 +674,15 @@ xf86platformAddDevice(int index)
xf86NumGPUScreens = old_screens;
return -1;
}
/* attach unbound to 0 protocol screen */
AttachUnboundGPU(xf86Screens[0]->pScreen, xf86GPUScreens[i]->pScreen);
/* attach unbound to the configured protocol screen (or 0) */
scrnum = xf86GPUScreens[i]->confScreen->screennum;
AttachUnboundGPU(xf86Screens[scrnum]->pScreen, xf86GPUScreens[i]->pScreen);
if (xf86Info.autoBindGPU)
RRProviderAutoConfigGpuScreen(xf86ScrnToScreen(xf86GPUScreens[i]),
xf86ScrnToScreen(xf86Screens[0]));
xf86ScrnToScreen(xf86Screens[scrnum]));
RRResourcesChanged(xf86Screens[0]->pScreen);
RRTellChanged(xf86Screens[0]->pScreen);
RRResourcesChanged(xf86Screens[scrnum]->pScreen);
RRTellChanged(xf86Screens[scrnum]->pScreen);
return 0;
}
@ -690,7 +691,7 @@ void
xf86platformRemoveDevice(int index)
{
EntityPtr entity;
int ent_num, i, j;
int ent_num, i, j, scrnum;
Bool found;
for (ent_num = 0; ent_num < xf86NumEntities; ent_num++) {
@ -717,6 +718,8 @@ xf86platformRemoveDevice(int index)
goto out;
}
scrnum = xf86GPUScreens[i]->confScreen->screennum;
xf86GPUScreens[i]->pScreen->CloseScreen(xf86GPUScreens[i]->pScreen);
RemoveGPUScreen(xf86GPUScreens[i]->pScreen);
@ -726,8 +729,8 @@ xf86platformRemoveDevice(int index)
xf86_remove_platform_device(index);
RRResourcesChanged(xf86Screens[0]->pScreen);
RRTellChanged(xf86Screens[0]->pScreen);
RRResourcesChanged(xf86Screens[scrnum]->pScreen);
RRTellChanged(xf86Screens[scrnum]->pScreen);
out:
return;
}

View File

@ -0,0 +1,35 @@
if build_docs_devel
basename = 'ddxDesign'
input_xml = basename + '.xml'
custom_target(
basename + '.html',
output: basename + '.html',
input: [input_xml],
command: [xmlto] + docs_xmlto_search_flags + [
'-x', join_paths(doc_stylesheet_srcdir, 'xorg-xhtml.xsl'),
'-o', meson.current_build_dir(),
'xhtml-nochunks', '@INPUT0@'],
build_by_default: true,
install: false,
)
if build_docs_pdf
foreach format : ['ps', 'pdf']
output_fn = basename + '.' + format
custom_target(
output_fn,
output: output_fn,
input: [input_xml],
command: [xmlto] + docs_xmlto_search_flags + [
'-x', join_paths(doc_stylesheet_srcdir, 'xorg-fo.xsl'),
'--stringparam', 'img.src.path=' + meson.current_build_dir(),
'-o', meson.current_build_dir(),
'--with-fop', format, '@INPUT0@'],
build_by_default: true,
install: false,
)
endforeach
endif
endif

View File

@ -272,6 +272,9 @@ ms_present_check_unflip(RRCrtcPtr crtc,
pixmap->devKind != drmmode_bo_get_pitch(&ms->drmmode.front_bo))
return FALSE;
if (!ms->drmmode.glamor)
return FALSE;
#ifdef GBM_BO_WITH_MODIFIERS
/* Check if buffer format/modifier is supported by all active CRTCs */
gbm = ms->glamor.gbm_bo_from_pixmap(screen, pixmap);

View File

@ -171,15 +171,6 @@ if get_option('suid_wrapper')
)
endif
executable('cvt',
['utils/cvt/cvt.c', 'modes/xf86cvt.c'],
include_directories: [inc, xorg_inc],
dependencies: xorg_deps,
link_with: libxserver_os,
c_args: xorg_c_args,
install: true,
)
executable('gtf',
'utils/gtf/gtf.c',
include_directories: [inc, xorg_inc],
@ -234,14 +225,10 @@ install_man(configure_file(
configuration: manpage_config,
))
install_man(configure_file(
input: 'utils/man/cvt.man',
output: 'cvt.1',
configuration: manpage_config,
))
install_man(configure_file(
input: 'utils/man/gtf.man',
output: 'gtf.1',
configuration: manpage_config,
))
subdir('doc')

View File

@ -8,7 +8,6 @@ libxf86modes_la_SOURCES = \
xf86Crtc.c \
xf86Crtc.h \
xf86Cursors.c \
xf86cvt.c \
xf86gtf.c \
xf86EdidModes.c \
xf86Modes.c \

View File

@ -1,7 +1,6 @@
srcs_xorg_modes = [
'xf86Crtc.c',
'xf86Cursors.c',
'xf86cvt.c',
'xf86gtf.c',
'xf86EdidModes.c',
'xf86Modes.c',
@ -15,8 +14,8 @@ endif
xorg_modes = static_library('xorg_modes',
srcs_xorg_modes,
include_directories: [inc, xorg_inc],
dependencies: common_dep,
include_directories: [ inc, xorg_inc ],
dependencies: [ common_dep, libxcvt_dep ],
c_args: xorg_c_args,
)

View File

@ -29,6 +29,7 @@
#include <xorg-config.h>
#endif
#include <libxcvt/libxcvt.h>
#include "xf86Modes.h"
#include "xf86Priv.h"
@ -792,3 +793,33 @@ xf86PruneDuplicateModes(DisplayModePtr modes)
return modes;
}
/*
* Generate a CVT standard mode from HDisplay, VDisplay and VRefresh.
*/
DisplayModePtr
xf86CVTMode(int HDisplay, int VDisplay, float VRefresh, Bool Reduced,
Bool Interlaced)
{
struct libxcvt_mode_info *libxcvt_mode_info;
DisplayModeRec *Mode = xnfcalloc(1, sizeof(DisplayModeRec));
libxcvt_mode_info =
libxcvt_gen_mode_info(HDisplay, VDisplay, VRefresh, Reduced, Interlaced);
Mode->VDisplay = libxcvt_mode_info->vdisplay;
Mode->HDisplay = libxcvt_mode_info->hdisplay;
Mode->Clock = libxcvt_mode_info->dot_clock;
Mode->HSyncStart = libxcvt_mode_info->hsync_start;
Mode->HSyncEnd = libxcvt_mode_info->hsync_end;
Mode->HTotal = libxcvt_mode_info->htotal;
Mode->VSyncStart = libxcvt_mode_info->vsync_start;
Mode->VSyncEnd = libxcvt_mode_info->vsync_end;
Mode->VTotal = libxcvt_mode_info->vtotal;
Mode->VRefresh = libxcvt_mode_info->vrefresh;
Mode->Flags = libxcvt_mode_info->mode_flags;
free(libxcvt_mode_info);
return Mode;
}

View File

@ -1,295 +0,0 @@
/*
* Copyright 2005-2006 Luc Verhaegen.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
/*
* The reason for having this function in a file of its own is
* so that ../utils/cvt/cvt can link to it, and that xf86CVTMode
* code is shared directly.
*/
#ifdef HAVE_XORG_CONFIG_H
#include <xorg-config.h>
#endif
#include "xf86.h"
#include "xf86Modes.h"
#include <string.h>
/*
* Generate a CVT standard mode from HDisplay, VDisplay and VRefresh.
*
* These calculations are stolen from the CVT calculation spreadsheet written
* by Graham Loveridge. He seems to be claiming no copyright and there seems to
* be no license attached to this. He apparently just wants to see his name
* mentioned.
*
* This file can be found at http://www.vesa.org/Public/CVT/CVTd6r1.xls
*
* Comments and structure corresponds to the comments and structure of the xls.
* This should ease importing of future changes to the standard (not very
* likely though).
*
* About margins; i'm sure that they are to be the bit between HDisplay and
* HBlankStart, HBlankEnd and HTotal, VDisplay and VBlankStart, VBlankEnd and
* VTotal, where the overscan colour is shown. FB seems to call _all_ blanking
* outside sync "margin" for some reason. Since we prefer seeing proper
* blanking instead of the overscan colour, and since the Crtc* values will
* probably get altered after us, we will disable margins altogether. With
* these calculations, Margins will plainly expand H/VDisplay, and we don't
* want that. -- libv
*
*/
DisplayModePtr
xf86CVTMode(int HDisplay, int VDisplay, float VRefresh, Bool Reduced,
Bool Interlaced)
{
DisplayModeRec *Mode = xnfcalloc(1, sizeof(DisplayModeRec));
/* 1) top/bottom margin size (% of height) - default: 1.8 */
#define CVT_MARGIN_PERCENTAGE 1.8
/* 2) character cell horizontal granularity (pixels) - default 8 */
#define CVT_H_GRANULARITY 8
/* 4) Minimum vertical porch (lines) - default 3 */
#define CVT_MIN_V_PORCH 3
/* 4) Minimum number of vertical back porch lines - default 6 */
#define CVT_MIN_V_BPORCH 6
/* Pixel Clock step (kHz) */
#define CVT_CLOCK_STEP 250
Bool Margins = FALSE;
float VFieldRate, HPeriod;
int HDisplayRnd, HMargin;
int VDisplayRnd, VMargin, VSync;
float Interlace; /* Please rename this */
char *tmp;
/* CVT default is 60.0Hz */
if (!VRefresh)
VRefresh = 60.0;
/* 1. Required field rate */
if (Interlaced)
VFieldRate = VRefresh * 2;
else
VFieldRate = VRefresh;
/* 2. Horizontal pixels */
HDisplayRnd = HDisplay - (HDisplay % CVT_H_GRANULARITY);
/* 3. Determine left and right borders */
if (Margins) {
/* right margin is actually exactly the same as left */
HMargin = (((float) HDisplayRnd) * CVT_MARGIN_PERCENTAGE / 100.0);
HMargin -= HMargin % CVT_H_GRANULARITY;
}
else
HMargin = 0;
/* 4. Find total active pixels */
Mode->HDisplay = HDisplayRnd + 2 * HMargin;
/* 5. Find number of lines per field */
if (Interlaced)
VDisplayRnd = VDisplay / 2;
else
VDisplayRnd = VDisplay;
/* 6. Find top and bottom margins */
/* nope. */
if (Margins)
/* top and bottom margins are equal again. */
VMargin = (((float) VDisplayRnd) * CVT_MARGIN_PERCENTAGE / 100.0);
else
VMargin = 0;
Mode->VDisplay = VDisplay + 2 * VMargin;
/* 7. Interlace */
if (Interlaced)
Interlace = 0.5;
else
Interlace = 0.0;
/* Determine VSync Width from aspect ratio */
if (!(VDisplay % 3) && ((VDisplay * 4 / 3) == HDisplay))
VSync = 4;
else if (!(VDisplay % 9) && ((VDisplay * 16 / 9) == HDisplay))
VSync = 5;
else if (!(VDisplay % 10) && ((VDisplay * 16 / 10) == HDisplay))
VSync = 6;
else if (!(VDisplay % 4) && ((VDisplay * 5 / 4) == HDisplay))
VSync = 7;
else if (!(VDisplay % 9) && ((VDisplay * 15 / 9) == HDisplay))
VSync = 7;
else /* Custom */
VSync = 10;
if (!Reduced) { /* simplified GTF calculation */
/* 4) Minimum time of vertical sync + back porch interval (µs)
* default 550.0 */
#define CVT_MIN_VSYNC_BP 550.0
/* 3) Nominal HSync width (% of line period) - default 8 */
#define CVT_HSYNC_PERCENTAGE 8
float HBlankPercentage;
int VSyncAndBackPorch, VBackPorch;
int HBlank;
/* 8. Estimated Horizontal period */
HPeriod = ((float) (1000000.0 / VFieldRate - CVT_MIN_VSYNC_BP)) /
(VDisplayRnd + 2 * VMargin + CVT_MIN_V_PORCH + Interlace);
/* 9. Find number of lines in sync + backporch */
if (((int) (CVT_MIN_VSYNC_BP / HPeriod) + 1) <
(VSync + CVT_MIN_V_PORCH))
VSyncAndBackPorch = VSync + CVT_MIN_V_PORCH;
else
VSyncAndBackPorch = (int) (CVT_MIN_VSYNC_BP / HPeriod) + 1;
/* 10. Find number of lines in back porch */
VBackPorch = VSyncAndBackPorch - VSync;
(void) VBackPorch;
/* 11. Find total number of lines in vertical field */
Mode->VTotal = VDisplayRnd + 2 * VMargin + VSyncAndBackPorch + Interlace
+ CVT_MIN_V_PORCH;
/* 5) Definition of Horizontal blanking time limitation */
/* Gradient (%/kHz) - default 600 */
#define CVT_M_FACTOR 600
/* Offset (%) - default 40 */
#define CVT_C_FACTOR 40
/* Blanking time scaling factor - default 128 */
#define CVT_K_FACTOR 128
/* Scaling factor weighting - default 20 */
#define CVT_J_FACTOR 20
#define CVT_M_PRIME CVT_M_FACTOR * CVT_K_FACTOR / 256
#define CVT_C_PRIME (CVT_C_FACTOR - CVT_J_FACTOR) * CVT_K_FACTOR / 256 + \
CVT_J_FACTOR
/* 12. Find ideal blanking duty cycle from formula */
HBlankPercentage = CVT_C_PRIME - CVT_M_PRIME * HPeriod / 1000.0;
/* 13. Blanking time */
if (HBlankPercentage < 20)
HBlankPercentage = 20;
HBlank = Mode->HDisplay * HBlankPercentage / (100.0 - HBlankPercentage);
HBlank -= HBlank % (2 * CVT_H_GRANULARITY);
/* 14. Find total number of pixels in a line. */
Mode->HTotal = Mode->HDisplay + HBlank;
/* Fill in HSync values */
Mode->HSyncEnd = Mode->HDisplay + HBlank / 2;
Mode->HSyncStart = Mode->HSyncEnd -
(Mode->HTotal * CVT_HSYNC_PERCENTAGE) / 100;
Mode->HSyncStart += CVT_H_GRANULARITY -
Mode->HSyncStart % CVT_H_GRANULARITY;
/* Fill in VSync values */
Mode->VSyncStart = Mode->VDisplay + CVT_MIN_V_PORCH;
Mode->VSyncEnd = Mode->VSyncStart + VSync;
}
else { /* Reduced blanking */
/* Minimum vertical blanking interval time (µs) - default 460 */
#define CVT_RB_MIN_VBLANK 460.0
/* Fixed number of clocks for horizontal sync */
#define CVT_RB_H_SYNC 32.0
/* Fixed number of clocks for horizontal blanking */
#define CVT_RB_H_BLANK 160.0
/* Fixed number of lines for vertical front porch - default 3 */
#define CVT_RB_VFPORCH 3
int VBILines;
/* 8. Estimate Horizontal period. */
HPeriod = ((float) (1000000.0 / VFieldRate - CVT_RB_MIN_VBLANK)) /
(VDisplayRnd + 2 * VMargin);
/* 9. Find number of lines in vertical blanking */
VBILines = ((float) CVT_RB_MIN_VBLANK) / HPeriod + 1;
/* 10. Check if vertical blanking is sufficient */
if (VBILines < (CVT_RB_VFPORCH + VSync + CVT_MIN_V_BPORCH))
VBILines = CVT_RB_VFPORCH + VSync + CVT_MIN_V_BPORCH;
/* 11. Find total number of lines in vertical field */
Mode->VTotal = VDisplayRnd + 2 * VMargin + Interlace + VBILines;
/* 12. Find total number of pixels in a line */
Mode->HTotal = Mode->HDisplay + CVT_RB_H_BLANK;
/* Fill in HSync values */
Mode->HSyncEnd = Mode->HDisplay + CVT_RB_H_BLANK / 2;
Mode->HSyncStart = Mode->HSyncEnd - CVT_RB_H_SYNC;
/* Fill in VSync values */
Mode->VSyncStart = Mode->VDisplay + CVT_RB_VFPORCH;
Mode->VSyncEnd = Mode->VSyncStart + VSync;
}
/* 15/13. Find pixel clock frequency (kHz for xf86) */
Mode->Clock = Mode->HTotal * 1000.0 / HPeriod;
Mode->Clock -= Mode->Clock % CVT_CLOCK_STEP;
/* 16/14. Find actual Horizontal Frequency (kHz) */
Mode->HSync = ((float) Mode->Clock) / ((float) Mode->HTotal);
/* 17/15. Find actual Field rate */
Mode->VRefresh = (1000.0 * ((float) Mode->Clock)) /
((float) (Mode->HTotal * Mode->VTotal));
/* 18/16. Find actual vertical frame frequency */
/* ignore - just set the mode flag for interlaced */
if (Interlaced)
Mode->VTotal *= 2;
XNFasprintf(&tmp, "%dx%d", HDisplay, VDisplay);
Mode->name = tmp;
if (Reduced)
Mode->Flags |= V_PHSYNC | V_NVSYNC;
else
Mode->Flags |= V_NHSYNC | V_PVSYNC;
if (Interlaced)
Mode->Flags |= V_INTERLACE;
return Mode;
}

View File

@ -1,4 +1,3 @@
SUBDIRS = \
gtf \
cvt \
man

View File

@ -1 +0,0 @@
cvt

View File

@ -1,35 +0,0 @@
# Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved.
#
# Permission is hereby granted, free of charge, to any person obtaining a
# copy of this software and associated documentation files (the "Software"),
# to deal in the Software without restriction, including without limitation
# the rights to use, copy, modify, merge, publish, distribute, sublicense,
# and/or sell copies of the Software, and to permit persons to whom the
# Software is furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice (including the next
# paragraph) shall be included in all copies or substantial portions of the
# Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
# DEALINGS IN THE SOFTWARE.
#
bin_PROGRAMS = cvt
AM_CPPFLAGS = $(XORG_INCS) \
-I$(top_srcdir)/hw/xfree86/ddc \
-I$(top_srcdir)/hw/xfree86/modes \
-I$(top_srcdir)/hw/xfree86/parser
# gah
cvt_SOURCES = cvt.c \
$(top_srcdir)/hw/xfree86/modes/xf86cvt.c \
$(top_srcdir)/os/xprintf.c
cvt_CFLAGS = $(DIX_CFLAGS) $(XORG_CFLAGS)

View File

@ -1,294 +0,0 @@
/*
* Copyright 2005-2006 Luc Verhaegen.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*
*/
/* Standalone VESA CVT standard timing modelines generator. */
#include "xf86.h"
#include "xf86Modes.h"
/* FatalError implementation used by the server code we built in */
void
FatalError(const char *f, ...)
{
va_list args;
va_start(args, f);
vfprintf(stderr, f, args);
va_end(args);
exit(1);
}
/* xnfalloc implementation used by the server code we built in */
void *
XNFalloc(unsigned long n)
{
void *r;
r = malloc(n);
if (!r) {
perror("malloc failed");
exit(1);
}
return r;
}
/* xnfcalloc implementation used by the server code we built in */
void *
XNFcallocarray(size_t nmemb, size_t size)
{
void *r;
r = calloc(nmemb, size);
if (!r) {
perror("calloc failed");
exit(1);
}
return r;
}
/*
* Quickly check whether this is a CVT standard mode.
*/
static Bool
CVTCheckStandard(int HDisplay, int VDisplay, float VRefresh, Bool Reduced,
Bool Verbose)
{
Bool IsCVT = TRUE;
if ((!(VDisplay % 3) && ((VDisplay * 4 / 3) == HDisplay)) ||
(!(VDisplay % 9) && ((VDisplay * 16 / 9) == HDisplay)) ||
(!(VDisplay % 10) && ((VDisplay * 16 / 10) == HDisplay)) ||
(!(VDisplay % 4) && ((VDisplay * 5 / 4) == HDisplay)) ||
(!(VDisplay % 9) && ((VDisplay * 15 / 9) == HDisplay)));
else {
if (Verbose)
fprintf(stderr, "Warning: Aspect Ratio is not CVT standard.\n");
IsCVT = FALSE;
}
if ((VRefresh != 50.0) && (VRefresh != 60.0) &&
(VRefresh != 75.0) && (VRefresh != 85.0)) {
if (Verbose)
fprintf(stderr, "Warning: Refresh Rate is not CVT standard "
"(50, 60, 75 or 85Hz).\n");
IsCVT = FALSE;
}
return IsCVT;
}
/*
* I'm not documenting --interlaced for obvious reasons, even though I did
* implement it. I also can't deny having looked at gtf here.
*/
static void
PrintUsage(char *Name)
{
fprintf(stderr, "\n");
fprintf(stderr, "usage: %s [-v|--verbose] [-r|--reduced] X Y [refresh]\n",
Name);
fprintf(stderr, "\n");
fprintf(stderr, " -v|--verbose : Warn about CVT standard adherence.\n");
fprintf(stderr, " -r|--reduced : Create a mode with reduced blanking "
"(default: normal blanking).\n");
fprintf(stderr, " X : Desired horizontal resolution "
"(multiple of 8, required).\n");
fprintf(stderr,
" Y : Desired vertical resolution (required).\n");
fprintf(stderr,
" refresh : Desired refresh rate (default: 60.0Hz).\n");
fprintf(stderr, "\n");
fprintf(stderr, "Calculates VESA CVT (Coordinated Video Timing) modelines"
" for use with X.\n");
}
/*
*
*/
static void
PrintComment(DisplayModeRec * Mode, Bool CVT, Bool Reduced)
{
printf("# %dx%d %.2f Hz ", Mode->HDisplay, Mode->VDisplay, Mode->VRefresh);
if (CVT) {
printf("(CVT %.2fM",
((float) Mode->HDisplay * Mode->VDisplay) / 1000000.0);
if (!(Mode->VDisplay % 3) &&
((Mode->VDisplay * 4 / 3) == Mode->HDisplay))
printf("3");
else if (!(Mode->VDisplay % 9) &&
((Mode->VDisplay * 16 / 9) == Mode->HDisplay))
printf("9");
else if (!(Mode->VDisplay % 10) &&
((Mode->VDisplay * 16 / 10) == Mode->HDisplay))
printf("A");
else if (!(Mode->VDisplay % 4) &&
((Mode->VDisplay * 5 / 4) == Mode->HDisplay))
printf("4");
else if (!(Mode->VDisplay % 9) &&
((Mode->VDisplay * 15 / 9) == Mode->HDisplay))
printf("9");
if (Reduced)
printf("-R");
printf(") ");
}
else
printf("(CVT) ");
printf("hsync: %.2f kHz; ", Mode->HSync);
printf("pclk: %.2f MHz", ((float) Mode->Clock) / 1000.0);
printf("\n");
}
/*
* Originally grabbed from xf86Mode.c.
*
* Ignoring the actual Mode->name, as the user will want something solid
* to grab hold of.
*/
static void
PrintModeline(DisplayModePtr Mode, int HDisplay, int VDisplay, float VRefresh,
Bool Reduced)
{
if (Reduced)
printf("Modeline \"%dx%dR\" ", HDisplay, VDisplay);
else
printf("Modeline \"%dx%d_%.2f\" ", HDisplay, VDisplay, VRefresh);
printf("%6.2f %i %i %i %i %i %i %i %i", Mode->Clock / 1000.,
Mode->HDisplay, Mode->HSyncStart, Mode->HSyncEnd, Mode->HTotal,
Mode->VDisplay, Mode->VSyncStart, Mode->VSyncEnd, Mode->VTotal);
if (Mode->Flags & V_INTERLACE)
printf(" interlace");
if (Mode->Flags & V_PHSYNC)
printf(" +hsync");
if (Mode->Flags & V_NHSYNC)
printf(" -hsync");
if (Mode->Flags & V_PVSYNC)
printf(" +vsync");
if (Mode->Flags & V_NVSYNC)
printf(" -vsync");
printf("\n");
}
/*
*
*/
int
main(int argc, char *argv[])
{
DisplayModeRec *Mode;
int HDisplay = 0, VDisplay = 0;
float VRefresh = 0.0;
Bool Reduced = FALSE, Verbose = FALSE, IsCVT;
Bool Interlaced = FALSE;
int n;
if ((argc < 3) || (argc > 7)) {
PrintUsage(argv[0]);
return 1;
}
/* This doesn't filter out bad flags properly. Bad flags get passed down
* to atoi/atof, which then return 0, so that these variables can get
* filled next time round. So this is just a cosmetic problem.
*/
for (n = 1; n < argc; n++) {
if (!strcmp(argv[n], "-r") || !strcmp(argv[n], "--reduced"))
Reduced = TRUE;
else if (!strcmp(argv[n], "-i") || !strcmp(argv[n], "--interlaced"))
Interlaced = TRUE;
else if (!strcmp(argv[n], "-v") || !strcmp(argv[n], "--verbose"))
Verbose = TRUE;
else if (!strcmp(argv[n], "-h") || !strcmp(argv[n], "--help")) {
PrintUsage(argv[0]);
return 0;
}
else if (!HDisplay) {
HDisplay = atoi(argv[n]);
if (!HDisplay) {
PrintUsage(argv[0]);
return 1;
}
}
else if (!VDisplay) {
VDisplay = atoi(argv[n]);
if (!VDisplay) {
PrintUsage(argv[0]);
return 1;
}
}
else if (!VRefresh) {
VRefresh = atof(argv[n]);
if (!VRefresh) {
PrintUsage(argv[0]);
return 1;
}
}
else {
PrintUsage(argv[0]);
return 1;
}
}
if (!HDisplay || !VDisplay) {
PrintUsage(argv[0]);
return 0;
}
/* Default to 60.0Hz */
if (!VRefresh)
VRefresh = 60.0;
/* Horizontal timing is always a multiple of 8: round up. */
if (HDisplay & 0x07) {
HDisplay &= ~0x07;
HDisplay += 8;
}
if (Reduced) {
if ((VRefresh / 60.0) != floor(VRefresh / 60.0)) {
fprintf(stderr,
"\nERROR: Multiple of 60Hz refresh rate required for "
" reduced blanking.\n");
PrintUsage(argv[0]);
return 0;
}
}
IsCVT = CVTCheckStandard(HDisplay, VDisplay, VRefresh, Reduced, Verbose);
Mode = xf86CVTMode(HDisplay, VDisplay, VRefresh, Reduced, Interlaced);
PrintComment(Mode, IsCVT, Reduced);
PrintModeline(Mode, HDisplay, VDisplay, VRefresh, Reduced);
return 0;
}

View File

@ -1,2 +1,2 @@
include $(top_srcdir)/manpages.am
appman_PRE = cvt.man gtf.man
appman_PRE = gtf.man

View File

@ -1,41 +0,0 @@
.TH CVT 1 @vendorversion@
.SH NAME
cvt - calculate VESA CVT mode lines
.SH SYNOPSIS
.B cvt
.RB [ \-v | \-\-verbose ]
.RB [ \-r | \-\-reduced ]
.I h-resolution
.I v-resolution
.RB [ refresh ]
.SH DESCRIPTION
.I Cvt
is a utility for calculating VESA Coordinated Video Timing modes. Given the
desired horizontal and vertical resolutions, a modeline adhering to the CVT
standard is printed. This modeline can be included in Xorg
.B xorg.conf(@filemansuffix@)
.
.SH OPTIONS
.TP 8
.BR refresh
Provide a vertical refresh rate in Hz. The CVT standard prefers either 50.0,
60.0, 75.0 or 85.0Hz. The default is 60.0Hz.
.TP 8
.BR \-v | \-\-verbose
Warn verbosely when a given mode does not completely correspond with CVT
standards.
.TP 8
.BR \-r | \-\-reduced
Create a mode with reduced blanking. This allows for higher frequency signals,
with a lower or equal dotclock. Not for Cathode Ray Tube based displays though.
.SH "SEE ALSO"
xorg.conf(@filemansuffix@), gtf(@appmansuffix@)
.SH AUTHOR
Luc Verhaegen.
.PP
This program is based on the Coordinated Video Timing sample
implementation written by Graham Loveridge. This file is publicly
available at <http://www.vesa.org/Public/CVT/CVTd6r1.xls>. CVT is a
VESA trademark.

View File

@ -12,7 +12,8 @@ Xwayland_CFLAGS = \
$(XWAYLANDMODULES_CFLAGS) \
$(DIX_CFLAGS) \
$(GLAMOR_CFLAGS) \
$(GBM_CFLAGS)
$(GBM_CFLAGS) \
$(LIBXCVT_CFLAGS)
Xwayland_SOURCES = \
xwayland.c \
@ -60,7 +61,8 @@ Xwayland_LDADD = \
$(GLXVND_LIB) \
$(XWAYLAND_SYS_LIBS) \
$(top_builddir)/Xext/libXvidmode.la \
$(XSERVER_SYS_LIBS)
$(XSERVER_SYS_LIBS) \
$(LIBXCVT_LIBS)
Xwayland_LDFLAGS = $(LD_EXPORT_SYMBOLS_FLAG)
Xwayland_built_sources =

View File

@ -171,6 +171,8 @@ xwl_cursor_attach_pixmap(struct xwl_seat *xwl_seat,
}
wl_surface_attach(xwl_cursor->surface, buffer, 0, 0);
wl_surface_set_buffer_scale(xwl_cursor->surface,
xwl_seat->xwl_screen->global_output_scale);
xwl_surface_damage(xwl_seat->xwl_screen, xwl_cursor->surface, 0, 0,
xwl_seat->x_cursor->bits->width,
xwl_seat->x_cursor->bits->height);
@ -190,6 +192,7 @@ xwl_cursor_attach_pixmap(struct xwl_seat *xwl_seat,
void
xwl_seat_set_cursor(struct xwl_seat *xwl_seat)
{
struct xwl_screen *xwl_screen = xwl_seat->xwl_screen;
struct xwl_cursor *xwl_cursor = &xwl_seat->cursor;
PixmapPtr pixmap;
CursorPtr cursor;
@ -220,8 +223,8 @@ xwl_seat_set_cursor(struct xwl_seat *xwl_seat)
wl_pointer_set_cursor(xwl_seat->wl_pointer,
xwl_seat->pointer_enter_serial,
xwl_cursor->surface,
xwl_seat->x_cursor->bits->xhot,
xwl_seat->x_cursor->bits->yhot);
xwl_scale_to(xwl_screen, xwl_seat->x_cursor->bits->xhot),
xwl_scale_to(xwl_screen, xwl_seat->x_cursor->bits->yhot));
xwl_cursor_attach_pixmap(xwl_seat, xwl_cursor, pixmap);
}
@ -230,6 +233,7 @@ void
xwl_tablet_tool_set_cursor(struct xwl_tablet_tool *xwl_tablet_tool)
{
struct xwl_seat *xwl_seat = xwl_tablet_tool->seat;
struct xwl_screen *xwl_screen = xwl_seat->xwl_screen;
struct xwl_cursor *xwl_cursor = &xwl_tablet_tool->cursor;
PixmapPtr pixmap;
CursorPtr cursor;
@ -258,9 +262,9 @@ xwl_tablet_tool_set_cursor(struct xwl_tablet_tool *xwl_tablet_tool)
zwp_tablet_tool_v2_set_cursor(xwl_tablet_tool->tool,
xwl_tablet_tool->proximity_in_serial,
xwl_cursor->surface,
xwl_seat->x_cursor->bits->xhot,
xwl_seat->x_cursor->bits->yhot);
xwl_scale_to(xwl_screen, xwl_seat->x_cursor->bits->xhot),
xwl_scale_to(xwl_screen, xwl_seat->x_cursor->bits->yhot));
wl_surface_set_buffer_scale(xwl_cursor->surface, xwl_screen->global_output_scale);
xwl_cursor_attach_pixmap(xwl_seat, xwl_cursor, pixmap);
}

View File

@ -1,8 +1,6 @@
/* Copied from hw/xfree86/modes/xf86cvt.c into xwayland DDX and
* changed to generate an RRMode */
/*
* Copyright 2005-2006 Luc Verhaegen.
* Copyright © 2021 Red Hat, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
@ -23,284 +21,38 @@
* OTHER DEALINGS IN THE SOFTWARE.
*/
/*
* The reason for having this function in a file of its own is
* so that ../utils/cvt/cvt can link to it, and that xf86CVTMode
* code is shared directly.
*/
#include <xwayland-config.h>
#include <string.h>
#include <randrstr.h>
#include <libxcvt/libxcvt.h>
#include "xwayland-cvt.h"
/*
* Generate a CVT standard mode from HDisplay, VDisplay and VRefresh.
*
* These calculations are stolen from the CVT calculation spreadsheet written
* by Graham Loveridge. He seems to be claiming no copyright and there seems to
* be no license attached to this. He apparently just wants to see his name
* mentioned.
*
* This file can be found at http://www.vesa.org/Public/CVT/CVTd6r1.xls
*
* Comments and structure corresponds to the comments and structure of the xls.
* This should ease importing of future changes to the standard (not very
* likely though).
*
* About margins; i'm sure that they are to be the bit between HDisplay and
* HBlankStart, HBlankEnd and HTotal, VDisplay and VBlankStart, VBlankEnd and
* VTotal, where the overscan colour is shown. FB seems to call _all_ blanking
* outside sync "margin" for some reason. Since we prefer seeing proper
* blanking instead of the overscan colour, and since the Crtc* values will
* probably get altered after us, we will disable margins altogether. With
* these calculations, Margins will plainly expand H/VDisplay, and we don't
* want that. -- libv
*
*/
RRModePtr
xwayland_cvt(int HDisplay, int VDisplay, float VRefresh, Bool Reduced,
Bool Interlaced)
xwayland_cvt(int hdisplay, int vdisplay, float vrefresh, Bool reduced,
Bool interlaced)
{
/* 1) top/bottom margin size (% of height) - default: 1.8 */
#define CVT_MARGIN_PERCENTAGE 1.8
/* 2) character cell horizontal granularity (pixels) - default 8 */
#define CVT_H_GRANULARITY 8
/* 4) Minimum vertical porch (lines) - default 3 */
#define CVT_MIN_V_PORCH 3
/* 4) Minimum number of vertical back porch lines - default 6 */
#define CVT_MIN_V_BPORCH 6
/* Pixel Clock step (kHz) */
#define CVT_CLOCK_STEP 250
Bool Margins = FALSE;
float VFieldRate, HPeriod;
int HDisplayRnd, HMargin;
int VDisplayRnd, VMargin, VSync;
float Interlace; /* Please rename this */
struct libxcvt_mode_info *libxcvt_mode_info;
char name[128];
xRRModeInfo modeinfo;
libxcvt_mode_info =
libxcvt_gen_mode_info(hdisplay, vdisplay, vrefresh, reduced, interlaced);
memset(&modeinfo, 0, sizeof modeinfo);
modeinfo.width = libxcvt_mode_info->hdisplay;
modeinfo.height = libxcvt_mode_info->vdisplay;
modeinfo.dotClock = libxcvt_mode_info->dot_clock * 1000.0;
modeinfo.hSyncStart = libxcvt_mode_info->hsync_start;
modeinfo.hSyncEnd = libxcvt_mode_info->hsync_end;
modeinfo.hTotal = libxcvt_mode_info->htotal;
modeinfo.vSyncStart = libxcvt_mode_info->vsync_start;
modeinfo.vSyncEnd = libxcvt_mode_info->vsync_end;
modeinfo.vTotal = libxcvt_mode_info->vtotal;
modeinfo.modeFlags = libxcvt_mode_info->mode_flags;
/* CVT default is 60.0Hz */
if (!VRefresh)
VRefresh = 60.0;
/* 1. Required field rate */
if (Interlaced)
VFieldRate = VRefresh * 2;
else
VFieldRate = VRefresh;
/* 2. Horizontal pixels */
HDisplayRnd = HDisplay - (HDisplay % CVT_H_GRANULARITY);
/* 3. Determine left and right borders */
if (Margins) {
/* right margin is actually exactly the same as left */
HMargin = (((float) HDisplayRnd) * CVT_MARGIN_PERCENTAGE / 100.0);
HMargin -= HMargin % CVT_H_GRANULARITY;
}
else
HMargin = 0;
/* 4. Find total active pixels */
modeinfo.width = HDisplayRnd + 2 * HMargin;
/* 5. Find number of lines per field */
if (Interlaced)
VDisplayRnd = VDisplay / 2;
else
VDisplayRnd = VDisplay;
/* 6. Find top and bottom margins */
/* nope. */
if (Margins)
/* top and bottom margins are equal again. */
VMargin = (((float) VDisplayRnd) * CVT_MARGIN_PERCENTAGE / 100.0);
else
VMargin = 0;
modeinfo.height = VDisplay + 2 * VMargin;
/* 7. Interlace */
if (Interlaced)
Interlace = 0.5;
else
Interlace = 0.0;
/* Determine VSync Width from aspect ratio */
if (!(VDisplay % 3) && ((VDisplay * 4 / 3) == HDisplay))
VSync = 4;
else if (!(VDisplay % 9) && ((VDisplay * 16 / 9) == HDisplay))
VSync = 5;
else if (!(VDisplay % 10) && ((VDisplay * 16 / 10) == HDisplay))
VSync = 6;
else if (!(VDisplay % 4) && ((VDisplay * 5 / 4) == HDisplay))
VSync = 7;
else if (!(VDisplay % 9) && ((VDisplay * 15 / 9) == HDisplay))
VSync = 7;
else /* Custom */
VSync = 10;
if (!Reduced) { /* simplified GTF calculation */
/* 4) Minimum time of vertical sync + back porch interval (µs)
* default 550.0 */
#define CVT_MIN_VSYNC_BP 550.0
/* 3) Nominal HSync width (% of line period) - default 8 */
#define CVT_HSYNC_PERCENTAGE 8
float HBlankPercentage;
int VSyncAndBackPorch, VBackPorch;
int HBlank;
/* 8. Estimated Horizontal period */
HPeriod = ((float) (1000000.0 / VFieldRate - CVT_MIN_VSYNC_BP)) /
(VDisplayRnd + 2 * VMargin + CVT_MIN_V_PORCH + Interlace);
/* 9. Find number of lines in sync + backporch */
if (((int) (CVT_MIN_VSYNC_BP / HPeriod) + 1) <
(VSync + CVT_MIN_V_PORCH))
VSyncAndBackPorch = VSync + CVT_MIN_V_PORCH;
else
VSyncAndBackPorch = (int) (CVT_MIN_VSYNC_BP / HPeriod) + 1;
/* 10. Find number of lines in back porch */
VBackPorch = VSyncAndBackPorch - VSync;
(void) VBackPorch;
/* 11. Find total number of lines in vertical field */
modeinfo.vTotal =
VDisplayRnd + 2 * VMargin + VSyncAndBackPorch + Interlace +
CVT_MIN_V_PORCH;
/* 5) Definition of Horizontal blanking time limitation */
/* Gradient (%/kHz) - default 600 */
#define CVT_M_FACTOR 600
/* Offset (%) - default 40 */
#define CVT_C_FACTOR 40
/* Blanking time scaling factor - default 128 */
#define CVT_K_FACTOR 128
/* Scaling factor weighting - default 20 */
#define CVT_J_FACTOR 20
#define CVT_M_PRIME CVT_M_FACTOR * CVT_K_FACTOR / 256
#define CVT_C_PRIME (CVT_C_FACTOR - CVT_J_FACTOR) * CVT_K_FACTOR / 256 + \
CVT_J_FACTOR
/* 12. Find ideal blanking duty cycle from formula */
HBlankPercentage = CVT_C_PRIME - CVT_M_PRIME * HPeriod / 1000.0;
/* 13. Blanking time */
if (HBlankPercentage < 20)
HBlankPercentage = 20;
HBlank = modeinfo.width * HBlankPercentage / (100.0 - HBlankPercentage);
HBlank -= HBlank % (2 * CVT_H_GRANULARITY);
/* 14. Find total number of pixels in a line. */
modeinfo.hTotal = modeinfo.width + HBlank;
/* Fill in HSync values */
modeinfo.hSyncEnd = modeinfo.width + HBlank / 2;
modeinfo.hSyncStart = modeinfo.hSyncEnd -
(modeinfo.hTotal * CVT_HSYNC_PERCENTAGE) / 100;
modeinfo.hSyncStart += CVT_H_GRANULARITY -
modeinfo.hSyncStart % CVT_H_GRANULARITY;
/* Fill in VSync values */
modeinfo.vSyncStart = modeinfo.height + CVT_MIN_V_PORCH;
modeinfo.vSyncEnd = modeinfo.vSyncStart + VSync;
}
else { /* Reduced blanking */
/* Minimum vertical blanking interval time (µs) - default 460 */
#define CVT_RB_MIN_VBLANK 460.0
/* Fixed number of clocks for horizontal sync */
#define CVT_RB_H_SYNC 32.0
/* Fixed number of clocks for horizontal blanking */
#define CVT_RB_H_BLANK 160.0
/* Fixed number of lines for vertical front porch - default 3 */
#define CVT_RB_VFPORCH 3
int VBILines;
/* 8. Estimate Horizontal period. */
HPeriod = ((float) (1000000.0 / VFieldRate - CVT_RB_MIN_VBLANK)) /
(VDisplayRnd + 2 * VMargin);
/* 9. Find number of lines in vertical blanking */
VBILines = ((float) CVT_RB_MIN_VBLANK) / HPeriod + 1;
/* 10. Check if vertical blanking is sufficient */
if (VBILines < (CVT_RB_VFPORCH + VSync + CVT_MIN_V_BPORCH))
VBILines = CVT_RB_VFPORCH + VSync + CVT_MIN_V_BPORCH;
/* 11. Find total number of lines in vertical field */
modeinfo.vTotal = VDisplayRnd + 2 * VMargin + Interlace + VBILines;
/* 12. Find total number of pixels in a line */
modeinfo.hTotal = modeinfo.width + CVT_RB_H_BLANK;
/* Fill in HSync values */
modeinfo.hSyncEnd = modeinfo.width + CVT_RB_H_BLANK / 2;
modeinfo.hSyncStart = modeinfo.hSyncEnd - CVT_RB_H_SYNC;
/* Fill in VSync values */
modeinfo.vSyncStart = modeinfo.height + CVT_RB_VFPORCH;
modeinfo.vSyncEnd = modeinfo.vSyncStart + VSync;
}
/* 15/13. Find pixel clock frequency (kHz for xf86) */
modeinfo.dotClock = modeinfo.hTotal * 1000.0 / HPeriod;
modeinfo.dotClock -= modeinfo.dotClock % CVT_CLOCK_STEP;
modeinfo.dotClock *= 1000.0;
#if 0
/* 16/14. Find actual Horizontal Frequency (kHz) */
modeinfo.hSync = ((float) modeinfo.dotClock) / ((float) modeinfo.hTotal);
#endif
#if 0
/* 17/15. Find actual Field rate */
modeinfo.vRefresh = (1000.0 * ((float) modeinfo.dotClock)) /
((float) (modeinfo.hTotal * modeinfo.vTotal));
#endif
/* 18/16. Find actual vertical frame frequency */
/* ignore - just set the mode flag for interlaced */
if (Interlaced)
modeinfo.vTotal *= 2;
if (Reduced)
modeinfo.modeFlags |= RR_HSyncPositive | RR_VSyncNegative;
else
modeinfo.modeFlags |= RR_HSyncNegative | RR_VSyncPositive;
if (Interlaced)
modeinfo.modeFlags |= RR_Interlace;
/* FWXGA hack adapted from hw/xfree86/modes/xf86EdidModes.c, because you can't say 1366 */
if (HDisplay == 1366 && VDisplay == 768) {
modeinfo.width = 1366;
modeinfo.hSyncStart--;
modeinfo.hSyncEnd--;
}
free(libxcvt_mode_info);
snprintf(name, sizeof name, "%dx%d",
modeinfo.width, modeinfo.height);

View File

@ -60,8 +60,6 @@ struct xwl_eglstream_private {
EGLConfig config;
SetWindowPixmapProcPtr SetWindowPixmap;
Bool have_egl_damage;
Bool have_egl_stream_flush;
@ -293,9 +291,11 @@ xwl_eglstream_destroy_pixmap_stream(struct xwl_pixmap *xwl_pixmap)
}
static void
xwl_glamor_eglstream_remove_pending_stream(struct xwl_pixmap *xwl_pixmap)
xwl_eglstream_destroy_pending_cb(PixmapPtr pixmap)
{
if (xwl_pixmap->pending_cb) {
struct xwl_pixmap *xwl_pixmap = xwl_pixmap_get(pixmap);
if (xwl_pixmap && xwl_pixmap->pending_cb) {
wl_callback_destroy(xwl_pixmap->pending_cb);
xwl_pixmap->pending_cb = NULL;
}
@ -307,7 +307,7 @@ xwl_glamor_eglstream_destroy_pixmap(PixmapPtr pixmap)
struct xwl_pixmap *xwl_pixmap = xwl_pixmap_get(pixmap);
if (xwl_pixmap && pixmap->refcnt == 1) {
xwl_glamor_eglstream_remove_pending_stream(xwl_pixmap);
xwl_eglstream_destroy_pending_cb(pixmap);
xwl_eglstream_destroy_pixmap_stream(xwl_pixmap);
xwl_pixmap_del_buffer_release_cb(pixmap);
}
@ -325,41 +325,6 @@ xwl_glamor_eglstream_get_wl_buffer_for_pixmap(PixmapPtr pixmap)
return xwl_pixmap->buffer;
}
static void
xwl_eglstream_cancel_pending_stream(PixmapPtr pixmap)
{
struct xwl_pixmap *xwl_pixmap;
xwl_pixmap = xwl_pixmap_get(pixmap);
if (xwl_pixmap)
xwl_glamor_eglstream_remove_pending_stream(xwl_pixmap);
}
static void
xwl_eglstream_set_window_pixmap(WindowPtr window, PixmapPtr pixmap)
{
ScreenPtr screen = window->drawable.pScreen;
struct xwl_screen *xwl_screen = xwl_screen_get(screen);
struct xwl_eglstream_private *xwl_eglstream =
xwl_eglstream_get(xwl_screen);
PixmapPtr old_pixmap;
/* The pixmap for this window has changed.
* If that occurs while there is a stream pending, i.e. before the
* compositor has finished attaching the consumer for the window's
* pixmap's original eglstream, then a producer could no longer be
* attached, so the stream would be useless.
*/
old_pixmap = (*screen->GetWindowPixmap) (window);
if (old_pixmap && old_pixmap != pixmap)
xwl_eglstream_cancel_pending_stream(old_pixmap);
xwl_screen->screen->SetWindowPixmap = xwl_eglstream->SetWindowPixmap;
(*xwl_screen->screen->SetWindowPixmap)(window, pixmap);
xwl_eglstream->SetWindowPixmap = xwl_screen->screen->SetWindowPixmap;
xwl_screen->screen->SetWindowPixmap = xwl_eglstream_set_window_pixmap;
}
static const char *
xwl_eglstream_get_error_str(EGLint error)
{
@ -449,8 +414,7 @@ xwl_eglstream_consumer_ready_callback(void *data,
struct xwl_eglstream_private *xwl_eglstream =
xwl_eglstream_get(xwl_screen);
wl_callback_destroy(callback);
xwl_pixmap->pending_cb = NULL;
xwl_eglstream_destroy_pending_cb(pixmap);
xwl_glamor_egl_make_current(xwl_screen);
@ -1109,16 +1073,11 @@ error:
static Bool
xwl_glamor_eglstream_init_screen(struct xwl_screen *xwl_screen)
{
struct xwl_eglstream_private *xwl_eglstream =
xwl_eglstream_get(xwl_screen);
ScreenPtr screen = xwl_screen->screen;
/* We can just let glamor handle CreatePixmap */
screen->DestroyPixmap = xwl_glamor_eglstream_destroy_pixmap;
xwl_eglstream->SetWindowPixmap = screen->SetWindowPixmap;
screen->SetWindowPixmap = xwl_eglstream_set_window_pixmap;
return TRUE;
}

View File

@ -412,8 +412,8 @@ pointer_handle_enter(void *data, struct wl_pointer *pointer,
DeviceIntPtr dev = get_pointer_device(xwl_seat);
DeviceIntPtr master;
int i;
int sx = wl_fixed_to_int(sx_w);
int sy = wl_fixed_to_int(sy_w);
int sx = wl_fixed_to_int(sx_w) * xwl_seat->xwl_screen->global_output_scale;
int sy = wl_fixed_to_int(sy_w) * xwl_seat->xwl_screen->global_output_scale;
int dx, dy;
ScreenPtr pScreen = xwl_seat->xwl_screen->screen;
ValuatorMask mask;
@ -592,13 +592,14 @@ pointer_handle_motion(void *data, struct wl_pointer *pointer,
uint32_t time, wl_fixed_t sx_w, wl_fixed_t sy_w)
{
struct xwl_seat *xwl_seat = data;
int32_t scale = xwl_seat->xwl_screen->global_output_scale;
if (!xwl_seat->focus_window)
return;
xwl_seat->pending_pointer_event.has_absolute = TRUE;
xwl_seat->pending_pointer_event.x = sx_w;
xwl_seat->pending_pointer_event.y = sy_w;
xwl_seat->pending_pointer_event.x = sx_w * scale;
xwl_seat->pending_pointer_event.y = sy_w * scale;
if (wl_proxy_get_version((struct wl_proxy *) xwl_seat->wl_pointer) < 5)
dispatch_pointer_motion_event(xwl_seat);
@ -672,7 +673,8 @@ pointer_handle_axis(void *data, struct wl_pointer *pointer,
xorg_list_del(&pending->l);
free(pending);
} else {
valuator_mask_set_double(&mask, index, wl_fixed_to_double(value) / divisor);
double scaled_value = wl_fixed_to_double(value);
valuator_mask_set_double(&mask, index, scaled_value / divisor);
}
QueuePointerEvents(get_pointer_device(xwl_seat),
@ -740,12 +742,13 @@ relative_pointer_handle_relative_motion(void *data,
wl_fixed_t dy_unaccelf)
{
struct xwl_seat *xwl_seat = data;
int32_t scale = xwl_seat->xwl_screen->global_output_scale;
xwl_seat->pending_pointer_event.has_relative = TRUE;
xwl_seat->pending_pointer_event.dx = wl_fixed_to_double(dxf);
xwl_seat->pending_pointer_event.dy = wl_fixed_to_double(dyf);
xwl_seat->pending_pointer_event.dx_unaccel = wl_fixed_to_double(dx_unaccelf);
xwl_seat->pending_pointer_event.dy_unaccel = wl_fixed_to_double(dy_unaccelf);
xwl_seat->pending_pointer_event.dx = wl_fixed_to_double(dxf) * scale;
xwl_seat->pending_pointer_event.dy = wl_fixed_to_double(dyf) * scale;
xwl_seat->pending_pointer_event.dx_unaccel = wl_fixed_to_double(dx_unaccelf) * scale;
xwl_seat->pending_pointer_event.dy_unaccel = wl_fixed_to_double(dy_unaccelf) * scale;
if (!xwl_seat->focus_window)
return;
@ -1057,8 +1060,8 @@ touch_handle_down(void *data, struct wl_touch *wl_touch,
xwl_touch->window = wl_surface_get_user_data(surface);
xwl_touch->id = id;
xwl_touch->x = wl_fixed_to_int(sx_w);
xwl_touch->y = wl_fixed_to_int(sy_w);
xwl_touch->x = wl_fixed_to_int(sx_w) * xwl_seat->xwl_screen->global_output_scale;
xwl_touch->y = wl_fixed_to_int(sy_w) * xwl_seat->xwl_screen->global_output_scale;
xorg_list_add(&xwl_touch->link_touch, &xwl_seat->touches);
xwl_touch_send_event(xwl_touch, xwl_seat, XI_TouchBegin);
@ -1094,8 +1097,8 @@ touch_handle_motion(void *data, struct wl_touch *wl_touch,
if (!xwl_touch)
return;
xwl_touch->x = wl_fixed_to_int(sx_w);
xwl_touch->y = wl_fixed_to_int(sy_w);
xwl_touch->x = wl_fixed_to_int(sx_w) * xwl_seat->xwl_screen->global_output_scale;;
xwl_touch->y = wl_fixed_to_int(sy_w) * xwl_seat->xwl_screen->global_output_scale;;
xwl_touch_send_event(xwl_touch, xwl_seat, XI_TouchUpdate);
}
@ -1726,8 +1729,8 @@ tablet_tool_motion(void *data, struct zwp_tablet_tool_v2 *tool,
struct xwl_tablet_tool *xwl_tablet_tool = data;
struct xwl_seat *xwl_seat = xwl_tablet_tool->seat;
int32_t dx, dy;
double sx = wl_fixed_to_double(x);
double sy = wl_fixed_to_double(y);
double sx = wl_fixed_to_double(x) * xwl_seat->xwl_screen->global_output_scale;
double sy = wl_fixed_to_double(y) * xwl_seat->xwl_screen->global_output_scale;
if (!xwl_seat->tablet_focus_window)
return;
@ -2714,6 +2717,7 @@ xwl_pointer_warp_emulator_set_fake_pos(struct xwl_pointer_warp_emulator *warp_em
int x,
int y)
{
struct xwl_screen *xwl_screen;
struct zwp_locked_pointer_v1 *locked_pointer =
warp_emulator->locked_pointer;
WindowPtr window;
@ -2725,6 +2729,7 @@ xwl_pointer_warp_emulator_set_fake_pos(struct xwl_pointer_warp_emulator *warp_em
if (!warp_emulator->xwl_seat->focus_window)
return;
xwl_screen = warp_emulator->xwl_seat->xwl_screen;
window = warp_emulator->xwl_seat->focus_window->window;
if (x >= window->drawable.x ||
y >= window->drawable.y ||
@ -2733,8 +2738,8 @@ xwl_pointer_warp_emulator_set_fake_pos(struct xwl_pointer_warp_emulator *warp_em
sx = x - window->drawable.x;
sy = y - window->drawable.y;
zwp_locked_pointer_v1_set_cursor_position_hint(locked_pointer,
wl_fixed_from_int(sx),
wl_fixed_from_int(sy));
wl_fixed_from_int(xwl_scale_to(xwl_screen, sx)),
wl_fixed_from_int(xwl_scale_to(xwl_screen, sy)));
wl_surface_commit(warp_emulator->xwl_seat->focus_window->surface);
}
}

View File

@ -191,6 +191,9 @@ update_screen_size(struct xwl_output *xwl_output, int width, int height)
{
struct xwl_screen *xwl_screen = xwl_output->xwl_screen;
width *= xwl_screen->global_output_scale;
height *= xwl_screen->global_output_scale;
if (xwl_screen->root_clip_mode == ROOT_CLIP_FULL)
SetRootClip(xwl_screen->screen, ROOT_CLIP_NONE);
@ -216,6 +219,8 @@ update_screen_size(struct xwl_output *xwl_output, int width, int height)
}
update_desktop_dimensions();
RRTellChanged(xwl_screen->screen);
}
struct xwl_emulated_mode *
@ -495,14 +500,15 @@ xwl_output_set_emulated_mode(struct xwl_output *xwl_output, ClientPtr client,
xwl_output_set_randr_emu_props(xwl_output->xwl_screen, client);
}
static void
apply_output_change(struct xwl_output *xwl_output)
void
xwl_output_apply_changes(struct xwl_output *xwl_output)
{
struct xwl_screen *xwl_screen = xwl_output->xwl_screen;
struct xwl_output *it;
int mode_width, mode_height, count;
int width = 0, height = 0, has_this_output = 0;
RRModePtr *randr_modes;
int32_t scale = xwl_screen->global_output_scale;
/* Clear out the "done" received flags */
xwl_output->wl_output_done = FALSE;
@ -521,10 +527,10 @@ apply_output_change(struct xwl_output *xwl_output)
}
/* Build a fresh modes array using the current refresh rate */
randr_modes = output_get_rr_modes(xwl_output, mode_width, mode_height, &count);
randr_modes = output_get_rr_modes(xwl_output, mode_width * scale, mode_height * scale, &count);
RROutputSetModes(xwl_output->randr_output, randr_modes, count, 1);
RRCrtcNotify(xwl_output->randr_crtc, randr_modes[0],
xwl_output->x, xwl_output->y,
xwl_output->x * scale, xwl_output->y * scale,
xwl_output->rotation, NULL, 1, &xwl_output->randr_output);
/* RROutputSetModes takes ownership of the passed in modes, so we only
* have to free the pointer array.
@ -565,7 +571,7 @@ output_handle_done(void *data, struct wl_output *wl_output)
*/
if (xwl_output->xdg_output_done || !xwl_output->xdg_output ||
zxdg_output_v1_get_version(xwl_output->xdg_output) >= 3)
apply_output_change(xwl_output);
xwl_output_apply_changes(xwl_output);
}
static void
@ -608,7 +614,7 @@ xdg_output_handle_done(void *data, struct zxdg_output_v1 *xdg_output)
xwl_output->xdg_output_done = TRUE;
if (xwl_output->wl_output_done &&
zxdg_output_v1_get_version(xdg_output) < 3)
apply_output_change(xwl_output);
xwl_output_apply_changes(xwl_output);
}
static void
@ -674,6 +680,9 @@ xwl_output_create(struct xwl_screen *xwl_screen, uint32_t id)
RRCrtcGammaSetSize(xwl_output->randr_crtc, 256);
RROutputSetCrtcs(xwl_output->randr_output, &xwl_output->randr_crtc, 1);
RROutputSetConnection(xwl_output->randr_output, RR_Connected);
RRTellChanged(xwl_screen->screen);
xwl_output->scale = 1;
/* We want the output to be in the list as soon as created so we can
* use it when binding to the xdg-output protocol...
@ -698,6 +707,8 @@ err:
void
xwl_output_destroy(struct xwl_output *xwl_output)
{
if (xwl_output->xdg_output)
zxdg_output_v1_destroy(xwl_output->xdg_output);
wl_output_destroy(xwl_output->output);
free(xwl_output);
}
@ -717,6 +728,7 @@ xwl_output_remove(struct xwl_output *xwl_output)
RRCrtcDestroy(xwl_output->randr_crtc);
RROutputDestroy(xwl_output->randr_output);
RRTellChanged(xwl_screen->screen);
xwl_output_destroy(xwl_output);
}

View File

@ -43,7 +43,7 @@ struct xwl_output {
struct xwl_screen *xwl_screen;
RROutputPtr randr_output;
RRCrtcPtr randr_crtc;
int32_t x, y, width, height, refresh;
int32_t x, y, width, height, scale, refresh;
Rotation rotation;
Bool wl_output_done;
Bool xdg_output_done;
@ -77,6 +77,8 @@ void xwl_output_set_emulated_mode(struct xwl_output *xwl_output,
void xwl_output_set_window_randr_emu_props(struct xwl_screen *xwl_screen,
WindowPtr window);
void xwl_output_apply_changes(struct xwl_output *xwl_output);
void xwl_screen_init_xdg_output(struct xwl_screen *xwl_screen);
#endif /* XWAYLAND_OUTPUT_H */

View File

@ -34,6 +34,10 @@
#include "xwayland-pixmap.h"
#include "glamor.h"
#define XWL_PRESENT_CAPS PresentCapabilityAsync
/*
* When not flipping let Present copy with 60fps.
* When flipping wait on frame_callback, otherwise
@ -62,13 +66,13 @@ xwl_present_window_get_priv(WindowPtr window)
if (!xwl_present_window)
return NULL;
xwl_present_window->window = window;
xwl_present_window->msc = 1;
xwl_present_window->ust = GetTimeInMicros();
xorg_list_init(&xwl_present_window->frame_callback_list);
xorg_list_init(&xwl_present_window->wait_list);
xorg_list_init(&xwl_present_window->release_list);
xorg_list_init(&xwl_present_window->flip_queue);
xorg_list_init(&xwl_present_window->idle_queue);
dixSetPrivate(&window->devPrivates,
&xwl_present_window_private_key,
@ -78,6 +82,12 @@ xwl_present_window_get_priv(WindowPtr window)
return xwl_present_window;
}
static struct xwl_present_event *
xwl_present_event_from_id(uint64_t event_id)
{
return (struct xwl_present_event*)(uintptr_t)event_id;
}
static void
xwl_present_free_timer(struct xwl_present_window *xwl_present_window)
{
@ -90,10 +100,29 @@ xwl_present_timer_callback(OsTimerPtr timer,
CARD32 time,
void *arg);
static present_vblank_ptr
xwl_present_get_pending_flip(struct xwl_present_window *xwl_present_window)
{
present_vblank_ptr flip_pending;
if (xorg_list_is_empty(&xwl_present_window->flip_queue))
return NULL;
flip_pending = xorg_list_first_entry(&xwl_present_window->flip_queue, present_vblank_rec,
event_queue);
if (flip_pending->queued)
return NULL;
return flip_pending;
}
static inline Bool
xwl_present_has_pending_events(struct xwl_present_window *xwl_present_window)
{
return !!xwl_present_window->sync_flip ||
present_vblank_ptr flip_pending = xwl_present_get_pending_flip(xwl_present_window);
return (flip_pending && flip_pending->sync_flip) ||
!xorg_list_is_empty(&xwl_present_window->wait_list);
}
@ -117,6 +146,58 @@ xwl_present_reset_timer(struct xwl_present_window *xwl_present_window)
}
}
static void
xwl_present_execute(present_vblank_ptr vblank, uint64_t ust, uint64_t crtc_msc);
static uint32_t
xwl_present_query_capabilities(present_screen_priv_ptr screen_priv)
{
return XWL_PRESENT_CAPS;
}
static int
xwl_present_get_ust_msc(ScreenPtr screen,
WindowPtr present_window,
uint64_t *ust,
uint64_t *msc)
{
struct xwl_present_window *xwl_present_window = xwl_present_window_get_priv(present_window);
if (!xwl_present_window)
return BadAlloc;
*ust = xwl_present_window->ust;
*msc = xwl_present_window->msc;
return Success;
}
/*
* When the wait fence or previous flip is completed, it's time
* to re-try the request
*/
static void
xwl_present_re_execute(present_vblank_ptr vblank)
{
uint64_t ust = 0, crtc_msc = 0;
(void) xwl_present_get_ust_msc(vblank->screen, vblank->window, &ust, &crtc_msc);
xwl_present_execute(vblank, ust, crtc_msc);
}
static void
xwl_present_flip_try_ready(struct xwl_present_window *xwl_present_window)
{
present_vblank_ptr vblank;
xorg_list_for_each_entry(vblank, &xwl_present_window->flip_queue, event_queue) {
if (vblank->queued) {
xwl_present_re_execute(vblank);
return;
}
}
}
static void
xwl_present_release_pixmap(struct xwl_present_event *event)
{
@ -131,18 +212,123 @@ xwl_present_release_pixmap(struct xwl_present_event *event)
static void
xwl_present_free_event(struct xwl_present_event *event)
{
if (!event)
xwl_present_release_pixmap(event);
xorg_list_del(&event->vblank.event_queue);
present_vblank_destroy(&event->vblank);
}
static void
xwl_present_free_idle_vblank(present_vblank_ptr vblank)
{
present_pixmap_idle(vblank->pixmap, vblank->window, vblank->serial, vblank->idle_fence);
xwl_present_free_event(xwl_present_event_from_id((uintptr_t)vblank));
}
static WindowPtr
xwl_present_toplvl_pixmap_window(WindowPtr window)
{
ScreenPtr screen = window->drawable.pScreen;
PixmapPtr pixmap = (*screen->GetWindowPixmap)(window);
WindowPtr w = window;
WindowPtr next_w;
while(w->parent) {
next_w = w->parent;
if ( (*screen->GetWindowPixmap)(next_w) != pixmap) {
break;
}
w = next_w;
}
return w;
}
static void
xwl_present_flips_stop(WindowPtr window)
{
struct xwl_present_window *xwl_present_window = xwl_present_window_priv(window);
present_vblank_ptr vblank, tmp;
/* Change back to the fast refresh rate */
xwl_present_reset_timer(xwl_present_window);
/* Free any left over idle vblanks */
xorg_list_for_each_entry_safe(vblank, tmp, &xwl_present_window->idle_queue, event_queue)
xwl_present_free_idle_vblank(vblank);
if (xwl_present_window->flip_active) {
xwl_present_free_idle_vblank(xwl_present_window->flip_active);
xwl_present_window->flip_active = NULL;
}
xwl_present_flip_try_ready(xwl_present_window);
}
static void
xwl_present_flip_notify_vblank(present_vblank_ptr vblank, uint64_t ust, uint64_t crtc_msc)
{
WindowPtr window = vblank->window;
struct xwl_present_window *xwl_present_window = xwl_present_window_priv(window);
DebugPresent(("\tn %" PRIu64 " %p %" PRIu64 " %" PRIu64 ": %08" PRIx32 " -> %08" PRIx32 "\n",
vblank->event_id, vblank, vblank->exec_msc, vblank->target_msc,
vblank->pixmap ? vblank->pixmap->drawable.id : 0,
vblank->window ? vblank->window->drawable.id : 0));
assert (&vblank->event_queue == xwl_present_window->flip_queue.next);
xorg_list_del(&vblank->event_queue);
if (xwl_present_window->flip_active) {
struct xwl_present_event *event =
xwl_present_event_from_id((uintptr_t)xwl_present_window->flip_active);
if (!event->pixmap)
xwl_present_free_event(event);
else
/* Put the previous flip in the idle_queue and wait for further notice from
* the Wayland compositor
*/
xorg_list_append(&xwl_present_window->flip_active->event_queue, &xwl_present_window->idle_queue);
}
xwl_present_window->flip_active = vblank;
present_vblank_notify(vblank, PresentCompleteKindPixmap, PresentCompleteModeFlip, ust, crtc_msc);
if (vblank->abort_flip)
xwl_present_flips_stop(window);
xwl_present_flip_try_ready(xwl_present_window);
}
static void
xwl_present_update_window_crtc(present_window_priv_ptr window_priv, RRCrtcPtr crtc, uint64_t new_msc)
{
/* Crtc unchanged, no offset. */
if (crtc == window_priv->crtc)
return;
xwl_present_release_pixmap(event);
xorg_list_del(&event->list);
free(event);
/* No crtc earlier to offset against, just set the crtc. */
if (window_priv->crtc == PresentCrtcNeverSet) {
window_priv->msc_offset = 0;
window_priv->crtc = crtc;
return;
}
/* In window-mode the last correct msc-offset is always kept
* in window-priv struct because msc is saved per window and
* not per crtc as in screen-mode.
*/
window_priv->msc_offset += new_msc - window_priv->msc;
window_priv->crtc = crtc;
}
void
xwl_present_cleanup(WindowPtr window)
{
struct xwl_present_window *xwl_present_window = xwl_present_window_priv(window);
present_window_priv_ptr window_priv = present_window_priv(window);
struct xwl_present_event *event, *tmp;
if (!xwl_present_window)
@ -156,12 +342,7 @@ xwl_present_cleanup(WindowPtr window)
}
/* Clear remaining events */
xorg_list_for_each_entry_safe(event, tmp, &xwl_present_window->wait_list, list)
xwl_present_free_event(event);
xwl_present_free_event(xwl_present_window->sync_flip);
xorg_list_for_each_entry_safe(event, tmp, &xwl_present_window->release_list, list)
xorg_list_for_each_entry_safe(event, tmp, &window_priv->vblank, vblank.window_list)
xwl_present_free_event(event);
/* Clear timer */
@ -178,53 +359,42 @@ xwl_present_cleanup(WindowPtr window)
static void
xwl_present_buffer_release(void *data)
{
struct xwl_present_window *xwl_present_window;
struct xwl_present_event *event = data;
present_vblank_ptr vblank;
if (!event)
return;
xwl_present_release_pixmap(event);
vblank = &event->vblank;
present_pixmap_idle(vblank->pixmap, vblank->window, vblank->serial, vblank->idle_fence);
if (!event->abort)
present_wnmd_idle_notify(event->xwl_present_window->window, event->event_id);
if (!event->pending)
xwl_present_window = xwl_present_window_priv(vblank->window);
if (xwl_present_window->flip_active == vblank ||
xwl_present_get_pending_flip(xwl_present_window) == vblank)
xwl_present_release_pixmap(event);
else
xwl_present_free_event(event);
}
static void
xwl_present_msc_bump(struct xwl_present_window *xwl_present_window)
{
present_vblank_ptr flip_pending = xwl_present_get_pending_flip(xwl_present_window);
uint64_t msc = ++xwl_present_window->msc;
struct xwl_present_event *event, *tmp;
present_vblank_ptr vblank, tmp;
xwl_present_window->ust = GetTimeInMicros();
event = xwl_present_window->sync_flip;
xwl_present_window->sync_flip = NULL;
if (event) {
event->pending = FALSE;
if (flip_pending && flip_pending->sync_flip)
xwl_present_flip_notify_vblank(flip_pending, xwl_present_window->ust, msc);
present_wnmd_flip_notify(xwl_present_window->window, event->event_id,
xwl_present_window->ust, msc);
xorg_list_for_each_entry_safe(vblank, tmp, &xwl_present_window->wait_list, event_queue) {
if (vblank->exec_msc <= msc) {
DebugPresent(("\te %" PRIu64 " ust %" PRIu64 " msc %" PRIu64 "\n",
vblank->event_id, xwl_present_window->ust, msc));
if (!event->pixmap) {
/* If the buffer was already released, clean up now */
xwl_present_free_event(event);
} else {
xorg_list_add(&event->list, &xwl_present_window->release_list);
}
}
xorg_list_for_each_entry_safe(event, tmp,
&xwl_present_window->wait_list,
list) {
if (event->target_msc <= msc) {
present_wnmd_event_notify(xwl_present_window->window,
event->event_id,
xwl_present_window->ust,
msc);
xwl_present_free_event(event);
xwl_present_execute(vblank, xwl_present_window->ust, msc);
}
}
}
@ -265,20 +435,13 @@ xwl_present_sync_callback(void *data,
struct wl_callback *callback,
uint32_t time)
{
struct xwl_present_event *event = data;
struct xwl_present_window *xwl_present_window = event->xwl_present_window;
present_vblank_ptr vblank = data;
struct xwl_present_window *xwl_present_window = xwl_present_window_get_priv(vblank->window);
wl_callback_destroy(xwl_present_window->sync_callback);
xwl_present_window->sync_callback = NULL;
event->pending = FALSE;
if (!event->abort)
present_wnmd_flip_notify(xwl_present_window->window, event->event_id,
xwl_present_window->ust, xwl_present_window->msc);
if (!event->pixmap)
xwl_present_free_event(event);
xwl_present_flip_notify_vblank(vblank, xwl_present_window->ust, xwl_present_window->msc);
}
static const struct wl_callback_listener xwl_present_sync_listener = {
@ -286,7 +449,8 @@ static const struct wl_callback_listener xwl_present_sync_listener = {
};
static RRCrtcPtr
xwl_present_get_crtc(WindowPtr present_window)
xwl_present_get_crtc(present_screen_priv_ptr screen_priv,
WindowPtr present_window)
{
struct xwl_present_window *xwl_present_window = xwl_present_window_get_priv(present_window);
rrScrPrivPtr rr_private;
@ -302,43 +466,25 @@ xwl_present_get_crtc(WindowPtr present_window)
return rr_private->crtcs[0];
}
static int
xwl_present_get_ust_msc(WindowPtr present_window, uint64_t *ust, uint64_t *msc)
{
struct xwl_present_window *xwl_present_window = xwl_present_window_get_priv(present_window);
if (!xwl_present_window)
return BadAlloc;
*ust = xwl_present_window->ust;
*msc = xwl_present_window->msc;
return Success;
}
/*
* Queue an event to report back to the Present extension when the specified
* MSC has past
* MSC has passed
*/
static int
xwl_present_queue_vblank(WindowPtr present_window,
xwl_present_queue_vblank(ScreenPtr screen,
WindowPtr present_window,
RRCrtcPtr crtc,
uint64_t event_id,
uint64_t msc)
{
struct xwl_present_window *xwl_present_window = xwl_present_window_get_priv(present_window);
struct xwl_window *xwl_window = xwl_window_from_window(present_window);
struct xwl_present_event *event;
struct xwl_present_event *event = xwl_present_event_from_id(event_id);
event = malloc(sizeof *event);
if (!event)
return BadAlloc;
event->vblank.exec_msc = msc;
event->event_id = event_id;
event->pixmap = NULL;
event->xwl_present_window = xwl_present_window;
event->target_msc = msc;
xorg_list_append(&event->list, &xwl_present_window->wait_list);
xorg_list_del(&event->vblank.event_queue);
xorg_list_append(&event->vblank.event_queue, &xwl_present_window->wait_list);
/* If there's a pending frame callback, use that */
if (xwl_window && xwl_window->frame_callback &&
@ -359,30 +505,22 @@ xwl_present_queue_vblank(WindowPtr present_window,
* to the extension
*/
static void
xwl_present_abort_vblank(WindowPtr present_window,
xwl_present_abort_vblank(ScreenPtr screen,
WindowPtr present_window,
RRCrtcPtr crtc,
uint64_t event_id,
uint64_t msc)
{
struct xwl_present_window *xwl_present_window = xwl_present_window_priv(present_window);
struct xwl_present_event *event, *tmp;
static Bool called;
if (!xwl_present_window)
if (called)
return;
xorg_list_for_each_entry_safe(event, tmp, &xwl_present_window->wait_list, list) {
if (event->event_id == event_id) {
xwl_present_free_event(event);
return;
}
}
xorg_list_for_each_entry(event, &xwl_present_window->release_list, list) {
if (event->event_id == event_id) {
event->abort = TRUE;
return;
}
}
/* xwl_present_cleanup should have cleaned up everything,
* present_free_window_vblank shouldn't need to call this.
*/
ErrorF("Unexpected call to %s:\n", __func__);
xorg_backtrace();
}
static void
@ -392,18 +530,49 @@ xwl_present_flush(WindowPtr window)
}
static Bool
xwl_present_check_flip2(RRCrtcPtr crtc,
WindowPtr present_window,
PixmapPtr pixmap,
Bool sync_flip,
PresentFlipReason *reason)
xwl_present_check_flip(RRCrtcPtr crtc,
WindowPtr present_window,
PixmapPtr pixmap,
Bool sync_flip,
RegionPtr valid,
int16_t x_off,
int16_t y_off,
PresentFlipReason *reason)
{
WindowPtr toplvl_window = xwl_present_toplvl_pixmap_window(present_window);
struct xwl_window *xwl_window = xwl_window_from_window(present_window);
ScreenPtr screen = pixmap->drawable.pScreen;
if (reason)
*reason = PRESENT_FLIP_REASON_UNKNOWN;
if (!xwl_window)
return FALSE;
if (!crtc)
return FALSE;
/* Source pixmap must align with window exactly */
if (x_off || y_off)
return FALSE;
/* Valid area must contain window (for simplicity for now just never flip when one is set). */
if (valid)
return FALSE;
/* Flip pixmap must have same dimensions as window */
if (present_window->drawable.width != pixmap->drawable.width ||
present_window->drawable.height != pixmap->drawable.height)
return FALSE;
/* Window must be same region as toplevel window */
if ( !RegionEqual(&present_window->winSize, &toplvl_window->winSize) )
return FALSE;
/* Can't flip if window clipped by children */
if (!RegionEqual(&present_window->clipList, &present_window->winSize))
return FALSE;
if (!xwl_glamor_check_flip(pixmap))
return FALSE;
@ -425,11 +594,63 @@ xwl_present_check_flip2(RRCrtcPtr crtc,
return TRUE;
}
/*
* 'window' is being reconfigured. Check to see if it is involved
* in flipping and clean up as necessary.
*/
static void
xwl_present_check_flip_window (WindowPtr window)
{
struct xwl_present_window *xwl_present_window = xwl_present_window_priv(window);
present_window_priv_ptr window_priv = present_window_priv(window);
present_vblank_ptr flip_pending;
present_vblank_ptr flip_active;
present_vblank_ptr vblank;
PresentFlipReason reason;
/* If this window hasn't ever been used with Present, it can't be
* flipping
*/
if (!xwl_present_window || !window_priv)
return;
flip_pending = xwl_present_get_pending_flip(xwl_present_window);
flip_active = xwl_present_window->flip_active;
if (flip_pending) {
if (!xwl_present_check_flip(flip_pending->crtc, flip_pending->window, flip_pending->pixmap,
flip_pending->sync_flip, flip_pending->valid, 0, 0, NULL))
flip_pending->abort_flip = TRUE;
} else if (flip_active) {
if (!xwl_present_check_flip(flip_active->crtc, flip_active->window, flip_active->pixmap,
flip_active->sync_flip, flip_active->valid, 0, 0, NULL))
xwl_present_flips_stop(window);
}
/* Now check any queued vblanks */
xorg_list_for_each_entry(vblank, &window_priv->vblank, window_list) {
if (vblank->queued && vblank->flip &&
!xwl_present_check_flip(vblank->crtc, window, vblank->pixmap,
vblank->sync_flip, vblank->valid, 0, 0, &reason)) {
vblank->flip = FALSE;
vblank->reason = reason;
}
}
}
/*
* Clean up any pending or current flips for this window
*/
static void
xwl_present_clear_window_flip(WindowPtr window)
{
/* xwl_present_cleanup cleaned up everything */
}
static Bool
xwl_present_flip(WindowPtr present_window,
RRCrtcPtr crtc,
uint64_t event_id,
uint64_t target_msc,
PixmapPtr pixmap,
Bool sync_flip,
RegionPtr damage)
@ -438,7 +659,7 @@ xwl_present_flip(WindowPtr present_window,
struct xwl_present_window *xwl_present_window = xwl_present_window_priv(present_window);
BoxPtr damage_box;
struct wl_buffer *buffer;
struct xwl_present_event *event;
struct xwl_present_event *event = xwl_present_event_from_id(event_id);
if (!xwl_window)
return FALSE;
@ -451,30 +672,16 @@ xwl_present_flip(WindowPtr present_window,
damage_box = RegionExtents(damage);
event = malloc(sizeof *event);
if (!event)
return FALSE;
pixmap->refcnt++;
event->event_id = event_id;
event->xwl_present_window = xwl_present_window;
event->pixmap = pixmap;
event->target_msc = target_msc;
event->pending = TRUE;
event->abort = FALSE;
if (sync_flip) {
xorg_list_init(&event->list);
xwl_present_window->sync_flip = event;
} else {
xorg_list_add(&event->list, &xwl_present_window->release_list);
}
xwl_pixmap_set_buffer_release_cb(pixmap, xwl_present_buffer_release, event);
/* We can flip directly to the main surface (full screen window without clips) */
wl_surface_attach(xwl_window->surface, buffer, 0, 0);
wl_surface_set_buffer_scale(xwl_window->surface,
xwl_window->xwl_screen->global_output_scale);
if (!xwl_window->frame_callback)
xwl_window_create_frame_callback(xwl_window);
@ -500,7 +707,7 @@ xwl_present_flip(WindowPtr present_window,
wl_display_sync(xwl_window->xwl_screen->display);
wl_callback_add_listener(xwl_present_window->sync_callback,
&xwl_present_sync_listener,
event);
&event->vblank);
}
wl_display_flush(xwl_window->xwl_screen->display);
@ -508,13 +715,206 @@ xwl_present_flip(WindowPtr present_window,
return TRUE;
}
/*
* Once the required MSC has been reached, execute the pending request.
*
* For requests to actually present something, either blt contents to
* the window pixmap or queue a window buffer swap on the backend.
*
* For requests to just get the current MSC/UST combo, skip that part and
* go straight to event delivery.
*/
static void
xwl_present_flips_stop(WindowPtr window)
xwl_present_execute(present_vblank_ptr vblank, uint64_t ust, uint64_t crtc_msc)
{
struct xwl_present_window *xwl_present_window = xwl_present_window_priv(window);
WindowPtr window = vblank->window;
struct xwl_present_window *xwl_present_window = xwl_present_window_get_priv(window);
present_vblank_ptr flip_pending = xwl_present_get_pending_flip(xwl_present_window);
/* Change back to the fast refresh rate */
xwl_present_reset_timer(xwl_present_window);
xorg_list_del(&vblank->event_queue);
if (present_execute_wait(vblank, crtc_msc))
return;
if (flip_pending && vblank->flip && vblank->pixmap && vblank->window) {
DebugPresent(("\tr %" PRIu64 " %p (pending %p)\n",
vblank->event_id, vblank, flip_pending));
xorg_list_append(&vblank->event_queue, &xwl_present_window->flip_queue);
vblank->flip_ready = TRUE;
return;
}
vblank->queued = FALSE;
if (vblank->pixmap && vblank->window) {
ScreenPtr screen = window->drawable.pScreen;
if (vblank->flip) {
RegionPtr damage;
DebugPresent(("\tf %" PRIu64 " %p %" PRIu64 ": %08" PRIx32 " -> %08" PRIx32 "\n",
vblank->event_id, vblank, crtc_msc,
vblank->pixmap->drawable.id, vblank->window->drawable.id));
/* Set update region as damaged */
if (vblank->update) {
damage = RegionDuplicate(vblank->update);
/* Translate update region to screen space */
assert(vblank->x_off == 0 && vblank->y_off == 0);
RegionTranslate(damage, window->drawable.x, window->drawable.y);
RegionIntersect(damage, damage, &window->clipList);
} else
damage = RegionDuplicate(&window->clipList);
if (xwl_present_flip(vblank->window, vblank->crtc, vblank->event_id,
vblank->pixmap, vblank->sync_flip, damage)) {
WindowPtr toplvl_window = xwl_present_toplvl_pixmap_window(vblank->window);
PixmapPtr old_pixmap = screen->GetWindowPixmap(window);
/* Replace window pixmap with flip pixmap */
#ifdef COMPOSITE
vblank->pixmap->screen_x = old_pixmap->screen_x;
vblank->pixmap->screen_y = old_pixmap->screen_y;
#endif
present_set_tree_pixmap(toplvl_window, old_pixmap, vblank->pixmap);
vblank->pixmap->refcnt++;
dixDestroyPixmap(old_pixmap, old_pixmap->drawable.id);
/* Report damage */
DamageDamageRegion(&vblank->window->drawable, damage);
RegionDestroy(damage);
/* Put pending flip at the flip queue head */
xorg_list_add(&vblank->event_queue, &xwl_present_window->flip_queue);
return;
}
vblank->flip = FALSE;
}
DebugPresent(("\tc %p %" PRIu64 ": %08" PRIx32 " -> %08" PRIx32 "\n",
vblank, crtc_msc, vblank->pixmap->drawable.id, vblank->window->drawable.id));
if (flip_pending)
flip_pending->abort_flip = TRUE;
else if (xwl_present_window->flip_active)
xwl_present_flips_stop(window);
present_execute_copy(vblank, crtc_msc);
assert(!vblank->queued);
if (xwl_present_queue_vblank(screen, window, vblank->crtc,
vblank->event_id, crtc_msc + 1)
== Success) {
/* Clear the pixmap field, so this will fall through to present_execute_post next time */
dixDestroyPixmap(vblank->pixmap, vblank->pixmap->drawable.id);
vblank->pixmap = NULL;
return;
}
}
present_execute_post(vblank, ust, crtc_msc);
}
static int
xwl_present_pixmap(WindowPtr window,
PixmapPtr pixmap,
CARD32 serial,
RegionPtr valid,
RegionPtr update,
int16_t x_off,
int16_t y_off,
RRCrtcPtr target_crtc,
SyncFence *wait_fence,
SyncFence *idle_fence,
uint32_t options,
uint64_t target_window_msc,
uint64_t divisor,
uint64_t remainder,
present_notify_ptr notifies,
int num_notifies)
{
uint64_t ust = 0;
uint64_t target_msc;
uint64_t crtc_msc = 0;
int ret;
present_vblank_ptr vblank, tmp;
ScreenPtr screen = window->drawable.pScreen;
present_window_priv_ptr window_priv = present_get_window_priv(window, TRUE);
present_screen_priv_ptr screen_priv = present_screen_priv(screen);
struct xwl_present_event *event;
if (!window_priv)
return BadAlloc;
target_crtc = xwl_present_get_crtc(screen_priv, window);
ret = xwl_present_get_ust_msc(screen, window, &ust, &crtc_msc);
xwl_present_update_window_crtc(window_priv, target_crtc, crtc_msc);
if (ret == Success) {
/* Stash the current MSC away in case we need it later
*/
window_priv->msc = crtc_msc;
}
target_msc = present_get_target_msc(target_window_msc + window_priv->msc_offset,
crtc_msc,
divisor,
remainder,
options);
/*
* Look for a matching presentation already on the list...
*/
if (!update && pixmap) {
xorg_list_for_each_entry_safe(vblank, tmp, &window_priv->vblank, window_list) {
if (!vblank->pixmap)
continue;
if (!vblank->queued)
continue;
if (vblank->target_msc != target_msc)
continue;
present_vblank_scrap(vblank);
if (vblank->flip_ready)
xwl_present_re_execute(vblank);
}
}
event = calloc(1, sizeof(*event));
if (!event)
return BadAlloc;
vblank = &event->vblank;
if (!present_vblank_init(vblank, window, pixmap, serial, valid, update, x_off, y_off,
target_crtc, wait_fence, idle_fence, options, XWL_PRESENT_CAPS,
notifies, num_notifies, target_msc, crtc_msc)) {
present_vblank_destroy(vblank);
return BadAlloc;
}
vblank->event_id = (uintptr_t)event;
/* Xwayland presentations always complete (at least) one frame after they
* are executed
*/
vblank->exec_msc = vblank->target_msc - 1;
vblank->queued = TRUE;
if (crtc_msc < vblank->exec_msc) {
if (xwl_present_queue_vblank(screen, window, target_crtc, vblank->event_id, vblank->exec_msc) == Success)
return Success;
DebugPresent(("present_queue_vblank failed\n"));
}
xwl_present_execute(vblank, ust, crtc_msc);
return Success;
}
void
@ -527,32 +927,41 @@ xwl_present_unrealize_window(struct xwl_present_window *xwl_present_window)
xwl_present_reset_timer(xwl_present_window);
}
static present_wnmd_info_rec xwl_present_info = {
.version = PRESENT_SCREEN_INFO_VERSION,
.get_crtc = xwl_present_get_crtc,
.get_ust_msc = xwl_present_get_ust_msc,
.queue_vblank = xwl_present_queue_vblank,
.abort_vblank = xwl_present_abort_vblank,
.flush = xwl_present_flush,
.capabilities = PresentCapabilityAsync,
.check_flip2 = xwl_present_check_flip2,
.flip = xwl_present_flip,
.flips_stop = xwl_present_flips_stop
};
Bool
xwl_present_init(ScreenPtr screen)
{
struct xwl_screen *xwl_screen = xwl_screen_get(screen);
present_screen_priv_ptr screen_priv;
if (!xwl_screen->glamor || !xwl_screen->egl_backend)
return FALSE;
if (!present_screen_register_priv_keys())
return FALSE;
if (present_screen_priv(screen))
return TRUE;
screen_priv = present_screen_priv_init(screen);
if (!screen_priv)
return FALSE;
if (!dixRegisterPrivateKey(&xwl_present_window_private_key, PRIVATE_WINDOW, 0))
return FALSE;
return present_wnmd_screen_init(screen, &xwl_present_info);
screen_priv->query_capabilities = xwl_present_query_capabilities;
screen_priv->get_crtc = xwl_present_get_crtc;
screen_priv->check_flip = xwl_present_check_flip;
screen_priv->check_flip_window = xwl_present_check_flip_window;
screen_priv->clear_window_flip = xwl_present_clear_window_flip;
screen_priv->present_pixmap = xwl_present_pixmap;
screen_priv->queue_vblank = xwl_present_queue_vblank;
screen_priv->flush = xwl_present_flush;
screen_priv->re_execute = xwl_present_re_execute;
screen_priv->abort_vblank = xwl_present_abort_vblank;
return TRUE;
}

View File

@ -29,13 +29,12 @@
#include <xwayland-config.h>
#include <dix.h>
#include <present_priv.h>
#include "xwayland-types.h"
#ifdef GLAMOR_HAS_GBM
struct xwl_present_window {
struct xwl_present_event *sync_flip;
WindowPtr window;
struct xorg_list frame_callback_list;
uint64_t msc;
@ -46,20 +45,16 @@ struct xwl_present_window {
struct wl_callback *sync_callback;
struct xorg_list wait_list;
struct xorg_list release_list;
struct xorg_list flip_queue;
struct xorg_list idle_queue;
present_vblank_ptr flip_active;
};
struct xwl_present_event {
uint64_t event_id;
uint64_t target_msc;
present_vblank_rec vblank;
Bool abort;
Bool pending;
struct xwl_present_window *xwl_present_window;
PixmapPtr pixmap;
struct xorg_list list;
};
void xwl_present_frame_callback(struct xwl_present_window *xwl_present_window);

View File

@ -51,6 +51,7 @@
#include "xwayland-pixmap.h"
#include "xwayland-present.h"
#include "xwayland-shm.h"
#include "xwayland-window-buffers.h"
#ifdef MITSHM
#include "shmint.h"
@ -110,6 +111,12 @@ xwl_screen_has_resolution_change_emulation(struct xwl_screen *xwl_screen)
return xwl_screen->rootless && xwl_screen_has_viewport_support(xwl_screen);
}
int
xwl_scale_to(struct xwl_screen *xwl_screen, int value)
{
return value / (double)xwl_screen->global_output_scale + 0.5;
}
/* Return the output @ 0x0, falling back to the first output in the list */
struct xwl_output *
xwl_screen_get_first_output(struct xwl_screen *xwl_screen)
@ -127,6 +134,37 @@ xwl_screen_get_first_output(struct xwl_screen *xwl_screen)
return xorg_list_first_entry(&xwl_screen->output_list, struct xwl_output, link);
}
static void
xwl_screen_set_global_scale_from_property(struct xwl_screen *screen,
PropertyPtr prop)
{
CARD32 *propdata;
if (prop->type != XA_CARDINAL || prop->format != 32 || prop->size != 1) {
// TODO: handle warnings more cleanly.
LogMessageVerb(X_WARNING, 0, "Bad value for property %s.\n",
NameForAtom(prop->propertyName));
return;
}
propdata = prop->data;
xwl_screen_set_global_scale(screen, propdata[0]);
}
static void
xwl_screen_update_property(struct xwl_screen *screen,
PropertyStateRec *propstate)
{
switch (propstate->state) {
case PropertyNewValue:
xwl_screen_set_global_scale_from_property(screen, propstate->prop);
break;
case PropertyDelete:
xwl_screen_set_global_scale(screen, 1);
break;
}
}
static void
xwl_property_callback(CallbackListPtr *pcbl, void *closure,
void *calldata)
@ -134,19 +172,24 @@ xwl_property_callback(CallbackListPtr *pcbl, void *closure,
ScreenPtr screen = closure;
PropertyStateRec *rec = calldata;
struct xwl_screen *xwl_screen;
struct xwl_window *xwl_window;
if (rec->win->drawable.pScreen != screen)
return;
xwl_window = xwl_window_get(rec->win);
if (!xwl_window)
return;
xwl_screen = xwl_screen_get(screen);
if (rec->prop->propertyName == xwl_screen->allow_commits_prop)
if (rec->prop->propertyName == xwl_screen->allow_commits_prop) {
struct xwl_window *xwl_window;
xwl_window = xwl_window_get(rec->win);
if (!xwl_window)
return;
xwl_window_update_property(xwl_window, rec);
}
else if (rec->prop->propertyName == xwl_screen->global_output_scale_prop) {
xwl_screen_update_property(xwl_screen, rec);
}
}
Bool
@ -521,8 +564,14 @@ void xwl_surface_damage(struct xwl_screen *xwl_screen,
{
if (wl_surface_get_version(surface) >= WL_SURFACE_DAMAGE_BUFFER_SINCE_VERSION)
wl_surface_damage_buffer(surface, x, y, width, height);
else
else {
x = xwl_scale_to(xwl_screen, x);
y = xwl_scale_to(xwl_screen, y);
width = xwl_scale_to(xwl_screen, width);
height = xwl_scale_to(xwl_screen, height);
wl_surface_damage(surface, x, y, width, height);
}
}
void
@ -538,10 +587,34 @@ xwl_screen_roundtrip(struct xwl_screen *xwl_screen)
xwl_give_up("could not connect to wayland server\n");
}
void
xwl_screen_set_global_scale(struct xwl_screen *xwl_screen, int32_t scale)
{
struct xwl_output *it;
struct xwl_window *xwl_window;
xwl_screen->global_output_scale = scale;
/* change randr resolutions and positions */
xorg_list_for_each_entry(it, &xwl_screen->output_list, link) {
xwl_output_apply_changes(it);
}
if (!xwl_screen->rootless && xwl_screen->screen->root) {
/* Clear all the buffers, so that they'll be remade with the new sizes
* (this doesn't occur automatically because as far as Xorg is
* concerned, the window's size is the same) */
xorg_list_for_each_entry(xwl_window, &xwl_screen->window_list, link_window) {
xwl_window_buffers_recycle(xwl_window);
}
}
}
Bool
xwl_screen_init(ScreenPtr pScreen, int argc, char **argv)
{
static const char allow_commits[] = "_XWAYLAND_ALLOW_COMMITS";
static const char global_output_scale[] = "_XWAYLAND_GLOBAL_OUTPUT_SCALE";
struct xwl_screen *xwl_screen;
Pixel red_mask, blue_mask, green_mask;
int ret, bpc, green_bpc, i;
@ -573,6 +646,7 @@ xwl_screen_init(ScreenPtr pScreen, int argc, char **argv)
#ifdef XWL_HAS_GLAMOR
xwl_screen->glamor = 1;
#endif
xwl_screen->global_output_scale = 1;
for (i = 1; i < argc; i++) {
if (strcmp(argv[i], "-rootless") == 0) {
@ -743,6 +817,12 @@ xwl_screen_init(ScreenPtr pScreen, int argc, char **argv)
if (xwl_screen->allow_commits_prop == BAD_RESOURCE)
return FALSE;
xwl_screen->global_output_scale_prop = MakeAtom(global_output_scale,
strlen(global_output_scale),
TRUE);
if (xwl_screen->global_output_scale_prop == BAD_RESOURCE)
return FALSE;
AddCallback(&PropertyStateCallback, xwl_property_callback, pScreen);
xwl_screen_roundtrip(xwl_screen);

View File

@ -72,6 +72,8 @@ struct xwl_screen {
struct xorg_list damage_window_list;
struct xorg_list window_list;
int32_t global_output_scale;
int wayland_fd;
struct wl_display *display;
struct wl_registry *registry;
@ -107,6 +109,7 @@ struct xwl_screen {
struct glamor_context *glamor_ctx;
Atom allow_commits_prop;
Atom global_output_scale_prop;
/* The preferred GLVND vendor. If NULL, "mesa" is assumed. */
const char *glvnd_vendor;
@ -134,5 +137,7 @@ void xwl_screen_roundtrip (struct xwl_screen *xwl_screen);
void xwl_surface_damage(struct xwl_screen *xwl_screen,
struct wl_surface *surface,
int32_t x, int32_t y, int32_t width, int32_t height);
int xwl_scale_to(struct xwl_screen *xwl_screen, int value);
void xwl_screen_set_global_scale(struct xwl_screen *xwl_screen, int32_t scale);
#endif /* XWAYLAND_SCREEN_H */

View File

@ -470,7 +470,8 @@ ensure_surface_for_window(WindowPtr window)
}
wl_region_add(region, 0, 0,
window->drawable.width, window->drawable.height);
xwl_scale_to(xwl_screen, window->drawable.width),
xwl_scale_to(xwl_screen, window->drawable.height));
wl_surface_set_opaque_region(xwl_window->surface, region);
wl_region_destroy(region);
}
@ -820,6 +821,7 @@ xwl_window_post_damage(struct xwl_window *xwl_window)
#endif
wl_surface_attach(xwl_window->surface, buffer, 0, 0);
wl_surface_set_buffer_scale(xwl_window->surface, xwl_screen->global_output_scale);
/* Arbitrary limit to try to avoid flooding the Wayland
* connection. If we flood it too much anyway, this could

View File

@ -61,60 +61,76 @@ SOFTWARE.
#define LATER 1
#define NullClient ((ClientPtr) 0)
#define REQUEST(type) \
type *stuff = (type *)client->requestBuffer
#define REQUEST(type) \
type * stuff = (type *)client->requestBuffer;
#define ARRAY_SIZE(a) (sizeof((a)) / sizeof((a)[0]))
#define REQUEST_SIZE_MATCH(req)\
if ((sizeof(req) >> 2) != client->req_len)\
return(BadLength)
#define REQUEST_SIZE_MATCH(req) \
do { \
if ((sizeof(req) >> 2) != client->req_len) \
return(BadLength); \
} while (0)
#define REQUEST_AT_LEAST_SIZE(req) \
if ((sizeof(req) >> 2) > client->req_len )\
return(BadLength)
#define REQUEST_AT_LEAST_SIZE(req) \
do { \
if ((sizeof(req) >> 2) > client->req_len) \
return(BadLength); \
} while (0)
#define REQUEST_AT_LEAST_EXTRA_SIZE(req, extra) \
if (((sizeof(req) + ((uint64_t) extra)) >> 2) > client->req_len ) \
return(BadLength)
#define REQUEST_AT_LEAST_EXTRA_SIZE(req, extra) \
do { \
if (((sizeof(req) + ((uint64_t) (extra))) >> 2) > client->req_len) \
return(BadLength); \
} while (0)
#define REQUEST_FIXED_SIZE(req, n)\
if (((sizeof(req) >> 2) > client->req_len) || \
(((n) >> 2) >= client->req_len) || \
((((uint64_t) sizeof(req) + (n) + 3) >> 2) != (uint64_t) client->req_len)) \
return(BadLength)
#define REQUEST_FIXED_SIZE(req, n) \
do { \
if ((((sizeof(req)) >> 2) > client->req_len) || \
(((n) >> 2) >= client->req_len) || \
((((uint64_t) sizeof(req) + (n) + 3) >> 2) != (uint64_t) client->req_len)) \
return(BadLength); \
} while (0)
#define LEGAL_NEW_RESOURCE(id,client)\
if (!LegalNewID(id,client)) \
{\
client->errorValue = id;\
return BadIDChoice;\
}
#define LEGAL_NEW_RESOURCE(id,client) \
do { \
if (!LegalNewID((id), (client))) { \
(client)->errorValue = (id); \
return BadIDChoice; \
} \
} while (0)
#define VALIDATE_DRAWABLE_AND_GC(drawID, pDraw, mode)\
{\
int tmprc = dixLookupDrawable(&(pDraw), drawID, client, M_ANY, mode);\
if (tmprc != Success)\
return tmprc;\
tmprc = dixLookupGC(&(pGC), stuff->gc, client, DixUseAccess);\
if (tmprc != Success)\
return tmprc;\
if ((pGC->depth != pDraw->depth) || (pGC->pScreen != pDraw->pScreen))\
return BadMatch;\
}\
if (pGC->serialNumber != pDraw->serialNumber)\
ValidateGC(pDraw, pGC);
#define VALIDATE_DRAWABLE_AND_GC(drawID, pDraw, mode) \
do { \
int tmprc = dixLookupDrawable(&(pDraw), drawID, client, M_ANY, mode); \
if (tmprc != Success) \
return tmprc; \
tmprc = dixLookupGC(&(pGC), stuff->gc, client, DixUseAccess); \
if (tmprc != Success) \
return tmprc; \
if ((pGC->depth != pDraw->depth) || (pGC->pScreen != pDraw->pScreen)) \
return BadMatch; \
if (pGC->serialNumber != pDraw->serialNumber) \
ValidateGC(pDraw, pGC); \
} while (0)
#define WriteReplyToClient(pClient, size, pReply) { \
if ((pClient)->swapped) \
(*ReplySwapVector[((xReq *)(pClient)->requestBuffer)->reqType]) \
(pClient, (int)(size), pReply); \
else WriteToClient(pClient, (int)(size), (pReply)); }
#define WriteReplyToClient(pClient, size, pReply) \
do { \
if ((pClient)->swapped) \
(*ReplySwapVector[((xReq *)(pClient)->requestBuffer)->reqType]) \
(pClient, (int)(size), pReply); \
else \
WriteToClient(pClient, (int)(size), (pReply)); \
} while (0)
#define WriteSwappedDataToClient(pClient, size, pbuf) \
if ((pClient)->swapped) \
(*(pClient)->pSwapReplyFunc)(pClient, (int)(size), pbuf); \
else WriteToClient(pClient, (int)(size), (pbuf));
#define WriteSwappedDataToClient(pClient, size, pbuf) \
do { \
if ((pClient)->swapped) \
(*(pClient)->pSwapReplyFunc)(pClient, (int)(size), pbuf); \
else \
WriteToClient(pClient, (int)(size), (pbuf)); \
} while (0)
typedef struct _TimeStamp *TimeStampPtr;

View File

@ -72,7 +72,7 @@ extern _X_EXPORT int dixChangeWindowProperty(ClientPtr pClient,
int format,
int mode,
unsigned long len,
void *value,
const void *value,
Bool sendevent);
extern _X_EXPORT int DeleteProperty(ClientPtr /*client */ ,

View File

@ -164,6 +164,9 @@ a list of accepted extension names is printed.
.B \-f \fIvolume\fP
sets beep (bell) volume (allowable range: 0-100).
.TP 8
.B \-fakescreenfps \fFps\fP
sets fake presenter screen default fps (allowable range: 1-600).
.TP 8
.B \-fp \fIfontPath\fP
sets the search path for fonts. This path is a comma separated list
of directories which the X server searches for font databases.

View File

@ -6,6 +6,8 @@ project('xserver', 'c',
version: '21.0.99.1',
meson_version: '>= 0.47.0',
)
release_date = '2021-07-05'
add_project_arguments('-DHAVE_DIX_CONFIG_H', language: ['c', 'objc'])
cc = meson.get_compiler('c')
@ -192,6 +194,7 @@ if (host_machine.system() != 'darwin' and
endif
endif
xorgsdkdir = join_paths(get_option('prefix'), get_option('includedir'), 'xorg')
libxcvt_dep = dependency('libxcvt', required: build_xorg)
build_xwayland = false
if (host_machine.system() != 'darwin' and
@ -208,6 +211,7 @@ if (host_machine.system() != 'darwin' and
xwayland_dep = [
dependency('wayland-client', version: wayland_req, required: xwayland_required),
dependency('wayland-protocols', version: wayland_protocols_req, required: xwayland_required),
dependency('libxcvt', required: xwayland_required),
]
if build_glamor
@ -480,7 +484,7 @@ else
endif
endif
libdrm_required = build_dri1 or build_dri2 or build_dri3
libdrm_required = (build_dri1 or build_dri2 or build_dri3) and get_option('drm') == true
if not libdrm_dep.found() and libdrm_required
error('DRI requested, but LIBDRM not found')
endif
@ -687,6 +691,50 @@ manpage_config.set('modulepath', module_dir)
manpage_config.set('suid_wrapper_dir', join_paths(get_option('prefix'), 'libexec'))
manpage_config.set('default_font_path', default_font_path)
require_docs = get_option('docs') == 'true'
require_devel_docs = get_option('devel-docs') == 'true'
require_docs_pdf = (require_docs or require_devel_docs) and get_option('docs-pdf') == 'true'
sgml_doctools_dep = dependency('xorg-sgml-doctools',
required: require_docs or require_devel_docs)
xmlto = find_program('xmlto', required: require_docs or require_devel_docs)
xsltproc = find_program('xsltproc', required: require_docs or require_devel_docs)
fop = find_program('fop', required: require_docs_pdf)
build_docs = (get_option('docs') != 'false' and
sgml_doctools_dep.found() and
xmlto.found())
build_docs_devel = (get_option('devel-docs') != 'false' and
sgml_doctools_dep.found() and
xmlto.found())
build_docs_pdf = (get_option('docs-pdf') != 'false' and
(build_docs or build_docs_devel) and
fop.found())
if build_docs or build_docs_devel
doc_sgml_path = sgml_doctools_dep.get_pkgconfig_variable('sgmlrootdir')
doc_stylesheet_srcdir = join_paths(doc_sgml_path, 'X11')
# once we bump meson dependency to 0.56.0 we can use
# meson.project_build_root() instead of meson.build_root()
# Meson does not and will not support functions so we are copy-pasting
# documentation build code around which is unfortunate
# See https://mesonbuild.com/FAQ.html#why-doesnt-meson-have-user-defined-functionsmacros
docs_xmlto_search_flags = [
'--searchpath', doc_stylesheet_srcdir,
'--searchpath', meson.build_root(),
]
docs_xslt_search_flags = [
'--path', doc_stylesheet_srcdir,
'--path', meson.build_root(),
]
endif
# Include must come first, as it sets up dix-config.h
subdir('include')
@ -726,6 +774,7 @@ endif
if build_xorg or get_option('xephyr')
subdir('exa')
endif
subdir('doc')
# Common static libraries of all X servers
libxserver = [
@ -823,3 +872,14 @@ if build_xorg
install_data('xorg-server.m4',
install_dir: join_paths(get_option('datadir'), 'aclocal'))
endif
if build_docs or build_docs_devel
docxmlconfig = configuration_data()
docxmlconfig.set('PACKAGE_VERSION', meson.project_version())
docxmlconfig.set('RELEASE_DATE', release_date)
configure_file(
input: 'xserver.ent.in',
output: 'xserver.ent',
configuration: docxmlconfig
)
endif

View File

@ -113,6 +113,8 @@ option('xf86-input-inputtest', type: 'boolean', value: true,
option('dri1', type: 'combo', choices: ['true', 'false', 'auto'], value: 'auto', description: 'Build DRI1 extension (default: auto)')
option('dri2', type: 'combo', choices: ['true', 'false', 'auto'], value: 'auto', description: 'Build DRI2 extension (default: auto)')
option('dri3', type: 'combo', choices: ['true', 'false', 'auto'], value: 'auto', description: 'Build DRI3 extension (default: auto)')
option('drm', type: 'boolean', value: 'true',
description: 'Build Xorg with libdrm support')
option('apple-applications-dir', type: 'string', value: '/Applications/Utilities',
description: 'Applications directory')
@ -129,3 +131,10 @@ option('libunwind', type: 'boolean', value: false,
description: 'Use libunwind for backtrace reporting')
option('xwayland-path', type: 'string', description: 'Directory containing Xwayland executable')
option('docs', type: 'combo', choices: ['true', 'false', 'auto'], value: 'auto',
description: 'Build documentation')
option('devel-docs', type: 'combo', choices: ['true', 'false', 'auto'], value: 'auto',
description: 'Build development documentation')
option('docs-pdf', type: 'combo', choices: ['true', 'false', 'auto'], value: 'auto',
description: 'Whether to build PDF version of documentation. Setting is ignored if documentation is not built.')

View File

@ -112,6 +112,8 @@ __stdcall unsigned long GetTickCount(void);
#include "miinitext.h"
#include "present.h"
Bool noTestExtensions;
#ifdef COMPOSITE
@ -534,6 +536,7 @@ UseMsg(void)
ErrorF
("-deferglyphs [none|all|16] defer loading of [no|all|16-bit] glyphs\n");
ErrorF("-f # bell base (0-100)\n");
ErrorF("-fakescreenfps # fake screen default fps (1-600)\n");
ErrorF("-fp string default font path\n");
ErrorF("-help prints message with these options\n");
ErrorF("+iglx Allow creating indirect GLX contexts\n");
@ -781,6 +784,15 @@ ProcessCommandLine(int argc, char *argv[])
else
UseMsg();
}
else if (strcmp(argv[i], "-fakescreenfps") == 0) {
if (++i < argc) {
FakeScreenFps = (uint32_t) atoi(argv[i]);
if (FakeScreenFps < 1 || FakeScreenFps > 600)
FatalError("fakescreenfps must be an integer in [1;600] range\n");
}
else
UseMsg();
}
else if (strcmp(argv[i], "-fp") == 0) {
if (++i < argc) {
defaultFontPath = argv[i];

View File

@ -14,7 +14,6 @@ libpresent_la_SOURCES = \
present_request.c \
present_scmd.c \
present_screen.c \
present_vblank.c \
present_wnmd.c
present_vblank.c
sdk_HEADERS = present.h presentext.h

View File

@ -9,7 +9,6 @@ srcs_present = [
'present_scmd.c',
'present_screen.c',
'present_vblank.c',
'present_wnmd.c',
]
hdrs_present = [

View File

@ -44,11 +44,19 @@ present_get_crtc(WindowPtr window)
{
ScreenPtr screen = window->drawable.pScreen;
present_screen_priv_ptr screen_priv = present_screen_priv(screen);
RRCrtcPtr crtc = NULL;
if (!screen_priv)
return NULL;
return screen_priv->get_crtc(screen_priv, window);
crtc = screen_priv->get_crtc(screen_priv, window);
if (crtc && !present_screen_priv(crtc->pScreen)) {
crtc = RRFirstEnabledCrtc(screen);
}
if (crtc && !present_screen_priv(crtc->pScreen)) {
crtc = NULL;
}
return crtc;
}
/*

View File

@ -139,21 +139,6 @@ typedef struct present_screen_info {
} present_screen_info_rec, *present_screen_info_ptr;
typedef struct present_wnmd_info {
uint32_t version;
present_get_crtc_ptr get_crtc;
present_wnmd_get_ust_msc_ptr get_ust_msc;
present_wnmd_queue_vblank_ptr queue_vblank;
present_wnmd_abort_vblank_ptr abort_vblank;
present_flush_ptr flush;
uint32_t capabilities;
present_check_flip2_ptr check_flip2;
present_wnmd_flip_ptr flip;
present_wnmd_flips_stop_ptr flips_stop;
} present_wnmd_info_rec, *present_wnmd_info_ptr;
/*
* Called when 'event_id' occurs. 'ust' and 'msc' indicate when the
* event actually happened
@ -161,30 +146,8 @@ typedef struct present_wnmd_info {
extern _X_EXPORT void
present_event_notify(uint64_t event_id, uint64_t ust, uint64_t msc);
/*
* Called when 'event_id' occurs for 'window'.
* 'ust' and 'msc' indicate when the event actually happened
*/
extern _X_EXPORT void
present_wnmd_event_notify(WindowPtr window, uint64_t event_id, uint64_t ust, uint64_t msc);
/*
* Called when presentation 'event_id' occurs for 'window'.
* 'ust' and 'msc' indicate when the presentation actually happened.
*/
extern _X_EXPORT void
present_wnmd_flip_notify(WindowPtr window, uint64_t event_id, uint64_t ust, uint64_t msc);
/*
* Called when the flipped Pixmap associated with 'event_id' is not used anymore by the DDX.
*/
extern _X_EXPORT void
present_wnmd_idle_notify(WindowPtr window, uint64_t event_id);
extern _X_EXPORT Bool
present_screen_init(ScreenPtr screen, present_screen_info_ptr info);
extern _X_EXPORT Bool
present_wnmd_screen_init(ScreenPtr screen, present_wnmd_info_ptr info);
typedef void (*present_complete_notify_proc)(WindowPtr window,
CARD8 kind,
@ -199,4 +162,6 @@ present_register_complete_notify(present_complete_notify_proc proc);
extern _X_EXPORT Bool
present_can_window_flip(WindowPtr window);
extern _X_EXPORT uint32_t FakeScreenFps;
#endif /* _PRESENT_H_ */

View File

@ -113,21 +113,29 @@ present_fake_queue_vblank(ScreenPtr screen,
return Success;
}
uint32_t FakeScreenFps = 0;
void
present_fake_screen_init(ScreenPtr screen)
{
uint32_t fake_fps;
present_screen_priv_ptr screen_priv = present_screen_priv(screen);
/* For screens with hardware vblank support, the fake code
* will be used for off-screen windows and while screens are blanked,
* in which case we want a slow interval here
*
* Otherwise, pretend that the screen runs at 60Hz
*/
if (screen_priv->info && screen_priv->info->get_crtc)
screen_priv->fake_interval = 1000000;
else
screen_priv->fake_interval = 16667;
if (FakeScreenFps)
fake_fps = FakeScreenFps;
else {
/* For screens with hardware vblank support, the fake code
* will be used for off-screen windows and while screens are blanked,
* in which case we want a large interval here: 1Hz
*
* Otherwise, pretend that the screen runs at 60Hz
*/
if (screen_priv->info && screen_priv->info->get_crtc)
fake_fps = 1;
else
fake_fps = 60;
}
screen_priv->fake_interval = 1000000 / fake_fps;
}
void

View File

@ -81,7 +81,6 @@ struct present_vblank {
Bool queued; /* on present_exec_queue */
Bool flip; /* planning on using flip */
Bool flip_ready; /* wants to flip, but waiting for previous flip or unflip */
Bool flip_idler; /* driver explicitly permitted idling */
Bool sync_flip; /* do flip synchronous to vblank */
Bool abort_flip; /* aborting this flip */
PresentFlipReason reason; /* reason for which flip is not possible */
@ -108,6 +107,7 @@ typedef Bool (*present_priv_check_flip_ptr)(RRCrtcPtr crtc,
PresentFlipReason *reason);
typedef void (*present_priv_check_flip_window_ptr)(WindowPtr window);
typedef Bool (*present_priv_can_window_flip_ptr)(WindowPtr window);
typedef void (*present_priv_clear_window_flip_ptr)(WindowPtr window);
typedef int (*present_priv_pixmap_ptr)(WindowPtr window,
PixmapPtr pixmap,
@ -126,9 +126,6 @@ typedef int (*present_priv_pixmap_ptr)(WindowPtr window,
present_notify_ptr notifies,
int num_notifies);
typedef void (*present_priv_create_event_id_ptr)(present_window_priv_ptr window_priv,
present_vblank_ptr vblank);
typedef int (*present_priv_queue_vblank_ptr)(ScreenPtr screen,
WindowPtr window,
RRCrtcPtr crtc,
@ -164,7 +161,6 @@ struct present_screen_priv {
Bool flip_sync;
present_screen_info_ptr info;
present_wnmd_info_ptr wnmd_info;
/* Mode hooks */
present_priv_query_capabilities_ptr query_capabilities;
@ -173,9 +169,9 @@ struct present_screen_priv {
present_priv_check_flip_ptr check_flip;
present_priv_check_flip_window_ptr check_flip_window;
present_priv_can_window_flip_ptr can_window_flip;
present_priv_clear_window_flip_ptr clear_window_flip;
present_priv_pixmap_ptr present_pixmap;
present_priv_create_event_id_ptr create_event_id;
present_priv_queue_vblank_ptr queue_vblank;
present_priv_flush_ptr flush;
@ -221,15 +217,6 @@ struct present_window_priv {
uint64_t msc; /* Last reported MSC from the current crtc */
struct xorg_list vblank;
struct xorg_list notifies;
/* Used for window flips */
uint64_t event_id;
struct xorg_list exec_queue;
struct xorg_list flip_queue;
struct xorg_list idle_queue;
present_vblank_ptr flip_pending;
present_vblank_ptr flip_active;
};
#define PresentCrtcNeverSet ((RRCrtcPtr) 1)
@ -448,6 +435,11 @@ present_scmd_init_mode_hooks(present_screen_priv_ptr screen_priv);
/*
* present_screen.c
*/
Bool
present_screen_register_priv_keys(void);
present_screen_priv_ptr
present_screen_priv_init(ScreenPtr screen);
/*
* present_vblank.c
@ -455,6 +447,25 @@ present_scmd_init_mode_hooks(present_screen_priv_ptr screen_priv);
void
present_vblank_notify(present_vblank_ptr vblank, CARD8 kind, CARD8 mode, uint64_t ust, uint64_t crtc_msc);
Bool
present_vblank_init(present_vblank_ptr vblank,
WindowPtr window,
PixmapPtr pixmap,
CARD32 serial,
RegionPtr valid,
RegionPtr update,
int16_t x_off,
int16_t y_off,
RRCrtcPtr target_crtc,
SyncFence *wait_fence,
SyncFence *idle_fence,
uint32_t options,
const uint32_t capabilities,
present_notify_ptr notifies,
int num_notifies,
uint64_t target_msc,
uint64_t crtc_msc);
present_vblank_ptr
present_vblank_create(WindowPtr window,
PixmapPtr pixmap,
@ -467,7 +478,7 @@ present_vblank_create(WindowPtr window,
SyncFence *wait_fence,
SyncFence *idle_fence,
uint32_t options,
const uint32_t *capabilities,
const uint32_t capabilities,
present_notify_ptr notifies,
int num_notifies,
uint64_t target_msc,
@ -479,10 +490,4 @@ present_vblank_scrap(present_vblank_ptr vblank);
void
present_vblank_destroy(present_vblank_ptr vblank);
/*
* present_wnmd.c
*/
void
present_wnmd_init_mode_hooks(present_screen_priv_ptr screen_priv);
#endif /* _PRESENT_PRIV_H_ */

View File

@ -35,20 +35,14 @@
*
*/
static uint64_t present_event_id;
static uint64_t present_scmd_event_id;
static struct xorg_list present_exec_queue;
static struct xorg_list present_flip_queue;
static void
present_execute(present_vblank_ptr vblank, uint64_t ust, uint64_t crtc_msc);
static void
present_scmd_create_event_id(present_window_priv_ptr window_priv,
present_vblank_ptr vblank)
{
vblank->event_id = ++present_event_id;
}
static inline PixmapPtr
present_flip_pending_pixmap(ScreenPtr screen)
{
@ -326,7 +320,7 @@ present_unflip(ScreenPtr screen)
present_restore_screen_pixmap(screen);
screen_priv->unflip_event_id = ++present_event_id;
screen_priv->unflip_event_id = ++present_scmd_event_id;
DebugPresent(("u %" PRIu64 "\n", screen_priv->unflip_event_id));
(*screen_priv->info->unflip) (screen, screen_priv->unflip_event_id);
}
@ -501,6 +495,26 @@ present_scmd_can_window_flip(WindowPtr window)
return TRUE;
}
/*
* Clean up any pending or current flips for this window
*/
static void
present_scmd_clear_window_flip(WindowPtr window)
{
ScreenPtr screen = window->drawable.pScreen;
present_screen_priv_ptr screen_priv = present_screen_priv(screen);
present_vblank_ptr flip_pending = screen_priv->flip_pending;
if (flip_pending && flip_pending->window == window) {
present_set_abort_flip(screen);
flip_pending->window = NULL;
}
if (screen_priv->flip_window == window) {
present_restore_screen_pixmap(screen);
screen_priv->flip_window = NULL;
}
}
/*
* Once the required MSC has been reached, execute the pending request.
*
@ -736,7 +750,7 @@ present_scmd_pixmap(WindowPtr window,
wait_fence,
idle_fence,
options,
screen_priv->info ? &screen_priv->info->capabilities : NULL,
screen_priv->info ? screen_priv->info->capabilities : 0,
notifies,
num_notifies,
target_msc,
@ -745,6 +759,8 @@ present_scmd_pixmap(WindowPtr window,
if (!vblank)
return BadAlloc;
vblank->event_id = ++present_scmd_event_id;
if (vblank->flip && vblank->sync_flip)
vblank->exec_msc--;
@ -816,9 +832,9 @@ present_scmd_init_mode_hooks(present_screen_priv_ptr screen_priv)
screen_priv->check_flip = &present_check_flip;
screen_priv->check_flip_window = &present_check_flip_window;
screen_priv->can_window_flip = &present_scmd_can_window_flip;
screen_priv->clear_window_flip = &present_scmd_clear_window_flip;
screen_priv->present_pixmap = &present_scmd_pixmap;
screen_priv->create_event_id = &present_scmd_create_event_id;
screen_priv->queue_vblank = &present_queue_vblank;
screen_priv->flush = &present_flush;

View File

@ -42,10 +42,6 @@ present_get_window_priv(WindowPtr window, Bool create)
xorg_list_init(&window_priv->vblank);
xorg_list_init(&window_priv->notifies);
xorg_list_init(&window_priv->exec_queue);
xorg_list_init(&window_priv->flip_queue);
xorg_list_init(&window_priv->idle_queue);
window_priv->window = window;
window_priv->crtc = PresentCrtcNeverSet;
dixSetPrivate(&window->devPrivates, &present_window_private_key, window_priv);
@ -86,50 +82,6 @@ present_free_window_vblank(WindowPtr window)
}
}
/*
* Clean up any pending or current flips for this window
*/
static void
present_clear_window_flip(WindowPtr window)
{
ScreenPtr screen = window->drawable.pScreen;
present_screen_priv_ptr screen_priv = present_screen_priv(screen);
present_vblank_ptr flip_pending = screen_priv->flip_pending;
if (flip_pending && flip_pending->window == window) {
present_set_abort_flip(screen);
flip_pending->window = NULL;
}
if (screen_priv->flip_window == window) {
present_restore_screen_pixmap(screen);
screen_priv->flip_window = NULL;
}
}
static void
present_wnmd_clear_window_flip(WindowPtr window)
{
present_window_priv_ptr window_priv = present_window_priv(window);
present_vblank_ptr vblank, tmp;
xorg_list_for_each_entry_safe(vblank, tmp, &window_priv->flip_queue, event_queue) {
present_pixmap_idle(vblank->pixmap, vblank->window, vblank->serial, vblank->idle_fence);
present_vblank_destroy(vblank);
}
xorg_list_for_each_entry_safe(vblank, tmp, &window_priv->idle_queue, event_queue) {
present_pixmap_idle(vblank->pixmap, vblank->window, vblank->serial, vblank->idle_fence);
present_vblank_destroy(vblank);
}
vblank = window_priv->flip_active;
if (vblank) {
present_pixmap_idle(vblank->pixmap, vblank->window, vblank->serial, vblank->idle_fence);
present_vblank_destroy(vblank);
}
window_priv->flip_active = NULL;
}
/*
* Hook the close window function to clean up our window private
*/
@ -146,10 +98,7 @@ present_destroy_window(WindowPtr window)
present_free_events(window);
present_free_window_vblank(window);
if (screen_priv->wnmd_info)
present_wnmd_clear_window_flip(window);
else
present_clear_window_flip(window);
screen_priv->clear_window_flip(window);
free(window_priv);
}
@ -202,7 +151,7 @@ present_clip_notify(WindowPtr window, int dx, int dy)
wrap(screen_priv, screen, ClipNotify, present_clip_notify);
}
static Bool
Bool
present_screen_register_priv_keys(void)
{
if (!dixRegisterPrivateKey(&present_screen_private_key, PRIVATE_SCREEN, 0))
@ -214,7 +163,7 @@ present_screen_register_priv_keys(void)
return TRUE;
}
static present_screen_priv_ptr
present_screen_priv_ptr
present_screen_priv_init(ScreenPtr screen)
{
present_screen_priv_ptr screen_priv;
@ -233,27 +182,6 @@ present_screen_priv_init(ScreenPtr screen)
return screen_priv;
}
/*
* Initialize a screen for use with present in window flip mode (wnmd)
*/
int
present_wnmd_screen_init(ScreenPtr screen, present_wnmd_info_ptr info)
{
if (!present_screen_register_priv_keys())
return FALSE;
if (!present_screen_priv(screen)) {
present_screen_priv_ptr screen_priv = present_screen_priv_init(screen);
if (!screen_priv)
return FALSE;
screen_priv->wnmd_info = info;
present_wnmd_init_mode_hooks(screen_priv);
}
return TRUE;
}
/*
* Initialize a screen for use with present in default screen flip mode (scmd)
*/

View File

@ -38,38 +38,39 @@ present_vblank_notify(present_vblank_ptr vblank, CARD8 kind, CARD8 mode, uint64_
}
}
present_vblank_ptr
present_vblank_create(WindowPtr window,
PixmapPtr pixmap,
CARD32 serial,
RegionPtr valid,
RegionPtr update,
int16_t x_off,
int16_t y_off,
RRCrtcPtr target_crtc,
SyncFence *wait_fence,
SyncFence *idle_fence,
uint32_t options,
const uint32_t *capabilities,
present_notify_ptr notifies,
int num_notifies,
uint64_t target_msc,
uint64_t crtc_msc)
/* The memory vblank points to must be 0-initialized before calling this function.
*
* If this function returns FALSE, present_vblank_destroy must be called to clean
* up.
*/
Bool
present_vblank_init(present_vblank_ptr vblank,
WindowPtr window,
PixmapPtr pixmap,
CARD32 serial,
RegionPtr valid,
RegionPtr update,
int16_t x_off,
int16_t y_off,
RRCrtcPtr target_crtc,
SyncFence *wait_fence,
SyncFence *idle_fence,
uint32_t options,
const uint32_t capabilities,
present_notify_ptr notifies,
int num_notifies,
uint64_t target_msc,
uint64_t crtc_msc)
{
ScreenPtr screen = window->drawable.pScreen;
present_window_priv_ptr window_priv = present_get_window_priv(window, TRUE);
present_screen_priv_ptr screen_priv = present_screen_priv(screen);
present_vblank_ptr vblank;
PresentFlipReason reason = PRESENT_FLIP_REASON_UNKNOWN;
if (target_crtc) {
screen_priv = present_screen_priv(target_crtc->pScreen);
}
vblank = calloc (1, sizeof (present_vblank_rec));
if (!vblank)
return NULL;
xorg_list_append(&vblank->window_list, &window_priv->vblank);
xorg_list_init(&vblank->event_queue);
@ -77,8 +78,6 @@ present_vblank_create(WindowPtr window,
vblank->window = window;
vblank->pixmap = pixmap;
screen_priv->create_event_id(window_priv, vblank);
if (pixmap) {
vblank->kind = PresentCompleteKindPixmap;
pixmap->refcnt++;
@ -107,17 +106,16 @@ present_vblank_create(WindowPtr window,
vblank->notifies = notifies;
vblank->num_notifies = num_notifies;
vblank->has_suboptimal = (options & PresentOptionSuboptimal);
vblank->flip_idler = FALSE;
if (pixmap != NULL &&
!(options & PresentOptionCopy) &&
capabilities) {
screen_priv->check_flip) {
if (msc_is_after(target_msc, crtc_msc) &&
screen_priv->check_flip (target_crtc, window, pixmap, TRUE, valid, x_off, y_off, &reason))
{
vblank->flip = TRUE;
vblank->sync_flip = TRUE;
} else if ((*capabilities & PresentCapabilityAsync) &&
} else if ((capabilities & PresentCapabilityAsync) &&
screen_priv->check_flip (target_crtc, window, pixmap, FALSE, valid, x_off, y_off, &reason))
{
vblank->flip = TRUE;
@ -142,10 +140,42 @@ present_vblank_create(WindowPtr window,
vblank->event_id, vblank, target_msc,
vblank->pixmap->drawable.id, vblank->window->drawable.id,
target_crtc, vblank->flip, vblank->sync_flip, vblank->serial));
return vblank;
return TRUE;
no_mem:
vblank->notifies = NULL;
return FALSE;
}
present_vblank_ptr
present_vblank_create(WindowPtr window,
PixmapPtr pixmap,
CARD32 serial,
RegionPtr valid,
RegionPtr update,
int16_t x_off,
int16_t y_off,
RRCrtcPtr target_crtc,
SyncFence *wait_fence,
SyncFence *idle_fence,
uint32_t options,
const uint32_t capabilities,
present_notify_ptr notifies,
int num_notifies,
uint64_t target_msc,
uint64_t crtc_msc)
{
present_vblank_ptr vblank = calloc(1, sizeof(present_vblank_rec));
if (!vblank)
return NULL;
if (present_vblank_init(vblank, window, pixmap, serial, valid, update,
x_off, y_off, target_crtc, wait_fence, idle_fence,
options, capabilities, notifies, num_notifies,
target_msc, crtc_msc))
return vblank;
present_vblank_destroy(vblank);
return NULL;
}

View File

@ -1,702 +0,0 @@
/*
* Copyright © 2018 Roman Gilg
*
* Permission to use, copy, modify, distribute, and sell this software and its
* documentation for any purpose is hereby granted without fee, provided that
* the above copyright notice appear in all copies and that both that copyright
* notice and this permission notice appear in supporting documentation, and
* that the name of the copyright holders not be used in advertising or
* publicity pertaining to distribution of the software without specific,
* written prior permission. The copyright holders make no representations
* about the suitability of this software for any purpose. It is provided "as
* is" without express or implied warranty.
*
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
* EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
* OF THIS SOFTWARE.
*/
#include "present_priv.h"
/*
* Window flip mode
*
* Provides per-window flips. Flips can be processed on windows that
* have the same size as their parents, which they share their pixmap with.
*
* A flip still requires a copy currently, since the original pixmap needs
* to be updated with the new pixmap content. Just a flip of all windows
* to the new pixmap is difficult, because the original pixmap might not be
* controlled by the Xserver.
*
*/
static void
present_wnmd_execute(present_vblank_ptr vblank, uint64_t ust, uint64_t crtc_msc);
static int
present_wnmd_queue_vblank(ScreenPtr screen,
WindowPtr window,
RRCrtcPtr crtc,
uint64_t event_id,
uint64_t msc)
{
present_screen_priv_ptr screen_priv = present_screen_priv(screen);
return (*screen_priv->wnmd_info->queue_vblank) (window, crtc, event_id, msc);
}
static void
present_wnmd_create_event_id(present_window_priv_ptr window_priv, present_vblank_ptr vblank)
{
vblank->event_id = ++window_priv->event_id;
}
static uint32_t
present_wnmd_query_capabilities(present_screen_priv_ptr screen_priv)
{
return screen_priv->wnmd_info->capabilities;
}
static RRCrtcPtr
present_wnmd_get_crtc(present_screen_priv_ptr screen_priv, WindowPtr window)
{
return (*screen_priv->wnmd_info->get_crtc)(window);
}
static int
present_wnmd_get_ust_msc(ScreenPtr screen, WindowPtr window, uint64_t *ust, uint64_t *msc)
{
present_screen_priv_ptr screen_priv = present_screen_priv(screen);
return (*screen_priv->wnmd_info->get_ust_msc)(window, ust, msc);
}
/*
* When the wait fence or previous flip is completed, it's time
* to re-try the request
*/
static void
present_wnmd_re_execute(present_vblank_ptr vblank)
{
uint64_t ust = 0, crtc_msc = 0;
(void) present_wnmd_get_ust_msc(vblank->screen, vblank->window, &ust, &crtc_msc);
present_wnmd_execute(vblank, ust, crtc_msc);
}
static void
present_wnmd_flip_try_ready(WindowPtr window)
{
present_window_priv_ptr window_priv = present_window_priv(window);
present_vblank_ptr vblank;
xorg_list_for_each_entry(vblank, &window_priv->flip_queue, event_queue) {
if (vblank->queued) {
present_wnmd_re_execute(vblank);
return;
}
}
}
static void
present_wnmd_free_idle_vblank(present_vblank_ptr vblank)
{
present_pixmap_idle(vblank->pixmap, vblank->window, vblank->serial, vblank->idle_fence);
present_vblank_destroy(vblank);
}
/*
* Free any left over idle vblanks
*/
static void
present_wnmd_free_idle_vblanks(WindowPtr window)
{
present_window_priv_ptr window_priv = present_window_priv(window);
present_vblank_ptr vblank, tmp;
xorg_list_for_each_entry_safe(vblank, tmp, &window_priv->idle_queue, event_queue) {
present_wnmd_free_idle_vblank(vblank);
}
if (window_priv->flip_active) {
present_wnmd_free_idle_vblank(window_priv->flip_active);
window_priv->flip_active = NULL;
}
}
static WindowPtr
present_wnmd_toplvl_pixmap_window(WindowPtr window)
{
ScreenPtr screen = window->drawable.pScreen;
PixmapPtr pixmap = (*screen->GetWindowPixmap)(window);
WindowPtr w = window;
WindowPtr next_w;
while(w->parent) {
next_w = w->parent;
if ( (*screen->GetWindowPixmap)(next_w) != pixmap) {
break;
}
w = next_w;
}
return w;
}
static void
present_wnmd_flips_stop(WindowPtr window)
{
present_window_priv_ptr window_priv = present_window_priv(window);
present_screen_priv_ptr screen_priv = present_screen_priv(window->drawable.pScreen);
assert (!window_priv->flip_pending);
(*screen_priv->wnmd_info->flips_stop) (window);
present_wnmd_free_idle_vblanks(window_priv->window);
present_wnmd_flip_try_ready(window_priv->window);
}
static void
present_wnmd_flip_notify_vblank(present_vblank_ptr vblank, uint64_t ust, uint64_t crtc_msc)
{
WindowPtr window = vblank->window;
present_window_priv_ptr window_priv = present_window_priv(window);
DebugPresent(("\tn %" PRIu64 " %p %" PRIu64 " %" PRIu64 ": %08" PRIx32 " -> %08" PRIx32 "\n",
vblank->event_id, vblank, vblank->exec_msc, vblank->target_msc,
vblank->pixmap ? vblank->pixmap->drawable.id : 0,
vblank->window ? vblank->window->drawable.id : 0));
assert (vblank == window_priv->flip_pending);
xorg_list_del(&vblank->event_queue);
if (window_priv->flip_active) {
if (window_priv->flip_active->flip_idler)
present_wnmd_free_idle_vblank(window_priv->flip_active);
else
/* Put the previous flip in the idle_queue and wait for further notice from DDX */
xorg_list_append(&window_priv->flip_active->event_queue, &window_priv->idle_queue);
}
window_priv->flip_active = vblank;
window_priv->flip_pending = NULL;
present_vblank_notify(vblank, PresentCompleteKindPixmap, PresentCompleteModeFlip, ust, crtc_msc);
if (vblank->abort_flip)
present_wnmd_flips_stop(window);
present_wnmd_flip_try_ready(window);
}
void
present_wnmd_event_notify(WindowPtr window, uint64_t event_id, uint64_t ust, uint64_t msc)
{
present_window_priv_ptr window_priv = present_window_priv(window);
present_vblank_ptr vblank;
if (!window_priv)
return;
if (!event_id)
return;
DebugPresent(("\te %" PRIu64 " ust %" PRIu64 " msc %" PRIu64 "\n", event_id, ust, msc));
xorg_list_for_each_entry(vblank, &window_priv->exec_queue, event_queue) {
if (event_id == vblank->event_id) {
present_wnmd_execute(vblank, ust, msc);
return;
}
}
xorg_list_for_each_entry(vblank, &window_priv->flip_queue, event_queue) {
if (vblank->event_id == event_id) {
assert(vblank->queued);
present_wnmd_execute(vblank, ust, msc);
return;
}
}
/* Copies which were executed but need their completion event sent */
xorg_list_for_each_entry(vblank, &window_priv->idle_queue, event_queue) {
if (vblank->event_id == event_id) {
present_execute_post(vblank, ust, msc);
return;
}
}
}
void
present_wnmd_flip_notify(WindowPtr window, uint64_t event_id, uint64_t ust, uint64_t msc)
{
present_window_priv_ptr window_priv = present_window_priv(window);
present_vblank_ptr vblank;
xorg_list_for_each_entry(vblank, &window_priv->flip_queue, event_queue) {
if (vblank->event_id == event_id) {
assert(!vblank->queued);
assert(vblank->window);
present_wnmd_flip_notify_vblank(vblank, ust, msc);
return;
}
}
}
void
present_wnmd_idle_notify(WindowPtr window, uint64_t event_id)
{
present_window_priv_ptr window_priv = present_window_priv(window);
present_vblank_ptr vblank;
if (window_priv->flip_active && window_priv->flip_active->event_id == event_id) {
/* Active flip is allowed to become idle directly when it becomes unactive again. */
window_priv->flip_active->flip_idler = TRUE;
return;
}
xorg_list_for_each_entry(vblank, &window_priv->idle_queue, event_queue) {
if (vblank->event_id == event_id) {
present_wnmd_free_idle_vblank(vblank);
return;
}
}
xorg_list_for_each_entry(vblank, &window_priv->flip_queue, event_queue) {
if (vblank->event_id == event_id) {
vblank->flip_idler = TRUE;
return;
}
}
}
static Bool
present_wnmd_check_flip(RRCrtcPtr crtc,
WindowPtr window,
PixmapPtr pixmap,
Bool sync_flip,
RegionPtr valid,
int16_t x_off,
int16_t y_off,
PresentFlipReason *reason)
{
ScreenPtr screen = window->drawable.pScreen;
present_screen_priv_ptr screen_priv = present_screen_priv(screen);
WindowPtr toplvl_window = present_wnmd_toplvl_pixmap_window(window);
if (reason)
*reason = PRESENT_FLIP_REASON_UNKNOWN;
if (!screen_priv)
return FALSE;
if (!screen_priv->wnmd_info)
return FALSE;
if (!crtc)
return FALSE;
/* Check to see if the driver supports flips at all */
if (!screen_priv->wnmd_info->flip)
return FALSE;
/* Source pixmap must align with window exactly */
if (x_off || y_off)
return FALSE;
/* Valid area must contain window (for simplicity for now just never flip when one is set). */
if (valid)
return FALSE;
/* Flip pixmap must have same dimensions as window */
if (window->drawable.width != pixmap->drawable.width ||
window->drawable.height != pixmap->drawable.height)
return FALSE;
/* Window must be same region as toplevel window */
if ( !RegionEqual(&window->winSize, &toplvl_window->winSize) )
return FALSE;
/* Can't flip if window clipped by children */
if (!RegionEqual(&window->clipList, &window->winSize))
return FALSE;
/* Ask the driver for permission */
if (screen_priv->wnmd_info->check_flip2) {
if (!(*screen_priv->wnmd_info->check_flip2) (crtc, window, pixmap, sync_flip, reason)) {
DebugPresent(("\td %08" PRIx32 " -> %08" PRIx32 "\n",
window->drawable.id, pixmap ? pixmap->drawable.id : 0));
return FALSE;
}
}
return TRUE;
}
/*
* 'window' is being reconfigured. Check to see if it is involved
* in flipping and clean up as necessary.
*/
static void
present_wnmd_check_flip_window (WindowPtr window)
{
present_window_priv_ptr window_priv = present_window_priv(window);
present_vblank_ptr flip_pending;
present_vblank_ptr flip_active;
present_vblank_ptr vblank;
PresentFlipReason reason;
/* If this window hasn't ever been used with Present, it can't be
* flipping
*/
if (!window_priv)
return;
flip_pending = window_priv->flip_pending;
flip_active = window_priv->flip_active;
if (flip_pending) {
if (!present_wnmd_check_flip(flip_pending->crtc, flip_pending->window, flip_pending->pixmap,
flip_pending->sync_flip, flip_pending->valid, 0, 0, NULL))
window_priv->flip_pending->abort_flip = TRUE;
} else if (flip_active) {
if (!present_wnmd_check_flip(flip_active->crtc, flip_active->window, flip_active->pixmap,
flip_active->sync_flip, flip_active->valid, 0, 0, NULL))
present_wnmd_flips_stop(window);
}
/* Now check any queued vblanks */
xorg_list_for_each_entry(vblank, &window_priv->vblank, window_list) {
if (vblank->queued && vblank->flip &&
!present_wnmd_check_flip(vblank->crtc, window, vblank->pixmap,
vblank->sync_flip, vblank->valid, 0, 0, &reason)) {
vblank->flip = FALSE;
vblank->reason = reason;
}
}
}
static Bool
present_wnmd_flip(WindowPtr window,
RRCrtcPtr crtc,
uint64_t event_id,
uint64_t target_msc,
PixmapPtr pixmap,
Bool sync_flip,
RegionPtr damage)
{
ScreenPtr screen = window->drawable.pScreen;
present_screen_priv_ptr screen_priv = present_screen_priv(screen);
return (*screen_priv->wnmd_info->flip) (window,
crtc,
event_id,
target_msc,
pixmap,
sync_flip,
damage);
}
static void
present_wnmd_cancel_flip(WindowPtr window)
{
present_window_priv_ptr window_priv = present_window_priv(window);
if (window_priv->flip_pending)
window_priv->flip_pending->abort_flip = TRUE;
else if (window_priv->flip_active)
present_wnmd_flips_stop(window);
}
/*
* Once the required MSC has been reached, execute the pending request.
*
* For requests to actually present something, either blt contents to
* the window pixmap or queue a window buffer swap on the backend.
*
* For requests to just get the current MSC/UST combo, skip that part and
* go straight to event delivery.
*/
static void
present_wnmd_execute(present_vblank_ptr vblank, uint64_t ust, uint64_t crtc_msc)
{
WindowPtr window = vblank->window;
present_window_priv_ptr window_priv = present_window_priv(window);
if (present_execute_wait(vblank, crtc_msc))
return;
if (vblank->flip && vblank->pixmap && vblank->window) {
if (window_priv->flip_pending) {
DebugPresent(("\tr %" PRIu64 " %p (pending %p)\n",
vblank->event_id, vblank,
window_priv->flip_pending));
xorg_list_del(&vblank->event_queue);
xorg_list_append(&vblank->event_queue, &window_priv->flip_queue);
vblank->flip_ready = TRUE;
return;
}
}
xorg_list_del(&vblank->event_queue);
xorg_list_del(&vblank->window_list);
vblank->queued = FALSE;
if (vblank->pixmap && vblank->window) {
ScreenPtr screen = window->drawable.pScreen;
if (vblank->flip) {
RegionPtr damage;
DebugPresent(("\tf %" PRIu64 " %p %" PRIu64 ": %08" PRIx32 " -> %08" PRIx32 "\n",
vblank->event_id, vblank, crtc_msc,
vblank->pixmap->drawable.id, vblank->window->drawable.id));
/* Prepare to flip by placing it in the flip queue
*/
xorg_list_add(&vblank->event_queue, &window_priv->flip_queue);
/* Set update region as damaged */
if (vblank->update) {
damage = RegionDuplicate(vblank->update);
/* Translate update region to screen space */
assert(vblank->x_off == 0 && vblank->y_off == 0);
RegionTranslate(damage, window->drawable.x, window->drawable.y);
RegionIntersect(damage, damage, &window->clipList);
} else
damage = RegionDuplicate(&window->clipList);
/* Try to flip - the vblank is now pending
*/
window_priv->flip_pending = vblank;
// ask the driver
if (present_wnmd_flip(vblank->window, vblank->crtc, vblank->event_id,
vblank->target_msc, vblank->pixmap, vblank->sync_flip, damage)) {
WindowPtr toplvl_window = present_wnmd_toplvl_pixmap_window(vblank->window);
PixmapPtr old_pixmap = screen->GetWindowPixmap(window);
/* Replace window pixmap with flip pixmap */
#ifdef COMPOSITE
vblank->pixmap->screen_x = old_pixmap->screen_x;
vblank->pixmap->screen_y = old_pixmap->screen_y;
#endif
present_set_tree_pixmap(toplvl_window, old_pixmap, vblank->pixmap);
vblank->pixmap->refcnt++;
dixDestroyPixmap(old_pixmap, old_pixmap->drawable.id);
/* Report damage */
DamageDamageRegion(&vblank->window->drawable, damage);
RegionDestroy(damage);
return;
}
xorg_list_del(&vblank->event_queue);
/* Flip failed. Clear the flip_pending field
*/
window_priv->flip_pending = NULL;
vblank->flip = FALSE;
}
DebugPresent(("\tc %p %" PRIu64 ": %08" PRIx32 " -> %08" PRIx32 "\n",
vblank, crtc_msc, vblank->pixmap->drawable.id, vblank->window->drawable.id));
present_wnmd_cancel_flip(window);
present_execute_copy(vblank, crtc_msc);
assert(!vblank->queued);
if (present_wnmd_queue_vblank(screen, window, vblank->crtc,
vblank->event_id, crtc_msc + 1)
== Success) {
xorg_list_add(&vblank->event_queue, &window_priv->idle_queue);
xorg_list_append(&vblank->window_list, &window_priv->vblank);
return;
}
}
present_execute_post(vblank, ust, crtc_msc);
}
static void
present_wnmd_update_window_crtc(WindowPtr window, RRCrtcPtr crtc, uint64_t new_msc)
{
present_window_priv_ptr window_priv = present_get_window_priv(window, TRUE);
/* Crtc unchanged, no offset. */
if (crtc == window_priv->crtc)
return;
/* No crtc earlier to offset against, just set the crtc. */
if (window_priv->crtc == PresentCrtcNeverSet) {
window_priv->msc_offset = 0;
window_priv->crtc = crtc;
return;
}
/* In window-mode the last correct msc-offset is always kept
* in window-priv struct because msc is saved per window and
* not per crtc as in screen-mode.
*/
window_priv->msc_offset += new_msc - window_priv->msc;
window_priv->crtc = crtc;
}
static int
present_wnmd_pixmap(WindowPtr window,
PixmapPtr pixmap,
CARD32 serial,
RegionPtr valid,
RegionPtr update,
int16_t x_off,
int16_t y_off,
RRCrtcPtr target_crtc,
SyncFence *wait_fence,
SyncFence *idle_fence,
uint32_t options,
uint64_t target_window_msc,
uint64_t divisor,
uint64_t remainder,
present_notify_ptr notifies,
int num_notifies)
{
uint64_t ust = 0;
uint64_t target_msc;
uint64_t crtc_msc = 0;
int ret;
present_vblank_ptr vblank, tmp;
ScreenPtr screen = window->drawable.pScreen;
present_window_priv_ptr window_priv = present_get_window_priv(window, TRUE);
present_screen_priv_ptr screen_priv = present_screen_priv(screen);
if (!window_priv)
return BadAlloc;
target_crtc = present_wnmd_get_crtc(screen_priv, window);
ret = present_wnmd_get_ust_msc(screen, window, &ust, &crtc_msc);
present_wnmd_update_window_crtc(window, target_crtc, crtc_msc);
if (ret == Success) {
/* Stash the current MSC away in case we need it later
*/
window_priv->msc = crtc_msc;
}
target_msc = present_get_target_msc(target_window_msc + window_priv->msc_offset,
crtc_msc,
divisor,
remainder,
options);
/*
* Look for a matching presentation already on the list...
*/
if (!update && pixmap) {
xorg_list_for_each_entry_safe(vblank, tmp, &window_priv->vblank, window_list) {
if (!vblank->pixmap)
continue;
if (!vblank->queued)
continue;
if (vblank->target_msc != target_msc)
continue;
present_vblank_scrap(vblank);
if (vblank->flip_ready)
present_wnmd_re_execute(vblank);
}
}
vblank = present_vblank_create(window,
pixmap,
serial,
valid,
update,
x_off,
y_off,
target_crtc,
wait_fence,
idle_fence,
options,
&screen_priv->wnmd_info->capabilities,
notifies,
num_notifies,
target_msc,
crtc_msc);
if (!vblank)
return BadAlloc;
/* WNMD presentations always complete (at least) one frame after they
* are executed
*/
vblank->exec_msc = vblank->target_msc - 1;
xorg_list_append(&vblank->event_queue, &window_priv->exec_queue);
vblank->queued = TRUE;
if (crtc_msc < vblank->exec_msc) {
if (present_wnmd_queue_vblank(screen, window, target_crtc, vblank->event_id, vblank->exec_msc) == Success) {
return Success;
}
DebugPresent(("present_queue_vblank failed\n"));
}
present_wnmd_execute(vblank, ust, crtc_msc);
return Success;
}
static void
present_wnmd_abort_vblank(ScreenPtr screen, WindowPtr window, RRCrtcPtr crtc, uint64_t event_id, uint64_t msc)
{
present_screen_priv_ptr screen_priv = present_screen_priv(screen);
present_window_priv_ptr window_priv = present_window_priv(window);
present_vblank_ptr vblank;
(*screen_priv->wnmd_info->abort_vblank) (window, crtc, event_id, msc);
xorg_list_for_each_entry(vblank, &window_priv->exec_queue, event_queue) {
if (vblank->event_id == event_id) {
xorg_list_del(&vblank->event_queue);
vblank->queued = FALSE;
return;
}
}
xorg_list_for_each_entry(vblank, &window_priv->flip_queue, event_queue) {
if (vblank->event_id == event_id) {
xorg_list_del(&vblank->event_queue);
vblank->queued = FALSE;
return;
}
}
}
static void
present_wnmd_flush(WindowPtr window)
{
ScreenPtr screen = window->drawable.pScreen;
present_screen_priv_ptr screen_priv = present_screen_priv(screen);
(*screen_priv->wnmd_info->flush) (window);
}
void
present_wnmd_init_mode_hooks(present_screen_priv_ptr screen_priv)
{
screen_priv->query_capabilities = &present_wnmd_query_capabilities;
screen_priv->get_crtc = &present_wnmd_get_crtc;
screen_priv->check_flip = &present_wnmd_check_flip;
screen_priv->check_flip_window = &present_wnmd_check_flip_window;
screen_priv->present_pixmap = &present_wnmd_pixmap;
screen_priv->create_event_id = &present_wnmd_create_event_id;
screen_priv->queue_vblank = &present_wnmd_queue_vblank;
screen_priv->flush = &present_wnmd_flush;
screen_priv->re_execute = &present_wnmd_re_execute;
screen_priv->abort_vblank = &present_wnmd_abort_vblank;
}

View File

@ -615,6 +615,10 @@ RRTellChanged(ScreenPtr pScreen)
primarysp = pScrPriv;
}
/* If there's no root window yet, can't send events */
if (!primary->root)
return;
xorg_list_for_each_entry(iter, &primary->secondary_list, secondary_head) {
pSecondaryScrPriv = rrGetScrPriv(iter);
@ -693,6 +697,33 @@ RRFirstOutput(ScreenPtr pScreen)
return NULL;
}
RRCrtcPtr
RRFirstEnabledCrtc(ScreenPtr pScreen)
{
rrScrPriv(pScreen);
RROutputPtr output;
int i, j;
if (!pScrPriv)
return NULL;
if (pScrPriv->primaryOutput && pScrPriv->primaryOutput->crtc &&
pScrPriv->primaryOutput->pScreen == pScreen)
return pScrPriv->primaryOutput->crtc;
for (i = 0; i < pScrPriv->numCrtcs; i++) {
RRCrtcPtr crtc = pScrPriv->crtcs[i];
for (j = 0; j < pScrPriv->numOutputs; j++) {
output = pScrPriv->outputs[j];
if (output->crtc == crtc && crtc->mode)
return crtc;
}
}
return NULL;
}
CARD16
RRVerticalRefresh(xRRModeInfo * mode)
{

View File

@ -593,6 +593,8 @@ extern _X_EXPORT Bool RRScreenInit(ScreenPtr pScreen);
extern _X_EXPORT RROutputPtr RRFirstOutput(ScreenPtr pScreen);
extern _X_EXPORT RRCrtcPtr RRFirstEnabledCrtc(ScreenPtr pScreen);
extern _X_EXPORT Bool RROutputSetNonDesktop(RROutputPtr output, Bool non_desktop);
extern _X_EXPORT CARD16

View File

@ -182,7 +182,7 @@ if build_xorg
unit = executable('tests',
unit_sources,
c_args: unit_c_args,
dependencies: [pixman_dep, randrproto_dep, inputproto_dep],
dependencies: [pixman_dep, randrproto_dep, inputproto_dep, libxcvt_dep],
include_directories: unit_includes,
link_args: ldwraps,
link_with: xorg_link,

View File

@ -215,7 +215,11 @@ static _X_COLD int
SProcXFixesDispatch(ClientPtr client)
{
REQUEST(xXFixesReq);
if (stuff->xfixesReqType >= XFixesNumberRequests)
XFixesClientPtr pXFixesClient = GetXFixesClient(client);
if (pXFixesClient->major_version >= ARRAY_SIZE(version_requests))
return BadRequest;
if (stuff->xfixesReqType > version_requests[pXFixesClient->major_version])
return BadRequest;
return (*SProcXFixesVector[stuff->xfixesReqType]) (client);
}

View File

@ -870,6 +870,7 @@ CopyISOLockArgs(XkbDescPtr xkb, XkbAction *action, char *buf, int *sz)
XkbISOAction *act;
char tbuf[64];
memset(tbuf, 0, sizeof(tbuf));
act = &action->iso;
if (act->flags & XkbSA_ISODfltIsGroup) {
TryCopyStr(tbuf, "group=", sz);