xenocara/xserver/miext/cw/cw_render.c

384 lines
12 KiB
C
Raw Normal View History

2006-11-26 11:13:41 -07:00
/*
* 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)
2006-11-26 11:13:41 -07:00
{
WindowPtr pWindow = (WindowPtr) pPicture->pDrawable;
PixmapPtr pPixmap = getCwPixmap(pWindow);
int error;
cwPicturePtr pPicturePrivate;
2006-11-26 11:13:41 -07:00
pPicturePrivate = malloc(sizeof(cwPictureRec));
2006-11-26 11:13:41 -07:00
if (!pPicturePrivate)
return NULL;
pPicturePrivate->pBackingPicture = CreatePicture(0, &pPixmap->drawable,
pPicture->pFormat,
0, 0, serverClient,
&error);
if (!pPicturePrivate->pBackingPicture) {
free(pPicturePrivate);
return NULL;
2006-11-26 11:13:41 -07:00
}
/*
* Ensure that this serial number does not match the window's
*/
pPicturePrivate->serialNumber = pPixmap->drawable.serialNumber;
pPicturePrivate->stateChanges = (1 << (CPLastBit + 1)) - 1;
2006-11-26 11:13:41 -07:00
setCwPicture(pPicture, pPicturePrivate);
return pPicturePrivate;
}
static void
cwDestroyPicturePrivate(PicturePtr pPicture)
2006-11-26 11:13:41 -07:00
{
cwPicturePrivate;
if (pPicturePrivate) {
if (pPicturePrivate->pBackingPicture)
FreePicture(pPicturePrivate->pBackingPicture, 0);
free(pPicturePrivate);
setCwPicture(pPicture, NULL);
2006-11-26 11:13:41 -07:00
}
}
static PicturePtr
cwGetBackingPicture(PicturePtr pPicture, int *x_off, int *y_off)
2006-11-26 11:13:41 -07:00
{
cwPicturePrivate;
if (pPicturePrivate) {
DrawablePtr pDrawable = pPicture->pDrawable;
WindowPtr pWindow = (WindowPtr) pDrawable;
PixmapPtr pPixmap = getCwPixmap(pWindow);
2006-11-26 11:13:41 -07:00
*x_off = pDrawable->x - pPixmap->screen_x;
*y_off = pDrawable->y - pPixmap->screen_y;
2006-11-26 11:13:41 -07:00
return pPicturePrivate->pBackingPicture;
2006-11-26 11:13:41 -07:00
}
else {
*x_off = *y_off = 0;
return pPicture;
2006-11-26 11:13:41 -07:00
}
}
2006-11-26 11:13:41 -07:00
static void
cwDestroyPicture(PicturePtr pPicture)
2006-11-26 11:13:41 -07:00
{
ScreenPtr pScreen = pPicture->pDrawable->pScreen;
2006-11-26 11:13:41 -07:00
cwPsDecl(pScreen);
2006-11-26 11:13:41 -07:00
cwPsUnwrap(DestroyPicture);
cwDestroyPicturePrivate(pPicture);
2006-11-26 11:13:41 -07:00
(*ps->DestroyPicture) (pPicture);
cwPsWrap(DestroyPicture, cwDestroyPicture);
}
static void
cwChangePicture(PicturePtr pPicture, Mask mask)
2006-11-26 11:13:41 -07:00
{
ScreenPtr pScreen = pPicture->pDrawable->pScreen;
2006-11-26 11:13:41 -07:00
cwPsDecl(pScreen);
cwPicturePtr pPicturePrivate = getCwPicture(pPicture);
2006-11-26 11:13:41 -07:00
cwPsUnwrap(ChangePicture);
(*ps->ChangePicture) (pPicture, mask);
if (pPicturePrivate)
pPicturePrivate->stateChanges |= mask;
2006-11-26 11:13:41 -07:00
cwPsWrap(ChangePicture, cwChangePicture);
}
static void
cwValidatePicture(PicturePtr pPicture, Mask mask)
2006-11-26 11:13:41 -07:00
{
DrawablePtr pDrawable = pPicture->pDrawable;
ScreenPtr pScreen = pDrawable->pScreen;
2006-11-26 11:13:41 -07:00
cwPsDecl(pScreen);
cwPicturePrivate;
2006-11-26 11:13:41 -07:00
cwPsUnwrap(ValidatePicture);
/*
* Must call ValidatePicture to ensure pPicture->pCompositeClip is valid
*/
(*ps->ValidatePicture) (pPicture, mask);
if (!cwDrawableIsRedirWindow(pDrawable)) {
if (pPicturePrivate)
cwDestroyPicturePrivate(pPicture);
2006-11-26 11:13:41 -07:00
}
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);
2006-11-26 11:13:41 -07:00
}
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)
2006-11-26 11:13:41 -07:00
{
ScreenPtr pScreen = pDstPicture->pDrawable->pScreen;
2006-11-26 11:13:41 -07:00
cwPsDecl(pScreen);
cwSrcPictureDecl;
cwMskPictureDecl;
cwDstPictureDecl;
2006-11-26 11:13:41 -07:00
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);
2006-11-26 11:13:41 -07:00
cwPsWrap(Composite, cwComposite);
}
static void
cwCompositeRects(CARD8 op,
PicturePtr pDstPicture,
xRenderColor * color, int nRect, xRectangle *rects)
2006-11-26 11:13:41 -07:00
{
ScreenPtr pScreen = pDstPicture->pDrawable->pScreen;
2006-11-26 11:13:41 -07:00
cwPsDecl(pScreen);
cwDstPictureDecl;
int i;
2006-11-26 11:13:41 -07:00
cwPsUnwrap(CompositeRects);
for (i = 0; i < nRect; i++) {
rects[i].x += dst_picture_x_off;
rects[i].y += dst_picture_y_off;
2006-11-26 11:13:41 -07:00
}
(*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)
2006-11-26 11:13:41 -07:00
{
ScreenPtr pScreen = pDstPicture->pDrawable->pScreen;
2006-11-26 11:13:41 -07:00
cwPsDecl(pScreen);
cwSrcPictureDecl;
cwDstPictureDecl;
int i;
2006-11-26 11:13:41 -07:00
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;
}
2006-11-26 11:13:41 -07:00
}
(*ps->Trapezoids) (op, pBackingSrcPicture, pBackingDstPicture, maskFormat,
xSrc + src_picture_x_off, ySrc + src_picture_y_off,
ntrap, traps);
2006-11-26 11:13:41 -07:00
cwPsWrap(Trapezoids, cwTrapezoids);
}
static void
cwTriangles(CARD8 op,
PicturePtr pSrcPicture,
PicturePtr pDstPicture,
PictFormatPtr maskFormat,
INT16 xSrc, INT16 ySrc, int ntri, xTriangle * tris)
2006-11-26 11:13:41 -07:00
{
ScreenPtr pScreen = pDstPicture->pDrawable->pScreen;
2006-11-26 11:13:41 -07:00
cwPsDecl(pScreen);
cwSrcPictureDecl;
cwDstPictureDecl;
int i;
2006-11-26 11:13:41 -07:00
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;
}
2006-11-26 11:13:41 -07:00
}
(*ps->Triangles) (op, pBackingSrcPicture, pBackingDstPicture, maskFormat,
xSrc + src_picture_x_off, ySrc + src_picture_y_off,
ntri, tris);
2006-11-26 11:13:41 -07:00
cwPsWrap(Triangles, cwTriangles);
}
void
cwInitializeRender(ScreenPtr pScreen)
2006-11-26 11:13:41 -07:00
{
cwPsDecl(pScreen);
2006-11-26 11:13:41 -07:00
cwPsWrap(DestroyPicture, cwDestroyPicture);
cwPsWrap(ChangePicture, cwChangePicture);
cwPsWrap(ValidatePicture, cwValidatePicture);
cwPsWrap(Composite, cwComposite);
cwPsWrap(CompositeRects, cwCompositeRects);
cwPsWrap(Trapezoids, cwTrapezoids);
cwPsWrap(Triangles, cwTriangles);
/* 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)
2006-11-26 11:13:41 -07:00
{
cwPsDecl(pScreen);
2006-11-26 11:13:41 -07:00
cwPsUnwrap(DestroyPicture);
cwPsUnwrap(ChangePicture);
cwPsUnwrap(ValidatePicture);
cwPsUnwrap(Composite);
cwPsUnwrap(CompositeRects);
cwPsUnwrap(Trapezoids);
cwPsUnwrap(Triangles);
}