Puttin' on the GL(itz)

Thomas Senyk thomas.senyk at nokia.com
Tue May 15 14:47:55 UTC 2012


On Tuesday, May 15, 2012 07:30:15 AM ext BogDan wrote:
> Hi Thomas,
> 
> > On Sunday, May 06, 2012 04:15:03 PM ext BogDan Vatra wrote:
> >>  Hello everyone,
> >> 
> >>    A few days ago I wrote an mail about "Qt Multimedia status on
> >> 
> >>  Android" [1], because I don't like to give up that easy, I tried
> > 
> > to
> > 
> >>  find another solution and I think I found one (at least for
> >>  android-14+). Also some people post other solutions, and I'd like to
> >>  thank them very much! Their methods can be used for older android
> >>  versions.
> >> 
> >>    At the end of that email, I complained about the fact that there is
> >> 
> >>  no fast way to read the texture from graphics memory back to the
> >>  system memory.
> >> 
> >>    After several days of reflection (and more investigations), it
> >> 
> >>  striked me another idea: to move everything in video memory, instead
> >>  to read textures from the video memory.
> >> 
> >>  Before we go further, I'd like to make some clarifications :
> >>   * in order to understand this mail, first, you must read "Qt
> >> 
> >>  Multimedia status on Android" [1] !
> >> 
> >>   * this is just a draft, the is no code behind it, so, I don't know if
> >> 
> >>  it's going to work or not, just my thoughts!
> >> 
> >>   * my OpenGL silks are near zero, any help will be very appreciated,
> >> 
> >>  also, if anyone spots any mistakes *please* reply to this mail !
> >>  
> >>  Currently Qt on Android uses two methods to draw the controls: raster
> >>  or opengl rendering.
> >>  OpenGL rendering is done using your device graphics card, it doesn't
> >>  seem to be the best solution [2],[3] to draw controls, but is good for
> >>  complex animations. It also have a big problem, currently it is
> >>  limited to a single Top Level Widget (I'll use TLW abbreviation from
> >>  now on) because Android OpenGL is limited to a single window surface
> >>  per process. Let's forget about OpenGL for now, we'll come back to
> > 
> > it
> > 
> >>  latter.
> >>  Raster rendering is done using a QImage for every TLW, is precise and
> >>  fast (if you don't have complex drawings and/or animations). So we
> >>  have a few QImage object which must be converted into gl textures,
> >>  then we can draw them to the windows surface, here I found that there
> >>  are two methods to do it, first one is to use glTex[Sub]Image* (this
> >>  one seems to be a little slow [4] on some devices, so maybe we should
> >>  avoid it ?) and another one is to use
> >>  eglCreateImageKHR/glEGLImageTargetTexture2DOES which seems much
> >>  faster, the problem with the second one is that we must use a few
> >>  non-public APIs to allocate the graphics buffer, even so, if is faster
> >>  than glTex[Sub]Image,
> > 
> > Does this mean you can get a eglImage sitting on application-space memory
> > (aka, QImage) without a copy?
> 
> No, you can't use QImage, you need to create a special graphics buffer
> http://androidxref.com/source/xref/frameworks/base/include/ui/GraphicBuffer.
> h But you can create a QImage which shares the same memory.
> 
> > Technically it's possible on a unified-memory system ... i guess ...,
> > I'm just
> > wondering because I've never seen any platform which can do that
> > (Not even a platform which wasn't caring about memory management at all
> > (e.g.
> > vxworks))
> > 
> > 
> > (fyi: I've used eglCreateImageKHR before ... it's main intention is to
> > bind
> > EGL and GL resources ... not software-resources
> >    ... but who knows ;)
> 
> I don't know if the same memory is also used by the graphics card, but this
> is the way android is doing with video and camera frames
> Here
> http://androidxref.com/source/xref/frameworks/base/opengl/tests/gl2_yuvtex/
> gl2_yuvtex.cpp#193 you can find a real example.
> 
> > .. but ok ... if that's the case: cool! That's going to have very good
> > performance!
> > 
> > 
> > But I suspect(!) you'll end up with a copy anyway ... so:
> > If there is a copy involved, it doesn't really matter where/who/how you
> > copy
> > 
> > 
> > as long as you copy junks (and not pixels) ... and glTexImage is your
> > friend here :)
> > 
> > .... it shouldn't be that big of a deal ... it's not helping the raster-
> > backend-performance ... but if you want to mix with video I guess there is
> > no way around it.
> 
> I also suspect that a copy is done, but it seems that copy is (much) faster
> than glTexImage, as I said android is using only eglCreateImageKHR for
> camera and video frames.
> 
> >>  IMHO it should not be a huge problem.
> >>  This is the way I'm planning to draw the raster images using OpenGL,
> >>  but where is Android's multimedia frame texture in this equations ?
> >>  To be able to display that texture I'm planning to add a new surface
> >>  type which will be linked to a TLW, this is the draft for the
> >>  interface:
> >>  
> >>  class QSurfaceTexture
> >>  {
> >> 
> >>     public:
> >>     virtual void paintTexture() = 0; // here the widget will draw the
> >> 
> >>  texture by itself.
> >>  }
> >>  
> >>  and I'm planning to add a few methods to QPlatformWindow, these
> >>  methods will be used to register/unregister a texture surface and to
> >>  iterate the textures.
> >>  class QPlatformWindow
> >>  {
> >>  ....
> >> 
> >>    /// this function will be used to link a new surface texture to a TLW
> >>    /// order is used to specify the drawing order,
> >>    ///  - negative values (or 0) means the texture will be draw under the
> > 
> > TLW
> > 
> >>  ///  - positive values means the texture will be draw over the TLW
> >>  virtual
> >>  void addSurfaceTexture(QSurfaceTexture *surface, int order = 0 );
> >>  virtual
> >>  void removeSurfaceTexture(QSurfaceTexture *surface);
> >> 
> >>    /// gets the surfaces textures ordered by order value
> >>    virtual const QList<QSurfaceTexture *> &
> > 
> > belowSurfaceTextures();
> > 
> >>    virtual const QList<QSurfaceTexture *> &
> > 
> > aboveSurfaceTextures();
> > 
> >>  }
> >>  
> >>  So, how a qt android multimedia widget will look like ?
> >>  class QAndroidMediaSurfaceTextureWidget: public QWidget, public
> >>  QSurfaceTexture, public AndroidSurfaceTexture
> >>  {
> >> 
> >>  public:
> >>        QAndroidMediaSurfaceTextureWidget( ... )
> >>        {
> >>           platformWindow()->addSurfaceTexture(this, -1); // the texture
> >> 
> >>  will be draw under the widget
> >> 
> >>        }
> >> 
> >>       void paintEvent ( QPaintEvent * event )
> >>       {
> >>         ...
> >>          p.fill(qRgba(255,255,255,255)); // the widget must be filled
> >> 
> >>  with a transparent color, otherwise the texture behind it will not be
> >>  visible.
> >> 
> >>       }
> >> 
> >>       void paintTexture()
> >>       {
> >>           glBindTexture​(GL_TEXTURE_2D, androidTextureName);
> >>           // draw the texture
> >>       }
> >> 
> >>  }
> >>  
> >>  then a simple window manager will paint all TLW on the window surface:
> >>  
> >>  drawWindows()
> >>  {
> >> 
> >>     eglMakeCurrent(...);
> >>     foreach ( QPlatformWindow * window, m_windows)
> >>     {
> >>           foreach (QSurfaceTexture * surfaceTexture,
> >> 
> >>  window->belowSurfaceTextures())
> >> 
> >>                 surfaceTexture->paintTexture(); // first draw all below
> >> 
> >>  textures
> >> 
> >>          drawWindow(window); // update texture for that window, than draw
> > 
> > it.
> > 
> >>           foreach (QSurfaceTexture * surfaceTexture,
> >> 
> >>  window->aboveSurfaceTextures())
> >> 
> >>                 surfaceTexture->paintTexture(); // last draw all below
> >> 
> >>  textures }
> >> 
> >>     eglSwapBuffers(...);
> >> 
> >>  }
> >>  
> >>  Now let's go back to the OpenGL rendering issue. Instead to use a
> >>  windows surface, I'm thinking to switch to a pixelbuffer surface
> >>  convert it to a texture (using glCopyTexImage2D ? ) then draw the
> >>  texture to window surface as the other TLWs.
> > 
> > No :) If you use OpenMAX AL you can let it render into a EGLSurface
> > 
> > 
> > And then there are functions to get a texture out of that,
> > eglCreateImageKHR   <= this is one of the possible friends
> > (this one would mean you first create a texture, map a EGLSurface around
> > it, and give that to openmax, there are other functions for the other way
> > around)
> > 
> > 
> > and then all you need to do is to render it using very limited opengl
> > code.
> > 
> > There is already a QtMultimedia-backend using OpenMAX AL, it's for symbian
> > tough!... Not sure how much code-reuse is possible but it's definitely a
> > very
> > good reference!
> > 
> > qt-mobility/plugins/multimedia/symbian/openmaxal
> > 
> > 
> > 
> > The awesome part of this is that the only data going over the GPU-bus is
> > the encoded(!) file/data   (aka. zero-copy)
> > .... and the GPU-bus is one of the weak links on all platforms.
> > 
> > 
> > 
> > For the fist case: raster:
> > If you go to way to copy/map the QImage's to EGL/GL resources, then 99% of
> > all
> > openmax al code should be reusable.
> 
> I think you misunderstand the last part which is not about OpenMAX.
> 
>  >>  Now let's go back to the OpenGL rendering issue. Instead to use a
> 
> >>  windows surface, I'm thinking to switch to a pixelbuffer surface
> >>  convert it to a texture (using glCopyTexImage2D ? ) then draw the
> >>  texture to window surface as the other TLWs.
> 
> Here I'm trying to say that if I'm going to use the only window EGLSurface,
> to paint the textures, then there is no *window* EGLSurface available for
> the QGLWidget, so for QGLWidget, I'm hopping to be able to use a
> *pixelbuffer* EGLSurface, then convert it into a texture, then paint it to
> window EGLSurface.

