p3/regal — pull request #44 by adhoc-bobcat (2013-02-01 01:04:28+00:00)
Title: Implement RegalPpca

Add Push/PopClientAttribute emulation for Regal, allowing the full
OpenGL 4.3 compatability profile pixel storage and vertex array client states to be
saved and restored.

These notes and the implementation are based on
glspec43.compatability.20120806.pdf, as well as
http://www.opengl.org/registry/specs/EXT/direct_state_access.txt

This is needed when running on top of a back-end which does not support it
(GLES2), when the caller is an more general OpenGL client.

Specifically, the state mentioned in Tables 23.4 - 23.8 identified as
"vertex array", and the state in Tables 23.34 and 23.35 identified as
"pixel-store" is what is saved and restored.

For the pixel store state, this was straightforward. For the vertex
array state, this was more involved than I initially expected, leading
to this rather large patch. Sorry.

I implemented this version with the following in mind:

* The client state tracking should not constrain itself to the client
state actually supported by the back-end. If the client for example
calls glPixelStorei(GL_UNPACK_SWAP_BYTES, GL_TRUE), we record and
attempt to restore this change in state even if the back-end is
GLES2 which does not support it. If the client never makes this
call, then we never attempt to touch this state on restore.

It is assumed that for GLES2 and other similarly restrictive
back-ends that some other emulation layer will handle it as needed.

* Primarily this change is about implementing emulated versions of
glPushClientAttrib and glPopClientAttrib. All "global" client state
is tracked. Note that some calls would set state inside a Vertex
Array Object if one is bound, and this code ignores those calls
since that goes beyond what was needed. Also, while it implements
glGet for the purposes of constraining certain attribute count
limits and other maximums, it does not otherwise implement any
real functionality to get the shadowed client state.

* Beyond the compatability profile specification, I only handled the
Direct State Access extension, as there was already the RegalDsa
module present to emulate it. I pass the calls through after
shadowing the state, but in restoring state, I went and made the
more stateful calls without using that extension.

* I did my best to track the spec properly. There are a few corner
cases I did not properly handle.

1. This code does not know what buffers and vertex array objects,
etc. are properly allocated. The specification calls for the
interface to not allow an unallocated named object to be bound,
which should mean that this shadowing interface should ignore
the attempt.

2. Between the glBegin() / glEnd() call pair, calls other than
those to set single vertex attributes should fail. The
specification calls out a limited set of functions which might
not (10.8.5, after the errors box).

3. I was uncertain what to do if a state saved on the stack
contained a named object that was deleted. While I check the
current state, and effectively unbind, I did not do so for the
state stack. Some similar handling might need to be done for
bound objects stored inside a Vertex Array Object.

As I neared the end of the work on this patch, I strongly felt that the
following should really be done further down the line:

* With this change, Regal now has much redundancy in code that tracks
client state. I was really tempted to help clean this up, but I
don't feel like I have the time.

I feel like the emulation layer should implement one or more modules
to shadow OpenGL state, which should be all they do. I could see
making them configurable so that for example if vertex array state
was not needed, no attempt would be made to shadow it.

Other modules can then "require" this layer to work. RegalPpca would
then just implement the state stacks, and the Push/pop
functionality.

I'm hoping at least that you will find my implementation at least a
good starting point for this unification. I checked it numerous
times.

* In working through this patch, I looked briefly at the code in
RegalIff, RegalVao, and RegalPpc (the last of which is not
apparently used, and appeared to be the closest to what I wanted to
do in this patch). I used them to cross check my version, but I did
not directly use them as I felt each of them was incomplete (not
implementing all the interfaces, not consistently checking for bad
parameters, ...)

There are still some differences to call out, which should be
resolved at part of the unification:

1. RegalVao implements Vertex Array Objects assuming the back-end
does not. If vertex array state were unified, it would still
perform this function.
2. RegalIff includes some code to handle the having only
8 vertex attributes, and also maps the fixed-function
attributes into generic attribute entries. The mapping seemed
wrong, so I did not do it, but I'm sure the 8 vertex attribute
restriction is important for some platform. Integrating the
state tracking done by this module would also seem like the
most work involved in a unification effort.
3. RegalPpc implements state query functionality, which RegalPpca
does not.