RGBA16F bitmaps are always encoded in linear space, which means we must
apply the opto-electronic transfer function before we can render them
in the framebuffer.
Since our linear bitmaps are assumed to be scRGB, values can be negative.
The OETF is a slightly modified sRGB OETF:
sign(x) * OETF_sRGB(abs(x))
This effectively mirrors the OETF over the negative domain.
This CL also removes the "optimized" shader generation path. With
current compilers, the optimized path doesn't do anything of value
and makes ProgramCache difficult to maintain. Shader compilers inline
everything and are really good at folding expressions and removing
unused code.
Bug: 32984164
Test: CtsUiRenderingTestCases
Change-Id: Ieb458ad53574e3a8959aa6bccbbd2d1fe203cbc5
As of O, gradients are interpolated in linear space. This unfortunately
affects applications that were expecting a certain behavior for the
alpha ramp. This change attempts to get the best of both world: better
color interpolation (in linear space) and the old alpha interpolation
(in gamma space). This is achieved by applying the electro-optical
transfer function to the alpha channel; an idea so wrong it would
make any graphics programmer worth his salt weep in disgust.
As abhorrent this idea might be to me, it also acts as a faint
beacon of hope admist the unfathomable darkness that is Android's
color management.
And if you allow me another misguided metaphor, this change
represents the flotsam I can cling onto in the hope to one day
reach the bountiful shores of linear blending and accurate color
management. Would this change not fix the distress caused by its
predecessors, I will have no choice but bow my head in shame until
the day I can finally devise an infallible plan.
Bug: 33010587
Test: CtsUiRenderingTestCases
Change-Id: I5397fefd7944413f2c820e613a5cba50579d4dd5
This configuration uses 64 bits per pixel. Heach component is stored as a
half precision float value (16 bits). Half floats can be decoded/encoded
using android.util.Half.
RGBA_F16 bitmaps are used to decode wide-gamut images stored in 16 bit
formats (PNG 16 bit for instance). aapt is currently not aware of PNG
16 bits so such files must be placed in raw/ resource directories.
This first pass provides only partial drawing support with hardware
acceleration. RGBA_F16 bitmaps are stored in linear space and need
to be encoded to gamma space with the appropriate OETF to be rendered
properly on Android's current surfaces. They are however suitable for
linear blending. Full rendering support will be provided in a future
CL (BitmapShaders might be a bit tricky to handle properly during
shader generation).
Bug: 32984164
Test: bit CtsGraphicsTestCases:android.graphics.cts.BitmapRGBAF16Test
Change-Id: I328e6b567441a1b9d152a3e7be944a2cf63193bd
NOTE: Linear blending is currently disabled in this CL as the
feature is still a work in progress
Android currently performs all blending (any kind of linear math
on colors really) on gamma-encoded colors. Since Android assumes
that the default color space is sRGB, all bitmaps and colors
are encoded with the sRGB Opto-Electronic Conversion Function
(OECF, which can be approximated with a power function). Since
the power curve is not linear, our linear math is incorrect.
The result is that we generate colors that tend to be too dark;
this affects blending but also anti-aliasing, gradients, blurs,
etc.
The solution is to convert gamma-encoded colors back to linear
space before doing any math on them, using the sRGB Electo-Optical
Conversion Function (EOCF). This is achieved in different
ways in different parts of the pipeline:
- Using hardware conversions when sampling from OpenGL textures
or writing into OpenGL frame buffers
- Using software conversion functions, to translate app-supplied
colors to and from sRGB
- Using Skia's color spaces
Any type of processing on colors must roughly ollow these steps:
[sRGB input]->EOCF->[linear data]->[processing]->OECF->[sRGB output]
For the sRGB color space, the conversion functions are defined as
follows:
OECF(linear) :=
linear <= 0.0031308 ? linear * 12.92 : (pow(linear, 1/2.4) * 1.055) - 0.055
EOCF(srgb) :=
srgb <= 0.04045 ? srgb / 12.92 : pow((srgb + 0.055) / 1.055, 2.4)
The EOCF is simply the reciprocal of the OECF.
While it is highly recommended to use the exact sRGB conversion
functions everywhere possible, it is sometimes useful or beneficial
to rely on approximations:
- pow(x,2.2) and pow(x,1/2.2)
- x^2 and sqrt(x)
The latter is particularly useful in fragment shaders (for instance
to apply dithering in sRGB space), especially if the sqrt() can be
replaced with an inversesqrt().
Here is a fairly exhaustive list of modifications implemented
in this CL:
- Set TARGET_ENABLE_LINEAR_BLENDING := false in BoardConfig.mk
to disable linear blending. This is only for GLES 2.0 GPUs
with no hardware sRGB support. This flag is currently assumed
to be false (see note above)
- sRGB writes are disabled when entering a functor (WebView).
This will need to be fixed at some point
- Skia bitmaps are created with the sRGB color space
- Bitmaps using a 565 config are expanded to 888
- Linear blending is disabled when entering a functor
- External textures are not properly sampled (see below)
- Gradients are interpolated in linear space
- Texture-based dithering was replaced with analytical dithering
- Dithering is done in the quantization color space, which is
why we must do EOCF(OECF(color)+dither)
- Text is now gamma corrected differently depending on the luminance
of the source pixel. The asumption is that a bright pixel will be
blended on a dark background and the other way around. The source
alpha is gamma corrected to thicken dark on bright and thin
bright on dark to match the intended design of fonts. This also
matches the behavior of popular design/drawing applications
- Removed the asset atlas. It did not contain anything useful and
could not be sampled in sRGB without a yet-to-be-defined GL
extension
- The last column of color matrices is converted to linear space
because its value are added to linear colors
Missing features:
- Resource qualifier?
- Regeneration of goldeng images for automated tests
- Handle alpha8/grey8 properly
- Disable sRGB write for layers with external textures
Test: Manual testing while work in progress
Bug: 29940137
Change-Id: I6a07b15ab49b554377cd33a36b6d9971a15e9a0b
Bug: 26980851
GL_RGBA16F was being incorrectly calculated
as 4 bpp instead of 16 in Texture's objectSize(),
leading to a mismatch in cache size tracking
in GradientCache
Change-Id: I533c52fcdf9910d7a7d14bbd80965b8cbef8e147
Full GLES error checking layer via -include
trickery. Change DEBUG_OPENGL to a level system.
HIGH = every GL call is error checked
MODERATE = checkpointing at interesting spots
LOW = only asserts there are no errors at the end of a frame
or when the FBO changes
NONE = AIN'T GOT NO TIME FOR ERRORS GOTTA GO FAST!
Change-Id: Ibe81aae93d942059c4ddf1cbb11c828b7ce4c10b
Bug: 26584230
activateTexture(0) was accidentally refactored into
Texture::upload. Only OffscreenBuffer intended for the
texture unit to change
Change-Id: I5dbfc3eab8843733084ce1ce38a0a946abf0e05b
Bug: 26584230
In the event that Texture decides it doesn't
need to actually call glTexImage2D/glSubTexImage2D
it needs to still activateTexture(0) and bindTexture(mId)
as this is the expected state after Texture::upload()
is called.
Change-Id: I62d689a9057907a10dda2bc8f40c3113e43b93b2
Several places were setting GL_UNPACK_ALIGNMENT
unneccessarily, whereas other places were assuming an
unpack alignment of 1. Since we never actually
do explicit row-alignment, set GL_UNPACK_ALIGNMENT
to 1 at context creation time and never change it
Bug: 26584230
Also turns on aggressive glGetError checking to
better catch potential problem zones
Change-Id: I190c8f0f0494a7f046d5ed769405c75d363be59a
Adds remaining missing overrides and nullptr usages, missed due to
an extreme failure in tool usage.
Change-Id: I56abd72975a3999ad13330003c348db40f59aebf
Bug #9316260
The GL specification indicates that deleting a bound texture has
the side effect of binding the default texture (name=0). This change
replaces all calls to glDeleteTextures() by Caches::deleteTexture()
to properly keep track of texture bindings.
Change-Id: Ifbc60ef433e0f9776a668dd5bd5f0adbc65a77a0