Sorry! my bad! :)
Replace all my "EGLSurface" with "EGLImage"  :)

EGLImage is a wrapper around "any" EGL/GL resource.

So yes, you don't need a EGLSurface! 
... all you need is a EGL/GL resource you can map a EGLImage around
     ... a texture is the simplest one. pixelbuffer or FBO are other examples.


And EGLImage is what OpenMAX AL deals with
(actually I don't know that, but OpenMAX IL(!) does, so I suspect OpenMAX AL 
does as well)


but again: any copy (within the gpu or not)  should not be necessary!



> 
> 
> Many thanks for your feedback !
> 
> >>  Any comments, suggestions and *help* will be very appreciated.
> >>  
> >>  Cheers,
> >>  BogDan.
> >>  
> >>  
> >>  [1] http://mail.kde.org/pipermail/necessitas-devel/2012-May/000900.html
> >>  [2] http://code.google.com/p/android-lighthouse/issues/detail?id=4#c28
> >>  [3] http://code.google.com/p/android-lighthouse/issues/detail?id=4#c23
> >>  [4]
> >>  http://groups.google.com/group/android-developers/browse_thread/thread/8
> >>  40e
> >>  4e20faab5c31 ,
> >>  https://developer.qualcomm.com/forum/qdevnet-forums/mobile-gaming-graphi
> >>  cs-
> >>  optimization-adreno/1969 _______________________________________________
> >>  Necessitas-devel mailing list
> >>  Necessitas-devel at kde.org
> >>  https://mail.kde.org/mailman/listinfo/necessitas-devel
> > 
> > _______________________________________________
> > Necessitas-devel mailing list
> > Necessitas-devel at kde.org
> > https://mail.kde.org/mailman/listinfo/necessitas-devel


More information about the Necessitas-devel mailing list