Bug 300403 - Adopt Windows 7 DirectX 2D API - use it instead of old GDI+ API
Summary: Adopt Windows 7 DirectX 2D API - use it instead of old GDI+ API
Status: NEW
Alias: None
Product: Platform
Classification: Eclipse Project
Component: SWT (show other bugs)
Version: 3.6   Edit
Hardware: PC Windows XP
: P3 enhancement with 2 votes (vote)
Target Milestone: ---   Edit
Assignee: Platform-SWT-Inbox CLA
QA Contact: Felipe Heidrich CLA
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2010-01-21 12:15 EST by Alex Boyko CLA
Modified: 2015-03-02 02:36 EST (History)
11 users (show)

See Also:


Attachments
patch with initial Direct2D support (35.94 KB, patch)
2010-04-14 12:02 EDT, buginox CLA
no flags Details | Diff
test project with initial Direct2D support (338.81 KB, application/x-zip-compressed)
2010-04-14 12:04 EDT, buginox CLA
no flags Details
test project without Direct2D support (1.41 MB, application/x-zip-compressed)
2010-04-14 12:07 EDT, buginox CLA
no flags Details
Poor text antialias with GDI+ (5.51 KB, image/png)
2012-04-03 08:04 EDT, Peter Severin CLA
no flags Details
A more recent d2d/dw test (186.40 KB, patch)
2012-06-22 04:34 EDT, L. Mihalkovic CLA
no flags Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Alex Boyko CLA 2010-01-21 12:15:45 EST
Draw2D suffers from GDI+ painting performance with anti-alias enabled. In particular the performance degrades when dash-lines are painted.
Draw2D solution for this problem would be paint without anti-alias and then when UI thread is free paint the same thing again with anti-alias. This solution is overly-complicated and doesn't fit well in the current framework.

Given that OpenGL 3-rd party Java bindings: LWJGL and JOGL can't be part of Orbit, because of the IP test failures, Draw2D would be interested in faster SWT rendering at least on Windows 7.
Comment 1 Felipe Heidrich CLA 2010-01-21 16:09:53 EST
This would be great improvement. I already did some investigation in this area.
My first goal was to have a few benchmarks that show real performance improvement for SWT using Direct2D versus GDI+. Unfortunately I didn't have time to finish it.

This is a big work item and it would be very dificult to get it in for 3.6 (we are all maxed around here).

Likewise, we should be able to DirectWrite to replace Uniscribe for TextLayout.

