转至元数据结尾
转至元数据起始

composite extension由两部分实现,一部分为X11 server,另一部分为compositor。两者之间通过扩展请求实现。

Compositor调用libXcomposite库实现composite扩展协议通信,X11 Server源码中集成了composite扩展功能,实现在源码树的composite目录下。

X11 Server端的实现

请求扩展

compositor向X11 server发送请求,X11 server影响请求,并做响应处理。

compositor request

X11 server process function

description

XCompositeQueryVersion

ProcCompositeQueryVersion

获取Composite扩展版本,当前版本为0.4

XCompositeRedirectWindow

ProcCompositeRedirectWindow

创建指定窗口的CompWindow,一般为CompositeRedirectManual类型

XCompositeRedirectSubwindows

ProcCompositeRedirectSubwindows

为指定窗口的直接子窗口创建CompWindow,一般为CompositeRedirectManual类型

XCompositeUnredirectWindow

ProcCompositeUnredirectWindow

销毁指定窗口的CompWindow

XCompositeUnredirectSubwindows

ProcCompositeUnredirectSubwindows

销毁指定窗口的子窗口的CompWindow

XCompositeCreateRegionFromBorderClip

ProcCompositeCreateRegionFromBorderClip

从包含窗口边框的区域创建CompWindow区间

XCompositeNameWindowPixmap

ProcCompositeNameWindowPixmap

获取指定窗口的pixmap

XCompositeGetOverlayWindow

ProcCompositeGetOverlayWindow

创建CompOverlayClient,若不存在overlay window,则创建一个,属性为(CWBackPixmap | CWOverrideRedirect)

XCompositeReleaseOverlayWindow

ProcCompositeReleaseOverlayWindow

销毁CompOverlayClient

从mutter的实现看,MetaCompositorServer只调用了XCompositeRedirectSubwindows一个扩展接口。而MetaCompositorX11调用了较多接口。

回调函数

X11 Server调用CompositeExtensionInit注册扩展协议的请求和回调函数。Composite扩展不支持8位仿真色彩。compScreenInit注册回调函数

当窗口的visual,depth等属性与父窗口一致时,创建窗口时,该窗口共享与父窗口的pixmap,即窗口画图内容显示在父窗口的pixmap中。

自动生成CompWindow的条件:

  1. visual与父窗口不同:创建一个类型为RedirectDrawAutomatic的CompWindow,窗口在MapWindow操作中分配新的pixmap

  2. 修改窗口属性,backingStore设置为WhenMapped或Always,窗口CompWindow;设置为NotUseful,销毁CompWindow。client可以在CreateWindow时指定窗口属性,或者同ChangeWindowAttributes请求修改窗口属性

另外一种场景时,compositor client调用XCompositeRedirectWindow或XCompositeRedirectSubwindows创建CompWindow。

callback

realize

description

CreateWindow

compCreateWindow

当窗口的visual与父窗口不同时,创建窗口的CompWindow

DestroyWindow

compDestroyWindow

销毁CompWindow

RealizeWindow

compRealizeWindow

为具有CompWindow的窗口创建一个独立的pixmap

UnrealizeWindow

compUnrealizeWindow

释放pixmap副本

PositionWindow

compPositionWindow

重新计算pixmap的位置

CopyWindow

compCopyWindow

从CompWindow中的pixmap从拷贝数据至窗口中的pixmap

MoveWindow

compMoveWindow

销毁CompWindow中的pixmap,why???

ResizeWindow

compResizeWindow

销毁CompWindow中的pixmap,先旧的pixmap销毁,再在ConfigNotify缓冲窗口的pixmap

ReparentWindow

compReparentWindow

销毁与原父窗口的CompWindow,以及CompSubwindows,创建与新父窗口的CompWindow,以及CompSubwindows

ConfigNotify

compConfigNotify

窗口大小有变化时,将窗口的pixmap交给CompWindow缓冲,然后重新分配pixmap

ClipNotify

compClipNotify

