In cogl_texture_new_from_file we create and own a temporary
bitmap. There's no need to copy this data if we need to do a premult
conversion so instead it just does conversion before passing it on to
cogl_texture_new_from_bitmap.
The Cogl atlas code was using _cogl_texture_prepare_for_upload with a
NULL pointer for the dst_bmp to determine the internal format of the
texture without converting the bitmap. It needs to do this to decide
whether the texture will go in the atlas before wasting time on the
conversion. This use of the function is a little confusing so that
part of it has been split out into a new function called
_cogl_texture_determine_internal_format. The code to decide whether a
premult conversion is needed has also been split out.
When deciding if a material layer is equal it now compares the GL
target and texture number if the textures are not sliced. This is
needed to get batching across atlased textures.
Cogl accepts a pixel format for both the data in memory and the
internal format to be used for the texture. If they do not match then
it would convert them using the CoglBitmap functions before uploading
the data. However, GL also lets you specify both formats so it makes
more sense to let GL do the conversion. The driver may need the
texture in a specific format so it may end up being converted anyway.
The cogl_texture_upload_data functions have been removed and replaced
with a single function to prepare the bitmap. This will only do the
premultiplication conversion because that is the only part that GL
can't do directly.
The premult part of _cogl_convert_premult has now been split out as
_cogl_convert_premult_status. _cogl_convert_premult has been renamed
to _cogl_convert_format to make it less confusing. The premult
conversion is now done in-place instead of copying the
buffer. Previously it was copying the buffer once for the format
conversion and then copying it again for the premult conversion. The
premult conversion never changes the size of the buffer so it's quite
easy to do in place. We can also use the separated out function
independently.
The internal format of the atlas texture is still set to the
appropriate format so Cogl will disable blending for textures that are
intended to be RGB. This should end up ignoring the alpha channel from
the texture in the atlas. This makes the code slightly easier to
maintain and should also improve the chances of batching.
Instead of assigning a new colour to each quad of a batch, the
rectangle debugging code now assigns a new colour to each batch so
that it can be used to visually see what is being batched. The colour
is stored in a global variable that is reset during cogl_clear. This
improves the chances that the same colour will be used for a batch in
the next frames to avoid flickering.
When setting up the state for the vertex buffer,
enable_state_for_drawing_buffer tries to keep track of the highest
numbered texture unit in use. It then disables any texture arrays for
units that were previously enabled if they are greater than that
number. However if there is no texturing in the VBO then the max used
unit would be left at 0 which it would later think meant unit 0 is
still in use so it wouldn't disable it. To fix this it now initialises
the max used unit to -1 which it should interpret as ‘no units are in
use’ so it will later disable the arrays for all units.
Thanks to Jon Mayo for reporting the bug.
http://bugzilla.openedhand.com/show_bug.cgi?id=1957
We were checking the number of texture units against the GL enum that is
used in glGetInteger() to query that number. Let's abstract this in a
little function.
Took the opportunity to dig a bit on the usage of GL limits for the
number of texture (image) units and document our use of them. We'll need
something finer grained if we want to fully exploit texture image units
with a programmable pipeline.
The index field of CoglTextureUnit was never set, leading to the
creation of units with index set to 0. When trying to retrieve a texture
unit by its index (!= 0) with _cogl_get_texture_unit(), a new one was
created as it could not find it back in the list of textures units:
ctx->texture_units.
http://bugzilla.openedhand.com/show_bug.cgi?id=1958
Previously the atlas textures were being created with whatever format
the first sub texture is in. Only three formats are supported so this
only matters if the first texture is a premultiplied alpha
texture. Instead it now masks out the premultiplied bit so that the
textures are always either RGB_888 or RGBA_8888.
When uploading texture data it was just calling cogl_texture_set_data
on the large texture. This would attempt to convert the data to the
format of the large texture. All of the textures with alpha channels
are stored together regardless of whether they are premultiplied so
this was causing premultiplied textures to be unpremultiplied
again. It now just uploads the data ignoring the premult bit of the
format so that it only gets converted once.
With the atlas texture backend ensuring the mipmaps can make it become
a completely different texture which will have different texture
coordinates or may even be sliced. Therefore we need to ensure the
mipmaps before deciding which quads to log in the journal. This adds a
new private function to cogl-material which ensures the mipmaps if
needed.
The sub texture backend doesn't work well as a completely general
texture backend because for example when rendering with cogl_polygon
it needs to be able to tranform arbitrary texture coordinates without
reference to the other coordintes. This can't be done when the texture
coordinates are a multiple of one because sometimes the coordinate
should represent the left or top edge and sometimes it should
represent the bottom or top edge. For example if the s coordinates are
0 and 1 then 1 represents the right edge but if they are 1 and 2 then
1 represents the left edge.
Instead the sub-textures are now documented not to support coordinates
outside the range [0,1]. The coordinates for the sub-region are now
represented as integers as this helps avoid rounding issues. The
region can no longer be a super-region of the texture as this
simplifies the code quite a lot.
There are two new texture virtual functions:
transform_quad_coords_to_gl - This transforms two pairs of coordinates
representing a quad. It will return FALSE if the coordinates can
not be transformed. The sub texture backend uses this to detect
coordinates that require repeating which causes cogl-primitives
to use manual repeating.
ensure_non_quad_rendering - This is used in cogl_polygon and
cogl_vertex_buffer to inform the texture backend that
transform_quad_to_gl is going to be used. The atlas backend
migrates the texture out of the atlas when it hits this.
When calculating the next integer position for negative coordinates it
would not increment if the position is already a multiple of one so we
need to manually add one.
When try_creating_fbo fails it returns 0 to report the error and if it
succeeds it returns ‘flags’. However cogl_offscreen_new_to_texture
also passes in 0 for the flags as the last fallback to create the fbo
with nothing but the color buffer. In that case it will return 0
regardless of whether it succeeded so the last fallback will always be
considered a failure.
To fix this it now just returns a gboolean to indicate whether it
succeeded and the flags used for each attempt is assigned when passing
the argument rather than from the return value of the function.
Also if the only configuration that succeeded was with flags==0 then
it would always try all combinations because last_working_flags would
also be zero. To avoid this it now uses a separate gboolean to mark
whether we found a successful set of flags.
http://bugzilla.openedhand.com/show_bug.cgi?id=1873
Since 755cce33a7 the framebuffer code is using the GL enums
GL_DEPTH_ATTACHMENT and GL_DEPTH_COMPONENT16. These aren't available
directly under GLES except with the OES suffix so we need to define
them manually as we do with the other framebuffer constants.
These macros used to define Cogl wrappers for the GLenum values. There are
now Cogl enums everywhere in the API where these were required so we
shouldn't need them anymore. They were in the public headers but as
they are not neccessary and were not in the API docs for Clutter 1.0
it should be safe to remove them.
If a user supplied multiple groups of texture coordinates with
cogl_rectangle_with_multitexture_coords() then we would repeatedly log only
the first group in the journal. This fixes that bug and adds a conformance
test to verify the fix.
Thanks to Gord Allott for reporting this bug.
The Intel drivers in Mesa 7.6 (and possibly earlier versions) don't
support creating FBOs with a stencil buffer but without a depth
buffer. This reworks framebuffer allocation so that we try a number
of fallback options before failing.
The options we try in order are:
- the same options that were sucessful last time if available
- combined depth and stencil
- separate depth and stencil
- just stencil, no depth
- just depth, no stencil
- neither depth or stencil
We weren't taking a reference on the texture to be used as the color buffer
for offscreen rendering, so it was possible to free the texture leaving the
framebuffer in an inconsistent state.
This adds gives Cogl a dedicated UProf context which will be linked together
with Clutter's context during clutter_init_real().
Initial timers cover _cogl_journal_flush and _cogl_journal_log_quad
You can explicitly ask for a report of Cogl statistics by exporting
COGL_PROFILE_OUTPUT_REPORT=1 but since the context is linked with Clutter's
the statisitcs will also be shown in the automatic Clutter reports.
* stage-use-alpha:
tests: Use accessor methods for :use-alpha
stage: Add accessors for :use-alpha
tests: Allow setting the stage opacity in test-paint-wrapper
stage: Premultiply the stage color
stage: Composite the opacity with the alpha channel
glx: Always request an ARGB visual
stage: Add :use-alpha property
materials: Get the right blend function for alpha
When the texture is in the atlas, ensuring the mipmaps can effectively
make it become a completely different texture so we should do this
before getting the GL handle.
Mipmaps don't work very well in the current atlas because there is not
enough padding between the textures. If ensure_mipmaps is called it
will now create a new texture and migrate the atlased texture to
it. It will use the same blit mechanism as when migrating so it will
try to use an FBO for a fast blit. However if this is not possible it
will end up downloading the data for the entire atlas which is not
ideal.
When reorganizing the textures, we can avoid downloading the entire
texture data if we bind the source texture in a framebuffer object and
copy the destination using glCopyTexSubImage2D. This is also
implemented using a much faster path in Mesa.
Currently it is calling the GL framebuffer API directly but ideally it
would use the Cogl offscreen API. However there is no way to tell Cogl
not to create a stencil renderbuffer which seems like a waste in this
situation.
If FBOs are not available it will fallback to reading back the entire
texture data as before.
This adds a 'dump-atlas-image' debug category. When enabled, CoglAtlas
will use Cairo to create a png which visualizes the leaf rectangles of
the atlas.
This adds an 'atlas' category to the COGL_DEBUG environment
variable. When enabled Cogl will display messages when textures are
added to the atlas and when the atlas is reorganized.
When space can't be found in the atlas for a new texture it will now
try to reorganize the atlas to make space. A new CoglAtlas is created
and all of the textures are readded in decreasing size order. If the
textures still don't fit then the size of the atlas is doubled until
either we find a space or we reach the texture size limits. If we
successfully find an organization that fits then all of the textures
will be migrated to a new texture. This involves copying the texture
data into CPU memory and then uploading it again. Potentially it could
eventually use a PBO or an FBO to transfer the image without going
through the CPU.
The algorithm for laying out the textures works a lot better if the
rectangles are added in order so we might eventually want some API for
creating multiple textures in one go to avoid reorganizing the atlas
as far as possible.
This adds a CoglAtlas type which is a data structure that keeps track
of unused sub rectangles of a larger rectangle. There is a new atlased
texture backend which uses this to put multiple textures into a single
larger texture.
Currently the atlas is always sized 256x256 and the textures are never
moved once they are put in. Eventually it needs to be able to
reorganise the atlas and grow it if necessary. It also needs to
migrate the textures out of the atlas if mipmaps are required.
This is an optimised version of CoglTexture2DSliced that always deals
with a single texture and always uses the GL_TEXTURE_2D
target. cogl_texture_new_from_bitmap now tries to use this backend
first. If it can't create a texture with that size then it falls back
the sliced backend.
cogl_texture_upload_data_prepare has been split into two functions
because the sliced backend needs to know the real internal format
before the conversion is performed. Otherwise the converted bitmap
will be wasted if the backend can't support the size.
This provides a way to upload the entire data for a texture without
having to first call glTexImage and then glTexSubImage. This should be
faster especially with indirect rendering where it would needlessy
send the data for the texture twice.
new_from_data and new_from_file can be implemented in terms of
new_from_bitmap so it makes sense to move these to cogl-texture rather
than having to implement them in every texture backend.
This adds a new texture backend which represents a sub texture of a
larger texture. The texture is created with a reference to the full
texture and a set of coordinates describing the region. The backend
simply defers to the full texture for all operations and maps the
coordinates to the other range. You can also use coordinates outside
the range [0,1] to create a repeated version of the full texture.
A new public API function called cogl_texture_new_from_sub_texture is
available to create the sub texture.