1. Code Analysis of DDX Output Layer
抱歉这篇报告是用英文写的,有兴趣的朋友可以参考。
1.1 A Big Picture of Maemo DDX Output Layer
From the above description, following is the big picture of it:
Figure 4: DDX Porting Output Layer Big Picture of Maemo
1.2 Start up procedure of Maemo DDX Output Layer
Output devices initialization is also started from main function in dix/main.cpp, which calls:
main(int argc, char *argv[], char *envp[])
{
……
while(1)
{
……
screenInfo.arraySize = MAXSCREENS;
screenInfo.numScreens = 0;
screenInfo.numVideoScreens = -1;
……
InitOutput(&screenInfo, argc, argv);
……
}
Variable screenInfo is a global DIX variable that list all screen devices, which is of type ScreenInfo, defined as following:
typedef struct _ScreenInfo {
int imageByteOrder;
int bitmapScanlineUnit;
int bitmapScanlinePad;
int bitmapBitOrder;
int numPixmapFormats;
PixmapFormatRec
formats[MAXFORMATS];
int arraySize;
int numScreens;
ScreenPtr screens[MAXSCREENS];
int numVideoScreens;
} ScreenInfo;
Function InitOutput is a DDX function, which in our case is in file kdrive/omap/omapinit.c. This function just simply calls KdInitOutput to finish all works. (We can see that many works are called back in omap layer from following analysis).
void
InitOutput (ScreenInfo *pScreenInfo, int argc, char **argv)
{
ENTER();
KdInitOutput(pScreenInfo, argc, argv);
LEAVE();
}
KdInitOutput is the core function that finishes most works of output devices initialization. Following is the code snap, and we will analyze them in details.
void
KdInitOutput (ScreenInfo *pScreenInfo,
int argc,
char **argv)
{
KdCardInfo *card;
KdScreenInfo *screen;
#ifdef COMPOSITE
/* kind of a hack: we want Composite enabled, but it's disabled per
* default. */
noCompositeExtension = FALSE;
#endif
if (!kdCardInfo)
{
InitCard (0);
if (!(card = KdCardInfoLast ()))
FatalError("No matching cards found!/n");
screen = KdScreenInfoAdd (card);
KdParseScreen (screen, 0);
}
/*
* Initialize all of the screens for all of the cards
*/
for (card = kdCardInfo; card; card = card->next)
{
int ret=1;
if(card->cfuncs->cardinit)
ret=(*card->cfuncs->cardinit) (card);
if (ret)
{
for (screen = card->screenList; screen; screen = screen->next)
KdInitScreen (pScreenInfo, screen, argc, argv);
}
}
/*
* Merge the various pixmap formats together, this can fail
* when two screens share depth but not bitsPerPixel
*/
if (!KdSetPixmapFormats (pScreenInfo))
return;
/*
* Add all of the screens
*/
for (card = kdCardInfo; card; card = card->next)
for (screen = card->screenList; screen; screen = screen->next)
KdAddScreen (pScreenInfo, screen, argc, argv);
#ifdef DEBUG
signal(SIGSEGV, KdBacktrace);
#endif
}
InitCard is first invoked since global DDX variable kdCardInfo is NULL when system starts up. It is a DDX function should be implemented by concrete vendors and is in kdrive/omap/omapinit.c in our case, which calls KdCardInfoAdd to add a new KdCardInfo struct, by passing omapFuncs as the parameter, which is of type KdCardFuncs. Function KdCardInfoAdd add a new KdCardInfo and link it to global variable kdCardInfo, and set member cfuncs of this new KdCardInfo to omapFuncs.
typedef struct _KdCardInfo {
struct _KdCardFuncs *cfuncs;
void *closure;
KdCardAttr attr;
void *driver;
struct _KdScreenInfo *screenList;
int selected;
struct _KdCardInfo *next;
Bool needSync;
int lastMarker;
} KdCardInfo;
typedef struct _KdCardFuncs {
Bool (*cardinit) (KdCardInfo *); /* detect and map device */
Bool (*scrinit) (KdScreenInfo *);/* initialize screen information */
Bool (*initScreen) (ScreenPtr); /* initialize ScreenRec */
Bool (*finishInitScreen) (ScreenPtr pScreen);
Bool (*createRes) (ScreenPtr); /* create screen resources */
void (*preserve) (KdCardInfo *); /* save graphics card state */
Bool (*enable) (ScreenPtr); /* set up for rendering */
Bool (*dpms) (ScreenPtr, int); /* set DPMS screen saver */
void (*disable) (ScreenPtr); /* turn off rendering */
void (*restore) (KdCardInfo *); /* restore graphics card state */
void (*scrfini) (KdScreenInfo *);/* close down screen */
void (*cardfini) (KdCardInfo *); /* close down */
Bool (*initCursor) (ScreenPtr); /* detect and map cursor */
void (*enableCursor) (ScreenPtr); /* enable cursor */
void (*disableCursor) (ScreenPtr); /* disable cursor */
void (*finiCursor) (ScreenPtr); /* close down */
void (*recolorCursor) (ScreenPtr, int, xColorItem *);
Bool (*initAccel) (ScreenPtr);
void (*enableAccel) (ScreenPtr);
void (*disableAccel) (ScreenPtr);
void (*finiAccel) (ScreenPtr);
void (*getColors) (ScreenPtr, int, int, xColorItem *);
void (*putColors) (ScreenPtr, int, int, xColorItem *);
} KdCardFuncs;
KdCardFuncs omapFuncs = {
.cardinit = omapCardInit,
.scrinit = omapScreenInit,
.initScreen = omapInitScreen,
.createRes = omapCreateResources,
.dpms = omapDPMS,
.scrfini = omapScreenFini,
.finishInitScreen = omapFinishInitScreen,
.cardfini = omapCardFini,
};
Function KdScreenInfoAdd is then invoked, it simply new a KdScreenInfo struct and add it to member screenList of the KdCardInfo struct just created above. Function