转换CompWindow Clip区域坐标

ChangeWindowAttributes

compChangeWindowAttributes

修改CWBackingStore掩码窗口属性时,创建或销毁CompWindow

ChangeBorderWidth

compChangeBorderWidth

销毁CompWindow缓冲的pixmap

InstallColormap

compInstallColormap

检查色彩映射表是否存在,若存在,则不再安装

SourceValidate

compSourceValidate

合成子窗口内容,将子窗口的pixmap合入窗口的pixmap

CloseScreen

compCloseScreen

关闭屏幕

Picture Screen Callback

callback

machine independence

framebuffer

glamor

damage

RealizeGlyph

miRealizeGlyph

UnrealizeGlyph

miUnrealizeGlyph

fbUnrealizeGlyph

Composite

fbComposite

glamor_composite

damageComposite

Glyphs

miGlyphs

fbGlyphs

glamor_composite_glyphs

damageGlyphs

CompositeRects

miCompositeRects

miCompositeRects

glamor_composite_rectangles

Trapezoids

fbTrapezoids

glamor_trapezoids

Triangles

fbTriangles

glamor_triangles

RasterizeTrapezoid

fbRasterizeTrapezoid

AddTraps

fbAddTraps

glamor_add_traps

damageAddTraps

AddTriangles

fbAddTriangles

TriStrip

miTriStrip

TriFan

miTriFan

CreatePicture

miCreatePicture

DestroyPicture

miDestroyPicture

ChangePictureClip

miChangePictureClip

DestroyPictureClip

miDestroyPictureClip

ChangePicture

miChangePicture

ValidatePicture

miValidatePicture

InitIndexed

miInitIndexed

CloseIndexed

miCloseIndexed

UpdateIndexed

miUpdateIndexed

ChangePictureTransform

miChangePictureTransform

ChangePictureFilter

miChangePictureFilter

mutter compositor实现

compositor根据窗口层级创建和销毁CompWindow,其创建的CompWindow类型为CompositeRedirectManual,具体合成功能在X11 server中完成。

  • compositor在初始化后,创建一个composite window,属性为CWOverrideRedirect,对X11的根窗口发送XCompositeRedirectSubwindows,对根窗口的所有直接子窗口创建CompWindow。

  • 在mutter中,一个MetaSurfaceActorX11对应的window会调用XCompositeRedirectWindow创建一个CompWindow。由调用ClutterActor::constructed回调函数meta_window_actor_constructed实现,meta_window_actor_constructed ->init_surface_actor ->meta_surface_actor_x11_new,这个过程只有使用MetaCompositorX11时才会调用,而非根模式下使用MetaCompositorServer和MetaWaylandCompositor,不会调用该过程,

  • MetaSurfaceActorX11更新pixmap时,调用XCompositeNameWindowPixmap获取指定Window的pixmap,最终创建CoglTexturePixmapX11与pixmap关联,在非根模式下,使用的时MetaWindowActorWayland。

Wayland compositor使用XCompositeRedirectSubwindows对根窗口的子窗口创建CompWindow,具体作用说明如下:

  • 为根窗口创建一个CompClientWindow(ccw)和CompSubwindows(csw),update均设置为CompositeRedirectManual,csw管理ccw链表。ccw的client为wayland compositor

  • 调用compRedirectWindow为每个顶级窗口创建一个CompWindow(cw)以及CompClientWindow(ccw),其update均为CompositeRedirectManual,cw管理ccw链表,将窗口的redirectDraw设置为RedirectDrawManual。

  • CreateWindow时,调用compCreateWindow对每个顶层窗口(根窗口的子窗口)创建一个CompWindow(cw)以及CompClientWindow(ccw)

  • ReparentWindow时,调用compReparentWindow,销毁原顶层窗口的CompWindow(cw)以及CompClientWindow(ccw)

