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的条件:
visual与父窗口不同:创建一个类型为RedirectDrawAutomatic的CompWindow,窗口在MapWindow操作中分配新的pixmap
修改窗口属性,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, }; |
0 评论