Freitag, 30. Mai 2008

Lines! (... and traps)

Lines and Traps:
I've just finished some code which generates a transformed rectangle out of ordinary lines, and generates Trapezoids out of it later.
It was ... well harder than expected and I needed an awful lot of trigonometry, some basics about tranformations (especially rotation) and a lot of debugging and trying.
Thanks to Heinz for some trigonometry lessons and for removing the need for two trigonometry functions (its now basically a few multiplications/divisions and a single square root).

I did the whole thing in Java first, because I am used to it and don't to read manuals just to get a line drawn to draw my calculations, and combined it with my Trapviewer app I wrote a few days ago.
The big difference is that now I calculate my own traps, instead of stealing cairo's ;)
The first window is simply a debug-window which shows the line maginifed, the second is trapviwer.

Why are Lines so hard?:

Well, XRender itself does not support lines, so they have to be composed out of trapezoids.
Furthermore lines are ... well some kind of rotated primitive, the rotation is more or less specified by the end points.

The sad thing is, you need 3 primitives for a single line, and lines are used a lot by application programmers as well as the java shape stroking (Graphics2D.draw()) code.
Best solution would be a Trapezoid-Generator, which could generate as much traps as really needed, but thats far beyond my qualification.

Some day it would be great if we could port Cairo's trap generator to Java, or use it through an JNI-Interface but for now its a private API(its LGPL after all).

Whats next:
Well tonight I'll rewrite the code in C and doing some fine-tuning for performance.
Macros, Macros, Macros ;)

Mittwoch, 28. Mai 2008


Because even simple lines were too much for my imagination, I hacked Cairo to output the generated trapezoids and wrote a small java program to parse the data and display it.

Well, now I understand how a line is implemented ... but I never knew that such triangle-trapezoids are valid ;)

So therefore horizontal and vertical lines can be done using FillRect or a single trapezoid, and when rotated we need 3 to create the end-points.

Dienstag, 27. Mai 2008


Well, the text-stuff is as expected quite hard.

The old implementation is quite interesting:
Because Java does its own glyph-rasterization I was not able to use XCore-Fonts back then, therefor it creates a Bitmap (a 1-bit alpha mask) when text is dran, uploads it to the server in a pixmap and uses this pixmap as a 1-bit mask for an area which is filled with the foreground-color.

I guess this is an area where Java2D performance will benefit a lot when using XRender, maybe much enough that it would justify a backport of the text-only stuff to the X11-only pipeline.
Even better XRender supports antialiased and subpixel antialiased (however, for now I don't know howto deal with that) text, which caused expensive readbacks till now.

Montag, 26. Mai 2008


Today I started to play a bit with XRRenderer.
For now only fillRect was implemented (because without it all the cool demos would have been even more crappy^^), so there is plenty of work to enhance it.
I started to add draw() and fill() support, replaced some fast-path methods with redirections to general draw/fill code (because those primitives don't exist with XRender anyway) and everything which relies on drawScanlines works some kind of.
However till now I was not able to figure our howto draw a simple line with XRender which is used a lot for path() stuff. I'll have a look at it later again.

Some thing I wonder about is that the Java2D code does not seem to allow those primitives for more advanced paint states like texturepaint. For XRender it would not matter much, because any paint is textured if not done by rectangles anyway. Stepping through the OpenGL indicates that everything is done in software, only the drawImage() calls later are done by hw (however I may be wrong here of course).

Tomorrow I'll have a first look at text rendering, something I hope to get good results from.
Anyway, most apps written in java rely on text, and in its current implementation its quite inefficient when done on hardware-surfaces (like VI or Screen).

Donnerstag, 22. Mai 2008

Hard times...

AlphaComposite with "extra alpha" gives me a hard time, if possible I would like to solve it without an temporary surface. In the worst case such a surface could be cached, but one composition step is always better than two ;)

The problem as far as I can see is, that XRender allows to specify an alternate alpha-mask which can be used for composition, instead of the alpha-mask embedded in ARGB surfaces.
However AlphaComposite would require not to replace, but to multiply the alpha values of both as far as I've understood.

So with what I've seen the following stuff could be done without a second composition step:
- (Alpha)-Colors, the "extra alpha" value can be simply calculated in the color-value
- Opaque Images, they don't have an alpha mask, so nothing to replace, a 1x1 mask could be used.

things that would need a second composition step:
- Bitmask and Translucent images. I currently treat bitmask-images like translucent ones (ARGB surfaces).
Their importance seems to decline, and ARGB images are guaranteed to be accalerated in almost any case.

I am currently also working on some hackish implementation of XRRenderer, which is responsible for rendering the known primitives like rects, ovals ....

Furthermore I've done some benchmarking for scaling and transformation.
With XRender those operations are a lot faster, but only if executed on a Pixmap, on Screen they suffer from terrible performance.
To-Screen-Rendering seems not really well implemented on todays hw, DirectX9 does not even allow it.
Swing and many games use BufferStrategy, so it shouldn't be a problem.

Mittwoch, 21. Mai 2008


Today I worked mostly on an University-Project, I am in a Team of 6 students.
Although some of them had not a lot routine when it came to programming, everybody gave/give their best.
Quite a good feeling to see a project grow, and you know everybody is working hard to make it a success :)