从上面的实现看,Wayland compositor对窗口管理器的页框和override direct窗口创建了CompWindow,其它窗口未管理。在X11 server处理窗口堆叠处理时,从miValidateTree实现看到,redirectDraw为RedirectDrawManual的窗口作为透明窗口处理,不覆盖显示区域。该函数计算父窗口的子窗口的可剪接区域以及各窗口的exposed和borderExposed区域。

// mutter检测xwayland已经启动后,对x11 display进行初始化,做为X11 server的client,初始化相关扩展
// 扩展包括:xsync, xshape, xcomposite, xdamage, xfixes, xi
gboolean meta_display_init_x11_finish (MetaDisplay *display, GAsyncResult  *result, GError **error){
  MetaX11Display *x11_display = meta_x11_display_new (display, error);
  if (!x11_display)
    return FALSE;
 
  display->x11_display = x11_display;
  g_signal_emit (display, display_signals[X11_DISPLAY_SETUP], 0);
  meta_x11_display_create_guard_window (x11_display);
 
  if (!display->display_opening){
    g_signal_emit (display, display_signals[X11_DISPLAY_OPENED], 0);
    // 创建composite window,属性为CWOverrideRedirect,保存在x11_display->wm_cm_selection_window
    meta_x11_display_set_cm_selection (x11_display);
    // 对已有的顶层窗口,增加页框窗口。(窗口管理器功能)
    meta_display_manage_all_xwindows (display);
    // 对根窗口发送XCompositeRedirectSubwindows,为其子窗口创建CompWindow
    meta_compositor_redirect_x11_windows (display->compositor);
  }
  return TRUE;
}

damage

在compRedirectWindow函数中调用DamageCreate为CompWindow创建Damage。在CompositeRedirectManual下,未主动调用DamageRegister注册damage。

// DamageReportNonEmpty,可显示区域变化时,当区域不为空时,调用compReportDamage
// cw->damage = DamageCreate(compReportDamage,compDestroyDamage,DamageReportNonEmpty,FALSE, pWin->drawable.pScreen, pWin);
 
static void compReportDamage(DamagePtr pDamage, RegionPtr pRegion, void *closure){
    WindowPtr pWin = (WindowPtr) closure;
    ScreenPtr pScreen = pWin->drawable.pScreen;
    CompScreenPtr cs = GetCompScreen(pScreen);
    CompWindowPtr cw = GetCompWindow(pWin);
    if (!cs->pendingScreenUpdate) {
        // 插入工作队列,在主线程下次迭代时处理
        QueueWorkProc(compScreenUpdate, serverClient, pScreen);
        cs->pendingScreenUpdate = TRUE;
    }
    cw->damaged = TRUE;
    // 标记祖父窗口,子孙窗口已被修改,即pWin->damagedDescendants = TRUE;
    compMarkAncestors(pWin);
}
 
static Bool compScreenUpdate(ClientPtr pClient, void *closure){
    ScreenPtr pScreen = closure;
    CompScreenPtr cs = GetCompScreen(pScreen);
    // 递归调用深度优先递归调用,若窗口有变化,调用compWindowUpdateAutomatic更新窗口
    compPaintChildrenToWindow(pScreen->root);
    cs->pendingScreenUpdate = FALSE; // Next damage will restore the worker
    return TRUE;
}
 
// Damage的回调函数
const DamageScreenFuncsRec miFuncs = {
    miDamageCreate,
    miDamageRegister,
    miDamageUnregister,
    miDamageDestroy
};
 
void miDamageCreate(DamagePtr pDamage) {}
 
void miDamageRegister(DrawablePtr pDrawable, DamagePtr pDamage){
    if (pDrawable->type == DRAWABLE_WINDOW)
        // 深度优先遍历窗口,更新窗口的序列号:pWin->drawable.serialNumber = NEXT_SERIAL_NUMBER;
        TraverseTree((WindowPtr)pDrawable, damageRegisterVisit, NULL);
    else
        pDrawable->serialNumber = NEXT_SERIAL_NUMBER;
}
 
