PowerVR G6430 on Linux with libhybris

Hello to everyone,

I am new to this forum and I am working on a private, non-profit project. I hope this is the right spot to place my question (and hopefully get some answers).

I am trying run Linux on the Google Nexus Player (Imagination PowerVR G6430 on an Intel Atom Z3560 CPU). I am running Linux/Kwin with EGL support via libhybris. The Android driver EGL blobs are from DDK “Rogue_DDK_Android rogueddk 1.8@” 468.8949, libpvrANDROID_WSEGL.so has BuildID[md5/uuid]=a7c0a8fdc5ab1c212efc27e3de1cd2e9

While Kwin is running smoothly and 3D effects are nicely hw accelerated, I am facing stability issues and glitches. What I think might be an issue is that calling eglMakeCurrent immediately causes the EGL implementation to dequeue a new buffer, while the window size has not been updated yet, so the buffer is ill (i.e. old) sized. I guess this is ok for Android but not for Linux where the surfaces are often resized. I have descibed my probelms here: Wayland resize issue/buffer not freed upon resize · Issue #444 · libhybris/libhybris · GitHub

Any input is highly appreciated. Thank you very much in advance, best regards and a happy new year

Hi fcipaq,

Welcome to the forums. I’ve inquired about the 1.8@4688949 driver implementation of eglMakeCurrent to confirm it is meant to function as described in your libhybris github issue. I’ll get back to you after some investigation and hopefully we can determine a client-side work around.

Kind Regards,
David

Hi David,

thank you very much for your answer, I really appreciate your effort. Looking forward to hearing from you.

Best regards

Hi fcipaq,

Your theory makes sense, eglMakeCurrent will call dequeueBuffer, and whilst the driver does call cancelBuffer in various places, they are in error paths that I don’t think will be hit in the situation you are describing.

When you changed the 2 lines in hybris/egl/platforms/wayland/wayland_window.cpp did it start working as expected?
Do you know if you can make the cancelBuffer call yourself in libhybris? And do you know where the eglMakeCurrent call for window resizing is in the libhybris source?

Kind Regards,
David

Hi David,

thank you for your answer and the input.

Changing the 2 lines in hybris/egl/platforms/wayland/wayland_window.cpp will enable resizing support from the compositor side at all. Without the changes a compositor ist not able to resize a window at all (which is fine on mobile UIs where the compositor usually does not resize windows or surfaces). I guess this is the reason no one has stumbled accross this issue before.

BUT changing these two lines also introduces the stability issues.

Now, I can call cancelBuffer (implemetation is inside libhybris itself) BUT I have found no way of informing neither the Android EGL implementation nor the wayland client about that. So basically the buffer handle is invalidated but it is still in use usually causing a segfault by the wayland client when trying to render to the buffer.

Inside libhybris eglMakeCurrent is currently just passed through to the Android EGL Implementation:

I also tried to re-call eglMakeCurrent when a resize event occurs. But to no avail - I guess the Android implemtation of eglMakeCurrent will simply return in case the context is already current.
So I probably need to make the context “uncurrent” first and make it current again? Is that an option?

tl;dr Is there a way to inform the Android EGL implentation to discard/cancel all buffers? Or better yet, is there a way of telling the Android EGL implentation the surface has been resized and the old buffers need to be discarded? In my opinion the whole problems comes down to the fact that I am using a window system on top of a window system and these two cannot communicate properly. I guess in a native wayland windowing system a call to “SetNativeWindowSize” will also discard the surface buffers and reallocate new ones.

Hi fcipaq,

Thanks for your message, we’ll review the issues you’re experiencing and come back to you shortly.

Best regards,
Alejandro

Hi, fcipaq,

From taking a look at your issue (and with no prior experience with libhybris) I suspect that the issue might be an ordering issue? I’d say that the expected order of operations would be:

  • Compositor
  • Client
  • eglMakeCurrent (which should get the current window size)
  • Client (which updates the native windows size, which I expect libhybris should then receive)

Is this your current order of operations?

I’ve also spoken to our Android and Driver teams. The suggestion I’ve received, if you haven’t tried it already, is that rather than trying to rollback the buffer dequeue which already happened, instead render for one more frame at the old resolution and when the actual surface size changes in the next frame EGL_WIDTH and EGL_HEIGHT should be updated to reflect the new sizes and theoretically everything should render correctly. You could also try and avoid doing the composition if you knew the contents were old (in this case the wrong size), the alternative is to live with the artefacts (clipped output on reduced size and cleared memory on increased size).

Kind regards,
Omar.

Hi Omar,

thank you for your answer and your suggestions. Yes, the order of operations is as described in your post:

  • The user resizes a window
  • The compositor sends this event to…
  • the client
  • Which then calls eglMakeCurrent
  • Afterwards the client updates the native window size.

Here is an example of how Firefox (84.0.2) handles the resize event:

  // If the widget size changed, we have to force a MakeCurrent
  // to make sure that GL sees the updated widget size.
  if (mWidgetSize.ToUnknownSize() != rect.Size()) {
    MakeCurrent(ForceMakeCurrent);

    mWidgetSize = LayoutDeviceIntSize::FromUnknownSize(rect.Size());
#ifdef MOZ_WAYLAND
    if (mWidget && mWidget->AsX11()) {
      mWidget->AsX11()->SetEGLNativeWindowSize(mWidgetSize);
    }
#endif
  }

The call to SetEGLNativeWindowSize eventually goes to libhybris and when this call happens - and now comes the part I do not understand - the buffer has already been dequed. But I do not understand why. I mean if you look at the Mozilla code above I do not see where a buffer could be requested. And I found no clues in the Khronos docs about eglMakeCurrent requesting/dequing any buffers.
This does not seem to be happening with other Android EGL implementations, so I thought this might be a for example and undocumented performance optimization etc. (Which might possibly be disabled/worked around.)
I really don’t mind having artifacts for one frame but some clients do not work at all with an ill sized buffer (for example Firefox) and that is a problem.

That being said, KDE has dropped support for the hwcomposer/libhybris backend. So soon this will all likely become obsolete…

Thank you again for your effort and best regards