Bad performance with Canvas and extensive clipping
Tom Schindl
tom.schindl at bestsolution.at
Tue May 27 21:57:39 UTC 2014
Is there anything I could do to help getting rectangular clipping into
JavaFX - I tried to find my way through the sources but I'm not sure I
have enough knowledge to provide a patch in this area.
BTW it looks like I'm not alone with the clipping performance problem
see
http://tomsondev.bestsolution.at/2014/05/24/swtonfx-javafx-canvas-with-many-clipping-calls-unacceptable-slow/#comments
Tom
On 27.05.14 23:47, Jim Graham wrote:
> Canvas is, essentially, a "draw pixels" mechanism. We have to bundle
> the requests into a command stream due to threading issues, but when the
> requests get to the render thread then they get turned into pixels so
> the command stream is a temporary intermediary. Some of the hw J2D
> pipelines also have a temporary command stream due to platform threading
> issues as well. It all depends on which pipeline you use and on which
> platform in the case of J2D. FX simply normalized the threading on all
> pipelines/platforms so that we have a separate UI and render thread in
> all cases, but that concept is not foreign to J2D either.
>
> I'm fairly certain that the lack of simple rectangular clipping is
> probably the biggest cause of your performance problems. We do AA on
> everything in FX, though, whereas rendering to a BufferedImage by
> default will be non-AA unless you requested AA using the graphics hints.
> But on the up-side, we hw accelerate just about every operation in FX
> so it should be on par with performance there, modulo the lack of
> rectangular clipping...
>
> ...jim
>
> On 5/23/14 5:46 PM, Tom Schindl wrote:
>> Hi,
>>
>> As an experiment I've now written a SWT-GC implementation using a
>> BufferedImage & Graphics2D and transfering the pixels over to JavaFX and
>> the performance is as it is with native SWT.
>>
>> I always thought Canvas works similar to Image and one only draws pixels
>> - looks like that is not the case, having a dep in my application
>> java.awt is not what I'm aiming at but without acceptable performance in
>> conjunction with clipping it looks like i have to go this route :-(
>>
>> Tom
>>
>> On 23.05.14 23:57, Tom Schindl wrote:
>>> In the current usecase it is a rect all time but that's just in this
>>> special use case.
>>>
>>> I guess that rect clipping is the most common one so having an
>>> optimization for rects and a slow path for none rects might help.
>>>
>>> Tom
>>>
>>> Von meinem iPhone gesendet
>>>
>>>> Am 23.05.2014 um 23:35 schrieb Jim Graham <james.graham at oracle.com>:
>>>>
>>>> Are you clipping to an arbitrary path in all cases or just a
>>>> rectangle? Unfortunately we only offer the arbitrary
>>>> clip-to-current-path method that isn't optimized for basic
>>>> rectangular clipping and it implements soft clipping.
>>>>
>>>> There is an outstanding tweak that we added faster clipping support
>>>> for WebNode and we need to start using it for
>>>> Node.setClipNode(non-rectangle) and Canvas, but we haven't
>>>> implemented that yet.
>>>> (https://javafx-jira.kenai.com/browse/RT-30107) It basically is a
>>>> direct "render this texture through that other texture as a clip"
>>>> operation instead of the current code that runs it through some
>>>> Blend effect filters. It would definitely improve your run times,
>>>> but I'm not sure how much.
>>>>
>>>> Even more savings could be had for rectangular clips if we provided
>>>> some way to communicate them to the GC...
>>>>
>>>> ...jim
>>>>
>>>>> On 5/23/14 11:47 AM, Tom Schindl wrote:
>>>>> Hi,
>>>>>
>>>>> Maybe as some of you might know I've been working since sometime on
>>>>> SWT
>>>>> on JavaFX and to implement direct drawing operations we use
>>>>> JavaFX-Canvas.
>>>>>
>>>>> I've today tried to run a heavy direct drawing grid implementation and
>>>>> it performed very bad because it makes heavy use of clipping.
>>>>>
>>>>> For a grid I've counted ~1500 clipping operations the library works
>>>>> something like this:
>>>>>
>>>>> boolean activeClip;
>>>>> Canvas canvas = new Canvas();
>>>>>
>>>>> public void setClipping(PathIterator pathIterator) {
>>>>> GraphicsContext gc = canvas.getGraphicsContext2D();
>>>>> if(activeClip) {
>>>>> gc.restore();
>>>>> activeClip= false;
>>>>> }
>>>>>
>>>>> if( pathIterator == null ) {
>>>>> return;
>>>>> }
>>>>>
>>>>> activeClip = true;
>>>>> float coords[] = new float[6];
>>>>> gc.save();
>>>>> gc.beginPath();
>>>>>
>>>>> float x = 0;
>>>>> float y = 0;
>>>>>
>>>>>
>>>>> gc.moveTo(0, 0);
>>>>>
>>>>> while( ! pathIterator.isDone() ) {
>>>>> switch (pathIterator.currentSegment(coords)) {
>>>>> case PathIterator.SEG_CLOSE:
>>>>> gc.lineTo(x, y);
>>>>> break;
>>>>> case PathIterator.SEG_CUBICTO:
>>>>> gc.bezierCurveTo(coords[0], coords[1], coords[2],
>>>>> coords[3],
>>>>> coords[4], coords[5]);
>>>>> break;
>>>>> case PathIterator.SEG_LINETO:
>>>>> gc.lineTo(coords[0], coords[1]);
>>>>> break;
>>>>> case PathIterator.SEG_MOVETO:
>>>>> gc.moveTo(coords[0], coords[1]);
>>>>> x = coords[0];
>>>>> y = coords[1];
>>>>> break;
>>>>> case PathIterator.SEG_QUADTO:
>>>>> gc.quadraticCurveTo(coords[0], coords[1],
>>>>> coords[2], coords[3]);
>>>>> break;
>>>>> default:
>>>>> break;
>>>>> }
>>>>> pathIterator.next();
>>>>> }
>>>>>
>>>>> gc.clip();
>>>>> gc.closePath();
>>>>> }
>>>>>
>>>>> Am I doing something ultimately wrong, totally wrong? Has anyone an
>>>>> idea
>>>>> how I would work around the problem?
>>>>>
>>>>> Tom
>>>>>
>>
More information about the openjfx-dev
mailing list