当前位置: 代码迷 >> 综合 >> X Server移植指导之三 输出层移植 (XServer Porting Guide)
  详细解决方案

X Server移植指导之三 输出层移植 (XServer Porting Guide)

热度:65   发布时间:2023-12-22 09:26:15.0

http://blog.csdn.net/huang_gao/article/details/5065950

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 KdParseScreen is then invoked to get related parameters of KdCardInfo member, such as widthwidth_mmheightheight_mmrandrfb 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 omapCardInitAfter 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 OmapCardInfoOmapPlaneInfo (only the one with type OMAP_PLANE_BASE) and KdScreenInfo through its member omapcplane 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 ScreenInfos 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 fbSetupScreenfbOverlayFinishScreenInitfbFinishScreenInitfbPictureInit 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 miDCInitializefbCreateDefColormap 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->preserveKdCardInfo.cfuncs->enableKdCardInfo.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.

1.3           Future works of Maemo DDX Output Layer

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.

2.                References

[1]. Architecture Analysis of Maemo                            Huang Gao/Wang Huageng

  相关解决方案