174 lines
4.8 KiB
C
174 lines
4.8 KiB
C
|
/*****************************************************************************
|
||
|
* driDrawable.c: Lean Version of DRI utilities.
|
||
|
*
|
||
|
* Copyright (c) 2005 Thomas Hellstrom. All rights reserved.
|
||
|
*
|
||
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
||
|
* copy of this software and associated documentation files (the "Software"),
|
||
|
* to deal in the Software without restriction, including without limitation
|
||
|
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||
|
* and/or sell copies of the Software, and to permit persons to whom the
|
||
|
* Software is furnished to do so, subject to the following conditions:
|
||
|
*
|
||
|
* The above copyright notice and this permission notice shall be included in
|
||
|
* all copies or substantial portions of the Software.
|
||
|
*
|
||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||
|
* AUTHOR(S) OR COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||
|
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||
|
* DEALINGS IN THE SOFTWARE.
|
||
|
*/
|
||
|
|
||
|
#include <X11/Xlibint.h>
|
||
|
#include <X11/Xutil.h>
|
||
|
#include "xf86drm.h"
|
||
|
#include "drm.h"
|
||
|
#include "xf86dri.h"
|
||
|
#include "drm_sarea.h"
|
||
|
#include "driDrawable.h"
|
||
|
|
||
|
static unsigned
|
||
|
drawStamp(volatile drm_sarea_t * pSarea, int index)
|
||
|
{
|
||
|
return pSarea->drawableTable[index].stamp;
|
||
|
}
|
||
|
|
||
|
int
|
||
|
getDRIDrawableInfoLocked(void *drawHash, Display * display, int screen,
|
||
|
Drawable draw, unsigned lockFlags, int drmFD, drm_context_t drmContext,
|
||
|
drmAddress sarea, Bool updateInfo, drawableInfo ** info,
|
||
|
unsigned long infoSize)
|
||
|
{
|
||
|
drawableInfo *drawInfo;
|
||
|
void *res;
|
||
|
drm_drawable_t drmDraw = 0;
|
||
|
volatile drm_sarea_t *pSarea = (drm_sarea_t *) sarea;
|
||
|
drm_clip_rect_t *clipFront, *clipBack;
|
||
|
|
||
|
int ret;
|
||
|
|
||
|
if (drmHashLookup(drawHash, (unsigned long)draw, &res)) {
|
||
|
|
||
|
/*
|
||
|
* The drawable is unknown to us. Create it and put it in the
|
||
|
* hash table.
|
||
|
*/
|
||
|
|
||
|
DRM_UNLOCK(drmFD, &pSarea->lock, drmContext);
|
||
|
if (!uniDRICreateDrawable(display, screen, draw, &drmDraw)) {
|
||
|
DRM_LOCK(drmFD, &pSarea->lock, drmContext, lockFlags);
|
||
|
return 1;
|
||
|
}
|
||
|
DRM_LOCK(drmFD, &pSarea->lock, drmContext, lockFlags);
|
||
|
|
||
|
drawInfo = (drawableInfo *) malloc(infoSize);
|
||
|
if (!drawInfo)
|
||
|
return 1;
|
||
|
|
||
|
drawInfo->drmDraw = drmDraw;
|
||
|
drawInfo->stamp = 0;
|
||
|
drawInfo->clipFront = 0;
|
||
|
drawInfo->clipBack = 0;
|
||
|
|
||
|
drmHashInsert(drawHash, (unsigned long)draw, drawInfo);
|
||
|
|
||
|
} else {
|
||
|
drawInfo = res;
|
||
|
}
|
||
|
|
||
|
drawInfo->touched = FALSE;
|
||
|
while (!drawInfo->clipFront
|
||
|
|| drawInfo->stamp != drawStamp(pSarea, drawInfo->index)) {
|
||
|
|
||
|
/*
|
||
|
* The drawable has been touched since we last got info about it.
|
||
|
* obtain new info from the X server.
|
||
|
*/
|
||
|
|
||
|
drawInfo->touched = TRUE;
|
||
|
|
||
|
if (updateInfo || !drawInfo->clipFront) {
|
||
|
DRM_UNLOCK(drmFD, &pSarea->lock, drmContext);
|
||
|
|
||
|
ret = uniDRIGetDrawableInfo(display, screen, draw,
|
||
|
&drawInfo->index, &drawInfo->stamp, &drawInfo->x,
|
||
|
&drawInfo->y, &drawInfo->w, &drawInfo->h,
|
||
|
&drawInfo->numClipFront, &clipFront,
|
||
|
&drawInfo->backX, &drawInfo->backY,
|
||
|
&drawInfo->numClipBack, &clipBack);
|
||
|
|
||
|
DRM_LIGHT_LOCK(drmFD, &pSarea->lock, drmContext);
|
||
|
|
||
|
/*
|
||
|
* Error. Probably the drawable is destroyed. Return error and old values.
|
||
|
*/
|
||
|
|
||
|
if (!ret) {
|
||
|
free(drawInfo);
|
||
|
drawInfo = NULL;
|
||
|
drmHashDelete(drawHash, (unsigned long)draw);
|
||
|
|
||
|
DRM_UNLOCK(drmFD, &pSarea->lock, drmContext);
|
||
|
uniDRIDestroyDrawable(display, screen, draw);
|
||
|
DRM_LOCK(drmFD, &pSarea->lock, drmContext, lockFlags);
|
||
|
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
if (drawInfo->stamp != drawStamp(pSarea, drawInfo->index)) {
|
||
|
|
||
|
/*
|
||
|
* The info is already outdated. Sigh. Have another go.
|
||
|
*/
|
||
|
|
||
|
XFree(clipFront);
|
||
|
XFree(clipBack);
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
if (drawInfo->clipFront)
|
||
|
XFree(drawInfo->clipFront);
|
||
|
drawInfo->clipFront = clipFront;
|
||
|
if (drawInfo->clipBack)
|
||
|
XFree(drawInfo->clipBack);
|
||
|
drawInfo->clipBack = clipBack;
|
||
|
} else {
|
||
|
if (!drawInfo->clipFront)
|
||
|
drawInfo->clipFront = (drm_clip_rect_t *) ~ 0UL;
|
||
|
drawInfo->stamp = drawStamp(pSarea, drawInfo->index);
|
||
|
}
|
||
|
}
|
||
|
*info = drawInfo;
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
void
|
||
|
driDestroyHashContents(void *drawHash)
|
||
|
{
|
||
|
unsigned long key;
|
||
|
void *content;
|
||
|
drawableInfo *drawInfo;
|
||
|
|
||
|
if (drmHashFirst(drawHash, &key, &content) < 1)
|
||
|
return;
|
||
|
drawInfo = (drawableInfo *) content;
|
||
|
if (drawInfo->clipBack)
|
||
|
XFree(drawInfo->clipBack);
|
||
|
if (drawInfo->clipFront)
|
||
|
XFree(drawInfo->clipFront);
|
||
|
free(drawInfo);
|
||
|
while (drmHashNext(drawHash, &key, &content) == 1) {
|
||
|
drawInfo = (drawableInfo *) content;
|
||
|
if (drawInfo->clipBack)
|
||
|
XFree(drawInfo->clipBack);
|
||
|
if (drawInfo->clipFront)
|
||
|
XFree(drawInfo->clipFront);
|
||
|
free(drawInfo);
|
||
|
}
|
||
|
|
||
|
return;
|
||
|
}
|