Some code in Cogl such as when flushing a stencil clip assumes that it
can push a temporary simple pipeline to reset to a known state for
internal drawing operations. However this breaks down if the
application has set any legacy state because that is set globally so
it will also get applied to the internal pipeline.
_cogl_draw_attributes already had an internal flag to disable applying
the legacy state but I think this is quite awkward to use because not
all places that push a pipeline draw the attribute buffers directly so
it is difficult to pass the flag down through the layers.
Conceptually the legacy state is meant to be like a layer on top of
the purely pipeline-based state API so I think ideally we should have
an internal function to push the source without the applying the
legacy state. The legacy state can't be applied as the pipeline is
pushed because the global state can be modified even after it is
pushed. This patch adds a _cogl_push_source() function which takes an
extra boolean flag to mark whether to enable the legacy state. The
value of this flag is stored alongside the pipeline in the pipeline
stack. Another new internal function called
_cogl_get_enable_legacy_state queries whether the top entry in the
pipeline stack has legacy state enabled. cogl-primitives and the
vertex array drawing code now use this to determine whether to apply
the legacy state when drawing. The COGL_DRAW_SKIP_LEGACY_STATE flag is
now removed.
Reviewed-by: Robert Bragg <robert@linux.intel.com>
Instead of calling _cogl_texutre_prepare_for_upload in
cogl_texture_set_region_from_bitmap the call is now deferred to the
implementation of the virtual for set_region. This is needed if the
texture backend is using a different format for the actual GL texture
than what is reported by cogl_texture_get_format. This happens for
example with atlas textures which report the original internal format
specified when the texture was created but actually always store the
data in an RGBA texture.
Also when creating an atlas texture from a bitmap it was preparing the
bitmap to be uploaded to the original format instead of the format of
the actual texture used for the atlas. Then it was using
cogl_texture_set_region_from_bitmap to upload the 5 pieces to make the
copies of the edge pixels. This would end up converting the image to
the actual format 5 times. The atlas textures have now been changed to
prepare the bitmap for the right format.
https://bugzilla.gnome.org/show_bug.cgi?id=657840
Reviewed-by: Robert Bragg <robert@linux.intel.com>
This exposes 2 experimental functions that make it possible to upload a
subregion of a texture from a CoglBuffer by first wrapping the buffer as
a CoglBitmap and then allowing uploading of a subregion from a
CoglBitmap. The new functions are:
cogl_bitmap_new_from_buffer() and
cogl_texture_set_region_from_bitmap()
Actually for now we are exporting this API for practical reasons since
we already had this API internally and it enables a specific feature
that was requested, but it is worth nothing that it's quite likely we
will replace these with functions that don't involve the CoglBitmap API
at some point.
For reference: The CoglBitmap API was actually removed from the 2.0
experimental API reference manual some time ago because the hope was
that we'd come up with a neater replacement. It doesn't seem entirely
clear what the scope of the CoglBitmap api is so it has became a bit of
a dumping ground. CoglBitmap is used for image loading, as a means to
represent the layout of image data and also internally deals with format
conversions.
Note: Because we are avoiding including CoglBitmap as part of the 2.0
API these functions aren't currently included in the 2.0 reference
manual.
Reviewed-by: Neil Roberts <neil@linux.intel.com>
The GL or GLES library is now dynamically loaded by the CoglRenderer
so that it can choose between GL, GLES1 and GLES2 at runtime. The
library is loaded by the renderer because it needs to be done before
calling eglInitialize. There is a new environment variable called
COGL_DRIVER to choose between gl, gles1 or gles2.
The #ifdefs for HAVE_COGL_GL, HAVE_COGL_GLES and HAVE_COGL_GLES2 have
been changed so that they don't assume the ifdefs are mutually
exclusive. They haven't been removed entirely so that it's possible to
compile the GLES backends without the the enums from the GL headers.
When using GLX the winsys additionally dynamically loads libGL because
that also contains the GLX API. It can't be linked in directly because
that would probably conflict with the GLES API if the EGL is
selected. When compiling with EGL support the library links directly
to libEGL because it doesn't contain any GL API so it shouldn't have
any conflicts.
When building for WGL or OSX Cogl still directly links against the GL
API so there is a #define in config.h so that Cogl won't try to dlopen
the library.
Cogl-pango previously had a #ifdef to detect when the GL backend is
used so that it can sneakily pass GL_QUADS to
cogl_vertex_buffer_draw. This is now changed so that it queries the
CoglContext for the backend. However to get this to work Cogl now
needs to export the _cogl_context_get_default symbol and cogl-pango
needs some extra -I flags to so that it can include
cogl-context-private.h
The texture driver functions are now accessed through a vtable pointed
to by a struct in the CoglContext so that eventually it will be
possible to compile both the GL and GLES texture drivers into a single
binary and then select between them at runtime.
cogl-ext-functions.h now contains definitions for all of the core GL
and GLES functions that we would normally link to directly. All of the
code has changed to access them through the cogl context pointer. The
GE macro now takes an extra parameter to specify the context because
the macro itself needs to make GL calls but various points in the Cogl
source use different names for the context variable.
This exposes experimental cogl_framebuffer APIs for getting and setting
a viewport without having to refer to the implicit CoglContext. It adds
the following experimental API:
cogl_framebuffer_set_viewport
cogl_framebuffer_get_viewport4fv
cogl_framebuffer_get_viewport_x
cogl_framebuffer_get_viewport_y
cogl_framebuffer_get_viewport_width
cogl_framebuffer_get_viewport_height
Signed-off-by: Neil Roberts <neil@linux.intel.com>
This exposes a CoglTexture2D typedef and adds the following experimental
API:
cogl_is_texture_2d
cogl_texture_2d_new_with_size
cogl_texture_2d_new_from_data
cogl_texture_2d_new_from_foreign
Since this is experimental API you need to define
COGL_ENABLE_EXPERIMENTAL_API before including cogl.h.
Note: With these new entrypoints we now expect a CoglContext pointer to
be passed in, instead of assuming there is a default context. The aim is
that for Cogl 2.0 we won't have a default context so this is a step in
that direction.
This is part of a broader cleanup of some of the experimental Cogl API.
One of the reasons for this particular rename is to switch away from
using the term "Array" which implies a regular, indexable layout which
isn't the case. We also want to strongly imply a relationship between
CoglBuffers and CoglPixelBuffers and be consistent with the
CoglAttributeBuffer and CoglIndexBuffer APIs.
This renames the two internal functions _cogl_get_draw/read_buffer
as cogl_get_draw_framebuffer and _cogl_get_read_framebuffer. The
former is now also exposed as experimental API.
OpenGL < 4.0 only supports integer based viewports and internally we
have a mixture of code using floats and integers for viewports. This
patch switches all viewports throughout clutter and cogl to be
represented using floats considering that in the future we may want to
take advantage of floating point viewports with modern hardware/drivers.
The current framebuffer is now internally separated so that there can
be a different draw and read buffer. This is required to use the
GL_EXT_framebuffer_blit extension. The current draw and read buffers
are stored as a pair in a single stack so that pushing the draw and
read buffer is done simultaneously with the new
_cogl_push_framebuffers internal function. Calling
cogl_pop_framebuffer will restore both the draw and read buffer to the
previous state. The public cogl_push_framebuffer function is layered
on top of the new function so that it just pushes the same buffer for
both drawing and reading.
When flushing the framebuffer state, the cogl_framebuffer_flush_state
function now tackes a pointer to both the draw and the read
buffer. Anywhere that was just flushing the state for the current
framebuffer with _cogl_get_framebuffer now needs to call both
_cogl_get_draw_buffer and _cogl_get_read_buffer.
Instead of having a single journal per context, we now have a
CoglJournal object for each CoglFramebuffer. This means we now don't
have to flush the journal when switching/pushing/popping between
different framebuffers so for example a Clutter scene that involves some
ClutterEffect actors that transiently redirect to an FBO can still be
batched.
This also allows us to track state in the journal that relates to the
current frame of its associated framebuffer which we'll need for our
optimization for using the CPU to handle reading a single pixel back
from a framebuffer when we know the whole scene is currently comprised
of simple rectangles in a journal.
If we have to copy the bitmap to do the premultiplication then we were
previously using the rowstride of the source image as the rowstride
for the new image. This is wasteful if the source image is a subregion
of a larger image which would make it use a large rowstride. If we
have to copy the data anyway we might as well compact it to the
smallest rowstride. This also prevents the copy from reading past the
end of the last row of pixels.
An internal function called _cogl_bitmap_copy has been added to do the
copy. It creates a new bitmap with the smallest possible rowstride
rounded up the nearest multiple of 4 bytes. There may be other places
in Cogl that are currently assuming we can read height*rowstride of
the source buffer so they may want to take advantage of this function
too.
http://bugzilla.clutter-project.org/show_bug.cgi?id=2491
* cogl_texture_get_data() is converted to use
_cogl_texture_foreach_sub_texture_in_region() to iterate
through the underlying textures.
* When we need to read only a portion of the underlying
texture, we set up a FBO and use _cogl_read_pixels()
to read the portion we need. This is enormously more
efficient for reading a small portion of a large atlas
texture.
* The CoglAtlasTexture, CoglSubTexture, and CoglTexture2dSliced
implementation of get_texture() are removed.
http://bugzilla.clutter-project.org/show_bug.cgi?id=2414
This applies an API naming change that's been deliberated over for a
while now which is to rename CoglMaterial to CoglPipeline.
For now the new pipeline API is marked as experimental and public
headers continue to talk about materials not pipelines. The CoglMaterial
API is now maintained in terms of the cogl_pipeline API internally.
Currently this API is targeting Cogl 2.0 so we will have time to
integrate it properly with other upcoming Cogl 2.0 work.
The basic reasons for the rename are:
- That the term "material" implies to many people that they are
constrained to fragment processing; perhaps as some kind of high-level
texture abstraction.
- In Clutter they get exposed by ClutterTexture actors which may be
re-inforcing this misconception.
- When comparing how other frameworks use the term material, a material
sometimes describes a multi-pass fragment processing technique which
isn't the case in Cogl.
- In code, "CoglPipeline" will hopefully be a much more self documenting
summary of what these objects represent; a full GPU pipeline
configuration including, for example, vertex processing, fragment
processing and blending.
- When considering the API documentation story, at some point we need a
document introducing developers to how the "GPU pipeline" works so it
should become intuitive that CoglPipeline maps back to that
description of the GPU pipeline.
- This is consistent in terminology and concept to OpenGL 4's new
pipeline object which is a container for program objects.
Note: The cogl-material.[ch] files have been renamed to
cogl-material-compat.[ch] because otherwise git doesn't seem to treat
the change as a moving the old cogl-material.c->cogl-pipeline.c and so
we loose all our git-blame history.
This exposes the idea of a stack of source materials instead of just
having a single current material. This allows the writing of orthogonal
code that can change the current source material and restore it to its
previous state. It also allows the implementation of new composite
primitives that may want to validate the current source material and
possibly make override changes in a derived material.
This adds two new internal functions to create a foreign texture for
the texture 2d and rectangle backends. cogl_texture_new_from_foreign
will now use one of these backends directly if there is no waste
instead of always using the sliced texture backend.
This function creates a CoglBitmap which internally references a
CoglBuffer. The map and unmap functions will divert to mapping the
buffer. There are also now bind and unbind functions which should be
used instead of map and unmap whenever the data doesn't need to be
read from the CPU but will instead be passed to GL for packing or
unpacking. For bitmaps created from buffers this just binds the
bitmap.
cogl_texture_new_from_buffer now just uses this function to wrap the
buffer in a bitmap rather than trying to bind the buffer
immediately. This means that the buffer will be bound only at the
point right before the texture data is uploaded.
This approach means that using a pixel array will take the fastest
upload route if possible, but can still fallback to copying the data
by mapping the buffer if some conversion is needed. Previously it
would just crash in this case because the texture functions were all
passed a NULL pointer.
http://bugzilla.clutter-project.org/show_bug.cgi?id=2112
The CoglBitmap struct is now only defined within cogl-bitmap.c so that
all of its members can now only be accessed with accessor
functions. To get to the data pointer for the bitmap image you must
first call _cogl_bitmap_map and later call _cogl_bitmap_unmap. The map
function takes the same arguments as cogl_pixel_array_map so that
eventually we can make a bitmap optionally internally divert to a
pixel array.
There is a _cogl_bitmap_new_from_data function which constructs a new
bitmap object and takes ownership of the data pointer. The function
gets passed a destroy callback which gets called when the bitmap is
freed. This is similar to how gdk_pixbuf_new_from_data
works. Alternatively NULL can be passed for the destroy function which
means that the caller will manage the life of the pointer (but must
guarantee that it stays alive at least until the bitmap is
freed). This mechanism is used instead of the old approach of creating
a CoglBitmap struct on the stack and manually filling in the
members. It could also later be used to create a CoglBitmap that owns
a GdkPixbuf ref so that we don't necessarily have to copy the
GdkPixbuf data when converting to a bitmap.
There is also _cogl_bitmap_new_shared. This creates a bitmap using a
reference to another CoglBitmap for the data. This is a bit of a hack
but it is needed by the atlas texture backend which wants to divert
the set_region virtual to another texture but it needs to override the
format of the bitmap to ignore the premult flag.
Using 'r' to name the third component is problematic because that is
commonly used to represent the red component of a vector representing
a color. Under GLSL this is awkward because the texture swizzling for
a vector uses a single letter for each component and the names for
colors, textures and positions are synonymous. GLSL works around this
by naming the components of the texture s, t, p and q. Cogl already
effectively already exposes this naming because it exposes GLSL so it
makes sense to use that naming consistently. Another alternative could
be u, v and w. This is what Blender and Direct3D use. However the w
component conflicts with the w component of a position vertex.
When an intermediate buffer is used for downloading texture data it
was using the wrong byte length for a row so the copy back to the
user's buffer would fail.
The fallback for when glGetTexImage is not available renders the
texture to the framebuffer to read the data using glReadPixels. This
patch just sets the COGL_MATERIAL_FILTER_NEAREST filter mode on the
material before rendering to avoid linear filtering which would alter
the texture data.
The fallback for when glGetTexImage is not available draws parts of
the texture to the framebuffer and uses glReadPixels to extract the
data. However it was using cogl_rectangle to draw and then immediately
using raw glReadPixels to fetch the data. This won't cause a journal
flush so the rectangle won't necessarily have hit the framebuffer
yet. Instead it now uses cogl_read_pixels which does flush the
journal.
There was a lot of common code that was copied to all of the backends
to convert the data to a suitable format and wrap it into a CoglBitmap
so that it can be passed to _cogl_texture_driver_upload_subregion_to_gl.
This patch moves the common code to cogl-texture.c so that the virtual
just takes a CoglBitmap that is already in the right format.
Previously cogl_texture_get_data would pretty much directly pass on to
the get_data texture virtual function. This ended up with a lot of
common code that was copied to all of the backends. For example, the
method is expected to return the required data size if the data
pointer is NULL and to calculate its own rowstride if the rowstride is
0. Also it needs to convert the downloaded data if GL can't support
that format directly.
This patch moves the common code to cogl-texture.c so the virtual is
always called with a format that can be downloaded directly by GL and
with a valid rowstride. If the download fails then the virtual can
return FALSE in which case cogl-texture will use the draw and read
fallback.
This makes CoglBuffer track the last used bind target as a private
property. This is later used when binding a buffer to map instead of
always using the PIXEL_UNPACK target.
This also adds some additional sanity checks that code doesn't try to
nest binds to the same target or bind a buffer to multiple targets at
the same time.
The _cogl_texture_needs_premult_conversion function was already
checking whether the source format had an alpha channel before
returning TRUE, but it also doesn't make sense to do the premult
conversion if the destination format has no alpha. This patch adds
that check in too.
Instead of the ensure_mipmaps virtual that is only called whenever the
texture is about to be rendered with a min filter that needs the
mipmap, there is now a pre_paint virtual that is always called when
the texture is about to be painted in any way. It has a flags
parameter which is used to specify whether the mipmap will be needed.
This is useful for CoglTexturePixmapX11 because it needs to do stuff
before painting that is unrelated to mipmapping.
Instead of having a hardcoded series of if-statements in
cogl_is_texture to determine which types should appear as texture
subclasses, they are now stored in a GSList attached to the Cogl
context. The list is amended to using a new cogl_texture_register_type
function. There is a convenience macro called COGL_TEXTURE_DEFINE
which uses COGL_HANDLE_DEFINE_WITH_CODE to register the texture type
when the _get_type() function is first called.
This adds a _cogl_bind_gl_texture_transient function that should be used
instead of glBindTexture so we can have a consistent cache of the
textures bound to each texture unit so we can avoid some redundant
binding.
In commit abe91784c4 I changed cogl-texture so that it would use the
OpenGL mechanism to specify a different internal texture format from
the image format so that it can do the conversion instead of
Cogl. However under GLES the internal format and the image format must
always be the same and it only supports a limited set of formats. This
patch changes _cogl_texture_prepare_for_upload so that it does the
conversion using the cogl bitmap code when compiling for GLES.
http://bugzilla.openedhand.com/show_bug.cgi?id=2059
GL supports setting different wrap modes for the s, t and r
coordinates so we should design the backend interface to support that
also. The r coordinate is not currently used by any of the backends
but we might as well have it to make life easier if we ever add
support for 3D textures.
http://bugzilla.openedhand.com/show_bug.cgi?id=2063
Add a return result from CoglTexture.transform_quad_coords_to_gl(),
so that we can properly determine the nature of repeats in
the face of GL_TEXTURE_RECTANGLE_ARB, where the returned
coordinates are not normalized.
The comment "We also work out whether any of the texture
coordinates are outside the range [0.0,1.0]. We need to do
this after calling transform_coords_to_gl in case the texture
backend is munging the coordinates (such as in the sub texture
backend)." is disregarded and removed, since it's actually
the virtual coordinates that determine whether we repeat,
not the GL coordinates.
Warnings about disregarded layers are used in all cases where
applicable, including for subtextures.
http://bugzilla.openedhand.com/show_bug.cgi?id=2016
Signed-off-by: Neil Roberts <neil@linux.intel.com>
Since using addresses that might change is something that finally
the FSF acknowledge as a plausible scenario (after changing address
twice), the license blurb in the source files should use the URI
for getting the license in case the library did not come with it.
Not that URIs cannot possibly change, but at least it's easier to
set up a redirection at the same place.
As a side note: this commit closes the oldes bug in Clutter's bug
report tool.
http://bugzilla.openedhand.com/show_bug.cgi?id=521
An initial pass over the Cogl source code using the Clang static
analysis tool flagged a few low hanging issues such as un-used variables
or redundant initializing of variables which this patch fixes.
We've had complaints that our Cogl code/headers are a bit "special" so
this is a first pass at tidying things up by giving them some
consistency. These changes are all consistent with how new code in Cogl
is being written, but the style isn't consistently applied across all
code yet.
There are two parts to this patch; but since each one required a large
amount of effort to maintain tidy indenting it made sense to combine the
changes to reduce the time spent re indenting the same lines.
The first change is to use a consistent style for declaring function
prototypes in headers. Cogl headers now consistently use this style for
prototypes:
return_type
cogl_function_name (CoglType arg0,
CoglType arg1);
Not everyone likes this style, but it seems that most of the currently
active Cogl developers agree on it.
The second change is to constrain the use of redundant glib data types
in Cogl. Uses of gint, guint, gfloat, glong, gulong and gchar have all
been replaced with int, unsigned int, float, long, unsigned long and char
respectively. When talking about pixel data; use of guchar has been
replaced with guint8, otherwise unsigned char can be used.
The glib types that we continue to use for portability are gboolean,
gint{8,16,32,64}, guint{8,16,32,64} and gsize.
The general intention is that Cogl should look palatable to the widest
range of C programmers including those outside the Gnome community so
- especially for the public API - we want to minimize the number of
foreign looking typedefs.
OpenGL ES has no PBO extension, so we fallback to using a malloc'ed
buffer. Make sure the OpenGL-only defines don't leak into the OpenGL ES
compilation.
First, let's add a new public feature called, surprisingly,
COGL_FEATURE_PBOS to check the availability of PBOs and provide a
fallback path when running on older GL implementations or on OpenGL ES
In case the underlying OpenGL implementation does not provide PBOs, we
need a fallback path (a malloc'ed buffer). The CoglPixelBufer
constructors will instanciate a subclass of CoglBuffer that handles
map/unmap and set_data() with a malloc'ed buffer.
The public feature is useful to check before using set_data() on a
buffer as it will mean doing a memcpy() when not supporting PBOs (in
that case, it's better to create the texture directly instead of using a
CoglBuffer).
The only goal of using COGL buffers is to use them to create
textures. cogl_texture_new_from_buffer() is the new symbol to create
textures out of buffers.
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.
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 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.