On Sun, 2009-02-22 at 01:35 -0500, Havoc Pennington wrote: > Hi, > > When using indirect rendering (I know, it's insane, but currently > needed for compositing managers), shoveling the matrix over the X > socket and occasionally pulling it back is turning out to be a pretty > bad problem. > > Every glPushMatrix(), PopMatrix, Translate, etc. is another X request. > In an even moderately complex clutter UI there are tons and tons of > these in every frame. Also, whenever an actor has a clip set on it, or > anyone calls one of the functions that computes a transformed or > absolute coordinate, there's a round-trip to the X server > (glGetDoublev) to get the current matrix. What typically happens is > that mesa's outgoing command buffer is packed with stuff, then > cogl_get_modelview_matrix() is called somewhere in the middle of > painting the stage, and that flushes the buffer and waits for the > reply - not unusual for this to take 100ms or so with a complex scene > on netbook-ish hardware. 100ms round trip in the middle of a frame is > bad; now think about if *two* actors have a clip set on them ;-) > > Anyway, maintaining the matrix client-side does not look super hard > but it's mostly a series of "matter of taste" judgment calls so if > anyone could give some guidance on how to approach this... some early > thoughts: > > * presumably could store a matrix in the cogl context along with a > "needs flush" flag; when calling any gl thing affected by the matrix, > some sort of _cogl_flush_matrix() would have to be called; this would > leave _cogl_flush_matrix() all over the place ... bad? better idea? > _cogl_flush_matrix() would of course just push the current matrix to > the gl implementation. I'd personally be fairly happy with the flush type approach; but I'd take the opportunity to add something like cogl_flush_gl_state() which I think would tie into ideas we've discussed in the past about improving the ability to break out of Cogl into raw GL.
Also; a goal I tend to keep in mind with Cogl is unifying drawing paths when possible (I.e. long term I'd quite like to unify on the vertex buffer API internally), so as it is there aren't many places in Cogl where we need to deal with flushing GL state, and going forward I hope to have even less. > > * is it desirable to prefer the "native" gl matrix calls when > rendering is direct? this will add complexity but could be considered > better, something like this on startup: > > extern void (* cogl_translate) (float x, float y, float z); > if (context is direct) > cogl_translate = glTranslatef; > else > cogl_translate = client_side_matrix_thingy; > > worth it or just annoying? I don't know enough about how clever GL > implementations are here and whether it's important to use their > matrix stuff. > > * I noticed cogl_matrix.c has a comment about adding cleverness like > m_matrix.c in Mesa; but m_matrix.c in Mesa is X-style licensed and > looks pretty standalone and reasonable; could we just use m_matrix.c > which appears pretty nicely optimized? (if so, one approach is to try > to leave it unmodified in a separate file so it can be resynced with > mesa, and wrap it in a nicer cogl API in a separate file ; another > approach is to just redo m_matrix.c to match the cogl style and > permanently fork it off) (I'm not even sure client-side matrix > requires anything not already in cogl-matrix.c, but if it does > m_matrix.c looks nice, and m_matrix.c looks pretty well-optimized and > comprehensive too) > > * I'm not quite sure what the guideline is for when to share code > between gl and gles; cogl_translate() for example seems to just be in > both subdirs, rather than in common/. Historical accident, or is there > a rationale? The client-side matrix code would presumably be the same > for gl and gles, but it would need to use the context, which is in the > subdirs... Its just a historical thing. If you look through the git logs you can find a number of GL vs GLES normalization commits that aim to converge this code to the point where 90% of it can simply be moved into cogl/common. I think it's basically at that point now; I just haven't gotten around to the final re-jig. > > * caching the matrix would be the first big reason I know of that cogl > would play poorly with direct GL API usage (cogl_enable is sort of a > headache here, but pretty easy to deal with). Is that OK? Should there > be a public cogl_allow_gl()/cogl_disallow_gl() that would be used > around any raw GL commands? There is also CoglMaterial that does lots of state caching too. Without getting distracted too much by this it probably worth mentioning that the ability to break out into raw GL is something we've discussed several times in the past, and I even made good progress with patches to improve it at one point. To give some context into that discussion; this was the proposal we came up with at the time: 1) We remove the internal cogl_enable function. (Internally it only manages 4 flags a.t.m) 2) Expose new cogl_enable and cogl_disable functions to be used like glEnable/glDisable that will sit on top of an internal cache. 2) Also add cogl_enable/disable_client_state calls + cogl_is_enabled calls. 3) We expose a new cogl_flush_cache func that commits the cache to GL 4) We expose a new cogl_dirty_cache func that lets you invalidate cogls cache. 5) Internaly re-work code in terms of these new funcs in place of the current cogl_enable. So if we come around to this problem again; I think it's still solvable and I don't think your client matrix stack has to conflict with it, but perhaps it would make sense to add top level cogl_flush_gl_caches and cogl_dirty_gl_caches at the same time. kind regards, - Robert -- Robert Bragg, Intel Open Source Technology Center -- To unsubscribe send a mail to [email protected]