void miDamageUnregister(DrawablePtr pDrawable, DamagePtr pDamage) {
    if (pDrawable->type == DRAWABLE_WINDOW)
        TraverseTree((WindowPtr)pDrawable, damageRegisterVisit, NULL);
    else
        pDrawable->serialNumber = NEXT_SERIAL_NUMBER;
}
 
void miDamageDestroy(DamagePtr pDamage) {}

Graphic Context ops

glamor在glamor_init函数中替换了framebuffer的GCOps回调函数,damage在DamageSetup函数中包装了glamor的回调函数。

name

framebuffer

glamor

damage

FillSpans

fbFillSpans

glamor_fill_spans

damageFillSpans

SetSpans

fbSetSpans

glamor_set_spans

damageSetSpans

PutImage

fbPutImage

glamor_put_image

damagePutImage

CopyArea

fbCopyArea

glamor_copy_area

damageCopyArea

CopyPlane

fbCopyPlane

glamor_copy_plane

damageCopyPlane

PolyPoint

fbPolyPoint

glamor_poly_point

damagePolyPoint

Polylines

fbPolyLine

glamor_poly_lines

damagePolylines

PolySegment

fbPolySegment

glamor_poly_segment

damagePolySegment

PolyRectangle

fbPolyRectangle

miPolyRectangle

damagePolyRectangle

PolyArc

fbPolyArc

miPolyArc

damagePolyArc

FillPolygon

miFillPolygon

miFillPolygon

damageFillPolygon

PolyFillRect

fbPolyFillRect

glamor_poly_fill_rect

damagePolyFillRect

PolyFillArc

fbPolyFillArc

miPolyFillArc

damagePolyFillArc

PolyText8

miPolyText8

glamor_poly_text8

damagePolyText8

PolyText16

miPolyText16

glamor_poly_text16

damagePolyText16

ImageText8

miImageText8

glamor_image_text8

damageImageText8

ImageText16

miImageText16

glamor_image_text16

damageImageText16

ImageGlyphBlt

fbImageGlyphBlt

miImageGlyphBlt

damageImageGlyphBlt

PolyGlyphBlt

fbPolyGlyphBlt

glamor_poly_glyph_blt

damagePolyGlyphBlt

PushPixels

fbPushPixels

glamor_push_pixels

damagePushPixels

Graphic Context Functions

glamor替换了framebuffer的GCFuncs,damage包装了glamor的GCFuncs回调函数

name

framebuffer

glamor

damage

ValidateGC

fbValidateGC

glamor_validate_gc

damageValidateGC

ChangeGC

miChangeGC

miChangeGC

damageChangeGC

CopyGC

miCopyGC

miCopyGC

damageCopyGC

DestroyGC

miDestroyGC

glamor_destroy_gc

damageDestroyGC

ChangeClip

miChangeClip

miChangeClip

damageChangeClip

DestroyClip

miDestroyClip

miDestroyClip

damageDestroyClip

CopyClip

miCopyClip

miCopyClip

damageCopyClip

Damage extension

在DamageExtensionInit函数中注册Damage的扩展请求和事件。由client创建和销毁Damage,Damage发生变化时,发送DamageNotify事件通知。

/* Requests */
#define X_DamageQueryVersion        0
#define X_DamageCreate          1
#define X_DamageDestroy         2
#define X_DamageSubtract        3
#define X_DamageAdd         4
 
/* Events */
#define XDamageNotify           0
#define XDamageNumberEvents     (XDamageNotify + 1)
 
/* Constants */
#define XDamageReportRawRectangles  0      // 原始区域
#define XDamageReportDeltaRectangles    1  // 变化区域
#define XDamageReportBoundingBox    2      // 边框区域
#define XDamageReportNonEmpty       3      // 非空时处理,无需区域信息
 
static int (*ProcDamageVector[XDamageNumberRequests]) (ClientPtr) = {
    ProcDamageQueryVersion,
    ProcDamageCreate,
    ProcDamageDestroy,
    ProcDamageSubtract,
    ProcDamageAdd,
};