The CoglPipelineCache is now extended to store templates for state
affecting vertex shaders and combined programs. The GLSL fragend,
vertend and progend now uses this to get cached shaders and a program.
When a new pipeline is created it will now get hashed three times if
the GLSL backends are in use (once for the fragend, once for the
vertend and once for the progend). Ideally we should add some way for
the progend to check its cache before the fragends and vertends are
checked so that it can bypass them entirely if it can find a cached
combined program.
Previously the fragends had a separate private data pointer which was
used by the GLSL and ARBfp fragends to store a tiny struct containing
a single pointer to the ref-counted shader state. The space for the
private data pointer is reserved in all of the pipelines for all of
the potential backends. The vertends and progends however did this
differently by directly storing the pointer to the ref counted data
using cogl_object_set_user_data. This patch unifies the different
methods so that they all use cogl_object_set_user_data and the
fragends don't bother with the separate tiny allocation for the
private data. The private data pointer array has been removed from
CoglPipeline and the corresponding fragend virtual to free the private
data has also been removed because this can instead be done with the
destroy notify from the object user data.
The variable names used have been unified so that all of the vertends
and fragends name their data struct CoglPipelineShaderState and use a
variable called shader_state to refer to it. The progend uses
CoglPipelineProgramState and a variable called program_state.
This should also fix two potential bugs. the ARBfp fragend was
apprently leaking a reference to the private state when it creates the
private data because it was adding a reference before stroring the
pointer to the newly allocated data but the ref count is already set
to 1 on creation. The other potential bug is that the free function
for CoglPipeline was only calling the free_priv virtual for the
currently used fragend of the pipeline. The design of the fragends is
meant to allow a pipeline to have multiple fragend priv datas because
a child pipeline could be attaching its fragend data to the ancestor
and its allowed to pick a different fragend.
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
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.
Instead of storing all of the feature function pointers in the driver
specific data of the CoglContext they are now all stored directly in
CoglContext. There is a single header containing the description of
the functions which gets included by cogl-context.h. There is a single
function in cogl-feature-private.c to check for all of these
functions.
The name of the function pointer variables have been changed from
ctx->drv.pf_glWhatever to just ctx->glWhatever.
The feature flags that get set when an extension is available are now
separated from the table of extensions. This is necessary because
different extensions can mean different things on GLES and GL. For
example, having access to glMapBuffer implies read and write support
on GL but only write support on GLES. The flags are instead set in the
driver specific init function by checking whether the function
pointers were successfully resolved.
_cogl_feature_check has been changed to assume the feature is
supported if any of the listed extensions are available instead of
requiring all of them. This makes it more convenient to specify
alternate names for the extension. Nothing else had previously listed
more than one name for an extension so this shouldn't cause any
problems.
When uploading the layer matrix to GL it wasn't first calling
glActiveTextureMatrix to set the right texture unit for the
layer. This would end up setting the texture matrix on whatever layer
happened to be previously active. This happened to work for
test-cogl-multitexture presumably because it was coincidentally
setting the layer matrix on the last used layer.
There are several places where we need to compare the texture state of a
pipeline and sometimes we need to take into consideration if the
underlying texture has changed but other times we may only care to know
if the texture target has changed.
For example the fragends typically generate programs that they want to
share with all pipelines with equivalent fragment processing state, and
in this case when comparing pipelines we only care about the texture
targets since changes to the underlying texture won't affect the
programs generated.
Prior to this we had tried to handle this by passing around some special
flags to various functions that evaluate pipeline state to say when we
do/don't care about the texture data, but this wasn't working in all
cases and was more awkward to manage than the new approach.
Now we simply have two state bits:
COGL_PIPELINE_LAYER_STATE_TEXTURE_TARGET and
COGL_PIPELINE_LAYER_STATE_TEXTURE_DATA and CoglPipelineLayer has an
additional target member. Since all the appropriate code takes masks of
these state bits to determine what to evaluate we don't need any extra
magic flags.
The GLES2 wrapper is no longer needed because the shader generation is
done within the GLSL fragend and vertend and any functions that are
different for GLES2 are now guarded by #ifdefs.
Once the GLES2 wrapper is removed we won't be able to upload the
matrices with the fixed function API any more. The fixed function API
gives a global state for setting the matrix but if a custom shader
uniform is used for the matrices then the state is per
program. _cogl_matrix_stack_flush_to_gl is called in a few places and
it is assumed the current pipeline doesn't need to be flushed before
it is called. To allow these semantics to continue to work, on GLES2
the matrix flush now just stores a reference to the matrix stack in
the CoglContext. A pre_paint virtual is added to the progend which is
called whenever a pipeline is flushed, even if the same pipeline was
flushed already. This gives the GLSL progend a chance to upload the
matrices to the uniforms. The combined modelview/projection matrix is
only calculated if it is used. The generated programs end up never
using the modelview or projection matrix so it usually only has to
upload the combined matrix. When a matrix stack is flushed a reference
is taked to it by the pipeline progend and the age is stored so that
if the same state is used with the same program again then we don't
need to reupload the uniform.
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.