Xephyr: properly clip GL drawables in Xephyr

This commit is contained in:
Dodji Seketeli 2007-09-17 18:15:03 +02:00
parent 3816d64e50
commit 7978272661
6 changed files with 223 additions and 36 deletions

View File

@ -467,7 +467,7 @@ Bool XF86DRIGetDrawableInfo(Display* dpy, int screen, Drawable drawable,
{
XExtDisplayInfo *info = find_display (dpy);
xXF86DRIGetDrawableInfoReply rep;
xXF86DRIGetDrawableInfoReq *req;
xXF86DRIGetDrawableInfoReq *req=NULL;
int total_rects;
TRACE("GetDrawableInfo...");
@ -521,7 +521,7 @@ Bool XF86DRIGetDrawableInfo(Display* dpy, int screen, Drawable drawable,
int len = sizeof(drm_clip_rect_t) * (*numClipRects);
*pClipRects = (drm_clip_rect_t *)Xcalloc(len, 1);
if (*pClipRects)
if (*pClipRects)
_XRead(dpy, (char*)*pClipRects, len);
} else {
*pClipRects = NULL;

View File

@ -240,6 +240,17 @@ ephyrDRIGetDrawableInfo (int a_screen,
goto out ;
}
EPHYR_LOG ("host x,y,w,h: (%d,%d,%d,%d)\n", *a_x, *a_y, *a_w, *a_h) ;
if (*a_num_back_clip_rects != *a_num_clip_rects) {
free (*a_back_clip_rects) ;
*a_back_clip_rects = calloc (*a_num_clip_rects,
sizeof (drm_clip_rect_t)) ;
memmove (*a_back_clip_rects,
*a_clip_rects,
*a_num_clip_rects * sizeof (drm_clip_rect_t)) ;
*a_num_back_clip_rects = *a_num_clip_rects;
}
EPHYR_LOG ("num back clip rects:%d, num clip rects:%d\n",
*a_num_clip_rects, *a_num_back_clip_rects) ;
*a_back_x = *a_x ;
*a_back_y = *a_y ;
*a_w = attrs.width;

View File

@ -73,6 +73,7 @@ typedef struct {
DestroyWindowProcPtr DestroyWindow ;
MoveWindowProcPtr MoveWindow ;
PositionWindowProcPtr PositionWindow ;
ClipNotifyProcPtr ClipNotify ;
} EphyrDRIScreenPrivRec;
typedef EphyrDRIScreenPrivRec* EphyrDRIScreenPrivPtr;
@ -107,6 +108,9 @@ static void ephyrDRIMoveWindow (WindowPtr a_win,
VTKind a_kind);
static Bool ephyrDRIPositionWindow (WindowPtr a_win,
int x, int y) ;
static void ephyrDRIClipNotify (WindowPtr a_win,
int a_x, int a_y) ;
static Bool EphyrMirrorHostVisuals (void) ;
static Bool destroyHostPeerWindow (const WindowPtr a_win) ;
static Bool findWindowPairFromLocal (WindowPtr a_local,
@ -204,11 +208,13 @@ ephyrDRIScreenInit (ScreenPtr a_screen)
screen_priv->DestroyWindow = a_screen->DestroyWindow ;
screen_priv->MoveWindow = a_screen->MoveWindow ;
screen_priv->PositionWindow = a_screen->PositionWindow ;
screen_priv->ClipNotify = a_screen->ClipNotify ;
a_screen->CreateWindow = ephyrDRICreateWindow ;
a_screen->DestroyWindow = ephyrDRIDestroyWindow ;
a_screen->MoveWindow = ephyrDRIMoveWindow ;
a_screen->PositionWindow = ephyrDRIPositionWindow ;
a_screen->ClipNotify = ephyrDRIClipNotify ;
is_ok = TRUE ;
out:
@ -259,7 +265,9 @@ ephyrDRIDestroyWindow (WindowPtr a_win)
FALSE) ;
screen->DestroyWindow = screen_priv->DestroyWindow ;
is_ok = (*screen->DestroyWindow) (a_win) ;
if (screen->DestroyWindow) {
is_ok = (*screen->DestroyWindow) (a_win) ;
}
screen->DestroyWindow = ephyrDRIDestroyWindow ;
if (is_ok) {
@ -298,7 +306,9 @@ ephyrDRIMoveWindow (WindowPtr a_win,
&& screen_priv->MoveWindow) ;
screen->MoveWindow = screen_priv->MoveWindow ;
(*screen->MoveWindow) (a_win, a_x, a_y, a_siblings, a_kind) ;
if (screen->MoveWindow) {
(*screen->MoveWindow) (a_win, a_x, a_y, a_siblings, a_kind) ;
}
screen->MoveWindow = ephyrDRIMoveWindow ;
EPHYR_LOG ("window: %#x\n", (unsigned int)a_win) ;
@ -356,7 +366,9 @@ ephyrDRIPositionWindow (WindowPtr a_win,
FALSE) ;
screen->PositionWindow = screen_priv->PositionWindow ;
(*screen->PositionWindow) (a_win, a_x, a_y) ;
if (screen->PositionWindow) {
(*screen->PositionWindow) (a_win, a_x, a_y) ;
}
screen->PositionWindow = ephyrDRIPositionWindow ;
EPHYR_LOG ("window: %#x\n", (unsigned int)a_win) ;
@ -385,6 +397,73 @@ out:
return is_ok ;
}
static void
ephyrDRIClipNotify (WindowPtr a_win,
int a_x, int a_y)
{
Bool is_ok=FALSE ;
ScreenPtr screen=NULL ;
EphyrDRIScreenPrivPtr screen_priv =NULL;
EphyrDRIWindowPrivPtr win_priv=NULL ;
EphyrWindowPair *pair=NULL ;
EphyrRect *rects=NULL;
int i=0 ;
EPHYR_RETURN_IF_FAIL (a_win) ;
EPHYR_LOG ("enter\n") ;
screen = a_win->drawable.pScreen ;
EPHYR_RETURN_IF_FAIL (screen) ;
screen_priv = GET_EPHYR_DRI_SCREEN_PRIV (screen) ;
EPHYR_RETURN_IF_FAIL (screen_priv && screen_priv->ClipNotify) ;
screen->ClipNotify = screen_priv->ClipNotify ;
if (screen->ClipNotify) {
(*screen->ClipNotify) (a_win, a_x, a_y) ;
}
screen->ClipNotify = ephyrDRIClipNotify ;
EPHYR_LOG ("window: %#x\n", (unsigned int)a_win) ;
win_priv = GET_EPHYR_DRI_WINDOW_PRIV (a_win) ;
if (!win_priv) {
EPHYR_LOG ("not a DRI peered window\n") ;
is_ok = TRUE ;
goto out ;
}
if (!findWindowPairFromLocal (a_win, &pair) || !pair) {
EPHYR_LOG_ERROR ("failed to get window pair\n") ;
goto out ;
}
rects = xcalloc (REGION_NUM_RECTS (&a_win->clipList),
sizeof (EphyrRect)) ;
for (i=0; i < REGION_NUM_RECTS (&a_win->clipList); i++) {
memmove (&rects[i],
&REGION_RECTS (&a_win->clipList)[i],
sizeof (EphyrRect)) ;
rects[i].x1 -= a_win->drawable.x;
rects[i].x2 -= a_win->drawable.x;
rects[i].y1 -= a_win->drawable.y;
rects[i].y2 -= a_win->drawable.y;
}
/*
* push the clipping region of this window
* to the peer window in the host
*/
is_ok = hostx_set_window_bounding_rectangles
(pair->remote,
rects,
REGION_NUM_RECTS (&a_win->clipList)) ;
is_ok = TRUE ;
out:
if (rects) {
xfree (rects) ;
rects = NULL ;
}
EPHYR_LOG ("leave. is_ok:%d\n", is_ok) ;
/*do cleanup here*/
}
/**
* Duplicates a visual of a_screen
* In screen a_screen, for depth a_depth, find a visual which
@ -1057,9 +1136,9 @@ ProcXF86DRIGetDrawableInfo (register ClientPtr client)
DrawablePtr drawable;
WindowPtr window=NULL;
EphyrWindowPair *pair=NULL;
int X=0, Y=0, W=0, H=0, backX=0, backY=0, rc=0;
drm_clip_rect_t *pClipRects=NULL, *pClippedRects=NULL;
drm_clip_rect_t *pBackClipRects=NULL;
int X=0, Y=0, W=0, H=0, backX=0, backY=0, rc=0, i=0;
drm_clip_rect_t *clipRects=NULL, *clippedRects=NULL;
drm_clip_rect_t *backClipRects=NULL;
EPHYR_LOG ("enter\n") ;
memset (&rep, 0, sizeof (rep)) ;
@ -1091,6 +1170,15 @@ ProcXF86DRIGetDrawableInfo (register ClientPtr client)
EPHYR_LOG_ERROR ("failed to find remote peer drawable\n") ;
return BadMatch ;
}
EPHYR_LOG ("clip list of xephyr gl drawable:\n") ;
for (i=0; i < REGION_NUM_RECTS (&window->clipList); i++) {
EPHYR_LOG ("x1:%d, y1:%d, x2:%d, y2:%d\n",
REGION_RECTS (&window->clipList)[i].x1,
REGION_RECTS (&window->clipList)[i].y1,
REGION_RECTS (&window->clipList)[i].x2,
REGION_RECTS (&window->clipList)[i].y2) ;
}
if (!ephyrDRIGetDrawableInfo (stuff->screen,
pair->remote/*the drawable in hostx*/,
(unsigned int*)&rep.drawableTableIndex,
@ -1100,54 +1188,56 @@ ProcXF86DRIGetDrawableInfo (register ClientPtr client)
(int*)&W,
(int*)&H,
(int*)&rep.numClipRects,
&pClipRects,
&clipRects,
&backX,
&backY,
(int*)&rep.numBackClipRects,
&pBackClipRects)) {
&backClipRects)) {
return BadValue;
}
EPHYR_LOG ("num clip rects:%d, num back clip rects:%d\n",
(int)rep.numClipRects, (int)rep.numBackClipRects) ;
backClipRects = clipRects ;
rep.drawableX = X;
rep.drawableY = Y;
rep.drawableWidth = W;
rep.drawableHeight = H;
rep.length = (SIZEOF(xXF86DRIGetDrawableInfoReply) -
rep.length = (SIZEOF(xXF86DRIGetDrawableInfoReply) -
SIZEOF(xGenericReply));
rep.backX = backX;
rep.backY = backY;
if (rep.numBackClipRects)
rep.length += sizeof(drm_clip_rect_t) * rep.numBackClipRects;
if (rep.numBackClipRects)
rep.length += sizeof(drm_clip_rect_t) * rep.numBackClipRects;
pClippedRects = pClipRects;
clippedRects = clipRects;
if (rep.numClipRects) {
/* Clip cliprects to screen dimensions (redirected windows) */
pClippedRects = xalloc(rep.numClipRects * sizeof(drm_clip_rect_t));
clippedRects = xalloc(rep.numClipRects * sizeof(drm_clip_rect_t));
if (pClippedRects) {
if (clippedRects) {
ScreenPtr pScreen = screenInfo.screens[stuff->screen];
int i, j;
int i=0;
for (i = 0, j = 0; i < rep.numClipRects; i++) {
pClippedRects[j].x1 = max(pClipRects[i].x1, 0);
pClippedRects[j].y1 = max(pClipRects[i].y1, 0);
pClippedRects[j].x2 = min(pClipRects[i].x2, pScreen->width);
pClippedRects[j].y2 = min(pClipRects[i].y2, pScreen->height);
if (pClippedRects[j].x1 < pClippedRects[j].x2 &&
pClippedRects[j].y1 < pClippedRects[j].y2) {
j++;
}
EPHYR_LOG ("clip list of host gl drawable:\n") ;
for (i = 0; i < rep.numClipRects; i++) {
clippedRects[i].x1 = max(clipRects[i].x1, 0);
clippedRects[i].y1 = max(clipRects[i].y1, 0);
clippedRects[i].x2 = min(clipRects[i].x2, pScreen->width);
clippedRects[i].y2 = min(clipRects[i].y2, pScreen->height);
EPHYR_LOG ("x1:%d, y1:%d, x2:%d, y2:%d\n",
clippedRects[i].x1, clippedRects[i].y1,
clippedRects[i].x2, clippedRects[i].y2) ;
}
rep.numClipRects = j;
/*rep.numClipRects = j*/;
EPHYR_LOG ("num host clip rects:%d\n", (int)rep.numClipRects) ;
} else {
rep.numClipRects = 0;
}
rep.length += sizeof(drm_clip_rect_t) * rep.numClipRects;
}
@ -1156,16 +1246,16 @@ ProcXF86DRIGetDrawableInfo (register ClientPtr client)
WriteToClient(client, sizeof(xXF86DRIGetDrawableInfoReply), (char *)&rep);
if (rep.numClipRects) {
WriteToClient(client,
sizeof(drm_clip_rect_t) * rep.numClipRects,
(char *)pClippedRects);
xfree(pClippedRects);
WriteToClient(client,
sizeof(drm_clip_rect_t) * rep.numClipRects,
(char *)clippedRects);
xfree(clippedRects);
}
if (rep.numBackClipRects) {
WriteToClient(client,
sizeof(drm_clip_rect_t) * rep.numBackClipRects,
(char *)pBackClipRects);
WriteToClient(client,
sizeof(drm_clip_rect_t) * rep.numBackClipRects,
(char *)backClipRects);
}
EPHYR_LOG ("leave\n") ;

View File

@ -773,6 +773,7 @@ ephyrHostXVPutImage (int a_port_id,
EPHYR_LOG ("enter, num_clip_rects: %d\n", a_clip_rect_nums) ;
memset (&gc_values, 0, sizeof (gc_values)) ;
gc = XCreateGC (dpy, hostx_get_window (), 0L, &gc_values);
if (!gc) {
EPHYR_LOG_ERROR ("failed to create gc \n") ;

View File

@ -40,6 +40,7 @@
#include <X11/Xatom.h>
#include <X11/keysym.h>
#include <X11/extensions/XShm.h>
#include <X11/extensions/shape.h>
#include "ephyrlog.h"
/*
@ -1215,3 +1216,77 @@ hostx_set_window_geometry (int a_win, EphyrBox *a_geo)
return TRUE;
}
int
hostx_set_window_bounding_rectangles (int a_window,
EphyrRect *a_rects,
int a_num_rects)
{
Bool is_ok=FALSE;
Display *dpy=hostx_get_display () ;
int i=0 ;
XRectangle *rects=NULL ;
EPHYR_RETURN_VAL_IF_FAIL (dpy && a_rects, FALSE) ;
EPHYR_LOG ("enter. num rects:%d\n", a_num_rects) ;
rects = calloc (a_num_rects, sizeof (XRectangle)) ;
for (i=0; i<a_num_rects; i++) {
rects[i].x = a_rects[i].x1 ;
rects[i].y = a_rects[i].y1 ;
rects[i].width = abs (a_rects[i].x2 - a_rects[i].x1);
rects[i].height = abs (a_rects[i].y2 - a_rects[i].y1) ;
EPHYR_LOG ("borders clipped to rect[x:%d,y:%d,w:%d,h:%d]\n",
rects[i].x, rects[i].y,
rects[i].width, rects[i].height) ;
}
/*this aways returns 1*/
XShapeCombineRectangles (dpy, a_window, ShapeBounding, 0, 0,
rects, a_num_rects, ShapeSet, YXBanded) ;
is_ok = TRUE ;
if (rects) {
free (rects) ;
rects = NULL ;
}
EPHYR_LOG ("leave\n") ;
return is_ok;
}
int
hostx_set_window_clipping_rectangles (int a_window,
EphyrRect *a_rects,
int a_num_rects)
{
Bool is_ok=FALSE;
Display *dpy=hostx_get_display () ;
int i=0 ;
XRectangle *rects=NULL ;
EPHYR_RETURN_VAL_IF_FAIL (dpy && a_rects, FALSE) ;
EPHYR_LOG ("enter. num rects:%d\n", a_num_rects) ;
rects = calloc (a_num_rects, sizeof (XRectangle)) ;
for (i=0; i<a_num_rects; i++) {
rects[i].x = a_rects[i].x1 ;
rects[i].y = a_rects[i].y1 ;
rects[i].width = abs (a_rects[i].x2 - a_rects[i].x1);
rects[i].height = abs (a_rects[i].y2 - a_rects[i].y1) ;
EPHYR_LOG ("clipped to rect[x:%d,y:%d,w:%d,h:%d]\n",
rects[i].x, rects[i].y,
rects[i].width, rects[i].height) ;
}
/*this aways returns 1*/
XShapeCombineRectangles (dpy, a_window, ShapeClip, 0, 0,
rects, a_num_rects, ShapeSet, YXBanded) ;
is_ok = TRUE ;
if (rects) {
free (rects) ;
rects = NULL ;
}
EPHYR_LOG ("leave\n") ;
return is_ok;
}

View File

@ -114,6 +114,10 @@ typedef struct {
int x,y,width,height;
} EphyrBox;
typedef struct {
short x1,y1,x2,y2;
} EphyrRect;
int
hostx_want_screen_size(EphyrScreenInfo screen, int *width, int *height);
@ -229,4 +233,10 @@ int hostx_set_window_geometry (int a_win, EphyrBox *a_geo) ;
int hostx_lookup_peer_window (void *a_local_window,
int *a_host_peer /*out parameter*/) ;
int hostx_set_window_bounding_rectangles (int a_window,
EphyrRect *a_rects,
int a_num_rects) ;
int hostx_set_window_clipping_rectangles (int a_window,
EphyrRect *a_rects,
int a_num_rects) ;
#endif