From: dmatic@athena.mit.edu (Davor Matic)
Subject: Customizable mfb Proposal
Organization: Massachusetts Institute of Technology
Date: Tue, 22 Dec 1992 17:46:33 GMT

----------------------


If anyone is interested in doing this, has commenst and/or suggestions,
please reply...



Customizable Monochrome Frame Buffer [cmfb] by Davor Matic

This is a proposal on how to make the current mfb implementation more
customizable with a minimal loss of performance.  The objective is to
create a monochrome frame buffer library that can be easily ported to
architectures which feature frame buffers that are either not directly
addressable or directly mapped.  This will not cover frame buffers
which are managed by graphics coprocessors.

The basic problem with the current mfb implementation is that it
assumes that the frame buffer is directly accessible and directly
mapped.  This is also a great strength of the current mfb
implementation, since no distinction is made between the internal
representation of pixmaps and external representation of the frame
buffer which account for superior speed and performance.  In the
attempt to make mfb customizable, we need to preserve the performance
as much as possible.  In order to successfully achieve this goal, I
suggest the following approach in customizing mfb.

Step 1.

The current implementation of mfb can be macroized with fairly
reasonable amount of work.  We need to introduce macros that intercept
all references to the frame buffer.  There needs to be a distinction
between references that read a word from the buffer, write a word into
the buffer, or do both operations in a sequence.  This distinction is
needed for directionally banked frame buffers.  Therefore, we will
introduce the following three mapping macros:

	#define  MAPR(ptr)  ((unsigned long *)(ptr))
	#define  MAPW(ptr)  ((unsigned long *)(ptr))
	#define  MAPRW(ptr) ((unsigned long *)(ptr))

The next step is to replace direct references to the frame buffer with
the mapping macros.  Sometimes it will be impossible to distinguish
between references to internal bitmaps and references to the frame
buffer at this stage.  On the other hand, if a reference can not yield
an access to the frame buffer, such as reading tiles which can only be
pixmaps, we shall not use the mapping macros.  An example of these
modifications is below:

	*pdst = *psrc & mask;	
	becomes
	*MAPW(pdst) = *MAPR(psrc) & mask;

	and

	*pdst &= mask;
	becomes
	*MAPRW(pdst) &= mask;

	and 

	src = psrc[-n];
	becomes
	src = *MAPR(&(psrc[-n]));

	and
	
	*pdst++ = *psrc++;
	becomes
	*MAPW(pdst) = *MAPR(psrc); pdst++; psrc++;

This last example is the only modification to the current
implementation of mfb that is visible after expanding the above
defined mapping macros.  I doubt that this would harm performance of
the code in any way.  After we have completed this stage, mfb should
work just as well as the original one without any difference in
behaviour.  This will be a good test for the new code.

Step 2

In this step, we will exercise the mapping macros.  Since at this
point the code is quite unintelligent about distinguishing references
to pixmaps from references to windows, it will be slow.  The speed
considerations will be addressed in steps 3 and 4.

At this point, our macroized mfb is ready to be used with a mapped
and/or banked frame buffer.  All we need to do is redefine the mapping
macros to perform appropriate actions.  When initializing mfb, we pass
it a very high pointer as a virtual frame buffer pointer, and redefine
mapping macros to trap on the pointers with higher values than the
virtual frame buffer pointer.  If we see a higher value than the
virtual frame buffer pointer, we know that mfb is referencing the
screen rather an internal pixmap.  Thus we do something like the
following:

	#define VIRT_FBP   0xFF000000

	unsigned long *virt_to_real_mapping[];

	#define MAPR(ptr) \
		((unsigned long *) \
		 ((ptr) > VIRT_FBP ? \
		  virt_to_real_mapping[(ptr) - VIRT_FBP] : \
		  (ptr)))

	#define MAPW(ptr)  MAPR(ptr)
	#define MAPRW(ptr) MAPR(ptr)

When we get this to work properly, we can go to the next step.  Or we
can stop here is we get too frustrated and don't wanna bother with
performance.

Step 3

Now, we are ready to concern ourselves with performance issues.  The
basic idea is to generate four different sorts of functions form each
previously defined function.  Each function kind will be called with
the right type of source and destination drawable.  We don't need to
write any new code to generate these functions.  All we need to do is
macroize the function names, make symbolic links to the the original
code, and compile each function with a different set macro
definitions.  This is already done in mfb for drawing function that
use different raster operations.

Thus, we will have usually two, or sometimes four new functions for
each old function from mfb.  Here is the example:

	mfbSegmentSS()
	becomes
	    mfbSegmentSSBmp() 
	and mfbSegmentSSWin()

	and

	mfbCopyArea()
	becomes 
	    mfbCopyAreaBmpBmp() 
	and mfbCopyAreaBmpWin() 
	and mfbCopyAreaWinBmp() 
	and mfbCopyAreaWinWin()

This simply means that each function performs operations on the
drawable types specified in the function name.  For mfbSegmentSS(),
all we need to do is compile it with dummy mapping functions to get
mfbSegmentSSBmp(), and compile it with appropriate mapping functions
to get mfbSegmentSSWin().  In the case of mfbCopyArea(), we need to
separate the mapping functions into two kinds.  One kind references
the source drawablle, and the other references the source drawable.
This is a trivial change, but it will have to be done manually.  Thus:

	MAPR()  becomes  MAPSRCR()  and MAPDSTR()
	MAPW()  becomes  MAPSRCW()  and MAPDSTW()
	MAPRW() becomes  MAPSRCRW() and MAPDSTRW()

In order to get mfbCopyAreaBmpBmp(), both, MAPSRCX and MAPDSTX
mappings are the dummy macros.  For mfbCopyAreaBmpWin(), the MAPSRCX
are the dummy macros, while MAPDSTX are the appropriate mapping
macros, etc.  Finally, we add top level procedures called the original
mfb names that perform checks on the drawable types and discriminantly
call the appropriate routines.  At this point, mfb should still
perform all the functions of the mfb from previous step, so we can
debug it against that code.

Step 4

At this point, the mapping macros will be engaged only if indeed mfb
is referencing the frame buffer, and never called when mfb is
referencing an internal pixmap.  Now, we can drop the check against
the virtual frame buffer pointer from the mapping macros:

	#define VIRT_FBP 0L

	#define MAPDSTR(ptr) \
		((unsigned long *) \
		 virt_to_real_mapping[(ptr)])

Step 5

Rename all the function prefixes to cmfb, build the appropriate
Imakefile, and we have completed the customizable monochrome frame
buffer library.



Newsgroups: comp.windows.x.i386unix,comp.os.linux