Slimming Graphics hierarchy
richard.bair at oracle.com
Tue Jul 23 10:55:43 PDT 2013
There are 14 types of com.sun.prism.Graphics (actually there is a 15th, PrinterGraphics, which is a graphics by name only since it is a tagging interface that doesn't extend from Graphics). Some of the methods in these classes and interfaces are documented, most of them are not, which makes understanding the code difficult (especially a couple methods in ShaderGraphics like drawTextureRaw2). Also, the architecture here is that we have Graphics interfaces and concrete implementations, and a lot of instanceof checks throughout the code to differentiate one type of Graphics object from another.
(Which is extra interesting in that the com.sun.prism.paint package goes to great lengths to avoid instanceof checks between different types of paints, but here we use instanceof a lot).
There are also some methods which look like there aren't being used at all (such as setWindowProjViewTx, which is also undocumented).
I worked up the inheritance hierarchy for Graphics and this is what it looks like. The colored round-rects are interfaces, the white square rects are classes (either abstract or concrete). The concrete class hierarchy looks fine to me -- having a different ES2Graphics from D3DGraphics from TestGraphics from DummyGraphics from J2DGraphics etc all seems fine (required, really, given our current pipeline architecture). Its the interfaces (and what is defined on them) that I'm not finding very useful. I think there are a couple questions worth asking:
SWGraphics and J2DPrismGraphics (should be renamed J2DGraphics for consistency) don't extend from BaseGraphics. In fact, only BaseShaderGraphics extends from BaseGraphics. This implies that either BaseGraphics & BaseShaderGraphics should be combined, or functionality that really is common between shader based implementations and J2D and SW should exist in BaseGraphics and the hierarchy modified accordingly. TestGraphics can just as easily come off BaseShaderGraphics.
MaskTextureGraphics is only used by web view (1 instanceof check)
ReadbackGraphics has two instanceof checks, both in NGNode. One of these is a method called isReadbackSupported.
RectShadowGraphics has one use in NGRectangle (1 instanceof check)
ShaderGraphics is not used in any instanceof checks, and only 1 cast. This is a good sign this interface is not needed.
PrinterGraphics has 4 instanceofs.
There aren't that many instanceof checks overall, which is a good thing (no performance penalty, really). The question is whether having interfaces at all here is buying us anything, and what exactly that might be. A couple methods returning booleans could also be used for determining feature support (and in fact we already do this in other places like ReadbackGraphics#canReadBack). Reducing class count is desirable because the more classes, the longer the startup costs and the more perm gen space used by the VM.
I'm thinking we should instead have a hierarchy that looks like this:
Its only 6 fewer classes (all interfaces) but it flattens things out a bit more and makes it a little more obvious who is extending what, and for what reason.
More information about the openjfx-dev