Yesterday I implemented renderImageXform, which means blits with arbitrary transformation, its called for almost any complex blit with transformation or with scaling and billiear/bicubic interpolation.

Which means accalerated rotated blits using XRender:

Left is the XRender rendered image, right the software RI.
For now I simply set an inverted Transformation on the source and composite over the whole destination surface. This could have a bad impact on performance (don't know for sure) and it also means antialiased edges, which differs from the RI -> bad.
Because destination coordinates are not transformed, and XRender does not support shapes, I'll try it triangles and see how it will influence performance (for traps and triangles an implicit mask is generated)

The bottom line is jaggy in both pictures, because I've set a clip which is alway not antialiased.

Dienstag, 20. Mai 2008

Scaling ... finally :)

Scaling is a pretty painful capter, I misunderstood a lot and in my opinion XRender is quite weird:
- Transformation is set on the source Picture
- Transformation does not affect destination coordinates

I don't really know OpenGL and maybe its the same there, but it somehow confuses(d) me.
It also implies that I have to validate also the source-surface (at least some states which are important when used as source) before blending with reversed transformation.

Furthermore the following method took me some hours of manual transformation-matrix tweaking:
public static int XDoubleToFixed(double dbl) { return (int) dbl*65536; }
Well not that problematic if you know whats going wrong, but if you suspect tons of other things going wrong, it takes quite some time. After all, something like this should not have happend ;)

Finally, here's a translucent pixmap - one time scaled down to 50% and one time scaled up to 200%:

Montag, 19. Mai 2008

DrawImage and TransformedBlit

I wonder why the following code:

g.drawImage(img, 0, 0, this);

is redirected to the DrawImage pipe (which I of course have not implemented until now ^^).

After all it quite puzzles me why there is a DrawImage-Pipe which seems to be able to handle all cases, and things like ScaledBlit and TransformedBlit. I registered a TransformedBlit which does does not seem not to be used in this case.
However the registered ScaledBlit does its job :)

Update: Seems to be done from inside OGLDrawImage. Did the same with XRDrawImage and now transformed blits also pick up the appropriate loops :)

Sonntag, 18. Mai 2008

How do they ...

I am currently quite a bit puzzled by trying to understand how software-fallbacks work with the OpenGL pipeline.

As far as I understand the X11 pipelines "punt" a pixmap (read it back to sysmem) when GetRasInfoFunc is called, however OpenGL does simply not implement it:
OGLSD_GetRasInfo(JNIEnv *env,
SurfaceDataOps *ops,
SurfaceDataRasInfo *pRasInfo)
JNU_ThrowInternalError(env, "OGLSD_GetRasInfo not implemented!");

Strange, either I completly misunderstood how software-fallbacks work in the X11 pipeline, or the OpenGL pipeline uses some other way to read their surface data back. Maybe this has been done because this way is not compatible with the STR design. Somehow I'll have to find it out ... although I already hestitate to ask at the 2d-dev lists. Its not funny to flood a list with tons of questions...

Donnerstag, 15. Mai 2008

XRender clipping working (sort of)

Clipping works now using XRender, although I am still confused why the original X11 pipeline did manual clipping in its blit routines. It still seems to work as-is without it :)

For now only cases work, which have been previously accalerated already by the existing X11 pipeline, however now also with the XRender stuff.

Yesterday I tried Fedora9 to see how far EXA (more or less a requirement to have fast XRender) has advanced, and I was surprised to see how well it was working. However Fedora9 itself ... will have to way until the first batch up updates are released.

Mittwoch, 14. Mai 2008

translucent images :)

