зеркало из https://github.com/mono/libgdiplus.git
Some minimal documentation about using valgrind to debug libgdiplus and about the different implementations to support regions
svn path=/trunk/libgdiplus/; revision=58362
This commit is contained in:
Родитель
c507663755
Коммит
3f096850cc
|
@ -0,0 +1,103 @@
|
|||
Region implementations in libgdiplus
|
||||
Last update: 2006-03-23
|
||||
|
||||
* Introduction
|
||||
|
||||
First you should notice "implementations" in the title. Yes there is more
|
||||
than one implementation to handle region code.
|
||||
|
||||
|
||||
* Rectangular based regions
|
||||
|
||||
The first implementation (i.e. the only one available before 1.1.14) is
|
||||
based on rectangles. A region is simply a list of rectangles and all
|
||||
binary operations (union, intersection, complement, exclude and xor) are
|
||||
done mathematically (i.e. they results in a new list of rectangles).
|
||||
|
||||
This approach is simple, efficient and allow to implement some other GDI+
|
||||
API very easily (e.g. GdipGetRegionData, GdipGetRegionDataSize,
|
||||
GdipGetRegionScans).
|
||||
|
||||
However it is limited to rectangles (i.e. no polygons, beziers ...) and
|
||||
makes it impossible to implement some other GDI+ API, like
|
||||
GdipTransformRegion where the rectangles would be transformed into paths.
|
||||
Software depending on these features simply can't work.
|
||||
|
||||
All the code for this implementation resides inside the file
|
||||
/libgdiplus/src/region.c
|
||||
|
||||
|
||||
* Bitmap based regions
|
||||
|
||||
This implementation use 1bbp (1 bit per pixel) bitmaps to represent the
|
||||
regions. This allows us to implement the binary operators on memory
|
||||
buffers, not on coordinates (see /libgdiplus/src/region-bitmap.c). At
|
||||
display time (GdipFillRegion) the bitmap is used as the alpha channel and
|
||||
we simply draw a rectangle using the selected brush.
|
||||
|
||||
This approach is simple, compared to a pure mathematical implementation,
|
||||
but not as efficient and somewhat less precise (float to int
|
||||
conversions). This is why the bitmap implementation co-exists with the
|
||||
rectangular based region code. Simple regions get treated simply ;-)
|
||||
|
||||
To minimize the inconveniences the bitmaps are created only on demand
|
||||
(e.g. when an API requires them) and we try, as much as possible, to
|
||||
avoid this code path (e.g. using the rectangle code where possible, check
|
||||
for special cases, like an union with infinity...).
|
||||
|
||||
Sadly having bitmaps isn't quite enough. We still have to be able to
|
||||
apply transforms (i.e. GdipTransformRegion) and be able to [de]serialize
|
||||
the region (GdipGetRegionData). While both operations _could_ be done
|
||||
with bitmaps the results wouldn't be very precise (transform) nor small
|
||||
(serialization). This is why the region keeps a tree of all the paths and
|
||||
operations required to re-construct itself (see
|
||||
/libgdiplus/src/region-path-tree.c).
|
||||
|
||||
The code for this implementation resides in the files:
|
||||
|
||||
/libgdiplus/src/region.c|h
|
||||
The GDI+ API for regions. The API will switch to the rectangle or
|
||||
bitmap code based on the regions type. If required a rectangle-
|
||||
based region will be "promoted" to a bitmap region.
|
||||
|
||||
/libgdiplus/src/region-bitmap.c|h
|
||||
Handle the bitmap allocation, creation (from path), the binary
|
||||
operations, ...
|
||||
|
||||
/libgdiplus/src/region-path-tree.c|h
|
||||
Handle the tree of path and (binary) operations required to
|
||||
re-construct the region if required (e.g. transform and
|
||||
serialization).
|
||||
|
||||
There are currently two main limitations to this approach:
|
||||
|
||||
1. Memory. It's simply impossible to allocate enough memory for an
|
||||
"infinite" region. There is a maximum of 2 megabytes allocated for a
|
||||
region bitmap (see region-bitmap.h). This is enough (1bbp) for
|
||||
regions to cover a full screen resolution.
|
||||
|
||||
2. Clipping. Graphics.Clip can't use the bitmap (at least not without
|
||||
major changes). This means that clipping _will_work_ for any region
|
||||
(not just rectangles) until a binary operation is done on it. So far
|
||||
I've not seen any code trying that...
|
||||
|
||||
|
||||
* Future?
|
||||
|
||||
A pure, totally mathematical, implementation would be a nice addition to
|
||||
libgdiplus. It could, once debugged, replace both the rectangular and
|
||||
bitmap implementations.
|
||||
|
||||
The main advantages of this implementation would be:
|
||||
- reduced memory requirements (well most of the time);
|
||||
- (almost) unlimited size;
|
||||
- more precision (no float to int conversion);
|
||||
- no limits on clipping;
|
||||
|
||||
So if it's the best solution why don't we have it yet ?
|
||||
|
||||
Well it's really not an easy problem. Writing an effective intersector is
|
||||
a complex problem. You must deal with curves (well they could be cheated
|
||||
into linear paths) and a _lot_ of corner cases (google for them). Most
|
||||
existing (open source) implementation aren't satisfied with their results
|
||||
(e.g. libart, livarot). But don't let us discourage you from trying! ;-)
|
|
@ -0,0 +1,42 @@
|
|||
Using valgrind to find memory leaks in libgdiplus
|
||||
Last update: 2006-03-23
|
||||
|
||||
* Introduction
|
||||
|
||||
Valgrind (http://valgrind.org/) is a nice tool for finding memory leaks
|
||||
and related problems (e.g. like reusing freed memory).
|
||||
|
||||
Libgdiplus is the foundation of Mono's System.Drawing.dll assembly. Any
|
||||
leak from libgdiplus will make your .NET application leak - no GC help
|
||||
here!
|
||||
|
||||
There are many ways to run valgrind on libgdiplus. The most simple one is
|
||||
to use (or write) a C program using and use valgrind on it, but the most
|
||||
interesting one are running System.Drawing samples using Mono.
|
||||
|
||||
|
||||
* Using valgrind with Mono
|
||||
|
||||
Historically Mono and Valgrind didn't always played well together. If
|
||||
this has discouraged you in the past then it's time to try it again!
|
||||
|
||||
Recent valgrind versions are able to deal with for self-modifying
|
||||
programs (which is what the mono JIT does) by using the
|
||||
--smc-check=all option.
|
||||
|
||||
As an extra bonus, Paolo (lupus) has shared his suppression file for
|
||||
Mono. This removes a lot, but not all, false positives (or unimportant)
|
||||
logs coming from the Mono runtime. This makes it easier and faster to
|
||||
find what you're looking for. The suppression file is available in
|
||||
Mono's SVN as /mono/data/mono.supp
|
||||
|
||||
|
||||
Sample usage:
|
||||
|
||||
valgrind --tool=memcheck -v --leak-check=full --log-file=log
|
||||
--smc-check=all --suppressions=mono.supp mono app.exe
|
||||
|
||||
This will run the app.exe application using mono and create a log file
|
||||
named "log.####" (where #### is the process id). The log file will
|
||||
indicates what leaked (and from where), what was (badly) reused after
|
||||
being freed, ...
|
Загрузка…
Ссылка в новой задаче