0

I'm working on an OpenGL app where the screen image is often static. I can think of 3 ways to handle this situation:

  1. Simply keep rendering the entire screen over and over anyways
  2. Ask OpenGL to call the render loop only when there are changes
  3. Only redraw the image when it changed and exit from render loop immediately otherwise

Clearly option 1 would be a gigantic waste of processing power (i.e. battery charge on mobile devices) and option 2 would be the optimal solution.

The power consumption difference between option 2 and option 3 is probably very minimal though (correct me if I'm wrong), since the unnecessary call to the render-loop and any associated setup-overhead should be tiny. It turns out that for my multi-threaded rendering pipeline option 3 would be a LOT easier to implement than option 2. So, I would like to give that a shot first if I can make it work.

When I tried it by rendering a static image once, the screen started flickering between that image and black like crazy. My guess is that this is due to double (or triple?) buffering: My image only gets drawn into one of the buffers, but on every call to the render-loop, the buffers are flipped, so that the image ends up on the screen only when that one buffer happens to be the active one.

Simple solution: Draw the static image once into every buffer and only then start exiting the render-loop immediately.

For this I need to know the number of buffers, i.e. the number of times I need to draw the image. Is there a way to query this number? Or can I somehow prevent the buffer switch if my render-loop turns into a NO-OP?

I am building an OpenGL ES 1.0 and an OpenGL ES 2.0 version of this code for maximal device support.

Markus A.
  • 12,349
  • 8
  • 52
  • 116

2 Answers2

1

There are two ways the rendering is triggered, depending on the framework/platform.

  1. Explicitly starting a new frame and flipping buffers yourself.
  2. Setting a render callback and the buffers are flipped after your callback returns.

Option 1 is what you'll generally see on PC programs. Option 2 is what you'll generally see on mobile applications (iOS/Android).

With option 1 as you control when to begin a render, you obviously just don't issue a render if nothing is changed. The OS will also have an event when your application needs a redraw (Say another application is partially dragged over yours). If you don't listen to this event and redraw, you will get flickering glitches.

With option 2 if the OS calls your render function, you must draw. If you draw nothing, whatever random data is in the buffers memory will be displayed. For example on android you can stop your redraw being triggered continuously with GLSurfaceView.RENDERMODE_WHEN_DIRTY. You can then requestRender() when you need to, but the OS will still call redraw when it needs to (e.g. like when things are composited over the top).

0

I'm not sure this is possible - it's actually invisible to OpenGL ES may actually change on some platforms (I've seen at least one system dynamically switch between 2 and 3 depending if vsync was being hit or not). EGL may give you some hints, but even there the assumption is that the application doesn't need to know.

Setting the surface property EGL_BUFFER_PRESERVE will ensure that the last frame's contents are preserved, but this is effectively a fullscreen copy inserted by the drivers, so it's often no more expensive just to redraw everything.

If you do go for the partial update case, remember to handle the case where the screen orientation changes.

solidpixel
  • 10,688
  • 1
  • 20
  • 33