nedjelja, 31. srpnja 2016.

Week 10: Journey to the new output configuration API


As mentioned in the last week's post, I've been trying to write an API for libweston that can be used to configure an output outside of libweston. This week I made a lot of progress. By combining code from previously failed attempts and feedback from both of my mentors, I believe I have finally written an acceptable API (at least by my standards).

So, how does it work? Current model works like this (I'll make an example with DRM and X11 backends, as those are ones I've worked with most):

The DRM backend initializes outputs present at runtime and implements output hotplug using udev. To use a DRM output, backend does a lot of magic (which I don't understand fully, to be perfectly honest). Then it calls a function that needs to be written when writing a compositor (not part of libweston), which will then obtain preferred output configuration and does some more magic to make the picture appear on your screen driven by the DRM backend.

For X11 backend, compositor (libweston user) tells how many outputs should be configured and then the backend creates a number of outputs, whose configuration is either read from the configuration file, weston command line or hardcoded defaults.

This seems to work just fine. So, why bother writing a new API for configuring those outputs? It enables compositors to enable/disable/reconfigure outputs at will, implement configuration dialogs for more fancy output configuration, etc. Another reason that's important to me is to move output layout configuration from libweston, so compositors can choose to implement whatever layout placement they want.

The new model consists of these steps:

- When an output gets plugged in (or is  "created" in case of backends such as headless, X11 or wayland), a backend creates an object representing that output, but doesn't fully initialize it like it was done before. It only initializes parts that are needed so an output can be cleanly configured or destroyed.

- A compositor is then notified that an output is created, and basic output is passed as the data which can be used to aid in configuration. At the moment, only data that's needed from the output object is its name, as the configuration is mostly done on per-output-name basis.

- Using plugin-registry, compositor calls corresponding function that's tied to the backend and tells it to configure an output using the desired configuration. Output can also be dropped, if it seems unnecessary.

This isn't much different from what DRM backend does presently: Detect an output -> Do a little magic to get the necessary data to ask for configuration -> Get its configuration from the compositor -> Configure the output. Only now, the user (libweston user) has the power to configure the output the way he sees fit. Of course, it's limited at the moment, but it can be extended, and it doesn't need to be generic or backend agonistic since it's exposed through plugin registry.

I hope I made some sense. I'm really tired and it's past midnight here. But it sure was fun working on this. So far, I've done the initial API and ported 4 backends to it: X11, fbdev, headless and DRM. Two backends remain: RDP and Wayland. I was looking at the wayland backend, but I need some more time to figure out how it really works. As for RDP, I might have a hard time there, as I don't know how to test it, given that I don't have the needed tools for it. All the code is in my git repository, which can be found at https://github.com/krezovic/weston/commits/gsoc-v6 so it's not just talk this week. I hope I can get this done in the next week and move to the final task in the remaining week of GSoC - configuring output positions.

ponedjeljak, 25. srpnja 2016.

Week 8 and 9: Nothing special

While I expected to work full time on the project as soon as summer holidays started, I didn't take into account some things. Last week, I didn't write a blog post beacuse I wasn't at home from Saturday evening to early Thursday, and also had an exam this Thursday.

Over the past two weeks, I've been trying to write an API for libweston that can be used to configure an output outside of libweston. Currently, when a backend receives an output connected signal (ie, DRM backend), it will first call the compositor defined function to receive a desired configuration for the output (if any), and then configure the output in the backend itself. Backends such as X11/Wayland/Headless have different approach. Since they don't depend on real hardware (I like to call them virtual outputs), outputs are created when the backend is started and there can't be more outputs plugged in at runtime (at the moment), but can disconnect an output in case there's more than one (closing X11 window representing an output will destroy that output).

What I was trying to do over last two weeks is (roughly written) to make the backends notify the compositor when an output gets connected, and let the compositor configure the output by calling backend specific functionality used to configure an output. And that's where it all began.

The first idea, written week before last, was to introduce a weston_pending_output structure, and initialize it with output name, default options and function pointer that can be used to configure it, and notify the compositor process that the output has been created. The compositor then would call the output configure function with choosen parameters or let the backend use defaults passed at runtime. The idea wasn't that good because the defaults were in the backend, and they shouldn't be there. I was then suggested to try using the new plugin-registry API to expose the configuration.

The second idea, similar to first, was to expose all backend functionality in the plugin registry and
let the compositor and libweston use that for manipulating the backends and options. Now, that wasn't really necessary, as that wasn't the original intended use for plugin-registry. The plugin-registry was intended to be used outside libweston for functionality that libweston can't directly provide for different reasons (different backends having different configuration options is just one example).

Even after I was explained what was plugin-registry about, I took a third approach, and still didn't get it right. The idea was still the same as the first one (backend creates the output, notifies the compositor, compositor configures it by calling backend specific function). Only this time, I reused weston_output instead of using weston_pending_output, but still exposed too much unnecessary things through the registry. I once again misunderstood the use of plugin-registry and tried to write generic configure functions for all backends that are exported through the registry. This contradicts what I've written above about plugin-registry (and I just realized that this morning when Pekka once again explained the purpose of registry to me).

This morning, we have come to a conclusion that the original idea is right, but the API still needs to be properly designed. So far, I have no code in the repository to show (I had several patches on pastebin sites shared with both of my mentors; Pekka and Quentin "SardemFF7"), but I belive all three of us finally agreed on how it should be done - so I have a task for this week. But hey, libinput api was modified several times before they got it right, so that gives me hope that I'll do the same for the task I was appointed. Stay tuned.

nedjelja, 10. srpnja 2016.

Week 7: Review feedback

I haven't spent this week working on anything new, but rather on polishing the existing patches I've written over the past two weeks.

First task that I was working on is reworking how views behave when all outputs were gone. In a post from two weeks ago, I pointed out how I got that to work back then. Now, thanks to Pekka's review, I took a different approach. Instead of forcing all views to assign an output when a first output gets plugged in after all outputs were gone, I simply mark all the views' geometry as dirty, so weston will take care of updating the transformations and assigning an output.

Second task was about reworking my patches for fullscreen shell and zero outputs scenario. Again, thanks to Pekka's feedback, I changed my patches from last week to have more code sharing, preserve the surface only when no output resource was given and implemented destroy callbacks for the preserved surface so it can be removed from preserved surfaces list once the client destroys it.

The final task for this week was working on the testing environment. While I did good amount of work last week, I lost some hours trying to integrate my work from the past week. That didn't go well and Pekka didn't like me using timers, so I threw that code aside.

With hints from Pekka and Quentin "SardemFF7", I completely reworked the testing environment and extended the testing protocol, so a client can itself control whether an output should be hotplugged or unplugged, and receive information on whether that's done. Doing this proved to be a bit harder than I expected, but I did learn how wayland protocols are written and implemented in compositor, so in the end it was totally worth it. However, the testing environment isn't yet ready. I need to fully integrate the tests in the weston-tests-env and disable/rework some tests under zero outputs scenario, so I can get acceptable results.

This went on a bit longer than I expected, but I think I can finally concentrate on second part of my GSoC proposal, which includes output position configuration using weston.ini. Pekka's tasked me with reworking big chunk of weston code, so all backends can share more code and so I can implement my task easier, instead of doing so in all the backends separately. Since Pekka's still on vacation, I'll be working with my other mentor, Quentin "SardemFF7". I really hope I can get the early prototype with at least one backend during the next week. Stay tuned.

ponedjeljak, 4. srpnja 2016.

Week 6: DRM Backend, Fullscreen Shell and a Test Suite

First of all, I want to thank the Wayland Project and my mentors, Pekka and Quentin "SardemFF7", for letting me pass the Google Midterms evaluation. That means that I'm still participating in GSoC and can continue my work.

Also, I'm proud to say that most of my work that was submitted was merged to weston master. So, if you are using weston git master, you should get working "zero outputs setup at startup" feature when using X11 backend and desktop-shell.

The past week was dedicated to ironing out remaining output hotplug and unplug at runtime issues with the things I never had the chance to touch before. That includes the DRM backend and fullscreen-shell. I've also started to prototype a test suite.

The DRM backend was easy to fix. It was already working, but had some codepaths that would make weston fail/exit when it hits zero outputs case, whether at startup or runtime. Removing those code paths fixed all the issues I've previously encountered during testing.

Fullscreen Shell was different story. A fullscreen surface was always tied to an output object and can only be created and configured when a fullscreen output object is present. And when all outputs are gone, the surface gets unmapped (because it doesn't have any more views associated to an output), and there was no way to display it again when an output gets back.

To overcome all this, I had to resort to preserving the surface manually in the shell process and remap/reconfigure it after an output gets attached, so it gets properly displayed. I'm not sure if this was the right solution, but it's the one that currently works, for both zero outputs and startup, and all outputs gone at runtime then one gets reconnected situations.

Another minor task which I've done, but haven't yet mentioned is a little more work on the gl-renderer. When using an output to draw stuff, gl-renderer makes the EGLSurface associated with an output current so all GL calls are being done on that surface. But what happens when all outputs are gone? What surface is current then? I wasn't really sure. So, to avoid any potential issues, I reused the dummy surface that was used to create a EGLContext at startup and make that surface current, so all future GL calls are using it, until an output gets attached. I want to note that I didn't notice any problems without the mentioned feature, but I still think this was the right thing to do.

And finally, the last feature I was working on last week was the testsuite. So far, I've only got the code parts finished and have yet to wire it up. But, the code changes include modifications to the headless backend to expose additional functionality, so a module can create an output and emulate output hotplug scenarion. This functionality was hidden behind a CPP define, so it doesn't always get built into the headless-backend. To avoid messing with the headless-backend which gets installed, I introduced a new, headless-testing-backend (which is headless-backend plus the mentioned functionality) which will be used for the testsuite instead of headless-backend, which is currently being used.

When that was done, two new testing modules were written; A module which emulates output hotplug in the headless backend by using the functionality previously mentioned and a module which emulates output unplug, by removing all the outputs that were present. Both modules use timers to do their job, so I had a hard time thinking how to get them wired up. I have to discuss this with someone who better understands the weston test suite.

That's all what was done this past week. This week I expect to finish the test suite integration and submit this part of my work to review and then start working on part 2 of my GSoC project. Stay tuned.