Re: [PATCH wayland v2] wayland-server: abort instead of posting events with wrong client objects
On Fri, 9 Dec 2016 15:51:10 +0100 Giulio Camuffosaid: > 2016-12-08 20:36 GMT+01:00 Derek Foreman : > > Check that all the objects in an event belong to the same client as > > the resource posting it. This prevents a compositor from accidentally > > mixing client objects and posting an event that causes a client to > > kill itself. > > > > It's intended that the compositor killing itself be easier to debug > > than the client killing itself for something that it's completely > > innocent of. > > It may be easier, but as an user the compositor crashing is a highly > disruptive event, and i think we should strive to avoid it at all > times. By all means, log the problem, get a backtrace and print it, > maybe, but i don't agree with the abort(). Unless the problem really > is unrecoverable, but it seems this is not the case. If it was an > assert(0) it may be better, but i'm not sure i'd like that either. i agree. aborts are VERY anti-social for a library to do. reporting an error and making the function a "NOP" is by far the best thing. > Cheers, > Giulio > > > > > Signed-off-by: Derek Foreman > > --- > > > > Changes since v1: > > uses get_next_arguments and arg_count_for_signature in the normal fashion > > abort instead of assert > > > > > > This does not address Pekka's request for a new_id test, as it's not > > immediately clear to me how to write it. > > > > src/wayland-server.c | 29 + > > 1 file changed, 29 insertions(+) > > > > diff --git a/src/wayland-server.c b/src/wayland-server.c > > index 9d7d9c1..429dbef 100644 > > --- a/src/wayland-server.c > > +++ b/src/wayland-server.c > > @@ -160,6 +160,33 @@ log_closure(struct wl_resource *resource, > > } > > } > > > > +static void > > +verify_objects(struct wl_resource *resource, uint32_t opcode, > > + union wl_argument *args) > > +{ > > + struct wl_object *object = >object; > > + const char *signature = object->interface->events[opcode].signature; > > + struct argument_details arg; > > + struct wl_resource *res; > > + int count, i; > > + > > + count = arg_count_for_signature(signature); > > + for (i = 0; i < count; i++) { > > + signature = get_next_argument(signature, ); > > + switch (arg.type) { > > + case 'o': > > + res = (struct wl_resource *) (args[i].o); > > + if (res && res->client != resource->client) { > > + wl_log("unrecoverable error: The compositor > > " > > + "tried to use an object from one " > > + "client in an event for a different " > > + "client.\n"); > > + abort(); > > + } > > + } > > + } > > +} > > + > > WL_EXPORT void > > wl_resource_post_event_array(struct wl_resource *resource, uint32_t opcode, > > union wl_argument *args) > > @@ -167,6 +194,7 @@ wl_resource_post_event_array(struct wl_resource > > *resource, uint32_t opcode, struct wl_closure *closure; > > struct wl_object *object = >object; > > > > + verify_objects(resource, opcode, args); > > closure = wl_closure_marshal(object, opcode, args, > > >interface->events[opcode]); > > > > @@ -206,6 +234,7 @@ wl_resource_queue_event_array(struct wl_resource > > *resource, uint32_t opcode, struct wl_closure *closure; > > struct wl_object *object = >object; > > > > + verify_objects(resource, opcode, args); > > closure = wl_closure_marshal(object, opcode, args, > > >interface->events[opcode]); > > > > -- > > 2.10.2 > > > > ___ > > wayland-devel mailing list > > wayland-devel@lists.freedesktop.org > > https://lists.freedesktop.org/mailman/listinfo/wayland-devel > ___ > wayland-devel mailing list > wayland-devel@lists.freedesktop.org > https://lists.freedesktop.org/mailman/listinfo/wayland-devel -- - Codito, ergo sum - "I code, therefore I am" -- The Rasterman (Carsten Haitzler)ras...@rasterman.com ___ wayland-devel mailing list wayland-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/wayland-devel
Re: [RFC wayland-protocols] Color management protocol
On Fri, 09 Dec 2016 14:06:46 +0100 Niels Ole Salscheidersaid: > Am Freitag, 9. Dezember 2016, 12:02:07 CET schrieb Carsten Haitzler: > > On Thu, 8 Dec 2016 17:32:37 +1100 Graeme Gill said: > > > Carsten Haitzler (The Rasterman) wrote: > > > > i'm curious... is the intent to make it requird that all compositors > > > > support color management (and thus have to support all the possible > > > > colorspaces> > > > > defined)... or are we going to go the path of: > > > I'd be happy if there was support for core color management (i.e. > > > application color management), before adding layers that depend on the > > > core. > > > > but is the intent that compositors MUST support color management and > > applications will fail entirely or fail to display even partly correctly if > > compositor doesnt support color management or doesnt support the color > > profile/space requested by the client? or will it be expected that apps need > > to always be able to convert to sRGB for compatibility and then have added > > colorspace capabilities if it's supported? what is the intent? > > We can't make support for this protocol mandatory because color correction > might be too much overhead for compositors for embedded devices. well graeme disagrees and effectively thinks it should be. :) > But I would say that every compositor that does some sort of color correction > should also implement the color management protocol. > If the protocol is not supported by the compositor you would assume that you > have to output the colors in the device color space (or just ignore it if you > do not care about accurate colors). > ___ > wayland-devel mailing list > wayland-devel@lists.freedesktop.org > https://lists.freedesktop.org/mailman/listinfo/wayland-devel -- - Codito, ergo sum - "I code, therefore I am" -- The Rasterman (Carsten Haitzler)ras...@rasterman.com ___ wayland-devel mailing list wayland-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/wayland-devel
Re: [RFC wayland-protocols] Color management protocol
On Fri, 09 Dec 2016 14:38:37 +0100 Niels Ole Salscheidersaid: > Am Donnerstag, 8. Dezember 2016, 15:51:12 CET schrieb Graeme Gill: > > Niels Ole Salscheider wrote: > > > Therefore I think that the situation has changed and I'd like to propose > > > this protocol for inclusion in wayland-protocols again. > > > What do you think? > > > > Hi, > > I'm prompted to look into the current state of color management > > in Wayland, by Richard Hughes comment on the ArgyllCMS mailing list > > > > recently that: > > > About this; in the near future systems will be migrating from X11 to > > > Wayland (Fedora 25 already defaults to Wayland, other distros will > > > follow) and so setting X atoms is no longer going to work. Even with > > > XWayland (the compatibility "wrapper" that provides an isolated > > > xserver for the app) you can't use the root window as it's isolated > > > from the other windows. I think most applications that want to know > > > what profile to use are now using either libcolord, or more commonly, > > > the colord DBus API. > > > > What I take from this is that XWayland is lacking in its emulation > > of existing X11 color management protocols (primarily due to lack > > of underlying support in Wayland), and that currently the only > > option for pure Wayland applications is to depend on system > > specific work-arounds such as using Weston with colord. I can > > therefore see that users that depend on color managed X11 applications > > (such as photographers, desktop publishers, video editors etc.) > > aren't going to be switching to Wayland based systems any > > time soon. > > > > Looking through the current Wayland color-management protocol > > proposal, I think it is missing a really fundamental thing - > > managing the output device color calibration state and color > > profile. I guess the assumption is that this is being done > > by colord, but my understanding is that colord is specific > > to Gnome based systems, and certainly depends on DBus, which > > Wayland does not. [ Please correct me if I've got any of this wrong. ] > > It is (currently) up to the compositor to decide how to implement this. The > compositor could come with its own settings for the output color profiles or > query some other program. This might be colord, but it could also be > kolormanager, or something else. > > > It also seems fundamentally poor design to be using a parallel > > protocol to manage the color of the graphics system, rather > > than it being kept in sync with the elements being managed, > > such as outputs and pixel rasters, etc. Certainly in X11 it is > > all kept within the X11 protocol or its extensions. > > If Wayland gets extended to be a remote protocol, then > > the existence of in band protocols for color management > > become even more important. > > Yes, with the protocol I proposed there is a (small) time window after > changing the output color space where the application might still display > surfaces with the old color space... wouldn't it be best not to explicitly ask for an output colorspace and just provide the colorspace of your buffer and let the compositor decide? e.g. if your window is on top, or it's the largest one, or it's focused,then the compositor MAY switch the colorspace of that monitor to match your surface's buffer colorspace, and if it goes into the background or whatever, switch back? it can (and likely should) emulato other colorspaced then. e.g. if buffer is adobe rgb, then switch display to work in adobe rgb but re-render everything else that is sRGB into adobe argb space... there might be a slight "flicker" so to speak as maybe some banding appears in some gradients of SRGB windows or colors are ever so slightly off, but the compositor is optimizing for the surface it thinks it most important. i really don't like the idea of applications explicitly controlling screen colorspace. simple being able to list colorspaces available, know which might be native or emulated, and then say which colorspace their buffer has. this way colorspace is tired directly to the buffer and the compositor can avoid these glitches (like time difference between switching screen colorspace and buffers actually being provided in that colorspace). > > So as a broad outline, what I would regard as features of > > a reasonable color management facility for a graphics > > system such as Wayland are: > > > > * That color management protocol's have two uses :- 1) configuring > > color management and 2) allowing applications to use color management. > > These two uses may need different security profiles. > > The assumption should be that color management applications > > used to create calibrations, profiles and configure the > > state of color management, are of equal importance to color > > managed applications that depend on a properly profiled and > > configured color management system, since you can't have latter > >
Re: [RFC wayland-protocols] Color management protocol
On Fri, 09 Dec 2016 14:29:14 +0100 Niels Ole Salscheidersaid: > Am Donnerstag, 8. Dezember 2016, 13:33:20 CET schrieb Graeme Gill: > > Niels Ole Salscheider wrote: > > > > Hi, > > > > > The first version of my proposal had such a flag. I removed it and > > > replaced it by the described version based on feedback from Zoxc > > > (zox...@gmail.com). > > Do you have a link to the specifics ? > > Most of the discussion happened on IRC back then. It should be in the logs > but... > > > > I can see advantages with both solutions. One advantage with the current > > > proposal is that you can have a surface that covers multiple screens. In > > > this case the compositor can still try its best to correct the colours > > > for all but the main screen. > > > > I'm not quite sure what you mean. Generally an application will have > > specific reasons for wanting to do it's own color management - for > > instance, perhaps it is previewing a CMYKOGlclm file, and wants to > > treat out of gamut mapping and black point mapping in a particular way, etc. > > I don't think the Wayland compositor is going to be expected to handle > > CMYKOGlclm etc. input rasters, never mind all the requirements of > > specialist application color management! > > This is of course something that the client application has to do. It would > query the main output for its surface, do the conversions to that color space > and then attach the output color space to the surface. > > The compositor now must not touch the parts of the surface on the main output > (where the color spaces match). But it could still try to convert from the > color space of the main output to that of a secondary screen if the surface > covers two screens with different color profiles. > > This might of course cause artifacts when one of the screens has a too small > gamut but still seems better than ignoring this. > > But then again most people that work with professional applications would not > make them cover multiple screens, I guess. Therefore I'm not opposed to > adding a flag that indicates that the application wants to disable color > corrections completely for that surface, independent of the output. why not simply let the compositor decide. if a surface spans multile screens it may have to emulate on another screen (egh one screen can do adobe arg, another is ye-olde sRGB). this is simply a matter of letting the compositor know what colorspace the rgb values are in so it can "do the appropriate thing". :) > > Which is not to say that compositor color management doesn't have its > > place - it is ideal for applications that just want to use "RGB", and > > not deal with specific display behavior. > > Very simple applications would just keep the attached sRGB color space and > maybe place images on subsurfaces with the embedded color space from the > image attached. > > Applications that care a bit more about color correction (but do not have > professional needs) could convert all their colors to the blending color > space of the compositor. I'd expect this blending color space to be linear if > the compositor cares about good colors. > This would have the advantage that the compositor does not have to do the > conversion "application output color space -> blending color space". if compositor just lists what colorspaces it can do, which happen to have native hardware support (i.e. the display panel itself is capable of it), then client can choose whatever works best, and compositor just "does its best" too which may mean adjusting dislpay gammut or output transforms at the gpu level or via side-bad protocols with the display panel itself if that were to exist. > > > Back then I argued that this might not be good enough if you want to > > > calibrate the monitor. But the consent was that this would require > > > another protocol to disable all colour corrections anyway and that it > > > could be developed at a later point. > > > > I strongly disagree with this idea - disabling application-side color > > management is a fundamental step in achieving end to end color management. > > You don't have color management until you are able to profile the output > > device, so this is not something that can be left until latter! > > > > Graeme Gill. > > > > > > ___ > > wayland-devel mailing list > > wayland-devel@lists.freedesktop.org > > https://lists.freedesktop.org/mailman/listinfo/wayland-devel > > > ___ > wayland-devel mailing list > wayland-devel@lists.freedesktop.org > https://lists.freedesktop.org/mailman/listinfo/wayland-devel -- - Codito, ergo sum - "I code, therefore I am" -- The Rasterman (Carsten Haitzler)ras...@rasterman.com ___ wayland-devel mailing list wayland-devel@lists.freedesktop.org
Re: [PATCH wayland] util: Document wl_array and wl_list members
Hi Yong, On 6 December 2016 at 15:21, Yong Bakoswrote: > Despite their clear names, wl_array and wl_list members are undocumented, > resulting in doxygen warnings[1] when building documentation. > > Document these members, suppressing the warnings. Not a difficult review; pushed. Cheers, Daniel ___ wayland-devel mailing list wayland-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/wayland-devel
Re: [PATCH weston RFC] compositor-wayland: Support building without EGL
Hi Armin, On 9 December 2016 at 21:58, Armin Krezovićwrote: > +#ifdef ENABLE_EGL /* Defined but not used */ > +#ifdef ENABLE_EGL /* Force pixman when EGL support is disabled */ > b->use_pixman = new_config->use_pixman; > +#else > + b->use_pixman = true; > +#endif Bikeshedding a bit, I don't think these comments really add anything, and I'd just ditch them when applying. But that being said: Acked-by: Daniel Stone and if no-one beats me to setting up an EGL-less environment to test it, I'll upgrade to R-b when I do. Thanks! (And yes, I'll modify pixel-formats to suit.) Cheers, Daniel ___ wayland-devel mailing list wayland-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/wayland-devel
Re: [PATCH 0/2] xdg-shell: Proposal to be more generic for decorations
Overall, I like the idea - it seems to solve the issues with raise/lower, etc. I wonder, though, if removing the explicit move/resize/etc. requests makes it too restrictive. Suppose that, for whatever reason, the client wants to trigger a move or a resize using the right or middle button. Maybe it's a weirdly-shaped surface (like weston-flower) where all of it is draggable, or some other strange case. As far as I can tell, it's possible in v6, but not v7. Another, more real use case: nautilus has a bunch of buttons in the titlebar. If you click them, they work as usual - but dragging a button triggers a shell move. That means, at the time the client receives a mouse down event, it doesn't know yet what it should do. Once it gets a mouse move, it sends a shell move request. Would that still be possible in v7? On Fri, Dec 9, 2016 at 2:20 PM, Adam Goodewrote: > Hi, > > There were many different opinions and suggestions for how to allow > for raise and lower to be bound to mouse clicks in titlebars. This > is one possible way forward. It removes some of the semantic requests > in xdg-shell and replaces it with a "interact_with_decoration" > request that lets more window management logic move into the compositor. > > Comments welcome. I know this is a tricky issue, but I hope this > is leading somewhat in the right direction. > > > Adam > > > > Adam Goode (2): > xdg-shell: Introduce protocol v7 > xdg-shell: Fold several client-side decoration requests into a generic > request > > COPYING |1 + > unstable/xdg-shell/xdg-shell-unstable-v7.xml | 1012 > ++ > 2 files changed, 1013 insertions(+) > create mode 100644 unstable/xdg-shell/xdg-shell-unstable-v7.xml > > -- > 2.8.0.rc3.226.g39d4020 > > ___ > wayland-devel mailing list > wayland-devel@lists.freedesktop.org > https://lists.freedesktop.org/mailman/listinfo/wayland-devel > ___ wayland-devel mailing list wayland-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/wayland-devel
[PATCH 2/2] xdg-shell: Fold several client-side decoration requests into a generic request
Compositors currently receive "move", "resize", and "show_window_menu" requests from clients whose decorations have been interacted with. Clients currently implement key- and mouse-binding policies to determine which one of these requests to send to the compositor in response to user action. Desktop environments traditionally have let users bind a large number of potential actions to various interactions with decorations: not just a handful like move and resize. This change to xdg-shell makes the protocol more generic, allowing more surface management policy to be implemented in the compositor directly. This centralizes more policy in compositors, reducing policy duplication from client toolkits and allowing for more standard surface management behavior across them. Signed-off-by: Adam Goode--- COPYING | 1 + unstable/xdg-shell/xdg-shell-unstable-v7.xml | 137 +++ 2 files changed, 55 insertions(+), 83 deletions(-) diff --git a/COPYING b/COPYING index 8ab3291..73cebf9 100644 --- a/COPYING +++ b/COPYING @@ -6,6 +6,7 @@ Copyright © 2014 Jonas Ådahl Copyright © 2014 Jason Ekstrand Copyright © 2014-2015 Collabora, Ltd. Copyright © 2015 Red Hat Inc. +Copyright © 2016 Google Inc. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), diff --git a/unstable/xdg-shell/xdg-shell-unstable-v7.xml b/unstable/xdg-shell/xdg-shell-unstable-v7.xml index de5d21c..c039936 100644 --- a/unstable/xdg-shell/xdg-shell-unstable-v7.xml +++ b/unstable/xdg-shell/xdg-shell-unstable-v7.xml @@ -580,101 +580,72 @@ - - - Clients implementing client-side decorations might want to show - a context menu when right-clicking on the decorations, giving the - user a menu that they can use to maximize or minimize the window. - - This request asks the compositor to pop up such a window menu at - the given position, relative to the local surface coordinates of - the parent surface. There are no guarantees as to what menu items - the window menu contains. - - This request must be used in response to some sort of user action - like a button press, key press, or touch down event. - - - - - - - - - - Start an interactive, user-driven move of the surface. - - This request must be used in response to some sort of user action - like a button press, key press, or touch down event. The passed - serial is used to determine the type of interactive move (touch, - pointer, etc). - - The server may ignore move requests depending on the state of - the surface (e.g. fullscreen or maximized), or if the passed serial - is no longer valid. - - If triggered, the surface will lose the focus of the device - (wl_pointer, wl_touch, etc) used for the move. It is up to the - compositor to visually indicate that the move is taking place, such as - updating a pointer cursor, during the move. There is no guarantee - that the device focus will return when the move is completed. - - - - - - - - These values are used to indicate which edge of a surface - is being dragged in a resize operation. + + + These values are used to indicate which part of a surface + is being interacted with in an interact_with_decoration operation. - - - - - - - - + + + + + + + + + - - - Start a user-driven, interactive resize of the surface. + + + Start a user-driven interaction on a client-side + decoration. Clients should send this when a user interacts + with the bare titlebar or edge of a client-side decoration. This request must be used in response to some sort of user action like a button press, key press, or touch down event. The passed - serial is used to determine the type of interactive resize (touch, + serial is used to determine the type of interactive action (touch, pointer, etc). - The server may ignore resize requests depending on the state of - the surface (e.g. fullscreen or maximized). - - If triggered, the client will receive configure events with the - "resize" state enum value and the expected sizes. See the "resize" - enum value for more details about what is required. The client - must also acknowledge configure events using "ack_configure". After - the resize is completed, the client will receive another "configure" - event without the resize state. - - If triggered, the surface also will lose the focus of the device - (wl_pointer, wl_touch, etc)
[PATCH 0/2] xdg-shell: Proposal to be more generic for decorations
Hi, There were many different opinions and suggestions for how to allow for raise and lower to be bound to mouse clicks in titlebars. This is one possible way forward. It removes some of the semantic requests in xdg-shell and replaces it with a "interact_with_decoration" request that lets more window management logic move into the compositor. Comments welcome. I know this is a tricky issue, but I hope this is leading somewhat in the right direction. Adam Adam Goode (2): xdg-shell: Introduce protocol v7 xdg-shell: Fold several client-side decoration requests into a generic request COPYING |1 + unstable/xdg-shell/xdg-shell-unstable-v7.xml | 1012 ++ 2 files changed, 1013 insertions(+) create mode 100644 unstable/xdg-shell/xdg-shell-unstable-v7.xml -- 2.8.0.rc3.226.g39d4020 ___ wayland-devel mailing list wayland-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/wayland-devel
[PATCH 1/2] xdg-shell: Introduce protocol v7
There are no changes in this from v6 to v7, that will come next. Signed-off-by: Adam Goode--- unstable/xdg-shell/xdg-shell-unstable-v7.xml | 1041 ++ 1 file changed, 1041 insertions(+) create mode 100644 unstable/xdg-shell/xdg-shell-unstable-v7.xml diff --git a/unstable/xdg-shell/xdg-shell-unstable-v7.xml b/unstable/xdg-shell/xdg-shell-unstable-v7.xml new file mode 100644 index 000..de5d21c --- /dev/null +++ b/unstable/xdg-shell/xdg-shell-unstable-v7.xml @@ -0,0 +1,1041 @@ + + + + +Copyright © 2008-2013 Kristian Høgsberg +Copyright © 2013 Rafael Antognolli +Copyright © 2013 Jasper St. Pierre +Copyright © 2010-2013 Intel Corporation + +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. + + + + + xdg_shell allows clients to turn a wl_surface into a "real window" + which can be dragged, resized, stacked, and moved around by the + user. Everything about this interface is suited towards traditional + desktop environments. + + + + + + + + + + + + + + Destroy this xdg_shell object. + + Destroying a bound xdg_shell object while there are surfaces + still alive created by this xdg_shell object instance is illegal + and will result in a protocol error. + + + + + + Create a positioner object. A positioner object is used to position + surfaces relative to some parent surface. See the interface description + and xdg_surface.get_popup for details. + + + + + + + This creates an xdg_surface for the given surface. While xdg_surface + itself is not a role, the corresponding surface may only be assigned + a role extending xdg_surface, such as xdg_toplevel or xdg_popup. + + This creates an xdg_surface for the given surface. An xdg_surface is + used as basis to define a role to a given surface, such as xdg_toplevel + or xdg_popup. It also manages functionality shared between xdg_surface + based surface roles. + + See the documentation of xdg_surface for more details about what an + xdg_surface is and how it is used. + + + + + + + + A client must respond to a ping event with a pong request or + the client may be deemed unresponsive. See xdg_shell.ping. + + + + + + + The ping event asks the client if it's still alive. Pass the + serial specified in the event back to the compositor by sending + a "pong" request back with the specified serial. See xdg_shell.ping. + + Compositors can use this to determine if the client is still + alive. It's unspecified what will happen if the client doesn't + respond to the ping request, or in what timeframe. Clients should + try to respond in a reasonable amount of time. + + A compositor is free to ping in any way it wants, but a client must + always respond to any xdg_shell object it created. + + + + + + + + The xdg_positioner provides a collection of rules for the placement of a + child surface relative to a parent surface. Rules can be defined to ensure + the child surface remains within the visible area's borders, and to + specify how the child surface changes its position, such as sliding along + an axis, or flipping around a rectangle. + + See the various requests for details about possible rules. + + At the time of the request, the compositor makes a copy of the rules + specified by the xdg_positioner. Thus, after the request is complete the + xdg_positioner object can be destroyed or reused; further changes to the + object will have no effect on previous usages. + + For an xdg_positioner object to be considered
Re: Fwd: [PATCH weston 01/68] libweston: Add pixel-format helpers
On 09.12.2016 22:30, Daniel Stone wrote: > Hi, > Hi, > On 9 December 2016 at 20:37, Armin Krezovićwrote: >> On 09.12.2016 20:57, Daniel Stone wrote: >>> libweston/pixel-formats.c | 398 >>> ++ >>> libweston/pixel-formats.h | 112 + >> >> Where are corresponding build system modifications? > > Missing, apparently ... :\ > >>> +#include >>> +#include >>> +#include >>> +#include >> >> Is it supposed to work without EGL/GLESv2 enabled? > > Not really, no; note that the DRM backend has a hard dependency on GBM > and the Wayland backend has a hard dependency on libwayland-egl, so > this only really affects people building the X11/headless backends > only with no EGL. I suppose we could do a giant #ifdef tree, or just > pull all the tokens we use into weston-egl-ext.h and use that. Do you > have any preferences? > Well, if my guess is correct, this is supposed to be part of libweston, no? I don't think some people would like to have hard EGL dep on libweston itself, and conditionally building this into the library might produce incompatible lib with and without --disable-egl using the same source. That said, I'm all for importing the needed bits into weston-egl-ext.h (if you prefer to #ifdef a lot, go ahead). >>> +/** >>> + * Table of DRM formats supported by Weston; RGB, ARGB and YUV formats are >>> + * supported. Indexed/greyscale formats, and formats not containing >>> complete >>> + * colour channels, are not supported. >>> + */ >> >> I expected something using this immediately. I suggest you squash it with >> something >> else that uses this. > > It could be squashed with 'Store format in drm_fb', but as the > DRM-specific parts of the series were getting very little review, and > it can also be useful for gl-renderer's SHM uploads in particular, I > didn't want to muddle it in with the rest of the series. Depending on > how that goes (whether I get to porting gl-renderer, if earlier parts > of the series get reviewed so we can merge this, etc), it can be > squashed into its first user. > Well, you could've squashed it into that patch and sent it (from what I've seen it doesn't involve any new code and doesn't depend on anything else), and I can help you with review and gl-renderer porting, as this can be landed independently from rest of the series. Even if they don't fit together, at least make the patch that uses this a next one, so someone can take a look at example usage without having to dig through whole series to find out what is using this. > Cheers, > Daniel > signature.asc Description: OpenPGP digital signature ___ wayland-devel mailing list wayland-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/wayland-devel
[PATCH weston RFC] compositor-wayland: Support building without EGL
Signed-off-by: Armin Krezović--- Makefile.am| 1 + configure.ac | 9 ++--- libweston/compositor-wayland.c | 23 ++- 3 files changed, 29 insertions(+), 4 deletions(-) diff --git a/Makefile.am b/Makefile.am index 2219e3d5..704d17af 100644 --- a/Makefile.am +++ b/Makefile.am @@ -383,6 +383,7 @@ wayland_backend_la_LDFLAGS = -module -avoid-version wayland_backend_la_LIBADD =\ $(COMPOSITOR_LIBS) \ $(WAYLAND_COMPOSITOR_LIBS) \ + $(WAYLAND_COMPOSITOR_EGL_LIBS) \ libshared-cairo.la wayland_backend_la_CFLAGS =\ $(COMPOSITOR_CFLAGS)\ diff --git a/configure.ac b/configure.ac index 1e251bfe..0542332c 100644 --- a/configure.ac +++ b/configure.ac @@ -237,11 +237,14 @@ AC_SUBST(WAYLAND_PROTOCOLS_DATADIR, $ac_wayland_protocols_pkgdatadir) AC_ARG_ENABLE(wayland-compositor, [ --enable-wayland-compositor],, enable_wayland_compositor=yes) AM_CONDITIONAL(ENABLE_WAYLAND_COMPOSITOR, - test x$enable_wayland_compositor = xyes -a x$enable_egl = xyes) -if test x$enable_wayland_compositor = xyes -a x$enable_egl = xyes; then + test x$enable_wayland_compositor = xyes) +if test x$enable_wayland_compositor = xyes; then AC_DEFINE([BUILD_WAYLAND_COMPOSITOR], [1], [Build the Wayland (nested) compositor]) - PKG_CHECK_MODULES(WAYLAND_COMPOSITOR, [wayland-client >= $WAYLAND_PREREQ_VERSION wayland-egl wayland-cursor]) + PKG_CHECK_MODULES(WAYLAND_COMPOSITOR, [wayland-client >= $WAYLAND_PREREQ_VERSION wayland-cursor]) + if test x$enable_egl = xyes; then +PKG_CHECK_MODULES(WAYLAND_COMPOSITOR_EGL, [wayland-egl]) + fi fi diff --git a/libweston/compositor-wayland.c b/libweston/compositor-wayland.c index d1e387df..925d2790 100644 --- a/libweston/compositor-wayland.c +++ b/libweston/compositor-wayland.c @@ -38,9 +38,12 @@ #include #include -#include #include +#ifdef ENABLE_EGL +#include +#endif + #include "compositor.h" #include "compositor-wayland.h" #include "gl-renderer.h" @@ -386,6 +389,7 @@ draw_initial_frame(struct wayland_output *output) output->base.current_mode->height); } +#ifdef ENABLE_EGL /* Defined but not used */ static void wayland_output_update_gl_border(struct wayland_output *output) { @@ -455,6 +459,7 @@ wayland_output_update_gl_border(struct wayland_output *output) cairo_image_surface_get_stride(output->gl.border.bottom) / 4, cairo_image_surface_get_data(output->gl.border.bottom)); } +#endif static void wayland_output_start_repaint_loop(struct weston_output *output_base) @@ -480,6 +485,7 @@ wayland_output_start_repaint_loop(struct weston_output *output_base) wl_display_flush(wb->parent.wl_display); } +#ifdef ENABLE_EGL static int wayland_output_repaint_gl(struct weston_output *output_base, pixman_region32_t *damage) @@ -498,6 +504,7 @@ wayland_output_repaint_gl(struct weston_output *output_base, >primary_plane.damage, damage); return 0; } +#endif static void wayland_output_update_shm_border(struct wayland_shm_buffer *buffer) @@ -665,9 +672,11 @@ wayland_output_disable(struct weston_output *base) if (b->use_pixman) { pixman_renderer_output_destroy(>base); +#ifdef ENABLE_EGL } else { gl_renderer->output_destroy(>base); wl_egl_window_destroy(output->gl.egl_window); +#endif } wayland_output_destroy_shm_buffers(output); @@ -702,6 +711,7 @@ wayland_output_destroy(struct weston_output *base) static const struct wl_shell_surface_listener shell_surface_listener; +#ifdef ENABLE_EGL static int wayland_output_init_gl_renderer(struct wayland_output *output) { @@ -737,6 +747,7 @@ cleanup_window: wl_egl_window_destroy(output->gl.egl_window); return -1; } +#endif static int wayland_output_init_pixman_renderer(struct wayland_output *output) @@ -785,6 +796,7 @@ wayland_output_resize_surface(struct wayland_output *output) wl_region_destroy(region); } +#ifdef ENABLE_EGL if (output->gl.egl_window) { wl_egl_window_resize(output->gl.egl_window, width, height, 0, 0); @@ -811,6 +823,7 @@ wayland_output_resize_surface(struct wayland_output *output) cairo_surface_destroy(output->gl.border.bottom); output->gl.border.bottom = NULL; } +#endif wayland_output_destroy_shm_buffers(output); } @@ -1037,11 +1050,13 @@ wayland_output_switch_mode(struct weston_output *output_base, pixman_renderer_output_destroy(output_base); if (wayland_output_init_pixman_renderer(output) <
Re: [PATCH weston v2 0/68] Atomic modesetting, planes, extended drm_fb
Hi, On 9 December 2016 at 19:58, Daniel Stonewrote: > This is v2 of the atomic patchset, which incorporates quite a few > fixups on the original code, and extends it far enough to flip > sprites_are_broken off for atomic. \o/ And it lives here: git://git.collabora.com/git/user/daniels/weston#wip/phab/T7595-atomic-modeset > First we try to construct a view made entirely out of planes and > nothing else; if this succeeds, we just use that and we don't need to > render anything. Failing that, we try to incrementally build a state, > trying one view at a time on one plane at a time, and seeing if that > changes anything. Doing this is what lets us flip sprites_are_broken, > because we can not only generate an optimal configuration, but make > sure it'll actually work when we do it. There are a couple of things I'm not entirely happy with here in hindsight, that a nice long walk has helped clarify. The duplicate_renderer dance in drm_output_propose_state / drm_output_prepare_scanout_view is messy, and in fact leaks the old state when we successfully promote a view to scanout. I did play around with special-casing the drm_plane_state_*() API to deal with this, but didn't like the non-obviousness it introduced. I think a cleaner solution might just be to duplicate the entire output_state; I'll have another play around with both (and a clearer head) next week. The 'test plane states' commit is obscured by the fact overlay assignment moves from picking one plane early and sticking to that, to testing all the planes in a loop. I was trying to avoid exploding the series into too many patches, but may have got the balance wrong there. I'll probably change that in the next iteration. I think we also need to delay start_repaint_loop() if we have a DPMS off that hasn't completed; in testing just now I was able to hit a rare breakage (hooray for asserts!) which I suspect was exactly this. Short of this, any general commments welcome, as well as review of the earlier patches in the series (thanks Armin!), so we can start landing the less dangerous/controversial pieces and trim the series down a bit. Testing on exotic platforms is always good too: I have Intel, Rockchip (with the Mali driver), and Raspberry Pi (less interesting as it can't put client surfaces in planes) here, and hopefully will have Freedreno running next week. Maybe Tegra if Alexandre posts a tree with that working too. Cheers, Daniel ___ wayland-devel mailing list wayland-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/wayland-devel
Fwd: [PATCH weston 01/68] libweston: Add pixel-format helpers
Hi, On 9 December 2016 at 20:37, Armin Krezovićwrote: > On 09.12.2016 20:57, Daniel Stone wrote: >> libweston/pixel-formats.c | 398 >> ++ >> libweston/pixel-formats.h | 112 + > > Where are corresponding build system modifications? Missing, apparently ... :\ >> +#include >> +#include >> +#include >> +#include > > Is it supposed to work without EGL/GLESv2 enabled? Not really, no; note that the DRM backend has a hard dependency on GBM and the Wayland backend has a hard dependency on libwayland-egl, so this only really affects people building the X11/headless backends only with no EGL. I suppose we could do a giant #ifdef tree, or just pull all the tokens we use into weston-egl-ext.h and use that. Do you have any preferences? >> +/** >> + * Table of DRM formats supported by Weston; RGB, ARGB and YUV formats are >> + * supported. Indexed/greyscale formats, and formats not containing complete >> + * colour channels, are not supported. >> + */ > > I expected something using this immediately. I suggest you squash it with > something > else that uses this. It could be squashed with 'Store format in drm_fb', but as the DRM-specific parts of the series were getting very little review, and it can also be useful for gl-renderer's SHM uploads in particular, I didn't want to muddle it in with the rest of the series. Depending on how that goes (whether I get to porting gl-renderer, if earlier parts of the series get reviewed so we can merge this, etc), it can be squashed into its first user. Cheers, Daniel signature.asc Description: PGP signature ___ wayland-devel mailing list wayland-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/wayland-devel
Re: [PATCH weston 02/68] meson: pixel-formats
Hi Armin, On 9 December 2016 at 20:37, Armin Krezovićwrote: >> diff --git a/libweston/meson.build b/libweston/meson.build >> index d396c00..aee444a 100644 >> --- a/libweston/meson.build >> +++ b/libweston/meson.build >> @@ -19,6 +19,7 @@ srcs_libweston = [ >> 'noop-renderer.c', >> 'pixman-renderer.c', >> 'linux-dmabuf.c', >> + 'pixel-formats.c', >> 'screenshooter.c', >> '../shared/file-util.c', >> '../shared/matrix.c', >> > > Since when is meson supported? I don't see it in git master. Oh, it's not; it's just there to make it easier for people who want to use Meson to build. Like me. :) It's really useful for this branch, since when rebasing I'll frequently do 'git rebase -i --exec [make|ninja]' along the entire branch to make sure it builds the whole way; it's easy to introduce warnings in intermediate patches when doing that. With 68 patches, Meson does this in around 30sec for the whole tree, against ~4min for autotools. Safe to say you can ignore this if you're not using Meson; it'll be squashed into either the actual pixel-formats patch or the Meson patch, depending on what lands first, as introducing intermediate build breakage is bad. I wanted to keep it separate from pixel-formats though, so that can land separately if necessary. Cheers, Daniel ___ wayland-devel mailing list wayland-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/wayland-devel
Re: [PATCH weston 41/68] [XXX] compositor-drm: Don't restore original CRTC mode
On 09.12.2016 20:57, Daniel Stone wrote: > When leaving Weston, don't attempt to restore the previous CRTC > settings. The framebuffer may well have disappeared, and in every > likelihood, whoever gets the KMS device afterwards will be repainting > anyway. > > XXX: This breaks gamma. Need to work around that. > > Differential Revision: https://phabricator.freedesktop.org/D1502 > > Signed-off-by: Daniel Stone> --- > libweston/compositor-drm.c | 20 +--- > 1 file changed, 1 insertion(+), 19 deletions(-) > > diff --git a/libweston/compositor-drm.c b/libweston/compositor-drm.c > index 5959aed..2db48f1 100644 > --- a/libweston/compositor-drm.c > +++ b/libweston/compositor-drm.c > @@ -297,7 +297,6 @@ struct drm_output { > uint32_t crtc_id; /* object ID to pass to DRM functions */ > int pipe; /* index of CRTC in resource array / bitmasks */ > uint32_t connector_id; > - drmModeCrtcPtr original_crtc; > struct drm_edid edid; > drmModePropertyPtr dpms_prop; > uint32_t gbm_format; > @@ -1513,8 +1512,6 @@ drm_output_set_gamma(struct weston_output *output_base, > /* check */ > if (output_base->gamma_size != size) > return; > - if (!output->original_crtc) > - return; > > rc = drmModeCrtcSetGamma(backend->drm.fd, >output->crtc_id, > @@ -3630,8 +3627,6 @@ drm_output_set_mode(struct weston_output *base, > output->base.serial_number = "unknown"; > wl_list_init(>base.mode_list); > > - output->original_crtc = drmModeGetCrtc(b->drm.fd, output->crtc_id); > - Can't you just store gamma_size from here? No need to store the original_crtc, just get the gamma value and let it go. > if (connector_get_current_mode(output->connector, b->drm.fd, > _mode) < 0) > goto err_free; > > @@ -3658,9 +3653,6 @@ drm_output_set_mode(struct weston_output *base, > return 0; > > err_free: > - drmModeFreeCrtc(output->original_crtc); > - output->original_crtc = NULL; > - > wl_list_for_each_safe(drm_mode, next, >base.mode_list, > base.link) { > wl_list_remove(_mode->base.link); > @@ -3741,7 +3733,7 @@ drm_output_enable(struct weston_output *base) > output->base.set_dpms = drm_set_dpms; > output->base.switch_mode = drm_output_switch_mode; > > - output->base.gamma_size = output->original_crtc->gamma_size; > + output->base.gamma_size = 0; /* XXX */ > output->base.set_gamma = drm_output_set_gamma; > > output->base.subpixel = > drm_subpixel_to_wayland(output->connector->subpixel); > @@ -3805,7 +3797,6 @@ drm_output_destroy(struct weston_output *base) > { > struct drm_output *output = to_drm_output(base); > struct drm_backend *b = to_drm_backend(base->compositor); > - drmModeCrtcPtr origcrtc = output->original_crtc; > > if (output->page_flip_pending || output->vblank_pending) { > output->destroy_pending = 1; > @@ -3816,14 +3807,6 @@ drm_output_destroy(struct weston_output *base) > if (output->base.enabled) > drm_output_deinit(>base); > > - if (origcrtc) { > - /* Restore original CRTC state */ > - drmModeSetCrtc(b->drm.fd, origcrtc->crtc_id, > origcrtc->buffer_id, > -origcrtc->x, origcrtc->y, > ->connector_id, 1, >mode); > - drmModeFreeCrtc(origcrtc); > - } > - > weston_output_destroy(>base); > > drmModeFreeConnector(output->connector); > @@ -3914,7 +3897,6 @@ create_output_for_connector(struct drm_backend *b, > > output->destroy_pending = 0; > output->disable_pending = 0; > - output->original_crtc = NULL; > > output->state_cur = drm_output_state_alloc(output); > > signature.asc Description: OpenPGP digital signature ___ wayland-devel mailing list wayland-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/wayland-devel
Re: [PATCH weston 18/68] compositor-drm: Drop output from release_fb
On 09.12.2016 20:57, Daniel Stone wrote: > We only need it for the GBM surface the FB was originally created > against; a mismatch here is very bad indeed, so no reason to pass it in > explictly every time rather than store it. > > Differential Revision: https://phabricator.freedesktop.org/D1490 > > Signed-off-by: Daniel StoneMakes sense. Reviewed-by: Armin Krezović > --- > libweston/compositor-drm.c | 20 +++- > 1 file changed, 11 insertions(+), 9 deletions(-) > > diff --git a/libweston/compositor-drm.c b/libweston/compositor-drm.c > index 7dbfc6b..eb735b2 100644 > --- a/libweston/compositor-drm.c > +++ b/libweston/compositor-drm.c > @@ -148,6 +148,7 @@ struct drm_fb { > > /* Used by gbm fbs */ > struct gbm_bo *bo; > + struct gbm_surface *gbm_surface; > > /* Used by dumb fbs */ > void *map; > @@ -466,7 +467,7 @@ drm_fb_set_buffer(struct drm_fb *fb, struct weston_buffer > *buffer) > } > > static void > -drm_output_release_fb(struct drm_output *output, struct drm_fb *fb) > +drm_fb_unref(struct drm_fb *fb) > { > if (!fb) > return; > @@ -479,7 +480,7 @@ drm_output_release_fb(struct drm_output *output, struct > drm_fb *fb) > gbm_bo_destroy(fb->bo); > break; > case BUFFER_GBM_SURFACE: > - gbm_surface_release_buffer(output->gbm_surface, fb->bo); > + gbm_surface_release_buffer(fb->gbm_surface, fb->bo); > break; > default: > assert(NULL); > @@ -615,6 +616,7 @@ drm_output_render_gl(struct drm_output *output, > pixman_region32_t *damage) > gbm_surface_release_buffer(output->gbm_surface, bo); > return; > } > + output->next->gbm_surface = output->gbm_surface; > } > > static void > @@ -798,7 +800,7 @@ drm_output_repaint(struct weston_output *output_base, > err_pageflip: > output->cursor_view = NULL; > if (output->next) { > - drm_output_release_fb(output, output->next); > + drm_fb_unref(output->next); > output->next = NULL; > } > > @@ -900,7 +902,7 @@ vblank_handler(int fd, unsigned int frame, unsigned int > sec, unsigned int usec, > drm_output_update_msc(output, frame); > output->vblank_pending = 0; > > - drm_output_release_fb(output, s->current); > + drm_fb_unref(s->current); > s->current = s->next; > s->next = NULL; > > @@ -930,7 +932,7 @@ page_flip_handler(int fd, unsigned int frame, >* we just want to page flip to the current buffer to get an accurate >* timestamp */ > if (output->page_flip_pending) { > - drm_output_release_fb(output, output->current); > + drm_fb_unref(output->current); > output->current = output->next; > output->next = NULL; > } > @@ -1452,8 +1454,8 @@ drm_output_switch_mode(struct weston_output > *output_base, struct weston_mode *mo > WL_OUTPUT_MODE_CURRENT | WL_OUTPUT_MODE_PREFERRED; > > /* reset rendering stuff. */ > - drm_output_release_fb(output, output->current); > - drm_output_release_fb(output, output->next); > + drm_fb_unref(output->current); > + drm_fb_unref(output->next); > output->current = output->next = NULL; > > if (b->use_pixman) { > @@ -2672,8 +2674,8 @@ destroy_sprites(struct drm_backend *backend) > sprite->plane_id, > output->crtc_id, 0, 0, > 0, 0, 0, 0, 0, 0, 0, 0); > - drm_output_release_fb(output, sprite->current); > - drm_output_release_fb(output, sprite->next); > + drm_fb_unref(sprite->current); > + drm_fb_unref(sprite->next); > weston_plane_release(>plane); > free(sprite); > } > signature.asc Description: OpenPGP digital signature ___ wayland-devel mailing list wayland-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/wayland-devel
Re: [PATCH weston 16/68] compositor-drm: Store format in drm_fb
On 09.12.2016 20:57, Daniel Stone wrote: > This uses the new pixel-format helpers, so we can also replace depth/bpp > with these. > > Signed-off-by: Daniel Stone> > Differential Revision: https://phabricator.freedesktop.org/D1513 So, this is where code added by patch 1 is being used. I suggest squashing it with this one (unless I missed an earlier patch that also uses it). > --- > libweston/compositor-drm.c | 43 +++ > 1 file changed, 27 insertions(+), 16 deletions(-) > > diff --git a/libweston/compositor-drm.c b/libweston/compositor-drm.c > index 217db32..af43a15 100644 > --- a/libweston/compositor-drm.c > +++ b/libweston/compositor-drm.c > @@ -54,6 +54,7 @@ > #include "gl-renderer.h" > #include "weston-egl-ext.h" > #include "pixman-renderer.h" > +#include "pixel-formats.h" > #include "libbacklight.h" > #include "libinput-seat.h" > #include "launcher-util.h" > @@ -140,6 +141,7 @@ struct drm_fb { > enum drm_fb_type type; > > uint32_t fb_id, stride, handle, size; > + const struct pixel_format_info *format; > int width, height; > int fd; > struct weston_buffer_reference buffer_ref; > @@ -267,7 +269,6 @@ drm_fb_create_dumb(struct drm_backend *b, int width, int > height, > { > struct drm_fb *fb; > int ret; > - uint32_t bpp, depth; > > struct drm_mode_create_dumb create_arg; > struct drm_mode_destroy_dumb destroy_arg; > @@ -277,20 +278,20 @@ drm_fb_create_dumb(struct drm_backend *b, int width, > int height, > if (!fb) > return NULL; > > - switch (format) { > - case GBM_FORMAT_XRGB: > - bpp = 32; > - depth = 24; > - break; > - case GBM_FORMAT_RGB565: > - bpp = depth = 16; > - break; > - default: > - return NULL; > + fb->format = pixel_format_get_info(format); > + if (!fb->format) { > + weston_log("failed to look up format 0x%lx\n", > +(unsigned long) format); > + goto err_fb; > + } > + > + if (!fb->format->depth || !fb->format->bpp) { > + weston_log("format 0x%lx is not compatible with dumb buffers\n", > +(unsigned long) format); > } > > memset(_arg, 0, sizeof create_arg); > - create_arg.bpp = bpp; > + create_arg.bpp = fb->format->bpp; > create_arg.width = width; > create_arg.height = height; > > @@ -316,7 +317,8 @@ drm_fb_create_dumb(struct drm_backend *b, int width, int > height, > offsets[0] = 0; > > ret = drmModeAddFB2(b->drm.fd, width, height, > - format, handles, pitches, offsets, > + fb->format->format, > + handles, pitches, offsets, > >fb_id, 0); > if (ret) { > weston_log("addfb2 failed: %m\n"); > @@ -325,7 +327,8 @@ drm_fb_create_dumb(struct drm_backend *b, int width, int > height, > } > > if (ret) { > - ret = drmModeAddFB(b->drm.fd, width, height, depth, bpp, > + ret = drmModeAddFB(b->drm.fd, width, height, > +fb->format->depth, fb->format->bpp, > fb->stride, fb->handle, >fb_id); > } > > @@ -402,9 +405,16 @@ drm_fb_get_from_bo(struct gbm_bo *bo, struct drm_backend > *backend, > fb->height = gbm_bo_get_height(bo); > fb->stride = gbm_bo_get_stride(bo); > fb->handle = gbm_bo_get_handle(bo).u32; > + fb->format = pixel_format_get_info(format); > fb->size = fb->stride * fb->height; > fb->fd = backend->drm.fd; > > + if (!fb->format) { > + weston_log("couldn't look up format 0x%lx\n", > +(unsigned long) format); > + goto err_free; > + } > + > if (backend->min_width > fb->width || > fb->width > backend->max_width || > backend->min_height > fb->height || > @@ -430,9 +440,10 @@ drm_fb_get_from_bo(struct gbm_bo *bo, struct drm_backend > *backend, > } > } > > - if (ret) > + if (ret && fb->format->depth && fb->format->bpp) > ret = drmModeAddFB(backend->drm.fd, fb->width, fb->height, > -24, 32, fb->stride, fb->handle, >fb_id); > +fb->format->depth, fb->format->bpp, > +fb->stride, fb->handle, >fb_id); > > if (ret) { > weston_log("failed to create kms fb: %m\n"); > signature.asc Description: OpenPGP digital signature ___ wayland-devel mailing list wayland-devel@lists.freedesktop.org
Re: [PATCH weston 14/68] compositor-drm: Store width and height inside drm_fb
On 09.12.2016 20:57, Daniel Stone wrote: > This will be used so we can later determine the compatibility of drm_fbs > without needing to introspect external state. > > Differential Revision: https://phabricator.freedesktop.org/D1487 > > Signed-off-by: Daniel StoneLooks fine. Reviewed-by: Armin Krezović > --- > libweston/compositor-drm.c | 24 +--- > 1 file changed, 13 insertions(+), 11 deletions(-) > > diff --git a/libweston/compositor-drm.c b/libweston/compositor-drm.c > index a5052b9..4ef7343 100644 > --- a/libweston/compositor-drm.c > +++ b/libweston/compositor-drm.c > @@ -131,6 +131,7 @@ struct drm_mode { > > struct drm_fb { > uint32_t fb_id, stride, handle, size; > + int width, height; > int fd; > int is_client_buffer; > struct weston_buffer_reference buffer_ref; > @@ -292,6 +293,8 @@ drm_fb_create_dumb(struct drm_backend *b, int width, int > height, > fb->handle = create_arg.handle; > fb->stride = create_arg.pitch; > fb->size = create_arg.size; > + fb->width = width; > + fb->height = height; > fb->fd = b->drm.fd; > > ret = -1; > @@ -371,7 +374,6 @@ drm_fb_get_from_bo(struct gbm_bo *bo, > struct drm_backend *backend, uint32_t format) > { > struct drm_fb *fb = gbm_bo_get_user_data(bo); > - int width, height; > uint32_t handles[4] = { 0 }, pitches[4] = { 0 }, offsets[4] = { 0 }; > int ret; > > @@ -384,17 +386,17 @@ drm_fb_get_from_bo(struct gbm_bo *bo, > > fb->bo = bo; > > - width = gbm_bo_get_width(bo); > - height = gbm_bo_get_height(bo); > + fb->width = gbm_bo_get_width(bo); > + fb->height = gbm_bo_get_height(bo); > fb->stride = gbm_bo_get_stride(bo); > fb->handle = gbm_bo_get_handle(bo).u32; > - fb->size = fb->stride * height; > + fb->size = fb->stride * fb->height; > fb->fd = backend->drm.fd; > > - if (backend->min_width > width || > - width > backend->max_width || > - backend->min_height > height || > - height > backend->max_height) { > + if (backend->min_width > fb->width || > + fb->width > backend->max_width || > + backend->min_height > fb->height || > + fb->height > backend->max_height) { > weston_log("bo geometry out of bounds\n"); > goto err_free; > } > @@ -406,7 +408,7 @@ drm_fb_get_from_bo(struct gbm_bo *bo, > pitches[0] = fb->stride; > offsets[0] = 0; > > - ret = drmModeAddFB2(backend->drm.fd, width, height, > + ret = drmModeAddFB2(backend->drm.fd, fb->width, fb->height, > format, handles, pitches, offsets, > >fb_id, 0); > if (ret) { > @@ -417,8 +419,8 @@ drm_fb_get_from_bo(struct gbm_bo *bo, > } > > if (ret) > - ret = drmModeAddFB(backend->drm.fd, width, height, 24, 32, > -fb->stride, fb->handle, >fb_id); > + ret = drmModeAddFB(backend->drm.fd, fb->width, fb->height, > +24, 32, fb->stride, fb->handle, >fb_id); > > if (ret) { > weston_log("failed to create kms fb: %m\n"); > signature.asc Description: OpenPGP digital signature ___ wayland-devel mailing list wayland-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/wayland-devel
Re: [PATCH weston 13/68] compositor-drm: Use signed int for width/height
On 09.12.2016 20:57, Daniel Stone wrote: > This makes it sign-compatible with weston_output->{width,height}. > > Differential Revision: https://phabricator.freedesktop.org/D1486 > > Signed-off-by: Daniel Stone> Reviewed-by: Quentin Glidic Makes sense Reviewed-by: Armin Krezović > --- > libweston/compositor-drm.c | 11 ++- > 1 file changed, 6 insertions(+), 5 deletions(-) > > diff --git a/libweston/compositor-drm.c b/libweston/compositor-drm.c > index a9bde0c..a5052b9 100644 > --- a/libweston/compositor-drm.c > +++ b/libweston/compositor-drm.c > @@ -104,8 +104,8 @@ struct drm_backend { >* due to out of bounds dimensions, and then mistakenly set >* sprites_are_broken: >*/ > - uint32_t min_width, max_width; > - uint32_t min_height, max_height; > + int min_width, max_width; > + int min_height, max_height; > int no_addfb2; > > struct wl_list sprite_list; > @@ -253,7 +253,7 @@ drm_fb_destroy_callback(struct gbm_bo *bo, void *data) > } > > static struct drm_fb * > -drm_fb_create_dumb(struct drm_backend *b, unsigned width, unsigned height, > +drm_fb_create_dumb(struct drm_backend *b, int width, int height, > uint32_t format) > { > struct drm_fb *fb; > @@ -371,7 +371,7 @@ drm_fb_get_from_bo(struct gbm_bo *bo, > struct drm_backend *backend, uint32_t format) > { > struct drm_fb *fb = gbm_bo_get_user_data(bo); > - uint32_t width, height; > + int width, height; > uint32_t handles[4] = { 0 }, pitches[4] = { 0 }, offsets[4] = { 0 }; > int ret; > > @@ -391,7 +391,8 @@ drm_fb_get_from_bo(struct gbm_bo *bo, > fb->size = fb->stride * height; > fb->fd = backend->drm.fd; > > - if (backend->min_width > width || width > backend->max_width || > + if (backend->min_width > width || > + width > backend->max_width || > backend->min_height > height || > height > backend->max_height) { > weston_log("bo geometry out of bounds\n"); > Ha, the patch description didn't mention coding style fix! (Just kidding) signature.asc Description: OpenPGP digital signature ___ wayland-devel mailing list wayland-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/wayland-devel
Re: [PATCH weston 12/68] compositor-drm: Use fb->fd consistently
On 09.12.2016 20:57, Daniel Stone wrote: > Everyone else uses fb->fd rather than pulling the FD back out of GBM. > Use that in the destroy callback too. > > Signed-off-by: Daniel Stone> Makes sense. Reviewed-by: Armin Krezović > Differential Revision: https://phabricator.freedesktop.org/D1406 > --- > libweston/compositor-drm.c | 3 +-- > 1 file changed, 1 insertion(+), 2 deletions(-) > > diff --git a/libweston/compositor-drm.c b/libweston/compositor-drm.c > index 3276ed0..a9bde0c 100644 > --- a/libweston/compositor-drm.c > +++ b/libweston/compositor-drm.c > @@ -243,10 +243,9 @@ static void > drm_fb_destroy_callback(struct gbm_bo *bo, void *data) > { > struct drm_fb *fb = data; > - struct gbm_device *gbm = gbm_bo_get_device(bo); > > if (fb->fb_id) > - drmModeRmFB(gbm_device_get_fd(gbm), fb->fb_id); > + drmModeRmFB(fb->fd, fb->fb_id); > > weston_buffer_reference(>buffer_ref, NULL); > > signature.asc Description: OpenPGP digital signature ___ wayland-devel mailing list wayland-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/wayland-devel
Re: [PATCH weston 09/68] compositor-drm: Reshuffle and comment plane conditions
On 09.12.2016 20:57, Daniel Stone wrote: > Try to harmonise the various plane-import paths a little bit, starting > with reshuffling and commenting the conditions to do so. > > Signed-off-by: Daniel Stone> This makes code more readable and understandable. So have a Reviewed-by: Armin Krezović > Differential Revision: https://phabricator.freedesktop.org/D1413 > --- > libweston/compositor-drm.c | 79 > -- > 1 file changed, 48 insertions(+), 31 deletions(-) > > diff --git a/libweston/compositor-drm.c b/libweston/compositor-drm.c > index 5fb45b4..8cd9d5a 100644 > --- a/libweston/compositor-drm.c > +++ b/libweston/compositor-drm.c > @@ -502,18 +502,28 @@ drm_output_prepare_scanout_view(struct drm_output > *output, > struct gbm_bo *bo; > uint32_t format; > > - if (ev->geometry.x != output->base.x || > - ev->geometry.y != output->base.y || > - buffer == NULL || b->gbm == NULL || > - buffer->width != output->base.current_mode->width || > - buffer->height != output->base.current_mode->height || > - output->base.transform != viewport->buffer.transform || > - ev->transform.enabled) > + /* We use GBM to import buffers. */ > + if (b->gbm == NULL) > + return NULL; > + > + if (buffer == NULL) > return NULL; > > + /* Make sure our view is exactly compatible with the output. */ > + if (ev->geometry.x != output->base.x || > + ev->geometry.y != output->base.y) > + return NULL; > + if (ev->transform.enabled) > + return NULL; > if (ev->geometry.scissor_enabled) > return NULL; > > + if (buffer->width != output->base.current_mode->width || > + buffer->height != output->base.current_mode->height) > + return NULL; > + if (viewport->buffer.transform != output->base.transform) > + return NULL; > + > bo = gbm_bo_import(b->gbm, GBM_BO_IMPORT_WL_BUFFER, > buffer->resource, GBM_BO_USE_SCANOUT); > > @@ -950,34 +960,33 @@ drm_output_prepare_overlay_view(struct drm_output > *output, > uint32_t format; > wl_fixed_t sx1, sy1, sx2, sy2; > > - if (b->gbm == NULL) > - return NULL; > - > - if (viewport->buffer.transform != output->base.transform) > - return NULL; > - > - if (viewport->buffer.scale != output->base.current_scale) > - return NULL; > - > if (b->sprites_are_broken) > return NULL; > > + /* Don't import buffers which span multiple outputs. */ > if (ev->output_mask != (1u << output->base.id)) > return NULL; > > - if (ev->surface->buffer_ref.buffer == NULL) > + /* We can only import GBM buffers. */ > + if (b->gbm == NULL) > return NULL; > - buffer_resource = ev->surface->buffer_ref.buffer->resource; > > - if (ev->alpha != 1.0f) > + if (ev->surface->buffer_ref.buffer == NULL) > return NULL; > - > + buffer_resource = ev->surface->buffer_ref.buffer->resource; > if (wl_shm_buffer_get(buffer_resource)) > return NULL; > > + if (viewport->buffer.transform != output->base.transform) > + return NULL; > + if (viewport->buffer.scale != output->base.current_scale) > + return NULL; > if (!drm_view_transform_supported(ev)) > return NULL; > > + if (ev->alpha != 1.0f) > + return NULL; > + > wl_list_for_each(s, >sprite_list, link) { > if (!drm_sprite_crtc_supported(output, s)) > continue; > @@ -1114,23 +1123,20 @@ drm_output_prepare_cursor_view(struct drm_output > *output, > struct weston_buffer_viewport *viewport = >surface->buffer_viewport; > struct wl_shm_buffer *shmbuf; > > - if (ev->transform.enabled && > - (ev->transform.matrix.type > WESTON_MATRIX_TRANSFORM_TRANSLATE)) > - return NULL; > - if (b->gbm == NULL) > - return NULL; > - if (output->base.transform != WL_OUTPUT_TRANSFORM_NORMAL) > - return NULL; > - if (viewport->buffer.scale != output->base.current_scale) > + if (b->cursors_are_broken) > return NULL; > + > if (output->cursor_view) > return NULL; > + > + /* Don't import buffers which span multiple outputs. */ > if (ev->output_mask != (1u << output->base.id)) > return NULL; > - if (b->cursors_are_broken) > - return NULL; > - if (ev->geometry.scissor_enabled) > + > + /* We use GBM to import SHM buffers. */ > + if (b->gbm == NULL) > return NULL; > + > if (ev->surface->buffer_ref.buffer == NULL) > return NULL; > shmbuf = wl_shm_buffer_get(ev->surface->buffer_ref.buffer->resource); > @@ -1138,6
Re: [PATCH weston 04/68] compositor-drm: Delete drm_backend_set_modes
On 09.12.2016 20:57, Daniel Stone wrote: > Even if we do have a framebuffer matching the mode, we immediately > schedule a repaint, meaning we either do work for no reason, or show > stale content before we bring up the new content. > > Delete this and just let repaint deal with it. > > Differential Revision: https://phabricator.freedesktop.org/D1481 > > Signed-off-by: Daniel StoneSince drm_output_repaint() calls drmModeSetCrtc() when needed and weston_compositor_damage_all() will schedule a repaint, this makes sense. Reviewed-by: Armin Krezović > --- > libweston/compositor-drm.c | 33 - > 1 file changed, 33 deletions(-) > > diff --git a/libweston/compositor-drm.c b/libweston/compositor-drm.c > index 268117d..7d1c01b 100644 > --- a/libweston/compositor-drm.c > +++ b/libweston/compositor-drm.c > @@ -2824,38 +2824,6 @@ drm_destroy(struct weston_compositor *ec) > } > > static void > -drm_backend_set_modes(struct drm_backend *backend) > -{ > - struct drm_output *output; > - struct drm_mode *drm_mode; > - int ret; > - > - wl_list_for_each(output, >compositor->output_list, base.link) { > - if (!output->current) { > - /* If something that would cause the output to > - * switch mode happened while in another vt, we > - * might not have a current drm_fb. In that case, > - * schedule a repaint and let drm_output_repaint > - * handle setting the mode. */ > - weston_output_schedule_repaint(>base); > - continue; > - } > - > - drm_mode = (struct drm_mode *) output->base.current_mode; > - ret = drmModeSetCrtc(backend->drm.fd, output->crtc_id, > - output->current->fb_id, 0, 0, > - >connector_id, 1, > - _mode->mode_info); > - if (ret < 0) { > - weston_log( > - "failed to set mode %dx%d for output at %d,%d: > %m\n", > - drm_mode->base.width, drm_mode->base.height, > - output->base.x, output->base.y); > - } > - } > -} > - > -static void > session_notify(struct wl_listener *listener, void *data) > { > struct weston_compositor *compositor = data; > @@ -2866,7 +2834,6 @@ session_notify(struct wl_listener *listener, void *data) > if (compositor->session_active) { > weston_log("activating session\n"); > compositor->state = b->prev_state; > - drm_backend_set_modes(b); > weston_compositor_damage_all(compositor); > udev_input_enable(>input); > } else { > signature.asc Description: OpenPGP digital signature ___ wayland-devel mailing list wayland-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/wayland-devel
Re: [PATCH weston 03/68] compositor-drm: Comment struct members
On 09.12.2016 20:57, Daniel Stone wrote: > Clarify the difference between crtc_id (DRM object) and pipe (index into > drmModeRes->crtcs array, possible_crtcs bitmask). > > Signed-off-by: Daniel Stone> Reviewed-by: Quentin Glidic > Differential Revision: https://phabricator.freedesktop.org/D1405 Documenting structure members is always welcome. Reviewed-by: Armin Krezović (this time it's me!) > --- > libweston/compositor-drm.c | 4 ++-- > 1 file changed, 2 insertions(+), 2 deletions(-) > > diff --git a/libweston/compositor-drm.c b/libweston/compositor-drm.c > index a899213..268117d 100644 > --- a/libweston/compositor-drm.c > +++ b/libweston/compositor-drm.c > @@ -155,8 +155,8 @@ struct drm_output { > struct weston_output base; > drmModeConnector *connector; > > - uint32_t crtc_id; > - int pipe; > + uint32_t crtc_id; /* object ID to pass to DRM functions */ > + int pipe; /* index of CRTC in resource array / bitmasks */ > uint32_t connector_id; > drmModeCrtcPtr original_crtc; > struct drm_edid edid; > signature.asc Description: OpenPGP digital signature ___ wayland-devel mailing list wayland-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/wayland-devel
Re: [PATCH weston 02/68] meson: pixel-formats
On 09.12.2016 20:57, Daniel Stone wrote: > Differential Revision: https://phabricator.freedesktop.org/D1512 > --- > libweston/meson.build | 1 + > 1 file changed, 1 insertion(+) > > diff --git a/libweston/meson.build b/libweston/meson.build > index d396c00..aee444a 100644 > --- a/libweston/meson.build > +++ b/libweston/meson.build > @@ -19,6 +19,7 @@ srcs_libweston = [ > 'noop-renderer.c', > 'pixman-renderer.c', > 'linux-dmabuf.c', > + 'pixel-formats.c', > 'screenshooter.c', > '../shared/file-util.c', > '../shared/matrix.c', > Since when is meson supported? I don't see it in git master. signature.asc Description: OpenPGP digital signature ___ wayland-devel mailing list wayland-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/wayland-devel
Re: [PATCH weston 01/68] libweston: Add pixel-format helpers
On 09.12.2016 20:57, Daniel Stone wrote: > Rather than duplicating knowledge of pixel formats across several > components, create a custom central repository. > Hi, > Signed-off-by: Daniel Stone> > Differential Revision: https://phabricator.freedesktop.org/D1511 > --- > libweston/pixel-formats.c | 398 > ++ > libweston/pixel-formats.h | 112 + > 2 files changed, 510 insertions(+) > create mode 100644 libweston/pixel-formats.c > create mode 100644 libweston/pixel-formats.h > Where are corresponding build system modifications? > diff --git a/libweston/pixel-formats.c b/libweston/pixel-formats.c > new file mode 100644 > index 000..9c70e73 > --- /dev/null > +++ b/libweston/pixel-formats.c > @@ -0,0 +1,398 @@ > +/* > + * Copyright © 2016 Collabora, Ltd. > + * > + * 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. > + * > + * Author: Daniel Stone > + */ > + > +#include "config.h" > + > +#include > +#include > +#include > +#include > + > +#include "helpers.h" > +#include "wayland-util.h" > +#include "pixel-formats.h" > + > +#include > +#include > +#include > +#include > + Is it supposed to work without EGL/GLESv2 enabled? > +#include "weston-egl-ext.h" > + > +/** > + * Table of DRM formats supported by Weston; RGB, ARGB and YUV formats are > + * supported. Indexed/greyscale formats, and formats not containing complete > + * colour channels, are not supported. > + */ I expected something using this immediately. I suggest you squash it with something else that uses this. signature.asc Description: OpenPGP digital signature ___ wayland-devel mailing list wayland-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/wayland-devel
[PATCH weston 61/68] compositor-drm: Ignore views on other outputs
When we come to assign_planes, try very hard to ignore views which are only visible on other outputs, rather than forcibly moving them to the primary plane, which causes damage all round and unnecessary repaints. Signed-off-by: Daniel StoneDifferential Revision: https://phabricator.freedesktop.org/D1530 --- libweston/compositor-drm.c | 24 +++- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/libweston/compositor-drm.c b/libweston/compositor-drm.c index be2b4ea..dc68768 100644 --- a/libweston/compositor-drm.c +++ b/libweston/compositor-drm.c @@ -1409,10 +1409,6 @@ drm_fb_get_from_view(struct drm_output_state *state, struct weston_view *ev) struct linux_dmabuf_buffer *dmabuf; struct drm_fb *fb; - /* Don't import buffers which span multiple outputs. */ - if (ev->output_mask != (1u << output->base.id)) - return NULL; - if (ev->alpha != 1.0f) return NULL; @@ -2504,10 +2500,6 @@ drm_output_prepare_cursor_view(struct drm_output_state *output_state, if (plane->state_cur->output && plane->state_cur->output != output) return NULL; - /* Don't import buffers which span multiple outputs. */ - if (ev->output_mask != (1u << output->base.id)) - return NULL; - /* We use GBM to import SHM buffers. */ if (b->gbm == NULL) return NULL; @@ -2666,13 +2658,22 @@ drm_output_propose_state(struct weston_output *output_base) wl_list_for_each(ev, _base->compositor->view_list, link) { struct weston_plane *next_plane = NULL; + /* If this view doesn't touch our output at all, there's no +* reason to do anything with it. */ + if (!(ev->output_mask & (1u << output->base.id))) + continue; + + /* We only assign planes to views which are exclusively present +* on our output. */ + if (ev->output_mask != (1u << output->base.id)) + next_plane = primary; + /* Since we process views from top to bottom, we know that if * the view intersects the calculated renderer region, it must * be part of, or occluded by, it, and cannot go on a plane. */ pixman_region32_init(_overlap); pixman_region32_intersect(_overlap, _region, >transform.boundingbox); - if (pixman_region32_not_empty(_overlap)) next_plane = primary; pixman_region32_fini(_overlap); @@ -2711,6 +2712,11 @@ drm_assign_planes(struct weston_output *output_base) wl_list_for_each(ev, _base->compositor->view_list, link) { struct drm_plane *target_plane = NULL; + /* If this view doesn't touch our output at all, there's no +* reason to do anything with it. */ + if (!(ev->output_mask & (1u << output->base.id))) + continue; + /* Test whether this buffer can ever go into a plane: * non-shm, or small enough to be a cursor. * -- 2.9.3 ___ wayland-devel mailing list wayland-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/wayland-devel
[PATCH weston 22/68] compositor-drm: Rename current/next FB members
'next' is used as a framebuffer which has either been rendered but not had a configuration request (pageflip or CRTC set) applied to it, or when for a framebuffer that has had configuration requested but not applied (delayed pageflip where the event has not been applied). 'current' is used as the last framebuffer for which we know configuration has been fully applied, i.e. CRTC set executed or pageflip requested and event received. Rename these members to fb_current and fb_pending. Signed-off-by: Daniel StoneDifferential Revision: https://phabricator.freedesktop.org/D1410 --- libweston/compositor-drm.c | 86 +++--- 1 file changed, 43 insertions(+), 43 deletions(-) diff --git a/libweston/compositor-drm.c b/libweston/compositor-drm.c index 557b97d..8071737 100644 --- a/libweston/compositor-drm.c +++ b/libweston/compositor-drm.c @@ -190,7 +190,7 @@ struct drm_output { int current_cursor; struct weston_plane fb_plane; - struct drm_fb *current, *next; + struct drm_fb *fb_current, *fb_pending; struct backlight *backlight; struct drm_fb *dumb[2]; @@ -211,7 +211,7 @@ struct drm_sprite { struct weston_plane plane; - struct drm_fb *current, *next; + struct drm_fb *fb_current, *fb_pending; struct drm_output *output; struct drm_backend *backend; @@ -604,13 +604,13 @@ drm_output_prepare_scanout_view(struct drm_output *output, return NULL; } - output->next = drm_fb_get_from_bo(bo, b, format, BUFFER_CLIENT); - if (!output->next) { + output->fb_pending = drm_fb_get_from_bo(bo, b, format, BUFFER_CLIENT); + if (!output->fb_pending) { gbm_bo_destroy(bo); return NULL; } - drm_fb_set_buffer(output->next, buffer); + drm_fb_set_buffer(output->fb_pending, buffer); return >fb_plane; } @@ -630,14 +630,14 @@ drm_output_render_gl(struct drm_output *output, pixman_region32_t *damage) return; } - output->next = drm_fb_get_from_bo(bo, b, output->gbm_format, - BUFFER_GBM_SURFACE); - if (!output->next) { + output->fb_pending = drm_fb_get_from_bo(bo, b, output->gbm_format, + BUFFER_GBM_SURFACE); + if (!output->fb_pending) { weston_log("failed to get drm_fb for bo\n"); gbm_surface_release_buffer(output->gbm_surface, bo); return; } - output->next->gbm_surface = output->gbm_surface; + output->fb_pending->gbm_surface = output->gbm_surface; } static void @@ -656,7 +656,7 @@ drm_output_render_pixman(struct drm_output *output, pixman_region32_t *damage) output->current_image ^= 1; - output->next = drm_fb_ref(output->dumb[output->current_image]); + output->fb_pending = drm_fb_ref(output->dumb[output->current_image]); pixman_renderer_output_set_buffer(>base, output->image[output->current_image]); @@ -742,16 +742,16 @@ drm_output_repaint(struct weston_output *output_base, if (output->disable_pending || output->destroy_pending) return -1; - if (!output->next) + if (!output->fb_pending) drm_output_render(output, damage); - if (!output->next) + if (!output->fb_pending) return -1; mode = container_of(output->base.current_mode, struct drm_mode, base); - if (!output->current || - output->current->stride != output->next->stride) { + if (!output->fb_current || + output->fb_current->stride != output->fb_pending->stride) { ret = drmModeSetCrtc(backend->drm.fd, output->crtc_id, -output->next->fb_id, 0, 0, +output->fb_pending->fb_id, 0, 0, >connector_id, 1, >mode_info); if (ret) { @@ -762,7 +762,7 @@ drm_output_repaint(struct weston_output *output_base, } if (drmModePageFlip(backend->drm.fd, output->crtc_id, - output->next->fb_id, + output->fb_pending->fb_id, DRM_MODE_PAGE_FLIP_EVENT, output) < 0) { weston_log("queueing pageflip failed: %m\n"); goto err_pageflip; @@ -782,12 +782,12 @@ drm_output_repaint(struct weston_output *output_base, .request.sequence = 1, }; - if ((!s->current && !s->next) || + if ((!s->fb_current && !s->fb_pending) || !drm_sprite_crtc_supported(output, s)) continue; - if (s->next && !backend->sprites_hidden) -
[PATCH weston 65/68] compositor-drm: Return plane state from plane preparation
Return a pointer to the plane state, rather than indirecting via a weston_plane. Signed-off-by: Daniel StoneDifferential Revision: https://phabricator.freedesktop.org/D1534 --- libweston/compositor-drm.c | 52 -- 1 file changed, 27 insertions(+), 25 deletions(-) diff --git a/libweston/compositor-drm.c b/libweston/compositor-drm.c index 5db0a1a..e51a5b2 100644 --- a/libweston/compositor-drm.c +++ b/libweston/compositor-drm.c @@ -1667,7 +1667,7 @@ enum drm_output_propose_state_mode { DRM_OUTPUT_PROPOSE_STATE_PLANES_ONLY, /**< only assign to planes */ }; -static struct weston_plane * +static struct drm_plane_state * drm_output_prepare_scanout_view(struct drm_output_state *output_state, struct weston_view *ev) { @@ -1706,7 +1706,7 @@ drm_output_prepare_scanout_view(struct drm_output_state *output_state, state->dest_h != (unsigned) output->base.current_mode->height) goto err; - return _plane->base; + return state; err: drm_plane_state_put_back(state); @@ -2399,7 +2399,7 @@ atomic_flip_handler(int fd, unsigned int frame, drm_output_update_complete(output, flags, sec, usec); } -static struct weston_plane * +static struct drm_plane_state * drm_output_prepare_overlay_view(struct drm_output_state *output_state, struct weston_view *ev) { @@ -2462,7 +2462,7 @@ drm_output_prepare_overlay_view(struct drm_output_state *output_state, state->src_h != state->dest_h << 16) goto err; - return >base; + return state; err: drm_plane_state_put_back(state); @@ -2506,7 +2506,7 @@ cursor_bo_update(struct drm_backend *b, struct gbm_bo *bo, weston_log("failed update cursor: %m\n"); } -static struct weston_plane * +static struct drm_plane_state * drm_output_prepare_cursor_view(struct drm_output_state *output_state, struct weston_view *ev) { @@ -2595,7 +2595,7 @@ drm_output_prepare_cursor_view(struct drm_output_state *output_state, if (needs_update) cursor_bo_update(b, plane_state->fb->bo, ev); - return >base; + return plane_state; err: drm_plane_state_put_back(plane_state); @@ -2664,7 +2664,6 @@ drm_output_propose_state(struct weston_output *output_base, struct drm_output_state *state; struct weston_view *ev; pixman_region32_t surface_overlap, renderer_region, occluded_region; - struct weston_plane *primary = _base->compositor->primary_plane; bool renderer_ok = (mode != DRM_OUTPUT_PROPOSE_STATE_PLANES_ONLY); bool planes_ok = !b->sprites_are_broken; @@ -2691,7 +2690,8 @@ drm_output_propose_state(struct weston_output *output_base, pixman_region32_init(_region); wl_list_for_each(ev, _base->compositor->view_list, link) { - struct weston_plane *next_plane = NULL; + struct drm_plane_state *ps = NULL; + bool force_renderer = false; bool occluded = false; /* If this view doesn't touch our output at all, there's no @@ -2702,7 +2702,7 @@ drm_output_propose_state(struct weston_output *output_base, /* We only assign planes to views which are exclusively present * on our output. */ if (ev->output_mask != (1u << output->base.id)) - next_plane = primary; + force_renderer = true; /* Ignore views we know to be totally occluded. */ pixman_region32_init(_overlap); @@ -2721,9 +2721,12 @@ drm_output_propose_state(struct weston_output *output_base, pixman_region32_intersect(_overlap, _region, >transform.boundingbox); if (pixman_region32_not_empty(_overlap)) - next_plane = primary; + force_renderer = true; pixman_region32_fini(_overlap); + if (force_renderer && !renderer_ok) + goto err; + if (drm_view_is_opaque(ev)) pixman_region32_union(_region, _region, @@ -2732,24 +2735,23 @@ drm_output_propose_state(struct weston_output *output_base, /* The cursor plane is 'special' in the sense that we can still * place it in the legacy API, and we gate that with a separate * cursors_are_broken flag. */ - if (next_plane == NULL && !b->cursors_are_broken) - next_plane = drm_output_prepare_cursor_view(state, ev); + if (!force_renderer && !b->cursors_are_broken) + ps = drm_output_prepare_cursor_view(state, ev); if (!planes_ok) -
[PATCH weston 34/68] compositor-drm: Introduce drm_plane_state structure
Track dynamic plane state (CRTC, FB, position) in separate structures, rather than as part of the plane. This will make it easier to handle state management later, and much more closely tracks what the kernel does with atomic modesets. The fb_last pointer previously used in drm_plane now becomes part of output->state_last, and is not directly visible from the plane itself. Signed-off-by: Daniel StoneDifferential Revision: https://phabricator.freedesktop.org/D1412 --- libweston/compositor-drm.c | 330 - 1 file changed, 270 insertions(+), 60 deletions(-) diff --git a/libweston/compositor-drm.c b/libweston/compositor-drm.c index 106d851..43b36f8 100644 --- a/libweston/compositor-drm.c +++ b/libweston/compositor-drm.c @@ -230,6 +230,29 @@ struct drm_edid { */ struct drm_output_state { struct drm_output *output; + + struct wl_list plane_list; +}; + +/** + * Plane state holds the dynamic state for a plane: where it is positioned, + * and which buffer it is currently displaying. + */ +struct drm_plane_state { + struct drm_plane *plane; + struct drm_output *output; + struct drm_output_state *output_state; + + struct drm_fb *fb; + + int32_t src_x, src_y; + uint32_t src_w, src_h; + uint32_t dest_x, dest_y; + uint32_t dest_w, dest_h; + + bool complete; + + struct wl_list link; /* drm_output_state::plane_list */ }; /** @@ -248,14 +271,12 @@ struct drm_output_state { * are referred to as 'sprites'. */ struct drm_plane { - struct wl_list link; - struct weston_plane base; - struct drm_fb *fb_current, *fb_pending, *fb_last; - struct drm_output *output; struct drm_backend *backend; + struct drm_plane_state *state_cur; + enum wdrm_plane_type type; struct plane_properties props; @@ -263,10 +284,7 @@ struct drm_plane { uint32_t plane_id; uint32_t count_formats; - int32_t src_x, src_y; - uint32_t src_w, src_h; - uint32_t dest_x, dest_y; - uint32_t dest_w, dest_h; + struct wl_list link; uint32_t formats[]; }; @@ -936,6 +954,134 @@ drm_fb_unref(struct drm_fb *fb) } /** + * Allocate a new, empty, plane state. + */ +static struct drm_plane_state * +drm_plane_state_alloc(struct drm_output_state *state_output, + struct drm_plane *plane) +{ + struct drm_plane_state *state = calloc(1, sizeof(*state)); + + assert(state); + state->output_state = state_output; + state->plane = plane; + + /* Here we only add the plane state to the desired link, and not +* set the member. Having an output pointer set means that the +* plane will be displayed on the output; this won't be the case +* when we go to disable a plane. In this case, it must be part of +* the commit (and thus the output state), but the member must be +* NULL, as it will not be on any output when the state takes +* effect. +*/ + if (state_output) + wl_list_insert(_output->plane_list, >link); + else + wl_list_init(>link); + + return state; +} + +/** + * Free an existing plane state. As a special case, the state will not + * normally be freed if it is the current state; see drm_plane_set_state. + */ +static void +drm_plane_state_free(struct drm_plane_state *state, bool force) +{ + if (!state) + return; + + wl_list_remove(>link); + wl_list_init(>link); + state->output_state = NULL; + + if (force || state != state->plane->state_cur) { + drm_fb_unref(state->fb); + free(state); + } +} + +/** + * Duplicate an existing plane state into a new output state. + */ +static struct drm_plane_state * +drm_plane_state_duplicate(struct drm_output_state *state_output, + struct drm_plane_state *src) +{ + struct drm_plane_state *dst = malloc(sizeof(*dst)); + struct drm_plane_state *old, *tmp; + + assert(src); + assert(dst); + memcpy(dst, src, sizeof(*dst)); + + wl_list_for_each_safe(old, tmp, _output->plane_list, link) { + if (old->plane == dst->plane) + drm_plane_state_free(old, false); + } + + wl_list_insert(_output->plane_list, >link); + if (src->fb) + dst->fb = drm_fb_ref(src->fb); + dst->output_state = state_output; + dst->complete = false; + + return dst; +} + +/** + * Remove a plane state from an output state; if the plane was previously + * enabled, then replace it with a disabling state. This ensures that the + * output state was untouched from it was before the plane state was + * modified by the caller of this function. + * + * This is required as drm_output_state_get_plane may either allocate a + * new plane state, in which case this
[PATCH weston 41/68] [XXX] compositor-drm: Don't restore original CRTC mode
When leaving Weston, don't attempt to restore the previous CRTC settings. The framebuffer may well have disappeared, and in every likelihood, whoever gets the KMS device afterwards will be repainting anyway. XXX: This breaks gamma. Need to work around that. Differential Revision: https://phabricator.freedesktop.org/D1502 Signed-off-by: Daniel Stone--- libweston/compositor-drm.c | 20 +--- 1 file changed, 1 insertion(+), 19 deletions(-) diff --git a/libweston/compositor-drm.c b/libweston/compositor-drm.c index 5959aed..2db48f1 100644 --- a/libweston/compositor-drm.c +++ b/libweston/compositor-drm.c @@ -297,7 +297,6 @@ struct drm_output { uint32_t crtc_id; /* object ID to pass to DRM functions */ int pipe; /* index of CRTC in resource array / bitmasks */ uint32_t connector_id; - drmModeCrtcPtr original_crtc; struct drm_edid edid; drmModePropertyPtr dpms_prop; uint32_t gbm_format; @@ -1513,8 +1512,6 @@ drm_output_set_gamma(struct weston_output *output_base, /* check */ if (output_base->gamma_size != size) return; - if (!output->original_crtc) - return; rc = drmModeCrtcSetGamma(backend->drm.fd, output->crtc_id, @@ -3630,8 +3627,6 @@ drm_output_set_mode(struct weston_output *base, output->base.serial_number = "unknown"; wl_list_init(>base.mode_list); - output->original_crtc = drmModeGetCrtc(b->drm.fd, output->crtc_id); - if (connector_get_current_mode(output->connector, b->drm.fd, _mode) < 0) goto err_free; @@ -3658,9 +3653,6 @@ drm_output_set_mode(struct weston_output *base, return 0; err_free: - drmModeFreeCrtc(output->original_crtc); - output->original_crtc = NULL; - wl_list_for_each_safe(drm_mode, next, >base.mode_list, base.link) { wl_list_remove(_mode->base.link); @@ -3741,7 +3733,7 @@ drm_output_enable(struct weston_output *base) output->base.set_dpms = drm_set_dpms; output->base.switch_mode = drm_output_switch_mode; - output->base.gamma_size = output->original_crtc->gamma_size; + output->base.gamma_size = 0; /* XXX */ output->base.set_gamma = drm_output_set_gamma; output->base.subpixel = drm_subpixel_to_wayland(output->connector->subpixel); @@ -3805,7 +3797,6 @@ drm_output_destroy(struct weston_output *base) { struct drm_output *output = to_drm_output(base); struct drm_backend *b = to_drm_backend(base->compositor); - drmModeCrtcPtr origcrtc = output->original_crtc; if (output->page_flip_pending || output->vblank_pending) { output->destroy_pending = 1; @@ -3816,14 +3807,6 @@ drm_output_destroy(struct weston_output *base) if (output->base.enabled) drm_output_deinit(>base); - if (origcrtc) { - /* Restore original CRTC state */ - drmModeSetCrtc(b->drm.fd, origcrtc->crtc_id, origcrtc->buffer_id, - origcrtc->x, origcrtc->y, - >connector_id, 1, >mode); - drmModeFreeCrtc(origcrtc); - } - weston_output_destroy(>base); drmModeFreeConnector(output->connector); @@ -3914,7 +3897,6 @@ create_output_for_connector(struct drm_backend *b, output->destroy_pending = 0; output->disable_pending = 0; - output->original_crtc = NULL; output->state_cur = drm_output_state_alloc(output); -- 2.9.3 ___ wayland-devel mailing list wayland-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/wayland-devel
[PATCH weston 15/68] compositor-drm: Add explicit type member to drm_fb
Rather than magically trying to infer what the buffer is and what we should do with it when we go to destroy it, add an explicit type instead. Differential Revision: https://phabricator.freedesktop.org/D1488 Signed-off-by: Daniel Stone--- libweston/compositor-drm.c | 50 +- 1 file changed, 32 insertions(+), 18 deletions(-) diff --git a/libweston/compositor-drm.c b/libweston/compositor-drm.c index 4ef7343..217db32 100644 --- a/libweston/compositor-drm.c +++ b/libweston/compositor-drm.c @@ -129,11 +129,19 @@ struct drm_mode { drmModeModeInfo mode_info; }; +enum drm_fb_type { + BUFFER_INVALID = 0, /**< never used */ + BUFFER_CLIENT, /**< directly sourced from client */ + BUFFER_PIXMAN_DUMB, /**< internal Pixman rendering */ + BUFFER_GBM_SURFACE, /**< internal EGL rendering */ +}; + struct drm_fb { + enum drm_fb_type type; + uint32_t fb_id, stride, handle, size; int width, height; int fd; - int is_client_buffer; struct weston_buffer_reference buffer_ref; /* Used by gbm fbs */ @@ -290,6 +298,7 @@ drm_fb_create_dumb(struct drm_backend *b, int width, int height, if (ret) goto err_fb; + fb->type = BUFFER_PIXMAN_DUMB; fb->handle = create_arg.handle; fb->stride = create_arg.pitch; fb->size = create_arg.size; @@ -352,6 +361,8 @@ drm_fb_destroy_dumb(struct drm_fb *fb) { struct drm_mode_destroy_dumb destroy_arg; + assert(fb->type == BUFFER_PIXMAN_DUMB); + if (!fb->map) return; @@ -370,8 +381,8 @@ drm_fb_destroy_dumb(struct drm_fb *fb) } static struct drm_fb * -drm_fb_get_from_bo(struct gbm_bo *bo, - struct drm_backend *backend, uint32_t format) +drm_fb_get_from_bo(struct gbm_bo *bo, struct drm_backend *backend, + uint32_t format, enum drm_fb_type type) { struct drm_fb *fb = gbm_bo_get_user_data(bo); uint32_t handles[4] = { 0 }, pitches[4] = { 0 }, offsets[4] = { 0 }; @@ -384,6 +395,7 @@ drm_fb_get_from_bo(struct gbm_bo *bo, if (fb == NULL) return NULL; + fb->type = type; fb->bo = bo; fb->width = gbm_bo_get_width(bo); @@ -440,9 +452,6 @@ static void drm_fb_set_buffer(struct drm_fb *fb, struct weston_buffer *buffer) { assert(fb->buffer_ref.buffer == NULL); - - fb->is_client_buffer = 1; - weston_buffer_reference(>buffer_ref, buffer); } @@ -452,15 +461,19 @@ drm_output_release_fb(struct drm_output *output, struct drm_fb *fb) if (!fb) return; - if (fb->map && -(fb != output->dumb[0] && fb != output->dumb[1])) { - drm_fb_destroy_dumb(fb); - } else if (fb->bo) { - if (fb->is_client_buffer) - gbm_bo_destroy(fb->bo); - else - gbm_surface_release_buffer(output->gbm_surface, - fb->bo); + switch (fb->type) { + case BUFFER_PIXMAN_DUMB: + /* nothing: pixman buffers are destroyed manually */ + break; + case BUFFER_CLIENT: + gbm_bo_destroy(fb->bo); + break; + case BUFFER_GBM_SURFACE: + gbm_surface_release_buffer(output->gbm_surface, fb->bo); + break; + default: + assert(NULL); + break; } } @@ -559,7 +572,7 @@ drm_output_prepare_scanout_view(struct drm_output *output, return NULL; } - output->next = drm_fb_get_from_bo(bo, b, format); + output->next = drm_fb_get_from_bo(bo, b, format, BUFFER_CLIENT); if (!output->next) { gbm_bo_destroy(bo); return NULL; @@ -585,7 +598,8 @@ drm_output_render_gl(struct drm_output *output, pixman_region32_t *damage) return; } - output->next = drm_fb_get_from_bo(bo, b, output->gbm_format); + output->next = drm_fb_get_from_bo(bo, b, output->gbm_format, + BUFFER_GBM_SURFACE); if (!output->next) { weston_log("failed to get drm_fb for bo\n"); gbm_surface_release_buffer(output->gbm_surface, bo); @@ -1054,7 +1068,7 @@ drm_output_prepare_overlay_view(struct drm_output *output, return NULL; } - s->next = drm_fb_get_from_bo(bo, b, format); + s->next = drm_fb_get_from_bo(bo, b, format, BUFFER_CLIENT); if (!s->next) { gbm_bo_destroy(bo); return NULL; -- 2.9.3 ___ wayland-devel mailing list wayland-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/wayland-devel
[PATCH weston 07/68] compositor-drm: Simplify drm_sprite_crtc_supported
No need to walk the CRTC list every time looking for CRTC indices, when we already have the CRTC index stashed away. Taking the plane as an argument also simplifies things a little for callers, and future-proofs for a potential future KMS API which passes a list of supported CRTC IDs rather than a bitmask of supported CRTC indices. Signed-off-by: Daniel StoneDifferential Revision: https://phabricator.freedesktop.org/D1407 --- libweston/compositor-drm.c | 20 1 file changed, 4 insertions(+), 16 deletions(-) diff --git a/libweston/compositor-drm.c b/libweston/compositor-drm.c index d577c05..2d5faa0 100644 --- a/libweston/compositor-drm.c +++ b/libweston/compositor-drm.c @@ -234,21 +234,9 @@ static void drm_output_update_msc(struct drm_output *output, unsigned int seq); static int -drm_sprite_crtc_supported(struct drm_output *output, uint32_t supported) +drm_sprite_crtc_supported(struct drm_output *output, struct drm_sprite *sprite) { - struct weston_compositor *ec = output->base.compositor; - struct drm_backend *b = to_drm_backend(ec); - int crtc; - - for (crtc = 0; crtc < b->num_crtcs; crtc++) { - if (b->crtcs[crtc] != output->crtc_id) - continue; - - if (supported & (1 << crtc)) - return -1; - } - - return 0; + return !!(sprite->possible_crtcs & (1 << output->pipe)); } static void @@ -716,7 +704,7 @@ drm_output_repaint(struct weston_output *output_base, }; if ((!s->current && !s->next) || - !drm_sprite_crtc_supported(output, s->possible_crtcs)) + !drm_sprite_crtc_supported(output, s)) continue; if (s->next && !backend->sprites_hidden) @@ -991,7 +979,7 @@ drm_output_prepare_overlay_view(struct drm_output *output, return NULL; wl_list_for_each(s, >sprite_list, link) { - if (!drm_sprite_crtc_supported(output, s->possible_crtcs)) + if (!drm_sprite_crtc_supported(output, s)) continue; if (!s->next) { -- 2.9.3 ___ wayland-devel mailing list wayland-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/wayland-devel
[PATCH weston 64/68] compositor-drm: Add test-only mode to state application
The atomic API can allow us to test state before we apply it, to see if it will be valid. Add support for this, which we will later use in assign_planes to ensure our plane configuration is valid. Signed-off-by: Daniel StoneDifferential Revision: https://phabricator.freedesktop.org/D1533 --- libweston/compositor-drm.c | 58 +- 1 file changed, 42 insertions(+), 16 deletions(-) diff --git a/libweston/compositor-drm.c b/libweston/compositor-drm.c index 6b5c7cb..5db0a1a 100644 --- a/libweston/compositor-drm.c +++ b/libweston/compositor-drm.c @@ -1561,7 +1561,12 @@ drm_output_get_disable_state(struct drm_output *output) return state; } -static int drm_output_apply_state(struct drm_output_state *state); +enum drm_output_apply_state_mode { + DRM_OUTPUT_APPLY_STATE_TEST, + DRM_OUTPUT_APPLY_STATE_REAL, +}; +static int drm_output_apply_state(struct drm_output_state *state, + enum drm_output_apply_state_mode mode); /** * Mark a drm_output_state (the output's last state) as complete. This handles @@ -1590,7 +1595,7 @@ drm_output_update_complete(struct drm_output *output, uint32_t flags, goto out; } else if (output->dpms_off_pending) { os = drm_output_get_disable_state(output); - drm_output_apply_state(os); + drm_output_apply_state(os, DRM_OUTPUT_APPLY_STATE_REAL); } ts.tv_sec = sec; @@ -1862,7 +1867,8 @@ drm_waitvblank_pipe(struct drm_output *output) } static int -drm_output_apply_state_legacy(struct drm_output_state *state) +drm_output_apply_state_legacy(struct drm_output_state *state, + enum drm_output_apply_state_mode mode) { struct drm_output *output = state->output; struct drm_backend *backend = to_drm_backend(output->base.compositor); @@ -1870,9 +1876,14 @@ drm_output_apply_state_legacy(struct drm_output_state *state) struct drm_plane_state *scanout_state; struct drm_plane_state *ps; struct drm_plane *p; - struct drm_mode *mode; + struct drm_mode *display_mode; int ret = 0; + /* The legacy DRM API gives us no way to test commits without actually +* applying them. */ + if (mode == DRM_OUTPUT_APPLY_STATE_TEST) + return 0; + if (state->dpms != WESTON_DPMS_ON) { wl_list_for_each(ps, >plane_list, link) { p = ps->plane; @@ -1922,7 +1933,7 @@ drm_output_apply_state_legacy(struct drm_output_state *state) assert(scanout_state->src_w == scanout_state->dest_w << 16); assert(scanout_state->src_h == scanout_state->dest_h << 16); - mode = to_drm_mode(output->base.current_mode); + display_mode = to_drm_mode(output->base.current_mode); if (!scanout_plane->state_cur->fb || scanout_plane->state_cur->fb->strides[0] != scanout_state->fb->strides[0]) { @@ -1930,7 +1941,7 @@ drm_output_apply_state_legacy(struct drm_output_state *state) scanout_state->fb->fb_id, 0, 0, >connector_id, 1, ->mode_info); +_mode->mode_info); if (ret) { weston_log("set mode failed: %m\n"); goto err; @@ -2086,14 +2097,15 @@ drm_mode_ensure_blob(struct drm_backend *backend, struct drm_mode *mode) } static int -drm_output_apply_state_atomic(struct drm_output_state *state) +drm_output_apply_state_atomic(struct drm_output_state *state, + enum drm_output_apply_state_mode mode) { struct drm_output *output = state->output; struct drm_backend *backend = to_drm_backend(output->base.compositor); struct drm_plane_state *plane_state; drmModeAtomicReq *req = drmModeAtomicAlloc(); struct drm_mode *current_mode = to_drm_mode(output->base.current_mode); - uint32_t flags = DRM_MODE_PAGE_FLIP_EVENT | DRM_MODE_ATOMIC_NONBLOCK; + uint32_t flags = 0; int ret = 0; if (!req) @@ -2154,7 +2166,16 @@ drm_output_apply_state_atomic(struct drm_output_state *state) } } - if (drmModeAtomicCommit(backend->drm.fd, req, flags, output) != 0) { + if (mode == DRM_OUTPUT_APPLY_STATE_TEST) + flags |= DRM_MODE_ATOMIC_TEST_ONLY; + else + flags |= DRM_MODE_PAGE_FLIP_EVENT | DRM_MODE_ATOMIC_NONBLOCK; + + ret = drmModeAtomicCommit(backend->drm.fd, req, flags, output); + if (mode == DRM_OUTPUT_APPLY_STATE_TEST) + return ret; + + if (ret != 0) { weston_log("couldn't commit new state: %m\n"); goto err; } @@ -2171,16 +2192,17 @@ err: #endif static int
[PATCH weston 66/68] compositor-drm: Test plane states before application
Generate an output state in two stages. Firstly, attempt to run through and generate a configuration with all views in planes. If this succeeds, we can bypass the renderer completely. If this fails, we know we need to have the renderer output used as a base on the scanout plane, and can incrementally attempt to construct a working state, by trying the combination of our old renderer state with planes added one-by-one. If they pass the test commit stage, we can use it, so we stash that state and continue on. Signed-off-by: Daniel StoneDifferential Revision: https://phabricator.freedesktop.org/D1535 --- libweston/compositor-drm.c | 135 + 1 file changed, 101 insertions(+), 34 deletions(-) diff --git a/libweston/compositor-drm.c b/libweston/compositor-drm.c index e51a5b2..7c8b5d9 100644 --- a/libweston/compositor-drm.c +++ b/libweston/compositor-drm.c @@ -1669,12 +1669,15 @@ enum drm_output_propose_state_mode { static struct drm_plane_state * drm_output_prepare_scanout_view(struct drm_output_state *output_state, - struct weston_view *ev) + struct weston_view *ev, + enum drm_output_propose_state_mode mode) { struct drm_output *output = output_state->output; struct drm_plane *scanout_plane = output->scanout_plane; struct drm_plane_state *state; + struct drm_plane_state *state_old = NULL; struct drm_fb *fb; + int ret; fb = drm_fb_get_from_view(output_state, ev); if (!fb) @@ -1687,7 +1690,16 @@ drm_output_prepare_scanout_view(struct drm_output_state *output_state, } state = drm_output_state_get_plane(output_state, scanout_plane); - if (state->fb) { + + /* Check if we've already placed a buffer on this plane; if there's a +* buffer there but it comes from GBM, then it's the result of +* drm_output_propose_state placing it here for testing purposes. */ + if (state->fb && + (state->fb->type == BUFFER_GBM_SURFACE || +state->fb->type == BUFFER_PIXMAN_DUMB)) { + state_old = calloc(1, sizeof(*state_old)); + memcpy(state_old, state, sizeof(*state_old)); + } else if (state->fb) { drm_fb_unref(fb); return NULL; } @@ -1706,10 +1718,21 @@ drm_output_prepare_scanout_view(struct drm_output_state *output_state, state->dest_h != (unsigned) output->base.current_mode->height) goto err; + if (mode == DRM_OUTPUT_PROPOSE_STATE_PLANES_ONLY) + return state; + + ret = drm_output_apply_state(output_state, mode); + if (ret != 0) + goto err; + return state; err: - drm_plane_state_put_back(state); + drm_plane_state_free(state, false); + if (state_old) { + wl_list_insert(_state->plane_list, _old->link); + state_old->output_state = output_state; + } return NULL; } @@ -1780,7 +1803,9 @@ drm_output_render(struct drm_output *output, pixman_region32_t *damage) * want to render. */ scanout_state = drm_output_state_get_plane(output->state_pending, output->scanout_plane); - if (scanout_state->fb) + if (scanout_state->fb && + scanout_state->fb->type != BUFFER_GBM_SURFACE && + scanout_state->fb->type != BUFFER_PIXMAN_DUMB) return; if (!pixman_region32_not_empty(damage) && @@ -1803,6 +1828,7 @@ drm_output_render(struct drm_output *output, pixman_region32_t *damage) return; } + drm_fb_unref(scanout_state->fb); scanout_state->fb = fb; scanout_state->output = output; @@ -2401,24 +2427,24 @@ atomic_flip_handler(int fd, unsigned int frame, static struct drm_plane_state * drm_output_prepare_overlay_view(struct drm_output_state *output_state, - struct weston_view *ev) + struct weston_view *ev, + enum drm_output_propose_state_mode mode) { struct drm_output *output = output_state->output; struct weston_compositor *ec = output->base.compositor; struct drm_backend *b = to_drm_backend(ec); struct drm_plane *p; - struct drm_plane_state *state = NULL; struct drm_fb *fb; unsigned int i; - - if (b->sprites_are_broken) - return NULL; + int ret; fb = drm_fb_get_from_view(output_state, ev); if (!fb) return NULL; wl_list_for_each(p, >plane_list, link) { + struct drm_plane_state *state = NULL; + if (p->type != WDRM_PLANE_TYPE_OVERLAY) continue; @@ -2444,28 +2470,30 @@ drm_output_prepare_overlay_view(struct
[PATCH weston 60/68] compositor-drm: Split drm_assign_planes in two
Move drm_assign_planes into two functions: one which proposes a plane configuration, and another which applies that state to the Weston internal structures. This will be used to try multiple configurations and see which is supported. Signed-off-by: Daniel StoneDifferential Revision: https://phabricator.freedesktop.org/D1529 --- libweston/compositor-drm.c | 106 ++--- 1 file changed, 72 insertions(+), 34 deletions(-) diff --git a/libweston/compositor-drm.c b/libweston/compositor-drm.c index 79f2941..be2b4ea 100644 --- a/libweston/compositor-drm.c +++ b/libweston/compositor-drm.c @@ -293,6 +293,8 @@ struct drm_plane_state { struct drm_fb *fb; + struct weston_view *ev; /**< maintained for drm_assign_planes only */ + int32_t src_x, src_y; uint32_t src_w, src_h; uint32_t dest_x, dest_y; @@ -1685,6 +1687,7 @@ drm_output_prepare_scanout_view(struct drm_output_state *output_state, } state->fb = fb; + state->ev = ev; state->output = output; drm_plane_state_coords_for_view(state, ev); @@ -2426,6 +2429,7 @@ drm_output_prepare_overlay_view(struct drm_output_state *output_state, } state->fb = fb; + state->ev = ev; state->output = output; drm_plane_state_coords_for_view(state, ev); @@ -2562,6 +2566,7 @@ drm_output_prepare_cursor_view(struct drm_output_state *output_state, } output->cursor_view = ev; + plane_state->ev = ev; plane_state->fb = drm_fb_ref(output->gbm_cursor_fb[output->current_cursor]); @@ -2629,16 +2634,14 @@ err: drmModeSetCursor(b->drm.fd, output->crtc_id, 0, 0, 0); } -static void -drm_assign_planes(struct weston_output *output_base) +static struct drm_output_state * +drm_output_propose_state(struct weston_output *output_base) { - struct drm_backend *b = to_drm_backend(output_base->compositor); struct drm_output *output = to_drm_output(output_base); struct drm_output_state *state; - struct drm_plane_state *plane_state; struct weston_view *ev; pixman_region32_t surface_overlap, renderer_region; - struct weston_plane *primary, *next_plane; + struct weston_plane *primary = _base->compositor->primary_plane; assert(!output->state_last); assert(!output->state_pending); @@ -2659,35 +2662,21 @@ drm_assign_planes(struct weston_output *output_base) * as we do for flipping full screen surfaces. */ pixman_region32_init(_region); - primary = _base->compositor->primary_plane; wl_list_for_each(ev, _base->compositor->view_list, link) { - struct weston_surface *es = ev->surface; - - /* Test whether this buffer can ever go into a plane: -* non-shm, or small enough to be a cursor. -* -* Also, keep a reference when using the pixman renderer. -* That makes it possible to do a seamless switch to the GL -* renderer and since the pixman renderer keeps a reference -* to the buffer anyway, there is no side effects. -*/ - if (b->use_pixman || - (es->buffer_ref.buffer && - (!wl_shm_buffer_get(es->buffer_ref.buffer->resource) || -(ev->surface->width <= b->cursor_width && - ev->surface->height <= b->cursor_height - es->keep_buffer = true; - else - es->keep_buffer = false; + struct weston_plane *next_plane = NULL; + /* Since we process views from top to bottom, we know that if +* the view intersects the calculated renderer region, it must +* be part of, or occluded by, it, and cannot go on a plane. */ pixman_region32_init(_overlap); pixman_region32_intersect(_overlap, _region, >transform.boundingbox); - next_plane = NULL; if (pixman_region32_not_empty(_overlap)) next_plane = primary; + pixman_region32_fini(_overlap); + if (next_plane == NULL) next_plane = drm_output_prepare_cursor_view(state, ev); if (next_plane == NULL) @@ -2697,17 +2686,69 @@ drm_assign_planes(struct weston_output *output_base) if (next_plane == NULL) next_plane = primary; - weston_view_move_to_plane(ev, next_plane); - if (next_plane == primary) pixman_region32_union(_region, _region, >transform.boundingbox); + } + pixman_region32_fini(_region); + +
[PATCH weston 56/68] compositor-drm: Avoid GBM for dmabuf import
From: Tomohito EsakiRather than relying on GBM for dmabuf import, perform the import directly through libdrm. This creates a specialised drm_fb type for dmabufs. This also supports multi-planar dmabuf. [daniels: Rebased on top of recent drm_fb/drm_plane_state/etc.] Signed-off-by: Daniel Stone Differential Revision: https://phabricator.freedesktop.org/D1525 --- configure.ac | 3 -- libweston/compositor-drm.c | 131 - 2 files changed, 95 insertions(+), 39 deletions(-) diff --git a/configure.ac b/configure.ac index 8fe48b6..54c6fcd 100644 --- a/configure.ac +++ b/configure.ac @@ -207,9 +207,6 @@ if test x$enable_drm_compositor = xyes; then PKG_CHECK_MODULES(DRM_COMPOSITOR_ATOMIC, [libdrm >= 2.4.62], [AC_DEFINE([HAVE_DRM_ATOMIC], 1, [libdrm supports atomic API])], [AC_MSG_WARN([libdrm does not support atomic modesetting, will omit that capability])]) - PKG_CHECK_MODULES(DRM_COMPOSITOR_GBM, [gbm >= 10.2], - [AC_DEFINE([HAVE_GBM_FD_IMPORT], 1, [gbm supports dmabuf import])], - [AC_MSG_WARN([gbm does not support dmabuf import, will omit that capability])]) fi diff --git a/libweston/compositor-drm.c b/libweston/compositor-drm.c index a2d4c8c..e6f94af 100644 --- a/libweston/compositor-drm.c +++ b/libweston/compositor-drm.c @@ -233,6 +233,7 @@ struct drm_mode { enum drm_fb_type { BUFFER_INVALID = 0, /**< never used */ BUFFER_CLIENT, /**< directly sourced from client */ + BUFFER_DMABUF, /**< imported from linux_dmabuf client */ BUFFER_PIXMAN_DUMB, /**< internal Pixman rendering */ BUFFER_GBM_SURFACE, /**< internal EGL rendering */ BUFFER_CURSOR, /**< internal cursor buffer */ @@ -986,6 +987,82 @@ drm_fb_ref(struct drm_fb *fb) return fb; } +static void +drm_fb_destroy_dmabuf(struct drm_fb *fb) +{ + unsigned int i; + + /* Unlike GBM buffers, where destroying the BO also closes the GEM +* handle, we fully control the handle lifetime for dmabuf buffers. */ + for (i = 0; i < ARRAY_LENGTH(fb->handles); i++) { + struct drm_gem_close gem_close = { .handle = fb->handles[i] }; + if (!gem_close.handle) + continue; + (void) drmIoctl(fb->fd, DRM_IOCTL_GEM_CLOSE, _close); + } + + drm_fb_destroy(fb); +} + +static struct drm_fb * +drm_fb_get_from_dmabuf(struct linux_dmabuf_buffer *dmabuf, + struct drm_backend *backend, bool is_opaque) +{ + struct drm_fb *fb; + int i, ret; + + fb = zalloc(sizeof *fb); + if (fb == NULL) + return NULL; + + fb->refcnt = 1; + fb->type = BUFFER_DMABUF; + + fb->width = dmabuf->attributes.width; + fb->height = dmabuf->attributes.height; + memcpy(fb->strides, dmabuf->attributes.stride, sizeof(fb->strides)); + memcpy(fb->offsets, dmabuf->attributes.offset, sizeof(fb->offsets)); + fb->format = pixel_format_get_info(dmabuf->attributes.format); + fb->size = 0; + fb->fd = backend->drm.fd; + + if (!fb->format) { + weston_log("couldn't look up format info for 0x%lx\n", + (unsigned long) fb->format); + goto err_free; + } + + if (is_opaque) + fb->format = pixel_format_get_opaque_substitute(fb->format); + + if (backend->min_width > fb->width || + fb->width > backend->max_width || + backend->min_height > fb->height || + fb->height > backend->max_height) { + weston_log("bo geometry out of bounds\n"); + goto err_free; + } + + for (i = 0; i < dmabuf->attributes.n_planes; i++) { + ret = drmPrimeFDToHandle(backend->drm.fd, +dmabuf->attributes.fd[i], +>handles[i]); + if (ret) + goto err_free; + } + + if (drm_fb_addfb(fb) != 0) { + weston_log("failed to create kms fb: %m\n"); + goto err_free; + } + + return fb; + +err_free: + drm_fb_destroy_dmabuf(fb); + return NULL; +} + static struct drm_fb * drm_fb_get_from_bo(struct gbm_bo *bo, struct drm_backend *backend, bool is_opaque, enum drm_fb_type type) @@ -1070,6 +1147,9 @@ drm_fb_unref(struct drm_fb *fb) case BUFFER_GBM_SURFACE: gbm_surface_release_buffer(fb->gbm_surface, fb->bo); break; + case BUFFER_DMABUF: + drm_fb_destroy_dmabuf(fb); + break; default: assert(NULL); break; @@ -1300,9 +1380,9 @@ drm_fb_get_from_view(struct drm_output_state *state, struct weston_view *ev) struct drm_output *output = state->output;
[PATCH weston 67/68] compositor-drm: Relax plane restrictions for atomic
Since we now incrementally test atomic state as we build it, we can loosen restrictions on what we can do with planes, and let the kernel tell us whether or not it's OK. Signed-off-by: Daniel StoneDifferential Revision: https://phabricator.freedesktop.org/D1536 --- libweston/compositor-drm.c | 21 + 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/libweston/compositor-drm.c b/libweston/compositor-drm.c index 7c8b5d9..e615eb5 100644 --- a/libweston/compositor-drm.c +++ b/libweston/compositor-drm.c @@ -1673,6 +1673,7 @@ drm_output_prepare_scanout_view(struct drm_output_state *output_state, enum drm_output_propose_state_mode mode) { struct drm_output *output = output_state->output; + struct drm_backend *b = to_drm_backend(output->base.compositor); struct drm_plane *scanout_plane = output->scanout_plane; struct drm_plane_state *state; struct drm_plane_state *state_old = NULL; @@ -1684,7 +1685,7 @@ drm_output_prepare_scanout_view(struct drm_output_state *output_state, return NULL; /* Can't change formats with just a pageflip */ - if (fb->format->format != output->gbm_format) { + if (!b->atomic_modeset && fb->format->format != output->gbm_format) { drm_fb_unref(fb); return NULL; } @@ -1709,15 +1710,18 @@ drm_output_prepare_scanout_view(struct drm_output_state *output_state, state->output = output; drm_plane_state_coords_for_view(state, ev); - /* The legacy API does not let us perform cropping or scaling. */ - if (state->src_x != 0 || state->src_y != 0 || - state->src_w != state->dest_w << 16 || - state->src_h != state->dest_h << 16 || - state->dest_x != 0 || state->dest_y != 0 || + if (state->dest_x != 0 || state->dest_y != 0 || state->dest_w != (unsigned) output->base.current_mode->width || state->dest_h != (unsigned) output->base.current_mode->height) goto err; + /* The legacy API does not let us perform cropping or scaling. */ + if (!b->atomic_modeset && + (state->src_x != 0 || state->src_y != 0 || +state->src_w != state->dest_w << 16 || +state->src_h != state->dest_h << 16)) + goto err; + if (mode == DRM_OUTPUT_PROPOSE_STATE_PLANES_ONLY) return state; @@ -2475,8 +2479,9 @@ drm_output_prepare_overlay_view(struct drm_output_state *output_state, state->output = output; drm_plane_state_coords_for_view(state, ev); - if (state->src_w != state->dest_w << 16 || - state->src_h != state->dest_h << 16) { + if (!b->atomic_modeset && + (state->src_w != state->dest_w << 16 || +state->src_h != state->dest_h << 16)) { drm_plane_state_put_back(state); continue; } -- 2.9.3 ___ wayland-devel mailing list wayland-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/wayland-devel
[PATCH weston 57/68] compositor-drm: Support modifiers for drm_fb
Use the new drmModeAddFB2WithModifiers interface to import buffers with modifiers. Signed-off-by: Daniel StoneDifferential Revision: https://phabricator.freedesktop.org/D1526 --- configure.ac | 3 +++ libweston/compositor-drm.c | 25 - 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index 54c6fcd..74fe7cd 100644 --- a/configure.ac +++ b/configure.ac @@ -207,6 +207,9 @@ if test x$enable_drm_compositor = xyes; then PKG_CHECK_MODULES(DRM_COMPOSITOR_ATOMIC, [libdrm >= 2.4.62], [AC_DEFINE([HAVE_DRM_ATOMIC], 1, [libdrm supports atomic API])], [AC_MSG_WARN([libdrm does not support atomic modesetting, will omit that capability])]) + PKG_CHECK_MODULES(DRM_COMPOSITOR_MODIFIERS, [libdrm >= 2.4.71], + [AC_DEFINE([HAVE_DRM_ADDFB2_MODIFIERS], 1, [libdrm supports modifiers])], + [AC_MSG_WARN([libdrm does not support AddFB2 with modifiers])]) fi diff --git a/libweston/compositor-drm.c b/libweston/compositor-drm.c index e6f94af..a36d27c 100644 --- a/libweston/compositor-drm.c +++ b/libweston/compositor-drm.c @@ -249,6 +249,7 @@ struct drm_fb { uint32_t strides[4]; uint32_t offsets[4]; const struct pixel_format_info *format; + uint64_t modifier; int width, height; int fd; struct weston_buffer_reference buffer_ref; @@ -882,7 +883,28 @@ drm_fb_destroy_gbm(struct gbm_bo *bo, void *data) static int drm_fb_addfb(struct drm_fb *fb) { - int ret; + int ret = -EINVAL; +#ifdef HAVE_DRM_ADDFB2_MODIFIERS + uint64_t mods[4] = { }; + int i; +#endif + + /* If we have a modifier set, we must only use the WithModifiers +* entrypoint; we cannot import it through legacy ioctls. */ + if (fb->modifier) { + /* KMS demands that if a modifier is set, it must be the same +* for all planes. */ +#ifdef HAVE_DRM_ADDFB2_MODIFIERS + for (i = 0; fb->handles[i]; i++) + mods[i] = fb->modifier; + ret = drmModeAddFB2WithModifiers(fb->fd, fb->width, fb->height, +fb->format->format, +fb->handles, fb->strides, +fb->offsets, mods, >fb_id, +DRM_MODE_FB_MODIFIERS); +#endif + return ret; + } ret = drmModeAddFB2(fb->fd, fb->width, fb->height, fb->format->format, fb->handles, fb->strides, fb->offsets, >fb_id, @@ -1023,6 +1045,7 @@ drm_fb_get_from_dmabuf(struct linux_dmabuf_buffer *dmabuf, memcpy(fb->strides, dmabuf->attributes.stride, sizeof(fb->strides)); memcpy(fb->offsets, dmabuf->attributes.offset, sizeof(fb->offsets)); fb->format = pixel_format_get_info(dmabuf->attributes.format); + fb->modifier = dmabuf->attributes.modifier[0]; fb->size = 0; fb->fd = backend->drm.fd; -- 2.9.3 ___ wayland-devel mailing list wayland-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/wayland-devel
[PATCH weston 49/68] compositor-drm: Use plane_state_coords_for_view for scanout
Use the shiny new helper we have for working through scanout as well. Signed-off-by: Daniel StoneDifferential Revision: https://phabricator.freedesktop.org/D1518 --- libweston/compositor-drm.c | 66 -- 1 file changed, 23 insertions(+), 43 deletions(-) diff --git a/libweston/compositor-drm.c b/libweston/compositor-drm.c index cd89083..202772b 100644 --- a/libweston/compositor-drm.c +++ b/libweston/compositor-drm.c @@ -1505,13 +1505,6 @@ drm_output_assign_state(struct drm_output_state *state, } } -static int -drm_view_transform_supported(struct weston_view *ev) -{ - return !ev->transform.enabled || - (ev->transform.matrix.type < WESTON_MATRIX_TRANSFORM_ROTATE); -} - static bool drm_view_is_opaque(struct weston_view *ev) { @@ -1543,7 +1536,6 @@ drm_output_prepare_scanout_view(struct drm_output_state *output_state, struct drm_plane *scanout_plane = output->scanout_plane; struct drm_plane_state *state; struct weston_buffer *buffer = ev->surface->buffer_ref.buffer; - struct weston_buffer_viewport *viewport = >surface->buffer_viewport; struct gbm_bo *bo; /* Don't import buffers which span multiple outputs. */ @@ -1559,67 +1551,55 @@ drm_output_prepare_scanout_view(struct drm_output_state *output_state, if (wl_shm_buffer_get(buffer->resource)) return NULL; - /* Make sure our view is exactly compatible with the output. */ - if (ev->geometry.x != output->base.x || - ev->geometry.y != output->base.y) - return NULL; - if (buffer->width != output->base.current_mode->width || - buffer->height != output->base.current_mode->height) - return NULL; + state = drm_output_state_get_plane(output_state, scanout_plane); + if (state->fb) + goto err; - if (ev->transform.enabled) - return NULL; - if (ev->geometry.scissor_enabled) - return NULL; - if (viewport->buffer.transform != output->base.transform) - return NULL; - if (viewport->buffer.scale != output->base.current_scale) - return NULL; - if (!drm_view_transform_supported(ev)) - return NULL; + state->output = output; + drm_plane_state_coords_for_view(state, ev); + + /* The legacy API does not let us perform cropping or scaling. */ + if (state->src_x != 0 || state->src_y != 0 || + state->src_w != state->dest_w << 16 || + state->src_h != state->dest_h << 16 || + state->dest_x != 0 || state->dest_y != 0 || + state->dest_w != (unsigned) output->base.current_mode->width || + state->dest_h != (unsigned) output->base.current_mode->height) + goto err; if (ev->alpha != 1.0f) - return NULL; + goto err; bo = gbm_bo_import(b->gbm, GBM_BO_IMPORT_WL_BUFFER, buffer->resource, GBM_BO_USE_SCANOUT); /* Unable to use the buffer for scanout */ if (!bo) - return NULL; + goto err; state = drm_output_state_get_plane(output_state, scanout_plane); state->fb = drm_fb_get_from_bo(bo, b, drm_view_is_opaque(ev), BUFFER_CLIENT); if (!state->fb) { - drm_plane_state_put_back(state); + /* We need to explicitly destroy the BO. */ gbm_bo_destroy(bo); - return NULL; + goto err; } /* Can't change formats with just a pageflip */ if (state->fb->format->format != output->gbm_format) { /* No need to destroy the GBM BO here, as it's now owned * by the FB. */ - drm_plane_state_put_back(state); - return NULL; + goto err; } drm_fb_set_buffer(state->fb, buffer); - state->output = output; - - state->src_x = 0; - state->src_y = 0; - state->src_w = ev->surface->width << 16; - state->src_h = ev->surface->height << 16; - - state->dest_x = 0; - state->dest_y = 0; - state->dest_w = output->base.width; - state->dest_h = output->base.height; - return _plane->base; + +err: + drm_plane_state_put_back(state); + return NULL; } static struct drm_fb * -- 2.9.3 ___ wayland-devel mailing list wayland-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/wayland-devel
[PATCH weston 53/68] compositor-drm: Remove no_addfb2 handling
If AddFB2 ever fails for any reason, we fall back to legacy AddFB, which doesn't support the same swathe of formats, or multi-planar formats, or modifiers. This can happen with arbitrary client buffers, condemning us to the fallback forever more. Remove this, at the cost of an unnecessary ioctl for users on old kernels without AddFB2; unfortunately, we cannot detect the complete absence of the ioctl, as the return here is -EINVAL rather than -ENOTTY. Signed-off-by: Daniel StoneDifferential Revision: https://phabricator.freedesktop.org/D1522 --- libweston/compositor-drm.c | 46 -- 1 file changed, 12 insertions(+), 34 deletions(-) diff --git a/libweston/compositor-drm.c b/libweston/compositor-drm.c index ba305ad..5fff646 100644 --- a/libweston/compositor-drm.c +++ b/libweston/compositor-drm.c @@ -204,7 +204,6 @@ struct drm_backend { */ int min_width, max_width; int min_height, max_height; - int no_addfb2; struct wl_list plane_list; int sprites_are_broken; @@ -886,6 +885,7 @@ drm_fb_create_dumb(struct drm_backend *b, int width, int height, struct drm_mode_create_dumb create_arg; struct drm_mode_destroy_dumb destroy_arg; struct drm_mode_map_dumb map_arg; + uint32_t handles[4] = { 0 }, pitches[4] = { 0 }, offsets[4] = { 0 }; fb = zalloc(sizeof *fb); if (!fb) @@ -925,23 +925,12 @@ drm_fb_create_dumb(struct drm_backend *b, int width, int height, ret = -1; - if (!b->no_addfb2) { - uint32_t handles[4] = { 0 }, pitches[4] = { 0 }, offsets[4] = { 0 }; - - handles[0] = fb->handle; - pitches[0] = fb->stride; - offsets[0] = 0; - - ret = drmModeAddFB2(b->drm.fd, width, height, - fb->format->format, - handles, pitches, offsets, - >fb_id, 0); - if (ret) { - weston_log("addfb2 failed: %m\n"); - b->no_addfb2 = 1; - } - } + handles[0] = fb->handle; + pitches[0] = fb->stride; + offsets[0] = 0; + ret = drmModeAddFB2(b->drm.fd, width, height, fb->format->format, + handles, pitches, offsets, >fb_id, 0); if (ret) { ret = drmModeAddFB(b->drm.fd, width, height, fb->format->depth, fb->format->bpp, @@ -1026,24 +1015,13 @@ drm_fb_get_from_bo(struct gbm_bo *bo, struct drm_backend *backend, goto err_free; } - ret = -1; - - if (!backend->no_addfb2) { - handles[0] = fb->handle; - pitches[0] = fb->stride; - offsets[0] = 0; - - ret = drmModeAddFB2(backend->drm.fd, fb->width, fb->height, - fb->format->format, - handles, pitches, offsets, - >fb_id, 0); - if (ret) { - weston_log("addfb2 failed: %m\n"); - backend->no_addfb2 = 1; - backend->sprites_are_broken = 1; - } - } + handles[0] = fb->handle; + pitches[0] = fb->stride; + offsets[0] = 0; + ret = drmModeAddFB2(backend->drm.fd, fb->width, fb->height, + fb->format->format, handles, pitches, offsets, + >fb_id, 0); if (ret && fb->format->depth && fb->format->bpp) ret = drmModeAddFB(backend->drm.fd, fb->width, fb->height, fb->format->depth, fb->format->bpp, -- 2.9.3 ___ wayland-devel mailing list wayland-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/wayland-devel
[PATCH weston 62/68] compositor-drm: Ignore occluded views
When trying to assign planes, keep track of the areas which are already occluded, and ignore views which are completely occluded. This allows us to build a state using planes only, when there are occluded views which cannot go into a plane behind views which can. Signed-off-by: Daniel StoneDifferential Revision: https://phabricator.freedesktop.org/D1531 --- libweston/compositor-drm.c | 20 +++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/libweston/compositor-drm.c b/libweston/compositor-drm.c index dc68768..1eb1fbb 100644 --- a/libweston/compositor-drm.c +++ b/libweston/compositor-drm.c @@ -2632,7 +2632,7 @@ drm_output_propose_state(struct weston_output *output_base) struct drm_output *output = to_drm_output(output_base); struct drm_output_state *state; struct weston_view *ev; - pixman_region32_t surface_overlap, renderer_region; + pixman_region32_t surface_overlap, renderer_region, occluded_region; struct weston_plane *primary = _base->compositor->primary_plane; assert(!output->state_last); @@ -2654,9 +2654,11 @@ drm_output_propose_state(struct weston_output *output_base) * as we do for flipping full screen surfaces. */ pixman_region32_init(_region); + pixman_region32_init(_region); wl_list_for_each(ev, _base->compositor->view_list, link) { struct weston_plane *next_plane = NULL; + bool occluded = false; /* If this view doesn't touch our output at all, there's no * reason to do anything with it. */ @@ -2668,6 +2670,16 @@ drm_output_propose_state(struct weston_output *output_base) if (ev->output_mask != (1u << output->base.id)) next_plane = primary; + /* Ignore views we know to be totally occluded. */ + pixman_region32_init(_overlap); + pixman_region32_subtract(_overlap, +>transform.boundingbox, +_region); + occluded = !pixman_region32_not_empty(_overlap); + pixman_region32_fini(_overlap); + if (occluded) + continue; + /* Since we process views from top to bottom, we know that if * the view intersects the calculated renderer region, it must * be part of, or occluded by, it, and cannot go on a plane. */ @@ -2678,6 +2690,11 @@ drm_output_propose_state(struct weston_output *output_base) next_plane = primary; pixman_region32_fini(_overlap); + if (drm_view_is_opaque(ev)) + pixman_region32_union(_region, + _region, + >transform.boundingbox); + if (next_plane == NULL) next_plane = drm_output_prepare_cursor_view(state, ev); if (next_plane == NULL) @@ -2693,6 +2710,7 @@ drm_output_propose_state(struct weston_output *output_base) >transform.boundingbox); } pixman_region32_fini(_region); + pixman_region32_fini(_region); return state; } -- 2.9.3 ___ wayland-devel mailing list wayland-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/wayland-devel
[PATCH weston 58/68] compositor-drm: Don't need safe view-list traversal
Nothing in this loop reorders views within the compositor's view_list. Signed-off-by: Daniel StoneDifferential Revision: https://phabricator.freedesktop.org/D1527 --- libweston/compositor-drm.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libweston/compositor-drm.c b/libweston/compositor-drm.c index a36d27c..b7ebb2f 100644 --- a/libweston/compositor-drm.c +++ b/libweston/compositor-drm.c @@ -2636,7 +2636,7 @@ drm_assign_planes(struct weston_output *output_base) struct drm_output *output = to_drm_output(output_base); struct drm_output_state *state; struct drm_plane_state *plane_state; - struct weston_view *ev, *next; + struct weston_view *ev; pixman_region32_t overlap, surface_overlap; struct weston_plane *primary, *next_plane; @@ -2661,7 +2661,7 @@ drm_assign_planes(struct weston_output *output_base) pixman_region32_init(); primary = _base->compositor->primary_plane; - wl_list_for_each_safe(ev, next, _base->compositor->view_list, link) { + wl_list_for_each(ev, _base->compositor->view_list, link) { struct weston_surface *es = ev->surface; /* Test whether this buffer can ever go into a plane: -- 2.9.3 ___ wayland-devel mailing list wayland-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/wayland-devel
[PATCH weston 32/68] compositor-drm: Track all plane types
Retain drm_plane tracking objects for all actual DRM planes when using universal planes, not just overlay planes. Rename uses of 'sprite' to 'plane' to make it clear that it can now be any kind of plane, not just an overlay/sprite. These are currently unused. Differential Revision: https://phabricator.freedesktop.org/D1496 Signed-off-by: Daniel Stone--- libweston/compositor-drm.c | 74 +- 1 file changed, 41 insertions(+), 33 deletions(-) diff --git a/libweston/compositor-drm.c b/libweston/compositor-drm.c index 46fcf0a..3dd2924 100644 --- a/libweston/compositor-drm.c +++ b/libweston/compositor-drm.c @@ -152,7 +152,7 @@ struct drm_backend { int min_height, max_height; int no_addfb2; - struct wl_list sprite_list; + struct wl_list plane_list; int sprites_are_broken; int sprites_hidden; @@ -1144,7 +1144,7 @@ drm_output_repaint(struct weston_output *output_base, struct drm_output *output = to_drm_output(output_base); struct drm_backend *backend = to_drm_backend(output->base.compositor); - struct drm_plane *s; + struct drm_plane *p; struct drm_mode *mode; int ret = 0; @@ -1190,26 +1190,31 @@ drm_output_repaint(struct weston_output *output_base, /* * Now, update all the sprite surfaces */ - wl_list_for_each(s, >sprite_list, link) { + wl_list_for_each(p, >plane_list, link) { uint32_t flags = 0, fb_id = 0; drmVBlank vbl = { .request.type = DRM_VBLANK_RELATIVE | DRM_VBLANK_EVENT, .request.sequence = 1, }; - if ((!s->fb_current && !s->fb_pending) || - !drm_plane_crtc_supported(output, s)) + if (p->type != WDRM_PLANE_TYPE_OVERLAY) + continue; + + /* XXX: Set output much earlier, so we don't attempt to place +* planes on entirely the wrong output. */ + if ((!p->fb_current && !p->fb_pending) || + !drm_plane_crtc_supported(output, p)) continue; - if (s->fb_pending && !backend->sprites_hidden) - fb_id = s->fb_pending->fb_id; + if (p->fb_pending && !backend->sprites_hidden) + fb_id = p->fb_pending->fb_id; - ret = drmModeSetPlane(backend->drm.fd, s->plane_id, + ret = drmModeSetPlane(backend->drm.fd, p->plane_id, output->crtc_id, fb_id, flags, - s->dest_x, s->dest_y, - s->dest_w, s->dest_h, - s->src_x, s->src_y, - s->src_w, s->src_h); + p->dest_x, p->dest_y, + p->dest_w, p->dest_h, + p->src_x, p->src_y, + p->src_w, p->src_h); if (ret) weston_log("setplane failed: %d: %s\n", ret, strerror(errno)); @@ -1220,17 +1225,17 @@ drm_output_repaint(struct weston_output *output_base, * Queue a vblank signal so we know when the surface * becomes active on the display or has been replaced. */ - vbl.request.signal = (unsigned long)s; + vbl.request.signal = (unsigned long) p; ret = drmWaitVBlank(backend->drm.fd, ); if (ret) { weston_log("vblank event request failed: %d: %s\n", ret, strerror(errno)); } - s->output = output; - s->fb_last = s->fb_current; - s->fb_current = s->fb_pending; - s->fb_pending = NULL; + p->output = output; + p->fb_last = p->fb_current; + p->fb_current = p->fb_pending; + p->fb_pending = NULL; output->vblank_pending++; } @@ -1469,7 +1474,10 @@ drm_output_prepare_overlay_view(struct drm_output *output, if (ev->alpha != 1.0f) return NULL; - wl_list_for_each(p, >sprite_list, link) { + wl_list_for_each(p, >plane_list, link) { + if (p->type != WDRM_PLANE_TYPE_OVERLAY) + continue; + if (!drm_plane_crtc_supported(output, p)) continue; @@ -2136,7 +2144,7 @@ drm_plane_create(struct drm_backend *b, const drmModePlane *kplane) plane->type = WDRM_PLANE_TYPE_OVERLAY; weston_plane_init(>base, b->compositor, 0, 0); - wl_list_insert(>sprite_list, >link); + wl_list_insert(>plane_list, >link);
[PATCH weston 52/68] compositor-drm: Use plane FB-import helper for scanout
Use the same codepath, which has the added advantage of being able to import dmabufs. Signed-off-by: Daniel StoneDifferential Revision: https://phabricator.freedesktop.org/D1521 --- libweston/compositor-drm.c | 54 +++--- 1 file changed, 12 insertions(+), 42 deletions(-) diff --git a/libweston/compositor-drm.c b/libweston/compositor-drm.c index 59a764d..ba305ad 100644 --- a/libweston/compositor-drm.c +++ b/libweston/compositor-drm.c @@ -1603,29 +1603,27 @@ drm_output_prepare_scanout_view(struct drm_output_state *output_state, struct weston_view *ev) { struct drm_output *output = output_state->output; - struct drm_backend *b = to_drm_backend(output->base.compositor); struct drm_plane *scanout_plane = output->scanout_plane; struct drm_plane_state *state; - struct weston_buffer *buffer = ev->surface->buffer_ref.buffer; - struct gbm_bo *bo; - - /* Don't import buffers which span multiple outputs. */ - if (ev->output_mask != (1u << output->base.id)) - return NULL; + struct drm_fb *fb; - /* We use GBM to import buffers. */ - if (b->gbm == NULL) + fb = drm_fb_get_from_view(output_state, ev); + if (!fb) return NULL; - if (buffer == NULL) - return NULL; - if (wl_shm_buffer_get(buffer->resource)) + /* Can't change formats with just a pageflip */ + if (fb->format->format != output->gbm_format) { + drm_fb_unref(fb); return NULL; + } state = drm_output_state_get_plane(output_state, scanout_plane); - if (state->fb) - goto err; + if (state->fb) { + drm_fb_unref(fb); + return NULL; + } + state->fb = fb; state->output = output; drm_plane_state_coords_for_view(state, ev); @@ -1638,34 +1636,6 @@ drm_output_prepare_scanout_view(struct drm_output_state *output_state, state->dest_h != (unsigned) output->base.current_mode->height) goto err; - if (ev->alpha != 1.0f) - goto err; - - bo = gbm_bo_import(b->gbm, GBM_BO_IMPORT_WL_BUFFER, - buffer->resource, GBM_BO_USE_SCANOUT); - - /* Unable to use the buffer for scanout */ - if (!bo) - goto err; - - state = drm_output_state_get_plane(output_state, scanout_plane); - state->fb = drm_fb_get_from_bo(bo, b, drm_view_is_opaque(ev), - BUFFER_CLIENT); - if (!state->fb) { - /* We need to explicitly destroy the BO. */ - gbm_bo_destroy(bo); - goto err; - } - - /* Can't change formats with just a pageflip */ - if (state->fb->format->format != output->gbm_format) { - /* No need to destroy the GBM BO here, as it's now owned -* by the FB. */ - goto err; - } - - drm_fb_set_buffer(state->fb, buffer); - return _plane->base; err: -- 2.9.3 ___ wayland-devel mailing list wayland-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/wayland-devel
[PATCH weston 68/68] compositor-drm: Enable planes for atomic
Now that we can sensibly test proposed plane configurations with atomic, sprites are not broken. Signed-off-by: Daniel StoneDifferential Revision: https://phabricator.freedesktop.org/D1537 --- libweston/compositor-drm.c | 22 +++--- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/libweston/compositor-drm.c b/libweston/compositor-drm.c index e615eb5..d1f7f0f 100644 --- a/libweston/compositor-drm.c +++ b/libweston/compositor-drm.c @@ -3111,6 +3111,17 @@ init_drm(struct drm_backend *b, struct udev_device *device) weston_log("DRM: %s atomic modesetting\n", b->atomic_modeset ? "supports" : "does not support"); + /* +* KMS support for hardware planes cannot properly synchronize +* without nuclear page flip. Without nuclear/atomic, hw plane +* and cursor plane updates would either tear or cause extra +* waits for vblanks which means dropping the compositor framerate +* to a fraction. For cursors, it's not so bad, so they are +* enabled. +*/ + if (!b->atomic_modeset) + b->sprites_are_broken = 1; + return 0; } @@ -4972,17 +4983,6 @@ drm_backend_create(struct weston_compositor *compositor, if (b == NULL) return NULL; - /* -* KMS support for hardware planes cannot properly synchronize -* without nuclear page flip. Without nuclear/atomic, hw plane -* and cursor plane updates would either tear or cause extra -* waits for vblanks which means dropping the compositor framerate -* to a fraction. For cursors, it's not so bad, so they are -* enabled. -* -* These can be enabled again when nuclear/atomic support lands. -*/ - b->sprites_are_broken = 1; b->compositor = compositor; b->use_pixman = config->use_pixman; b->use_current_mode = config->use_current_mode; -- 2.9.3 ___ wayland-devel mailing list wayland-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/wayland-devel
[PATCH weston 46/68] compositor-drm: Make alpha-to-opaque handling common
Rather than a hardcoded ARGB -> XRGB translation inside a GBM-specific helper, just determine whether or not the view is opaque, and use the generic helpers to implement the format translation. Signed-off-by: Daniel StoneDifferential Revision: https://phabricator.freedesktop.org/D1515 --- libweston/compositor-drm.c | 114 + 1 file changed, 43 insertions(+), 71 deletions(-) diff --git a/libweston/compositor-drm.c b/libweston/compositor-drm.c index 2f9415c..893fdbd 100644 --- a/libweston/compositor-drm.c +++ b/libweston/compositor-drm.c @@ -984,7 +984,7 @@ drm_fb_ref(struct drm_fb *fb) static struct drm_fb * drm_fb_get_from_bo(struct gbm_bo *bo, struct drm_backend *backend, - uint32_t format, enum drm_fb_type type) + bool is_opaque, enum drm_fb_type type) { struct drm_fb *fb = gbm_bo_get_user_data(bo); uint32_t handles[4] = { 0 }, pitches[4] = { 0 }, offsets[4] = { 0 }; @@ -1005,16 +1005,19 @@ drm_fb_get_from_bo(struct gbm_bo *bo, struct drm_backend *backend, fb->height = gbm_bo_get_height(bo); fb->stride = gbm_bo_get_stride(bo); fb->handle = gbm_bo_get_handle(bo).u32; - fb->format = pixel_format_get_info(format); + fb->format = pixel_format_get_info(gbm_bo_get_format(bo)); fb->size = fb->stride * fb->height; fb->fd = backend->drm.fd; if (!fb->format) { weston_log("couldn't look up format 0x%lx\n", - (unsigned long) format); + (unsigned long) gbm_bo_get_format(bo)); goto err_free; } + if (is_opaque) + fb->format = pixel_format_get_opaque_substitute(fb->format); + if (backend->min_width > fb->width || fb->width > backend->max_width || backend->min_height > fb->height || @@ -1025,13 +1028,14 @@ drm_fb_get_from_bo(struct gbm_bo *bo, struct drm_backend *backend, ret = -1; - if (format && !backend->no_addfb2) { + if (!backend->no_addfb2) { handles[0] = fb->handle; pitches[0] = fb->stride; offsets[0] = 0; ret = drmModeAddFB2(backend->drm.fd, fb->width, fb->height, - format, handles, pitches, offsets, + fb->format->format, + handles, pitches, offsets, >fb_id, 0); if (ret) { weston_log("addfb2 failed: %m\n"); @@ -1422,34 +1426,26 @@ drm_view_transform_supported(struct weston_view *ev) (ev->transform.matrix.type < WESTON_MATRIX_TRANSFORM_ROTATE); } -static uint32_t -drm_output_check_scanout_format(struct drm_output *output, - struct weston_surface *es, struct gbm_bo *bo) +static bool +drm_view_is_opaque(struct weston_view *ev) { - uint32_t format; pixman_region32_t r; + bool ret = false; - format = gbm_bo_get_format(bo); - - if (format == GBM_FORMAT_ARGB) { - /* We can scanout an ARGB buffer if the surface's -* opaque region covers the whole output, but we have -* to use XRGB as the KMS format code. */ - pixman_region32_init_rect(, 0, 0, - output->base.width, - output->base.height); - pixman_region32_subtract(, , >opaque); + /* We can scanout an ARGB buffer if the surface's +* opaque region covers the whole output, but we have +* to use XRGB as the KMS format code. */ + pixman_region32_init_rect(, 0, 0, + ev->surface->width, + ev->surface->height); + pixman_region32_subtract(, , >surface->opaque); - if (!pixman_region32_not_empty()) - format = GBM_FORMAT_XRGB; - - pixman_region32_fini(); - } + if (!pixman_region32_not_empty()) + ret = true; - if (output->gbm_format == format) - return format; + pixman_region32_fini(); - return 0; + return ret; } static struct weston_plane * @@ -1463,7 +1459,6 @@ drm_output_prepare_scanout_view(struct drm_output_state *output_state, struct weston_buffer *buffer = ev->surface->buffer_ref.buffer; struct weston_buffer_viewport *viewport = >surface->buffer_viewport; struct gbm_bo *bo; - uint32_t format; /* Don't import buffers which span multiple outputs. */ if (ev->output_mask != (1u << output->base.id)) @@ -1507,17 +1502,20 @@ drm_output_prepare_scanout_view(struct drm_output_state *output_state, if (!bo) return NULL; - format =
[PATCH weston 36/68] compositor-drm: Use drm_plane for scanout plane
Use a real drm_plane to back the scanout plane, displacing output->fb_{last,cur,pending} to their plane-tracked equivalents. Signed-off-by: Daniel StoneDifferential Revision: https://phabricator.freedesktop.org/D1416 --- libweston/compositor-drm.c | 132 + 1 file changed, 87 insertions(+), 45 deletions(-) diff --git a/libweston/compositor-drm.c b/libweston/compositor-drm.c index 36468b9..e575429 100644 --- a/libweston/compositor-drm.c +++ b/libweston/compositor-drm.c @@ -315,8 +315,8 @@ struct drm_output { int current_cursor; /* Plane currently being directly displayed by KMS */ - struct weston_plane scanout_plane; - struct drm_fb *fb_current, *fb_pending, *fb_last; + struct drm_plane *scanout_plane; + struct backlight *backlight; struct drm_output_state *state_last; @@ -1242,6 +1242,8 @@ drm_output_assign_state(struct drm_output_state *state, if (plane->type == WDRM_PLANE_TYPE_OVERLAY) output->vblank_pending++; + else if (plane->type == WDRM_PLANE_TYPE_PRIMARY) + output->page_flip_pending = 1; } } @@ -1289,6 +1291,8 @@ drm_output_prepare_scanout_view(struct drm_output_state *output_state, { struct drm_output *output = output_state->output; struct drm_backend *b = to_drm_backend(output->base.compositor); + struct drm_plane *scanout_plane = output->scanout_plane; + struct drm_plane_state *state; struct weston_buffer *buffer = ev->surface->buffer_ref.buffer; struct weston_buffer_viewport *viewport = >surface->buffer_viewport; struct gbm_bo *bo; @@ -1342,15 +1346,29 @@ drm_output_prepare_scanout_view(struct drm_output_state *output_state, return NULL; } - output->fb_pending = drm_fb_get_from_bo(bo, b, format, BUFFER_CLIENT); - if (!output->fb_pending) { + state = drm_output_state_get_plane(output_state, scanout_plane); + state->fb = drm_fb_get_from_bo(bo, b, format, BUFFER_CLIENT); + if (!state->fb) { + drm_plane_state_put_back(state); gbm_bo_destroy(bo); return NULL; } - drm_fb_set_buffer(output->fb_pending, buffer); + drm_fb_set_buffer(state->fb, buffer); + + state->output = output; + + state->src_x = 0; + state->src_y = 0; + state->src_w = ev->surface->width << 16; + state->src_h = ev->surface->height << 16; - return >scanout_plane; + state->dest_x = 0; + state->dest_y = 0; + state->dest_w = output->base.width; + state->dest_h = output->base.height; + + return _plane->base; } static struct drm_fb * @@ -1411,12 +1429,15 @@ static void drm_output_render(struct drm_output *output, pixman_region32_t *damage) { struct weston_compositor *c = output->base.compositor; + struct drm_plane_state *scanout_state; struct drm_backend *b = to_drm_backend(c); struct drm_fb *fb; /* If we already have a client buffer promoted to scanout, then we don't * want to render. */ - if (output->fb_pending) + scanout_state = drm_output_state_get_plane(output->state_pending, + output->scanout_plane); + if (scanout_state->fb) return; if (b->use_pixman) @@ -1424,9 +1445,24 @@ drm_output_render(struct drm_output *output, pixman_region32_t *damage) else fb = drm_output_render_gl(output, damage); - if (!fb) + if (!fb) { + drm_plane_state_put_back(scanout_state); return; - output->fb_pending = fb; + } + + scanout_state->fb = fb; + scanout_state->output = output; + + scanout_state->src_x = 0; + scanout_state->src_y = 0; + scanout_state->src_w = output->base.current_mode->width << 16; + scanout_state->src_h = output->base.current_mode->height << 16; + + scanout_state->dest_x = 0; + scanout_state->dest_y = 0; + scanout_state->dest_w = scanout_state->src_w >> 16; + scanout_state->dest_h = scanout_state->src_h >> 16; + pixman_region32_subtract(>primary_plane.damage, >primary_plane.damage, damage); @@ -1486,6 +1522,8 @@ drm_output_repaint(struct weston_output *output_base, struct drm_output *output = to_drm_output(output_base); struct drm_backend *backend = to_drm_backend(output->base.compositor); + struct drm_plane *scanout_plane = output->scanout_plane; + struct drm_plane_state *scanout_state; struct drm_plane_state *ps; struct drm_plane *p; struct drm_mode *mode; @@ -1500,17 +1538,31 @@ drm_output_repaint(struct weston_output *output_base,
[PATCH weston 45/68] compositor-drm: Atomic modesetting support
Add support for using the atomic-modesetting API to apply output state. Unlike previous series, this commit does not unflip sprites_are_broken, until further work has been done with assign_planes to make it reliable. Differential Revision: https://phabricator.freedesktop.org/D1507 Signed-off-by: Daniel StoneCo-authored-by: Pekka Paalanen Co-authored-by: Louis-Francis Ratté-Boulianne Co-authored-by: Derek Foreman --- libweston/compositor-drm.c | 208 +++-- 1 file changed, 203 insertions(+), 5 deletions(-) diff --git a/libweston/compositor-drm.c b/libweston/compositor-drm.c index b33d519..2f9415c 100644 --- a/libweston/compositor-drm.c +++ b/libweston/compositor-drm.c @@ -349,6 +349,7 @@ struct drm_output { int vblank_pending; int page_flip_pending; + int atomic_complete_pending; int destroy_pending; int disable_pending; int dpms_off_pending; @@ -1376,6 +1377,7 @@ drm_output_assign_state(struct drm_output_state *state, enum drm_output_state_update_mode mode) { struct drm_output *output = state->output; + struct drm_backend *b = to_drm_backend(output->base.compositor); struct drm_plane_state *plane_state; assert(!output->state_last); @@ -1388,6 +1390,9 @@ drm_output_assign_state(struct drm_output_state *state, output->state_cur = state; output->state_pending = NULL; + if (b->atomic_modeset && mode == DRM_OUTPUT_STATE_UPDATE_ASYNCHRONOUS) + output->atomic_complete_pending = 1; + /* Replace state_cur on each affected plane with the new state, being * careful to dispose of orphaned (but only orphaned) previous state. * If the previous state is not orphaned (still has an output_state @@ -1399,7 +1404,8 @@ drm_output_assign_state(struct drm_output_state *state, drm_plane_state_free(plane->state_cur, true); plane->state_cur = plane_state; - if (mode != DRM_OUTPUT_STATE_UPDATE_ASYNCHRONOUS) + if (mode != DRM_OUTPUT_STATE_UPDATE_ASYNCHRONOUS || + b->atomic_modeset) continue; if (plane->type == WDRM_PLANE_TYPE_OVERLAY) @@ -1686,7 +1692,7 @@ drm_waitvblank_pipe(struct drm_output *output) } static int -drm_output_apply_state(struct drm_output_state *state) +drm_output_apply_state_legacy(struct drm_output_state *state) { struct drm_output *output = state->output; struct drm_backend *backend = to_drm_backend(output->base.compositor); @@ -1844,6 +1850,168 @@ err: return -1; } +#ifdef HAVE_DRM_ATOMIC +static int +crtc_add_prop(drmModeAtomicReq *req, struct drm_output *output, + enum wdrm_crtc_property prop, uint64_t val) +{ + struct property_item *item = >props_crtc.item[prop]; + int ret; + + if (!item) + return -1; + + ret = drmModeAtomicAddProperty(req, output->crtc_id, + item->drm_prop->prop_id, val); + return (ret <= 0) ? -1 : 0; +} + +static int +connector_add_prop(drmModeAtomicReq *req, struct drm_output *output, + enum wdrm_connector_property prop, uint64_t val) +{ + struct property_item *item = >props_conn.item[prop]; + int ret; + + if (!item) + return -1; + + ret = drmModeAtomicAddProperty(req, output->connector_id, + item->drm_prop->prop_id, val); + return (ret <= 0) ? -1 : 0; +} + +static int +plane_add_prop(drmModeAtomicReq *req, struct drm_plane *plane, + enum wdrm_plane_property prop, uint64_t val) +{ + struct property_item *item = >props.item[prop]; + int ret; + + if (!item) + return -1; + + ret = drmModeAtomicAddProperty(req, plane->plane_id, + item->drm_prop->prop_id, val); + return (ret <= 0) ? -1 : 0; +} + +static int +drm_mode_ensure_blob(struct drm_backend *backend, struct drm_mode *mode) +{ + int ret; + + if (mode->blob_id) + return 0; + + ret = drmModeCreatePropertyBlob(backend->drm.fd, + >mode_info, + sizeof(mode->mode_info), + >blob_id); + if (ret != 0) + weston_log("failed to create mode property blob: %m\n"); + + return ret; +} + +static int +drm_output_apply_state_atomic(struct drm_output_state *state) +{ + struct drm_output *output = state->output; + struct drm_backend *backend = to_drm_backend(output->base.compositor); + struct drm_plane_state *plane_state; + drmModeAtomicReq *req = drmModeAtomicAlloc(); + struct
[PATCH weston 48/68] compositor-drm: Only disallow scaling for overlay planes
Now we have a more comprehensive overview of the transform we're going to apply, use this to explicitly disallow scaling and rotation. XXX: This does not actually disallow rotation for square surfaces. We would have to build up a full buffer->view->output transform matrix, and then analyse that. Signed-off-by: Daniel StoneDifferential Revision: https://phabricator.freedesktop.org/D1517 --- libweston/compositor-drm.c | 27 --- 1 file changed, 12 insertions(+), 15 deletions(-) diff --git a/libweston/compositor-drm.c b/libweston/compositor-drm.c index b57e2ee..cd89083 100644 --- a/libweston/compositor-drm.c +++ b/libweston/compositor-drm.c @@ -2294,7 +2294,6 @@ drm_output_prepare_overlay_view(struct drm_output_state *output_state, { struct drm_output *output = output_state->output; struct weston_compositor *ec = output->base.compositor; - struct weston_buffer_viewport *viewport = >surface->buffer_viewport; struct drm_backend *b = to_drm_backend(ec); struct wl_resource *buffer_resource; struct drm_plane *p; @@ -2320,13 +2319,6 @@ drm_output_prepare_overlay_view(struct drm_output_state *output_state, if (wl_shm_buffer_get(buffer_resource)) return NULL; - if (viewport->buffer.transform != output->base.transform) - return NULL; - if (viewport->buffer.scale != output->base.current_scale) - return NULL; - if (!drm_view_transform_supported(ev)) - return NULL; - if (ev->alpha != 1.0f) return NULL; @@ -2355,6 +2347,12 @@ drm_output_prepare_overlay_view(struct drm_output_state *output_state, if (!state) return NULL; + state->output = output; + drm_plane_state_coords_for_view(state, ev); + if (state->src_w != state->dest_w << 16 || + state->src_h != state->dest_h << 16) + goto err; + if ((dmabuf = linux_dmabuf_buffer_get(buffer_resource))) { #ifdef HAVE_GBM_FD_IMPORT /* XXX: TODO: @@ -2373,7 +2371,7 @@ drm_output_prepare_overlay_view(struct drm_output_state *output_state, }; if (dmabuf->attributes.n_planes != 1 || dmabuf->attributes.offset[0] != 0) - return NULL; + goto err; bo = gbm_bo_import(b->gbm, GBM_BO_IMPORT_FD, _dmabuf, GBM_BO_USE_SCANOUT); @@ -2389,8 +2387,12 @@ drm_output_prepare_overlay_view(struct drm_output_state *output_state, state->fb = drm_fb_get_from_bo(bo, b, drm_view_is_opaque(ev), BUFFER_CLIENT); - if (!state->fb) + if (!state->fb) { + /* Destroy the BO as we've allocated it, but it won't yet +* be deallocated by the state. */ + gbm_bo_destroy(bo); goto err; + } /* Check whether the format is supported */ for (i = 0; i < p->count_formats; i++) @@ -2401,15 +2403,10 @@ drm_output_prepare_overlay_view(struct drm_output_state *output_state, drm_fb_set_buffer(state->fb, ev->surface->buffer_ref.buffer); - state->output = output; - drm_plane_state_coords_for_view(state, ev); - return >base; err: drm_plane_state_put_back(state); - if (bo) - gbm_bo_destroy(bo); return NULL; } -- 2.9.3 ___ wayland-devel mailing list wayland-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/wayland-devel
[PATCH weston 30/68] compositor-drm: Rename fb_plane to scanout_plane
All planes being displayed have a framebuffer. What makes 'fb_plane' special is that it's being displayed as the primary plane by KMS. Previous patchsets renamed this to 'primary_plane' to match the KMS terminology, namely the CRTC's base plane, which is controlled by drmModeSetCrtc in the legacy API, and identified by PLANE_TYPE == "Primary" in the universal-plane API. However, Weston uses 'primary_plane' internally to refer to the case where client content is _not_ directly displayed on a plane, but composited via the renderer, with the result of the compositing then shown. Rename to 'scanout_plane' as our least-ambiguous name, and document it a bit. Signed-off-by: Daniel StoneDifferential Revision: https://phabricator.freedesktop.org/D1415 --- libweston/compositor-drm.c | 11 ++- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/libweston/compositor-drm.c b/libweston/compositor-drm.c index 9a27f03..e4d6743 100644 --- a/libweston/compositor-drm.c +++ b/libweston/compositor-drm.c @@ -225,7 +225,8 @@ struct drm_output { struct weston_view *cursor_view; int current_cursor; - struct weston_plane fb_plane; + /* Plane currently being directly displayed by KMS */ + struct weston_plane scanout_plane; struct drm_fb *fb_current, *fb_pending, *fb_last; struct backlight *backlight; @@ -623,7 +624,7 @@ drm_output_prepare_scanout_view(struct drm_output *output, drm_fb_set_buffer(output->fb_pending, buffer); - return >fb_plane; + return >scanout_plane; } static struct drm_fb * @@ -2656,10 +2657,10 @@ drm_output_enable(struct weston_output *base) weston_plane_init(>cursor_plane, b->compositor, INT32_MIN, INT32_MIN); - weston_plane_init(>fb_plane, b->compositor, 0, 0); + weston_plane_init(>scanout_plane, b->compositor, 0, 0); weston_compositor_stack_plane(b->compositor, >cursor_plane, NULL); - weston_compositor_stack_plane(b->compositor, >fb_plane, + weston_compositor_stack_plane(b->compositor, >scanout_plane, >compositor->primary_plane); weston_log("Output %s, (connector %d, crtc %d)\n", @@ -2693,7 +2694,7 @@ drm_output_deinit(struct weston_output *base) else drm_output_fini_egl(output); - weston_plane_release(>fb_plane); + weston_plane_release(>scanout_plane); weston_plane_release(>cursor_plane); drmModeFreeProperty(output->dpms_prop); -- 2.9.3 ___ wayland-devel mailing list wayland-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/wayland-devel
[PATCH weston 51/68] compositor-drm: Extract overlay FB import to helper
... in order to be able to use it from scanout as well. Signed-off-by: Daniel StoneDifferential Revision: https://phabricator.freedesktop.org/D1520 --- libweston/compositor-drm.c | 200 - 1 file changed, 109 insertions(+), 91 deletions(-) diff --git a/libweston/compositor-drm.c b/libweston/compositor-drm.c index 1dc63c8..59a764d 100644 --- a/libweston/compositor-drm.c +++ b/libweston/compositor-drm.c @@ -1293,6 +1293,99 @@ drm_plane_state_coords_for_view(struct drm_plane_state *state, pixman_region32_fini(_rect); } +static bool +drm_view_is_opaque(struct weston_view *ev) +{ + pixman_region32_t r; + bool ret = false; + + /* We can scanout an ARGB buffer if the surface's +* opaque region covers the whole output, but we have +* to use XRGB as the KMS format code. */ + pixman_region32_init_rect(, 0, 0, + ev->surface->width, + ev->surface->height); + pixman_region32_subtract(, , >surface->opaque); + + if (!pixman_region32_not_empty()) + ret = true; + + pixman_region32_fini(); + + return ret; +} + +static struct drm_fb * +drm_fb_get_from_view(struct drm_output_state *state, struct weston_view *ev) +{ + struct drm_output *output = state->output; + struct drm_backend *b = to_drm_backend(output->base.compositor); + struct weston_buffer *buffer = ev->surface->buffer_ref.buffer; + struct linux_dmabuf_buffer *dmabuf; + struct drm_fb *fb; + struct gbm_bo *bo; + + /* Don't import buffers which span multiple outputs. */ + if (ev->output_mask != (1u << output->base.id)) + return NULL; + + if (ev->alpha != 1.0f) + return NULL; + + if (!buffer) + return NULL; + + if (wl_shm_buffer_get(buffer->resource)) + return NULL; + + if (!b->gbm) + return NULL; + + dmabuf = linux_dmabuf_buffer_get(buffer->resource); + if (dmabuf) { +#ifdef HAVE_GBM_FD_IMPORT + /* XXX: TODO: +* +* Use AddFB2 directly, do not go via GBM. +* Add support for multiplanar formats. +* Both require refactoring in the DRM-backend to +* support a mix of gbm_bos and drmfbs. +*/ +struct gbm_import_fd_data gbm_dmabuf = { +.fd = dmabuf->attributes.fd[0], +.width = dmabuf->attributes.width, +.height = dmabuf->attributes.height, +.stride = dmabuf->attributes.stride[0], +.format = dmabuf->attributes.format +}; + + if (dmabuf->attributes.n_planes != 1 || + dmabuf->attributes.offset[0]) + return NULL; + + bo = gbm_bo_import(b->gbm, GBM_BO_IMPORT_FD, _dmabuf, + GBM_BO_USE_SCANOUT); +#else + return NULL; +#endif + } else { + bo = gbm_bo_import(b->gbm, GBM_BO_IMPORT_WL_BUFFER, + buffer->resource, GBM_BO_USE_SCANOUT); + } + + if (!bo) + return NULL; + + fb = drm_fb_get_from_bo(bo, b, drm_view_is_opaque(ev), BUFFER_CLIENT); + if (!fb) { + gbm_bo_destroy(bo); + return NULL; + } + + drm_fb_set_buffer(fb, buffer); + return fb; +} + /** * Return a plane state from a drm_output_state. */ @@ -1505,28 +1598,6 @@ drm_output_assign_state(struct drm_output_state *state, } } -static bool -drm_view_is_opaque(struct weston_view *ev) -{ - pixman_region32_t r; - bool ret = false; - - /* We can scanout an ARGB buffer if the surface's -* opaque region covers the whole output, but we have -* to use XRGB as the KMS format code. */ - pixman_region32_init_rect(, 0, 0, - ev->surface->width, - ev->surface->height); - pixman_region32_subtract(, , >surface->opaque); - - if (!pixman_region32_not_empty()) - ret = true; - - pixman_region32_fini(); - - return ret; -} - static struct weston_plane * drm_output_prepare_scanout_view(struct drm_output_state *output_state, struct weston_view *ev) @@ -2275,31 +2346,16 @@ drm_output_prepare_overlay_view(struct drm_output_state *output_state, struct drm_output *output = output_state->output; struct weston_compositor *ec = output->base.compositor; struct drm_backend *b = to_drm_backend(ec); - struct wl_resource *buffer_resource; struct drm_plane *p; struct drm_plane_state *state = NULL; - struct linux_dmabuf_buffer *dmabuf; - struct gbm_bo
[PATCH weston 59/68] compositor-drm: Rename region variable
Make it a bit more clear what the purpose of the variable is. Signed-off-by: Daniel StoneDifferential Revision: https://phabricator.freedesktop.org/D1528 --- libweston/compositor-drm.c | 11 ++- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/libweston/compositor-drm.c b/libweston/compositor-drm.c index b7ebb2f..79f2941 100644 --- a/libweston/compositor-drm.c +++ b/libweston/compositor-drm.c @@ -2637,7 +2637,7 @@ drm_assign_planes(struct weston_output *output_base) struct drm_output_state *state; struct drm_plane_state *plane_state; struct weston_view *ev; - pixman_region32_t overlap, surface_overlap; + pixman_region32_t surface_overlap, renderer_region; struct weston_plane *primary, *next_plane; assert(!output->state_last); @@ -2658,7 +2658,7 @@ drm_assign_planes(struct weston_output *output_base) * the client buffer can be used directly for the sprite surface * as we do for flipping full screen surfaces. */ - pixman_region32_init(); + pixman_region32_init(_region); primary = _base->compositor->primary_plane; wl_list_for_each(ev, _base->compositor->view_list, link) { @@ -2682,7 +2682,7 @@ drm_assign_planes(struct weston_output *output_base) es->keep_buffer = false; pixman_region32_init(_overlap); - pixman_region32_intersect(_overlap, , + pixman_region32_intersect(_overlap, _region, >transform.boundingbox); next_plane = NULL; @@ -2700,7 +2700,8 @@ drm_assign_planes(struct weston_output *output_base) weston_view_move_to_plane(ev, next_plane); if (next_plane == primary) - pixman_region32_union(, , + pixman_region32_union(_region, + _region, >transform.boundingbox); if (next_plane == primary || @@ -2717,7 +2718,7 @@ drm_assign_planes(struct weston_output *output_base) pixman_region32_fini(_overlap); } - pixman_region32_fini(); + pixman_region32_fini(_region); /* We rely on ev->cursor_view being both an accurate reflection of the * cursor plane's state, but also being maintained across repaints to -- 2.9.3 ___ wayland-devel mailing list wayland-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/wayland-devel
[PATCH weston 54/68] compositor-drm: Extract drm_fb_addfb into a helper
We currently do the same thing in two places, and will soon have a third. Signed-off-by: Daniel StoneDifferential Revision: https://phabricator.freedesktop.org/D1523 --- libweston/compositor-drm.c | 63 +++--- 1 file changed, 31 insertions(+), 32 deletions(-) diff --git a/libweston/compositor-drm.c b/libweston/compositor-drm.c index 5fff646..72337a6 100644 --- a/libweston/compositor-drm.c +++ b/libweston/compositor-drm.c @@ -875,6 +875,33 @@ drm_fb_destroy_gbm(struct gbm_bo *bo, void *data) drm_fb_destroy(fb); } +static int +drm_fb_addfb(struct drm_fb *fb) +{ + uint32_t handles[4] = { 0 }, pitches[4] = { 0 }, offsets[4] = { 0 }; + int ret; + + handles[0] = fb->handle; + pitches[0] = fb->stride; + offsets[0] = 0; + + ret = drmModeAddFB2(fb->fd, fb->width, fb->height, + fb->format->format, handles, pitches, + offsets, >fb_id, 0); + if (ret == 0) + return 0; + + /* Legacy AddFB can't always infer the format from depth/bpp alone, so +* check if our format is one of the lucky ones. */ + if (!fb->format->depth || !fb->format->bpp) + return ret; + + ret = drmModeAddFB(fb->fd, fb->width, fb->height, + fb->format->depth, fb->format->bpp, + fb->stride, fb->handle, >fb_id); + return ret; +} + static struct drm_fb * drm_fb_create_dumb(struct drm_backend *b, int width, int height, uint32_t format) @@ -885,12 +912,10 @@ drm_fb_create_dumb(struct drm_backend *b, int width, int height, struct drm_mode_create_dumb create_arg; struct drm_mode_destroy_dumb destroy_arg; struct drm_mode_map_dumb map_arg; - uint32_t handles[4] = { 0 }, pitches[4] = { 0 }, offsets[4] = { 0 }; fb = zalloc(sizeof *fb); if (!fb) return NULL; - fb->refcnt = 1; fb->format = pixel_format_get_info(format); @@ -923,22 +948,10 @@ drm_fb_create_dumb(struct drm_backend *b, int width, int height, fb->height = height; fb->fd = b->drm.fd; - ret = -1; - - handles[0] = fb->handle; - pitches[0] = fb->stride; - offsets[0] = 0; - - ret = drmModeAddFB2(b->drm.fd, width, height, fb->format->format, - handles, pitches, offsets, >fb_id, 0); - if (ret) { - ret = drmModeAddFB(b->drm.fd, width, height, - fb->format->depth, fb->format->bpp, - fb->stride, fb->handle, >fb_id); - } - - if (ret) + if (drm_fb_addfb(fb) != 0) { + weston_log("failed to create kms fb: %m\n"); goto err_bo; + } memset(_arg, 0, sizeof map_arg); map_arg.handle = fb->handle; @@ -976,8 +989,6 @@ drm_fb_get_from_bo(struct gbm_bo *bo, struct drm_backend *backend, bool is_opaque, enum drm_fb_type type) { struct drm_fb *fb = gbm_bo_get_user_data(bo); - uint32_t handles[4] = { 0 }, pitches[4] = { 0 }, offsets[4] = { 0 }; - int ret; if (fb) return drm_fb_ref(fb); @@ -1015,19 +1026,7 @@ drm_fb_get_from_bo(struct gbm_bo *bo, struct drm_backend *backend, goto err_free; } - handles[0] = fb->handle; - pitches[0] = fb->stride; - offsets[0] = 0; - - ret = drmModeAddFB2(backend->drm.fd, fb->width, fb->height, - fb->format->format, handles, pitches, offsets, - >fb_id, 0); - if (ret && fb->format->depth && fb->format->bpp) - ret = drmModeAddFB(backend->drm.fd, fb->width, fb->height, - fb->format->depth, fb->format->bpp, - fb->stride, fb->handle, >fb_id); - - if (ret) { + if (drm_fb_addfb(fb) != 0) { weston_log("failed to create kms fb: %m\n"); goto err_free; } -- 2.9.3 ___ wayland-devel mailing list wayland-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/wayland-devel
[PATCH weston 63/68] compositor-drm: Add modes to drm_output_propose_state
Add support for multiple modes: toggling whether or not the renderer and/or planes are acceptable. This will be used to implement a smarter plane-placement heuristic when we have support for testing output states. Signed-off-by: Daniel StoneDifferential Revision: https://phabricator.freedesktop.org/D1532 --- libweston/compositor-drm.c | 37 +++-- 1 file changed, 31 insertions(+), 6 deletions(-) diff --git a/libweston/compositor-drm.c b/libweston/compositor-drm.c index 1eb1fbb..6b5c7cb 100644 --- a/libweston/compositor-drm.c +++ b/libweston/compositor-drm.c @@ -1657,6 +1657,11 @@ drm_output_assign_state(struct drm_output_state *state, } } +enum drm_output_propose_state_mode { + DRM_OUTPUT_PROPOSE_STATE_MIXED, /**< mix renderer & planes */ + DRM_OUTPUT_PROPOSE_STATE_PLANES_ONLY, /**< only assign to planes */ +}; + static struct weston_plane * drm_output_prepare_scanout_view(struct drm_output_state *output_state, struct weston_view *ev) @@ -2627,13 +2632,17 @@ err: } static struct drm_output_state * -drm_output_propose_state(struct weston_output *output_base) +drm_output_propose_state(struct weston_output *output_base, +enum drm_output_propose_state_mode mode) { struct drm_output *output = to_drm_output(output_base); + struct drm_backend *b = to_drm_backend(output_base->compositor); struct drm_output_state *state; struct weston_view *ev; pixman_region32_t surface_overlap, renderer_region, occluded_region; struct weston_plane *primary = _base->compositor->primary_plane; + bool renderer_ok = (mode != DRM_OUTPUT_PROPOSE_STATE_PLANES_ONLY); + bool planes_ok = !b->sprites_are_broken; assert(!output->state_last); assert(!output->state_pending); @@ -2643,6 +2652,7 @@ drm_output_propose_state(struct weston_output *output_base) /* * Find a surface for each sprite in the output using some heuristics: * 1) size + * 2) frequency of update * 3) opacity (though some hw might support alpha blending) * 4) clipping (this can be fixed with color keys) @@ -2695,24 +2705,38 @@ drm_output_propose_state(struct weston_output *output_base) _region, >transform.boundingbox); - if (next_plane == NULL) + /* The cursor plane is 'special' in the sense that we can still +* place it in the legacy API, and we gate that with a separate +* cursors_are_broken flag. */ + if (next_plane == NULL && !b->cursors_are_broken) next_plane = drm_output_prepare_cursor_view(state, ev); + if (!planes_ok) + next_plane = primary; + if (next_plane == NULL) next_plane = drm_output_prepare_scanout_view(state, ev); if (next_plane == NULL) next_plane = drm_output_prepare_overlay_view(state, ev); - if (next_plane == NULL) - next_plane = primary; - if (next_plane == primary) + if (!next_plane || next_plane == primary) { + if (!renderer_ok) + goto err; + pixman_region32_union(_region, _region, >transform.boundingbox); + } } pixman_region32_fini(_region); pixman_region32_fini(_region); return state; + +err: + pixman_region32_fini(_region); + pixman_region32_fini(_region); + drm_output_state_free(state); + return NULL; } static void @@ -2725,7 +2749,8 @@ drm_assign_planes(struct weston_output *output_base) struct weston_view *ev; struct weston_plane *primary = _base->compositor->primary_plane; - state = drm_output_propose_state(output_base); + state = drm_output_propose_state(output_base, +DRM_OUTPUT_PROPOSE_STATE_MIXED); wl_list_for_each(ev, _base->compositor->view_list, link) { struct drm_plane *target_plane = NULL; -- 2.9.3 ___ wayland-devel mailing list wayland-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/wayland-devel
[PATCH weston 24/68] compositor-drm: Return FB directly from render
Instead of setting state members directly in the drm_output_render functions (to paint using Pixman or GL), just return a drm_fb, and let the core function place it in state. Signed-off-by: Daniel StoneDifferential Revision: https://phabricator.freedesktop.org/D1419 --- libweston/compositor-drm.c | 30 +++--- 1 file changed, 19 insertions(+), 11 deletions(-) diff --git a/libweston/compositor-drm.c b/libweston/compositor-drm.c index 08634cd..5909239 100644 --- a/libweston/compositor-drm.c +++ b/libweston/compositor-drm.c @@ -615,11 +615,12 @@ drm_output_prepare_scanout_view(struct drm_output *output, return >fb_plane; } -static void +static struct drm_fb * drm_output_render_gl(struct drm_output *output, pixman_region32_t *damage) { struct drm_backend *b = to_drm_backend(output->base.compositor); struct gbm_bo *bo; + struct drm_fb *ret; output->base.compositor->renderer->repaint_output(>base, damage); @@ -627,20 +628,21 @@ drm_output_render_gl(struct drm_output *output, pixman_region32_t *damage) bo = gbm_surface_lock_front_buffer(output->gbm_surface); if (!bo) { weston_log("failed to lock front buffer: %m\n"); - return; + return NULL; } - output->fb_pending = drm_fb_get_from_bo(bo, b, output->gbm_format, - BUFFER_GBM_SURFACE); - if (!output->fb_pending) { + ret = drm_fb_get_from_bo(bo, b, output->gbm_format, BUFFER_GBM_SURFACE); + if (!ret) { weston_log("failed to get drm_fb for bo\n"); gbm_surface_release_buffer(output->gbm_surface, bo); - return; + return NULL; } - output->fb_pending->gbm_surface = output->gbm_surface; + ret->gbm_surface = output->gbm_surface; + + return ret; } -static void +static struct drm_fb * drm_output_render_pixman(struct drm_output *output, pixman_region32_t *damage) { struct weston_compositor *ec = output->base.compositor; @@ -656,7 +658,6 @@ drm_output_render_pixman(struct drm_output *output, pixman_region32_t *damage) output->current_image ^= 1; - output->fb_pending = drm_fb_ref(output->dumb[output->current_image]); pixman_renderer_output_set_buffer(>base, output->image[output->current_image]); @@ -664,6 +665,8 @@ drm_output_render_pixman(struct drm_output *output, pixman_region32_t *damage) pixman_region32_fini(_damage); pixman_region32_fini(_damage); + + return drm_fb_ref(output->dumb[output->current_image]); } static void @@ -671,6 +674,7 @@ drm_output_render(struct drm_output *output, pixman_region32_t *damage) { struct weston_compositor *c = output->base.compositor; struct drm_backend *b = to_drm_backend(c); + struct drm_fb *fb; /* If we already have a client buffer promoted to scanout, then we don't * want to render. */ @@ -678,9 +682,13 @@ drm_output_render(struct drm_output *output, pixman_region32_t *damage) return; if (b->use_pixman) - drm_output_render_pixman(output, damage); + fb = drm_output_render_pixman(output, damage); else - drm_output_render_gl(output, damage); + fb = drm_output_render_gl(output, damage); + + if (!fb) + return; + output->fb_pending = fb; pixman_region32_subtract(>primary_plane.damage, >primary_plane.damage, damage); -- 2.9.3 ___ wayland-devel mailing list wayland-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/wayland-devel
[PATCH weston 42/68] compositor-drm: Discover atomic properties
From: Pekka PaalanenSet the atomic client cap, where it exists, and use this to discover the plane/CRTC/connector properties we require for atomic modesetting. Differential Revision: https://phabricator.freedesktop.org/D1503 Signed-off-by: Daniel Stone Co-authored-by: Pekka Paalanen --- configure.ac | 3 + libweston/compositor-drm.c | 142 + 2 files changed, 145 insertions(+) diff --git a/configure.ac b/configure.ac index 7d5eaa1..8fe48b6 100644 --- a/configure.ac +++ b/configure.ac @@ -204,6 +204,9 @@ AM_CONDITIONAL(ENABLE_DRM_COMPOSITOR, test x$enable_drm_compositor = xyes) if test x$enable_drm_compositor = xyes; then AC_DEFINE([BUILD_DRM_COMPOSITOR], [1], [Build the DRM compositor]) PKG_CHECK_MODULES(DRM_COMPOSITOR, [libudev >= 136 libdrm >= 2.4.30 gbm mtdev >= 1.1.0]) + PKG_CHECK_MODULES(DRM_COMPOSITOR_ATOMIC, [libdrm >= 2.4.62], + [AC_DEFINE([HAVE_DRM_ATOMIC], 1, [libdrm supports atomic API])], + [AC_MSG_WARN([libdrm does not support atomic modesetting, will omit that capability])]) PKG_CHECK_MODULES(DRM_COMPOSITOR_GBM, [gbm >= 10.2], [AC_DEFINE([HAVE_GBM_FD_IMPORT], 1, [gbm supports dmabuf import])], [AC_MSG_WARN([gbm does not support dmabuf import, will omit that capability])]) diff --git a/libweston/compositor-drm.c b/libweston/compositor-drm.c index 2db48f1..7874c35 100644 --- a/libweston/compositor-drm.c +++ b/libweston/compositor-drm.c @@ -99,6 +99,16 @@ struct property_item { */ enum wdrm_plane_property { WDRM_PLANE_TYPE = 0, + WDRM_PLANE_SRC_X, + WDRM_PLANE_SRC_Y, + WDRM_PLANE_SRC_W, + WDRM_PLANE_SRC_H, + WDRM_PLANE_CRTC_X, + WDRM_PLANE_CRTC_Y, + WDRM_PLANE_CRTC_W, + WDRM_PLANE_CRTC_H, + WDRM_PLANE_FB_ID, + WDRM_PLANE_CRTC_ID, WDRM_PLANE__COUNT }; @@ -122,6 +132,37 @@ struct plane_properties { }; /** + * List of properties attached to DRM CRTCs + */ +enum wdrm_crtc_property { + WDRM_CRTC_MODE_ID = 0, + WDRM_CRTC_ACTIVE, + WDRM_CRTC__COUNT +}; + +/** + * List of properties attached to DRM connectors + */ +enum wdrm_connector_property { + WDRM_CONNECTOR_CRTC_ID = 0, + WDRM_CONNECTOR__COUNT +}; + +/** + * Holding structure for CRTC properties. + */ +struct crtc_properties { + struct property_item item[WDRM_CRTC__COUNT]; +}; + +/** + * Holding structure for CRTC properties. + */ +struct connector_properties { + struct property_item item[WDRM_CONNECTOR__COUNT]; +}; + +/** * Mode for drm_output_state_duplicate. */ enum drm_output_state_duplicate_mode { @@ -172,6 +213,7 @@ struct drm_backend { int cursors_are_broken; bool universal_planes; + bool atomic_modeset; int use_pixman; @@ -301,6 +343,9 @@ struct drm_output { drmModePropertyPtr dpms_prop; uint32_t gbm_format; + struct crtc_properties props_crtc; + struct connector_properties props_conn; + int vblank_pending; int page_flip_pending; int destroy_pending; @@ -591,6 +636,16 @@ plane_properties_init(struct drm_plane *plane) { static const char * const plane_property_names[] = { [WDRM_PLANE_TYPE] = "type", + [WDRM_PLANE_SRC_X] = "SRC_X", + [WDRM_PLANE_SRC_Y] = "SRC_Y", + [WDRM_PLANE_SRC_W] = "SRC_W", + [WDRM_PLANE_SRC_H] = "SRC_H", + [WDRM_PLANE_CRTC_X] = "CRTC_X", + [WDRM_PLANE_CRTC_Y] = "CRTC_Y", + [WDRM_PLANE_CRTC_W] = "CRTC_W", + [WDRM_PLANE_CRTC_H] = "CRTC_H", + [WDRM_PLANE_FB_ID] = "FB_ID", + [WDRM_PLANE_CRTC_ID] = "CRTC_ID", }; static const char * const plane_type_names[] = { [WDRM_PLANE_TYPE_PRIMARY] = "Primary", @@ -683,6 +738,84 @@ drm_plane_get_type(struct drm_plane *plane) return WDRM_PLANE_TYPE_OVERLAY; } +/** + * Initialise DRM properties for CRTC and connector + * + * Set up the holding structures to track DRM object properties set on the CRTC + * and connector associated with an output. + * Free the memory allocated here with output_properties_release. + * + * @param b DRM backend + * @param output Output to configure + */ +static bool output_properties_init(struct drm_backend *b, + struct drm_output *output) +{ + static const char * const crtc_property_names[] = { + [WDRM_CRTC_MODE_ID] = "MODE_ID", + [WDRM_CRTC_ACTIVE] = "ACTIVE", + }; + static const char * const connector_property_names[] = { + [WDRM_CONNECTOR_CRTC_ID] = "CRTC_ID", + }; + uint32_t valid_mask, required_mask; + + static_assert(ARRAY_LENGTH(crtc_property_names) == WDRM_CRTC__COUNT, +
[PATCH weston 55/68] compositor-drm: Support multi-planar drm_fb
Signed-off-by: Daniel StoneDifferential Revision: https://phabricator.freedesktop.org/D1524 --- libweston/compositor-drm.c | 45 - 1 file changed, 24 insertions(+), 21 deletions(-) diff --git a/libweston/compositor-drm.c b/libweston/compositor-drm.c index 72337a6..a2d4c8c 100644 --- a/libweston/compositor-drm.c +++ b/libweston/compositor-drm.c @@ -243,7 +243,10 @@ struct drm_fb { int refcnt; - uint32_t fb_id, stride, handle, size; + uint32_t fb_id, size; + uint32_t handles[4]; + uint32_t strides[4]; + uint32_t offsets[4]; const struct pixel_format_info *format; int width, height; int fd; @@ -859,7 +862,7 @@ drm_fb_destroy_dumb(struct drm_fb *fb) munmap(fb->map, fb->size); memset(_arg, 0, sizeof(destroy_arg)); - destroy_arg.handle = fb->handle; + destroy_arg.handle = fb->handles[0]; drmIoctl(fb->fd, DRM_IOCTL_MODE_DESTROY_DUMB, _arg); drm_fb_destroy(fb); @@ -878,16 +881,11 @@ drm_fb_destroy_gbm(struct gbm_bo *bo, void *data) static int drm_fb_addfb(struct drm_fb *fb) { - uint32_t handles[4] = { 0 }, pitches[4] = { 0 }, offsets[4] = { 0 }; int ret; - handles[0] = fb->handle; - pitches[0] = fb->stride; - offsets[0] = 0; - - ret = drmModeAddFB2(fb->fd, fb->width, fb->height, - fb->format->format, handles, pitches, - offsets, >fb_id, 0); + ret = drmModeAddFB2(fb->fd, fb->width, fb->height, fb->format->format, + fb->handles, fb->strides, fb->offsets, >fb_id, + 0); if (ret == 0) return 0; @@ -896,9 +894,13 @@ drm_fb_addfb(struct drm_fb *fb) if (!fb->format->depth || !fb->format->bpp) return ret; + /* Cannot fall back to AddFB for multi-planar formats either. */ + if (fb->handles[1] || fb->handles[2] || fb->handles[3]) + return ret; + ret = drmModeAddFB(fb->fd, fb->width, fb->height, fb->format->depth, fb->format->bpp, - fb->stride, fb->handle, >fb_id); + fb->strides[0], fb->handles[0], >fb_id); return ret; } @@ -941,8 +943,8 @@ drm_fb_create_dumb(struct drm_backend *b, int width, int height, goto err_fb; fb->type = BUFFER_PIXMAN_DUMB; - fb->handle = create_arg.handle; - fb->stride = create_arg.pitch; + fb->handles[0] = create_arg.handle; + fb->strides[0] = create_arg.pitch; fb->size = create_arg.size; fb->width = width; fb->height = height; @@ -954,7 +956,7 @@ drm_fb_create_dumb(struct drm_backend *b, int width, int height, } memset(_arg, 0, sizeof map_arg); - map_arg.handle = fb->handle; + map_arg.handle = fb->handles[0]; ret = drmIoctl(fb->fd, DRM_IOCTL_MODE_MAP_DUMB, _arg); if (ret) goto err_add_fb; @@ -1003,10 +1005,10 @@ drm_fb_get_from_bo(struct gbm_bo *bo, struct drm_backend *backend, fb->width = gbm_bo_get_width(bo); fb->height = gbm_bo_get_height(bo); - fb->stride = gbm_bo_get_stride(bo); - fb->handle = gbm_bo_get_handle(bo).u32; + fb->strides[0] = gbm_bo_get_stride(bo); + fb->handles[0] = gbm_bo_get_handle(bo).u32; fb->format = pixel_format_get_info(gbm_bo_get_format(bo)); - fb->size = fb->stride * fb->height; + fb->size = fb->strides[0] * fb->height; fb->fd = backend->drm.fd; if (!fb->format) { @@ -1836,7 +1838,8 @@ drm_output_apply_state_legacy(struct drm_output_state *state) mode = to_drm_mode(output->base.current_mode); if (!scanout_plane->state_cur->fb || - scanout_plane->state_cur->fb->stride != scanout_state->fb->stride) { + scanout_plane->state_cur->fb->strides[0] != + scanout_state->fb->strides[0]) { ret = drmModeSetCrtc(backend->drm.fd, output->crtc_id, scanout_state->fb->fb_id, 0, 0, @@ -3515,7 +3518,7 @@ drm_output_init_pixman(struct drm_output *output, struct drm_backend *b) output->image[i] = pixman_image_create_bits(pixman_format, w, h, output->dumb[i]->map, -output->dumb[i]->stride); +output->dumb[i]->strides[0]); if (!output->image[i]) goto err; } @@ -4539,7 +4542,7 @@ recorder_frame_notify(struct wl_listener *listener, void *data) return; ret = drmPrimeHandleToFD(b->drm.fd, -output->scanout_plane->state_cur->fb->handle, +
[PATCH weston 47/68] compositor-drm: Extract buffer->plane co-ord translation
Pull this into a helper function, so we can use it everywhere. Signed-off-by: Daniel StoneDifferential Revision: https://phabricator.freedesktop.org/D1516 --- libweston/compositor-drm.c | 157 + 1 file changed, 88 insertions(+), 69 deletions(-) diff --git a/libweston/compositor-drm.c b/libweston/compositor-drm.c index 893fdbd..b57e2ee 100644 --- a/libweston/compositor-drm.c +++ b/libweston/compositor-drm.c @@ -1208,6 +1208,92 @@ drm_plane_state_put_back(struct drm_plane_state *state) } /** + * Given a weston_view, fill the drm_plane_state's co-ordinates to display on + * a given plane. + */ +static void +drm_plane_state_coords_for_view(struct drm_plane_state *state, + struct weston_view *ev) +{ + struct drm_output *output = state->output; + struct weston_buffer_viewport *viewport = >surface->buffer_viewport; + pixman_region32_t dest_rect, src_rect; + pixman_box32_t *box, tbox; + wl_fixed_t sx1, sy1, sx2, sy2; + + /* Update the base weston_plane co-ordinates. */ + box = pixman_region32_extents(>transform.boundingbox); + state->plane->base.x = box->x1; + state->plane->base.y = box->y1; + + /* First calculate the destination co-ordinates by taking the +* area of the view which is visible on this output, performing any +* transforms to account for output rotation and scale as necessary. */ + pixman_region32_init(_rect); + pixman_region32_intersect(_rect, >transform.boundingbox, + >base.region); + pixman_region32_translate(_rect, -output->base.x, -output->base.y); + box = pixman_region32_extents(_rect); + tbox = weston_transformed_rect(output->base.width, + output->base.height, + output->base.transform, + output->base.current_scale, + *box); + state->dest_x = tbox.x1; + state->dest_y = tbox.y1; + state->dest_w = tbox.x2 - tbox.x1; + state->dest_h = tbox.y2 - tbox.y1; + pixman_region32_fini(_rect); + + /* Now calculate the source rectangle, by finding the points in the +* view and working backwards to source co-ordinates. */ + pixman_region32_init(_rect); + pixman_region32_intersect(_rect, >transform.boundingbox, + >base.region); + box = pixman_region32_extents(_rect); + + /* Accounting for any transformations made to this particular surface +* view, find the source rectangle to use. */ + weston_view_from_global_fixed(ev, + wl_fixed_from_int(box->x1), + wl_fixed_from_int(box->y1), + , ); + weston_view_from_global_fixed(ev, + wl_fixed_from_int(box->x2), + wl_fixed_from_int(box->y2), + , ); + + /* XXX: How is this possible ... ? */ + if (sx1 < 0) + sx1 = 0; + if (sy1 < 0) + sy1 = 0; + if (sx2 > wl_fixed_from_int(ev->surface->width)) + sx2 = wl_fixed_from_int(ev->surface->width); + if (sy2 > wl_fixed_from_int(ev->surface->height)) + sy2 = wl_fixed_from_int(ev->surface->height); + + tbox.x1 = sx1; + tbox.y1 = sy1; + tbox.x2 = sx2; + tbox.y2 = sy2; + + /* Apply viewport transforms in reverse, to get the source co-ordinates +* in buffer space. */ + tbox = weston_transformed_rect(wl_fixed_from_int(ev->surface->width), + wl_fixed_from_int(ev->surface->height), + viewport->buffer.transform, + viewport->buffer.scale, + tbox); + + state->src_x = tbox.x1 << 8; + state->src_y = tbox.y1 << 8; + state->src_w = (tbox.x2 - tbox.x1) << 8; + state->src_h = (tbox.y2 - tbox.y1) << 8; + pixman_region32_fini(_rect); +} + +/** * Return a plane state from a drm_output_state. */ static struct drm_plane_state * @@ -2208,16 +2294,13 @@ drm_output_prepare_overlay_view(struct drm_output_state *output_state, { struct drm_output *output = output_state->output; struct weston_compositor *ec = output->base.compositor; - struct drm_backend *b = to_drm_backend(ec); struct weston_buffer_viewport *viewport = >surface->buffer_viewport; + struct drm_backend *b = to_drm_backend(ec); struct wl_resource *buffer_resource; struct drm_plane *p; struct drm_plane_state *state = NULL; struct linux_dmabuf_buffer *dmabuf; struct gbm_bo *bo; -
[PATCH weston 19/68] compositor-drm: Refcount drm_fb
Sometimes we need to duplicate an existing drm_fb, e.g. when pageflipping to the same buffer to kickstart the repaint loop. To handle situations like these, and simplify resource management for dumb and cursor buffers, refcount drm_fb. Differential Revision: https://phabricator.freedesktop.org/D1491 Signed-off-by: Daniel Stone--- libweston/compositor-drm.c | 19 ++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/libweston/compositor-drm.c b/libweston/compositor-drm.c index eb735b2..a684ac9 100644 --- a/libweston/compositor-drm.c +++ b/libweston/compositor-drm.c @@ -140,6 +140,8 @@ enum drm_fb_type { struct drm_fb { enum drm_fb_type type; + int refcnt; + uint32_t fb_id, stride, handle, size; const struct pixel_format_info *format; int width, height; @@ -302,6 +304,8 @@ drm_fb_create_dumb(struct drm_backend *b, int width, int height, if (!fb) return NULL; + fb->refcnt = 1; + fb->format = pixel_format_get_info(format); if (!fb->format) { weston_log("failed to look up format 0x%lx\n", @@ -312,6 +316,7 @@ drm_fb_create_dumb(struct drm_backend *b, int width, int height, if (!fb->format->depth || !fb->format->bpp) { weston_log("format 0x%lx is not compatible with dumb buffers\n", (unsigned long) format); + goto err_fb; } memset(_arg, 0, sizeof create_arg); @@ -384,6 +389,13 @@ err_fb: } static struct drm_fb * +drm_fb_ref(struct drm_fb *fb) +{ + fb->refcnt++; + return fb; +} + +static struct drm_fb * drm_fb_get_from_bo(struct gbm_bo *bo, struct drm_backend *backend, uint32_t format, enum drm_fb_type type) { @@ -392,13 +404,14 @@ drm_fb_get_from_bo(struct gbm_bo *bo, struct drm_backend *backend, int ret; if (fb) - return fb; + return drm_fb_ref(fb); fb = zalloc(sizeof *fb); if (fb == NULL) return NULL; fb->type = type; + fb->refcnt = 1; fb->bo = bo; fb->width = gbm_bo_get_width(bo); @@ -472,6 +485,10 @@ drm_fb_unref(struct drm_fb *fb) if (!fb) return; + assert(fb->refcnt > 0); + if (--fb->refcnt > 0) + return; + switch (fb->type) { case BUFFER_PIXMAN_DUMB: /* nothing: pixman buffers are destroyed manually */ -- 2.9.3 ___ wayland-devel mailing list wayland-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/wayland-devel
[PATCH weston 29/68] compositor-drm: Refactor sprite create/destroy into helpers
From: Pekka PaalanenThis moves the single sprite creation code from create_sprites() into a new function. The readability clean-up is small, but my intention is to write an alternate version of create_sprites(), and sharing the single sprite creation code is useful. [daniels: Genericised from drm_sprite to drm_plane, moving some of the logic back into create_sprites(), also symmetrical drm_plane_destroy.] Signed-off-by: Pekka Paalanen Signed-off-by: Daniel Stone Differential Revision: https://phabricator.freedesktop.org/D1409 --- libweston/compositor-drm.c | 188 - 1 file changed, 117 insertions(+), 71 deletions(-) diff --git a/libweston/compositor-drm.c b/libweston/compositor-drm.c index 1b123b5..9a27f03 100644 --- a/libweston/compositor-drm.c +++ b/libweston/compositor-drm.c @@ -1703,6 +1703,123 @@ init_pixman(struct drm_backend *b) } /** + * Create a drm_plane for a hardware plane + * + * Creates one drm_plane structure for a hardware plane, and initialises its + * properties and formats. + * + * This function does not add the plane to the list of usable planes in Weston + * itself; the caller is responsible for this. + * + * Call drm_plane_destroy to clean up the plane. + * + * @param ec Compositor to create plane for + * @param kplane DRM plane to create + */ +static struct drm_plane * +drm_plane_create(struct drm_backend *b, const drmModePlane *kplane) +{ + struct drm_plane *plane; + + plane = zalloc(sizeof(*plane) + ((sizeof(uint32_t)) * + kplane->count_formats)); + if (!plane) { + weston_log("%s: out of memory\n", __func__); + return NULL; + } + + plane->backend = b; + plane->possible_crtcs = kplane->possible_crtcs; + plane->plane_id = kplane->plane_id; + plane->count_formats = kplane->count_formats; + memcpy(plane->formats, kplane->formats, + kplane->count_formats * sizeof(kplane->formats[0])); + + weston_plane_init(>base, b->compositor, 0, 0); + wl_list_insert(>sprite_list, >link); + + return plane; +} + +/** + * Destroy one DRM plane + * + * Destroy a DRM plane, removing it from screen and releasing its retained + * buffers in the process. The counterpart to drm_plane_create. + * + * @param plane Plane to deallocate (will be freed) + */ +static void +drm_plane_destroy(struct drm_plane *plane) +{ + drmModeSetPlane(plane->backend->drm.fd, plane->plane_id, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0); + drm_fb_unref(plane->fb_last); + drm_fb_unref(plane->fb_current); + assert(!plane->fb_pending); + weston_plane_release(>base); + wl_list_remove(>link); + free(plane); +} + +/** + * Initialise sprites (overlay planes) + * + * Walk the list of provided DRM planes, and add overlay planes. + * + * Call destroy_sprites to free these planes. + * + * @param ec Compositor to create sprites for. + */ +static void +create_sprites(struct drm_backend *b) +{ + drmModePlaneRes *kplane_res; + drmModePlane *kplane; + struct drm_plane *drm_plane; + uint32_t i; + + kplane_res = drmModeGetPlaneResources(b->drm.fd); + if (!kplane_res) { + weston_log("failed to get plane resources: %s\n", + strerror(errno)); + return; + } + + for (i = 0; i < kplane_res->count_planes; i++) { + kplane = drmModeGetPlane(b->drm.fd, kplane_res->planes[i]); + if (!kplane) + continue; + + drm_plane = drm_plane_create(b, kplane); + drmModeFreePlane(kplane); + if (!drm_plane) + continue; + + weston_compositor_stack_plane(b->compositor, _plane->base, + >compositor->primary_plane); + } + + drmModeFreePlaneResources(kplane_res); +} + +/** + * Clean up sprites (overlay planes) + * + * The counterpart to create_sprites. + * + * @param compositor Compositor to deallocate sprites for. + */ +static void +destroy_sprites(struct drm_backend *backend) +{ + struct drm_plane *plane, *next; + + wl_list_for_each_safe(plane, next, >sprite_list, link) + drm_plane_destroy(plane); +} + +/** * Add a mode to output's mode list * * Copy the supplied DRM mode into a Weston mode structure, and add it to the @@ -2703,77 +2820,6 @@ create_output_for_connector(struct drm_backend *b, return 0; } -static void -create_sprites(struct drm_backend *b) -{ - struct drm_plane *plane; - drmModePlaneRes *kplane_res; - drmModePlane *kplane; - uint32_t i; - - kplane_res = drmModeGetPlaneResources(b->drm.fd); - if (!kplane_res) { - weston_log("failed to
[PATCH weston 33/68] compositor-drm: Introduce drm_output_state structure
Currently this doesn't actually really do anything, but will be used in the future to track the state for both modeset and repaint requests. Completion of the request gives us a single request-completion path for both pageflip and vblank events. Differential Revision: https://phabricator.freedesktop.org/D1497 Signed-off-by: Daniel Stone--- libweston/compositor-drm.c | 229 ++--- 1 file changed, 196 insertions(+), 33 deletions(-) diff --git a/libweston/compositor-drm.c b/libweston/compositor-drm.c index 3dd2924..106d851 100644 --- a/libweston/compositor-drm.c +++ b/libweston/compositor-drm.c @@ -121,6 +121,19 @@ struct plane_properties { uint64_t value; }; +/** + * Mode for drm_output_state_duplicate. + */ +enum drm_output_state_duplicate_mode { + DRM_OUTPUT_STATE_CLEAR_PLANES, /**< reset all planes to off */ + DRM_OUTPUT_STATE_PRESERVE_PLANES, /**< preserve plane state */ +}; + +enum drm_output_state_update_mode { + DRM_OUTPUT_STATE_UPDATE_SYNCHRONOUS, /**< state already applied */ + DRM_OUTPUT_STATE_UPDATE_ASYNCHRONOUS, /**< pending event delivery */ +}; + struct drm_backend { struct weston_backend base; struct weston_compositor *compositor; @@ -210,6 +223,16 @@ struct drm_edid { }; /** + * Output state holds the dynamic state for one Weston output, i.e. a KMS CRTC, + * plus >= 1 each of encoder/connector/plane. Since everything but the planes + * is currently statically assigned per-output, we mainly use this to track + * plane state. + */ +struct drm_output_state { + struct drm_output *output; +}; + +/** * A plane represents one buffer, positioned within a CRTC, and stacked * relative to other planes on the same CRTC. * @@ -278,6 +301,10 @@ struct drm_output { struct drm_fb *fb_current, *fb_pending, *fb_last; struct backlight *backlight; + struct drm_output_state *state_last; + struct drm_output_state *state_cur; + struct drm_output_state *state_pending; + struct drm_fb *dumb[2]; pixman_image_t *image[2]; int current_image; @@ -645,6 +672,9 @@ drm_output_set_cursor(struct drm_output *output); static void drm_output_update_msc(struct drm_output *output, unsigned int seq); +static void +drm_output_destroy(struct weston_output *output_base); + static int drm_plane_crtc_supported(struct drm_output *output, struct drm_plane *plane) { @@ -905,6 +935,112 @@ drm_fb_unref(struct drm_fb *fb) } } +/** + * Allocate a new, empty drm_output_state. This should not generally be used + * in the repaint cycle; see drm_output_state_duplicate. + */ +static struct drm_output_state * +drm_output_state_alloc(struct drm_output *output) +{ + struct drm_output_state *state = calloc(1, sizeof(*state)); + + state->output = output; + + return state; +} + +/** + * Duplicate an existing drm_output_state into a new one. This is generally + * used during the repaint cycle, to capture the existing state of an output + * and modify it to create a new state to be used. + * + * The mode determines whether the output will be reset to an a blank state, + * or an exact mirror of the current state. + */ +static struct drm_output_state * +drm_output_state_duplicate(struct drm_output_state *src, + enum drm_output_state_duplicate_mode plane_mode) +{ + struct drm_output_state *dst = malloc(sizeof(*dst)); + + assert(dst); + memcpy(dst, src, sizeof(*dst)); + + return dst; +} + +/** + * Free an unused drm_output_state. + */ +static void +drm_output_state_free(struct drm_output_state *state) +{ + if (!state) + return; + + free(state); +} + +/** + * Mark a drm_output_state (the output's last state) as complete. This handles + * any post-completion actions such as updating the repaint timer, disabling the + * output, and finally freeing the state. + */ +static void +drm_output_update_complete(struct drm_output *output, uint32_t flags, + unsigned int sec, unsigned int usec) +{ + struct timespec ts; + + drm_output_state_free(output->state_last); + output->state_last = NULL; + + if (output->destroy_pending) { + drm_output_destroy(>base); + goto out; + } else if (output->disable_pending) { + weston_output_disable(>base); + goto out; + } + + ts.tv_sec = sec; + ts.tv_nsec = usec * 1000; + weston_output_finish_frame(>base, , flags); + + /* We can't call this from frame_notify, because the output's +* repaint needed flag is cleared just after that */ + if (output->recorder) + weston_output_schedule_repaint(>base); + +out: + output->destroy_pending = 0; + output->disable_pending = 0; +} + +/** + * Mark an output state as current on the output, i.e. it has been + * submitted to the
[PATCH weston 38/68] compositor-drm: Split repaint into helper
We can separate repainting into two phases: one performing the actual repaint (essentially drm_output_render) and populating the plane state that wasn't already populated by drm_output_assign_planes, and another applying this state to the device. Differential Revision: https://phabricator.freedesktop.org/D1500 Signed-off-by: Daniel Stone--- libweston/compositor-drm.c | 58 +- 1 file changed, 37 insertions(+), 21 deletions(-) diff --git a/libweston/compositor-drm.c b/libweston/compositor-drm.c index f0a13e1..f1f9bcb 100644 --- a/libweston/compositor-drm.c +++ b/libweston/compositor-drm.c @@ -1527,12 +1527,10 @@ drm_waitvblank_pipe(struct drm_output *output) } static int -drm_output_repaint(struct weston_output *output_base, - pixman_region32_t *damage) +drm_output_apply_state(struct drm_output_state *state) { - struct drm_output *output = to_drm_output(output_base); - struct drm_backend *backend = - to_drm_backend(output->base.compositor); + struct drm_output *output = state->output; + struct drm_backend *backend = to_drm_backend(output->base.compositor); struct drm_plane *scanout_plane = output->scanout_plane; struct drm_plane_state *scanout_state; struct drm_plane_state *ps; @@ -1540,20 +1538,7 @@ drm_output_repaint(struct weston_output *output_base, struct drm_mode *mode; int ret = 0; - if (output->disable_pending || output->destroy_pending) - goto err; - - assert(!output->state_last); - if (!output->state_pending) - output->state_pending = - drm_output_state_duplicate(output->state_cur, - DRM_OUTPUT_STATE_CLEAR_PLANES); - - drm_output_render(output, damage); - scanout_state = drm_output_state_get_plane(output->state_pending, - scanout_plane); - if (!scanout_state || !scanout_state->fb) - goto err; + scanout_state = drm_output_state_get_plane(state, scanout_plane); /* The legacy SetCrtc API doesn't allow us to do scaling, and the * legacy PageFlip API doesn't allow us to do clipping either. */ @@ -1580,7 +1565,7 @@ drm_output_repaint(struct weston_output *output_base, weston_log("set mode failed: %m\n"); goto err; } - output_base->set_dpms(output_base, WESTON_DPMS_ON); + output->base.set_dpms(>base, WESTON_DPMS_ON); } if (drmModePageFlip(backend->drm.fd, output->crtc_id, @@ -1592,7 +1577,7 @@ drm_output_repaint(struct weston_output *output_base, assert(!output->page_flip_pending); - drm_output_set_cursor(output->state_pending); + drm_output_set_cursor(state); /* * Now, update all the sprite surfaces @@ -1655,6 +1640,37 @@ err: return -1; } +static int +drm_output_repaint(struct weston_output *output_base, + pixman_region32_t *damage) +{ + struct drm_output *output = to_drm_output(output_base); + struct drm_plane_state *scanout_state; + + if (output->disable_pending || output->destroy_pending) + goto err; + + assert(!output->state_last); + if (!output->state_pending) + output->state_pending = + drm_output_state_duplicate(output->state_cur, + DRM_OUTPUT_STATE_CLEAR_PLANES); + + drm_output_render(output, damage); + scanout_state = drm_output_state_get_plane(output->state_pending, + output->scanout_plane); + if (!scanout_state || !scanout_state->fb) + goto err; + + return drm_output_apply_state(output->state_pending); + +err: + drm_output_state_free(output->state_pending); + output->state_pending = NULL; + return -1; +} + + static void drm_output_start_repaint_loop(struct weston_output *output_base) { -- 2.9.3 ___ wayland-devel mailing list wayland-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/wayland-devel
[PATCH weston 39/68] compositor-drm: Move DPMS into output state
Extend drm_output_state to also cover DPMS, so we can use it to enable and disable outputs, and always keep a coherent state. Differential Revision: https://phabricator.freedesktop.org/D1501 Signed-off-by: Daniel Stone--- libweston/compositor-drm.c | 139 + 1 file changed, 114 insertions(+), 25 deletions(-) diff --git a/libweston/compositor-drm.c b/libweston/compositor-drm.c index f1f9bcb..ec8db31 100644 --- a/libweston/compositor-drm.c +++ b/libweston/compositor-drm.c @@ -231,6 +231,7 @@ struct drm_edid { struct drm_output_state { struct drm_output *output; + enum dpms_enum dpms; struct wl_list plane_list; }; @@ -301,12 +302,11 @@ struct drm_output { drmModePropertyPtr dpms_prop; uint32_t gbm_format; - enum dpms_enum dpms; - int vblank_pending; int page_flip_pending; int destroy_pending; int disable_pending; + int dpms_off_pending; struct gbm_surface *gbm_surface; struct drm_fb *gbm_cursor_fb[2]; @@ -1107,6 +1107,7 @@ drm_output_state_alloc(struct drm_output *output) struct drm_output_state *state = calloc(1, sizeof(*state)); state->output = output; + state->dpms = WESTON_DPMS_OFF; wl_list_init(>plane_list); return state; @@ -1163,6 +1164,23 @@ drm_output_state_free(struct drm_output_state *state) free(state); } +static struct drm_output_state * +drm_output_get_disable_state(struct drm_output *output) +{ + struct drm_output_state *state; + + if (!output->state_cur) + state = drm_output_state_alloc(output); + else + state = drm_output_state_duplicate(output->state_cur, + DRM_OUTPUT_STATE_CLEAR_PLANES); + state->dpms = WESTON_DPMS_OFF; + + return state; +} + +static int drm_output_apply_state(struct drm_output_state *state); + /** * Mark a drm_output_state (the output's last state) as complete. This handles * any post-completion actions such as updating the repaint timer, disabling the @@ -1173,6 +1191,7 @@ drm_output_update_complete(struct drm_output *output, uint32_t flags, unsigned int sec, unsigned int usec) { struct drm_plane_state *ps; + struct drm_output_state *os; struct timespec ts; wl_list_for_each(ps, >state_cur->plane_list, link) @@ -1187,6 +1206,9 @@ drm_output_update_complete(struct drm_output *output, uint32_t flags, } else if (output->disable_pending) { weston_output_disable(>base); goto out; + } else if (output->dpms_off_pending) { + os = drm_output_get_disable_state(output); + drm_output_apply_state(os); } ts.tv_sec = sec; @@ -1201,6 +1223,7 @@ drm_output_update_complete(struct drm_output *output, uint32_t flags, out: output->destroy_pending = 0; output->disable_pending = 0; + output->dpms_off_pending = 0; } /** @@ -1247,7 +1270,6 @@ drm_output_assign_state(struct drm_output_state *state, } } - static int drm_view_transform_supported(struct weston_view *ev) { @@ -1538,7 +1560,41 @@ drm_output_apply_state(struct drm_output_state *state) struct drm_mode *mode; int ret = 0; - scanout_state = drm_output_state_get_plane(state, scanout_plane); + if (state->dpms != WESTON_DPMS_ON) { + wl_list_for_each(ps, >plane_list, link) { + p = ps->plane; + assert(ps->fb == NULL); + assert(ps->output == NULL); + + if (p->type != WDRM_PLANE_TYPE_OVERLAY) + continue; + + ret = drmModeSetPlane(backend->drm.fd, p->plane_id, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); + if (ret) + weston_log("drmModeSetPlane failed disable: %m\n"); + } + + if (output->cursor_plane) { + ret = drmModeSetCursor(backend->drm.fd, output->crtc_id, + 0, 0, 0); + if (ret) + weston_log("drmModeSetCursor failed disable: %m\n"); + } + + ret = drmModeSetCrtc(backend->drm.fd, output->crtc_id, 0, 0, 0, +>connector_id, 0, NULL); + if (ret) + weston_log("drmModeSetCrtc failed disabling: %m\n"); + + drm_output_assign_state(state, + DRM_OUTPUT_STATE_UPDATE_SYNCHRONOUS); + + return 0; + } + + scanout_state = + drm_output_state_get_existing_plane(state, scanout_plane); /* The legacy SetCrtc API doesn't
[PATCH weston 20/68] compositor-drm: Use refcounted FBs for Pixman
When using the Pixman renderer, use drm_fb refcounting explicitly. Differential Revision: https://phabricator.freedesktop.org/D1492 Signed-off-by: Daniel Stone--- libweston/compositor-drm.c | 8 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/libweston/compositor-drm.c b/libweston/compositor-drm.c index a684ac9..950c265 100644 --- a/libweston/compositor-drm.c +++ b/libweston/compositor-drm.c @@ -491,7 +491,7 @@ drm_fb_unref(struct drm_fb *fb) switch (fb->type) { case BUFFER_PIXMAN_DUMB: - /* nothing: pixman buffers are destroyed manually */ + drm_fb_destroy_dumb(fb); break; case BUFFER_CLIENT: gbm_bo_destroy(fb->bo); @@ -652,7 +652,7 @@ drm_output_render_pixman(struct drm_output *output, pixman_region32_t *damage) output->current_image ^= 1; - output->next = output->dumb[output->current_image]; + output->next = drm_fb_ref(output->dumb[output->current_image]); pixman_renderer_output_set_buffer(>base, output->image[output->current_image]); @@ -1973,7 +1973,7 @@ drm_output_init_pixman(struct drm_output *output, struct drm_backend *b) err: for (i = 0; i < ARRAY_LENGTH(output->dumb); i++) { if (output->dumb[i]) - drm_fb_destroy_dumb(output->dumb[i]); + drm_fb_unref(output->dumb[i]); if (output->image[i]) pixman_image_unref(output->image[i]); @@ -1993,8 +1993,8 @@ drm_output_fini_pixman(struct drm_output *output) pixman_region32_fini(>previous_damage); for (i = 0; i < ARRAY_LENGTH(output->dumb); i++) { - drm_fb_destroy_dumb(output->dumb[i]); pixman_image_unref(output->image[i]); + drm_fb_unref(output->dumb[i]); output->dumb[i] = NULL; output->image[i] = NULL; } -- 2.9.3 ___ wayland-devel mailing list wayland-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/wayland-devel
[PATCH weston 37/68] compositor-drm: Don't repaint if no damage
If we don't have any damage for the primary plane, then don't force a repaint; simply reuse the old buffer we already have. Differential Revision: https://phabricator.freedesktop.org/D1499 Signed-off-by: Daniel Stone--- libweston/compositor-drm.c | 15 +-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/libweston/compositor-drm.c b/libweston/compositor-drm.c index e575429..f0a13e1 100644 --- a/libweston/compositor-drm.c +++ b/libweston/compositor-drm.c @@ -1430,6 +1430,7 @@ drm_output_render(struct drm_output *output, pixman_region32_t *damage) { struct weston_compositor *c = output->base.compositor; struct drm_plane_state *scanout_state; + struct drm_plane *scanout_plane = output->scanout_plane; struct drm_backend *b = to_drm_backend(c); struct drm_fb *fb; @@ -1440,10 +1441,20 @@ drm_output_render(struct drm_output *output, pixman_region32_t *damage) if (scanout_state->fb) return; - if (b->use_pixman) + if (!pixman_region32_not_empty(damage) && + scanout_plane->state_cur->fb && + (scanout_plane->state_cur->fb->type == BUFFER_GBM_SURFACE || +scanout_plane->state_cur->fb->type == BUFFER_PIXMAN_DUMB) && + scanout_plane->state_cur->fb->width == + output->base.current_mode->width && + scanout_plane->state_cur->fb->height == + output->base.current_mode->height) { + fb = drm_fb_ref(scanout_plane->state_cur->fb); + } else if (b->use_pixman) { fb = drm_output_render_pixman(output, damage); - else + } else { fb = drm_output_render_gl(output, damage); + } if (!fb) { drm_plane_state_put_back(scanout_state); -- 2.9.3 ___ wayland-devel mailing list wayland-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/wayland-devel
[PATCH weston 06/68] Remove DPMS-on when going offscreen
Forcing DPMS on when we lose our session may force an expensive modeset operation, which is pointless if the next consumer (another compositor, or the console) is going to do a modeset. These should force DPMS on regardless. This actively causes problems for the DRM backend, in that it may actually require a repaint to set coherent state for DPMS off -> DPMS on transitions, which is very much not what we want when going offscreen. As DRM is the only backend which actually implements DPMS, just remove this call. Differential Revision: https://phabricator.freedesktop.org/D1483 Signed-off-by: Daniel Stone--- libweston/compositor.c | 9 + 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/libweston/compositor.c b/libweston/compositor.c index ad59156..895a040 100644 --- a/libweston/compositor.c +++ b/libweston/compositor.c @@ -3933,10 +3933,9 @@ weston_compositor_wake(struct weston_compositor *compositor) switch (old_state) { case WESTON_COMPOSITOR_SLEEPING: - weston_compositor_dpms(compositor, WESTON_DPMS_ON); - /* fall through */ case WESTON_COMPOSITOR_IDLE: case WESTON_COMPOSITOR_OFFSCREEN: + weston_compositor_dpms(compositor, WESTON_DPMS_ON); wl_signal_emit(>wake_signal, compositor); /* fall through */ default: @@ -3952,10 +3951,6 @@ weston_compositor_wake(struct weston_compositor *compositor) * This is used for example to prevent further rendering while the * compositor is shutting down. * - * \note When offscreen state is entered, outputs will be powered - * back on if they were sleeping (in DPMS off mode), even though - * no rendering will be performed. - * * Stops the idle timer. */ WL_EXPORT void @@ -3965,8 +3960,6 @@ weston_compositor_offscreen(struct weston_compositor *compositor) case WESTON_COMPOSITOR_OFFSCREEN: return; case WESTON_COMPOSITOR_SLEEPING: - weston_compositor_dpms(compositor, WESTON_DPMS_ON); - /* fall through */ default: compositor->state = WESTON_COMPOSITOR_OFFSCREEN; wl_event_source_timer_update(compositor->idle_source, 0); -- 2.9.3 ___ wayland-devel mailing list wayland-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/wayland-devel
[PATCH weston 40/68] compositor-drm: Use apply_state for starting repaint
Rather than open-coding it ourselves, use the new apply_state helper in drm_output_start_repaint. Signed-off-by: Daniel StoneReported-by: Fabien DESSENNE Differential Revision: https://phabricator.freedesktop.org/D1514 --- libweston/compositor-drm.c | 27 --- 1 file changed, 4 insertions(+), 23 deletions(-) diff --git a/libweston/compositor-drm.c b/libweston/compositor-drm.c index ec8db31..5959aed 100644 --- a/libweston/compositor-drm.c +++ b/libweston/compositor-drm.c @@ -1743,12 +1743,9 @@ static void drm_output_start_repaint_loop(struct weston_output *output_base) { struct drm_output *output = to_drm_output(output_base); - struct drm_output_state *output_state; - struct drm_plane_state *plane_state; struct drm_plane *scanout_plane = output->scanout_plane; struct drm_backend *backend = to_drm_backend(output_base->compositor); - uint32_t fb_id; struct timespec ts, tnow; struct timespec vbl2now; int64_t refresh_nsec; @@ -1798,37 +1795,21 @@ drm_output_start_repaint_loop(struct weston_output *output_base) /* Immediate query didn't provide valid timestamp. * Use pageflip fallback. */ - fb_id = scanout_plane->state_cur->fb->fb_id; assert(!output->page_flip_pending); assert(!output->state_last); assert(!output->state_pending); - output_state = + output->state_pending = drm_output_state_duplicate(output->state_cur, DRM_OUTPUT_STATE_PRESERVE_PLANES); - if (drmModePageFlip(backend->drm.fd, output->crtc_id, fb_id, - DRM_MODE_PAGE_FLIP_EVENT, output) < 0) { - weston_log("queueing pageflip failed: %m\n"); - drm_output_state_free(output_state); + ret = drm_output_apply_state(output->state_pending); + if (ret != 0) { + weston_log("applying repaint-start state failed: %m\n"); goto finish_frame; } - wl_list_for_each(plane_state, _state->plane_list, link) { - if (plane_state->plane->type != WDRM_PLANE_TYPE_OVERLAY) - continue; - - vbl.request.type = DRM_VBLANK_RELATIVE | DRM_VBLANK_EVENT; - vbl.request.type |= drm_waitvblank_pipe(output); - vbl.request.sequence = 1; - vbl.request.signal = (unsigned long) plane_state; - drmWaitVBlank(backend->drm.fd, ); - } - - drm_output_assign_state(output_state, - DRM_OUTPUT_STATE_UPDATE_ASYNCHRONOUS); - return; finish_frame: -- 2.9.3 ___ wayland-devel mailing list wayland-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/wayland-devel
[PATCH weston 44/68] compositor-drm: Add to_drm_mode helper
Much like we already have to_drm_output and to_drm_backend. Differential Revision: https://phabricator.freedesktop.org/D1505 Signed-off-by: Daniel Stone--- libweston/compositor-drm.c | 8 +++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/libweston/compositor-drm.c b/libweston/compositor-drm.c index c98ba25..b33d519 100644 --- a/libweston/compositor-drm.c +++ b/libweston/compositor-drm.c @@ -393,6 +393,12 @@ to_drm_backend(struct weston_compositor *base) return container_of(base->backend, struct drm_backend, base); } +static inline struct drm_mode * +to_drm_mode(struct weston_mode *base) +{ + return container_of(base, struct drm_mode, base); +} + /** * Return a string describing the type of a DRM object */ @@ -1740,7 +1746,7 @@ drm_output_apply_state(struct drm_output_state *state) assert(scanout_state->src_w == scanout_state->dest_w << 16); assert(scanout_state->src_h == scanout_state->dest_h << 16); - mode = container_of(output->base.current_mode, struct drm_mode, base); + mode = to_drm_mode(output->base.current_mode); if (!scanout_plane->state_cur->fb || scanout_plane->state_cur->fb->stride != scanout_state->fb->stride) { ret = drmModeSetCrtc(backend->drm.fd, output->crtc_id, -- 2.9.3 ___ wayland-devel mailing list wayland-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/wayland-devel
[PATCH weston 31/68] compositor-drm: Add universal plane awareness
From: Pekka PaalanenAdd awareness of, rather than support for, universal planes. Activate the client cap when we start if possible, and if this is activated, studiously ignore non-overlay planes. For now. [daniels: Rebased, split up, otherwise modified.] Differential Revision: https://phabricator.freedesktop.org/D1495 Signed-off-by: Daniel Stone Co-authored-by: Pekka Paalanen Co-authored-by: Louis-Francis Ratté-Boulianne --- libweston/compositor-drm.c | 406 + 1 file changed, 406 insertions(+) diff --git a/libweston/compositor-drm.c b/libweston/compositor-drm.c index e4d6743..46fcf0a 100644 --- a/libweston/compositor-drm.c +++ b/libweston/compositor-drm.c @@ -62,10 +62,18 @@ #include "presentation-time-server-protocol.h" #include "linux-dmabuf.h" +#ifndef static_assert +#define static_assert(cond, msg) assert((cond) && msg) +#endif + #ifndef DRM_CAP_TIMESTAMP_MONOTONIC #define DRM_CAP_TIMESTAMP_MONOTONIC 0x6 #endif +#ifndef DRM_CLIENT_CAP_UNIVERSAL_PLANES +#define DRM_CLIENT_CAP_UNIVERSAL_PLANES 2 +#endif + #ifndef DRM_CAP_CURSOR_WIDTH #define DRM_CAP_CURSOR_WIDTH 0x8 #endif @@ -78,6 +86,41 @@ #define GBM_BO_USE_CURSOR GBM_BO_USE_CURSOR_64X64 #endif +/** + * Holding structure for one DRM property. + */ +struct property_item { + drmModePropertyRes *drm_prop; + uint64_t value; +}; + +/** + * List of properties attached to DRM planes + */ +enum wdrm_plane_property { + WDRM_PLANE_TYPE = 0, + WDRM_PLANE__COUNT +}; + +/** + * Possible values for the WDRM_PLANE_TYPE property. + */ +enum wdrm_plane_type { + WDRM_PLANE_TYPE_PRIMARY = 0, + WDRM_PLANE_TYPE_CURSOR, + WDRM_PLANE_TYPE_OVERLAY, + WDRM_PLANE_TYPE__COUNT +}; + +/** + * Holding structure for plane properties. + */ +struct plane_properties { + struct property_item item[WDRM_PLANE__COUNT]; + uint64_t typemap[WDRM_PLANE_TYPE__COUNT]; /**< map for type enum */ + uint64_t value; +}; + struct drm_backend { struct weston_backend base; struct weston_compositor *compositor; @@ -115,6 +158,8 @@ struct drm_backend { int cursors_are_broken; + bool universal_planes; + int use_pixman; struct udev_input input; @@ -188,6 +233,9 @@ struct drm_plane { struct drm_output *output; struct drm_backend *backend; + enum wdrm_plane_type type; + struct plane_properties props; + uint32_t possible_crtcs; uint32_t plane_id; uint32_t count_formats; @@ -255,6 +303,342 @@ to_drm_backend(struct weston_compositor *base) return container_of(base->backend, struct drm_backend, base); } +/** + * Return a string describing the type of a DRM object + */ +static const char * +drm_object_type_str(uint32_t obj_type) +{ + switch (obj_type) { + case DRM_MODE_OBJECT_CRTC: return "crtc"; + case DRM_MODE_OBJECT_CONNECTOR: return "connector"; + case DRM_MODE_OBJECT_ENCODER: return "encoder"; + case DRM_MODE_OBJECT_MODE: return "mode"; + case DRM_MODE_OBJECT_PROPERTY: return "property"; + case DRM_MODE_OBJECT_FB:return "fb"; + case DRM_MODE_OBJECT_BLOB: return "blob"; + case DRM_MODE_OBJECT_PLANE: return "plane"; + default: return "???"; + } +} + +/** + * Cache a mapping from static values to a DRM property enum + * + * DRM property enum values are dynamic at runtime; the user must query the + * property to find out the desired runtime value for a requested string + * name. Using the 'type' field on planes as an example, there is no single + * hardcoded constant for primary plane types; instead, the property must be + * queried at runtime to find the value associated with the string "Primary". + * + * This helper queries and caches the enum values, to allow us to use a set + * of compile-time-constant enums portably across various implementations. + * The values given in enum_names are searched for, and stored in the + * same-indexed field of the map array. + * + * For example, if the DRM driver exposes 'Foo' as value 7 and 'Bar' as value + * 19, passing in enum_names containing 'Foo' and 'Bar' in that order, will + * populate map with 7 and 19, in that order. + * + * This should always be used with static C enums to represent each value, e.g. + * WDRM_PLANE_MISC_FOO, WDRM_PLANE_MISC_BAR. + * + * Property lookup is not mandatory and may fail; users should carefully + * check the return value, which is a bitmask populated with the indices + * of properties which were successfully looked up. Values not successfully + * looked up may return 0, which may represent a false positive. + * + * @param prop DRM enum property to cache map for + * @param map Array for enum values; each entry is written for the corresponding + *
[PATCH weston 27/68] compositor-drm: Clean up page_flip_pending path
page_flip_pending is set when we do a no-effect pageflip, and thus don't need to release the buffer as we don't have a new one pending. Now we have last/cur/pending properly broken out, we can just use these consistently, and test if last != current (the effect), rather than the specific path which triggered it. Signed-off-by: Daniel StoneDifferential Revision: https://phabricator.freedesktop.org/D1417 --- libweston/compositor-drm.c | 19 +++ 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/libweston/compositor-drm.c b/libweston/compositor-drm.c index 382c8e2..bd6170a 100644 --- a/libweston/compositor-drm.c +++ b/libweston/compositor-drm.c @@ -786,6 +786,7 @@ drm_output_repaint(struct weston_output *output_base, output->fb_current = output->fb_pending; output->fb_pending = NULL; + assert(!output->page_flip_pending); output->page_flip_pending = 1; drm_output_set_cursor(output); @@ -907,12 +908,18 @@ drm_output_start_repaint_loop(struct weston_output *output_base) */ fb_id = output->fb_current->fb_id; + assert(!output->page_flip_pending); + assert(!output->fb_last); + if (drmModePageFlip(backend->drm.fd, output->crtc_id, fb_id, DRM_MODE_PAGE_FLIP_EVENT, output) < 0) { weston_log("queueing pageflip failed: %m\n"); goto finish_frame; } + output->fb_last = drm_fb_ref(output->fb_current); + output->page_flip_pending = 1; + return; finish_frame: @@ -973,16 +980,12 @@ page_flip_handler(int fd, unsigned int frame, drm_output_update_msc(output, frame); - /* We don't set page_flip_pending on start_repaint_loop, in that case -* we just want to page flip to the current buffer to get an accurate -* timestamp */ - if (output->page_flip_pending) { - drm_fb_unref(output->fb_last); - output->fb_last = NULL; - } - + assert(output->page_flip_pending); output->page_flip_pending = 0; + drm_fb_unref(output->fb_last); + output->fb_last = NULL; + if (output->destroy_pending) drm_output_destroy(>base); else if (output->disable_pending) -- 2.9.3 ___ wayland-devel mailing list wayland-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/wayland-devel
[PATCH weston 26/68] compositor-drm: Turn vblank_pending from bool to refcount
vblank_pending is currently a bool, which is reset on every vblank requests (i.e. sprite pageflip). This can occur more than once per frame, so turn it into a callback, so we only fire frame-done when we've collected all the events. Signed-off-by: Daniel StoneDifferential Revision: https://phabricator.freedesktop.org/D1418 --- libweston/compositor-drm.c | 7 --- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/libweston/compositor-drm.c b/libweston/compositor-drm.c index 0d3ca35..382c8e2 100644 --- a/libweston/compositor-drm.c +++ b/libweston/compositor-drm.c @@ -836,7 +836,7 @@ drm_output_repaint(struct weston_output *output_base, s->fb_last = s->fb_current; s->fb_current = s->fb_pending; s->fb_pending = NULL; - output->vblank_pending = 1; + output->vblank_pending++; } return 0; @@ -944,13 +944,14 @@ vblank_handler(int fd, unsigned int frame, unsigned int sec, unsigned int usec, WP_PRESENTATION_FEEDBACK_KIND_HW_CLOCK; drm_output_update_msc(output, frame); - output->vblank_pending = 0; + output->vblank_pending--; + assert(output->vblank_pending >= 0); assert(s->fb_last || s->fb_current); drm_fb_unref(s->fb_last); s->fb_last = NULL; - if (!output->page_flip_pending) { + if (!output->page_flip_pending && !output->vblank_pending) { ts.tv_sec = sec; ts.tv_nsec = usec * 1000; weston_output_finish_frame(>base, , flags); -- 2.9.3 ___ wayland-devel mailing list wayland-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/wayland-devel
[PATCH weston 50/68] compositor-drm: Use plane_coords_for_view for cursor
Use the new helper to populate the cursor state as well, with some special-case handling to account for how we always upload a full-size BO. Signed-off-by: Daniel StoneReported-by: Derek Foreman Differential Revision: https://phabricator.freedesktop.org/D1519 --- libweston/compositor-drm.c | 48 +++--- 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/libweston/compositor-drm.c b/libweston/compositor-drm.c index 202772b..1dc63c8 100644 --- a/libweston/compositor-drm.c +++ b/libweston/compositor-drm.c @@ -2435,10 +2435,8 @@ drm_output_prepare_cursor_view(struct drm_output_state *output_state, struct drm_backend *b = to_drm_backend(output->base.compositor); struct drm_plane *plane = output->cursor_plane; struct drm_plane_state *plane_state; - struct weston_buffer_viewport *viewport = >surface->buffer_viewport; struct wl_shm_buffer *shmbuf; bool needs_update = false; - float x, y; if (!plane) return NULL; @@ -2468,16 +2466,6 @@ drm_output_prepare_cursor_view(struct drm_output_state *output_state, if (wl_shm_buffer_get_format(shmbuf) != WL_SHM_FORMAT_ARGB) return NULL; - if (output->base.transform != WL_OUTPUT_TRANSFORM_NORMAL) - return NULL; - if (ev->transform.enabled && - (ev->transform.matrix.type > WESTON_MATRIX_TRANSFORM_TRANSLATE)) - return NULL; - if (viewport->buffer.scale != output->base.current_scale) - return NULL; - if (ev->geometry.scissor_enabled) - return NULL; - if (ev->surface->width > b->cursor_width || ev->surface->height > b->cursor_height) return NULL; @@ -2488,6 +2476,26 @@ drm_output_prepare_cursor_view(struct drm_output_state *output_state, if (plane_state && plane_state->fb) return NULL; + /* We can't scale with the legacy API, and we don't try to account for +* simple cropping/translation in cursor_bo_update. */ + plane_state->output = output; + drm_plane_state_coords_for_view(plane_state, ev); + if (plane_state->src_x != 0 || plane_state->src_y != 0 || + plane_state->src_w > (unsigned) b->cursor_width << 16 || + plane_state->src_h > (unsigned) b->cursor_height << 16 || + plane_state->src_w != plane_state->dest_w << 16 || + plane_state->src_h != plane_state->dest_h << 16) + goto err; + + /* The cursor API is somewhat special: in cursor_bo_update(), we upload +* a buffer which is always cursor_width x cursor_height, even if the +* surface we want to promote is actually smaller than this. Manually +* mangle the plane state to deal with this. */ + plane_state->src_w = b->cursor_width << 16; + plane_state->src_h = b->cursor_height << 16; + plane_state->dest_w = b->cursor_width; + plane_state->dest_h = b->cursor_height; + /* Since we're setting plane state up front, we need to work out * whether or not we need to upload a new cursor. We can't use the * plane damage, since the planes haven't actually been calculated @@ -2504,26 +2512,18 @@ drm_output_prepare_cursor_view(struct drm_output_state *output_state, } output->cursor_view = ev; - weston_view_to_global_float(ev, 0, 0, , ); - plane->base.x = x; - plane->base.y = y; plane_state->fb = drm_fb_ref(output->gbm_cursor_fb[output->current_cursor]); - plane_state->output = output; - plane_state->src_x = 0; - plane_state->src_y = 0; - plane_state->src_w = b->cursor_width << 16; - plane_state->src_h = b->cursor_height << 16; - plane_state->dest_x = (x - output->base.x) * output->base.current_scale; - plane_state->dest_y = (y - output->base.y) * output->base.current_scale; - plane_state->dest_w = b->cursor_width; - plane_state->dest_h = b->cursor_height; if (needs_update) cursor_bo_update(b, plane_state->fb->bo, ev); return >base; + +err: + drm_plane_state_put_back(plane_state); + return NULL; } static void -- 2.9.3 ___ wayland-devel mailing list wayland-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/wayland-devel
[PATCH weston 14/68] compositor-drm: Store width and height inside drm_fb
This will be used so we can later determine the compatibility of drm_fbs without needing to introspect external state. Differential Revision: https://phabricator.freedesktop.org/D1487 Signed-off-by: Daniel Stone--- libweston/compositor-drm.c | 24 +--- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/libweston/compositor-drm.c b/libweston/compositor-drm.c index a5052b9..4ef7343 100644 --- a/libweston/compositor-drm.c +++ b/libweston/compositor-drm.c @@ -131,6 +131,7 @@ struct drm_mode { struct drm_fb { uint32_t fb_id, stride, handle, size; + int width, height; int fd; int is_client_buffer; struct weston_buffer_reference buffer_ref; @@ -292,6 +293,8 @@ drm_fb_create_dumb(struct drm_backend *b, int width, int height, fb->handle = create_arg.handle; fb->stride = create_arg.pitch; fb->size = create_arg.size; + fb->width = width; + fb->height = height; fb->fd = b->drm.fd; ret = -1; @@ -371,7 +374,6 @@ drm_fb_get_from_bo(struct gbm_bo *bo, struct drm_backend *backend, uint32_t format) { struct drm_fb *fb = gbm_bo_get_user_data(bo); - int width, height; uint32_t handles[4] = { 0 }, pitches[4] = { 0 }, offsets[4] = { 0 }; int ret; @@ -384,17 +386,17 @@ drm_fb_get_from_bo(struct gbm_bo *bo, fb->bo = bo; - width = gbm_bo_get_width(bo); - height = gbm_bo_get_height(bo); + fb->width = gbm_bo_get_width(bo); + fb->height = gbm_bo_get_height(bo); fb->stride = gbm_bo_get_stride(bo); fb->handle = gbm_bo_get_handle(bo).u32; - fb->size = fb->stride * height; + fb->size = fb->stride * fb->height; fb->fd = backend->drm.fd; - if (backend->min_width > width || - width > backend->max_width || - backend->min_height > height || - height > backend->max_height) { + if (backend->min_width > fb->width || + fb->width > backend->max_width || + backend->min_height > fb->height || + fb->height > backend->max_height) { weston_log("bo geometry out of bounds\n"); goto err_free; } @@ -406,7 +408,7 @@ drm_fb_get_from_bo(struct gbm_bo *bo, pitches[0] = fb->stride; offsets[0] = 0; - ret = drmModeAddFB2(backend->drm.fd, width, height, + ret = drmModeAddFB2(backend->drm.fd, fb->width, fb->height, format, handles, pitches, offsets, >fb_id, 0); if (ret) { @@ -417,8 +419,8 @@ drm_fb_get_from_bo(struct gbm_bo *bo, } if (ret) - ret = drmModeAddFB(backend->drm.fd, width, height, 24, 32, - fb->stride, fb->handle, >fb_id); + ret = drmModeAddFB(backend->drm.fd, fb->width, fb->height, + 24, 32, fb->stride, fb->handle, >fb_id); if (ret) { weston_log("failed to create kms fb: %m\n"); -- 2.9.3 ___ wayland-devel mailing list wayland-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/wayland-devel
[PATCH weston 18/68] compositor-drm: Drop output from release_fb
We only need it for the GBM surface the FB was originally created against; a mismatch here is very bad indeed, so no reason to pass it in explictly every time rather than store it. Differential Revision: https://phabricator.freedesktop.org/D1490 Signed-off-by: Daniel Stone--- libweston/compositor-drm.c | 20 +++- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/libweston/compositor-drm.c b/libweston/compositor-drm.c index 7dbfc6b..eb735b2 100644 --- a/libweston/compositor-drm.c +++ b/libweston/compositor-drm.c @@ -148,6 +148,7 @@ struct drm_fb { /* Used by gbm fbs */ struct gbm_bo *bo; + struct gbm_surface *gbm_surface; /* Used by dumb fbs */ void *map; @@ -466,7 +467,7 @@ drm_fb_set_buffer(struct drm_fb *fb, struct weston_buffer *buffer) } static void -drm_output_release_fb(struct drm_output *output, struct drm_fb *fb) +drm_fb_unref(struct drm_fb *fb) { if (!fb) return; @@ -479,7 +480,7 @@ drm_output_release_fb(struct drm_output *output, struct drm_fb *fb) gbm_bo_destroy(fb->bo); break; case BUFFER_GBM_SURFACE: - gbm_surface_release_buffer(output->gbm_surface, fb->bo); + gbm_surface_release_buffer(fb->gbm_surface, fb->bo); break; default: assert(NULL); @@ -615,6 +616,7 @@ drm_output_render_gl(struct drm_output *output, pixman_region32_t *damage) gbm_surface_release_buffer(output->gbm_surface, bo); return; } + output->next->gbm_surface = output->gbm_surface; } static void @@ -798,7 +800,7 @@ drm_output_repaint(struct weston_output *output_base, err_pageflip: output->cursor_view = NULL; if (output->next) { - drm_output_release_fb(output, output->next); + drm_fb_unref(output->next); output->next = NULL; } @@ -900,7 +902,7 @@ vblank_handler(int fd, unsigned int frame, unsigned int sec, unsigned int usec, drm_output_update_msc(output, frame); output->vblank_pending = 0; - drm_output_release_fb(output, s->current); + drm_fb_unref(s->current); s->current = s->next; s->next = NULL; @@ -930,7 +932,7 @@ page_flip_handler(int fd, unsigned int frame, * we just want to page flip to the current buffer to get an accurate * timestamp */ if (output->page_flip_pending) { - drm_output_release_fb(output, output->current); + drm_fb_unref(output->current); output->current = output->next; output->next = NULL; } @@ -1452,8 +1454,8 @@ drm_output_switch_mode(struct weston_output *output_base, struct weston_mode *mo WL_OUTPUT_MODE_CURRENT | WL_OUTPUT_MODE_PREFERRED; /* reset rendering stuff. */ - drm_output_release_fb(output, output->current); - drm_output_release_fb(output, output->next); + drm_fb_unref(output->current); + drm_fb_unref(output->next); output->current = output->next = NULL; if (b->use_pixman) { @@ -2672,8 +2674,8 @@ destroy_sprites(struct drm_backend *backend) sprite->plane_id, output->crtc_id, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); - drm_output_release_fb(output, sprite->current); - drm_output_release_fb(output, sprite->next); + drm_fb_unref(sprite->current); + drm_fb_unref(sprite->next); weston_plane_release(>plane); free(sprite); } -- 2.9.3 ___ wayland-devel mailing list wayland-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/wayland-devel
[PATCH weston 01/68] libweston: Add pixel-format helpers
Rather than duplicating knowledge of pixel formats across several components, create a custom central repository. Signed-off-by: Daniel StoneDifferential Revision: https://phabricator.freedesktop.org/D1511 --- libweston/pixel-formats.c | 398 ++ libweston/pixel-formats.h | 112 + 2 files changed, 510 insertions(+) create mode 100644 libweston/pixel-formats.c create mode 100644 libweston/pixel-formats.h diff --git a/libweston/pixel-formats.c b/libweston/pixel-formats.c new file mode 100644 index 000..9c70e73 --- /dev/null +++ b/libweston/pixel-formats.c @@ -0,0 +1,398 @@ +/* + * Copyright © 2016 Collabora, Ltd. + * + * 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. + * + * Author: Daniel Stone + */ + +#include "config.h" + +#include +#include +#include +#include + +#include "helpers.h" +#include "wayland-util.h" +#include "pixel-formats.h" + +#include +#include +#include +#include + +#include "weston-egl-ext.h" + +/** + * Table of DRM formats supported by Weston; RGB, ARGB and YUV formats are + * supported. Indexed/greyscale formats, and formats not containing complete + * colour channels, are not supported. + */ +static const struct pixel_format_info pixel_format_table[] = { + { + .format = DRM_FORMAT_XRGB, + }, + { + .format = DRM_FORMAT_ARGB, + .opaque_substitute = DRM_FORMAT_XRGB, + }, + { + .format = DRM_FORMAT_XBGR, + }, + { + .format = DRM_FORMAT_ABGR, + .opaque_substitute = DRM_FORMAT_XBGR, + }, + { + .format = DRM_FORMAT_RGBX, + .gl_format = GL_RGBA, + .gl_type = GL_UNSIGNED_SHORT_4_4_4_4, + }, + { + .format = DRM_FORMAT_RGBA, + .opaque_substitute = DRM_FORMAT_RGBX, + .gl_format = GL_RGBA, + .gl_type = GL_UNSIGNED_SHORT_4_4_4_4, + }, + { + .format = DRM_FORMAT_BGRX, + .gl_format = GL_BGRA_EXT, + .gl_type = GL_UNSIGNED_SHORT_4_4_4_4, + }, + { + .format = DRM_FORMAT_BGRA, + .opaque_substitute = DRM_FORMAT_BGRX, + .gl_format = GL_BGRA_EXT, + .gl_type = GL_UNSIGNED_SHORT_4_4_4_4, + }, + { + .format = DRM_FORMAT_XRGB1555, + .depth = 15, + .bpp = 16, + }, + { + .format = DRM_FORMAT_ARGB1555, + .opaque_substitute = DRM_FORMAT_XRGB1555, + }, + { + .format = DRM_FORMAT_XBGR1555, + }, + { + .format = DRM_FORMAT_ABGR1555, + .opaque_substitute = DRM_FORMAT_XBGR1555, + }, + { + .format = DRM_FORMAT_RGBX5551, + .gl_format = GL_RGBA, + .gl_type = GL_UNSIGNED_SHORT_5_5_5_1, + }, + { + .format = DRM_FORMAT_RGBA5551, + .opaque_substitute = DRM_FORMAT_RGBX5551, + .gl_format = GL_RGBA, + .gl_type = GL_UNSIGNED_SHORT_5_5_5_1, + }, + { + .format = DRM_FORMAT_BGRX5551, + .gl_format = GL_BGRA_EXT, + .gl_type = GL_UNSIGNED_SHORT_5_5_5_1, + }, + { + .format = DRM_FORMAT_BGRA5551, + .opaque_substitute = DRM_FORMAT_BGRX5551, + .gl_format = GL_BGRA_EXT, + .gl_type = GL_UNSIGNED_SHORT_5_5_5_1, + }, + { + .format = DRM_FORMAT_RGB565, + .depth = 16, + .bpp = 16, + .gl_type = GL_RGB, + .gl_type = GL_UNSIGNED_SHORT_5_6_5, + }, + { + .format =
[PATCH weston 16/68] compositor-drm: Store format in drm_fb
This uses the new pixel-format helpers, so we can also replace depth/bpp with these. Signed-off-by: Daniel StoneDifferential Revision: https://phabricator.freedesktop.org/D1513 --- libweston/compositor-drm.c | 43 +++ 1 file changed, 27 insertions(+), 16 deletions(-) diff --git a/libweston/compositor-drm.c b/libweston/compositor-drm.c index 217db32..af43a15 100644 --- a/libweston/compositor-drm.c +++ b/libweston/compositor-drm.c @@ -54,6 +54,7 @@ #include "gl-renderer.h" #include "weston-egl-ext.h" #include "pixman-renderer.h" +#include "pixel-formats.h" #include "libbacklight.h" #include "libinput-seat.h" #include "launcher-util.h" @@ -140,6 +141,7 @@ struct drm_fb { enum drm_fb_type type; uint32_t fb_id, stride, handle, size; + const struct pixel_format_info *format; int width, height; int fd; struct weston_buffer_reference buffer_ref; @@ -267,7 +269,6 @@ drm_fb_create_dumb(struct drm_backend *b, int width, int height, { struct drm_fb *fb; int ret; - uint32_t bpp, depth; struct drm_mode_create_dumb create_arg; struct drm_mode_destroy_dumb destroy_arg; @@ -277,20 +278,20 @@ drm_fb_create_dumb(struct drm_backend *b, int width, int height, if (!fb) return NULL; - switch (format) { - case GBM_FORMAT_XRGB: - bpp = 32; - depth = 24; - break; - case GBM_FORMAT_RGB565: - bpp = depth = 16; - break; - default: - return NULL; + fb->format = pixel_format_get_info(format); + if (!fb->format) { + weston_log("failed to look up format 0x%lx\n", + (unsigned long) format); + goto err_fb; + } + + if (!fb->format->depth || !fb->format->bpp) { + weston_log("format 0x%lx is not compatible with dumb buffers\n", + (unsigned long) format); } memset(_arg, 0, sizeof create_arg); - create_arg.bpp = bpp; + create_arg.bpp = fb->format->bpp; create_arg.width = width; create_arg.height = height; @@ -316,7 +317,8 @@ drm_fb_create_dumb(struct drm_backend *b, int width, int height, offsets[0] = 0; ret = drmModeAddFB2(b->drm.fd, width, height, - format, handles, pitches, offsets, + fb->format->format, + handles, pitches, offsets, >fb_id, 0); if (ret) { weston_log("addfb2 failed: %m\n"); @@ -325,7 +327,8 @@ drm_fb_create_dumb(struct drm_backend *b, int width, int height, } if (ret) { - ret = drmModeAddFB(b->drm.fd, width, height, depth, bpp, + ret = drmModeAddFB(b->drm.fd, width, height, + fb->format->depth, fb->format->bpp, fb->stride, fb->handle, >fb_id); } @@ -402,9 +405,16 @@ drm_fb_get_from_bo(struct gbm_bo *bo, struct drm_backend *backend, fb->height = gbm_bo_get_height(bo); fb->stride = gbm_bo_get_stride(bo); fb->handle = gbm_bo_get_handle(bo).u32; + fb->format = pixel_format_get_info(format); fb->size = fb->stride * fb->height; fb->fd = backend->drm.fd; + if (!fb->format) { + weston_log("couldn't look up format 0x%lx\n", + (unsigned long) format); + goto err_free; + } + if (backend->min_width > fb->width || fb->width > backend->max_width || backend->min_height > fb->height || @@ -430,9 +440,10 @@ drm_fb_get_from_bo(struct gbm_bo *bo, struct drm_backend *backend, } } - if (ret) + if (ret && fb->format->depth && fb->format->bpp) ret = drmModeAddFB(backend->drm.fd, fb->width, fb->height, - 24, 32, fb->stride, fb->handle, >fb_id); + fb->format->depth, fb->format->bpp, + fb->stride, fb->handle, >fb_id); if (ret) { weston_log("failed to create kms fb: %m\n"); -- 2.9.3 ___ wayland-devel mailing list wayland-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/wayland-devel
[PATCH weston 10/68] compositor-drm: Make scanout view preparation more stringent
Don't import buffers which span multiple outputs, short-cut any attempt to import SHM buffers, and ignore buffers with a global alpha set. I'm not convinced all of these conditions entirely make sense, but this at least makes them equally nonsensical. Signed-off-by: Daniel StoneDifferential Revision: https://phabricator.freedesktop.org/D1414 --- libweston/compositor-drm.c | 35 --- 1 file changed, 24 insertions(+), 11 deletions(-) diff --git a/libweston/compositor-drm.c b/libweston/compositor-drm.c index 8cd9d5a..e22d792 100644 --- a/libweston/compositor-drm.c +++ b/libweston/compositor-drm.c @@ -462,6 +462,13 @@ drm_output_release_fb(struct drm_output *output, struct drm_fb *fb) } } +static int +drm_view_transform_supported(struct weston_view *ev) +{ + return !ev->transform.enabled || + (ev->transform.matrix.type < WESTON_MATRIX_TRANSFORM_ROTATE); +} + static uint32_t drm_output_check_scanout_format(struct drm_output *output, struct weston_surface *es, struct gbm_bo *bo) @@ -502,27 +509,40 @@ drm_output_prepare_scanout_view(struct drm_output *output, struct gbm_bo *bo; uint32_t format; + /* Don't import buffers which span multiple outputs. */ + if (ev->output_mask != (1u << output->base.id)) + return NULL; + /* We use GBM to import buffers. */ if (b->gbm == NULL) return NULL; if (buffer == NULL) return NULL; + if (wl_shm_buffer_get(buffer->resource)) + return NULL; /* Make sure our view is exactly compatible with the output. */ if (ev->geometry.x != output->base.x || ev->geometry.y != output->base.y) return NULL; + if (buffer->width != output->base.current_mode->width || + buffer->height != output->base.current_mode->height) + return NULL; + if (ev->transform.enabled) return NULL; if (ev->geometry.scissor_enabled) return NULL; - - if (buffer->width != output->base.current_mode->width || - buffer->height != output->base.current_mode->height) - return NULL; if (viewport->buffer.transform != output->base.transform) return NULL; + if (viewport->buffer.scale != output->base.current_scale) + return NULL; + if (!drm_view_transform_supported(ev)) + return NULL; + + if (ev->alpha != 1.0f) + return NULL; bo = gbm_bo_import(b->gbm, GBM_BO_IMPORT_WL_BUFFER, buffer->resource, GBM_BO_USE_SCANOUT); @@ -936,13 +956,6 @@ drm_output_check_sprite_format(struct drm_sprite *s, return 0; } -static int -drm_view_transform_supported(struct weston_view *ev) -{ - return !ev->transform.enabled || - (ev->transform.matrix.type < WESTON_MATRIX_TRANSFORM_ROTATE); -} - static struct weston_plane * drm_output_prepare_overlay_view(struct drm_output *output, struct weston_view *ev) -- 2.9.3 ___ wayland-devel mailing list wayland-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/wayland-devel
[PATCH weston 25/68] compositor-drm: Introduce fb_last member
Clean up some ambiguity around current/next: current could previously have referred to a buffer which was being displayed, or the last buffer being displayed whilst we waited for a configuration we'd requested to take effect. Introduce a new variable, fb_last, which exclusively holds the latter case, thus leaving us with three unambiguous members: fb_pending is used as a scratch space for a buffer we're about to post, fb_current holds the buffer we last requested to display (whether active yet or not), and fb_last is again scratch space for a buffer which is no longer being displayed after a previous configuration reqeust. Signed-off-by: Daniel StoneDifferential Revision: https://phabricator.freedesktop.org/D1411 --- libweston/compositor-drm.c | 42 ++ 1 file changed, 30 insertions(+), 12 deletions(-) diff --git a/libweston/compositor-drm.c b/libweston/compositor-drm.c index 5909239..0d3ca35 100644 --- a/libweston/compositor-drm.c +++ b/libweston/compositor-drm.c @@ -190,7 +190,7 @@ struct drm_output { int current_cursor; struct weston_plane fb_plane; - struct drm_fb *fb_current, *fb_pending; + struct drm_fb *fb_current, *fb_pending, *fb_last; struct backlight *backlight; struct drm_fb *dumb[2]; @@ -211,7 +211,7 @@ struct drm_sprite { struct weston_plane plane; - struct drm_fb *fb_current, *fb_pending; + struct drm_fb *fb_current, *fb_pending, *fb_last; struct drm_output *output; struct drm_backend *backend; @@ -755,6 +755,8 @@ drm_output_repaint(struct weston_output *output_base, if (output->disable_pending || output->destroy_pending) return -1; + assert(!output->fb_last); + drm_output_render(output, damage); if (!output->fb_pending) return -1; @@ -780,6 +782,10 @@ drm_output_repaint(struct weston_output *output_base, goto err_pageflip; } + output->fb_last = output->fb_current; + output->fb_current = output->fb_pending; + output->fb_pending = NULL; + output->page_flip_pending = 1; drm_output_set_cursor(output); @@ -794,6 +800,8 @@ drm_output_repaint(struct weston_output *output_base, .request.sequence = 1, }; + /* XXX: Set output much earlier, so we don't attempt to place +* planes on entirely the wrong output. */ if ((!s->fb_current && !s->fb_pending) || !drm_sprite_crtc_supported(output, s)) continue; @@ -825,6 +833,9 @@ drm_output_repaint(struct weston_output *output_base, } s->output = output; + s->fb_last = s->fb_current; + s->fb_current = s->fb_pending; + s->fb_pending = NULL; output->vblank_pending = 1; } @@ -935,9 +946,9 @@ vblank_handler(int fd, unsigned int frame, unsigned int sec, unsigned int usec, drm_output_update_msc(output, frame); output->vblank_pending = 0; - drm_fb_unref(s->fb_current); - s->fb_current = s->fb_pending; - s->fb_pending = NULL; + assert(s->fb_last || s->fb_current); + drm_fb_unref(s->fb_last); + s->fb_last = NULL; if (!output->page_flip_pending) { ts.tv_sec = sec; @@ -965,9 +976,8 @@ page_flip_handler(int fd, unsigned int frame, * we just want to page flip to the current buffer to get an accurate * timestamp */ if (output->page_flip_pending) { - drm_fb_unref(output->fb_current); - output->fb_current = output->fb_pending; - output->fb_pending = NULL; + drm_fb_unref(output->fb_last); + output->fb_last = NULL; } output->page_flip_pending = 0; @@ -1486,10 +1496,16 @@ drm_output_switch_mode(struct weston_output *output_base, struct weston_mode *mo output->base.current_mode->flags = WL_OUTPUT_MODE_CURRENT | WL_OUTPUT_MODE_PREFERRED; - /* reset rendering stuff. */ + /* XXX: This drops our current buffer too early, before we've started +* displaying it. Ideally this should be much more atomic and +* integrated with a full repaint cycle, rather than doing a +* sledgehammer modeswitch first, and only later showing new +* content. +*/ drm_fb_unref(output->fb_current); - drm_fb_unref(output->fb_pending); - output->fb_current = output->fb_pending = NULL; + assert(!output->fb_last); + assert(!output->fb_pending); + output->fb_last = output->fb_current = NULL; if (b->use_pixman) { drm_output_fini_pixman(output); @@ -2705,6 +2721,7 @@ create_sprites(struct drm_backend *b) sprite->possible_crtcs =
[PATCH weston 11/68] compositor-drm: Calculate more cursor state up front
Make drm_output_set_cursor more deterministic, by calculating more state and performing more plane manipulation, inside drm_output_prepare_cursor_view. Differential Revision: https://phabricator.freedesktop.org/D1485 Signed-off-by: Daniel Stone--- libweston/compositor-drm.c | 39 --- 1 file changed, 16 insertions(+), 23 deletions(-) diff --git a/libweston/compositor-drm.c b/libweston/compositor-drm.c index e22d792..3276ed0 100644 --- a/libweston/compositor-drm.c +++ b/libweston/compositor-drm.c @@ -1135,6 +1135,7 @@ drm_output_prepare_cursor_view(struct drm_output *output, struct drm_backend *b = to_drm_backend(output->base.compositor); struct weston_buffer_viewport *viewport = >surface->buffer_viewport; struct wl_shm_buffer *shmbuf; + float x, y; if (b->cursors_are_broken) return NULL; @@ -1173,6 +1174,9 @@ drm_output_prepare_cursor_view(struct drm_output *output, return NULL; output->cursor_view = ev; + weston_view_to_global_float(ev, 0, 0, , ); + output->cursor_plane.x = x; + output->cursor_plane.y = y; return >cursor_plane; } @@ -1218,24 +1222,17 @@ static void drm_output_set_cursor(struct drm_output *output) { struct weston_view *ev = output->cursor_view; - struct weston_buffer *buffer; struct drm_backend *b = to_drm_backend(output->base.compositor); EGLint handle; struct gbm_bo *bo; float x, y; - output->cursor_view = NULL; if (ev == NULL) { drmModeSetCursor(b->drm.fd, output->crtc_id, 0, 0, 0); - output->cursor_plane.x = INT32_MIN; - output->cursor_plane.y = INT32_MIN; return; } - buffer = ev->surface->buffer_ref.buffer; - - if (buffer && - pixman_region32_not_empty(>cursor_plane.damage)) { + if (pixman_region32_not_empty(>cursor_plane.damage)) { pixman_region32_fini(>cursor_plane.damage); pixman_region32_init(>cursor_plane.damage); output->current_cursor ^= 1; @@ -1250,22 +1247,14 @@ drm_output_set_cursor(struct drm_output *output) } } - weston_view_to_global_float(ev, 0, 0, , ); - - /* From global to output space, output transform is guaranteed to be -* NORMAL by drm_output_prepare_cursor_view(). -*/ - x = (x - output->base.x) * output->base.current_scale; - y = (y - output->base.y) * output->base.current_scale; + x = (output->cursor_plane.x - output->base.x) * + output->base.current_scale; + y = (output->cursor_plane.y - output->base.y) * + output->base.current_scale; - if (output->cursor_plane.x != x || output->cursor_plane.y != y) { - if (drmModeMoveCursor(b->drm.fd, output->crtc_id, x, y)) { - weston_log("failed to move cursor: %m\n"); - b->cursors_are_broken = 1; - } - - output->cursor_plane.x = x; - output->cursor_plane.y = y; + if (drmModeMoveCursor(b->drm.fd, output->crtc_id, x, y)) { + weston_log("failed to move cursor: %m\n"); + b->cursors_are_broken = 1; } } @@ -1294,6 +1283,10 @@ drm_assign_planes(struct weston_output *output_base) pixman_region32_init(); primary = _base->compositor->primary_plane; + output->cursor_view = NULL; + output->cursor_plane.x = INT32_MIN; + output->cursor_plane.y = INT32_MIN; + wl_list_for_each_safe(ev, next, _base->compositor->view_list, link) { struct weston_surface *es = ev->surface; -- 2.9.3 ___ wayland-devel mailing list wayland-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/wayland-devel
[PATCH weston 21/68] compositor-drm: Use drm_fb for cursor buffers
Now that we have better types in drm_fb, use it for cursor buffers as well. Differential Revision: https://phabricator.freedesktop.org/D1493 Signed-off-by: Daniel Stone--- libweston/compositor-drm.c | 73 +- 1 file changed, 53 insertions(+), 20 deletions(-) diff --git a/libweston/compositor-drm.c b/libweston/compositor-drm.c index 950c265..557b97d 100644 --- a/libweston/compositor-drm.c +++ b/libweston/compositor-drm.c @@ -135,6 +135,7 @@ enum drm_fb_type { BUFFER_CLIENT, /**< directly sourced from client */ BUFFER_PIXMAN_DUMB, /**< internal Pixman rendering */ BUFFER_GBM_SURFACE, /**< internal EGL rendering */ + BUFFER_CURSOR, /**< internal cursor buffer */ }; struct drm_fb { @@ -183,11 +184,12 @@ struct drm_output { int disable_pending; struct gbm_surface *gbm_surface; - struct gbm_bo *gbm_cursor_bo[2]; + struct drm_fb *gbm_cursor_fb[2]; struct weston_plane cursor_plane; - struct weston_plane fb_plane; struct weston_view *cursor_view; int current_cursor; + + struct weston_plane fb_plane; struct drm_fb *current, *next; struct backlight *backlight; @@ -285,7 +287,8 @@ drm_fb_destroy_gbm(struct gbm_bo *bo, void *data) { struct drm_fb *fb = data; - assert(fb->type == BUFFER_GBM_SURFACE || fb->type == BUFFER_CLIENT); + assert(fb->type == BUFFER_GBM_SURFACE || fb->type == BUFFER_CLIENT || + fb->type == BUFFER_CURSOR); drm_fb_destroy(fb); } @@ -493,6 +496,7 @@ drm_fb_unref(struct drm_fb *fb) case BUFFER_PIXMAN_DUMB: drm_fb_destroy_dumb(fb); break; + case BUFFER_CURSOR: case BUFFER_CLIENT: gbm_bo_destroy(fb->bo); break; @@ -1281,7 +1285,7 @@ drm_output_set_cursor(struct drm_output *output) pixman_region32_fini(>cursor_plane.damage); pixman_region32_init(>cursor_plane.damage); output->current_cursor ^= 1; - bo = output->gbm_cursor_bo[output->current_cursor]; + bo = output->gbm_cursor_fb[output->current_cursor]->bo; cursor_bo_update(b, bo, ev); handle = gbm_bo_get_handle(bo).s32; @@ -1867,6 +1871,48 @@ find_crtc_for_connector(struct drm_backend *b, return -1; } +static void drm_output_fini_cursor_egl(struct drm_output *output) +{ + unsigned int i; + + for (i = 0; i < ARRAY_LENGTH(output->gbm_cursor_fb); i++) { + drm_fb_unref(output->gbm_cursor_fb[i]); + output->gbm_cursor_fb[i] = NULL; + } +} + +static int +drm_output_init_cursor_egl(struct drm_output *output, struct drm_backend *b) +{ + unsigned int i; + + for (i = 0; i < ARRAY_LENGTH(output->gbm_cursor_fb); i++) { + struct gbm_bo *bo; + + bo = gbm_bo_create(b->gbm, b->cursor_width, b->cursor_height, + GBM_FORMAT_ARGB, + GBM_BO_USE_CURSOR | GBM_BO_USE_WRITE); + if (!bo) + goto err; + + output->gbm_cursor_fb[i] = + drm_fb_get_from_bo(bo, b, GBM_FORMAT_ARGB, + BUFFER_CURSOR); + if (!output->gbm_cursor_fb[i]) { + gbm_bo_destroy(bo); + goto err; + } + } + + return 0; + +err: + weston_log("cursor buffers unavailable, using gl cursors\n"); + b->cursors_are_broken = 1; + drm_output_fini_cursor_egl(output); + return -1; +} + /* Init output state that depends on gl or gbm */ static int drm_output_init_egl(struct drm_output *output, struct drm_backend *b) @@ -1875,7 +1921,7 @@ drm_output_init_egl(struct drm_output *output, struct drm_backend *b) output->gbm_format, fallback_format_for(output->gbm_format), }; - int i, flags, n_formats = 1; + int n_formats = 1; output->gbm_surface = gbm_surface_create(b->gbm, output->base.current_mode->width, @@ -1901,21 +1947,7 @@ drm_output_init_egl(struct drm_output *output, struct drm_backend *b) return -1; } - flags = GBM_BO_USE_CURSOR | GBM_BO_USE_WRITE; - - for (i = 0; i < 2; i++) { - if (output->gbm_cursor_bo[i]) - continue; - - output->gbm_cursor_bo[i] = - gbm_bo_create(b->gbm, b->cursor_width, b->cursor_height, - GBM_FORMAT_ARGB, flags); - } - - if (output->gbm_cursor_bo[0] == NULL || output->gbm_cursor_bo[1] == NULL) { - weston_log("cursor buffers unavailable, using gl cursors\n"); - b->cursors_are_broken = 1; - } +
[PATCH weston 23/68] compositor-drm: Reshuffle drm_output_render
Call drm_output_render unconditionally, doing an early exit if we're already rendering a client buffer on the primary plane, and asserting for damage on the way out. Differential Revision: https://phabricator.freedesktop.org/D1494 Signed-off-by: Daniel Stone--- libweston/compositor-drm.c | 8 ++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/libweston/compositor-drm.c b/libweston/compositor-drm.c index 8071737..08634cd 100644 --- a/libweston/compositor-drm.c +++ b/libweston/compositor-drm.c @@ -672,6 +672,11 @@ drm_output_render(struct drm_output *output, pixman_region32_t *damage) struct weston_compositor *c = output->base.compositor; struct drm_backend *b = to_drm_backend(c); + /* If we already have a client buffer promoted to scanout, then we don't +* want to render. */ + if (output->fb_pending) + return; + if (b->use_pixman) drm_output_render_pixman(output, damage); else @@ -742,8 +747,7 @@ drm_output_repaint(struct weston_output *output_base, if (output->disable_pending || output->destroy_pending) return -1; - if (!output->fb_pending) - drm_output_render(output, damage); + drm_output_render(output, damage); if (!output->fb_pending) return -1; -- 2.9.3 ___ wayland-devel mailing list wayland-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/wayland-devel
[PATCH weston 17/68] compositor-drm: Refactor destroy drm_fb function
From: Tomohito EsakiThe drm_fb destroy callback to mostly the same thing regardless of whether the buffer is a dumb buffer or gbm buffer. This patch refactors the common parts into a new function that can be called for both cases. [daniels: Rebased on top of fb->fd changes, cosmetic changes.] Differential Revision: https://phabricator.freedesktop.org/D1489 Signed-off-by: Tomohito Esaki Signed-off-by: Daniel Stone --- libweston/compositor-drm.c | 61 +++--- 1 file changed, 30 insertions(+), 31 deletions(-) diff --git a/libweston/compositor-drm.c b/libweston/compositor-drm.c index af43a15..7dbfc6b 100644 --- a/libweston/compositor-drm.c +++ b/libweston/compositor-drm.c @@ -251,16 +251,39 @@ drm_sprite_crtc_supported(struct drm_output *output, struct drm_sprite *sprite) } static void -drm_fb_destroy_callback(struct gbm_bo *bo, void *data) +drm_fb_destroy(struct drm_fb *fb) { - struct drm_fb *fb = data; + drmModeRmFB(fb->fd, fb->fb_id); + weston_buffer_reference(>buffer_ref, NULL); + free(fb); +} + +static void +drm_fb_destroy_dumb(struct drm_fb *fb) +{ + struct drm_mode_destroy_dumb destroy_arg; - if (fb->fb_id) - drmModeRmFB(fb->fd, fb->fb_id); + if (!fb) + return; - weston_buffer_reference(>buffer_ref, NULL); + assert(fb->type == BUFFER_PIXMAN_DUMB); + + munmap(fb->map, fb->size); + + memset(_arg, 0, sizeof(destroy_arg)); + destroy_arg.handle = fb->handle; + drmIoctl(fb->fd, DRM_IOCTL_MODE_DESTROY_DUMB, _arg); + + drm_fb_destroy(fb); +} + +static void +drm_fb_destroy_gbm(struct gbm_bo *bo, void *data) +{ + struct drm_fb *fb = data; - free(data); + assert(fb->type == BUFFER_GBM_SURFACE || fb->type == BUFFER_CLIENT); + drm_fb_destroy(fb); } static struct drm_fb * @@ -359,30 +382,6 @@ err_fb: return NULL; } -static void -drm_fb_destroy_dumb(struct drm_fb *fb) -{ - struct drm_mode_destroy_dumb destroy_arg; - - assert(fb->type == BUFFER_PIXMAN_DUMB); - - if (!fb->map) - return; - - if (fb->fb_id) - drmModeRmFB(fb->fd, fb->fb_id); - - weston_buffer_reference(>buffer_ref, NULL); - - munmap(fb->map, fb->size); - - memset(_arg, 0, sizeof(destroy_arg)); - destroy_arg.handle = fb->handle; - drmIoctl(fb->fd, DRM_IOCTL_MODE_DESTROY_DUMB, _arg); - - free(fb); -} - static struct drm_fb * drm_fb_get_from_bo(struct gbm_bo *bo, struct drm_backend *backend, uint32_t format, enum drm_fb_type type) @@ -450,7 +449,7 @@ drm_fb_get_from_bo(struct gbm_bo *bo, struct drm_backend *backend, goto err_free; } - gbm_bo_set_user_data(bo, fb, drm_fb_destroy_callback); + gbm_bo_set_user_data(bo, fb, drm_fb_destroy_gbm); return fb; -- 2.9.3 ___ wayland-devel mailing list wayland-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/wayland-devel
[PATCH weston 28/68] compositor-drm: Rename drm_sprite to drm_plane
We make the differentiation where planes are an abstract framebuffer with a position within a CRTC/output, and sprites are special cases of planes that are neither the primary (base/framebuffer) nor cursor plane. drm_sprite, OTOH, contains nothing that's actually specific to sprites, and we end up duplicating a lot of code to deal with them, especially when we come to use an entirely plane-based interface with atomic modesetting. Rename drm_sprite to drm_plane, to reflect that it's actually generic. No functional changes. Signed-off-by: Daniel StoneReviewed-by: Pekka Paalanen Reviewed-by: Quentin Glidic Differential Revision: https://phabricator.freedesktop.org/D1408 --- libweston/compositor-drm.c | 187 - 1 file changed, 98 insertions(+), 89 deletions(-) diff --git a/libweston/compositor-drm.c b/libweston/compositor-drm.c index bd6170a..1b123b5 100644 --- a/libweston/compositor-drm.c +++ b/libweston/compositor-drm.c @@ -164,6 +164,42 @@ struct drm_edid { char serial_number[13]; }; +/** + * A plane represents one buffer, positioned within a CRTC, and stacked + * relative to other planes on the same CRTC. + * + * Each CRTC has a 'primary plane', which use used to display the classic + * framebuffer contents, as accessed through the legacy drmModeSetCrtc + * call (which combines setting the CRTC's actual physical mode, and the + * properties of the primary plane). + * + * The cursor plane also has its own alternate legacy API. + * + * Other planes are used opportunistically to display content we do not + * wish to blit into the primary plane. These non-primary/cursor planes + * are referred to as 'sprites'. + */ +struct drm_plane { + struct wl_list link; + + struct weston_plane base; + + struct drm_fb *fb_current, *fb_pending, *fb_last; + struct drm_output *output; + struct drm_backend *backend; + + uint32_t possible_crtcs; + uint32_t plane_id; + uint32_t count_formats; + + int32_t src_x, src_y; + uint32_t src_w, src_h; + uint32_t dest_x, dest_y; + uint32_t dest_w, dest_h; + + uint32_t formats[]; +}; + struct drm_output { struct weston_output base; drmModeConnector *connector; @@ -202,31 +238,6 @@ struct drm_output { struct wl_listener recorder_frame_listener; }; -/* - * An output has a primary display plane plus zero or more sprites for - * blending display contents. - */ -struct drm_sprite { - struct wl_list link; - - struct weston_plane plane; - - struct drm_fb *fb_current, *fb_pending, *fb_last; - struct drm_output *output; - struct drm_backend *backend; - - uint32_t possible_crtcs; - uint32_t plane_id; - uint32_t count_formats; - - int32_t src_x, src_y; - uint32_t src_w, src_h; - uint32_t dest_x, dest_y; - uint32_t dest_w, dest_h; - - uint32_t formats[]; -}; - static struct gl_renderer_interface *gl_renderer; static const char default_seat[] = "seat0"; @@ -250,9 +261,9 @@ static void drm_output_update_msc(struct drm_output *output, unsigned int seq); static int -drm_sprite_crtc_supported(struct drm_output *output, struct drm_sprite *sprite) +drm_plane_crtc_supported(struct drm_output *output, struct drm_plane *plane) { - return !!(sprite->possible_crtcs & (1 << output->pipe)); + return !!(plane->possible_crtcs & (1 << output->pipe)); } static void @@ -748,7 +759,7 @@ drm_output_repaint(struct weston_output *output_base, struct drm_output *output = to_drm_output(output_base); struct drm_backend *backend = to_drm_backend(output->base.compositor); - struct drm_sprite *s; + struct drm_plane *s; struct drm_mode *mode; int ret = 0; @@ -801,10 +812,8 @@ drm_output_repaint(struct weston_output *output_base, .request.sequence = 1, }; - /* XXX: Set output much earlier, so we don't attempt to place -* planes on entirely the wrong output. */ if ((!s->fb_current && !s->fb_pending) || - !drm_sprite_crtc_supported(output, s)) + !drm_plane_crtc_supported(output, s)) continue; if (s->fb_pending && !backend->sprites_hidden) @@ -944,7 +953,7 @@ static void vblank_handler(int fd, unsigned int frame, unsigned int sec, unsigned int usec, void *data) { - struct drm_sprite *s = (struct drm_sprite *)data; + struct drm_plane *s = (struct drm_plane *)data; struct drm_output *output = s->output; struct timespec ts; uint32_t flags = WP_PRESENTATION_FEEDBACK_KIND_HW_COMPLETION | @@ -1003,7 +1012,7 @@ page_flip_handler(int fd, unsigned int frame, } static uint32_t
[PATCH weston 12/68] compositor-drm: Use fb->fd consistently
Everyone else uses fb->fd rather than pulling the FD back out of GBM. Use that in the destroy callback too. Signed-off-by: Daniel StoneDifferential Revision: https://phabricator.freedesktop.org/D1406 --- libweston/compositor-drm.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/libweston/compositor-drm.c b/libweston/compositor-drm.c index 3276ed0..a9bde0c 100644 --- a/libweston/compositor-drm.c +++ b/libweston/compositor-drm.c @@ -243,10 +243,9 @@ static void drm_fb_destroy_callback(struct gbm_bo *bo, void *data) { struct drm_fb *fb = data; - struct gbm_device *gbm = gbm_bo_get_device(bo); if (fb->fb_id) - drmModeRmFB(gbm_device_get_fd(gbm), fb->fb_id); + drmModeRmFB(fb->fd, fb->fb_id); weston_buffer_reference(>buffer_ref, NULL); -- 2.9.3 ___ wayland-devel mailing list wayland-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/wayland-devel
[PATCH weston 13/68] compositor-drm: Use signed int for width/height
This makes it sign-compatible with weston_output->{width,height}. Differential Revision: https://phabricator.freedesktop.org/D1486 Signed-off-by: Daniel StoneReviewed-by: Quentin Glidic --- libweston/compositor-drm.c | 11 ++- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/libweston/compositor-drm.c b/libweston/compositor-drm.c index a9bde0c..a5052b9 100644 --- a/libweston/compositor-drm.c +++ b/libweston/compositor-drm.c @@ -104,8 +104,8 @@ struct drm_backend { * due to out of bounds dimensions, and then mistakenly set * sprites_are_broken: */ - uint32_t min_width, max_width; - uint32_t min_height, max_height; + int min_width, max_width; + int min_height, max_height; int no_addfb2; struct wl_list sprite_list; @@ -253,7 +253,7 @@ drm_fb_destroy_callback(struct gbm_bo *bo, void *data) } static struct drm_fb * -drm_fb_create_dumb(struct drm_backend *b, unsigned width, unsigned height, +drm_fb_create_dumb(struct drm_backend *b, int width, int height, uint32_t format) { struct drm_fb *fb; @@ -371,7 +371,7 @@ drm_fb_get_from_bo(struct gbm_bo *bo, struct drm_backend *backend, uint32_t format) { struct drm_fb *fb = gbm_bo_get_user_data(bo); - uint32_t width, height; + int width, height; uint32_t handles[4] = { 0 }, pitches[4] = { 0 }, offsets[4] = { 0 }; int ret; @@ -391,7 +391,8 @@ drm_fb_get_from_bo(struct gbm_bo *bo, fb->size = fb->stride * height; fb->fd = backend->drm.fd; - if (backend->min_width > width || width > backend->max_width || + if (backend->min_width > width || + width > backend->max_width || backend->min_height > height || height > backend->max_height) { weston_log("bo geometry out of bounds\n"); -- 2.9.3 ___ wayland-devel mailing list wayland-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/wayland-devel
[PATCH weston 02/68] meson: pixel-formats
Differential Revision: https://phabricator.freedesktop.org/D1512 --- libweston/meson.build | 1 + 1 file changed, 1 insertion(+) diff --git a/libweston/meson.build b/libweston/meson.build index d396c00..aee444a 100644 --- a/libweston/meson.build +++ b/libweston/meson.build @@ -19,6 +19,7 @@ srcs_libweston = [ 'noop-renderer.c', 'pixman-renderer.c', 'linux-dmabuf.c', + 'pixel-formats.c', 'screenshooter.c', '../shared/file-util.c', '../shared/matrix.c', -- 2.9.3 ___ wayland-devel mailing list wayland-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/wayland-devel
[PATCH weston 09/68] compositor-drm: Reshuffle and comment plane conditions
Try to harmonise the various plane-import paths a little bit, starting with reshuffling and commenting the conditions to do so. Signed-off-by: Daniel StoneDifferential Revision: https://phabricator.freedesktop.org/D1413 --- libweston/compositor-drm.c | 79 -- 1 file changed, 48 insertions(+), 31 deletions(-) diff --git a/libweston/compositor-drm.c b/libweston/compositor-drm.c index 5fb45b4..8cd9d5a 100644 --- a/libweston/compositor-drm.c +++ b/libweston/compositor-drm.c @@ -502,18 +502,28 @@ drm_output_prepare_scanout_view(struct drm_output *output, struct gbm_bo *bo; uint32_t format; - if (ev->geometry.x != output->base.x || - ev->geometry.y != output->base.y || - buffer == NULL || b->gbm == NULL || - buffer->width != output->base.current_mode->width || - buffer->height != output->base.current_mode->height || - output->base.transform != viewport->buffer.transform || - ev->transform.enabled) + /* We use GBM to import buffers. */ + if (b->gbm == NULL) + return NULL; + + if (buffer == NULL) return NULL; + /* Make sure our view is exactly compatible with the output. */ + if (ev->geometry.x != output->base.x || + ev->geometry.y != output->base.y) + return NULL; + if (ev->transform.enabled) + return NULL; if (ev->geometry.scissor_enabled) return NULL; + if (buffer->width != output->base.current_mode->width || + buffer->height != output->base.current_mode->height) + return NULL; + if (viewport->buffer.transform != output->base.transform) + return NULL; + bo = gbm_bo_import(b->gbm, GBM_BO_IMPORT_WL_BUFFER, buffer->resource, GBM_BO_USE_SCANOUT); @@ -950,34 +960,33 @@ drm_output_prepare_overlay_view(struct drm_output *output, uint32_t format; wl_fixed_t sx1, sy1, sx2, sy2; - if (b->gbm == NULL) - return NULL; - - if (viewport->buffer.transform != output->base.transform) - return NULL; - - if (viewport->buffer.scale != output->base.current_scale) - return NULL; - if (b->sprites_are_broken) return NULL; + /* Don't import buffers which span multiple outputs. */ if (ev->output_mask != (1u << output->base.id)) return NULL; - if (ev->surface->buffer_ref.buffer == NULL) + /* We can only import GBM buffers. */ + if (b->gbm == NULL) return NULL; - buffer_resource = ev->surface->buffer_ref.buffer->resource; - if (ev->alpha != 1.0f) + if (ev->surface->buffer_ref.buffer == NULL) return NULL; - + buffer_resource = ev->surface->buffer_ref.buffer->resource; if (wl_shm_buffer_get(buffer_resource)) return NULL; + if (viewport->buffer.transform != output->base.transform) + return NULL; + if (viewport->buffer.scale != output->base.current_scale) + return NULL; if (!drm_view_transform_supported(ev)) return NULL; + if (ev->alpha != 1.0f) + return NULL; + wl_list_for_each(s, >sprite_list, link) { if (!drm_sprite_crtc_supported(output, s)) continue; @@ -1114,23 +1123,20 @@ drm_output_prepare_cursor_view(struct drm_output *output, struct weston_buffer_viewport *viewport = >surface->buffer_viewport; struct wl_shm_buffer *shmbuf; - if (ev->transform.enabled && - (ev->transform.matrix.type > WESTON_MATRIX_TRANSFORM_TRANSLATE)) - return NULL; - if (b->gbm == NULL) - return NULL; - if (output->base.transform != WL_OUTPUT_TRANSFORM_NORMAL) - return NULL; - if (viewport->buffer.scale != output->base.current_scale) + if (b->cursors_are_broken) return NULL; + if (output->cursor_view) return NULL; + + /* Don't import buffers which span multiple outputs. */ if (ev->output_mask != (1u << output->base.id)) return NULL; - if (b->cursors_are_broken) - return NULL; - if (ev->geometry.scissor_enabled) + + /* We use GBM to import SHM buffers. */ + if (b->gbm == NULL) return NULL; + if (ev->surface->buffer_ref.buffer == NULL) return NULL; shmbuf = wl_shm_buffer_get(ev->surface->buffer_ref.buffer->resource); @@ -1138,6 +1144,17 @@ drm_output_prepare_cursor_view(struct drm_output *output, return NULL; if (wl_shm_buffer_get_format(shmbuf) != WL_SHM_FORMAT_ARGB) return NULL; + + if (output->base.transform !=
[PATCH weston 05/68] compositor-drm: Remove open-coded weston_compositor_wake
This always changes the state to ACTIVE when we enter the session, whereas the previous implementation preserved the state (i.e. if state was SLEEPING on exit, it would be restored to SLEEPING, but also with a repaint). This seems more helpful behaviour, however: if you enter a session, it's probably in order to interact with it. Differential Revision: https://phabricator.freedesktop.org/D1482 Signed-off-by: Daniel StoneReviewed-by: Quentin Glidic --- libweston/compositor-drm.c | 7 +-- 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/libweston/compositor-drm.c b/libweston/compositor-drm.c index 7d1c01b..d577c05 100644 --- a/libweston/compositor-drm.c +++ b/libweston/compositor-drm.c @@ -116,8 +116,6 @@ struct drm_backend { int use_pixman; - uint32_t prev_state; - struct udev_input input; int32_t cursor_width; @@ -2833,14 +2831,13 @@ session_notify(struct wl_listener *listener, void *data) if (compositor->session_active) { weston_log("activating session\n"); - compositor->state = b->prev_state; + weston_compositor_wake(compositor); weston_compositor_damage_all(compositor); udev_input_enable(>input); } else { weston_log("deactivating session\n"); udev_input_disable(>input); - b->prev_state = compositor->state; weston_compositor_offscreen(compositor); /* If we have a repaint scheduled (either from a @@ -3197,8 +3194,6 @@ drm_backend_create(struct weston_compositor *compositor, b->base.destroy = drm_destroy; b->base.restore = drm_restore; - b->prev_state = WESTON_COMPOSITOR_ACTIVE; - weston_setup_vt_switch_bindings(compositor); wl_list_init(>sprite_list); -- 2.9.3 ___ wayland-devel mailing list wayland-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/wayland-devel
[PATCH weston 08/68] compositor-drm: Extract EGL destroy to helper
No functional change. Differential Revision: https://phabricator.freedesktop.org/D1484 Signed-off-by: Daniel Stone--- libweston/compositor-drm.c | 26 +++--- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/libweston/compositor-drm.c b/libweston/compositor-drm.c index 2d5faa0..5fb45b4 100644 --- a/libweston/compositor-drm.c +++ b/libweston/compositor-drm.c @@ -1322,9 +1322,6 @@ drm_assign_planes(struct weston_output *output_base) pixman_region32_fini(); } -static void -drm_output_fini_pixman(struct drm_output *output); - /** * Find the closest-matching mode for a given target * @@ -1363,8 +1360,12 @@ choose_mode (struct drm_output *output, struct weston_mode *target_mode) static int drm_output_init_egl(struct drm_output *output, struct drm_backend *b); +static void +drm_output_fini_egl(struct drm_output *output); static int drm_output_init_pixman(struct drm_output *output, struct drm_backend *b); +static void +drm_output_fini_pixman(struct drm_output *output); static int drm_output_switch_mode(struct weston_output *output_base, struct weston_mode *mode) @@ -1414,9 +1415,7 @@ drm_output_switch_mode(struct weston_output *output_base, struct weston_mode *mo return -1; } } else { - gl_renderer->output_destroy(>base); - gbm_surface_destroy(output->gbm_surface); - + drm_output_fini_egl(output); if (drm_output_init_egl(output, b) < 0) { weston_log("failed to init output egl state with " "new mode"); @@ -1853,6 +1852,13 @@ drm_output_init_egl(struct drm_output *output, struct drm_backend *b) return 0; } +static void +drm_output_fini_egl(struct drm_output *output) +{ + gl_renderer->output_destroy(>base); + gbm_surface_destroy(output->gbm_surface); +} + static int drm_output_init_pixman(struct drm_output *output, struct drm_backend *b) { @@ -2423,12 +2429,10 @@ drm_output_deinit(struct weston_output *base) struct drm_output *output = to_drm_output(base); struct drm_backend *b = to_drm_backend(base->compositor); - if (b->use_pixman) { + if (b->use_pixman) drm_output_fini_pixman(output); - } else { - gl_renderer->output_destroy(>base); - gbm_surface_destroy(output->gbm_surface); - } + else + drm_output_fini_egl(output); weston_plane_release(>fb_plane); weston_plane_release(>cursor_plane); -- 2.9.3 ___ wayland-devel mailing list wayland-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/wayland-devel
[PATCH weston 04/68] compositor-drm: Delete drm_backend_set_modes
Even if we do have a framebuffer matching the mode, we immediately schedule a repaint, meaning we either do work for no reason, or show stale content before we bring up the new content. Delete this and just let repaint deal with it. Differential Revision: https://phabricator.freedesktop.org/D1481 Signed-off-by: Daniel Stone--- libweston/compositor-drm.c | 33 - 1 file changed, 33 deletions(-) diff --git a/libweston/compositor-drm.c b/libweston/compositor-drm.c index 268117d..7d1c01b 100644 --- a/libweston/compositor-drm.c +++ b/libweston/compositor-drm.c @@ -2824,38 +2824,6 @@ drm_destroy(struct weston_compositor *ec) } static void -drm_backend_set_modes(struct drm_backend *backend) -{ - struct drm_output *output; - struct drm_mode *drm_mode; - int ret; - - wl_list_for_each(output, >compositor->output_list, base.link) { - if (!output->current) { - /* If something that would cause the output to -* switch mode happened while in another vt, we -* might not have a current drm_fb. In that case, -* schedule a repaint and let drm_output_repaint -* handle setting the mode. */ - weston_output_schedule_repaint(>base); - continue; - } - - drm_mode = (struct drm_mode *) output->base.current_mode; - ret = drmModeSetCrtc(backend->drm.fd, output->crtc_id, -output->current->fb_id, 0, 0, ->connector_id, 1, -_mode->mode_info); - if (ret < 0) { - weston_log( - "failed to set mode %dx%d for output at %d,%d: %m\n", - drm_mode->base.width, drm_mode->base.height, - output->base.x, output->base.y); - } - } -} - -static void session_notify(struct wl_listener *listener, void *data) { struct weston_compositor *compositor = data; @@ -2866,7 +2834,6 @@ session_notify(struct wl_listener *listener, void *data) if (compositor->session_active) { weston_log("activating session\n"); compositor->state = b->prev_state; - drm_backend_set_modes(b); weston_compositor_damage_all(compositor); udev_input_enable(>input); } else { -- 2.9.3 ___ wayland-devel mailing list wayland-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/wayland-devel
[PATCH weston 03/68] compositor-drm: Comment struct members
Clarify the difference between crtc_id (DRM object) and pipe (index into drmModeRes->crtcs array, possible_crtcs bitmask). Signed-off-by: Daniel StoneReviewed-by: Quentin Glidic Differential Revision: https://phabricator.freedesktop.org/D1405 --- libweston/compositor-drm.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libweston/compositor-drm.c b/libweston/compositor-drm.c index a899213..268117d 100644 --- a/libweston/compositor-drm.c +++ b/libweston/compositor-drm.c @@ -155,8 +155,8 @@ struct drm_output { struct weston_output base; drmModeConnector *connector; - uint32_t crtc_id; - int pipe; + uint32_t crtc_id; /* object ID to pass to DRM functions */ + int pipe; /* index of CRTC in resource array / bitmasks */ uint32_t connector_id; drmModeCrtcPtr original_crtc; struct drm_edid edid; -- 2.9.3 ___ wayland-devel mailing list wayland-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/wayland-devel
[PATCH weston v2 0/68] Atomic modesetting, planes, extended drm_fb
Hi all, This is v2 of the atomic patchset, which incorporates quite a few fixups on the original code, and extends it far enough to flip sprites_are_broken off for atomic. \o/ Compared to earlier versions, drm_output_state is introduced much earlier, and everything hangs off this. This made a lot of things much more clean than they used to be. Most of the patches before this are relatively untouched, but for bugfixes. The pixel-format helpers patch is new, after I got frustrated at having to write yet another table of formats with validation. I'm fully intending to convert gl-renderer over to using this for its SHM upload path, but on the other hand I didn't want to tie that together with this series; it's big enough as it is. (Similarly, for multi-output you'll need the 'Assign new views to the primary plane' patch I sent out earlier, separately.) On top of the code from v1, which is primarily concerned with how we apply state, v2 attacks how we _generate_ the state in the first place. The major difference is the whittling down of the prepare_*_view() functions into common helpers, and then cleaving assign_planes() in two. Doing the latter allows us to actually reasonably do atomic TEST_ONLY. First we try to construct a view made entirely out of planes and nothing else; if this succeeds, we just use that and we don't need to render anything. Failing that, we try to incrementally build a state, trying one view at a time on one plane at a time, and seeing if that changes anything. Doing this is what lets us flip sprites_are_broken, because we can not only generate an optimal configuration, but make sure it'll actually work when we do it. Included in with this is a set of patches which let us import more exotic buffers: primarily multi-planar, and with buffers. The earlier work means that this is now generalised, and we can use them for scanout, overlay, or anything really. After this, a set of optimisation patches to ignore views which aren't on other outputs and occluded views. This prevents us from triggering spurious repaints on multi-head systems. At the end of this, on my multihead setup, I was able to set up one fullscreen (but scaled, due to HiDPI) and one non-fullscreen view above it. With nothing else on screen, these were promoted to planes (scanout and overlay, respectively), and no rendering was done. When something was moved on top of them, they moved back to GPU composition where necessary. Any review or testing would be appreciated; I have no idea when 1.13 is supposed to be (in 11 days ...?), so I assume it won't land for then, but I'd like to get this in as early as possible for the 1.14 cycle, so we can iron out as many of the bugs as possible. Many thanks to Fabien DESSENNE for testing and fixes, Tomohito Esaki for the dmabuf-without-GBM patch, Derek Foreman and others for things like cursor clipping (already fixed, but the reports were nice). And of course, I somehow forgot to mention in my original mail - to Pekka Paalanen, Louis-Francis Ratté-Boulianne and Derek Foreman, who worked on much earlier iterations of atomic support. Cheers, Daniel ___ wayland-devel mailing list wayland-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/wayland-devel
Re: [PATCH weston] compositor: Assign new views to the primary plane
Hi, On 9 December 2016 at 16:35, Daniel Stonewrote: > However, this is undesirable for DRM. In a multi-output situation, > we would see a view only visible on another output, reasonably decide we > didn't want it in a plane on our output, and move it to the primary > plane, causing damage, and an output repaint. The plane wouldn't be > assigned until the other output ran through repaint. > > For large SHM buffers (weston_surface->keep_buffer as false), this means > that the other output would assign it to a plane later, which caused > weston_surface_damage to be called - in the exact way the comment says > it shouldn't - which triggered a flush and buffer upload. By this stage, > the buffer content would be gone and we would upload garbage. Er, I can't English this afternoon. Imagine the above two paragraphs never happened, and mentally replace them with: However, this is undesirable for DRM. With multi-output, when assign_planes() is called, any view which wasn't on a plane for our putput was moved to the primary plane, thus causing damage, and an output repaint. Fixing this, to ignore views which do not touch our output at all, means that the view wouldn't have a plane assigned until the other output eventually ran through repaint. For large SHM buffers (weston_surface->keep_buffer == false), this means that by the time the other output assigned it to a plane, the buffer may have been discarded on the client side. Cheers, Daniel ___ wayland-devel mailing list wayland-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/wayland-devel
[PATCH weston] compositor: Assign new views to the primary plane
When we create a new view, assign it to the primary plane from the beginning. This made no difference before, since the next surface repaint would forcibly assign all views to a plane, either through DRM's assign_planes() hook, or the fallback inside core repaint. However, this is undesirable for DRM. In a multi-output situation, we would see a view only visible on another output, reasonably decide we didn't want it in a plane on our output, and move it to the primary plane, causing damage, and an output repaint. The plane wouldn't be assigned until the other output ran through repaint. For large SHM buffers (weston_surface->keep_buffer as false), this means that the other output would assign it to a plane later, which caused weston_surface_damage to be called - in the exact way the comment says it shouldn't - which triggered a flush and buffer upload. By this stage, the buffer content would be gone and we would upload garbage. Avoid this problem for now by assigning the view to the primary plane on creation, thus short-circuiting weston_view_move_to_plane when we do call it during output repaint. This is arguably the right thing to do if definitely the wrong way to fix it, but the atomic series is long enough for now. Signed-off-by: Daniel StoneCc: Pekka Paalanen --- libweston/compositor.c | 1 + 1 file changed, 1 insertion(+) diff --git a/libweston/compositor.c b/libweston/compositor.c index 6a69394..895a040 100644 --- a/libweston/compositor.c +++ b/libweston/compositor.c @@ -269,6 +269,7 @@ weston_view_create(struct weston_surface *surface) return NULL; view->surface = surface; + view->plane = >compositor->primary_plane; /* Assign to surface */ wl_list_insert(>views, >surface_link); -- 2.9.3 ___ wayland-devel mailing list wayland-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/wayland-devel
Re: [PATCH wayland v2] wayland-server: abort instead of posting events with wrong client objects
On 09/12/16 08:51 AM, Giulio Camuffo wrote: 2016-12-08 20:36 GMT+01:00 Derek Foreman: Check that all the objects in an event belong to the same client as the resource posting it. This prevents a compositor from accidentally mixing client objects and posting an event that causes a client to kill itself. It's intended that the compositor killing itself be easier to debug than the client killing itself for something that it's completely innocent of. It may be easier, but as an user the compositor crashing is a highly disruptive event, and i think we should strive to avoid it at all times. By all means, log the problem, get a backtrace and print it, maybe, but i don't agree with the abort(). Unless the problem really is unrecoverable, but it seems this is not the case. If it was an assert(0) it may be better, but i'm not sure i'd like that either. Yeah, Pekka and I have been discussing that further on-list (and off). At this point I'm thinking it should just wl_log(), and drop the client the same way nullable violation does. I wouldn't mind a conditional assert on WAYLAND_DEBUG=server or such... I'm also wondering if other aborts() that happen in wl_closure_marshal() should be reconsidered... I think perhaps they were added with client side in mind, without paying attention to the fact that wl_closure_marshal() is called from both client and server. Thanks, Derek Cheers, Giulio Signed-off-by: Derek Foreman --- Changes since v1: uses get_next_arguments and arg_count_for_signature in the normal fashion abort instead of assert This does not address Pekka's request for a new_id test, as it's not immediately clear to me how to write it. src/wayland-server.c | 29 + 1 file changed, 29 insertions(+) diff --git a/src/wayland-server.c b/src/wayland-server.c index 9d7d9c1..429dbef 100644 --- a/src/wayland-server.c +++ b/src/wayland-server.c @@ -160,6 +160,33 @@ log_closure(struct wl_resource *resource, } } +static void +verify_objects(struct wl_resource *resource, uint32_t opcode, + union wl_argument *args) +{ + struct wl_object *object = >object; + const char *signature = object->interface->events[opcode].signature; + struct argument_details arg; + struct wl_resource *res; + int count, i; + + count = arg_count_for_signature(signature); + for (i = 0; i < count; i++) { + signature = get_next_argument(signature, ); + switch (arg.type) { + case 'o': + res = (struct wl_resource *) (args[i].o); + if (res && res->client != resource->client) { + wl_log("unrecoverable error: The compositor " + "tried to use an object from one " + "client in an event for a different " + "client.\n"); + abort(); + } + } + } +} + WL_EXPORT void wl_resource_post_event_array(struct wl_resource *resource, uint32_t opcode, union wl_argument *args) @@ -167,6 +194,7 @@ wl_resource_post_event_array(struct wl_resource *resource, uint32_t opcode, struct wl_closure *closure; struct wl_object *object = >object; + verify_objects(resource, opcode, args); closure = wl_closure_marshal(object, opcode, args, >interface->events[opcode]); @@ -206,6 +234,7 @@ wl_resource_queue_event_array(struct wl_resource *resource, uint32_t opcode, struct wl_closure *closure; struct wl_object *object = >object; + verify_objects(resource, opcode, args); closure = wl_closure_marshal(object, opcode, args, >interface->events[opcode]); -- 2.10.2 ___ wayland-devel mailing list wayland-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/wayland-devel ___ wayland-devel mailing list wayland-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/wayland-devel
Re: [PATCH wayland v2] wayland-server: abort instead of posting events with wrong client objects
2016-12-08 20:36 GMT+01:00 Derek Foreman: > Check that all the objects in an event belong to the same client as > the resource posting it. This prevents a compositor from accidentally > mixing client objects and posting an event that causes a client to > kill itself. > > It's intended that the compositor killing itself be easier to debug > than the client killing itself for something that it's completely > innocent of. It may be easier, but as an user the compositor crashing is a highly disruptive event, and i think we should strive to avoid it at all times. By all means, log the problem, get a backtrace and print it, maybe, but i don't agree with the abort(). Unless the problem really is unrecoverable, but it seems this is not the case. If it was an assert(0) it may be better, but i'm not sure i'd like that either. Cheers, Giulio > > Signed-off-by: Derek Foreman > --- > > Changes since v1: > uses get_next_arguments and arg_count_for_signature in the normal fashion > abort instead of assert > > > This does not address Pekka's request for a new_id test, as it's not > immediately clear to me how to write it. > > src/wayland-server.c | 29 + > 1 file changed, 29 insertions(+) > > diff --git a/src/wayland-server.c b/src/wayland-server.c > index 9d7d9c1..429dbef 100644 > --- a/src/wayland-server.c > +++ b/src/wayland-server.c > @@ -160,6 +160,33 @@ log_closure(struct wl_resource *resource, > } > } > > +static void > +verify_objects(struct wl_resource *resource, uint32_t opcode, > + union wl_argument *args) > +{ > + struct wl_object *object = >object; > + const char *signature = object->interface->events[opcode].signature; > + struct argument_details arg; > + struct wl_resource *res; > + int count, i; > + > + count = arg_count_for_signature(signature); > + for (i = 0; i < count; i++) { > + signature = get_next_argument(signature, ); > + switch (arg.type) { > + case 'o': > + res = (struct wl_resource *) (args[i].o); > + if (res && res->client != resource->client) { > + wl_log("unrecoverable error: The compositor " > + "tried to use an object from one " > + "client in an event for a different " > + "client.\n"); > + abort(); > + } > + } > + } > +} > + > WL_EXPORT void > wl_resource_post_event_array(struct wl_resource *resource, uint32_t opcode, > union wl_argument *args) > @@ -167,6 +194,7 @@ wl_resource_post_event_array(struct wl_resource > *resource, uint32_t opcode, > struct wl_closure *closure; > struct wl_object *object = >object; > > + verify_objects(resource, opcode, args); > closure = wl_closure_marshal(object, opcode, args, > >interface->events[opcode]); > > @@ -206,6 +234,7 @@ wl_resource_queue_event_array(struct wl_resource > *resource, uint32_t opcode, > struct wl_closure *closure; > struct wl_object *object = >object; > > + verify_objects(resource, opcode, args); > closure = wl_closure_marshal(object, opcode, args, > >interface->events[opcode]); > > -- > 2.10.2 > > ___ > wayland-devel mailing list > wayland-devel@lists.freedesktop.org > https://lists.freedesktop.org/mailman/listinfo/wayland-devel ___ wayland-devel mailing list wayland-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/wayland-devel
Re: [PATCH wayland v2] wayland-server: abort instead of posting events with wrong client objects
Hi Derek, > On Dec 8, 2016, at 11:36 AM, Derek Foremanwrote: > > Check that all the objects in an event belong to the same client as > the resource posting it. This prevents a compositor from accidentally > mixing client objects and posting an event that causes a client to > kill itself. > > It's intended that the compositor killing itself be easier to debug > than the client killing itself for something that it's completely > innocent of. > > Signed-off-by: Derek Foreman > --- > > Changes since v1: > uses get_next_arguments and arg_count_for_signature in the normal fashion > abort instead of assert > > > This does not address Pekka's request for a new_id test, as it's not > immediately clear to me how to write it. > > src/wayland-server.c | 29 + > 1 file changed, 29 insertions(+) > > diff --git a/src/wayland-server.c b/src/wayland-server.c > index 9d7d9c1..429dbef 100644 > --- a/src/wayland-server.c > +++ b/src/wayland-server.c > @@ -160,6 +160,33 @@ log_closure(struct wl_resource *resource, > } > } > > +static void > +verify_objects(struct wl_resource *resource, uint32_t opcode, > + union wl_argument *args) > +{ > + struct wl_object *object = >object; > + const char *signature = object->interface->events[opcode].signature; > + struct argument_details arg; > + struct wl_resource *res; I know that `res` is used throughout the source, but since there are two resources here, it might be nice to add some semantics, eg. `event_resource` or `argument_resource`. > + int count, i; > + > + count = arg_count_for_signature(signature); > + for (i = 0; i < count; i++) { > + signature = get_next_argument(signature, ); > + switch (arg.type) { > + case 'o': > + res = (struct wl_resource *) (args[i].o); > + if (res && res->client != resource->client) { > + wl_log("unrecoverable error: The compositor " > +"tried to use an object from one " > +"client in an event for a different " > +"client.\n"); > + abort(); This should probably wl_abort, right? Regards, yong > + } > + } > + } > +} > + > WL_EXPORT void > wl_resource_post_event_array(struct wl_resource *resource, uint32_t opcode, >union wl_argument *args) > @@ -167,6 +194,7 @@ wl_resource_post_event_array(struct wl_resource > *resource, uint32_t opcode, > struct wl_closure *closure; > struct wl_object *object = >object; > > + verify_objects(resource, opcode, args); > closure = wl_closure_marshal(object, opcode, args, >>interface->events[opcode]); > > @@ -206,6 +234,7 @@ wl_resource_queue_event_array(struct wl_resource > *resource, uint32_t opcode, > struct wl_closure *closure; > struct wl_object *object = >object; > > + verify_objects(resource, opcode, args); > closure = wl_closure_marshal(object, opcode, args, >>interface->events[opcode]); > > -- > 2.10.2 > > ___ > wayland-devel mailing list > wayland-devel@lists.freedesktop.org > https://lists.freedesktop.org/mailman/listinfo/wayland-devel ___ wayland-devel mailing list wayland-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/wayland-devel
Re: [RFC wayland-protocols] Color management protocol
Am Donnerstag, 8. Dezember 2016, 15:51:12 CET schrieb Graeme Gill: > Niels Ole Salscheider wrote: > > Therefore I think that the situation has changed and I'd like to propose > > this protocol for inclusion in wayland-protocols again. > > What do you think? > > Hi, > I'm prompted to look into the current state of color management > in Wayland, by Richard Hughes comment on the ArgyllCMS mailing list > > recently that: > > About this; in the near future systems will be migrating from X11 to > > Wayland (Fedora 25 already defaults to Wayland, other distros will > > follow) and so setting X atoms is no longer going to work. Even with > > XWayland (the compatibility "wrapper" that provides an isolated > > xserver for the app) you can't use the root window as it's isolated > > from the other windows. I think most applications that want to know > > what profile to use are now using either libcolord, or more commonly, > > the colord DBus API. > > What I take from this is that XWayland is lacking in its emulation > of existing X11 color management protocols (primarily due to lack > of underlying support in Wayland), and that currently the only > option for pure Wayland applications is to depend on system > specific work-arounds such as using Weston with colord. I can > therefore see that users that depend on color managed X11 applications > (such as photographers, desktop publishers, video editors etc.) > aren't going to be switching to Wayland based systems any > time soon. > > Looking through the current Wayland color-management protocol > proposal, I think it is missing a really fundamental thing - > managing the output device color calibration state and color > profile. I guess the assumption is that this is being done > by colord, but my understanding is that colord is specific > to Gnome based systems, and certainly depends on DBus, which > Wayland does not. [ Please correct me if I've got any of this wrong. ] It is (currently) up to the compositor to decide how to implement this. The compositor could come with its own settings for the output color profiles or query some other program. This might be colord, but it could also be kolormanager, or something else. > It also seems fundamentally poor design to be using a parallel > protocol to manage the color of the graphics system, rather > than it being kept in sync with the elements being managed, > such as outputs and pixel rasters, etc. Certainly in X11 it is > all kept within the X11 protocol or its extensions. > If Wayland gets extended to be a remote protocol, then > the existence of in band protocols for color management > become even more important. Yes, with the protocol I proposed there is a (small) time window after changing the output color space where the application might still display surfaces with the old color space... > So as a broad outline, what I would regard as features of > a reasonable color management facility for a graphics > system such as Wayland are: > > * That color management protocol's have two uses :- 1) configuring > color management and 2) allowing applications to use color management. > These two uses may need different security profiles. > The assumption should be that color management applications > used to create calibrations, profiles and configure the > state of color management, are of equal importance to color > managed applications that depend on a properly profiled and > configured color management system, since you can't have latter > with out the former. > > * Color management of a graphics rendering system such as Wayland > should be split into two levels (possibly two extensions) :- > > 1) Core == output device management, which involves identifying output > devices, controlling their calibration state (Video LUT), installing a > color profile resources associated with that output device, and identifying > which rendered pixels go to which output device(s). This is the most basic > requirement, since this is the bare minimum for applications to be properly > color managed. It is also a necessary resource for the second level to be > able to operate. > > 2) Enhanced == input space management, which assumes a graphics > server rendering system capable of color management. This involves > labeling an input raster with a color profile, and controlling the manner > of rendering (i.e. rendering intent, maybe blending space ? etc.) This is > useful for implementing default color management (e.g. as a means of coping > with wide gamut displays when many applications are not color aware), or as > a low developer overhead means of implementing basic color management in > non color critical applications. > > Translating these aims into a more concrete set of capabilities might > look like this: > > Core: > Get corresponding CRTC regions for a given Surface. > Get corresponding Output(s) for a CRTC. > Get unique Monitor identifier for an Output (i.e. EDID) >
Re: [RFC wayland-protocols] Color management protocol
Am Donnerstag, 8. Dezember 2016, 13:33:20 CET schrieb Graeme Gill: > Niels Ole Salscheider wrote: > > Hi, > > > The first version of my proposal had such a flag. I removed it and > > replaced it by the described version based on feedback from Zoxc > > (zox...@gmail.com). > Do you have a link to the specifics ? Most of the discussion happened on IRC back then. It should be in the logs but... > > I can see advantages with both solutions. One advantage with the current > > proposal is that you can have a surface that covers multiple screens. In > > this case the compositor can still try its best to correct the colours > > for all but the main screen. > > I'm not quite sure what you mean. Generally an application will have > specific reasons for wanting to do it's own color management - for > instance, perhaps it is previewing a CMYKOGlclm file, and wants to > treat out of gamut mapping and black point mapping in a particular way, etc. > I don't think the Wayland compositor is going to be expected to handle > CMYKOGlclm etc. input rasters, never mind all the requirements of > specialist application color management! This is of course something that the client application has to do. It would query the main output for its surface, do the conversions to that color space and then attach the output color space to the surface. The compositor now must not touch the parts of the surface on the main output (where the color spaces match). But it could still try to convert from the color space of the main output to that of a secondary screen if the surface covers two screens with different color profiles. This might of course cause artifacts when one of the screens has a too small gamut but still seems better than ignoring this. But then again most people that work with professional applications would not make them cover multiple screens, I guess. Therefore I'm not opposed to adding a flag that indicates that the application wants to disable color corrections completely for that surface, independent of the output. > Which is not to say that compositor color management doesn't have its > place - it is ideal for applications that just want to use "RGB", and > not deal with specific display behavior. Very simple applications would just keep the attached sRGB color space and maybe place images on subsurfaces with the embedded color space from the image attached. Applications that care a bit more about color correction (but do not have professional needs) could convert all their colors to the blending color space of the compositor. I'd expect this blending color space to be linear if the compositor cares about good colors. This would have the advantage that the compositor does not have to do the conversion "application output color space -> blending color space". > > Back then I argued that this might not be good enough if you want to > > calibrate the monitor. But the consent was that this would require > > another protocol to disable all colour corrections anyway and that it > > could be developed at a later point. > > I strongly disagree with this idea - disabling application-side color > management is a fundamental step in achieving end to end color management. > You don't have color management until you are able to profile the output > device, so this is not something that can be left until latter! > > Graeme Gill. > > > ___ > wayland-devel mailing list > wayland-devel@lists.freedesktop.org > https://lists.freedesktop.org/mailman/listinfo/wayland-devel ___ wayland-devel mailing list wayland-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/wayland-devel