Android render effects is a way to globally change the colors used when rendering, for example by using only the Red channel (disabling Green and Blue). It was first presented on Jeff Sharkey’s blog, and it is now implemented and available in CyanogenMod.
Instead of using the three color channels (RGB) you may chose to use only one, let’s say Red. White becomes Red, while the disabled channels (Green, Blue) become black. The colors are very weird, but the screen remains sort-of readable in general. Why would anybody want to do something so horrible to a display?
The first reason is to save power. A phone’s display uses a significant portion of the battery. For OLED displays, making pixels (or subpixels) black saves power. Turning color channels off saves power. For example using only the Red channel instead of all three RGB cuts the display power to less than 50%.
Android phones have a Display Brightness setting, which is usually set to “Automatic Brightness”. This reduces the brightness of the display in dark indoors (when the screen is easy to read), while increasing the brightness in sunny outdoors, when the screen is barely readable.
On OLED displays, which have deep blacks, increased brightness usually looks better. So why there exists this adaptive brightness at all, instead of keeping the display simply set to maximum brightness all the time?
Mainly for two reasons:
- lower brightness saves battery power
- lower brightness increases the display lifetime (for OLED).
Yes, that’s right: the “brightness” setting is not there to improve the visual quality — it is there to increase the battery life. Try setting your phone to “maximum brightness” for one day, it’ll look great but will empty the battery much faster.
Traditional LCD displays need a backlight, a source of white light that is filtered through the liquid cristal layer to produce the colors. The power usage of an LCD display is independent of the colors displayed (e.g. redardless whether the screen is white, red or blue, the power usage of the display is the same).
OLED displays do not have a backlight. In OLED the pixels themselves emit light, and each individual subpixel uses power in doing so. OLED power usage depends on the colors displayed. A white screen (which has all subpixels Red, Green, Blue lighten up at maximum intensity) uses the most power, while a black screen uses almost no power at all.
In addition, OLEDs have a general difficulty with Blue. The Blue subpixels use much more power (compared to the Red or Green channels). In addition to the increased power usage (or because of it) the Blue subpixels have a much shorter lifetime. If the OLED display is kept on, bright white, for a long time, the Blue subpixels will wear off visibly and irreversibly.
So a way to increase the battery lifetime of the phone is to disable the Blue channel. Of course, this is a pretty high price to pay for power as the colors don’t look normal anymore. A more extreme is to disable two channels, e.g. Blue and Green, resulting in more battery life and a Red-only display.
But hacking is fun, and Jeff Sharkey first implemented a proof-of-concept of the color-reduction. It is implemented as an OpenGL transform in SurfaceFlinger. This means that the pixel colors undergo a final modification (e.g. zeroing-out the Blue and Green channels) just before they’re sent to the display panel. The problem is that this solution uses CPU or GPU resources (due to the additional OpenGL processing), and this means more power usage. So while some power is gained by reducing OLED colors, some power is lost because of the additional GPU usage.
Now the question presents itself: is it possible to implement this color warping, a.k.a. RenderFX, without the burden of the additional OpenGL transform? Well.. yes, there is a cool trick that does it, but it only works for OLED displays. But anyway we’re only interested in RenderFX on OLEDs (because only there it saves power).
The trick concerns the backlight color. Traditional LCDs have a real backlight, a source of white light, whose intensity can be changed (more or less bright) but the color stays white.
On the other hand OLEDs do not have a real backlight. The brightness setting for OLED is not implemented by changing the backlight intensity, but simply by remapping the intensity of the pixels in the display controller. You can think of an OLED backlight, but that’s an imaginary concept simulated by the display controller.
It turns out, the OLED panel can control the intensity of the backlight color channels (RGB) independently. This can be represented as if having a backlight which can be set to any color and intensity, not only grayscale. And this is the solution: by setting the backlight to various non-white colors it is possible to implement RenderFX without the OpenGL overhead.
For example, to disable the Blue channel, it is enough to set the backlight to Yellow (Red+Green). To disable both Blue and Green we set the backlight to Red. And so on, many intermediate variations are possible.
I tested this in practice on Nexus One with CyanogenMod by modifying the kernel file
which implements the “backlight intensity setting” for the OLED panel, to allow for non-white backlight colors — and it works nicely!
For a general and clean solution, a bit more work is needed throughout the framework in order to expose in the API the concept of “LCD backlight color” instead of “LCD backlight intensity” as it is now. This is a generalization, as an RGB color can easily be mapped to a grayscale intensity, but not the other way around (i.e. RGB is a superset of grayscale).