Please, provide a simple benchmark for the case you have that is slow.
Comment 2 Alex Boyko CLA 2010-01-21 16:42:10 EST
Do you mind if I create a Draw2D dependent snippet?
Comment 3 Felipe Heidrich CLA 2010-01-21 16:53:51 EST
(In reply to comment #2)
> Do you mind if I create a Draw2D dependent snippet?

SWT only is better for me, that way I can't blame poor performance on any other component but SWT itself ;-)
Comment 4 buginox CLA 2010-04-14 12:02:30 EDT
Created attachment 164844 [details]
patch with initial Direct2D support

There are two test projects for initial implementation of Direct2D support. There are two projects: 
- SwtDirect2D - instead of gdi+ it uses direct2d to draw lines.
- SwtGdip - normal GDI+ implementation
Both projects contain all required libraries and launch configurations. Below is a list of Direct2D features already supported:
- drawing on event.gc
- drawing both Direct2D and GDI+ objects on the same gc
- options for lines: width, start cap, end cap, dash cap, line join, miter limit, dash style dash offest
- supported methods: setLineWidth(), setForeground(), setLineCap(), setAntialias(), setLineJoin(), setLineWidth(), drawLine(), setLineAttributies()

I have used gdip.cpp to implement all native methods. Of course, all direct2d methods should be extracted into direct2d.cpp file.

I haven't made any bigger tests yet but the performance difference is significant, e.g. in Direct2D drawing 10.000 lines took 0.15s when in gdi+ it took 17s. The main difference is that Direct2D draws all lines and them display them instead of gdi+ which display each line separately.

Also native transformation methods are also implemented but I haven't added access to them cause of some problems with adopting them into existing gdi+ transforming methods.
Comment 5 buginox CLA 2010-04-14 12:04:19 EDT
Created attachment 164845 [details]
test project with initial Direct2D support

This project needs swt.jar created with patch attached to this bug.
Comment 6 buginox CLA 2010-04-14 12:07:51 EDT
Created attachment 164847 [details]
test project without Direct2D support

This is the same project as SwtDirect2D but with old GDI+. It doesn't require any additional libraries (swt.jar is included).
Comment 7 Wojciech Galanciak CLA 2010-04-14 12:12:45 EDT
Last three comment are written by me. I haven't noticed that I had been logged on a different account.
Comment 8 Felipe Heidrich CLA 2010-04-14 15:34:32 EDT
The number on my machine are:
Direct2D: time for 100000 lines: 5.36 sec
GDI+: time for 10000 lines: 9.469 sec

>The main difference is that Direct2D draws all lines and them display
>them instead of gdi+ which display each line separately.

It is because, in Direct2D, you call BeginDraw one time before the first line draw and then you call EndDraw one time after the last line draw (which is right). For testing sake, can we batch all drawing operations in GDI+ too ?

About the code:
the native part can't be used.
- lots of unnecessary custom code
- requires Windows 7 SDK (we use a much older SDK for compability reasons)

For some reason I thought there was a OLE API for Direct2D we could use; all class would be dynamic (vtbl); would not use a flat hierarchy

The code in GC, I personally found it quite messy (that is probably because it is not finished yet).
Comment 9 Felipe Heidrich CLA 2010-04-14 15:42:51 EDT
If I set SWT.DOUBLE_BUFFERED in the canvas (and remove SWT.NO_BACKGROUND and SWT.RESIZE_REDRAW) the direct2d implementation stop working (draws all black).

the gdip+ implementation gets a bit faster:
time for 10000 lines: 8.0 sec
Comment 10 Wojciech Galanciak CLA 2010-04-15 06:02:21 EDT
> It is because, in Direct2D, you call BeginDraw one time before the first line
> draw and then you call EndDraw one time after the last line draw (which is
> right). For testing sake, can we batch all drawing operations in GDI+ too ?
How can we do that except double buffering option for canvas? I have tested Direct2D with each draw operation wrapped into begin and end but it is very slow and comparable with GDI+ performance. 

> About the code:
> the native part can't be used.
> - lots of unnecessary custom code
There are methods for transformation which I haven't implemented in java yet. Also StrokeStyle is not fully implemented (there is no support for custom dashes). Anyway, what do you mean by custom code (I would like to know what I should improve)?

> - requires Windows 7 SDK (we use a much older SDK for compability reasons)
Can it be the reason why I cannot run Direct2D project on Windows XP?


> For some reason I thought there was a OLE API for Direct2D we could use; all
> class would be dynamic (vtbl); would not use a flat hierarchy
I think that there is no such API for Direct2D.


> The code in GC, I personally found it quite messy (that is probably because it
> is not finished yet).
Yes, I agree. Most of this mess is caused by simultaneous support of GDI+ and Direct2D. I mean you can draw using GDI+ and Direct2D in the same GC. In this case EndDraw must be called before each draw operation except DrawLine which support Direct2D.

> If I set SWT.DOUBLE_BUFFERED in the canvas (and remove SWT.NO_BACKGROUND and
> SWT.RESIZE_REDRAW) the direct2d implementation stop working (draws all black).
This option on Windows 7/Vista causes that double buffering provided by Vista/7 is used. I think that for Windows 7 is unnecessary cause Direct2D is already double buffered. In this case this double buffering should be used only if direct2d is unavailable and operating system is Windows Vista.
Comment 11 Peter Severin CLA 2012-04-03 08:03:31 EDT
I am also interested in this API, specifically in DirectWrite support for antialiased text. Right now results produced by GDI+ are not ideal and compare poorly with results on Mac and Linux. This can be easily seen with large font sizes (see letter e and a in attached screenshot). Here's a good article that compares rendering engines, DirectWrite and GDI+ among them: http://blog.typekit.com/2010/10/15/type-rendering-operating-systems/
Comment 12 Peter Severin CLA 2012-04-03 08:04:19 EDT
Created attachment 213490 [details]
Poor text antialias with GDI+
Comment 13 Peter Severin CLA 2012-04-04 04:12:10 EDT
Here's a blog post that talks about text rendering in Firefox using DirectWrite vs GDI:
http://blog.mozilla.com/nattokirai/2011/08/11/directwrite-text-rendering-in-firefox-6/
Comment 14 L. Mihalkovic CLA 2012-06-22 04:34:22 EDT
Created attachment 217731 [details]
A more recent d2d/dw test

I started playing with d2d and dw support in win7. There are a few issues with it (not dynamically looking up factories, using vtbl vs. direct calls, ...). Can someone have a quick peek and gage if it is worth I address them to keep going in that direction!?

The directWrite tests I made are really showing how much nicer the text looks like for large scale. I was reading the firefox article and wondering if it would be worth having something similar in eclipse where different fonts/sizes would configure different rendering paths to maximize legibility (disclaimer, I do not have a windows machine and all the tests are done inside a vm).
Comment 15 L. Mihalkovic CLA 2012-06-22 04:35:10 EDT
I will push the code to a swt fork on github (easier to manipulate)