抱歉这篇报告是用英文写的,有兴趣的朋友可以参考。
From the above description, following is the big picture of it:
Figure 4: DDX Porting Output Layer Big Picture of Maemo
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 KdParseScreen is then invoked to get related parameters of KdCardInfo member, such as width, width_mm, height, height_mm, randr, fb and its members, rate, etc. Please notice that frame buffer is linked in to the list of KdScreenInfo, the member name is fb[KD_MAX_FB].
typedef struct _KdScreenInfo {
struct _KdScreenInfo *next;
KdCardInfo *card;
ScreenPtr pScreen;
void *driver;
Rotation randr; /* rotation and reflection */
int width;
int height;
int rate;
int width_mm;
int height_mm;
int subpixel_order;
Bool dumb;
Bool softCursor;
int mynum;
DDXPointRec origin;
KdFrameBuffer fb[KD_MAX_FB];
CARD8 *memory_base;
unsigned long memory_size;
unsigned long off_screen_base;
} KdScreenInfo;
typedef struct _KdFrameBuffer {
CARD8 *frameBuffer;
int depth;
int bitsPerPixel;
int pixelStride;
int byteStride;
Bool shadow;
unsigned long visuals;
Pixel redMask, greenMask, blueMask;
void *closure;
} KdFrameBuffer;
Let’s go back to function KdInitOutput. For each added cards (in our case, there is only one card), its cardinit function is then called, which should be in omapCardInit our case.
static Bool omapCardInit(KdCardInfo *card)
{
OmapCardInfo *omapc;
char fbpath[10];
int i;
ENTER();
omapc = (OmapCardInfo *) xcalloc(1, sizeof(OmapCardInfo));
if (!omapc)
return FALSE;
if (!omapSetupPlane(omapc, "/dev/fb0", OMAP_PLANE_BASE))
FatalError("omapCardInit: couldn't open dispc gfx plane/n");
for (i = 1; i < 100; i++) {
snprintf(fbpath, sizeof(fbpath), "/dev/fb%d", i);
if (omapSetupPlane(omapc, fbpath, OMAP_PLANE_OVERLAY))
DebugF("omapCardInit: added plane %d/n", i);
else
break;
}
card->driver = omapc;
LEAVE();
return TRUE;
}
Firstly, OmapCardInfo struct is generated and passed to function omapSetupPlane., by passing "/dev/fb0" as the file path, and OMAP_PLANE_BASE as the frame buffer type to indicate that it is the first frame buffer. In function omapSetupPlane, an OmapPlaneInfo struct is generated, which is added into the list of member planes of OmapCardInfo in the end of this function, and frame buffer is opened and set to member fd of just created OmapPlaneInfo. This function also set related parameters of OmapPlaneInfo by using ioctl on the opened frame buffer.
typedef struct _omapCardInfo OmapCardInfo;
struct _omapCardInfo {
OmapPlaneInfo *planes;
/* The mode which was set at startup. */
int orig_width, orig_height, orig_bpp;
};
typedef struct _omapPlaneInfo OmapPlaneInfo;
struct _omapPlaneInfo {
/* Unique identifier. */
int id;
OmapPlaneType type;
/* Intrinsic properties of the plane. */
char *filename;
int fd;
CARD8 *fb;
int fb_size;
int pitch, bpp;
int max_width, max_height;
unsigned long colors;
/* Whether or not the plane is enabled. If a plane is not active and
* not dirty, it can be restarted without being reconfigured. */
OmapPlaneState state;
/* Do we need to set the plane up again? */
int dirty;
/* Changeable; changing any of these requires setting the
* dirty flag. */
xRectangle src_area;
xRectangle dst_area;
enum omapfb_color_format format;
/* OMAP_EXT_* flags. */
int ext_state;
/* Plane capabilities, from omapfb.h. */
unsigned long caps;
/* Colour key, in RGB565. */
int colorkey;
enum {
OMAP_VSYNC_NONE,
OMAP_VSYNC_TEAR,
OMAP_VSYNC_FORCE,
} vsync;
/* Number of frames we've drawn, for profiling. */
int frames;
int frames_since;
/* Pointer back to our base screen. */
struct _omapScreenInfo *omaps;
struct _omapPlaneInfo *next;
};
Now we come back to function omapCardInit. After generating the first OmapPlaneInfo, it tries to generate other 100 OmapPlaneInfo structures, from "/dev/fb1" to "/dev/fb100", by checking these devices’ existence, and their type will be set to OMAP_PLANE_OVERLAY if they exist. Finally, the generated OmapCardInfo is set to member driver of KdCardInfo, which is used to store private data for Card Driver.
And then we come back to function KdInitOutput. Now OMAP card is initialized, and then for each KdScreenInfo structure, function calls KdInitScreen to initialize each of them, which just call scrinit of function list passed to KdCardInfo, and should be omapScreenInit in our case. Notice that member dumb of KdScreenInfo means whether this screen has accelerator feature.
Function omapScreenInit created a structure OmapScreenInfo, and link it to OmapPlaneInfo and KdScreenInfo through their member OmapPlaneInfo.omaps and KdScreenInfo.driver (this member is used to store private data of KdScreenInfo for its driver). OmapScreenInfo also point to OmapCardInfo, OmapPlaneInfo (only the one with type OMAP_PLANE_BASE) and KdScreenInfo through its member omapc, plane and screen. Besides setting related parameters for OmapPlaneInfo and KdScreenInfo, an important point is that this function calls omapPlaneEnable to put the main OmapPlaneInfo into use, which means that mmap of this OmapPlaneInfo is done.
typedef struct _omapScreenInfo OmapScreenInfo;
struct _omapScreenInfo {
OmapCardInfo *omapc;
KdScreenInfo *screen;
/* Number of updates kicked from the timer. */
int updates;
/* Timer gets disabled after 500ms of inactivity. */
int empty_updates, timer_active;
/* Should we avoid aggregating updates? */
int individual_updates;
/* Pointer to our base plane. */
OmapPlaneInfo *plane;
/* The current damaged area. */
BoxRec dirty_area;
/* Have we enabled pixel doubling? */
int pixel_doubled;
/* Do we need to block UI updates? */
int block_updates;
/* Are we using a shadow framebuffer? */
int shadowfb;
/* Use for tracking damage for window updates. */
PixmapPtr pixmap;
DamagePtr damage;
RegionPtr tmp_region;
RegionPtr video_region;
int num_video_ports;
#ifdef XV
KdVideoAdaptorPtr xv_adaptors;
#else
void *xv_adaptors;
#endif
};
Now again we come back to function KdInitOutput. For each KdScreenInfo linked in each KdCardInfo (as we mentioned above, there is only one KdCardInfo and one KdScreenInfo in our case, which are initialized by function InitCard and KdScreenInfoAdd above), function KdAddScreen is invoked to add a KdScreenInfo into system.
Skipping parameters setting part, we go into the last part called by function KdAddScreen, which is AddScreen (in dix/main.c), a DIX function. Please notice that before calling this function, current KdScreenInfo structure is set to kdCurrentScreen (kdCurrentScreen = screen;), which is then used by the call back function KdScreenInit that passed as a parameter to AddScreen function call in the following codes.
Function AddScreen first generate a ScreenRec structure, and link it into ScreenInfo’s member screens[i], which is a very big structure and used very commonly in future. Like many other functions, AddScreen set a lot of related parameters of this structure, and we skip those parts and just go to the last part of it, where pfnInit call back is called, which is KdScreenInit in our case.
typedef struct _Screen *ScreenPtr;
typedef struct _Screen {
int myNum; /* index of this instance in Screens[] */
ATOM id;
short width, height;
short mmWidth, mmHeight;
short numDepths;
unsigned char rootDepth;
DepthPtr allowedDepths;
unsigned long rootVisual;
unsigned long defColormap;
short minInstalledCmaps, maxInstalledCmaps;
char backingStoreSupport, saveUnderSupport;
unsigned long whitePixel, blackPixel;
unsigned long rgf; /* array of flags; she's -- HUNGARIAN */
GCPtr GCperDepth[MAXFORMATS+1];
/* next field is a stipple to use as default in
a GC. we don't build default tiles of all depths
because they are likely to be of a color
different from the default fg pixel, so
we don't win anything by building
a standard one.
*/
PixmapPtr PixmapPerDepth[1];
pointer devPrivate;
short numVisuals;
VisualPtr visuals;
int WindowPrivateLen;
unsigned *WindowPrivateSizes;
unsigned totalWindowSize;
int GCPrivateLen;
unsigned *GCPrivateSizes;
unsigned totalGCSize;
/* Random screen procedures */
CloseScreenProcPtr CloseScreen;
QueryBestSizeProcPtr QueryBestSize;
SaveScreenProcPtr SaveScreen;
GetImageProcPtr GetImage;
GetSpansProcPtr GetSpans;
PointerNonInterestBoxProcPtr PointerNonInterestBox;
SourceValidateProcPtr SourceValidate;
/* Window Procedures */
CreateWindowProcPtr CreateWindow;
DestroyWindowProcPtr DestroyWindow;
PositionWindowProcPtr PositionWindow;
ChangeWindowAttributesProcPtr ChangeWindowAttributes;
RealizeWindowProcPtr RealizeWindow;
UnrealizeWindowProcPtr UnrealizeWindow;
ValidateTreeProcPtr ValidateTree;
PostValidateTreeProcPtr PostValidateTree;
WindowExposuresProcPtr WindowExposures;
PaintWindowBackgroundProcPtr PaintWindowBackground;
PaintWindowBorderProcPtr PaintWindowBorder;
CopyWindowProcPtr CopyWindow;
ClearToBackgroundProcPtr ClearToBackground;
ClipNotifyProcPtr ClipNotify;
RestackWindowProcPtr RestackWindow;
/* Pixmap procedures */
CreatePixmapProcPtr CreatePixmap;
DestroyPixmapProcPtr DestroyPixmap;
/* Backing store procedures */
SaveDoomedAreasProcPtr SaveDoomedAreas;
RestoreAreasProcPtr RestoreAreas;
ExposeCopyProcPtr ExposeCopy;
TranslateBackingStoreProcPtr TranslateBackingStore;
ClearBackingStoreProcPtr ClearBackingStore;
DrawGuaranteeProcPtr DrawGuarantee;
/*
* A read/write copy of the lower level backing store vector is needed now
* that the functions can be wrapped.
*/
BSFuncRec BackingStoreFuncs;
/* Font procedures */
RealizeFontProcPtr RealizeFont;
UnrealizeFontProcPtr UnrealizeFont;
/* Cursor Procedures */
ConstrainCursorProcPtr ConstrainCursor;
CursorLimitsProcPtr CursorLimits;
DisplayCursorProcPtr DisplayCursor;
RealizeCursorProcPtr RealizeCursor;
UnrealizeCursorProcPtr UnrealizeCursor;
RecolorCursorProcPtr RecolorCursor;
SetCursorPositionProcPtr SetCursorPosition;
/* GC procedures */
CreateGCProcPtr CreateGC;
/* Colormap procedures */
CreateColormapProcPtr CreateColormap;
DestroyColormapProcPtr DestroyColormap;
InstallColormapProcPtr InstallColormap;
UninstallColormapProcPtr UninstallColormap;
ListInstalledColormapsProcPtr ListInstalledColormaps;
StoreColorsProcPtr StoreColors;
ResolveColorProcPtr ResolveColor;
/* Region procedures */
BitmapToRegionProcPtr BitmapToRegion;
SendGraphicsExposeProcPtr SendGraphicsExpose;
/* os layer procedures */
ScreenBlockHandlerProcPtr BlockHandler;
ScreenWakeupHandlerProcPtr WakeupHandler;
pointer blockData;
pointer wakeupData;
/* anybody can get a piece of this array */
DevUnion *devPrivates;
CreateScreenResourcesProcPtr CreateScreenResources;
ModifyPixmapHeaderProcPtr ModifyPixmapHeader;
GetWindowPixmapProcPtr GetWindowPixmap;
SetWindowPixmapProcPtr SetWindowPixmap;
GetScreenPixmapProcPtr GetScreenPixmap;
SetScreenPixmapProcPtr SetScreenPixmap;
PixmapPtr pScratchPixmap; /* scratch pixmap "pool" */
#ifdef PIXPRIV
int PixmapPrivateLen;
unsigned int *PixmapPrivateSizes;
unsigned int totalPixmapSize;
#endif
MarkWindowProcPtr MarkWindow;
MarkOverlappedWindowsProcPtr MarkOverlappedWindows;
ChangeSaveUnderProcPtr ChangeSaveUnder;
PostChangeSaveUnderProcPtr PostChangeSaveUnder;
MoveWindowProcPtr MoveWindow;
ResizeWindowProcPtr ResizeWindow;
GetLayerWindowProcPtr GetLayerWindow;
HandleExposuresProcPtr HandleExposures;
ReparentWindowProcPtr ReparentWindow;
#ifdef SHAPE
SetShapeProcPtr SetShape;
#endif /* SHAPE */
ChangeBorderWidthProcPtr ChangeBorderWidth;
MarkUnrealizedWindowProcPtr MarkUnrealizedWindow;
} ScreenRec;
Function KdScreenInit is a relatively long function. From now to the end, we will all focus on it then. It first uses KdAllocatePrivates and KdGetScreenPriv Macro to generate member devPrivates to store private data for ScreenRec, though I do not like the style to use Macro to define variables, which is not good for an understandable codes.
typedef struct {
KdScreenInfo *screen;
KdCardInfo *card;
Bool enabled;
Bool closed;
int bytesPerPixel[KD_MAX_FB];
int dpmsState;
KdOffscreenArea *off_screen_areas;
ColormapPtr pInstalledmap[KD_MAX_FB]; /* current colormap */
xColorItem systemPalette[KD_MAX_PSEUDO_SIZE];/* saved windows colors */
CreateScreenResourcesProcPtr CreateScreenResources;
CloseScreenProcPtr CloseScreen;
#ifdef FB_OLD_SCREEN
miBSFuncRec BackingStoreFuncs;
#endif
} KdPrivScreenRec, *KdPrivScreenPtr;
Functions fbSetupScreen, fbOverlayFinishScreenInit, fbFinishScreenInit, fbPictureInit are all used to set up parameters of the created ScreenRec structure (You may also guess it based on the fact that all these functions are DIX part and all in fb directory, and therefore should not be related to porting layer).
KdCardInfo.cfuncs->initScreen is then called for specific initialization of the newly generated structure ScreenRec, which should be omapInitScreen in kdrive/omap/omap.c in our case. omapScreenInfo just fetched out OmapScreenInfo from the long long link list, which can be briefly stated as: ScreenRec.devPrivates[kdScreenPrivateIndex].screen.driver, and it is also the reason that I do not like use Macro to define variable. Then omapVideoInit is invoked (There are two definitions of this function, and I prefer the long one here since I guess Macro XV should be defined).
Function omapVideoInit firstly calls KdXVListGenericAdaptors to generate some KdVideoAdaptorPtr. However, in our case this function should do nothing. If we go into details of this function, we can see that NumGenDrivers and GenDrivers are used to generate those adaptors. Yet NumGenDrivers is set to zero, and increased while GenDrivers is added in through KdXVRegisterGenericAdaptorDriver function (GenDrivers is really a link list to store all functions, and a new call back is added in every time that KdXVRegisterGenericAdaptorDriver is called by passing a KdXVInitGenericAdaptorPtr as a new driver function call back). However, I searched all codes and found that KdXVRegisterGenericAdaptorDriver is never called, and therefore NumGenDrivers should be zero in our case. Therefore, function omapVideoOverlaySetup is the real one that generates KdVideoAdaptorRec structure. This function first searches all OmapPlaneInfo structure list, and find those support YUV signals and regard them as video layer. And then, all these video OmapPlaneInfo are registered in port_info[i] of member adapt->pPortPrivates (In fact, port_info[i] is just pPortPrivates[i]). Please notice that member pPortPrivates of KdVideoAdaptorRec is of type DevUnion, and therefore when creating this structure, omaps->num_video_ports * (sizeof(OmapPortPriv) + sizeof(DevUnion)) is used to create N OmapPortPriv structures after the main body of structure KdVideoAdaptorRec, and let its pPortPrivates point to it to reference this part.
typedef struct {
unsigned int type;
int flags;
char *name;
int nEncodings;
KdVideoEncodingPtr pEncodings;
int nFormats;
KdVideoFormatPtr pFormats;
int nPorts;
DevUnion *pPortPrivates;
int nAttributes;
KdAttributePtr pAttributes;
int nImages;
KdImagePtr pImages;
PutVideoFuncPtr PutVideo;
PutStillFuncPtr PutStill;
GetVideoFuncPtr GetVideo;
GetStillFuncPtr GetStill;
StopVideoFuncPtr StopVideo;
SetPortAttributeFuncPtr SetPortAttribute;
GetPortAttributeFuncPtr GetPortAttribute;
QueryBestSizeFuncPtr QueryBestSize;
PutImageFuncPtr PutImage;
ReputImageFuncPtr ReputImage;
QueryImageAttributesFuncPtr QueryImageAttributes;
ClipNotifyFuncPtr ClipNotify;
} KdVideoAdaptorRec, *KdVideoAdaptorPtr;
Finally, function omapVideoOverlaySetup set corresponding OMAP Video functions to those call backs of KdVideoAdaptorRec as following:
adapt->PutImage = omapPutImage;
adapt->ReputImage = omapReputImage;
adapt->StopVideo = omapVideoStop;
adapt->GetPortAttribute = omapGetPortAttribute;
adapt->SetPortAttribute = omapSetPortAttribute;
adapt->QueryBestSize = omapQueryBestSize;
adapt->QueryImageAttributes = omapQueryImageAttributes;
adapt->ClipNotify = omapClipNotify;
Now we come back to function omapVideoInit. It then calls KdXVScreenInit to initialize all just added KdVideoAdaptorRec structures, and there is only one added by omapVideoOverlaySetup function in our case. Function KdXVScreenInit changes the call back function of a standard FB call back function to corresponding XV call back functions, and set the original FB call back function to pScreen->devPrivates[KdXvScreenIndex], such as:
ScreenPriv->CreateWindow = pScreen->CreateWindow;
……
pScreen->CreateWindow = KdXVCreateWindow;
Then function KdXVScreenInit calls KdXVInitAdaptors. This function is also relatively long. The main target of this function is to generate and set related parameters of an XvAdaptorRec structure, which is pointed by pa in this function and is a structure of DIX layer. This structure point to structure ScreenRec through member pScreen, and is pointed by structure ScreenRec through its member devPrivates[KdXvScreenIndex].pAdaptors.
typedef struct {
unsigned long base_id;
unsigned char type;
char *name;
int nEncodings;
XvEncodingPtr pEncodings;
int nFormats;
XvFormatPtr pFormats;
int nAttributes;
XvAttributePtr pAttributes;
int nImages;
XvImagePtr pImages;
int nPorts;
struct _XvPortRec *pPorts;
ScreenPtr pScreen;
int (* ddAllocatePort)(unsigned long, struct _XvPortRec*,
struct _XvPortRec**);
int (* ddFreePort)(struct _XvPortRec*);
int (* ddPutVideo)(ClientPtr, DrawablePtr,struct _XvPortRec*, GCPtr,
INT16, INT16, CARD16, CARD16,
INT16, INT16, CARD16, CARD16);
int (* ddPutStill)(ClientPtr, DrawablePtr,struct _XvPortRec*, GCPtr,
INT16, INT16, CARD16, CARD16,
INT16, INT16, CARD16, CARD16);
int (* ddGetVideo)(ClientPtr, DrawablePtr,struct _XvPortRec*, GCPtr,
INT16, INT16, CARD16, CARD16,
INT16, INT16, CARD16, CARD16);
int (* ddGetStill)(ClientPtr, DrawablePtr,struct _XvPortRec*, GCPtr,
INT16, INT16, CARD16, CARD16,
INT16, INT16, CARD16, CARD16);
int (* ddStopVideo)(ClientPtr, struct _XvPortRec*, DrawablePtr);
int (* ddSetPortAttribute)(ClientPtr, struct _XvPortRec*, Atom, INT32);
int (* ddGetPortAttribute)(ClientPtr, struct _XvPortRec*, Atom, INT32*);
int (* ddQueryBestSize)(ClientPtr, struct _XvPortRec*, CARD8,
CARD16, CARD16,CARD16, CARD16,
unsigned int*, unsigned int*);
int (* ddPutImage)(ClientPtr, DrawablePtr, struct _XvPortRec*, GCPtr,
INT16, INT16, CARD16, CARD16,
INT16, INT16, CARD16, CARD16,
XvImagePtr, unsigned char*, Bool,
CARD16, CARD16);
int (* ddQueryImageAttributes)(ClientPtr, struct _XvPortRec*, XvImagePtr,
CARD16*, CARD16*, int*, int*);
DevUnion devPriv;
} XvAdaptorRec, *XvAdaptorPtr;
typedef struct {
int id;
ScreenPtr pScreen;
char *name;
unsigned short width, height;
XvRationalRec rate;
} XvEncodingRec, *XvEncodingPtr;
typedef struct _XvAttributeRec {
int flags;
int min_value;
int max_value;
char *name;
} XvAttributeRec, *XvAttributePtr;
typedef struct {
int id;
int type;
int byte_order;
char guid[16];
int bits_per_pixel;
int format;
int num_planes;
/* for RGB formats only */
int depth;
unsigned int red_mask;
unsigned int green_mask;
unsigned int blue_mask;
/* for YUV formats only */
unsigned int y_sample_bits;
unsigned int u_sample_bits;
unsigned int v_sample_bits;
unsigned int horz_y_period;
unsigned int horz_u_period;
unsigned int horz_v_period;
unsigned int vert_y_period;
unsigned int vert_u_period;
unsigned int vert_v_period;
char component_order[32];
int scanline_order;
} XvImageRec, *XvImagePtr;
typedef struct _XvPortRec {
unsigned long id;
XvAdaptorPtr pAdaptor;
XvPortNotifyPtr pNotify;
DrawablePtr pDraw;
ClientPtr client;
XvGrabRec grab;
TimeStamp time;
DevUnion devPriv;
} XvPortRec, *XvPortPtr;
typedef struct {
int flags;
PutVideoFuncPtr PutVideo;
PutStillFuncPtr PutStill;
GetVideoFuncPtr GetVideo;
GetStillFuncPtr GetStill;
StopVideoFuncPtr StopVideo;
SetPortAttributeFuncPtr SetPortAttribute;
GetPortAttributeFuncPtr GetPortAttribute;
QueryBestSizeFuncPtr QueryBestSize;
PutImageFuncPtr PutImage;
ReputImageFuncPtr ReputImage;
QueryImageAttributesFuncPtr QueryImageAttributes;
ClipNotifyFuncPtr ClipNotify;
} XvAdaptorRecPrivate, *XvAdaptorRecPrivatePtr;
typedef struct {
char depth;
short class;
} KdVideoFormatRec, *KdVideoFormatPtr;
Function omapVideoInit finally delete newAdaptors, not newAdaptor that generated by omapVideoOverlaySetup, which has confused me for a while.
Now the long omapVideoInit procedure is finished, and we come back to function KdScreenInit, then KdCardInfo.cfuncs->initAccel is called, which is NULL in our case. And then, KdCardInfo.cfuncs->finishInitScreen is called, it calls the shadowSetup if OmapScreenInfo supports shadowfb, and I have not gone details on this part. Similar, KdCardInfo .cfuncs->initCursor is also NULL in our case. Functions miDCInitialize, fbCreateDefColormap are in DIX layer and therefore skipped here. Function KdSetSubpixelOrder seemed to be targeted to finish rotation function, and is not reviewed yet.
At last, since screen->mynum == card->selected valid (I have take some time to verify why these two number are equal, and found that card->selected is set in function KdEnableScreen in kdrive/src, however, no tips can help me find where this function is invoked. Finally, it turns out that the fact is very simple. pScreen->myNum = screenInfo.numScreens is called in function AddScreen in dix/main.c, and card->selected = 0 is called in function KdCardInfoAdd in kdrive/src, and all of them are initialized to 0 then). And therefore, KdCardInfo.cfuncs->preserve, KdCardInfo.cfuncs->enable, KdCardInfo.cfuncs->enableCursor and KdCardInfo.cfuncs->enableAccel are called, yet all of them are set to NULL in our case.
Till now, function KdScreenInit is finished, and the long long story of output start up code is also finished.
In this document we only analyzed the whole architecture of DDX output layer, focusing on the data structure and whole picture of this sub-system. However, many detailed works have not been touched. It seemed that Maemo has utilized Video frame buffer, yet we still do not understand the concrete meaning of this XV extension, neither do we know how to use it. I believe Marvell would have the same feature.
I even have not found where these video frame buffers are opened.
To put all words into one, more details about X Window Display system should be studied, and we should then come back to see how they are implemented and how we can build our own system.
[1]. Architecture Analysis of Maemo Huang Gao/Wang Huageng