Sometimes it would be useful if we could efficiently track when a matrix
stack has been modified. For example on GLES2 we have to upload the
modelview as a uniform to our glsl programs but because the modelview
state is part of the framebuffer state it becomes a bit more tricky to
know when to re-sync the value of the uniform with the framebuffer
state. This adds an "age" counter to CoglMatrixStack which is
incremented for any operation that effectively modifies the top of the
stack so now we can save the age of the stack inside the pipeline
whenever we update modelview uniform and later compare that with the
stack to determine if it has changed.
This returns the layer matrix given a pipeline and a layer index. The
API is kept as internal because it directly returns a pointer into the
layer private data to avoid a copy into an out-param. We might also
want to add a public function which does the copy.
When the GLES2 wrapper is removed we can't use the fixed function API
such as glColorPointer to set the builtin attributes. Instead the GLSL
progend now maintains a cache of attribute locations that are queried
with glGetAttribLocation. The code that previously maintained a cache
of the enabled texture coord arrays has been modified to also cache
the enabled vertex attributes under GLES2. The vertex attribute API is
now the only place that is using this cache so it has been moved into
cogl-vertex-attribute.c
Previously when stroking a path it was flushing a pipeline and then
directly calling glDrawArrays to draw the line strip from the path
nodes array. This patch changes it to build a CoglVertexArray and a
series of attributes to paint with instead. The vertex array and
attributes are attached to the CoglPath so it can be reused later. The
old vertex array for filling has been renamed to fill_vbo.
The code to display the source when the show-source debug option is
given has been moved to _cogl_shader_set_source_with_boilerplate so
that it will show both user shaders and generated shaders. It also
shows the code with the full boilerplate. To make it the same for
ARBfp, cogl_shader_compile_real now also dumps user ARBfp shaders.
The GLSL vertend is mostly only useful for GLES2. The fixed function
vertend is kept at higher priority than the GLSL vertend so it is
unlikely to be used in any other circumstances.
Due to Mesa bug 28585 calling glVertexAttrib with attrib location 0
doesn't appear to work. This patch just reorders the vertex and color
attributes in the shader in the hope that Mesa will assign the color
attribute to a different location.
Some builtin attributes such as the matrix uniforms and some varyings
were missing from the boilerplate for GLES2. This also moves the
texture matrix and texture coord attribute declarations to
cogl-shader.c so that they can be dynamically defined depending on the
number of texture coord arrays enabled.
The vertends are intended to flush state that would be represented in
a vertex program. Code to handle the layer matrix, lighting and
point size has now been moved from the common cogl-pipeline-opengl
backend to the fixed vertend.
'progend' is short for 'program backend'. The progend is intended to
operate on combined state from a fragment backend and a vertex
backend. The progend has an 'end' function which is run whenever the
pipeline is flushed and the two pipeline change notification
functions. All of the progends are run whenever the pipeline is
flushed instead of selecting a single one because it is possible that
multiple progends may be in use for example if the vertends and
fragends are different. The GLSL progend will take the shaders
generated by the fragend and vertend and link them into a single
program. The fragend code has been changed to only generate the shader
and not the program. The idea is that pipelines can share fragment
shader objects even if their vertex state is different. The authority
for the progend needs to be the combined authority on the vertend and
fragend state.
This adds two internal functions:
gboolean
_cogl_program_has_fragment_shader (CoglHandle handle);
gboolean
_cogl_program_has_vertex_shader (CoglHandle handle);
They just check whether any of the contained shaders are of that type.
The pipeline function _cogl_pipeline_find_codegen_authority has been
renamed to _cogl_pipeline_find_equivalent_parent and it now takes a
set of flags for the pipeline and layer state that affects the
authority. This is needed so that we can reuse the same code in the
vertend and progends.
Previously enabling and disabling textures was done whatever the
backend in cogl-pipeline-opengl. However enabling and disabling
texture targets only has any meaning if no fragment shaders are being
used so this patch moves the code to cogl-pipeline-fragend-fixed.
The GLES2 wrapper has also been changed to ignore enabledness when
deciding whether to update texture coordinate attribute pointers.
The current Cogl pipeline backends are entirely concerned with the
fragment processing state. We also want to eventually have separate
backends to generate shaders for the vertex processing state so we
need to rename the fragment backends. 'Fragend' is a somewhat weird
name but we wanted to avoid ending up with illegible symbols like
CoglPipelineFragmentBackendGlslPrivate.
We are currently using a pipeline as a key into our arbfp program cache
but because we weren't making a copy of the pipelines used as keys there
were times when doing a lookup in the cache would end up trying to
compare a lookup key with an entry key that would point to invalid
memory.
Note: the current approach isn't ideal from the pov that that key
pipeline may reference some arbitrarily large user textures will now be
kept alive indefinitely. The plan to improve on this is that we will
have a mechanism to create a special "key pipeline" which will derive
from the default Cogl pipeline (to avoid affecting the lifetime of
other pipelines) and only copy state from the original pipeline that
affects the arbfp program and will reference small dummy textures
instead of potentially large user textures.
In the arbfp backend there is a seqential approach to finding a suitable
arbfp program to use for a given pipeline; first we see if there's
already a program associated with the pipeline, 2nd we try and find a
program associated with the "arbfp-authority" 3rd we try and lookup a
program in a cache and finally we resort to starting code-generation for
a new program. This patch slightly reworks the code of these steps to
hopefully make them a bit clearer.
_cogl_pipeline_needs_blending_enabled tries to determine whether each
layer is using the default combine state. However it was using
argument 0 for both checks so the if-statement would never be true.
There are a set of "EvalFlags" that get passed to _cogl_pipeline_hash
that can tweak the semantics of what state is evaluated for hashing but
these flags weren't getting passed via the HashState state structure
so it would be undefined if you would get the correct semantics.
According to 9cc9033347 the windows headers #define near as nothing,
and presumable the same is true for 'far' too. Apparently this define is
to improve compatibility with code written for Windows 3.1, so it's good
that people will be able to incorporate such code into their Clutter
applications.
We were trying to declare and initializing an arbfp program cache for
GLES but since the prototypes for the _hash and _equal functions were
only available for GL this broke the GLES builds. By #ifdefing the code
to conditionally declare/initialize for GL only this should hopefully
fix GLES builds.
The constant 'True' is defined by Xlib which isn't used for all clutter
builds so this replaces occurrences of True with TRUE which is defined
by glib. This should hopefully fix the win32 builds.
This adds a cache (A GHashTable) of ARBfp programs and before ever
starting to code-generate a new program we will always first try and
find an existing program in the cache. This uses _cogl_pipeline_hash and
_cogl_pipeline_equal to hash and compare the keys for the cache.
There is a new COGL_DEBUG=disable-program-caches option that can disable
the cache for debugging purposes.
This allows us to get a hash for a set of state groups for a given
pipeline. This can be used for example to get a hash of the fragment
processing state of a pipeline so we can implement a cache for compiled
arbfp/glsl programs.
_cogl_pipeline_equal now accepts a mask of pipeline differences and layer
differences to constrain what state will be compared. In addition a set
of flags are passed that can tweak the comparison semantics for some
state groups. For example when comparing layer textures we sometimes
only need to compare the texture target and can ignore the data itself.
In updating the code this patch also changes it so all required pipeline
authorities are resolved in one step up-front instead of resolving the
authority for each state group in turn and repeatedly having to traverse
the pipeline's ancestry. This adds two new functions
_cogl_pipeline_resolve_authorities and
_cogl_pipeline_layer_resolve_authorities to handle resolving a set of
authorities.
This removes the unused array of per-packend priv data pointers
associated with every CoglPipelineLayer. This reduces the size of all
layer allocations and avoids having to zero an array for each
_cogl_pipeline_layer_copy.
A non-static function named cogl_object_get_type was inadvertently added
during the addition of the CoglObject base type, but there is no public
prototype in the headers and it's only referenced inside cogl-object.c
to implement cogl_handle_get_type() for compatibility. This removes the
function since we don't want to commit to CoglObject always simply being
a boxed type. In the future we may want to register hierarchical
GTypeInstance based types.
To allow us to have gobject properties that accept a CoglMatrix value we
need to register a GType. This adds a cogl_gtype_matrix_get_type function
that will register a static boxed type called "CoglMatrix".
This adds a new section to the reference manual for GType integration
functions.
As a pre-requisite for being able to register a boxed GType for
CoglMatrix (enabling us to define gobject properties that accept a
CoglMatrix) this adds cogl_matrix_copy and _free functions.
In _cogl_pipeline_needs_blending_enabled after first checking whether
the property most recently changed requires blending we would then
resort to checking all other properties too in case some other state
also requires blending. We now avoid checking all other properties in
the case that blending was previously disabled and checking the property
recently changed doesn't require blending.
Note: the plan is to improve this further by explicitly keeping track
of the properties that currently cause blending to be enabled so that we
never have to resort to checking all other properties we can constrain
the checks to those masked properties.
This moves _cogl_pipeline_get_parent and _cogl_pipeline_get_authority
into cogl-pipeline-private.h so they can be inlined since they have been
seen to get quite high in profiles. Given that they both contain such
small amounts of code the function call overhead is significant.
This adds a debug option called disable-software-clipping which causes
the journal to always log the clip stack state rather than trying to
manually clip rectangles.
Before flushing the journal there is now a separate iteration that
will try to determine if the matrix of the clip stack and the matrix
of the rectangle in each entry are on the same plane. If they are it
can completely avoid the clip stack and instead manually modify the
vertex and texture coordinates to implement the clip. The has the
advantage that it won't break up batching if a single clipped
rectangle is used in a scene.
The software clip is only used if there is no user program and no
texture matrices. There is a threshold to the size of the batch where
it is assumed that it is worth the cost to break up a batch and
program the GPU to do the clipping. Currently this is set to 8
although this figure is plucked out of thin air.
To check whether the two matrices are on the same plane it tries to
determine if one of the matrices is just a simple translation of the
other. In the process of this it also works out what the translation
would be. These values can be used to translate the clip rectangle
into the coordinate space of the rectangle to be logged. Then we can
do the clip directly in the rectangle's coordinate space.
Previously in cogl-clip-state.c when it detected that the current
modelview matrix is screen-aligned it would convert the clip entry to
a window clip. Instead of doing this cogl-clip-stack.c now contains
the detection and keeps the entry as a rectangle clip but marks that
it is entirely described by its scissor rect. When flusing the clip
stack it doesn't do anything extra for entries that have this mark
(because the clip will already been setup by the scissor). This is
needed so that we can still track the original rectangle coordinates
and modelview matrix to help detect when it would be faster to modify
the rectangle when adding it to the journal rather than having to
break up the batch to set the clip state.
When logging a quad we now only store the 2 vertices representing the
top left and bottom right of the quad. The color is only stored once
per entry. Once we come to upload the data we expand the 2 vertices
into four and copy the color to each vertex. We do this by mapping the
buffer and directly expanding into it. We have to copy the data before
we can render it anyway so it doesn't make much sense to expand the
vertices before uploading and this way should save some space in the
size of the journal. It also makes it slightly easier if we later want
to do pre-processing on the journal entries before uploading such as
doing software clipping.
The modelview matrix is now always copied to the journal entry whereas
before it would only be copied if we aren't doing software
transform. The journal entry struct always has the space for the
modelview matrix so hopefully it's only a small cost to copy the
matrix.
The transform for the four entries is now done using
cogl_matrix_transform_points which may be slightly faster than
transforming them each individually with a call to
cogl_matrix_transfom.
This reverts commit 4cfe90bde2.
GLSL 1.00 on GLES doesn't support unsized arrays so the whole idea
can't work.
Conflicts:
clutter/cogl/cogl/cogl-pipeline-glsl.c
The check for whether we can reuse a program we've already generated
was only being done if the pipeline already had a
glsl_program_state. When there is no glsl_program_state it then looks
for the nearest ancestor it can share the program with. It then
wasn't checking whether that ancestor already had a GL program so it
would start generating the source again. It wouldn't however compile
that source again because _cogl_pipeline_backend_glsl_end does check
whether there is already a program. This patch moves the check until
after it has found the glsl_program_state, whether or not it was found
from an ancestor or as its own state.
Under GLES2 we were defining the cogl_tex_coord_in varying as an array
with a size determined by the number of texture coordinate arrays
enabled whenever the program is used. This meant that we may have to
regenerate the shader with a different size if the shader is used with
more texture coord arrays later. However in OpenGL the equivalent
builtin varying gl_TexCoord is simply defined as:
varying vec4 gl_TexCoord[]; /* <-- no size */
GLSL is documented that if you declare an array with no size then you
can only access it with a constant index and the size of the array
will be determined by the highest index used. If you want to access it
with a non-constant expression you need to redeclare the array
yourself with a size.
We can replicate the same behaviour in our Cogl shaders by instead
declaring the cogl_tex_coord_in with no size. That way we don't have
to pass around the number of tex coord attributes enabled when we
flush a material. It also means that CoglShader can go back to
directly uploading the source string to GL when cogl_shader_source is
called so that we don't have to keep a copy of it around.
If the user wants to access cogl_tex_coord_in with a non-constant
index then they can simply redeclare the array themself. Hopefully
developers will expect to have to do this if they are accustomed to
the gl_TexCoord array.
When compiling for GLES2, the codegen is affected by state other than
the layers. That means when we find an authority for the codegen state
we can't directly look at authority->n_layers to determine the number
of layers because it isn't necessarily the layer state authority. This
patch changes it to use cogl_pipeline_get_n_layers instead. Once we
have two authorities that differ in codegen state we then compare all
of the layers to decide if they would affect codegen. However it was
ignoring the fact that the authorities might also differ by the other
codegen state. This path also adds an extra check for whether
_cogl_pipeline_compare_differences contains any codegen bits other
than COGL_PIPELINE_STATE_LAYERS.
When determining if a layer would require a different shader to be
generated it needs to check a certain set of state changes and it
needs to check whether the texture target is different. However it was
checking whether texture texture was different only if the other state
was also different which doesn't make any sense. It also only checked
the texture difference if that was the only state change which meant
that effectively the code was impossible to reach. Now it does the
texture target check indepent of the other state changes.
The fixed pipeline backend wasn't correctly flushing the combine
constant because it was using the wrong flag to determine if the
combine constant has changed since the last flushed material.
When enabling a unit that was disabled from a previous flush pipeline
it was forgetting to rebind the right texture unit so it wouldn't
work. This was causing the redhand to disappear when using the fixed
function backend in test-cogl-multitexture if anything else is added
to the scene.
For shader generation backends we don't need to worry about changes to
the texture object and changing the user matrix. The missing user
matrix flag was causing test-cogl-multitexture to regenerate the
shader every frame.
Having ctx here produces a warning on GLES. However it's needed for Big
GL as we have at the top of the file:
#ifdef HAVE_COGL_GL
#define glClientActiveTexture ctx->drv.pf_glClientActiveTexture
#endif
This reverts commit 27a3a2056a.
In 6246c2bd6 I moved the code to add the boilerplate to a shader to a
separate function and also made it so that the common boilerplate is
added as a separate string to glShaderSource. However I didn't notice
that the #define for the vertex and fragment shaders already includes
the common part so it was being added twice. Mesa seems to accept this
but it was causing problems on the IMG driver because COGL_VERSION was
defined twice.
Before commit 49898d43 CoglPipeline would compare whether a pipeline
layer's texture is equal by fetching the underlying GL handle. I
changed that so that it would only compare the CoglHandles because
that commit removes the GL handle texture overrides and sliced
textures instead log the underlying primitive texture. However I
forgot that the primitives don't always use
_cogl_texture_foreach_sub_texture_in_region when the quad fits within
the single texture so it won't use a texture override. This meant that
atlas textures and sub textures get logged with the atlas handle so
the comparison still needs to be done using the GL handles. It might
be nice to add a CoglTexture virtual to get the underlying primitive
texture instead to avoid having the pipeline poke around with GL
handles.
If we have to make override changes to the user's source material to
handle cogl_polygon then we need to make sure we unref the override
material at the end.
Previously we used the layers->backend_priv[] members to determine when
to notify backends about layer changes, but it entirely up to the
backends if they want to associate private state with layers, even
though they may still be interested in layer change notifications (they
may associate layer related state with the owner pipeline).
We now make the observation that in
_cogl_pipeline_backend_layer_change_notify we should be able to assume
there can only be one backend currently associated with the layer
because we wouldn't allow changes to a layer with multiple dependants.
This means we can determine the backend to notify by looking at the
owner pipeline instead.
The features_cached member of CoglContext is intended to mark when
we've calculated the features so that we know if they are ready in
cogl_get_features. However we always intialize the features while
creating the context so features_cached will never be FALSE so it's
not useful. We also had the odd behaviour that the COGL_DEBUG feature
overrides were only applied in the first call to
cogl_get_features. However there are other functions that use the
feature flags such as cogl_features_available that don't use this
function so in some cases the feature flags will be interpreted before
the overrides are applied. This patch makes it always initialize the
features and apply the overrides immediately while creating the
context. This fixes a problem with COGL_DEBUG=disable-arbfp where the
first material flushed is done before any call to cogl_get_features so
it may still use ARBfp.
Now that the GLSL backend can generate code it can effectively handle
any pipeline unless there is an ARBfp program. However with current
open source GL drivers the ARBfp compiler is more stable so it makes
sense to prefer ARBfp when possible. The GLSL backend is also lower
than the fixed function backend on the assumption that any driver that
supports GLSL will also support ARBfp so it's quicker to try the fixed
function backend next.
This adds COGL_DEBUG=disable-fixed to disable the fixed function
pipeline backend. This is needed to test the GLSL shader generation
because otherwise the fixed function backend would always override it.
We don't want to use gl_PointCoord to implement point sprites on big
GL because in that case we already use glTexEnv(GL_COORD_REPLACE) to
replace the texture coords with the point sprite coords. Although GL
also supports the gl_PointCoord variable, it requires GLSL 1.2 which
would mean we would have to declare the GLSL version and check for
it. We continue to use gl_PointCoord for GLES2 because it has no
glTexEnv function.
The GLES2 wrapper no longer needs to generate any fragment shader
state because the GLSL pipeline backend will always give the wrapper a
custom fragment shader. This simplifies a lot of the state comparison
done by the wrapper. The fog generation is also removed even though
it's actually part of the vertex shader because only the fixed
function pipeline backend actually calls the fog functions so it would
be disabled when using any of the other backends anyway. We can fix
this when the two shader backends also start generating vertex
shaders.
GLES2 has no glAlphaFunc function so we need to simulate the behaviour
in the fragment shader. The alpha test function is simulated with an
if-statement and a discard statement. The reference value is stored as
a uniform.
Previously the flag to mark the differences for the alpha test
function and reference value were conflated into one. However this is
awkward when generating shader code to simulate the alpha testing for
GLES 2 because in that case changing the function would need a
different program but changing the reference value just requires
updating a uniform. This patch makes the function and reference have
their own state flags.
The GLSL shader generation supports layer combine constants so there's
no need to disable it for GLES2. It looks like there was also code for
it in the GLES2 wrapper so I'm not sure why it was disabled in the
first place.
The GLSL pipeline backend can now generate code to represent the
pipeline state in a similar way to the ARBfp backend. Most of the code
for this is taken from the GLES 2 wrapper.
_cogl_shader_compile_real had some code to create a set of strings to
combine the boilerplate code with a shader before calling
glShaderSource. This has now been moved to its own internal function
so that it could be used from the GLSL pipeline backend as well.
need_texture_combine_separate is moved to cogl-pipeline.c and renamed
to _cogl_pipeline_need_texture_combine_separate. The function is
needed by both the ARBfp and GLSL codegen backends so it makes sense to
share it.
The code for finding the arbfp authority for a pipeline should be the
same as finding the GLSL authority. So that the code can be shared the
function has been moved to cogl-pipeline.c and renamed to
_cogl_pipeline_find_codegen_authority.
Only one of the material backends can be generating code at the same
time so it seems to make sense to share the same source buffer between
arbfp and glsl. The new name is fragment_source_buffer in case we
later want to create a new buffer for the vertex shader. That probably
couldn't share the same buffer because it will likely need to be
generated at the same time.
* 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
Previously in cogl_read_pixels we assume the format of the framebuffer
is always premultiplied because that is the most likely format with
the default Cogl blend mode. However when the framebuffer is bound to
a texture we should be able to make a better guess at the format
because we know the texture keeps track of the premult status. This
patch adds an internal format member to CoglFramebuffer. For onscreen
framebuffers we still assume it is RGBA_8888_PRE but for offscreen to
textures we copy the texture format. cogl_read_pixels uses this to
determine whether the data returned by glReadPixels will be
premultiplied.
http://bugzilla.clutter-project.org/show_bug.cgi?id=2414
When converting the data in cogl_read_pixels it was using bmp_format
instead of the format passed in to the function. bmp_format is the
same as the passed in format except that it always has the premult bit
set. Therefore the conversion would not handle premultiply correctly.
http://bugzilla.clutter-project.org/show_bug.cgi?id=2414
This is the same as _cogl_read_pixels except that it takes a rowstride
parameter for the destination buffer. Under OpenGL setting the
rowstride this will end up calling GL_ROW_LENGTH so that the buffer
region can be directly written to. Under GLES GL_ROW_LENGTH is not
supported so it will use an intermediate buffer as it does if the
format is not GL_RGBA.
cogl_read_pixels now just calls the full version of the function with
the rowstride set to width*bpp.
http://bugzilla.clutter-project.org/show_bug.cgi?id=2414
This function is the same as cogl_offscreen_new_to_texture but it
takes a level parameter and a set of flags so that FBOs can be used to
render to higher mipmap levels and to disable the depth and stencil
buffers. cogl_offscreen_new_to_texture now just calls the new function
with the level set to zero. This function could be useful in a few
places in Cogl where we want to use FBOs as an implementation detail
such as when copying between textures.
http://bugzilla.clutter-project.org/show_bug.cgi?id=2414
When uploading a 3D texture with an awkward rowstride, on GLES Cogl
will copy the images to an intermediate buffer to pass to GL. However
it was using the wrong height when copying the data so it would end up
overflowing the buffer and crashing.
Since we're using CoglPipelineWrapModeInternal in the internal API
anyway, and the compiler complains loudly when comparing two enumeration
types without casting, the PipelineLayer struct should store the
wrap modes using the internal enumeration.
When using clip planes and we we have to project some vertices into
screen coordinates we used to transform those by the modelview and then
the projection matrix separately. Now we combine the modelview and
projection matrix and then use that to transform the vertices in one
step instead.
When logging quads in the journal it used to be possible to specify a
mask of fallback layers (layers where a default white texture should be
used in-place of the corresponding texture in the current source
pipeline). Since we now handle fallbacks for cogl_rectangle* primitives
when validating the pipeline up-front before logging in the journal we
no longer need the ability for the journal to apply fallbacks too.
This add two new function that allows us to transform or project an
array of points instead of only transforming one point at a time. Recent
benchmarking has shown cogl_matrix_transform_point to be a bottleneck
sometimes, so this should allow us to reduce the overhead when
transforming lots of vertices at the same time, and also reduce the cost
of 3 component, non-projective transforms.
For now they are marked as experimental (you have to define
COGL_ENABLE_EXPERIMENTAL_API) because there is some concern that it
introduces some inconsistent naming. cogl_matrix_transform_point would
have to be renamed cogl_matrix_project_point to be consistent, but that
would be an API break.
Switch _cogl_rectangles_with_multitexture_coords to using
_cogl_pipeline_foreach_layer to iterate the layers of a pipeline when
validating instead of iterating the pipelines internal list, which is
risky since any modifications to pipelines (even to an override pipeline
derived from the original), could potentially corrupt the list as it is
being iterated.
This removes the possibility to specify wrap mode overrides within a
CoglPipelineFlushOptions struct since the right way to handle these
overrides is by copying the user's material and making the changes to
that copy before flushing. All primitives code has already switched away
from using these wrap mode overrides so this patch just removes unused
code and types. It also remove the wrap_mode_overrides argument for
_cogl_journal_log_quad.
With the refactoring to centralize code into CoglBuffer,
_cogl_buffer_fini() was never actually implemented, so all GL
vertex and index buffer objects were leaked.
The duplicate call to glDeleteBuffers() in CoglPixelArray is
removed (it wasn't paying attention to whether the buffer had been
allocated as a PBO or not.)
http://bugzilla.clutter-project.org/show_bug.cgi?id=2423
This adds a COGL_DEBUG=wireframe option to visualize the underlying
geometry of the primitives being drawn via Cogl. This works for triangle
list, triangle fan, triangle strip and quad (internal only) primitives.
It also works for indexed vertex arrays.
In cogl_vertex_buffer_indices_get_for_quads() we sometimes have to
extend the length of an existing array, but when we came to unref the
previous array we didn't first check that it wasn't simply NULL.
This adds an optional data argument for cogl_vertex_array_new() since it
seems that mostly every case where we use this API we follow up with a
cogl_buffer_set_data() matching the size of the new array. This
simplifies all those cases and whenever we want to delay uploading of
data then NULL can simply be passed.
There's no longer any need to use the GL handle in the callback for
_cogl_texture_foreach_sub_texture_in_region because it can now work in
terms of primitive cogl textures so it has now been removed. This
would be helpful if we ever want to make the foreach function public
so that apps could implement their own primitives using sliced
textures.
Since d5634e37 the sliced texture backend now works in terms of
CoglTexture2Ds so there's no need to have special casing for
overriding the texture of a pipeline layer with a GL handle. Instead
we can just use cogl_pipeline_set_layer_texture with the
CoglHandle. The special _cogl_pipeline_set_layer_gl_texture_slice
function has now been removed and parts of the code for comparing
materials have been simplified.
The cogl_texture_foreach_sub_texture_in_region virtual for the sliced
texture backend was previously passing the CoglHandle of the sliced
texture to the callback. Since d5634e37 the slice texture backend now
works in terms of 2D textures so it's possible to pass the underlying
slice texture as a handle too. This makes all of the foreach callbacks
consistent in that they pass a CoglHandle of the primitive texture
type that matches the GL handle.
When COGL_ENABLE_EXPERIMENTAL_2_0_API is defined cogl.h will now include
cogl2-path.h which changes cogl_path_new() so it can directly return a
CoglPath pointer; it no longer exposes a prototype for
cogl_{get,set}_path and all the remaining cogl_path_ functions now take
an explicit path as their first argument.
The idea is that we want to encourage developers to retain path objects
for as long as possible so they can take advantage of us uploading the
path geometry to the GPU. Currently although it is possible to start a
new path and query the current path, it is not convenient.
The other thing is that we want to get Cogl to the point where nothing
depends on a global, current context variable. This will allow us to one
day define a sensible threading model if/when that is ever desired.
For now this new define is simply an alias for
COGL_ENABLE_EXPERIMENTAL_API but the intention is that we will also use
it to start experimenting with changes that need to break the existing
Cogl API in incompatible ways.
We now prepend a set of defines to any given GLSL shader so that we can
define builtin uniforms/attributes within the "cogl" namespace that we
can use to provide compatibility across a range of the earlier versions
of GLSL.
This updates test-cogl-shader-glsl.c and test-shader.c so they no longer
needs to special case GLES vs GL when splicing together its shaders as
well as the blur, colorize and desaturate effects.
To get a feel for the new, portable uniform/attribute names here are the
defines for OpenGL vertex shaders:
#define cogl_position_in gl_Vertex
#define cogl_color_in gl_Color
#define cogl_tex_coord_in gl_MultiTexCoord0
#define cogl_tex_coord0_in gl_MultiTexCoord0
#define cogl_tex_coord1_in gl_MultiTexCoord1
#define cogl_tex_coord2_in gl_MultiTexCoord2
#define cogl_tex_coord3_in gl_MultiTexCoord3
#define cogl_tex_coord4_in gl_MultiTexCoord4
#define cogl_tex_coord5_in gl_MultiTexCoord5
#define cogl_tex_coord6_in gl_MultiTexCoord6
#define cogl_tex_coord7_in gl_MultiTexCoord7
#define cogl_normal_in gl_Normal
#define cogl_position_out gl_Position
#define cogl_point_size_out gl_PointSize
#define cogl_color_out gl_FrontColor
#define cogl_tex_coord_out gl_TexCoord
#define cogl_modelview_matrix gl_ModelViewMatrix
#define cogl_modelview_projection_matrix gl_ModelViewProjectionMatrix
#define cogl_projection_matrix gl_ProjectionMatrix
#define cogl_texture_matrix gl_TextureMatrix
And for fragment shaders we have:
#define cogl_color_in gl_Color
#define cogl_tex_coord_in gl_TexCoord
#define cogl_color_out gl_FragColor
#define cogl_depth_out gl_FragDepth
#define cogl_front_facing gl_FrontFacing
When converting the virtual coordinates of the underlying texture for
a slice to virtual coordinates for the whole texture it was using the
size and offset of the intersection as the size of the child
texture. This would be incorrect if the texture contains waste or the
texture coordinates are not the default. Instead the sliced foreach
function now passes the CoglSpan to the callback instead of the
intersection.
http://bugzilla.clutter-project.org/show_bug.cgi?id=2398
Previously in the tests/tools directory we build a disable-npots
library which was used as an LD_PRELOAD to trick Cogl in to thinking
there is no NPOT texture extension. This is a little awkward to use so
it seems much simpler to just define a COGL_DEBUG option to disable
npot textures.
In some micro-benchmarks testing journal throughput the list
manipulation jumps pretty high in the profile. This replaces the GSList
usage with a GArray instead which is effectively a grow only allocation
that means we avoid ongoing allocations while manipulating the stack
mid-scene.
During _cogl_pipeline_needs_blending_enabled we were always checking the
current lighting properties (ambient,diffuse,specular,emission) which
had a notable impact during micro-benchmarks that exercise journal
throughput of simple colored rectangles. This #if 0's the offending code
considering that Cogl doesn't actually support lighting currently and
when it actually does then we will be able to optimize this by avoiding
the checks when lighting is disabled.
When using cogl_set_source_color4ub there is a notable difference
between colors that require blending and those that dont. When trying to
modify the color of pipeline referenced by the journal we don't force a
flush of the journal unless the color change will also change the
blending state. By using two separate pipeline objects for handing
opaque or transparent colors we can avoid ever flushing the journal when
repeatedly using cogl_set_source_color and jumping between opaque and
transparent colors.
This reworks _cogl_texture_quad_multiple_primitives so instead of using
the CoglPipelineWrapModeOverrides mechanism to force the clamp to edge
repeat mode we now derive an override pipeline using cogl_pipeline_copy
instead. This avoids a relatively large, unconditional, memset.
This avoids using the wrap mode overrides mechanism to implement
_cogl_multitexture_quad_single_primitive which requires memsetting a
fairly large array. This updates it to use cogl_pipeline_foreach_layer()
and we now derive an override_material to handle changes to the wrap
modes instead of using the CoglPipelineWrapModeOverrides.
Previously there was a check to avoid filling the path if there are
zero nodes. However the tesselator also won't generate any triangles
if there are less than 3 nodes so we might as well bail out in that
case too. If we don't emit any triangles then we would end up trying
to create an empty VBO. Although I don't think this should necessarily
be a problem, this seems to cause Mesa to segfault in version 7.8.1
when calling glBufferSubData (although not in
master). test-cogl-primitives tries to fill a path with only two
points so it's convenient to be able to avoid the crash in this case.
When adding a new entry to the journal a reference is now taken on the
current clip stack. Modifying the current clip state no longer causes
a journal flush. The journal flushing code now has an extra stage to
compare the clip state of each entry. The comparison can simply be
done by comparing the pointers. Although different clip states will
still end up with multiple draw calls this at leasts allows a scene
comprising of multiple different clips to be upload with one vbo. It
also lays the groundwork to do certain tricks when drawing clipped
rectangles such as modifying the geometry instead of setting a clip
state.
This adds a flag to avoid flushing the clip state when flushing the
framebuffer state. This will be used by the journal to manage its own
clip state flushing.
Flushing the clip state no longer does anything that would cause the
journal to flush. The clip state is only flushed when flushing the
framebuffer state and in all cases this ends up flushing the journal
in one way or another anyway. Avoiding flushing the journal will make
it easier to log the clip state in the journal.
Previously when trying to set up a rectangle clip that can't be
scissored or when using a path clip the code would use cogl_rectangle
as part of the process to fill the stencil buffer. This is now changed
to use a new internal _cogl_rectangle_immediate function which
directly uses the vertex array API to draw a triangle strip without
affecting the journal. This should be just as efficient as the
previous journalled code because these places would end up flushing
the journal immediately before and after submitting the single
rectangle anyway and flushing the journal always creates a new vbo so
it would effectively do the same thing.
Similarly there is also a new internal _cogl_clear function that does
not flush the journal.
Previously we tracked whether the clip stack needs flushing as part of
the CoglClipState which is part of the CoglFramebuffer state. This is
a bit odd because most of the clipping state (such as the clip planes
and the scissor) are part of the GL context's state rather than the
framebuffer. We were marking the clip state on the framebuffer dirty
every time we change the framebuffer anyway so it seems to make more
sense to have the dirtiness be part of the global context.
Instead of a just a single boolean to record whether the state needs
flushing, the CoglContext now holds a reference to the clip stack that
was flushed. That way we can flush arbitrary stack states and if it
happens to be the same as the state already flushed then Cogl will do
nothing. This will be useful if we log the clip stack in the journal
because then we will need to flush unrelated clip stack states for
each batch.
Instead of having a separate CoglHandle for CoglClipStack the code is
now expected to directly hold a pointer to the top entry on the
stack. The empty stack is then the NULL pointer. This saves an
allocation when we want to copy the stack because we can just take a
reference on a stack entry. The idea is that this will make it
possible to store the clip stack in the journal without any extra
allocations.
The _cogl_get_clip_stack and set functions now take a CoglClipStack
pointer instead of a handle so it would no longer make sense to make
them public. However I think the only reason we would have wanted that
in the first place would be to save the clip state between switching
FBOs and that is no longer necessary.
CoglVertexAttribute has an internal draw function that is used by the
CoglJournal to avoid the call to cogl_journal_flush which would
otherwise end up recursively flushing the journal forever. The
enable_gl_state function called by this was previously also calling
_cogl_flush_framebuffer_state. However the journal code tries to
handle this function specially by calling it with a flag to disable
flushing the modelview matrix. This is useful because the journal
handles flushing the modelview itself. Without this patch the journal
state ends up getting flushed twice. This isn't a particularly big
problem currently because the matrix stack has caching to recognise
when it would push the same state twice and bails out. However if we
later want to use the framebuffer flush flags to override a particular
state of the framebuffer (such as the clip state) then we need to make
sure the flush isn't called twice.
Unless the CoglBuffer is being used for texture data then it's
relatively unlikely that the data will contain an array of bytes. For
example if it's used as a vertex array then it's more likely to be
floats or some vertex struct. In that case it's much more convenient
if set_data and map use void* pointers so that we can avoid a cast.
The convenience constructors for the builtin vertex structs were
creating the primitive and then immediately destroying it and
returning the pointer. I think the intention was to unref the
attributes instead. This adds an internal wrapper around the
new_with_attributes_array constructor which unrefs the attributes
instead of the primitive. The convenience constructors now use that.
The GLES2 wrapper was referring to COGL_MATERIAL_PROGRAM_TYPE_GLSL but
this has since been renamed to COGL_PIPELINE_PROGRAM_TYPE_GLSL so the
GLES2 backend wouldn't compile.
The gles2 wrapper functions don't understand about the CoglBuffer API so
they don't support attributes stored in a CoglVertexArray. Instead of
teaching the backend about buffers we are going to wait until we have
overhauled the GLES 2 backend. We are currently making progress
consolidating the GLES 2 backend with a new GLSL backend for
CoglMaterial. This will hugely simplify the GLES 2 support and share
code with the OpenGL backend. In the end it's hoped that this problem
will simply go away so it doesn't make much sense to solve it with the
current design.
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 updates the implementation of cogl_polygon so it sits on the new
CoglVertexArray and CoglVertexAttribute apis. This lets us minimize the
number of different drawing paths we have to maintain in Cogl.
Since the sliced texture support for cogl_polygon has been broken for a
long time now and no one has complained this patch also greatly
simplifies the code by not doing any special material validation so
cogl_polygon will be restricted in the same way as
cogl_draw_vertex_attributes. (i.e. sliced textures not supported).
Instead of using raw OpenGL in the journal we now use the vertex
attributes API instead. This is part of an ongoing effort to reduce the
number of drawing paths we maintain in Cogl.
The functionality of cogl_vertex_buffer_indices_get_for_quads is now
provided by cogl_get_rectangle_indices so this reworks the former to now
work in terms of the latter so we don't have duplicated logic.
As part of an ongoing effort to reduce the number of draw paths we have
in Cogl this re-works CoglVertexBuffer to use the CoglVertexAttribute
and CoglPrimitive APIs instead of using raw GL.
This adds a way to mark that a primitive is in use so that modifications
will generate a warning. The plan is to use this mechanism when batching
primitives in the journal to warn users that mid-scene modifications of
primitives is not allowed.
This adds convenience primitive constructors named like:
cogl_primitive_new_p3 or
cogl_primitive_new_p3c4 or
cogl_primitive_new_p3t2c4
where the letters correspond to the interleved vertex attributes layouts
such as CoglP3Vertex which is a struct with 3 float x,y,z members for
the [p]osition, or CoglP3T2C4Vertex which is a struct with 3 float x,y,z
members for the [p]osition, 2 float s,t members for the [t]exture
coordinates and 4 unsigned byte r,g,b,a members for the [c]olor.
The hope is that people will find these convenient enough to replace
cogl_polygon.
A CoglPrimitive is a retainable object for drawing a single primitive,
such as a triangle strip, fan or list.
CoglPrimitives build on CoglVertexAttributes and CoglIndices which
themselves build on CoglVertexArrays and CoglIndexArrays respectively.
A CoglPrimitive encapsulates enough information such that it can be
retained in a queue (e.g. the Cogl Journal, or renderlists in the
future) and drawn at some later time.
A CoglVertexAttribute defines a single attribute contained in a
CoglVertexArray. I.e. a CoglVertexArray is simply a buffer of N bytes
intended for containing a collection of attributes (position, color,
normals etc) and a CoglVertexAttribute defines one such attribute by
specifying its start offset in the array, its type, the number of
components and the stride etc.
CoglIndices define a range of indices inside a CoglIndexArray. I.e. a
CoglIndexArray is simply a buffer of N bytes and you can then
instantiate multiple CoglIndices collections that define a sub-region of
a CoglIndexArray by specifying a start offset and an index data type.
This adds a new CoglVertexArray object which is a subclass of CoglBuffer
used to hold vertex attributes. A later commit will add a
CoglVertexAttribute API which will be used to describe the attributes
inside a CoglVertexArray.
A CoglIndexArray is a subclass of CoglBuffer and will be used to hold
vertex indices. A later commit will add a CoglIndices API which will
allow describing a range of indices inside a CoglIndexArray.
This adds an internal mechanism to mark that a buffer is in-use so that
a warning can be generated if the user attempts to modify the buffer.
The plans is for the journal to use this mechanism so that we can warn
users about mid-scene modifications of buffers.
We now make _cogl_buffer_bind return a base pointer for the bound buffer
which can be used with OpenGL. The pointer will be NULL for GPU based
buffers or may point to an malloc'd buffer. Since OpenGL expects an
offset instead of a pointer when dealing with buffer objects this means
we can handle fallback malloc buffers and GPU buffers in a consistent
way.
This allows _cogl_material_flush_gl_state to bail out faster if
repeatedly asked to flush the same material and we can see the material
hasn't changed.
Since we can rely on the material age incrementing when any material
property changes or any associated layer property changes then we can
track the age of the material after flushing so it can be compared with
the age of the material if it is subsequently re-flushed. If the age is
the same we only have to re-assert the texture object state.
MaterialNodes are used for the sparse graph of material state and layer
state. In the case of materials there is the idea of weak materials that
don't take a reference on their parent and in that case we need to be
careful not to unref our parent during
_cogl_material_node_unparent_real. This adds a has_parent_reference
member to the CoglMaterialNode struct so we now know when to skip the
unref.
If there is private data associated with a CoglObject then there may be
a user_data_array that needs to be freed. The code was mistakenly
freeing the array inside the loop that was actually iterating over the
user data array notifying the objects destruction instead of waiting
until all the data entries had been destroyed.
This merges the two implementations of CoglProgram for the GLES2 and
GL backends into one. The implementation is more like the GLES2
version which would track the uniform values and delay sending them to
GL. CoglProgram is now effectively just a GList of CoglShaders along
with an array of stored uniform values. CoglProgram never actually
creates a GL program, instead this is left up to the GLSL material
backend. This is necessary on GLES2 where we may need to relink the
user's program with different generated shaders depending on the other
emulated fixed function state. It will also be necessary in the future
GLSL backends for regular OpenGL. The GLSL and ARBfp material backends
are now the ones that create and link the GL program from the list of
shaders. The linked program is attached to the private material state
so that it can be reused if the CoglProgram is used again with the
same material. This does mean the program will get relinked if the
shader is used with multiple materials. This will be particularly bad
if the legacy cogl_program_use function is used because that
effectively always makes one-shot materials. This problem will
hopefully be alleviated if we make a hash table with a cache of
generated programs. The cogl program would then need to become part of
the hash lookup.
Each CoglProgram now has an age counter which is incremented every
time a shader is added. This is used by the material backends to
detect when we need to create a new GL program for the user program.
The internal _cogl_use_program function now takes a GL program handle
rather than a CoglProgram. It no longer needs any special differences
for GLES2. The GLES2 wrapper function now also uses this function to
bind its generated shaders.
The ARBfp shaders no longer store a copy of the program source but
instead just directly create a program object when cogl_shader_source
is called. This avoids having to reupload the source if the same
shader is used in multiple materials.
There are currently a few gross hacks to get the GLES2 backend to work
with this. The problem is that the GLSL material backend is now
generating a complete GL program but the GLES2 wrapper still needs to
add its fixed function emulation shaders if the program doesn't
provide either a vertex or fragment shader. There is a new function in
the GLES2 wrapper called _cogl_gles2_use_program which replaces the
previous cogl_program_use implementation. It extracts the GL shaders
from the GL program object and creates a new GL program containing all
of the shaders plus its fixed function emulation. This new program is
returned to the GLSL material backend so that it can still flush the
custom uniforms using it. The user_program is attached to the GLES2
settings struct as before but its stored using a GL program handle
rather than a CoglProgram pointer. This hack will go away once the
GLSL material backend replaces the GLES2 wrapper by generating the
code itself.
Under Mesa this currently generates some GL errors when glClear is
called in test-cogl-shader-glsl. I think this is due to a bug in Mesa
however. When the user program on the material is changed the GLSL
backend gets notified and deletes the GL program that it linked from
the user shaders. The program will still be bound in GL
however. Leaving a deleted shader bound exposes a bug in Mesa's
glClear implementation. More details are here:
https://bugs.freedesktop.org/show_bug.cgi?id=31194
Previously cogl_set_source_color and cogl_set_source_texture modified
a single global material. If an application then mixes using
cogl_set_source_color and texture then the material will constantly
need a new ARBfp program because the numbers of layers alternates
between 0 and 1. This patch just adds a second global material that is
only used for cogl_set_source_texture. I think it would still end up
flushing the journal if cogl_set_source_texture is used with multiple
different textures but at least it should avoid a recompile unless the
texture target also changes. It might be nice to somehow attach a
material to the CoglTexture for use with cogl_set_source_texture but
it would be difficult to implement this without creating a circular
reference.
This moves the CoglIndicesType and CoglVerticesMode typedefs from
cogl-vertex-buffer.h to cogl-types.h so they can be shared with the
anticipated cogl vertex attribute API.
This renames the BufferBindTarget + BufferUsageHint enums to match the
anticipated new APIs for "index arrays" and "vertex arrays" as opposed
to using the terms "vertices" or "indices".