xenocara/xserver/miext/cw/cw_render.c
matthieu 428261197a Upgrade to xorg-server 1.9.2.
Tested by ajacoutot@, krw@, shadchin@ and jasper@ on various configurations
including multihead with both zaphod and xrandr.
2010-12-05 15:36:02 +00:00

470 lines
13 KiB
C

/*
* Copyright © 2004 Eric Anholt
*
* Permission to use, copy, modify, distribute, and sell this software and its
* documentation for any purpose is hereby granted without fee, provided that
* the above copyright notice appear in all copies and that both that
* copyright notice and this permission notice appear in supporting
* documentation, and that the name of Eric Anholt not be used in
* advertising or publicity pertaining to distribution of the software without
* specific, written prior permission. Eric Anholt makes no
* representations about the suitability of this software for any purpose. It
* is provided "as is" without express or implied warranty.
*
* ERIC ANHOLT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
* EVENT SHALL ERIC ANHOLT BE LIABLE FOR ANY SPECIAL, INDIRECT OR
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
*/
#ifdef HAVE_DIX_CONFIG_H
#include <dix-config.h>
#endif
#include <string.h>
#include "gcstruct.h"
#include "windowstr.h"
#include "cw.h"
#define cwPsDecl(pScreen) \
PictureScreenPtr ps = GetPictureScreen (pScreen); \
cwScreenPtr pCwScreen = getCwScreen (pScreen)
#define cwPicturePrivate \
cwPicturePtr pPicturePrivate = getCwPicture(pPicture)
#define cwSrcPictureDecl \
int src_picture_x_off, src_picture_y_off; \
PicturePtr pBackingSrcPicture = cwGetBackingPicture(pSrcPicture, \
&src_picture_x_off,\
&src_picture_y_off)
#define cwDstPictureDecl \
int dst_picture_x_off, dst_picture_y_off; \
PicturePtr pBackingDstPicture = cwGetBackingPicture(pDstPicture, \
&dst_picture_x_off,\
&dst_picture_y_off)
#define cwMskPictureDecl \
int msk_picture_x_off = 0, msk_picture_y_off = 0; \
PicturePtr pBackingMskPicture = (!pMskPicture ? 0 : \
cwGetBackingPicture(pMskPicture, \
&msk_picture_x_off,\
&msk_picture_y_off))
#define cwPsUnwrap(elt) { \
ps->elt = pCwScreen->elt; \
}
#define cwPsWrap(elt,func) { \
pCwScreen->elt = ps->elt; \
ps->elt = func; \
}
static cwPicturePtr
cwCreatePicturePrivate (PicturePtr pPicture)
{
WindowPtr pWindow = (WindowPtr) pPicture->pDrawable;
PixmapPtr pPixmap = getCwPixmap (pWindow);
int error;
cwPicturePtr pPicturePrivate;
pPicturePrivate = malloc(sizeof (cwPictureRec));
if (!pPicturePrivate)
return NULL;
pPicturePrivate->pBackingPicture = CreatePicture (0, &pPixmap->drawable,
pPicture->pFormat,
0, 0, serverClient,
&error);
if (!pPicturePrivate->pBackingPicture)
{
free(pPicturePrivate);
return NULL;
}
/*
* Ensure that this serial number does not match the window's
*/
pPicturePrivate->serialNumber = pPixmap->drawable.serialNumber;
pPicturePrivate->stateChanges = (1 << (CPLastBit + 1)) - 1;
setCwPicture(pPicture, pPicturePrivate);
return pPicturePrivate;
}
static void
cwDestroyPicturePrivate (PicturePtr pPicture)
{
cwPicturePrivate;
if (pPicturePrivate)
{
if (pPicturePrivate->pBackingPicture)
FreePicture (pPicturePrivate->pBackingPicture, 0);
free(pPicturePrivate);
setCwPicture(pPicture, NULL);
}
}
static PicturePtr
cwGetBackingPicture (PicturePtr pPicture, int *x_off, int *y_off)
{
cwPicturePrivate;
if (pPicturePrivate)
{
DrawablePtr pDrawable = pPicture->pDrawable;
WindowPtr pWindow = (WindowPtr) pDrawable;
PixmapPtr pPixmap = getCwPixmap (pWindow);
*x_off = pDrawable->x - pPixmap->screen_x;
*y_off = pDrawable->y - pPixmap->screen_y;
return pPicturePrivate->pBackingPicture;
}
else
{
*x_off = *y_off = 0;
return pPicture;
}
}
static void
cwDestroyPicture (PicturePtr pPicture)
{
ScreenPtr pScreen = pPicture->pDrawable->pScreen;
cwPsDecl(pScreen);
cwPsUnwrap(DestroyPicture);
cwDestroyPicturePrivate (pPicture);
(*ps->DestroyPicture) (pPicture);
cwPsWrap(DestroyPicture, cwDestroyPicture);
}
static void
cwChangePicture (PicturePtr pPicture, Mask mask)
{
ScreenPtr pScreen = pPicture->pDrawable->pScreen;
cwPsDecl(pScreen);
cwPicturePtr pPicturePrivate = getCwPicture(pPicture);
cwPsUnwrap(ChangePicture);
(*ps->ChangePicture) (pPicture, mask);
if (pPicturePrivate)
pPicturePrivate->stateChanges |= mask;
cwPsWrap(ChangePicture, cwChangePicture);
}
static void
cwValidatePicture (PicturePtr pPicture,
Mask mask)
{
DrawablePtr pDrawable = pPicture->pDrawable;
ScreenPtr pScreen = pDrawable->pScreen;
cwPsDecl(pScreen);
cwPicturePrivate;
cwPsUnwrap(ValidatePicture);
/*
* Must call ValidatePicture to ensure pPicture->pCompositeClip is valid
*/
(*ps->ValidatePicture) (pPicture, mask);
if (!cwDrawableIsRedirWindow (pDrawable))
{
if (pPicturePrivate)
cwDestroyPicturePrivate (pPicture);
}
else
{
PicturePtr pBackingPicture;
DrawablePtr pBackingDrawable;
int x_off, y_off;
pBackingDrawable = cwGetBackingDrawable(pDrawable, &x_off, &y_off);
if (pPicturePrivate &&
pPicturePrivate->pBackingPicture->pDrawable != pBackingDrawable)
{
cwDestroyPicturePrivate (pPicture);
pPicturePrivate = 0;
}
if (!pPicturePrivate)
{
pPicturePrivate = cwCreatePicturePrivate (pPicture);
if (!pPicturePrivate)
{
cwPsWrap(ValidatePicture, cwValidatePicture);
return;
}
}
pBackingPicture = pPicturePrivate->pBackingPicture;
/*
* Always copy transform and filters because there's no
* indication of when they've changed
*/
SetPictureTransform(pBackingPicture, pPicture->transform);
if (pBackingPicture->filter != pPicture->filter ||
pPicture->filter_nparams > 0)
{
char *filter = PictureGetFilterName (pPicture->filter);
SetPictureFilter(pBackingPicture,
filter, strlen (filter),
pPicture->filter_params,
pPicture->filter_nparams);
}
pPicturePrivate->stateChanges |= mask;
if (pPicturePrivate->serialNumber != pDrawable->serialNumber ||
(pPicturePrivate->stateChanges & (CPClipXOrigin|CPClipYOrigin|CPClipMask)))
{
SetPictureClipRegion (pBackingPicture,
x_off - pDrawable->x,
y_off - pDrawable->y,
pPicture->pCompositeClip);
pPicturePrivate->serialNumber = pDrawable->serialNumber;
pPicturePrivate->stateChanges &= ~(CPClipXOrigin | CPClipYOrigin | CPClipMask);
}
CopyPicture(pPicture, pPicturePrivate->stateChanges, pBackingPicture);
ValidatePicture (pBackingPicture);
}
cwPsWrap(ValidatePicture, cwValidatePicture);
}
static void
cwComposite (CARD8 op,
PicturePtr pSrcPicture,
PicturePtr pMskPicture,
PicturePtr pDstPicture,
INT16 xSrc,
INT16 ySrc,
INT16 xMsk,
INT16 yMsk,
INT16 xDst,
INT16 yDst,
CARD16 width,
CARD16 height)
{
ScreenPtr pScreen = pDstPicture->pDrawable->pScreen;
cwPsDecl(pScreen);
cwSrcPictureDecl;
cwMskPictureDecl;
cwDstPictureDecl;
cwPsUnwrap(Composite);
(*ps->Composite) (op, pBackingSrcPicture, pBackingMskPicture, pBackingDstPicture,
xSrc + src_picture_x_off, ySrc + src_picture_y_off,
xMsk + msk_picture_x_off, yMsk + msk_picture_y_off,
xDst + dst_picture_x_off, yDst + dst_picture_y_off,
width, height);
cwPsWrap(Composite, cwComposite);
}
static void
cwCompositeRects (CARD8 op,
PicturePtr pDstPicture,
xRenderColor *color,
int nRect,
xRectangle *rects)
{
ScreenPtr pScreen = pDstPicture->pDrawable->pScreen;
cwPsDecl(pScreen);
cwDstPictureDecl;
int i;
cwPsUnwrap(CompositeRects);
for (i = 0; i < nRect; i++)
{
rects[i].x += dst_picture_x_off;
rects[i].y += dst_picture_y_off;
}
(*ps->CompositeRects) (op, pBackingDstPicture, color, nRect, rects);
cwPsWrap(CompositeRects, cwCompositeRects);
}
static void
cwTrapezoids (CARD8 op,
PicturePtr pSrcPicture,
PicturePtr pDstPicture,
PictFormatPtr maskFormat,
INT16 xSrc,
INT16 ySrc,
int ntrap,
xTrapezoid *traps)
{
ScreenPtr pScreen = pDstPicture->pDrawable->pScreen;
cwPsDecl(pScreen);
cwSrcPictureDecl;
cwDstPictureDecl;
int i;
cwPsUnwrap(Trapezoids);
if (dst_picture_x_off || dst_picture_y_off) {
for (i = 0; i < ntrap; i++)
{
traps[i].top += dst_picture_y_off << 16;
traps[i].bottom += dst_picture_y_off << 16;
traps[i].left.p1.x += dst_picture_x_off << 16;
traps[i].left.p1.y += dst_picture_y_off << 16;
traps[i].left.p2.x += dst_picture_x_off << 16;
traps[i].left.p2.y += dst_picture_y_off << 16;
traps[i].right.p1.x += dst_picture_x_off << 16;
traps[i].right.p1.y += dst_picture_y_off << 16;
traps[i].right.p2.x += dst_picture_x_off << 16;
traps[i].right.p2.y += dst_picture_y_off << 16;
}
}
(*ps->Trapezoids) (op, pBackingSrcPicture, pBackingDstPicture, maskFormat,
xSrc + src_picture_x_off, ySrc + src_picture_y_off,
ntrap, traps);
cwPsWrap(Trapezoids, cwTrapezoids);
}
static void
cwTriangles (CARD8 op,
PicturePtr pSrcPicture,
PicturePtr pDstPicture,
PictFormatPtr maskFormat,
INT16 xSrc,
INT16 ySrc,
int ntri,
xTriangle *tris)
{
ScreenPtr pScreen = pDstPicture->pDrawable->pScreen;
cwPsDecl(pScreen);
cwSrcPictureDecl;
cwDstPictureDecl;
int i;
cwPsUnwrap(Triangles);
if (dst_picture_x_off || dst_picture_y_off) {
for (i = 0; i < ntri; i++)
{
tris[i].p1.x += dst_picture_x_off << 16;
tris[i].p1.y += dst_picture_y_off << 16;
tris[i].p2.x += dst_picture_x_off << 16;
tris[i].p2.y += dst_picture_y_off << 16;
tris[i].p3.x += dst_picture_x_off << 16;
tris[i].p3.y += dst_picture_y_off << 16;
}
}
(*ps->Triangles) (op, pBackingSrcPicture, pBackingDstPicture, maskFormat,
xSrc + src_picture_x_off, ySrc + src_picture_y_off,
ntri, tris);
cwPsWrap(Triangles, cwTriangles);
}
static void
cwTriStrip (CARD8 op,
PicturePtr pSrcPicture,
PicturePtr pDstPicture,
PictFormatPtr maskFormat,
INT16 xSrc,
INT16 ySrc,
int npoint,
xPointFixed *points)
{
ScreenPtr pScreen = pDstPicture->pDrawable->pScreen;
cwPsDecl(pScreen);
cwSrcPictureDecl;
cwDstPictureDecl;
int i;
cwPsUnwrap(TriStrip);
if (dst_picture_x_off || dst_picture_y_off) {
for (i = 0; i < npoint; i++)
{
points[i].x += dst_picture_x_off << 16;
points[i].y += dst_picture_y_off << 16;
}
}
(*ps->TriStrip) (op, pBackingSrcPicture, pBackingDstPicture, maskFormat,
xSrc + src_picture_x_off, ySrc + src_picture_y_off,
npoint, points);
cwPsWrap(TriStrip, cwTriStrip);
}
static void
cwTriFan (CARD8 op,
PicturePtr pSrcPicture,
PicturePtr pDstPicture,
PictFormatPtr maskFormat,
INT16 xSrc,
INT16 ySrc,
int npoint,
xPointFixed *points)
{
ScreenPtr pScreen = pDstPicture->pDrawable->pScreen;
cwPsDecl(pScreen);
cwSrcPictureDecl;
cwDstPictureDecl;
int i;
cwPsUnwrap(TriFan);
if (dst_picture_x_off || dst_picture_y_off) {
for (i = 0; i < npoint; i++)
{
points[i].x += dst_picture_x_off << 16;
points[i].y += dst_picture_y_off << 16;
}
}
(*ps->TriFan) (op, pBackingSrcPicture, pBackingDstPicture, maskFormat,
xSrc + src_picture_x_off, ySrc + src_picture_y_off,
npoint, points);
cwPsWrap(TriFan, cwTriFan);
}
void
cwInitializeRender (ScreenPtr pScreen)
{
cwPsDecl (pScreen);
cwPsWrap(DestroyPicture, cwDestroyPicture);
cwPsWrap(ChangePicture, cwChangePicture);
cwPsWrap(ValidatePicture, cwValidatePicture);
cwPsWrap(Composite, cwComposite);
cwPsWrap(CompositeRects, cwCompositeRects);
cwPsWrap(Trapezoids, cwTrapezoids);
cwPsWrap(Triangles, cwTriangles);
cwPsWrap(TriStrip, cwTriStrip);
cwPsWrap(TriFan, cwTriFan);
/* There is no need to wrap AddTraps as far as we can tell. AddTraps can
* only be done on alpha-only pictures, and we won't be getting
* alpha-only window pictures, so there's no need to translate.
*/
}
void
cwFiniRender (ScreenPtr pScreen)
{
cwPsDecl (pScreen);
cwPsUnwrap(DestroyPicture);
cwPsUnwrap(ChangePicture);
cwPsUnwrap(ValidatePicture);
cwPsUnwrap(Composite);
cwPsUnwrap(CompositeRects);
cwPsUnwrap(Trapezoids);
cwPsUnwrap(Triangles);
cwPsUnwrap(TriStrip);
cwPsUnwrap(TriFan);
}