After a long time reading and trying to understand and some time of hacking in the existing X11 sources, I finally got something cool to work: translucent images:

XRender makes it really easy, providing support for ARGB pixmaps, which is exactly what we need.
Well, cliping is now broken when rendering images (of course^^) but its the first stuff working now ... which could not be accalerated with X11 Core Rendering.
It first looked really weird because RENDER expects premultiplied data, but after changing the data-type for cached pixmaps to ARGBPre everything worked as expected :)

Although it first seems to be really complex and weird, the design of Java2D is quite clever and well thought.

I am quite interested how the existing code will handle stuff like:
  • Clipping
  • Complex tranformations
  • Text
  • Antialiasing
  • Solid rendering
As far as I understand if we don't want to composite to get clipping we have to do it ourself ... which is boring.
Transformations could mean simply adjusting the transformation matrix, well, I have to look at it.
Solid rendering means replacing all the existing primitive drawing operation with XRender's ... I guess this will look very much like the OpenGL pipeline directing anything but lines and simple fills to the generic path/fill code.

Schedule, Design descisions

Maybe you know that my proposal at "OpenJDK Community Innovators' Challenge" has been accepted quite some time ago. So after all why I am so late ... where are the results?

For now I worked on understanding the XRender API, understanding how they match with Java2D - and how I could start. I hacked and played with the existing Java2D pipeline and wrote several samples in C emulating the behaviour required later by the pipeline and as usual were nerving the Xorg and Java2D developers with neverending questions.

Well I have to admit I am a bit late when it comes to my planned schedule, caused by project-internal and external factor, so instead if writing thousands of words why I am so late ... I'll simply write a short list:

* Maths2 exam
* Laptop died
* Had quite a hard time understanding the existing code
* Design desisions and validation

So, although the first three sound quite boring, there's something to write about "Design desisions".
The proposal itself proposed a STR (single-threaded-rendering) based design which buffers commands from multiple threads and interprets those rendering-commands using a single thread - however after some benchmarking I found that the classic Java->JNI->C design was as fast as the STR-Design but a lot less complex and less code.

Furthermore a lot of code I expected to belong to "AWT" is also contained in "2D", so writing a completly new pipeline from scratch would either mean a lot of duplicated code or a lot of work in the existing codebase to make it more shareable.

I have not found the final design for now, but as far as I can tell it most probably will not be STR based.
For the beginning I will play and extend the existing pipeline, and if I find design problems which make it hard to accalerate some operations I will think how the existing design could be adopted to fit this better.

More information about the challenge:


Welcome to Linuxhippy's Blog!

Over the next few months this will be the home for my blog about Development of the XRender OpenJDK project.
Its goal is to bring Java2D on Unix on par with the Direct3D implementation which will replace the current design starting with JDK6u10.

The existing X11 backend is very prooven, stable and well tuned, however it falls back to software for many operations which can accalerated more or less efficiently by modern X-Servers using the RENDER extension.
OpenGL is a quite sad story on Linux, especially with free-software drivers and even the proprietary drivers often break it from release to release, so although there is an excellent OpenGL backend for Java2D most Linux-Desktops currently are unable to run it.

So the target for the XRender backend is to replace the existing X11 pipeline over time on Desktop systems, leaving the old there for legancy systems. Although it will not be as capable as the OpenGL-pipeline it hopefully will be able to provide features modern toolkits (like Nimbus) and applications rely on, on most Unix systems by default.

By the way:
This OpenJDK project was proposed at the "OpenJDK Community Innovators' Challenge" and got one of seven slots.
This is really great ... wonderful ... wow ... cool - I thought about the idea of XRender accaleration for Java2D for quite some time now and always had to give up because of time and money constraints. This way I can work on a really favourable, cool and interesting project and ... if everything goes well ... it will allow my to concentrate on univesity and development of free software for quite some time :)

Why "Linuxhippy"?:
Well bad choice a long time ago ... when I was 13 I created my first email account. Yes right, I needed an address and thought it should be something cool ... and because I got used to it I often still use it for my email addresses and as nickname. I got so used to it that I forgot it does irritate many people thinking I am some kind of radical, immature or a hippy. Well ... I am not (at least not a hippy^^).

So Linuxhippy is more like "GoldStar" was in 2000, a name from tha 80's which sounded cool than, but ... well is not that cool anymore. Unlike GoldStar I don't have the time to re-name all my stuff ;)

.... Enjoy!