[prev in list] [next in list] [prev in thread] [next in thread] 

List:       wine-devel
Subject:    RFC: Logical to device translation layer
From:       Patrik Stridvall <ps () leissner ! se>
Date:       2000-10-27 19:24:03
[Download RAW message or body]


After the discussion triggered by Mark Dufour's attempt
to optimize X11DRV_LineTo, I sat down I tried to think
through what various people had said and try to find
a solution that would satisfy the worries of different
people including myself. :-)

This resulted in the following solution to the problem
of optimizing the GDI functions that I have implemented
the _infrastructure_ for. A patch that does this is
attached in order to try to move the discussion from
teoretical worries and problems down to the worries and
problems of the real world.

So what I'm I trying to do?

First an observation: The current mapping, to use a
common name for offsets, scale factors, rotations
or other kind of transforms, seldom changes. In fact
it can only change if the application calls one of
the following functions.

SetMapMode
{Set,Modify}WorldTransform
{Set,Offset,Scale}{Viewport,Window}{Ext,Org}Ex

In Wine's implementation, all of these functions
will eventually call the function DC_UpdateXforms
in object/dc.c before returning.

Since all calls to the device driver (X11, printer etc)
goes through the the dc->funcs (DC_FUNCTIONS) jump table,
we could check how advanced the current mapping and
change the jump table accordingly.

This is pretty obvious. As Huw D M Davies said to me
"I know you were going to suggest that". :-)

However if done in a bad way this will lead to a lot
of code duplication and make maintaince more difficult
as Ulrich Weigand pointed out.

So I sat down and though about it some more.

One of the first things I observed is that there are two
different kinds of device drivers. One that works in logical
coordinates since the underlying "system" can or must
use them and the kind the have no real concept of logical
coordinates and always converts them to device coordinates.
The important ones that works with logical coordinates is 
the {,enh}metafile drivers and among the important ones that
works with device coordinates is primarily the X11 driver.

This realization led to the idea that we really should have
two DC_FUNCTIONS jump tables of that takes logical coordinates
and one that takes device coordinates.

Before anybody points it out, I will point out the fact that
many functions are coordinate system independent and that we in
that case should split up DC_FUNCTIONS is two different structures.
This is probably true but this is an almost completly ortogonal
problem, that is easy to solve, so I will not discuss it further.
It doesn't really effect performance, it mainly effects maintainance.

So we will end up with drivers that have device jump table 
mainly empty (metafile) and drivers that will have the logical
jump table mainly empty (X11).

OK, so how are we going to call everything from the device independent
parts. We don't want to the device independ layer to work with
device coordinates that will probably be painful.

So we have the device indendent layer that wants to use logical
coordinates and some device drivers (X11) that wishes to use
device coordinates. That doesn't really mix well together does it?

The answer is a logical to device translation layer.
Will that not be expensive permformancewise and hard to
maintain you ask? No, not at all. See the attached patch.
In fact it will optimize the most important path, the
constant scaling zero offset case, the best. That is, the case
that applications that really cares about performance are
likely to use.

It might be a little hard to see what the patch does so I will
try to explain.

There are 4 different kinds of translations.
1. Full world transform (implemented in graphics/log2dev.c)
2. Scaling (implemented in graphics/scl2dev.c)
3. Offsetting (implemented in graphics/off2dev.c)
4. Nothing (not implemented anywhere since it is not needed)

Each device driver have two DC_FUNCTIONS jump tables, or for logical
coordinates and one for device coordinates.

When we register even device driver we use these 2 jump tables
to generate 4 jump tables for the 4 cases above that uses that
the translation function if needed. The jump table for case 4
is just a direct call to device driver table for device
coordinates so _no_ translation is performed at all.

When the mapping changes (DC_UpdateXforms
in object/dc.c is eventually called) we choose
which of the 4 jump tables which should be used.

Note that this patch currently only implement the
infrastructure for this. If and when applied, however
we can begin the real work of making Wine run faster.

However we have to be really careful when we do this,
there are a few dragons lurking in the forest of
ignorance.

In case 4 no translation is needed, so the translation layer
is not called at all. This which mean that we have to be
really careful _where_ optimizing if-nothing-visible-needs-to-be-
drawn tests and swap-the-parameters-when-"left"-greater-than-
"right" test are performed.

There are three places when such tests can be placed.
(1) Logical (device independent) layer
(2) Logical to Device layer 
(3) Device layer.

Note as I said earlier that (2) is not called
if logical coordinates are already device coordinates.
However that doesn't mean that the different classes
of optimizations shouldn't be performed and care should
be take to only do them once.

In principle I think no such things should be performed
the device layer at all if avoidable. This is order to
make the important case 4 have maximum performance.

So what do you think?

PS. If anybody applies the patch and tests it,
the correct behavior is that Wine works exactly
as before and just as fast. It currently only
a add some infrastructure. But please test it
to assure that everything really is like before. :-)


["log-dev.tar" (application/octet-stream)]

[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic