Blame src/Xdamage.c

Packit 1f38fa
/*
Packit 1f38fa
 * Copyright © 2003 Keith Packard
Packit 1f38fa
 * Copyright © 2007 Eric Anholt
Packit 1f38fa
 *
Packit 1f38fa
 * Permission to use, copy, modify, distribute, and sell this software and its
Packit 1f38fa
 * documentation for any purpose is hereby granted without fee, provided that
Packit 1f38fa
 * the above copyright notice appear in all copies and that both that
Packit 1f38fa
 * copyright notice and this permission notice appear in supporting
Packit 1f38fa
 * documentation, and that the name of Keith Packard not be used in
Packit 1f38fa
 * advertising or publicity pertaining to distribution of the software without
Packit 1f38fa
 * specific, written prior permission.  Keith Packard makes no
Packit 1f38fa
 * representations about the suitability of this software for any purpose.  It
Packit 1f38fa
 * is provided "as is" without express or implied warranty.
Packit 1f38fa
 *
Packit 1f38fa
 * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
Packit 1f38fa
 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
Packit 1f38fa
 * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
Packit 1f38fa
 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
Packit 1f38fa
 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
Packit 1f38fa
 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
Packit 1f38fa
 * PERFORMANCE OF THIS SOFTWARE.
Packit 1f38fa
 */
Packit 1f38fa
Packit 1f38fa
#ifdef HAVE_CONFIG_H
Packit 1f38fa
#include <config.h>
Packit 1f38fa
#endif
Packit 1f38fa
#include "xdamageint.h"
Packit 1f38fa
Packit 1f38fa
XDamageExtInfo XDamageExtensionInfo;
Packit 1f38fa
Packit 1f38fa
const char XDamageExtensionName[] = DAMAGE_NAME;
Packit 1f38fa
Packit 1f38fa
static int
Packit 1f38fa
XDamageCloseDisplay (Display *dpy, XExtCodes *codes);
Packit 1f38fa
Packit 1f38fa
static Bool
Packit 1f38fa
XDamageWireToEvent(Display *dpy, XEvent *event, xEvent *wire);
Packit 1f38fa
Packit 1f38fa
static Status
Packit 1f38fa
XDamageEventToWire(Display *dpy, XEvent *event, xEvent *wire);
Packit 1f38fa
Packit 1f38fa
/*
Packit 1f38fa
 * XDamageExtAddDisplay - add a display to this extension. (Replaces
Packit 1f38fa
 * XextAddDisplay)
Packit 1f38fa
 */
Packit 1f38fa
static XDamageExtDisplayInfo *
Packit 1f38fa
XDamageExtAddDisplay (XDamageExtInfo	*extinfo,
Packit 1f38fa
                      Display		*dpy,
Packit 1f38fa
                      const char	*ext_name)
Packit 1f38fa
{
Packit 1f38fa
    XDamageExtDisplayInfo    *info;
Packit 1f38fa
    int			    ev;
Packit 1f38fa
Packit 1f38fa
    info = (XDamageExtDisplayInfo *) Xmalloc (sizeof (XDamageExtDisplayInfo));
Packit 1f38fa
    if (!info) return NULL;
Packit 1f38fa
    info->display = dpy;
Packit 1f38fa
Packit 1f38fa
    info->codes = XInitExtension (dpy, ext_name);
Packit 1f38fa
Packit 1f38fa
    /*
Packit 1f38fa
     * if the server has the extension, then we can initialize the
Packit 1f38fa
     * appropriate function vectors
Packit 1f38fa
     */
Packit 1f38fa
    if (info->codes) {
Packit 1f38fa
	xDamageQueryVersionReply	rep;
Packit 1f38fa
	xDamageQueryVersionReq	*req;
Packit 1f38fa
        XESetCloseDisplay (dpy, info->codes->extension,
Packit 1f38fa
                           XDamageCloseDisplay);
Packit 1f38fa
	for (ev = info->codes->first_event;
Packit 1f38fa
	     ev < info->codes->first_event + XDamageNumberEvents;
Packit 1f38fa
	     ev++)
Packit 1f38fa
	{
Packit 1f38fa
	    XESetWireToEvent (dpy, ev, XDamageWireToEvent);
Packit 1f38fa
	    XESetEventToWire (dpy, ev, XDamageEventToWire);
Packit 1f38fa
	}
Packit 1f38fa
	/*
Packit 1f38fa
	 * Get the version info
Packit 1f38fa
	 */
Packit 1f38fa
	LockDisplay (dpy);
Packit 1f38fa
	GetReq (DamageQueryVersion, req);
Packit 1f38fa
	req->reqType = info->codes->major_opcode;
Packit 1f38fa
	req->damageReqType = X_DamageQueryVersion;
Packit 1f38fa
	req->majorVersion = DAMAGE_MAJOR;
Packit 1f38fa
	req->minorVersion = DAMAGE_MINOR;
Packit 1f38fa
	if (!_XReply (dpy, (xReply *) &rep, 0, xTrue))
Packit 1f38fa
	{
Packit 1f38fa
	    UnlockDisplay (dpy);
Packit 1f38fa
	    SyncHandle ();
Packit 1f38fa
	    Xfree(info);
Packit 1f38fa
	    return NULL;
Packit 1f38fa
	}
Packit 1f38fa
	info->major_version = rep.majorVersion;
Packit 1f38fa
	info->minor_version = rep.minorVersion;
Packit 1f38fa
	UnlockDisplay (dpy);
Packit 1f38fa
	SyncHandle ();
Packit 1f38fa
    } else {
Packit 1f38fa
	/* The server doesn't have this extension.
Packit 1f38fa
	 * Use a private Xlib-internal extension to hang the close_display
Packit 1f38fa
	 * hook on so that the "cache" (extinfo->cur) is properly cleaned.
Packit 1f38fa
	 * (XBUG 7955)
Packit 1f38fa
	 */
Packit 1f38fa
	XExtCodes *codes = XAddExtension(dpy);
Packit 1f38fa
	if (!codes) {
Packit 1f38fa
	    XFree(info);
Packit 1f38fa
	    return NULL;
Packit 1f38fa
	}
Packit 1f38fa
        XESetCloseDisplay (dpy, codes->extension, XDamageCloseDisplay);
Packit 1f38fa
    }
Packit 1f38fa
Packit 1f38fa
    /*
Packit 1f38fa
     * now, chain it onto the list
Packit 1f38fa
     */
Packit 1f38fa
    _XLockMutex(_Xglobal_lock);
Packit 1f38fa
    info->next = extinfo->head;
Packit 1f38fa
    extinfo->head = info;
Packit 1f38fa
    extinfo->cur = info;
Packit 1f38fa
    extinfo->ndisplays++;
Packit 1f38fa
    _XUnlockMutex(_Xglobal_lock);
Packit 1f38fa
    return info;
Packit 1f38fa
}
Packit 1f38fa
Packit 1f38fa
Packit 1f38fa
/*
Packit 1f38fa
 * XDamageExtRemoveDisplay - remove the indicated display from the
Packit 1f38fa
 * extension object. (Replaces XextRemoveDisplay.)
Packit 1f38fa
 */
Packit 1f38fa
static int
Packit 1f38fa
XDamageExtRemoveDisplay (XDamageExtInfo *extinfo, Display *dpy)
Packit 1f38fa
{
Packit 1f38fa
    XDamageExtDisplayInfo *info, *prev;
Packit 1f38fa
Packit 1f38fa
    /*
Packit 1f38fa
     * locate this display and its back link so that it can be removed
Packit 1f38fa
     */
Packit 1f38fa
    _XLockMutex(_Xglobal_lock);
Packit 1f38fa
    prev = NULL;
Packit 1f38fa
    for (info = extinfo->head; info; info = info->next) {
Packit 1f38fa
	if (info->display == dpy) break;
Packit 1f38fa
	prev = info;
Packit 1f38fa
    }
Packit 1f38fa
    if (!info) {
Packit 1f38fa
	_XUnlockMutex(_Xglobal_lock);
Packit 1f38fa
	return 0;		/* hmm, actually an error */
Packit 1f38fa
    }
Packit 1f38fa
Packit 1f38fa
    /*
Packit 1f38fa
     * remove the display from the list; handles going to zero
Packit 1f38fa
     */
Packit 1f38fa
    if (prev)
Packit 1f38fa
	prev->next = info->next;
Packit 1f38fa
    else
Packit 1f38fa
	extinfo->head = info->next;
Packit 1f38fa
Packit 1f38fa
    extinfo->ndisplays--;
Packit 1f38fa
    if (info == extinfo->cur) extinfo->cur = NULL;  /* flush cache */
Packit 1f38fa
    _XUnlockMutex(_Xglobal_lock);
Packit 1f38fa
Packit 1f38fa
    Xfree ((char *) info);
Packit 1f38fa
    return 1;
Packit 1f38fa
}
Packit 1f38fa
Packit 1f38fa
/*
Packit 1f38fa
 * XDamageExtFindDisplay - look for a display in this extension; keeps a
Packit 1f38fa
 * cache of the most-recently used for efficiency. (Replaces
Packit 1f38fa
 * XextFindDisplay.)
Packit 1f38fa
 */
Packit 1f38fa
static XDamageExtDisplayInfo *
Packit 1f38fa
XDamageExtFindDisplay (XDamageExtInfo *extinfo,
Packit 1f38fa
		      Display	    *dpy)
Packit 1f38fa
{
Packit 1f38fa
    XDamageExtDisplayInfo *info;
Packit 1f38fa
Packit 1f38fa
    /*
Packit 1f38fa
     * see if this was the most recently accessed display
Packit 1f38fa
     */
Packit 1f38fa
    if ((info = extinfo->cur) && info->display == dpy)
Packit 1f38fa
	return info;
Packit 1f38fa
Packit 1f38fa
    /*
Packit 1f38fa
     * look for display in list
Packit 1f38fa
     */
Packit 1f38fa
    _XLockMutex(_Xglobal_lock);
Packit 1f38fa
    for (info = extinfo->head; info; info = info->next) {
Packit 1f38fa
	if (info->display == dpy) {
Packit 1f38fa
	    extinfo->cur = info;     /* cache most recently used */
Packit 1f38fa
	    _XUnlockMutex(_Xglobal_lock);
Packit 1f38fa
	    return info;
Packit 1f38fa
	}
Packit 1f38fa
    }
Packit 1f38fa
    _XUnlockMutex(_Xglobal_lock);
Packit 1f38fa
Packit 1f38fa
    return NULL;
Packit 1f38fa
}
Packit 1f38fa
Packit 1f38fa
XDamageExtDisplayInfo *
Packit 1f38fa
XDamageFindDisplay (Display *dpy)
Packit 1f38fa
{
Packit 1f38fa
    XDamageExtDisplayInfo *info;
Packit 1f38fa
Packit 1f38fa
    info = XDamageExtFindDisplay (&XDamageExtensionInfo, dpy);
Packit 1f38fa
    if (!info)
Packit 1f38fa
	info = XDamageExtAddDisplay (&XDamageExtensionInfo, dpy,
Packit 1f38fa
				    XDamageExtensionName);
Packit 1f38fa
    return info;
Packit 1f38fa
}
Packit 1f38fa
Packit 1f38fa
static int
Packit 1f38fa
XDamageCloseDisplay (Display *dpy, XExtCodes *codes)
Packit 1f38fa
{
Packit 1f38fa
    return XDamageExtRemoveDisplay (&XDamageExtensionInfo, dpy);
Packit 1f38fa
}
Packit 1f38fa
Packit 1f38fa
static Bool
Packit 1f38fa
XDamageWireToEvent(Display *dpy, XEvent *event, xEvent *wire)
Packit 1f38fa
{
Packit 1f38fa
    XDamageExtDisplayInfo *info = XDamageFindDisplay(dpy);
Packit 1f38fa
Packit 1f38fa
    XDamageCheckExtension(dpy, info, False);
Packit 1f38fa
Packit 1f38fa
    switch ((wire->u.u.type & 0x7F) - info->codes->first_event)
Packit 1f38fa
    {
Packit 1f38fa
    case XDamageNotify: {
Packit 1f38fa
	XDamageNotifyEvent *aevent = (XDamageNotifyEvent *) event;
Packit 1f38fa
	xDamageNotifyEvent *awire = (xDamageNotifyEvent *) wire;
Packit 1f38fa
Packit 1f38fa
	aevent->type = awire->type & 0x7F;
Packit 1f38fa
	aevent->serial = _XSetLastRequestRead(dpy,
Packit 1f38fa
					      (xGenericReply *) wire);
Packit 1f38fa
	aevent->send_event = (awire->type & 0x80) != 0;
Packit 1f38fa
	aevent->display = dpy;
Packit 1f38fa
	aevent->drawable = awire->drawable;
Packit 1f38fa
	aevent->damage = awire->damage;
Packit 1f38fa
	aevent->level = awire->level & ~DamageNotifyMore;
Packit 1f38fa
	aevent->more = (awire->level & DamageNotifyMore) ? True : False;
Packit 1f38fa
	aevent->timestamp = awire->timestamp;
Packit 1f38fa
	aevent->area.x = awire->area.x;
Packit 1f38fa
	aevent->area.y = awire->area.y;
Packit 1f38fa
	aevent->area.width = awire->area.width;
Packit 1f38fa
	aevent->area.height = awire->area.height;
Packit 1f38fa
	aevent->geometry.x = awire->geometry.x;
Packit 1f38fa
	aevent->geometry.y = awire->geometry.y;
Packit 1f38fa
	aevent->geometry.width = awire->geometry.width;
Packit 1f38fa
	aevent->geometry.height = awire->geometry.height;
Packit 1f38fa
	return True;
Packit 1f38fa
    }
Packit 1f38fa
    }
Packit 1f38fa
    return False;
Packit 1f38fa
}
Packit 1f38fa
Packit 1f38fa
static Status
Packit 1f38fa
XDamageEventToWire(Display *dpy, XEvent *event, xEvent *wire)
Packit 1f38fa
{
Packit 1f38fa
    XDamageExtDisplayInfo *info = XDamageFindDisplay(dpy);
Packit 1f38fa
Packit 1f38fa
    XDamageCheckExtension(dpy, info, False);
Packit 1f38fa
Packit 1f38fa
    switch ((event->type & 0x7F) - info->codes->first_event)
Packit 1f38fa
    {
Packit 1f38fa
    case XDamageNotify: {
Packit 1f38fa
	XDamageNotifyEvent *aevent;
Packit 1f38fa
	xDamageNotifyEvent *awire;
Packit 1f38fa
	awire = (xDamageNotifyEvent *) wire;
Packit 1f38fa
	aevent = (XDamageNotifyEvent *) event;
Packit 1f38fa
	awire->type = aevent->type | (aevent->send_event ? 0x80 : 0);
Packit 1f38fa
	awire->drawable = aevent->drawable;
Packit 1f38fa
	awire->damage = aevent->damage;
Packit 1f38fa
	awire->level = aevent->level | (aevent->more ? DamageNotifyMore : 0);
Packit 1f38fa
	awire->timestamp = aevent->timestamp;
Packit 1f38fa
	awire->area.x = aevent->area.x;
Packit 1f38fa
	awire->area.y = aevent->area.y;
Packit 1f38fa
	awire->area.width = aevent->area.width;
Packit 1f38fa
	awire->area.height = aevent->area.height;
Packit 1f38fa
	awire->geometry.x = aevent->geometry.x;
Packit 1f38fa
	awire->geometry.y = aevent->geometry.y;
Packit 1f38fa
	awire->geometry.width = aevent->geometry.width;
Packit 1f38fa
	awire->geometry.height = aevent->geometry.height;
Packit 1f38fa
	return True;
Packit 1f38fa
    }
Packit 1f38fa
    }
Packit 1f38fa
    return False;
Packit 1f38fa
}
Packit 1f38fa
Packit 1f38fa
Bool
Packit 1f38fa
XDamageQueryExtension (Display *dpy,
Packit 1f38fa
			int *event_base_return,
Packit 1f38fa
			int *error_base_return)
Packit 1f38fa
{
Packit 1f38fa
    XDamageExtDisplayInfo *info = XDamageFindDisplay (dpy);
Packit 1f38fa
Packit 1f38fa
    if (XDamageHasExtension(info))
Packit 1f38fa
    {
Packit 1f38fa
	*event_base_return = info->codes->first_event;
Packit 1f38fa
	*error_base_return = info->codes->first_error;
Packit 1f38fa
	return True;
Packit 1f38fa
    }
Packit 1f38fa
    else
Packit 1f38fa
	return False;
Packit 1f38fa
}
Packit 1f38fa
Packit 1f38fa
Status
Packit 1f38fa
XDamageQueryVersion (Display *dpy,
Packit 1f38fa
		    int	    *major_version_return,
Packit 1f38fa
		    int	    *minor_version_return)
Packit 1f38fa
{
Packit 1f38fa
    XDamageExtDisplayInfo	*info = XDamageFindDisplay (dpy);
Packit 1f38fa
Packit 1f38fa
    XDamageCheckExtension (dpy, info, 0);
Packit 1f38fa
Packit 1f38fa
    *major_version_return = info->major_version;
Packit 1f38fa
    *minor_version_return = info->minor_version;
Packit 1f38fa
    return 1;
Packit 1f38fa
}
Packit 1f38fa
Packit 1f38fa
Damage
Packit 1f38fa
XDamageCreate (Display *dpy, Drawable drawable, int level)
Packit 1f38fa
{
Packit 1f38fa
    XDamageExtDisplayInfo	*info = XDamageFindDisplay (dpy);
Packit 1f38fa
    xDamageCreateReq		*req;
Packit 1f38fa
    Damage			damage;
Packit 1f38fa
Packit 1f38fa
    XDamageCheckExtension (dpy, info, 0);
Packit 1f38fa
    LockDisplay (dpy);
Packit 1f38fa
    GetReq (DamageCreate, req);
Packit 1f38fa
    req->reqType = info->codes->major_opcode;
Packit 1f38fa
    req->damageReqType = X_DamageCreate;
Packit 1f38fa
    req->damage = damage = XAllocID (dpy);
Packit 1f38fa
    req->drawable = drawable;
Packit 1f38fa
    req->level = level;
Packit 1f38fa
    UnlockDisplay (dpy);
Packit 1f38fa
    SyncHandle ();
Packit 1f38fa
    return damage;
Packit 1f38fa
}
Packit 1f38fa
Packit 1f38fa
void
Packit 1f38fa
XDamageDestroy (Display *dpy, Damage damage)
Packit 1f38fa
{
Packit 1f38fa
    XDamageExtDisplayInfo	*info = XDamageFindDisplay (dpy);
Packit 1f38fa
    xDamageDestroyReq		*req;
Packit 1f38fa
Packit 1f38fa
    XDamageSimpleCheckExtension (dpy, info);
Packit 1f38fa
    LockDisplay (dpy);
Packit 1f38fa
    GetReq (DamageDestroy, req);
Packit 1f38fa
    req->reqType = info->codes->major_opcode;
Packit 1f38fa
    req->damageReqType = X_DamageDestroy;
Packit 1f38fa
    req->damage = damage;
Packit 1f38fa
    UnlockDisplay (dpy);
Packit 1f38fa
    SyncHandle ();
Packit 1f38fa
}
Packit 1f38fa
Packit 1f38fa
void
Packit 1f38fa
XDamageSubtract (Display *dpy, Damage damage,
Packit 1f38fa
		 XserverRegion repair, XserverRegion parts)
