This is quite big, so:
* There are new Magnum::PixelFormat and Magnum::CompressedPixelFormat
enums, which contain generic API-independent formats. In particular,
PixelFormat replaces GL::PixelFormat and GL::PixelType with a single
value.
* There's GL::pixelFormat(), GL::pixelType(),
GL::compressedPixelFormat() to convert the generic enums to
GL-specific. The mapping is only in one direction, done with a lookup
table (generic enums are indices to that table).
* GL classes taking the formats directly (such as GL::BufferImage) have
overloads that take both the GL-specific and generic format.
* The generic Image, CompressedImage, ImageView, CompressedImageView,
and Trade::ImageData classes now accept the generic formats
first-class. However, it's also possible to store an
implementation-specific value to cover cases where a generic format
enum doesn't have support for a particular format. This is done by
wrapping the value using pixelFormatWrap() or
compressedPixelFormatWrap(). Particular GPU APIs then assume it's
their implementation-specific value and extract the value back using
pixelFormatUnwrap() or compressedPixelFormatUnwrap(). There's also an
isPixelFormatImplementationSpecific() and
isCompressedPixelFormatImplementationSpecific() that distinguishes
these values.
* Many operations need pixel size and in order to have it even for
implementation-specific formats, a corresponding pixelSize()
overload is found via ADL on construction and the calculated size
stored along the format. Previously the pixel size was only
calculated on demand, but that's not possible now. In case such
overload is not available, it's possible to pass pixel size manually
as well.
* In order to support the GL format+type pair, Image, ImageView and
Trade::ImageData, there's now an additional untyped formatExtra()
field that holds the second value.
* The CompressedPixelStorage class is now unconditionally available on
all targets, including OpenGL ES and WebGL. However, on OpenGL ES the
GL APIs expect that it's all at default values.
I attempted to preserve backwards compatibility as much as possible:
* The PixelFormat and CompressedPixelFormat enum now contains generic
API-independent values. The GL-specific formats are present there,
but marked as deprecated. Use either the generic values or
GL::PixelFormat (togehter with GL::PixelType) and
GL::CompressedPixelFormat instead. There's a lot of ugliness caused
by this, but seems to work well.
* *Image::type() functions are deprecated as they were too
GL-specific. Use formatExtra() and cast it to GL::PixelType instead.
* Image constructors take templated format or format+extra arguments,
so passing GL-specific values to them should still work.
The general part stays in the root namespace, while the GL-specific
stuff goes to the GL namespace. Also all GL-specific documentation was
moved to relevant APIs in the GL namespace. This finally allows me to
build PixelStorage.cpp as part of the root namespace.
The PixelStorage::pixelSize() function and
PixelStorage::dataProperties() taking a pair of GL::PixelFormat /
GL::PixelType enums is deprecated, use GL::pixelSize() and
dataProperties() taking pixel size directly instead. A lot of code is
still using these, including images; the deprecated aliases are inlined
in the header to avoid a compile-time dependency on the GL library.
At the moment just the GL library itself w/o the tests, and without
backwards compatibility aliases. The following types were left in the
root namespace, despite being in the GL/ directory, as they will get
moved back soon:
* Image, CompressedImage and their dimensional typedefs
* ImageView, CompressedImageView and their dimensional typedefs
* PixelStorage
Not PixelFormat etc., that one will stay in the GL namespace and a
completely new PixelFormat enum will be provided in the root namespace.
Minimal updates (just the include guards) so Git is hopefully able to
detect the rename and track the history properly.
Everything except Magnum::GL doesn't compile now.
* Half-floats and floats are usable in ES2 / WebGL 1 (they weren't by
mistake) -- just use OES_texture_float or OES_texture_half_float.
* Half-floats are linearly filterable in ES3 / WebGL 2 and
OES_texture_half_float_linear makes it possible in ES2 / WebGL 1.
* Floats are not linearly filterable, not even in ES3 (they were by
mistake) -- one needs OES_texture_float_linear for that.
* Neither floats nor half-floats are renderable in ES < 3.2 -- one
needs EXT_color_buffer_half_float or EXT_color_buffer_float for that.
The former is available for example on iOS, the latter is apparently
only on NV cards. Both are builtin in ES 3.2, EXT_color_buffer_float
depends in ES3, so half-floats are the only possible format to render
to in ES2.
* Rendering to floats in WebGL is slightly more complicated --
unlike with OpenGL ES 2 it's possible to render to floats in WebGL 1
using WEBGL_color_buffer_float. There's another WebGL 1 extension
called EXT_color_buffer_half_float and they are both replaced with
EXT_color_buffer_float in WebGL 2.
And, as a cherry on top, GPH (formerly SGI) has patents on most of
these, which is probably why the support for them is so spotty.
Since 98a676ef65, on ES2 and WebGL1 the
Texture::setStorage() emulation passes the pixel format to both <format>
and <internalFormat> of glTexImage() APIs. On desktop the go-to way to
create a sRGB texture is by passing GL_SRGB to <internalFormat> and
GL_RGB to <format>, but here GL_RGB was passed to both and thus the
information about sRGB was lost.
With the new PixelFormat::SRGB and PixelFormat::SRGBAlpha enums that
are present only on ES2/WebGL1 this case is fixed -- sRGB texture format
will get translated to sRGB pixel format and that used for both
<format> and <internalFormat>.
Another case is when EXT_texture_storage is available -- passing unsized
GL_SRGB_EXT or GL_SRGB_ALPHA_EXT to glTexStorageEXT() is an error and
there's apparently no mention of this in any extension, making it
impossible to create sRGB textures using EXT_texture_storage. I bit the
bullet and tried passing the (numerical value of) GL_SRGB8 and
GL_SRGB8_ALPHA8 to it. At least on my NV it worked, so I enabled these
two in TextureFormat for ES2. No EXT_texture_storage is on WebGL1, so
they are only on ES2.
These two sized TextureFormat::SRGB8 and TextureFormat::SRGB8Alpha8
formats are translated to GL_SRGB and GL_SRGB_ALPHA and so using them
unconditionally for all platforms (except WebGL1) "just works".
Followup to previous commit -- links to opengl.org are now redirected to
khronos.org and the extension links have the same format for both GL and
GLES. That allows me to remove some of the Doxygen aliases and use just
a single set of the functions for both GL and GLES.
Most of the code is in the actual test where I'm comparing and
benchmarking three different implementations (a
naive/straightforward/ground-truth one, the chosen one and a fast though
cache-spilling table-based one) to ensure the behavior is consistent
across all of them and that the performance is within reasonable bounds.
The Corrade::TestSuite benchmarking stuff needs serious improvements,
though.
Yeah, sorry, I know, the enums are renamed for second or third time in a
row, first they were Image::Format, then ImageFormat, then ColorFormat
and now PixelFormat. But this time it's final and last time they are
renamed and now everything is finally consistent:
* ColorFormat::DepthComponent -- depth is not a color, thus
PixelFormat::DepthComponent makes a lot more sense.
* There will be PixelStorage classes, which will be stored in images
alonside PixelFormat/PixelType enums, making everything nicely
aligned.
* The GL documentation about glTexImage2D() etc. denotes the <format>
and <type> parameters as format and type of *pixel* data, so now we
are _finally_ consistent with the official naming.
I wonder why did I not choose PixelFormat originally. Anyway, the old
<Magnum/ColorFormat.h> header, ColorFormat, ColorType and
CompressedColorFormat types are now aliases to the new ones, are marked
as deprecated and will be removed in some future release (as always, I'm
waiting at least six months before removing the deprecated
functionality).
With pixel pack/unpack support it will be possible to create views onto
sub-images, renamed the class to reflect that.
The old Magnum/ImageReference.h and ImageReference types are now aliases
to ImageView.h and ImageView types, are marked as deprecated and will be
removed in future release.
ARB_direct_state_access doesn't have equivalent for glTexImage*D(),
which indicates that these calls should not be used anymore. Also
removed EXT_direct_state_access code path and kept just the plain
glBindTexture() + glTexImage*D(), as I assume that all implementations
which have EXT_DSA have also ARB_texture_storage, thus this alternative
would have no use.
According to reports on delphigl.de this extension is far more supported
in comparison to the NV version (and also there's much less FF cruft in
the specification).
It makes sense, but this ordering also helps to avoid bug in Doxygen
1.8.6+ which merges next non-xrefitem section with the previous one (so
e.g. the TODO list contained the following @see block, which is not
desired).
As we are now using absolute includes, there is no need to prefix
everything with "magnum<Namespace>" etc. All generated configuration
files are renamed to configure.h and their path is included _before_
everything else to avoid accidental collisions.
The only places where they aren't absolute are:
- when header is included from corresponding source file
- when including headers which are not part of final installation (e.g.
test-specific configuration, headers from Implementation/)
Everything what was in src/ is now in src/Corrade, everything from
src/Plugins is now in src/MagnumPlugins, everything from external/ is in
src/MagnumExternal. Added new CMakeLists.txt file and updated the other
ones for the moves, no other change was made. If MAGNUM_BUILD_DEPRECATED
is set, everything compiles and installs like previously except for the
plugins, which are now in MagnumPlugins and not in Magnum/Plugins.
Until recently (or maybe not too recently) ES3 extension header was
"currently empty", now the extension header is shared with ES2. It's
nice to finally get rid of all the weird ifndefs.