|
|
||
Chris Campbell's BlogCommunity: JavaDesktop ArchivesEffectuation: The IntroPosted by campbell on February 01, 2008 at 02:32 AM | Permalink | Comments (21)For the past few months, I've been involved with various aspects of Project Scene Graph and the JavaFX Script runtime libraries. Hans has already introduced the core elements of the scenegraph package, and Chet has donned his Groucho mask to explain the animation package in great detail (three chairs for that!). Today I'm finally going to talk about the third major component of the overall Scene Graph project, and that is the Effects Framework. If you've been wondering why I've been quiet lately, this is the reason. Our team has already had plenty of experience in delivering GPU-accelerated imaging operations. Now we've taken it to the next level, by offering a long list of effects commonly used by designers, packaging them up into an easy-to-use API, and providing a sophisticated implementation that can take advantage of GPU acceleration (and later, SIMD instructions on the CPU) for blazingly fast performance. All of this integrates seamlessly with the scenegraph and animation packages, and soon will be exposed just as pleasantly through the JavaFX Script runtime APIs. You can even take advantage of the Effects Framework in existing Swing and Java 2D applications. Anyway, enough yapping; let's move on to the introductory demo... This application demonstrates just a few of the effects available in the new API. I'll let it speak for itself. (Requires Java SE 6 or above.)
(*) GPU acceleration requires the latest build of JDK 6uN, a compatible graphics card, and up-to-date graphics drivers. If GPU acceleration cannot be enabled for any reason, the framework will automatically fall back on the software-based implementation. Yes, the software-based backend is much slower than it should be; we're working on that. These projects are still in the early stages, but over the next few weeks, I'll have much more to say about (and more demos to share from) the Effects Framework and the Scene Graph project at large, so stay tuned. In the meantime, take a gander at the JavaDocs and let us know what you think. Hans should have news shortly of an 0.5 release that includes all of this and more.
In my ears: Enon, "High Society"
Faster Java 2D Via ShadersPosted by campbell on April 07, 2007 at 07:58 PM | Permalink | Comments (18)We've been doing a lot of work over the past couple years to accelerate many complex Java 2D operations on the GPU via OpenGL fragment shaders. (Fragment shaders are little programs that operate on each pixel being rendered on the screen; they're infinitely more flexible than the fixed functionality that's historically been available in OpenGL.) The sky's the limit when it comes to the kind of effects one can achieve by writing shader programs. The first GPUs with fully programmable shader support were made available from Nvidia and ATI in 2002. It took a couple years for the new hardware to penetrate into the consumer market, but now shader-capable GPUs are extremely prevalent (thanks in part to the hefty graphical requirements of Mac OS X and Windows Vista), so much so that we can reliably take advantage of shaders to accelerate complex Java 2D operations. Even those first-generation boards are capable of providing huge performance gains, and each new generation of hardware seems to give an order of magnitude improvement over the last. This should be quite evident from the charts that follow. While CPU speeds seem to be nearing an asymptote, GPU performance continues to rocket, and now Java 2D is able to benefit from that power. Not only does this mean improved performance for your Swing or Java 2D application, but also reduced CPU consumption, thus freeing up your CPU to crunch on application logic rather than getting bogged down with rendering tasks. [This is one of those blog entries that could be novel length, but no one would actually read the words, because there are too many pretty bar charts to distract the reader. Blah blah blah, words words words. See? No one's reading. So let's skip the prose and get on with it... Oh, but first, I have to tell you how to read these charts. I generated these numbers on a couple different machines, using J2DBench on Windows XP with the latest graphics drivers (ATI Catalyst 7.3 and Nvidia 93.71). Since the machines vary slightly in processor performance and bus speed (the GeForce 7800 is a PCI-E board, the rest are AGP), I decided to use our software pipeline as a baseline, and then compare the OGL pipeline numbers to that baseline. For example, if you see a result that lines up with the number 2000, it means that test is 2000% of baseline, or in other words, it is about 20 times faster on the GPU than on the CPU. Your mileage may vary, but the big takeaway is that most operations are many times faster when executed on the GPU...] Text Rendering (Bug 6274813: Available in JDK 6)
LCD-Optimized Text
BufferedImageOps (Bug 6514990: Available in JDK 7 b08)
ConvolveOp
LookupOp
RescaleOp
Multi-stop Gradient Paints (Bug 6521533: Available in JDK 7 b10)
LinearGradientPaint
RadialGradientPaint
Extended Composite Modes (Bugs 6531647, 5094232: On the way)
Antialiased Painting (with Non-SrcOver AlphaComposite)
Coming Soon: PhotoComposite What's Next? There are plenty more optimizations that can be made to common Java 2D operations by leveraging shader technology; we'll keep working on this. Also, there have been some discussion on the interest list recently about the use of shaders in Java 2D. Some folks would like to be able to write arbitrary shaders and have them work on Java 2D content. I think it would be hard to come up with a general solution (in the public API) to make this work everywhere, and would shift an unreasonable burden to Java 2D (which is designed with WORA in mind). However, I do recognize that it would be great if it were easy for developers to make use of shaders in their applications (as Romain has demonstrated) without getting bogged down in the OpenGL/GLSL learning curve. To that extent, I've been working on a few utility classes for JOGL in the vein of TextureIO and related classes. This is another way to make the transition easier for existing Swing developers to leverage JOGL in their applications. More on that in a future blog entry. Finally, it's worth mentioning that all the shader-based optimizations I've described above are currently only available for the OpenGL-based Java 2D pipeline, but that will soon change. For JDK 7 (maybe sooner?), we have a newly redesigned Direct3D-9-based pipeline in the works that will share much of the architecture (and code) of the OpenGL-based pipeline. We fully expect that all of these shader-based optimizations will be available for most Windows users in the near future. Stay tuned.
In my ears: Panda Bear, "Person Pitch"
Java 2D Trickery: Antialiased Image TransformsPosted by campbell on March 10, 2007 at 04:31 PM | Permalink | Comments (15)Note: The code snippets in this blog entry are intended to be used with Scott Violet's nifty Interactive Graphics Editor. Just cut and paste the code into that application, et voila: instant gratification. This allows you to tinker with the code and immediately see how your changes affect the rendering.
It's been a while since I posted a "Trickery" blog (previous installments in this series include "Soft Clipping" and "Light and Shadow"). This week at the Desktop Matters conference (which was great, by the way) someone asked if there was a way to antialias the edges of an image when rotating it in Java 2D. The kind gentleman noted that on Mac OS X with Apple's JDK, they do see antialiased edges if they enable
It is true that Sun's Java 2D implementation does not automatically antialias image edges when rendering with
Here's the resulting screenshot showing the different options:
Note that there will likely be some performance hit from transforming the image in this manner, but if quality is of utmost importance (as it was in this developer's case), then the cost is probably acceptable. Hope this helps!
In my ears: The Fall, "Perverted By Language"
Swing and GTK: What a LAF!Posted by campbell on February 22, 2007 at 08:17 PM | Permalink | Comments (5)[If it's not readily apparent, I wrote this blog entry months ago because I was waiting around for the bug fixes described here to make it into JDK 7. So just as a brief diversion from your day, pretend for a few moments that you've traveled back to the distant past, specifically the trail end of the year 2006...]
How I Spent My Summer
Anyway, with JDK 6 in a frozen state and summer rapidly approaching, I figured that it would be a good time for a change, but (oh!), what to work on? I started with a blank slate, but quickly found my toes overdipped. Here's a partial list of my non-OGL dabblings over the last six or so months:
This list serves dual purposes. First, it's a pathetic attempt to prove to my manager that I did accomplish something this summer besides, um, building an Adirondack chair and paddling around Shook's Pond. More relevantly, it demonstrates that I have issues with focusing on one concrete project. However, the one item that showed the most potential (and had well-defined constraints) was the set of GTK L&F deficiencies. Ubuntu wasn't a tier-one testing platform for us in JDK 6 (something I hope will change for JDK 7), and it turns out that Ubuntu's 6.06 release introduced a new GTK engine (ubuntulooks) and theme (Human). The ubuntulooks engine is different enough from the clearlooks engine (from which it was derived) to warrant a close look, and it would require a number of special fixes to make Swing's GTK L&F look great on that distro. Another reason to focus on a concrete project like the GTK L&F is that there's been an effort underway for some time by the NetBeans team to enable the GTK L&F by default on Linux and Solaris, just as Mac OS X and Windows use the platform L&F by default. After all, if Sun doesn't set an example by enabling the platform L&F in all of our desktop-focused software, how can we expect developers to do the same in their apps? Again, despite all the major improvements to Swing's GTK L&F in JDK 6, there were a few issues that slipped through the cracks, and we wanted to make sure those are addressed soon (ideally in the upcoming JDK 6 update releases). Expect to see NetBeans make this switch in their 6.0 release (or thereabouts) in Spring 2007. [Update: The NetBeans folks just this week flipped the switch in NetBeans 6.0 M7 so that the GTK L&F is now enabled by default on Solaris and Linux (on JDK 6u1 and above). Check out the "new and noteworthy" page for a few sample screenshots and more information. To get things looking good in time for the NetBeans 6.0 release, a lot of energy was invested by the NetBeans, Solaris, and Swing teams. Thanks guys!]
Before and After Science
Fig. 1 -- Native "twf" demo application.
Fig. 2 -- Java/Swing mockup of "twf", courtesy of Elliott Hughes, running on JDK 6.
Fig. 3 -- Same as above, but running on JDK 7-b08; can you spot the 6 (or 25) differences? These particular screenshots were taken on an Ubuntu 6.06 system with the default Human theme, but similar improvements can be seen on many other GTK themes such as Nimbus (the new default on Solaris), Clearlooks (the most popular on various Linux distros), and so on. In total, over 30 GTK-specific bugs have been fixed so far in JDK 7, and there are plenty more fixes on the way. For more details on these bug fixes, refer to this list. As you can probably see from Figure 3, there's still a bit more work to be done (e.g. table headers, non-editable comboboxes, tabs), but we're getting closer.
Help Wanted
I hope these statements don't come across as whining. The fact of the matter is that at Sun we have anywhere from 1.33 to 2.117 persons available to work on the GTK L&F at any given time. Since time is the limiting factor, there's only so many fixes we can get in within a given year, maybe 50 tops. But what if we took a page from the book of CMT and increased the number of threads crunching on these issues in parallel? I think we could see some quick progress. There are a number of people (you know who you are, Elliott Hughes; nudge nudge, Brian Harry; wink wink Roman Kennke) who are actively interested in the success of the GTK L&F. That's great, but I'd like to see more activity in this area, perhaps in addition to the aforementioned/illustrious names. And not just in the form of an independent project. We'd be happy to work closely with 1 or 2 (or 3) developers out there in the OpenJDK community, collaborating on fixes, and so on. Eventually it would be nice to see a couple folks in the community with the same level of expertise as we have in Kirill K. and Peter Z. (our resident GTK experts on the Swing team at Sun). At the very least it would be a fun experiment as we move towards completely opening up the JDK library source code in the next few months. As has been stated elsewhere, we still have a lot of work to do w.r.t. opening up our internal processes (bug evaluations, code reviews, etc) to the outside world, but I think it would help the transition if we had a few external folks get more involved with this process now. Send me email if you'd like to get involved. I can't promise you fame or fortune, but I can promise you a beer or two (*, **, ***, ****, *****) in return for your hard work.
* Valid only in the Bay Area, California, unless you want to fly me to your location. (I'd gladly oblige, especially if you're located outside the U.S.)
In my ears: Deerhoof, "Reveille" [digging through old favorites...]
Orange Box: New Java Plugin AnimationPosted by campbell on February 02, 2007 at 10:54 AM | Permalink | Comments (33)[Concision is often a difficult thing for me. Everytime I write a blog entry I tell myself, "This one's a-gonna be a short 'un." But it just never seems to work out that way. Perhaps I'll succeed today.] For the dozen or so folks that attended the User Experience BOF at JavaOne 2006, this is probably not news. But if you're one of my (14 million) readers who did not attend that BOF, you may be interested to learn that we've revamped the quick little animation that users see when the Java Plugin is being initialized in the browser. In the years prior to JDK 5, users saw little more than a gray box and a tiny coffee cup logo. Besides being dull, there was no indication of applet startup progress; not exactly a brilliant user experience! Fast forward to 2004 when a certain high-level-exec-turned-CEO decided it was time to improve that experience. A short startup animation (with progress indicator) was proposed, and the general design was (somewhat unfortunately) handed down from above. Our multi-talented visual designer, Coleen Baik *, and I were given only a couple weeks to churn out the final design and implementation (written purely in Java 2D, of course) in time for the impending JDK 5 release. Thus was born the original "gray box animation," called as such despite the fact that it was now much more white than gray:
About a year later we were again asked to update the look of the animation, this time for the JDK 6 release. Our initial reaction was one or more of:
[Concision, man, concision! Enough yapping! Show them some pictures, already!] So without further ado, I present the new "orange box" Java Plugin startup animation...
The screenshot doesn't really do it justice, so I'd recommend trying the live demo (sandboxed; requires JDK 6) to see the fancy page flips, fades, and so on. You can resize the window to see how the animation behaves at different sizes. Note that the demo is derived from one of the final prototypes (before it was integrated into the JDK), so the behavior might differ slightly in the actual deployment scenario. And before anyone asks, as always you can override this animation (instructions here) with a static image of your choosing, such as a company logo, if desired. Also, despite the fact that this animation looks significantly more complex than the old one, I'm happy to say that the new animation requires less CPU cycles than the old one; in both cases, we promise we're not slowing the applet startup process by displaying this animation (applet startup is usually I/O bound, and the animation requires very few compute cycles). The new animation unfortunately missed the original JDK 6 release due to time constraints, but I'm glad to report that it's now available in early builds of JDK 6u1 and JDK 7. If you have either of those installed, try loading a large applet (the animation is usually only visible for larger applets that take a while to download) and let us know your thoughts. Hope you enjoy the new look! * ... who unfortunately is leaving Sun as of today... Why, Coleen, why?
In my ears: King Geedorah, "Take Me To Your Leader"
Java 2D and JOGL: The Flip SidePosted by campbell on January 23, 2007 at 12:25 PM | Permalink | Comments (35)The Hemingway Version In my last blog entry, Easy 2D/3D Mixing in Swing, my goal was to show Swing developers how easy it can be to include 3D content in a desktop application via JOGL and OpenGL. I think we've done a decent job of making things easier for that class of developers, but what if we look at the problem from the other end of the barrel? There are lots of JOGL/OpenGL developers that want to include Java 2D elements in their applications. Historically it has been possible to include Java 2D content in a JOGL application, but there haven't been any good standard APIs to make this sort of integration convenient for developers. Until now. Let's get the demo out of the way before getting into any of the details. Here's a screenshot (click to enlarge), for the truly impatient reader:
Better yet, run the demo yourself (the app itself is sandboxed and only requires JDK 5; here's the source code, with NetBeans project included):
The Faulkner Version Ken Russell (the mastermind behind JOGL) promises me that he'll soon have a blog of his own, which means I'll have to stop stealing all of his thunder. In the meantime, let's look at some of the new convenience classes that he's cooked up in the past few weeks (with some prodding from James Gosling, and inspired by some of the reader comments from my last blog).
Texture and
TextureIO
TextureRenderer
Note that currently the
TextRenderer
Overlay
To help explain how these new APIs fit together and how they layer on top of OpenGL, I put together a pancake diagram showing how it all comes together. (I don't have my charting software handy, so the following, might I add beautiful, ASCII art diagram will have to suffice.)
+----------------------------+
| TextRenderer | Overlay |
|----------------------------|
| TextureRenderer - - | - - -> BufferedImage, Graphics2D
|----------------------------|
| Texture - - | - - -> TextureIO, ImageIO
|============================|
| OpenGL textures |
+----------------------------+
That's all for now. In my next entry I'll have some exciting performance numbers to share in the context of the OpenGL-based Java 2D pipeline (hint: hardware accelerated BufferedImageOps).
In my ears: Sloan, "Never Hear The End Of It"
Is This Game Of Tag Over Yet?Posted by campbell on January 05, 2007 at 02:32 PM | Permalink | Comments (1)Well, Richard Bair was kind enough to tag me, but I'm not sure if it was out of pity, or simply out of convenience (we work about 3.5 feet from each other). I've been shocked by how prevalent this whole tag thing has been recently; I mean, doesn't it remind you of those lame chain emails circa 1996? I told myself, "Self, if this tagging thing ever reaches you, you'd better not play along! Those other bloggers are being so vain! Remember your principles!" But it's a new year (a time for resolutions), and I should probably resolve to stop resisting social phenomena just for the sake of resistance. Then again, I usually resist making new year's resolutions as well, for all the same reasons. (Late last year, Chet and I summed up this philosophy as: "I'm sticking it to the man, but the man ain't listening.") Anyway, that's it. I give in. Here are five things you may not know about me:
Okay, that's that. I still feel dirty about keeping this phenomenon alive, but I hope these colleagues of mine have more willpower than I do: Shannon, Alex, Artem, and Jasper.
In my ears: Cluster, "Cluster '71"
Easy 2D/3D Mixing in SwingPosted by campbell on October 12, 2006 at 12:47 PM | Permalink | Comments (29)When You're A Jet... A couple weeks back, I had the privilege of speaking to the Java Programming Club at Monta Vista High School in Cupertino, CA. I'm still amazed at the turnout: about 25 students showed up, all with varying levels of experience with Java, and all apparently willing to endure my so-so demos on their lunch hour. The thing that grabs me though is, if they have a Java club, does that imply that they have other similarly specialized programming clubs too? Do the Ruby, Haskell, Java, and Lisp clubs all confront each other just outside school grounds when they have a score to settle, á la Sharks v. Jets? Anyway, I'd like to thank their president, Anshul Bhagi, for inviting me. It was fun! I promised to post the (rather scattershot) slides from my talk, which mainly revolved around JDK 6 (the new SplashScreen API, 2D/3D mixing in Swing apps, how to get involved, etc). I asked the students if anyone had tried out JDK 6 snapshots, and was surprised to find that none of them had. All the more reason to pose a challenge to the students... By the end of this school year, I'd like to see at least two of them contribute fixes to the JDK 7 project. I know we've had a number of contributions for JDK 6 from the university level, but none that I'm aware of at the high school level, so I think that would be pretty cool. It's A Bit Of A Pain To get the students interested in doing some basic 2D and 3D graphics programming, I showed a couple of existing 2D/3D mixing demos, like Aerith. The great thing about demos like Aerith and its precursor Twinkle is that they're polished and they even behave like "real apps" (bells and whistles included), so ooh/aah factor is never an issue. But of course, we all know that the road to real-app-hood often involves thousands of lines of code, so if you're trying to learn from their source code, it's often difficult to locate the essence of the demo. Twinkle's cool and all, but the source code can be daunting to a newcomer (no fault of Romain's). Quite frequently I hear from developers who are familiar with Swing and Java2D, but haven't the foggiest idea where to begin when it comes to using JOGL in their application. It's especially difficult for developers who have no 3D graphics programming experience to be thrown into the world of OpenGL so abruptly. This time around, I decided to develop my own demo from scratch (with only a few, sparse, documented classes) to help show how to use some complementary technologies in the same application:
Hans thinks we're incapable of writing a 2D/3D demo that goes outside the realm of photo viewers, and you know what, he's probably right (at least for this week). So, mea culpa, I wrote yet another photo-centric demo, but this time I stripped out all that pesky application logic. All that's left is a minimal demo that I hope is easy to understand for beginners. Here's a screenshot of "PhotoCube" (click to enlarge):
Or, why not run it yourself (the app itself is unsigned and requires JDK 6): And finally, here's the source code (NetBeans project included).
The core functionality can be found in the DemoPanel class. The timingframework-specific code is isolated to the (As an aside, one thing I'd like to see is something like a RepaintingObjectModifier, because so often in Swing applications all you want to say is, for example, "animate the location property of this JComponent from here to there, and call repaint() upon each timing event". Right now you have to override ObjectModifier or TimingTarget to get this common behavior, which just adds to the verbosity.)
The 2D/3D mixing code is also in that class, look for the Finally, check out the PhotoCube class, where I demonstrate the nifty TextureIO utility classes. (They're not part of the official JSR-231 spec, but rather are part of the com.sun.opengl.* packages that ship with the JOGL 1.0.0 distribution.) These classes work just like my other favorite API, Image I/O, and really make it easy to load an image from disk (or any other location) into an OpenGL texture. From there, you can use the Texture class, a simple wrapper object for OpenGL textures, which again provides an easier and slightly more object-oriented approach to dealing with OpenGL (a decidedly non-OO library). Enjoy... Okay, I swear, I'm really done now, once again proving that I'm incapable of short-and-sweet...
In my ears: Faust, "IV"
Java 2D Trickery: Light and ShadowPosted by campbell on July 27, 2006 at 04:20 PM | Permalink | Comments (5)Note: The code snippets in this blog entry are intended to be used with Scott Violet's nifty Interactive Graphics Editor. Just cut and paste the code into that application, et voila: instant gratification. This allows you to tinker with the code and immediately see how your changes affect the rendering. In the first installment of my "Trickery" series, I demonstrated a technique for achieving a soft clipping effect. Now let's put it to good use. In this installment I'll show how to add a lighting effect to give your otherwise flat shapes a 3D-ish appearance. If you like your literature illustrated, perhaps a picture will help. I'll show you how to go from the boring, flat shape on the left to the slightly less boring, glossy shape on the right:
With the right colors, you can use this technique to simulate a colored light shining across your shape, producing a subtle glow. How do we achieve this effect? Check out the code below; the comments above the
Note that I've left a few "alternate" lines of code commented out in the example above. Feel free to try uncommenting those lines in IGE and see how they affect the rendering.
Bonus: Astute readers may notice that the same technique used in the Here's some more code you can insert into the above example to add a shadow border to that same shape:
And here's the resulting image:
Note that this is just a quick attempt at adding a drop shadow for demonstration purposes. If I wasn't so lazy, I'd probably use a lighter gray color and a non-linear ramp to achieve a more realistic effect. Also note that this is just one of many ways to add a drop shadow using Java 2D. Romain has discussed different drop shadow implementations in his blog here and here. The SwingLabs folks have a In the next installment of my "Trickery" series, I'll move away from low-level Java 2D effects and show you how to add animations to your applications using the SwingX Painters API and Chet's Timing Framework [tm]. In the meantime, let's see if Josh and Richard pick up the slack and turn some of the above code into stock painters (nudge nudge).
In my ears: Wire, "Chairs Missing" [for about the 3 billionth time in my life]
Five More Easy PiecesPosted by campbell on July 21, 2006 at 01:52 PM | Permalink | Comments (16)I'm sure you're all sick of reading my blogs at this point, because each time I state definitively that the OpenGL-based Java 2D pipeline is "now better than ever," only to follow it up a couple months later with a blog that says, "no really, this time it's even better," and so on. It reminds me of a nearby store called "Cheaper Then Cheaper Cigarettes" [sic]; can you really improve on "cheaper" like that? Anyway, at the risk of sounding like the boy who cried wolf, as of Mustang b92, the OGL pipeline is now "better than better", one might even say it's superfantastic. In the spirit of my recent "Five Easy Pieces" entry, here are five more reasons why the OGL pipeline is better than ever...
OGL: scrolling is extremely slow on Nvidia boards
This bug frustrated me for a number of months, but I was confident that the Nvidia driver engineers would be able to come up with a solution as they've done with so many other issues. Unfortunately, the problem is specific to the way data is laid out in texture memory on certain Nvidia hardware, so a simple driver fix wasn't possible. However, they were kind enough to offer a (somewhat odd) workaround of using the GL_ARB_texture_rectangle extension, since rectangular textures are laid out more efficiently on said hardware and therefore do not exhibit the performance issues reported in this bug. It took quite a bit of work, but the good news is that we were able to get support for the GL_ARB_texture_rectangle extension implemented for b92, so scrolling/dragging performance is back to normal on Nvidia hardware, for both pbuffers and framebuffer objects (FBOs). As an added bonus, the use of that extension allows us to use less texture memory since we no longer have to pad up to power-of-two sized textures on older hardware. (This is what Michael Scott would call a "win win win" situation.)
OGL: enable sun.java2d.opengl.fbobject by default
Another big benefit in fixing the previous scrolling performance bug is that it removed the last big barrier that prevented us from enabling the FBO codepath by default. (I mentioned the FBO codepath in a blog entry from last autumn. Note that since then, Ken Russell and I managed to get JOGL's GLJPanel working with the FBO codepath, so that is no longer a barrier.) So as of b92, we've enabled the FBO codepath by default, which has many benefits when compared to the existing pbuffer-based codepath:
If you've been been bitten by the OGL pipeline in the past (especially those folks with ATI hardware), I'd highly recommend installing b92 for this change alone.
OGL: use new AffineTransform methods in enableGradientPaint()
This one's not terribly exciting... Just a three-line change, but I wanted to mention it in case folks are not aware of some new convenience methods added to the AffineTransform class in Mustang. The first is AffineTransform.invert(), which is useful in those cases where you want to invert the transform matrix in place (hence no need to create a new AffineTransform object). The second is AffineTransform.rotate(vecx, vecy), which is helpful when you want to rotate about a vector (instead of using a relative angle value). In this particular case, the old code was not a major bottleneck in the gradient/texture acceleration path, so there wasn't a huge performance benefit. However, if you have some code that exercises AffineTransform heavily, you might want to check to see if these new methods give you a boost.
OGL: accelerate Gradient/TexturePaint when antialiasing is enabled
This one is terribly exciting, to me at least. We've had some nifty acceleration for GradientPaint and TexturePaint since the OGL pipeline was introduced in JDK 5, but it always came with the caveat that only non-antialiased primitives were accelerated. But as of Mustang b92, we've figured out a way to use multitexturing to combine the gradient/texture acceleration code with our existing antialiased rendering code, which means GradientPaint and TexturePaint are now fully accelerated by the OGL pipeline, regardless of whether antialiasing is enabled. The bug report has more details, but I'll include the executive summary here, because the numbers speak for themselves:
OGL: overlapping LCD glyphs not rendered properly
This was a visible problem caused by an obscure bug, but fortunately the fix was easy. It was the last known problem with the LCD text acceleration code mentioned in my last blog on the subject, and the driver bugs mentioned there have since been fixed as well.
So if you're a fan of LCD text (meaning everyone but Scott, wink wink) and you have shader level hardware (Nvidia GeForce FX/6/7 series, ATI Radeon 9500 and up, etc), please try Bonus: The Driver Report As I've mentioned in past blogs, we've been working with driver teams from Nvidia, ATI, and Sun to ensure that any remaining driver issues are resolved by the time Mustang ships. We have updated our basic acceptance test (BAT) suite with over 50 tests that said driver teams can use to prevent the introduction of new regressions and to test that their existing drivers work well with our OpenGL-based pipeline. For the past couple years, ATI's drivers have been in a sad state of affairs w.r.t. our OGL pipeline (lots of crashes and rendering artifacts). However, I'm now happy to report that ATI has fixed the remaining Linux-specific OpenGL driver bugs that affect our OGL pipeline, so our BAT suite now runs without failure on their forthcoming 8.27 series release. If you're a Linux user with ATI hardware, I'd suggest upgrading to 8.27 when it becomes available in the next couple weeks. As for ATI's OpenGL drivers for Windows, some bugs remain and we are continuing to push those with ATI. But as I mentioned above, the change in b92 that makes the FBO codepath the default means that most of those bugs are no longer reproducible for most newer boards. On the Nvidia and Sun fronts, things are looking really good. There were a couple driver bugs found recently on certain Nvidia laptop GPUs that have since been fixed. If your laptop has an Nvidia GPU and you've been seeing weird artifacts when enabling the OGL pipeline, please install Nvidia's 95.xx series driver when it becomes available in the near future.
In my ears: Viktor Vaughn, "Vaudeville Villain"
Java 2D Trickery: Soft ClippingPosted by campbell on July 19, 2006 at 10:59 PM | Permalink | Comments (10)Note: The code snippets in this blog entry are intended to be used with Scott Violet's nifty Interactive Graphics Editor. Just cut and paste the code into that application, et voila: instant gratification. This allows you to tinker with the code and immediately see how your changes affect the rendering. If you're familiar with Java 2D, you probably already know that you can clip out a portion of your rendering with any arbitrary shape. (If not, go check out the Java Tutorial.) For example, you can give the illusion of someone shining a flashlight on your application by setting a circular clip and then rendering your scene normally. When you clip using a complex shape, you will typically see jaggies around the edges of the region being clipped, which can uglify your app. To illustrate the effect that I'll call "hard clipping", try the following example:
Here's the resulting image:
Wouldn't it be nice if you could antialias those hard edges to remove the jaggies caused by clipping? Well, unfortunately Java 2D (or at least Sun's current implementation) does not support "soft clipping." Sidebar: I add the caveat about Sun's implementation because I was surprised to find that when I tried the above code on my Mac, there were no jaggies! What's going on here? Well, it turns out that Apple's Java 2D implementation uses Quartz under the hood, which appears to do soft clipping by default. In Mustang, Apple is planning to use Sun's software renderer instead of their Quartz renderer by default, so the tips in this blog entry should be relevant for Macs as well. You'd think there would be a RenderingHint to control this behavior, but sorry, no such luck. A few developers have asked for soft clipping in the past, but it doesn't seem to be common enough to warrant adding support for it in our implementation. (I was going to say that it's too much work, and it probably would be, but then my esteemed readers would probably say "well if Apple could implement it in Quartz, why can't you?" Damn those show-offs at Apple. But I digress...)
Fortunately, we've found a fairly simple way to achieve a soft clipping effect using an intermediate image (see Chet's article on that subject) and a little known
Compare the resulting image to the jaggy one above:
Looks better, no? I'll admit that this example is a bit contrived, and it might be hard to see the real world applicability. In the next installment of my "Trickery" series, I'll show you how to apply this technique when creating a lighting effect for arbitrary shapes.
In my ears: Asobi Seksu, "Citrus" [just got back from their show at the Bowery Ballroom no less]
The World's Slowest Web ServicePosted by campbell on April 26, 2006 at 05:03 PM | Permalink | Comments (17)
The Set Up
Person: This rendering op is so slow...
Audience: How slow is it?
Person: It's so slow that it would be faster to air mail each
individual pixel to Timbuktu and back.
A few years ago when the phrase "web services" became all the rage we had to update the punchline:
Person: It's so slow that it would be faster to implement this
op as a web service and host the server in Timbuktu.
Okay, so you're not laughing, but I warned you earlier, I did. Plus, it doesn't help that our collective senses of humor have all been addled recently by Chet and his killer puns (Minneapplet anyone?)... But seriously forks, all the web service yumminess being integrated into Mustang has peaked my interest, especially from the desktop Java standpoint. I've seen a few JAX-WS 2.0 tutorials recently (see "Useful Resources" section below), but most are written from the server-side perspective, and therefore start out with "download the latest GlassFish build" or "grab the latest JWSDP release" or something similar. Already that's one too many steps for my lazy self. I'm a minimalist at heart, so what I really wanted to know was how quickly one could get up and running with JAX-WS using only the latest Mustang binaries. And what better way to learn than to bring that old "joke" to life, so I now present to a truly contrived example: a pixel blender service (and client).
Step 1: Write and compile the endpoint
package blend.endpoint;
import javax.jws.WebMethod;
import javax.jws.WebService;
import javax.xml.ws.Endpoint;
@WebService(serviceName="BlenderService")
public class Blender {
@WebMethod
public int blend(int src, int dst) {
int srcA = src >>> 24;
int srcR = (src >> 16) & 0xff;
int srcG = (src >> 8) & 0xff;
int srcB = (src ) & 0xff;
int dstA = dst >>> 24;
int dstR = (dst >> 16) & 0xff;
int dstG = (dst >> 8) & 0xff;
int dstB = (dst ) & 0xff;
int resA = (int)((srcA * 0.5) + (dstA * 0.5));
int resR = (int)((srcR * 0.5) + (dstR * 0.5));
int resG = (int)((srcG * 0.5) + (dstG * 0.5));
int resB = (int)((srcB * 0.5) + (dstB * 0.5));
return (resA << 24) | (resR << 16) | (resG << 8) | resB;
}
}
The "serviceName" parameter on
As the final part of this step, we will simply compile this source file:
Step 2: Generate the endpoint "portable artifacts"
We pass the
Step 3: Generate the client "portable artifacts"
The
Step 4: Write and compile the client application
package blend.client;
public class Test {
public static void main(String[] args) throws Exception {
BlenderService service = new BlenderService();
Blender blender = service.getBlenderPort();
int src = 0xff00ff00;
int dst = 0xff0000ff;
int res = blender.blend(src, dst);
System.out.printf("src=%08x dst=%08x result=%08x\n",
src, dst, res);
}
}
Note that by default this testcase will talk to the web service endpoint running at
Step 5: Publish the endpoint
package blend.endpoint;
import javax.xml.ws.Endpoint;
public class Test {
public static void main(String[] args) throws Exception {
Endpoint e = Endpoint.create(new Blender());
e.publish("http://127.0.0.1:8084/blend");
System.out.println("Endpoint running");
try {
Thread.sleep(300000);
} catch (InterruptedException ex) {
}
e.stop();
System.out.println("Endpoint stopped");
}
}
This code will publish the web service endpoint on the local machine on port 8084, and will keep it running for 5 minutes. You can run compile and run this testcase easily:
Note that the Endpoint API in Mustang is mainly useful for testing purposes. If you were to publish this for real, you'd probably want to deploy it on one of them application server things the server-side folks like to talk about these days.
Step 6: Run the client application
First fire up the endpoint (Blender Endpoint) using this link (thanks to Romain for hosting the binaries):
Then once the endpoint is running, try running the client app (Blender Client):
Click the button and behold, it should look something like this:
If all goes well, you should see the blended image filling in very, very slowly in the middle of the window. Basically, the app is consulting the Blender web service running on your machine, one pixel and one scanline at a time. Scary, and useless! (By the way, the source code for this application demonstrates a couple other Mustang features, namely SwingWorker and the Desktop integration API, in case you're curious.)
Conclusion
At some point I'd like to go into more detail about my issues with JAX-WS, but I've got a plane to catch! I'll be away for a couple weeks, so hopefully you'll understand if I don't respond to any comments right away. Useful Resources
In my ears: Destroyer, "Destroyer's Rubies"
Five Easy PiecesPosted by campbell on April 24, 2006 at 01:04 AM | Permalink | Comments (8)I'm looking forward to a 2-week vacation in Greece that begins this week, so my mind is prone to wandering these days. Therefore, I wanted to share with you a few short tidbits about some recent/nifty Mustang (Java SE 6) putbacks before they are indefinitely purged from my brain. These fixes and features are small compared to most others in Mustang, but sometimes it's the little things that help round out a release, even for one that already contains so much desktop goodness. And away we go, in no particular order...
AlphaComposite.derive(float alpha)
It's super easy to code up a fade effect in Java 2D using the AlphaComposite class, but eventually your fingers will tire of writing the following verbose code:
g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER,
alpha));
Carpal Tunnel? Suffer no more! Mustang will save you a few keystrokes:
g2d.setComposite(AlphaComposite.SrcOver.derive(alpha));
Clear, concise, nice! This new method saves Romain so much time that he can invent twice as many ridiculous office weapons as before. I recently had to work on a project that needed to run on JDK 5, and if there was one thing I wish I had from Mustang, it was AlphaComposite.derive()!
GTK L&F Default Font
In Tiger and earlier builds of Mustang, Swing's GTK L&F would simply use the default "Dialog" font. In most cases, the chosen font would not be the same as the one used by native GTK applications, and as a result Java applications would look woefully out of place. However, as of Mustang b77, the GTK L&F now consults the fontconfig library, so Swing applications will pick up the same desktop font used by native GTK applications. Clearly this fix is long overdue; it required quite a bit of work, so I'm grateful that Phil fixed this for Mustang (and now I don't have to pester him anymore)! Native fidelity of the GTK L&F has improved considerably in Mustang, and this fix played no small part, but in my opinion we still have a ways to go, so keep those contributions coming...
Double Precision for GeneralPath
This issue has come up at every Java 2D BOF at JavaOne for as long as I can remember, and I'm glad to say that this year we'll finally be able to say that it's available in Mustang. The GeneralPath class has always looked a bit strange without a "double" counterpart, and beyond the obvious symmetry issue, GeneralPath has not been sufficient from a technical standpoint for many advanced users, especially those in the GIS and mapping industries (see the bug report for one such justification). This is another long overdue enhancement, but it required a surprising amount of investigation to come up with a solution that fits in well with the existing java.awt.geom.* class hierarchy, performs well, and is easy to use. The solution that Jim devised, with help from our community friend "leouser", required lots of thought, but it was worth the wait. There is now a Path2D class (with Float and Double variants) in the java.awt.geom package, which will look familiar to longtime Java 2D users. The GeneralPath class is now a trivial subclass of the Path2D.Float class, so your code will continue to work as always with single point precision, but now you have the option to migrate to the new Path2D.Float/Double classes to make the choice of storage a bit more explicit in your code.
OpenGL Acceleration of LCD Text
If you've read Chet's blog or article on the subject, you'll know that it takes quite a bit more computation to get LCD-optimized text onto the screen (when compared to grayscale or monochrome text). As of Mustang b77, the text rendering codepath in the OpenGL-based Java 2D pipeline has been revamped to allow for acceleration of LCD text, in addition to the existing (and very fast) grayscale/monochrome codepath. This is especially noteworthy because it is the first time we have leveraged programmable fragment shader technology in Java 2D. We spent a number of weeks experimenting with a number of approaches in order to achieve maximum performance, and that work has mostly paid off. The performance benefits aren't so noticeable on first and second generation shader-level hardware, but advancements are happening so fast in the graphics hardware space that I think this work will really pay off on today's hardware and beyond (think Nvidia GeForce 7800, ATI Radeon x1800, etc). Unfortunately when this work was putback last month, there were a couple unresolved driver bugs that prevented us from enabling this support by default (see the above bug report for more details on performance as well as the magic incantation to enable this new codepath). Since then, I'm happy to say that both Nvidia and ATI have addressed those issues, but the fixes are not yet in publically available drivers. Once we're satisfied with those driver fixes, we should be able to turn this codepath on by default, when the OGL pipeline is enabled of course. While we're on the subject of driver fixes, I'd like to quickly say thanks to Andy Ritger and team at Nvidia, and Matthew Tippett and Balaji Calidas at ATI, for all their help the past couple years in resolving the remaining driver kinks affecting Java 2D and our OGL pipeline. It's been a lot of work, but the collaboration has paid off and I'm hoping that by the time Mustang ships the last couple outstanding driver issues will be resolved.
Multi-stop Linear/RadialGradientPaints
If you're familiar with the Batik SVG library, you may have used the multi-stop gradient paint classes that are included with it. Those classes were originally written by an intern on the Java 2D team, Nico Talian, way back in the year 2000 (when I was just a lowly intern myself!). The code was donated to the Batik project at that time and the classes have served their purpose well, but in recent years there have been quite a few requests to include these classes with the core JDK. Well, mostly it's been Josh, Richard, and Romain who have been doing the requesting on behalf of SwingLabs (check out their recent work on "painters"), and eventually they wore me down enough so that I'd take on this project. So, we cleaned up the original API and got it into Mustang just in time for b81. The JavaDocs for these new classes include a few basic (yet pretty) images to illustrate the various options: You can also download the latest Mustang snapshot and try the updated "GradAnim" pane in Java2Demo, which demonstrates these new multi-stop gradient classes. (Oh, and before anyone yells at me for not mentioning this, the standard disclaimer applies that these new classes are not officially "in" until the Mustang JSR community -- and the proverbial fat lady -- say so.) The biggest benefit of having these classes in the core JDK, other than the convenience factor, is that we are now able to provide hardware acceleration for these operations, which has been impossible up until this point. As you may know, the OpenGL pipeline already accelerates the basic GradientPaint and TexturePaint operations in hardware for ridiculously good performance (GradientPaint for example is as much as 25x faster via OpenGL than in software!)... When I get back from vacation, I hope to provide similar acceleration for LinearGradientPaint and RadialGradientPaint when the OpenGL pipeline is enabled. More fun with fragment shaders awaits!
More to come...
In my ears: Neu!, "Neu! 2"
Wild Horses: Mustang Beta Is OutPosted by campbell on February 15, 2006 at 08:55 AM | Permalink | Comments (2)I'm an engineer, and if there's one thing that engineers suck at, it's taking stock of recent accomplishments. As soon as one project is "completed" (no matter how significant or gratifying), we're already looking forward to the next big task into which to sink our collective teeth. Who has time to sit around chatting about that old project when there's something new and shiny to tinker with? Such is the case with Mustang (Java SE 6) Beta. No doubt by now you've already downloaded JDK 6 Beta (and if you haven't, then stop reading this drivel and go download it). But when I heard that Mustang Beta hit the streets this morning, my first reaction was something like: "Ho hum, b59g? That's so passe!"... After all, most of my concentration these days is directed on bug fixes and last minute enhancements for Mustang Beta 2, and I'm even spending some time looking into the hazy future that is Dolphin (Java SE 7). Well, Mustang Beta may be passe to me (and to a few thousand eager early adopters who have been downloading the weekly snapshots), but it's new to the other N million Java developers out there. And if you're one of those N million, you can rest assured that the JDK 6 Beta bits you've just gotten your hands on have been much more polished and well-tested than any of those weekly snapshots. Almost all the major features of Mustang are in there, so there's no better time to kick the tires and see how well your application performs on the latest and greatest JDK. At this point, I think I've convinced myself that Mustang Beta isn't passe at all, actually it's quite rad. So maybe it is worth taking a quick look back at my favorite personal accomplishments in Mustang:
5. I assisted with my first externally contributed fix for Mustang. Can't wait to see more of these in the near future. And those of my colleagues:
6. No more scary WebStart dialogs (and the new splashscreens and icons are pretty slick as well).
In my ears: The Buzzcocks, "Singles Going Steady"
400 Horsepower: Image I/O Improvements in MustangPosted by campbell on January 13, 2006 at 01:04 AM | Permalink | Comments (22)Happy New Year! It's been a while since my last post, but I wanted to kick off 2006 by reporting some nice performance improvements in Image I/O. As you may know, we're constantly finding ways to boost performance in various parts of the JDK. In JDK 5 we did some performance work in Image I/O, specifically to avoid finalization in the JPEGImageReader, which made for huge gains in scalability and performance of reading JPEG images. We heard some great feedback about those changes, but we knew there was more work to be done. So a couple months ago, I spent a few solid weeks digging deep into the Image I/O framework and the core plugins trying to find ways to improve performance. I've identified a few long term things we can do to optimize certain plugins even more, perhaps in the Dolphin timeframe. But along the way, I uncovered (and picked off) some low hanging fruit and fixed them in Mustang b63. I won't bore you with all the details, but if you're interested, you can read the evaluations of the following bug reports, all of which were fixed in b63:
Also in those evaluations you'll find lots of raw J2DBench numbers and analysis, but ASCII can be so boring. What blog entry would be complete without a Ross Perot-style chart? [Did I really just make a Ross Perot reference? How pathetic... Maybe next time I'll make a clever remark about Dan Quayle's potatoe?] Feast yr eyes: ![]() That 20x20 JPEG score for JDK 1.4.2 isn't a glitch; it really was that bad (yet another demonstration of the evils of finalizers and explicit System.gc() calls)... Note that this chart only shows results for small images just because I'm tired and lazy, but similar improvements can be seen for larger images as well. For example, I've measured a 53% improvement in reading 4000x4000 pixel JPEG images between Mustang b62 and b63. And yet somehow I'm still not satisfied... We'll continue to work on this stuff as time goes on. In the meantime, please download the latest Mustang snapshot and let us know if these Image I/O enhancements are helping your application. Are You Ready To Testify? I Give You... A Testimonial! While we're on the subject, just yesterday I received some exciting feedback from Jeffrey Moore and James Todd from the JXTA project. You may have read recently that MyJXTA now has a video conferencing feature, which uses MJPEG as the video protocol. It's not the most efficient video format out there, but it was easy for them to use the JPEGImageReader in Image I/O to assist in decoding the JPEG frames. They were asking about JPEG decoding performance and I suggested that they try the latest Mustang builds because of the fixes I mentioned above. It turns out that with the latest Mustang snapshots they are seeing CPU usage cut in half when decoding an MJPEG stream at 30 fps (compared to JDK 5)! The fixes above had a lot to do with it, but I know there have been other performance improvements across the stack (in HotSpot and elsewhere) that are probably contributing as well. This chart tells all:
Meet the Java Client Team When he's not working on one of his cool JOGL/Java2D demos, you can find Romain snapping some photos of the desktop Java geeks that work here on Sun's Santa Clara campus. If you've ever wondered about the faces behind the names, now's your chance to satisfy your curiosity. Or maybe you have a favorite Java2D or Swing bug that still isn't fixed? Here's what you do: print out the responsible engineer's photo, tape it to your office dartboard, and then play a little game of cricket... It may not get that bug fixed any sooner, but what better way is there to relieve the frustration of waiting? Get Involved with Mustang! Well, perhaps that was a tad sinister. I would never condone violence against my fellow Sun engineers (except maybe Chet, but I kid, I kid). If you really do want to see a languishing JDK bug fixed, let me once again recommend the JDK Collaboration project (aka Project Peabody). We've had lots of external developers digging into the JDK source code and submitting complete bug fixes, but we'd love to see more, so why not get involved? There are plenty of open bugs on the "starter list" that you can hack on to get your feet wet. On that note, I recently had the pleasure of working with one such external developer, Rémi Forax, who submitted a really nice patch for this Image I/O RFE. This was a model submission: it wasn't just a cut-and-paste job, but instead included a more complete fix (using JDK 5 features, no less) to make the existing code even better, and to top it off it included the requisite testcase. Thanks for the great fix, Rémi! I hope to see more submissions just like that in the near future...
In my ears-uh: The Fall, "Bend Sinister"
Java2D/JOGL InteroperabilityPosted by campbell on September 15, 2005 at 04:04 PM | Permalink | Comments (13)And so then Java2D says to JOGL: "Ni hao, wode pengyou" In Mustang b51, we made some minor enhancements to Java2D that allow JOGL's GLJPanel implementation to render directly into the Swing backbuffer when the OpenGL-based Java2D pipeline is enabled (see 6309763). While it was certainly possible before to use JOGL in a Swing application, it required a number of intermediate steps to get the proper rendering on the screen in the correct order. With these minor changes in place, JOGL is now able to use an optimized codepath so that rendering goes directly into the OpenGL-enabled Swing backbuffer, effectively bypassing all those slow intermediate steps. Let's just say this makes for some wicked fast 3D rendering in Swing applications! If you've ever tried to integrate a JOGL (or other heavyweight) component into your Swing application, you're probably aware of the horrors of lightweight/heavyweight mixing. The above changes represent a novel solution to the dreaded lw/hw problem because it's now possible to achieve nearly the same framerates as you would in the heavyweight GLCanvas case, instead now all the rendering is respecting the lightweight clipping boundaries and therefore plays nicely with Swing. In addition, this new JOGL codepath takes advantage of the single-threaded architecture of the OpenGL-based Java2D pipeline, so both implementations benefit from improved stability. I'd like to reiterate that this is simply a new optimized codepath in the existing GLJPanel implementation, which means if you're currently using GLJPanel there are no code changes required in your application to take advanatage of this new, fast codepath! So if the OpenGL-based Java2D pipeline is disabled, or you're running your JOGL app on a pre-b51 build of Mustang, or you're running on another vendor's VM that does not include the OpenGL-based Java2D pipeline, then fear not, your app will still run correctly, albeit not as fast as the ideal described above. This post by Ken Russell on the javagaming.org forums has all the details, including links to some cool WebStarted demos. Here are some pretty screenshots of the application running a number of JOGL and Java2D demos in overlapping internal frames. I never thought I'd see the day... [Is that a tear in Ken's eye, or just the sweat from making this happen? Hmm...] Running on Windows XP:
The same demo running unmodified on Solaris 10 (x64, with CDE for some reason, ick!):
The whizzy 3D demos shown here are really impressive, but in my opinion, the real potential here is in the "gears" demo. "But the gears demo is as old as the hills!", I'm hearing you say? Sure, but take a closer look at the screenshots. Note that in this version of the gears demo, the background is filled with a GradientPaint using Java2D (this is accelerated by the OGL pipeline, by the way). Then on top | ||