Packit 1f38fa
{
Packit 1f38fa
    XDamageExtDisplayInfo	*info = XDamageFindDisplay (dpy);
Packit 1f38fa
    xDamageSubtractReq		*req;
Packit 1f38fa
Packit 1f38fa
    XDamageSimpleCheckExtension (dpy, info);
Packit 1f38fa
    LockDisplay (dpy);
Packit 1f38fa
    GetReq (DamageSubtract, req);
Packit 1f38fa
    req->reqType = info->codes->major_opcode;
Packit 1f38fa
    req->damageReqType = X_DamageSubtract;
Packit 1f38fa
    req->damage = damage;
Packit 1f38fa
    req->repair = repair;
Packit 1f38fa
    req->parts = parts;
Packit 1f38fa
    UnlockDisplay (dpy);
Packit 1f38fa
    SyncHandle ();
Packit 1f38fa
}
Packit 1f38fa
Packit 1f38fa
void
Packit 1f38fa
XDamageAdd (Display *dpy, Drawable drawable, XserverRegion region)
Packit 1f38fa
{
Packit 1f38fa
    XDamageExtDisplayInfo	*info = XDamageFindDisplay (dpy);
Packit 1f38fa
    xDamageAddReq		*req;
Packit 1f38fa
Packit 1f38fa
    XDamageSimpleCheckExtension (dpy, info);
Packit 1f38fa
    LockDisplay (dpy);
Packit 1f38fa
    GetReq (DamageAdd, req);
Packit 1f38fa
    req->reqType = info->codes->major_opcode;
Packit 1f38fa
    req->damageReqType = X_DamageAdd;
Packit 1f38fa
    req->drawable = drawable;
Packit 1f38fa
    req->region = region;
Packit 1f38fa
Packit 1f38fa
    UnlockDisplay (dpy);
Packit 1f38fa
    SyncHandle ();
Packit 1f38fa
}