From 9508a382f8a9f241dab097d921b6d290c1c3a776 Mon Sep 17 00:00:00 2001 From: Kaleb Keithley Date: Fri, 14 Nov 2003 16:48:57 +0000 Subject: Initial revision --- render/animcur.c | 400 ++++++++ render/filter.c | 263 ++++++ render/glyph.c | 416 +++++++++ render/glyphstr.h | 127 +++ render/miglyph.c | 239 +++++ render/miindex.c | 353 +++++++ render/mipict.c | 516 ++++++++++ render/mipict.h | 210 +++++ render/mirect.c | 181 ++++ render/mitrap.c | 196 ++++ render/mitri.c | 352 +++++++ render/picture.c | 1305 ++++++++++++++++++++++++++ render/picture.h | 228 +++++ render/picturestr.h | 501 ++++++++++ render/render.c | 2584 +++++++++++++++++++++++++++++++++++++++++++++++++++ 15 files changed, 7871 insertions(+) create mode 100644 render/animcur.c create mode 100644 render/filter.c create mode 100644 render/glyph.c create mode 100644 render/glyphstr.h create mode 100644 render/miglyph.c create mode 100644 render/miindex.c create mode 100644 render/mipict.c create mode 100644 render/mipict.h create mode 100644 render/mirect.c create mode 100644 render/mitrap.c create mode 100644 render/mitri.c create mode 100644 render/picture.c create mode 100644 render/picture.h create mode 100644 render/picturestr.h create mode 100644 render/render.c (limited to 'render') diff --git a/render/animcur.c b/render/animcur.c new file mode 100644 index 000000000..7a4e22d59 --- /dev/null +++ b/render/animcur.c @@ -0,0 +1,400 @@ +/* + * $XFree86: xc/programs/Xserver/render/animcur.c,v 1.5 2002/12/22 15:07:12 tsi Exp $ + * + * Copyright © 2002 Keith Packard, member of The XFree86 Project, Inc. + * + * 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 Keith Packard not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Keith Packard makes no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL KEITH PACKARD 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. + */ + +/* + * Animated cursors for X. Not specific to Render in any way, but + * stuck there because Render has the other cool cursor extension. + * Besides, everyone has Render. + * + * Implemented as a simple layer over the core cursor code; it + * creates composite cursors out of a set of static cursors and + * delta times between each image. + */ + +#include "X.h" +#include "Xmd.h" +#include "servermd.h" +#include "scrnintstr.h" +#include "dixstruct.h" +#include "cursorstr.h" +#include "dixfontstr.h" +#include "opaque.h" +#include "picturestr.h" + +typedef struct _AnimCurElt { + CursorPtr pCursor; /* cursor to show */ + CARD32 delay; /* in ms */ +} AnimCurElt; + +typedef struct _AnimCur { + int nelt; /* number of elements in the elts array */ + AnimCurElt *elts; /* actually allocated right after the structure */ +} AnimCurRec, *AnimCurPtr; + +typedef struct _AnimScrPriv { + CursorPtr pCursor; + int elt; + CARD32 time; + + CloseScreenProcPtr CloseScreen; + + ScreenBlockHandlerProcPtr BlockHandler; + + CursorLimitsProcPtr CursorLimits; + DisplayCursorProcPtr DisplayCursor; + SetCursorPositionProcPtr SetCursorPosition; + RealizeCursorProcPtr RealizeCursor; + UnrealizeCursorProcPtr UnrealizeCursor; + RecolorCursorProcPtr RecolorCursor; +} AnimCurScreenRec, *AnimCurScreenPtr; + +typedef struct _AnimCurState { + CursorPtr pCursor; + ScreenPtr pScreen; + int elt; + CARD32 time; +} AnimCurStateRec, *AnimCurStatePtr; + +static AnimCurStateRec animCurState; + +static unsigned char empty[4]; + +static CursorBits animCursorBits = { + empty, empty, 2, 1, 1, 0, 0, 1 +}; + +int AnimCurScreenPrivateIndex = -1; +int AnimCurGeneration; + +#define IsAnimCur(c) ((c)->bits == &animCursorBits) +#define GetAnimCur(c) ((AnimCurPtr) ((c) + 1)) +#define GetAnimCurScreen(s) ((AnimCurScreenPtr) ((s)->devPrivates[AnimCurScreenPrivateIndex].ptr)) +#define GetAnimCurScreenIfSet(s) ((AnimCurScreenPrivateIndex != -1) ? GetAnimCurScreen(s) : NULL) +#define SetAnimCurScreen(s,p) ((s)->devPrivates[AnimCurScreenPrivateIndex].ptr = (pointer) (p)) + +#define Wrap(as,s,elt,func) (((as)->elt = (s)->elt), (s)->elt = func) +#define Unwrap(as,s,elt) ((s)->elt = (as)->elt) + +static Bool +AnimCurDisplayCursor (ScreenPtr pScreen, + CursorPtr pCursor); + +static Bool +AnimCurSetCursorPosition (ScreenPtr pScreen, + int x, + int y, + Bool generateEvent); + +static Bool +AnimCurCloseScreen (int index, ScreenPtr pScreen) +{ + AnimCurScreenPtr as = GetAnimCurScreen(pScreen); + Bool ret; + + Unwrap(as, pScreen, CloseScreen); + + Unwrap(as, pScreen, BlockHandler); + + Unwrap(as, pScreen, CursorLimits); + Unwrap(as, pScreen, DisplayCursor); + Unwrap(as, pScreen, SetCursorPosition); + Unwrap(as, pScreen, RealizeCursor); + Unwrap(as, pScreen, UnrealizeCursor); + Unwrap(as, pScreen, RecolorCursor); + SetAnimCurScreen(pScreen,0); + ret = (*pScreen->CloseScreen) (index, pScreen); + xfree (as); + if (index == 0) + AnimCurScreenPrivateIndex = -1; + return ret; +} + +static void +AnimCurCursorLimits (ScreenPtr pScreen, + CursorPtr pCursor, + BoxPtr pHotBox, + BoxPtr pTopLeftBox) +{ + AnimCurScreenPtr as = GetAnimCurScreen(pScreen); + + Unwrap (as, pScreen, CursorLimits); + if (IsAnimCur(pCursor)) + { + AnimCurPtr ac = GetAnimCur(pCursor); + + (*pScreen->CursorLimits) (pScreen, ac->elts[0].pCursor, pHotBox, pTopLeftBox); + } + else + { + (*pScreen->CursorLimits) (pScreen, pCursor, pHotBox, pTopLeftBox); + } + Wrap (as, pScreen, CursorLimits, AnimCurCursorLimits); +} + +/* + * This has to be a screen block handler instead of a generic + * block handler so that it is well ordered with respect to the DRI + * block handler responsible for releasing the hardware to DRI clients + */ + +static void +AnimCurScreenBlockHandler (int screenNum, + pointer blockData, + pointer pTimeout, + pointer pReadmask) +{ + ScreenPtr pScreen = screenInfo.screens[screenNum]; + AnimCurScreenPtr as = GetAnimCurScreen(pScreen); + + if (pScreen == animCurState.pScreen) + { + CARD32 now = GetTimeInMillis (); + + if ((INT32) (now - animCurState.time) >= 0) + { + AnimCurPtr ac = GetAnimCur(animCurState.pCursor); + int elt = (animCurState.elt + 1) % ac->nelt; + DisplayCursorProcPtr DisplayCursor; + + /* + * Not a simple Unwrap/Wrap as this + * isn't called along the DisplayCursor + * wrapper chain. + */ + DisplayCursor = pScreen->DisplayCursor; + pScreen->DisplayCursor = as->DisplayCursor; + (void) (*pScreen->DisplayCursor) (pScreen, ac->elts[elt].pCursor); + as->DisplayCursor = pScreen->DisplayCursor; + pScreen->DisplayCursor = DisplayCursor; + + animCurState.elt = elt; + animCurState.time = now + ac->elts[elt].delay; + } + AdjustWaitForDelay (pTimeout, animCurState.time - now); + } + Unwrap (as, pScreen, BlockHandler); + (*pScreen->BlockHandler) (screenNum, blockData, pTimeout, pReadmask); + Wrap (as, pScreen, BlockHandler, AnimCurScreenBlockHandler); +} + +static Bool +AnimCurDisplayCursor (ScreenPtr pScreen, + CursorPtr pCursor) +{ + AnimCurScreenPtr as = GetAnimCurScreen(pScreen); + Bool ret; + + Unwrap (as, pScreen, DisplayCursor); + if (IsAnimCur(pCursor)) + { + if (pCursor != animCurState.pCursor) + { + AnimCurPtr ac = GetAnimCur(pCursor); + + ret = (*pScreen->DisplayCursor) (pScreen, ac->elts[0].pCursor); + if (ret) + { + animCurState.elt = 0; + animCurState.time = GetTimeInMillis () + ac->elts[0].delay; + animCurState.pCursor = pCursor; + animCurState.pScreen = pScreen; + } + } + else + ret = TRUE; + } + else + { + animCurState.pCursor = 0; + animCurState.pScreen = 0; + ret = (*pScreen->DisplayCursor) (pScreen, pCursor); + } + Wrap (as, pScreen, DisplayCursor, AnimCurDisplayCursor); + return ret; +} + +static Bool +AnimCurSetCursorPosition (ScreenPtr pScreen, + int x, + int y, + Bool generateEvent) +{ + AnimCurScreenPtr as = GetAnimCurScreen(pScreen); + Bool ret; + + Unwrap (as, pScreen, SetCursorPosition); + if (animCurState.pCursor) + animCurState.pScreen = pScreen; + ret = (*pScreen->SetCursorPosition) (pScreen, x, y, generateEvent); + Wrap (as, pScreen, SetCursorPosition, AnimCurSetCursorPosition); + return ret; +} + +static Bool +AnimCurRealizeCursor (ScreenPtr pScreen, + CursorPtr pCursor) +{ + AnimCurScreenPtr as = GetAnimCurScreen(pScreen); + Bool ret; + + Unwrap (as, pScreen, RealizeCursor); + if (IsAnimCur(pCursor)) + ret = TRUE; + else + ret = (*pScreen->RealizeCursor) (pScreen, pCursor); + Wrap (as, pScreen, RealizeCursor, AnimCurRealizeCursor); + return ret; +} + +static Bool +AnimCurUnrealizeCursor (ScreenPtr pScreen, + CursorPtr pCursor) +{ + AnimCurScreenPtr as = GetAnimCurScreen(pScreen); + Bool ret; + + Unwrap (as, pScreen, UnrealizeCursor); + if (IsAnimCur(pCursor)) + { + AnimCurPtr ac = GetAnimCur(pCursor); + int i; + + if (pScreen->myNum == 0) + for (i = 0; i < ac->nelt; i++) + FreeCursor (ac->elts[i].pCursor, 0); + ret = TRUE; + } + else + ret = (*pScreen->UnrealizeCursor) (pScreen, pCursor); + Wrap (as, pScreen, UnrealizeCursor, AnimCurUnrealizeCursor); + return ret; +} + +static void +AnimCurRecolorCursor (ScreenPtr pScreen, + CursorPtr pCursor, + Bool displayed) +{ + AnimCurScreenPtr as = GetAnimCurScreen(pScreen); + + Unwrap (as, pScreen, RecolorCursor); + if (IsAnimCur(pCursor)) + { + AnimCurPtr ac = GetAnimCur(pCursor); + int i; + + for (i = 0; i < ac->nelt; i++) + (*pScreen->RecolorCursor) (pScreen, ac->elts[i].pCursor, + displayed && + animCurState.elt == i); + } + else + (*pScreen->RecolorCursor) (pScreen, pCursor, displayed); + Wrap (as, pScreen, RecolorCursor, AnimCurRecolorCursor); +} + +Bool +AnimCurInit (ScreenPtr pScreen) +{ + AnimCurScreenPtr as; + + if (AnimCurGeneration != serverGeneration) + { + AnimCurScreenPrivateIndex = AllocateScreenPrivateIndex (); + if (AnimCurScreenPrivateIndex < 0) + return FALSE; + AnimCurGeneration = serverGeneration; + animCurState.pCursor = 0; + animCurState.pScreen = 0; + animCurState.elt = 0; + animCurState.time = 0; + } + as = (AnimCurScreenPtr) xalloc (sizeof (AnimCurScreenRec)); + if (!as) + return FALSE; + Wrap(as, pScreen, CloseScreen, AnimCurCloseScreen); + + Wrap(as, pScreen, BlockHandler, AnimCurScreenBlockHandler); + + Wrap(as, pScreen, CursorLimits, AnimCurCursorLimits); + Wrap(as, pScreen, DisplayCursor, AnimCurDisplayCursor); + Wrap(as, pScreen, SetCursorPosition, AnimCurSetCursorPosition); + Wrap(as, pScreen, RealizeCursor, AnimCurRealizeCursor); + Wrap(as, pScreen, UnrealizeCursor, AnimCurUnrealizeCursor); + Wrap(as, pScreen, RecolorCursor, AnimCurRecolorCursor); + SetAnimCurScreen(pScreen,as); + return TRUE; +} + +int +AnimCursorCreate (CursorPtr *cursors, CARD32 *deltas, int ncursor, CursorPtr *ppCursor) +{ + CursorPtr pCursor; + int i; + AnimCurPtr ac; + AnimCurElt *ae; + + for (i = 0; i < screenInfo.numScreens; i++) + if (!GetAnimCurScreenIfSet (screenInfo.screens[i])) + return BadImplementation; + + for (i = 0; i < ncursor; i++) + if (IsAnimCur (cursors[i])) + return BadMatch; + + pCursor = (CursorPtr) xalloc (sizeof (CursorRec) + + sizeof (AnimCurRec) + + ncursor * sizeof (AnimCurElt)); + if (!pCursor) + return BadAlloc; + pCursor->bits = &animCursorBits; + animCursorBits.refcnt++; + pCursor->refcnt = 1; + + pCursor->foreRed = cursors[0]->foreRed; + pCursor->foreGreen = cursors[0]->foreGreen; + pCursor->foreBlue = cursors[0]->foreBlue; + + pCursor->backRed = cursors[0]->backRed; + pCursor->backGreen = cursors[0]->backGreen; + pCursor->backBlue = cursors[0]->backBlue; + + /* + * Fill in the AnimCurRec + */ + ac = GetAnimCur (pCursor); + ac->nelt = ncursor; + ac->elts = (AnimCurElt *) (ac + 1); + ae = ac->elts; + + for (i = 0; i < ncursor; i++) + { + cursors[i]->refcnt++; + ac->elts[i].pCursor = cursors[i]; + ac->elts[i].delay = deltas[i]; + } + + *ppCursor = pCursor; + return Success; +} diff --git a/render/filter.c b/render/filter.c new file mode 100644 index 000000000..a2f7563cb --- /dev/null +++ b/render/filter.c @@ -0,0 +1,263 @@ +/* + * $XFree86: xc/programs/Xserver/render/filter.c,v 1.1 2002/09/26 02:56:52 keithp Exp $ + * + * Copyright © 2002 Keith Packard, member of The XFree86 Project, Inc. + * + * 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 Keith Packard not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Keith Packard makes no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL KEITH PACKARD 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. + */ + +#include "misc.h" +#include "scrnintstr.h" +#include "os.h" +#include "regionstr.h" +#include "validate.h" +#include "windowstr.h" +#include "input.h" +#include "resource.h" +#include "colormapst.h" +#include "cursorstr.h" +#include "dixstruct.h" +#include "gcstruct.h" +#include "servermd.h" +#include "picturestr.h" + +static char **filterNames; +static int nfilterNames; + +int +PictureGetFilterId (char *filter, int len, Bool makeit) +{ + int i; + char *name; + char **names; + + if (len < 0) + len = strlen (filter); + for (i = 0; i < nfilterNames; i++) + if (len == strlen (filterNames[i]) && + !strncmp (filterNames[i], filter, len)) + return i; + if (!makeit) + return -1; + name = xalloc (strlen (filter) + 1); + if (!name) + return -1; + strncpy (name, filter, len); + name[len] = '\0'; + if (filterNames) + names = xrealloc (filterNames, (nfilterNames + 1) * sizeof (char *)); + else + names = xalloc (sizeof (char *)); + if (!names) + { + xfree (name); + return -1; + } + filterNames = names; + i = nfilterNames++; + filterNames[i] = name; + return i; +} + +static Bool +PictureSetDefaultIds (void) +{ + /* careful here -- this list must match the #define values */ + + if (PictureGetFilterId (FilterNearest, -1, TRUE) != PictFilterNearest) + return FALSE; + if (PictureGetFilterId (FilterBilinear, -1, TRUE) != PictFilterBilinear) + return FALSE; + + if (PictureGetFilterId (FilterFast, -1, TRUE) != PictFilterFast) + return FALSE; + if (PictureGetFilterId (FilterGood, -1, TRUE) != PictFilterGood) + return FALSE; + if (PictureGetFilterId (FilterBest, -1, TRUE) != PictFilterBest) + return FALSE; + return TRUE; +} + +char * +PictureGetFilterName (int id) +{ + if (0 <= id && id < nfilterNames) + return filterNames[id]; + else + return 0; +} + +static void +PictureFreeFilterIds (void) +{ + int i; + + for (i = 0; i < nfilterNames; i++) + xfree (filterNames[i]); + xfree (filterNames); + nfilterNames = 0; + filterNames = 0; +} + +int +PictureAddFilter (ScreenPtr pScreen, char *filter, xFixed *params, int nparams) +{ + PictureScreenPtr ps = GetPictureScreen(pScreen); + int id = PictureGetFilterId (filter, -1, TRUE); + int i; + PictFilterPtr filters; + + if (id < 0) + return -1; + /* + * It's an error to attempt to reregister a filter + */ + for (i = 0; i < ps->nfilters; i++) + if (ps->filters[i].id == id) + return -1; + if (ps->filters) + filters = xrealloc (ps->filters, (ps->nfilters + 1) * sizeof (PictFilterRec)); + else + filters = xalloc (sizeof (PictFilterRec)); + if (!filters) + return -1; + ps->filters = filters; + i = ps->nfilters++; + ps->filters[i].name = PictureGetFilterName (id); + ps->filters[i].params = params; + ps->filters[i].nparams = nparams; + ps->filters[i].id = id; + return id; +} + +Bool +PictureSetFilterAlias (ScreenPtr pScreen, char *filter, char *alias) +{ + PictureScreenPtr ps = GetPictureScreen(pScreen); + int filter_id = PictureGetFilterId (filter, -1, FALSE); + int alias_id = PictureGetFilterId (alias, -1, TRUE); + int i; + + if (filter_id < 0 || alias_id < 0) + return FALSE; + for (i = 0; i < ps->nfilterAliases; i++) + if (ps->filterAliases[i].alias_id == alias_id) + break; + if (i == ps->nfilterAliases) + { + PictFilterAliasPtr aliases; + + if (ps->filterAliases) + aliases = xrealloc (ps->filterAliases, + (ps->nfilterAliases + 1) * + sizeof (PictFilterAliasRec)); + else + aliases = xalloc (sizeof (PictFilterAliasRec)); + if (!aliases) + return FALSE; + ps->filterAliases = aliases; + ps->filterAliases[i].alias = PictureGetFilterName (alias_id); + ps->filterAliases[i].alias_id = alias_id; + ps->nfilterAliases++; + } + ps->filterAliases[i].filter_id = filter_id; + return TRUE; +} + +PictFilterPtr +PictureFindFilter (ScreenPtr pScreen, char *name, int len) +{ + PictureScreenPtr ps = GetPictureScreen(pScreen); + int id = PictureGetFilterId (name, len, FALSE); + int i; + + if (id < 0) + return 0; + /* Check for an alias, allow them to recurse */ + for (i = 0; i < ps->nfilterAliases; i++) + if (ps->filterAliases[i].alias_id == id) + { + id = ps->filterAliases[i].filter_id; + i = 0; + } + /* find the filter */ + for (i = 0; i < ps->nfilters; i++) + if (ps->filters[i].id == id) + return &ps->filters[i]; + return 0; +} + +Bool +PictureSetDefaultFilters (ScreenPtr pScreen) +{ + if (!filterNames) + if (!PictureSetDefaultIds ()) + return FALSE; + if (PictureAddFilter (pScreen, FilterNearest, 0, 0) < 0) + return FALSE; + if (PictureAddFilter (pScreen, FilterBilinear, 0, 0) < 0) + return FALSE; + + if (!PictureSetFilterAlias (pScreen, FilterNearest, FilterFast)) + return FALSE; + if (!PictureSetFilterAlias (pScreen, FilterBilinear, FilterGood)) + return FALSE; + if (!PictureSetFilterAlias (pScreen, FilterBilinear, FilterBest)) + return FALSE; + return TRUE; +} + +void +PictureResetFilters (ScreenPtr pScreen) +{ + PictureScreenPtr ps = GetPictureScreen(pScreen); + + xfree (ps->filters); + xfree (ps->filterAliases); + PictureFreeFilterIds (); +} + +int +SetPictureFilter (PicturePtr pPicture, char *name, int len, xFixed *params, int nparams) +{ + ScreenPtr pScreen = pPicture->pDrawable->pScreen; + PictFilterPtr pFilter = PictureFindFilter (pScreen, name, len); + xFixed *new_params; + int i; + + if (!pFilter) + return BadName; + if (nparams > pFilter->nparams) + return BadMatch; + if (pFilter->nparams != pPicture->filter_nparams) + { + new_params = xalloc (pFilter->nparams * sizeof (xFixed)); + if (!new_params) + return BadAlloc; + xfree (pPicture->filter_params); + pPicture->filter_params = new_params; + pPicture->filter_nparams = pFilter->nparams; + } + for (i = 0; i < nparams; i++) + pPicture->filter_params[i] = params[i]; + for (; i < pFilter->nparams; i++) + pPicture->filter_params[i] = pFilter->params[i]; + pPicture->filter = pFilter->id; + return Success; +} diff --git a/render/glyph.c b/render/glyph.c new file mode 100644 index 000000000..b4f08c223 --- /dev/null +++ b/render/glyph.c @@ -0,0 +1,416 @@ +/* + * $XFree86: xc/programs/Xserver/render/glyph.c,v 1.6 2001/10/28 03:34:19 tsi Exp $ + * + * Copyright © 2000 SuSE, Inc. + * + * 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 SuSE not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. SuSE makes no representations about the + * suitability of this software for any purpose. It is provided "as is" + * without express or implied warranty. + * + * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE + * 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. + * + * Author: Keith Packard, SuSE, Inc. + */ + +#include "misc.h" +#include "scrnintstr.h" +#include "os.h" +#include "regionstr.h" +#include "validate.h" +#include "windowstr.h" +#include "input.h" +#include "resource.h" +#include "colormapst.h" +#include "cursorstr.h" +#include "dixstruct.h" +#include "gcstruct.h" +#include "servermd.h" +#include "picturestr.h" +#include "glyphstr.h" + +/* + * From Knuth -- a good choice for hash/rehash values is p, p-2 where + * p and p-2 are both prime. These tables are sized to have an extra 10% + * free to avoid exponential performance degradation as the hash table fills + */ +static GlyphHashSetRec glyphHashSets[] = { + { 32, 43, 41 }, + { 64, 73, 71 }, + { 128, 151, 149 }, + { 256, 283, 281 }, + { 512, 571, 569 }, + { 1024, 1153, 1151 }, + { 2048, 2269, 2267 }, + { 4096, 4519, 4517 }, + { 8192, 9013, 9011 }, + { 16384, 18043, 18041 }, + { 32768, 36109, 36107 }, + { 65536, 72091, 72089 }, + { 131072, 144409, 144407 }, + { 262144, 288361, 288359 }, + { 524288, 576883, 576881 }, + { 1048576, 1153459, 1153457 }, + { 2097152, 2307163, 2307161 }, + { 4194304, 4613893, 4613891 }, + { 8388608, 9227641, 9227639 }, + { 16777216, 18455029, 18455027 }, + { 33554432, 36911011, 36911009 }, + { 67108864, 73819861, 73819859 }, + { 134217728, 147639589, 147639587 }, + { 268435456, 295279081, 295279079 }, + { 536870912, 590559793, 590559791 } +}; + +#define NGLYPHHASHSETS (sizeof(glyphHashSets)/sizeof(glyphHashSets[0])) + +const CARD8 glyphDepths[GlyphFormatNum] = { 1, 4, 8, 16, 32 }; + +GlyphHashRec globalGlyphs[GlyphFormatNum]; + +GlyphHashSetPtr +FindGlyphHashSet (CARD32 filled) +{ + int i; + + for (i = 0; i < NGLYPHHASHSETS; i++) + if (glyphHashSets[i].entries >= filled) + return &glyphHashSets[i]; + return 0; +} + +Bool +GlyphInit (ScreenPtr pScreen) +{ + return TRUE; +} + +GlyphRefPtr +FindGlyphRef (GlyphHashPtr hash, CARD32 signature, Bool match, GlyphPtr compare) +{ + CARD32 elt, step, s; + GlyphPtr glyph; + GlyphRefPtr table, gr, del; + CARD32 tableSize = hash->hashSet->size; + + table = hash->table; + elt = signature % tableSize; + step = 0; + del = 0; + for (;;) + { + gr = &table[elt]; + s = gr->signature; + glyph = gr->glyph; + if (!glyph) + { + if (del) + gr = del; + break; + } + if (glyph == DeletedGlyph) + { + if (!del) + del = gr; + else if (gr == del) + break; + } + else if (s == signature && + (!match || + memcmp (&compare->info, &glyph->info, compare->size) == 0)) + { + break; + } + if (!step) + { + step = signature % hash->hashSet->rehash; + if (!step) + step = 1; + } + elt += step; + if (elt >= tableSize) + elt -= tableSize; + } + return gr; +} + +CARD32 +HashGlyph (GlyphPtr glyph) +{ + CARD32 *bits = (CARD32 *) &(glyph->info); + CARD32 hash; + int n = glyph->size / sizeof (CARD32); + + hash = 0; + while (n--) + hash ^= *bits++; + return hash; +} + +#ifdef CHECK_DUPLICATES +void +DuplicateRef (GlyphPtr glyph, char *where) +{ + ErrorF ("Duplicate Glyph 0x%x from %s\n", glyph, where); +} + +void +CheckDuplicates (GlyphHashPtr hash, char *where) +{ + GlyphPtr g; + int i, j; + + for (i = 0; i < hash->hashSet->size; i++) + { + g = hash->table[i].glyph; + if (!g || g == DeletedGlyph) + continue; + for (j = i + 1; j < hash->hashSet->size; j++) + if (hash->table[j].glyph == g) + DuplicateRef (g, where); + } +} +#else +#define CheckDuplicates(a,b) +#define DuplicateRef(a,b) +#endif + +void +FreeGlyph (GlyphPtr glyph, int format) +{ + CheckDuplicates (&globalGlyphs[format], "FreeGlyph"); + if (--glyph->refcnt == 0) + { + GlyphRefPtr gr; + int i; + int first; + + first = -1; + for (i = 0; i < globalGlyphs[format].hashSet->size; i++) + if (globalGlyphs[format].table[i].glyph == glyph) + { + if (first != -1) + DuplicateRef (glyph, "FreeGlyph check"); + first = i; + } + + gr = FindGlyphRef (&globalGlyphs[format], + HashGlyph (glyph), TRUE, glyph); + if (gr - globalGlyphs[format].table != first) + DuplicateRef (glyph, "Found wrong one"); + if (gr->glyph && gr->glyph != DeletedGlyph) + { + gr->glyph = DeletedGlyph; + gr->signature = 0; + globalGlyphs[format].tableEntries--; + } + xfree (glyph); + } +} + +void +AddGlyph (GlyphSetPtr glyphSet, GlyphPtr glyph, Glyph id) +{ + GlyphRefPtr gr; + CARD32 hash; + + CheckDuplicates (&globalGlyphs[glyphSet->fdepth], "AddGlyph top global"); + /* Locate existing matching glyph */ + hash = HashGlyph (glyph); + gr = FindGlyphRef (&globalGlyphs[glyphSet->fdepth], hash, TRUE, glyph); + if (gr->glyph && gr->glyph != DeletedGlyph) + { + xfree (glyph); + glyph = gr->glyph; + } + else + { + gr->glyph = glyph; + gr->signature = hash; + globalGlyphs[glyphSet->fdepth].tableEntries++; + } + + /* Insert/replace glyphset value */ + gr = FindGlyphRef (&glyphSet->hash, id, FALSE, 0); + ++glyph->refcnt; + if (gr->glyph && gr->glyph != DeletedGlyph) + FreeGlyph (gr->glyph, glyphSet->fdepth); + else + glyphSet->hash.tableEntries++; + gr->glyph = glyph; + gr->signature = id; + CheckDuplicates (&globalGlyphs[glyphSet->fdepth], "AddGlyph bottom"); +} + +Bool +DeleteGlyph (GlyphSetPtr glyphSet, Glyph id) +{ + GlyphRefPtr gr; + GlyphPtr glyph; + + gr = FindGlyphRef (&glyphSet->hash, id, FALSE, 0); + glyph = gr->glyph; + if (glyph && glyph != DeletedGlyph) + { + gr->glyph = DeletedGlyph; + glyphSet->hash.tableEntries--; + FreeGlyph (glyph, glyphSet->fdepth); + return TRUE; + } + return FALSE; +} + +GlyphPtr +FindGlyph (GlyphSetPtr glyphSet, Glyph id) +{ + GlyphPtr glyph; + + glyph = FindGlyphRef (&glyphSet->hash, id, FALSE, 0)->glyph; + if (glyph == DeletedGlyph) + glyph = 0; + return glyph; +} + +GlyphPtr +AllocateGlyph (xGlyphInfo *gi, int fdepth) +{ + int size; + GlyphPtr glyph; + + size = gi->height * PixmapBytePad (gi->width, glyphDepths[fdepth]); + glyph = (GlyphPtr) xalloc (size + sizeof (GlyphRec)); + if (!glyph) + return 0; + glyph->refcnt = 0; + glyph->size = size + sizeof (xGlyphInfo); + glyph->info = *gi; + return glyph; +} + +Bool +AllocateGlyphHash (GlyphHashPtr hash, GlyphHashSetPtr hashSet) +{ + hash->table = (GlyphRefPtr) xalloc (hashSet->size * sizeof (GlyphRefRec)); + if (!hash->table) + return FALSE; + memset (hash->table, 0, hashSet->size * sizeof (GlyphRefRec)); + hash->hashSet = hashSet; + hash->tableEntries = 0; + return TRUE; +} + +Bool +ResizeGlyphHash (GlyphHashPtr hash, CARD32 change, Bool global) +{ + CARD32 tableEntries; + GlyphHashSetPtr hashSet; + GlyphHashRec newHash; + GlyphRefPtr gr; + GlyphPtr glyph; + int i; + int oldSize; + CARD32 s; + + tableEntries = hash->tableEntries + change; + hashSet = FindGlyphHashSet (tableEntries); + if (hashSet == hash->hashSet) + return TRUE; + if (global) + CheckDuplicates (hash, "ResizeGlyphHash top"); + if (!AllocateGlyphHash (&newHash, hashSet)) + return FALSE; + if (hash->table) + { + oldSize = hash->hashSet->size; + for (i = 0; i < oldSize; i++) + { + glyph = hash->table[i].glyph; + if (glyph && glyph != DeletedGlyph) + { + s = hash->table[i].signature; + gr = FindGlyphRef (&newHash, s, global, glyph); + gr->signature = s; + gr->glyph = glyph; + ++newHash.tableEntries; + } + } + xfree (hash->table); + } + *hash = newHash; + if (global) + CheckDuplicates (hash, "ResizeGlyphHash bottom"); + return TRUE; +} + +Bool +ResizeGlyphSet (GlyphSetPtr glyphSet, CARD32 change) +{ + return (ResizeGlyphHash (&glyphSet->hash, change, FALSE) && + ResizeGlyphHash (&globalGlyphs[glyphSet->fdepth], change, TRUE)); +} + +GlyphSetPtr +AllocateGlyphSet (int fdepth, PictFormatPtr format) +{ + GlyphSetPtr glyphSet; + + if (!globalGlyphs[fdepth].hashSet) + { + if (!AllocateGlyphHash (&globalGlyphs[fdepth], &glyphHashSets[0])) + return FALSE; + } + glyphSet = xalloc (sizeof (GlyphSetRec)); + if (!glyphSet) + return FALSE; + if (!AllocateGlyphHash (&glyphSet->hash, &glyphHashSets[0])) + { + xfree (glyphSet); + return FALSE; + } + glyphSet->refcnt = 1; + glyphSet->fdepth = fdepth; + glyphSet->format = format; + return glyphSet; +} + +int +FreeGlyphSet (pointer value, + XID gid) +{ + GlyphSetPtr glyphSet = (GlyphSetPtr) value; + + if (--glyphSet->refcnt == 0) + { + CARD32 i, tableSize = glyphSet->hash.hashSet->size; + GlyphRefPtr table = glyphSet->hash.table; + GlyphPtr glyph; + + for (i = 0; i < tableSize; i++) + { + glyph = table[i].glyph; + if (glyph && glyph != DeletedGlyph) + FreeGlyph (glyph, glyphSet->fdepth); + } + if (!globalGlyphs[glyphSet->fdepth].tableEntries) + { + xfree (globalGlyphs[glyphSet->fdepth].table); + globalGlyphs[glyphSet->fdepth].table = 0; + globalGlyphs[glyphSet->fdepth].hashSet = 0; + } + else + ResizeGlyphHash (&globalGlyphs[glyphSet->fdepth], 0, TRUE); + xfree (table); + xfree (glyphSet); + } + return Success; +} diff --git a/render/glyphstr.h b/render/glyphstr.h new file mode 100644 index 000000000..99f55e3eb --- /dev/null +++ b/render/glyphstr.h @@ -0,0 +1,127 @@ +/* + * $XFree86: xc/programs/Xserver/render/glyphstr.h,v 1.4 2001/01/21 21:19:39 tsi Exp $ + * + * Copyright © 2000 SuSE, Inc. + * + * 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 SuSE not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. SuSE makes no representations about the + * suitability of this software for any purpose. It is provided "as is" + * without express or implied warranty. + * + * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE + * 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. + * + * Author: Keith Packard, SuSE, Inc. + */ + +#ifndef _GLYPHSTR_H_ +#define _GLYPHSTR_H_ + +#include "renderproto.h" +#include "picture.h" +#include "screenint.h" + +#define GlyphFormat1 0 +#define GlyphFormat4 1 +#define GlyphFormat8 2 +#define GlyphFormat16 3 +#define GlyphFormat32 4 +#define GlyphFormatNum 5 + +typedef struct _Glyph { + CARD32 refcnt; + CARD32 size; /* info + bitmap */ + xGlyphInfo info; + /* bits follow */ +} GlyphRec, *GlyphPtr; + +typedef struct _GlyphRef { + CARD32 signature; + GlyphPtr glyph; +} GlyphRefRec, *GlyphRefPtr; + +#define DeletedGlyph ((GlyphPtr) 1) + +typedef struct _GlyphHashSet { + CARD32 entries; + CARD32 size; + CARD32 rehash; +} GlyphHashSetRec, *GlyphHashSetPtr; + +typedef struct _GlyphHash { + GlyphRefPtr table; + GlyphHashSetPtr hashSet; + CARD32 tableEntries; +} GlyphHashRec, *GlyphHashPtr; + +typedef struct _GlyphSet { + CARD32 refcnt; + PictFormatPtr format; + int fdepth; + GlyphHashRec hash; +} GlyphSetRec, *GlyphSetPtr; + +typedef struct _GlyphList { + INT16 xOff; + INT16 yOff; + CARD8 len; + PictFormatPtr format; +} GlyphListRec, *GlyphListPtr; + +extern GlyphHashRec globalGlyphs[GlyphFormatNum]; + +GlyphHashSetPtr +FindGlyphHashSet (CARD32 filled); + +Bool +GlyphInit (ScreenPtr pScreen); + +GlyphRefPtr +FindGlyphRef (GlyphHashPtr hash, CARD32 signature, Bool match, GlyphPtr compare); + +CARD32 +HashGlyph (GlyphPtr glyph); + +void +FreeGlyph (GlyphPtr glyph, int format); + +void +AddGlyph (GlyphSetPtr glyphSet, GlyphPtr glyph, Glyph id); + +Bool +DeleteGlyph (GlyphSetPtr glyphSet, Glyph id); + +GlyphPtr +FindGlyph (GlyphSetPtr glyphSet, Glyph id); + +GlyphPtr +AllocateGlyph (xGlyphInfo *gi, int format); + +Bool +AllocateGlyphHash (GlyphHashPtr hash, GlyphHashSetPtr hashSet); + +Bool +ResizeGlyphHash (GlyphHashPtr hash, CARD32 change, Bool global); + +Bool +ResizeGlyphSet (GlyphSetPtr glyphSet, CARD32 change); + +GlyphSetPtr +AllocateGlyphSet (int fdepth, PictFormatPtr format); + +int +FreeGlyphSet (pointer value, + XID gid); + + + +#endif /* _GLYPHSTR_H_ */ diff --git a/render/miglyph.c b/render/miglyph.c new file mode 100644 index 000000000..00b6764d6 --- /dev/null +++ b/render/miglyph.c @@ -0,0 +1,239 @@ +/* + * $XFree86: xc/programs/Xserver/render/miglyph.c,v 1.6 2000/12/05 03:13:31 keithp Exp $ + * + * Copyright © 2000 SuSE, Inc. + * + * 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 SuSE not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. SuSE makes no representations about the + * suitability of this software for any purpose. It is provided "as is" + * without express or implied warranty. + * + * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE + * 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. + * + * Author: Keith Packard, SuSE, Inc. + */ + +#include "scrnintstr.h" +#include "gcstruct.h" +#include "pixmapstr.h" +#include "windowstr.h" +#include "mi.h" +#include "picturestr.h" +#include "mipict.h" + +void +miGlyphExtents (int nlist, + GlyphListPtr list, + GlyphPtr *glyphs, + BoxPtr extents) +{ + int x1, x2, y1, y2; + int n; + GlyphPtr glyph; + int x, y; + + x = 0; + y = 0; + extents->x1 = MAXSHORT; + extents->x2 = MINSHORT; + extents->y1 = MAXSHORT; + extents->y2 = MINSHORT; + while (nlist--) + { + x += list->xOff; + y += list->yOff; + n = list->len; + list++; + while (n--) + { + glyph = *glyphs++; + x1 = x - glyph->info.x; + if (x1 < MINSHORT) + x1 = MINSHORT; + y1 = y - glyph->info.y; + if (y1 < MINSHORT) + y1 = MINSHORT; + x2 = x1 + glyph->info.width; + if (x2 > MAXSHORT) + x2 = MAXSHORT; + y2 = y1 + glyph->info.height; + if (y2 > MAXSHORT) + y2 = MAXSHORT; + if (x1 < extents->x1) + extents->x1 = x1; + if (x2 > extents->x2) + extents->x2 = x2; + if (y1 < extents->y1) + extents->y1 = y1; + if (y2 > extents->y2) + extents->y2 = y2; + x += glyph->info.xOff; + y += glyph->info.yOff; + } + } +} + +#define NeedsComponent(f) (PICT_FORMAT_A(f) != 0 && PICT_FORMAT_RGB(f) != 0) + +void +miGlyphs (CARD8 op, + PicturePtr pSrc, + PicturePtr pDst, + PictFormatPtr maskFormat, + INT16 xSrc, + INT16 ySrc, + int nlist, + GlyphListPtr list, + GlyphPtr *glyphs) +{ + PixmapPtr pPixmap = 0; + PicturePtr pPicture; + PixmapPtr pMaskPixmap = 0; + PicturePtr pMask; + ScreenPtr pScreen = pDst->pDrawable->pScreen; + int width = 0, height = 0; + int x, y; + int xDst = list->xOff, yDst = list->yOff; + int n; + GlyphPtr glyph; + int error; + BoxRec extents; + CARD32 component_alpha; + + if (maskFormat) + { + GCPtr pGC; + xRectangle rect; + + miGlyphExtents (nlist, list, glyphs, &extents); + + if (extents.x2 <= extents.x1 || extents.y2 <= extents.y1) + return; + width = extents.x2 - extents.x1; + height = extents.y2 - extents.y1; + pMaskPixmap = (*pScreen->CreatePixmap) (pScreen, width, height, maskFormat->depth); + if (!pMaskPixmap) + return; + component_alpha = NeedsComponent(maskFormat->format); + pMask = CreatePicture (0, &pMaskPixmap->drawable, + maskFormat, CPComponentAlpha, &component_alpha, + serverClient, &error); + if (!pMask) + { + (*pScreen->DestroyPixmap) (pMaskPixmap); + return; + } + pGC = GetScratchGC (pMaskPixmap->drawable.depth, pScreen); + ValidateGC (&pMaskPixmap->drawable, pGC); + rect.x = 0; + rect.y = 0; + rect.width = width; + rect.height = height; + (*pGC->ops->PolyFillRect) (&pMaskPixmap->drawable, pGC, 1, &rect); + FreeScratchGC (pGC); + x = -extents.x1; + y = -extents.y1; + } + else + { + pMask = pDst; + x = 0; + y = 0; + } + pPicture = 0; + while (nlist--) + { + x += list->xOff; + y += list->yOff; + n = list->len; + while (n--) + { + glyph = *glyphs++; + if (!pPicture) + { + pPixmap = GetScratchPixmapHeader (pScreen, glyph->info.width, glyph->info.height, + list->format->depth, + list->format->depth, + 0, (pointer) (glyph + 1)); + if (!pPixmap) + return; + component_alpha = NeedsComponent(list->format->format); + pPicture = CreatePicture (0, &pPixmap->drawable, list->format, + CPComponentAlpha, &component_alpha, + serverClient, &error); + if (!pPicture) + { + FreeScratchPixmapHeader (pPixmap); + return; + } + } + (*pScreen->ModifyPixmapHeader) (pPixmap, + glyph->info.width, glyph->info.height, + 0, 0, -1, (pointer) (glyph + 1)); + pPixmap->drawable.serialNumber = NEXT_SERIAL_NUMBER; + if (maskFormat) + { + CompositePicture (PictOpAdd, + pPicture, + None, + pMask, + 0, 0, + 0, 0, + x - glyph->info.x, + y - glyph->info.y, + glyph->info.width, + glyph->info.height); + } + else + { + CompositePicture (op, + pSrc, + pPicture, + pDst, + xSrc + (x - glyph->info.x) - xDst, + ySrc + (y - glyph->info.y) - yDst, + 0, 0, + x - glyph->info.x, + y - glyph->info.y, + glyph->info.width, + glyph->info.height); + } + x += glyph->info.xOff; + y += glyph->info.yOff; + } + list++; + if (pPicture) + { + FreeScratchPixmapHeader (pPixmap); + FreePicture ((pointer) pPicture, 0); + pPicture = 0; + pPixmap = 0; + } + } + if (maskFormat) + { + x = extents.x1; + y = extents.y1; + CompositePicture (op, + pSrc, + pMask, + pDst, + xSrc + x - xDst, + ySrc + y - yDst, + 0, 0, + x, y, + width, height); + FreePicture ((pointer) pMask, (XID) 0); + (*pScreen->DestroyPixmap) (pMaskPixmap); + } +} diff --git a/render/miindex.c b/render/miindex.c new file mode 100644 index 000000000..739348273 --- /dev/null +++ b/render/miindex.c @@ -0,0 +1,353 @@ +/* + * $XFree86: xc/programs/Xserver/render/miindex.c,v 1.8 2002/11/06 22:45:36 keithp Exp $ + * + * Copyright © 2001 Keith Packard, member of The XFree86 Project, Inc. + * + * 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 Keith Packard not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Keith Packard makes no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL KEITH PACKARD 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. + */ + +#ifndef _MIINDEX_H_ +#define _MIINDEX_H_ + +#include "scrnintstr.h" +#include "gcstruct.h" +#include "pixmapstr.h" +#include "windowstr.h" +#include "mi.h" +#include "picturestr.h" +#include "mipict.h" +#include "colormapst.h" + +#define NUM_CUBE_LEVELS 4 +#define NUM_GRAY_LEVELS 13 + +static Bool +miBuildRenderColormap (ColormapPtr pColormap, Pixel *pixels, int *nump) +{ + int r, g, b; + unsigned short red, green, blue; + Pixel pixel; + Bool used[MI_MAX_INDEXED]; + int needed; + int policy; + int cube, gray; + int i, n; + + if (pColormap->mid != pColormap->pScreen->defColormap) + { + policy = PictureCmapPolicyAll; + } + else + { + int avail = pColormap->pVisual->ColormapEntries; + policy = PictureCmapPolicy; + if (policy == PictureCmapPolicyDefault) + { + if (avail >= 256 && (pColormap->pVisual->class|DynamicClass) == PseudoColor) + policy = PictureCmapPolicyColor; + else if (avail >= 64) + policy = PictureCmapPolicyGray; + else + policy = PictureCmapPolicyMono; + } + } + /* + * Make sure enough cells are free for the chosen policy + */ + for (;;) + { + switch (policy) { + case PictureCmapPolicyAll: + needed = 0; + break; + case PictureCmapPolicyColor: + needed = 71; + break; + case PictureCmapPolicyGray: + needed = 11; + break; + case PictureCmapPolicyMono: + default: + needed = 0; + break; + } + if (needed <= pColormap->freeRed) + break; + policy--; + } + + /* + * Compute size of cube and gray ramps + */ + cube = gray = 0; + switch (policy) { + case PictureCmapPolicyAll: + /* + * Allocate as big a cube as possible + */ + if ((pColormap->pVisual->class|DynamicClass) == PseudoColor) + { + for (cube = 1; cube * cube * cube < pColormap->pVisual->ColormapEntries; cube++) + ; + cube--; + if (cube == 1) + cube = 0; + } + else + cube = 0; + /* + * Figure out how many gray levels to use so that they + * line up neatly with the cube + */ + if (cube) + { + needed = pColormap->pVisual->ColormapEntries - (cube*cube*cube); + /* levels to fill in with */ + gray = needed / (cube - 1); + /* total levels */ + gray = (gray + 1) * (cube - 1) + 1; + } + else + gray = pColormap->pVisual->ColormapEntries; + break; + + case PictureCmapPolicyColor: + cube = NUM_CUBE_LEVELS; + /* fall through ... */ + case PictureCmapPolicyGray: + gray = NUM_GRAY_LEVELS; + break; + case PictureCmapPolicyMono: + default: + gray = 2; + break; + } + + memset (used, '\0', pColormap->pVisual->ColormapEntries * sizeof (Bool)); + for (r = 0; r < cube; r++) + for (g = 0; g < cube; g++) + for (b = 0; b < cube; b++) + { + red = (r * 65535 + (cube-1)/2) / (cube - 1); + green = (g * 65535 + (cube-1)/2) / (cube - 1); + blue = (b * 65535 + (cube-1)/2) / (cube - 1); + if (AllocColor (pColormap, &red, &green, + &blue, &pixel, 0) != Success) + return FALSE; + used[pixel] = TRUE; + } + for (g = 0; g < gray; g++) + { + red = green = blue = (g * 65535 + (gray-1)/2) / (gray - 1); + if (AllocColor (pColormap, &red, &green, &blue, &pixel, 0) != Success) + return FALSE; + used[pixel] = TRUE; + } + n = 0; + for (i = 0; i < pColormap->pVisual->ColormapEntries; i++) + if (used[i]) + pixels[n++] = i; + + *nump = n; + + return TRUE; +} + +/* 0 <= red, green, blue < 32 */ +static Pixel +FindBestColor (miIndexedPtr pIndexed, Pixel *pixels, int num, + int red, int green, int blue) +{ + Pixel best = pixels[0]; + int bestDist = 1 << 30; + int dist; + int dr, dg, db; + while (num--) + { + Pixel pixel = *pixels++; + CARD32 v = pIndexed->rgba[pixel]; + + dr = ((v >> 19) & 0x1f); + dg = ((v >> 11) & 0x1f); + db = ((v >> 3) & 0x1f); + dr = dr - red; + dg = dg - green; + db = db - blue; + dist = dr * dr + dg * dg + db * db; + if (dist < bestDist) + { + bestDist = dist; + best = pixel; + } + } + return best; +} + +/* 0 <= gray < 32768 */ +static Pixel +FindBestGray (miIndexedPtr pIndexed, Pixel *pixels, int num, int gray) +{ + Pixel best = pixels[0]; + int bestDist = 1 << 30; + int dist; + int dr; + int r; + + while (num--) + { + Pixel pixel = *pixels++; + CARD32 v = pIndexed->rgba[pixel]; + + r = v & 0xff; + r = r | (r << 8); + dr = gray - (r >> 1); + dist = dr * dr; + if (dist < bestDist) + { + bestDist = dist; + best = pixel; + } + } + return best; +} + +Bool +miInitIndexed (ScreenPtr pScreen, + PictFormatPtr pFormat) +{ + ColormapPtr pColormap = pFormat->index.pColormap; + VisualPtr pVisual = pColormap->pVisual; + miIndexedPtr pIndexed; + Pixel pixels[MI_MAX_INDEXED]; + xrgb rgb[MI_MAX_INDEXED]; + int num; + int i; + Pixel p, r, g, b; + + if (pVisual->ColormapEntries > MI_MAX_INDEXED) + return FALSE; + + if (pVisual->class & DynamicClass) + { + if (!miBuildRenderColormap (pColormap, pixels, &num)) + return FALSE; + } + else + { + num = pVisual->ColormapEntries; + for (p = 0; p < num; p++) + pixels[p] = p; + } + + pIndexed = xalloc (sizeof (miIndexedRec)); + if (!pIndexed) + return FALSE; + + pFormat->index.nvalues = num; + pFormat->index.pValues = xalloc (num * sizeof (xIndexValue)); + if (!pFormat->index.pValues) + { + xfree (pIndexed); + return FALSE; + } + + + /* + * Build mapping from pixel value to ARGB + */ + QueryColors (pColormap, num, pixels, rgb); + for (i = 0; i < num; i++) + { + p = pixels[i]; + pFormat->index.pValues[i].pixel = p; + pFormat->index.pValues[i].red = rgb[i].red; + pFormat->index.pValues[i].green = rgb[i].green; + pFormat->index.pValues[i].blue = rgb[i].blue; + pFormat->index.pValues[i].alpha = 0xffff; + pIndexed->rgba[p] = (0xff000000 | + ((rgb[i].red & 0xff00) << 8) | + ((rgb[i].green & 0xff00) ) | + ((rgb[i].blue & 0xff00) >> 8)); + } + + /* + * Build mapping from RGB to pixel value. This could probably be + * done a bit quicker... + */ + switch (pVisual->class | DynamicClass) { + case GrayScale: + pIndexed->color = FALSE; + for (r = 0; r < 32768; r++) + pIndexed->ent[r] = FindBestGray (pIndexed, pixels, num, r); + break; + case PseudoColor: + pIndexed->color = TRUE; + p = 0; + for (r = 0; r < 32; r++) + for (g = 0; g < 32; g++) + for (b = 0; b < 32; b++) + { + pIndexed->ent[p] = FindBestColor (pIndexed, pixels, num, + r, g, b); + p++; + } + break; + } + pFormat->index.devPrivate = pIndexed; + return TRUE; +} + +void +miCloseIndexed (ScreenPtr pScreen, + PictFormatPtr pFormat) +{ + if (pFormat->index.devPrivate) + { + xfree (pFormat->index.devPrivate); + pFormat->index.devPrivate = 0; + } + if (pFormat->index.pValues) + { + xfree (pFormat->index.pValues); + pFormat->index.pValues = 0; + } +} + +void +miUpdateIndexed (ScreenPtr pScreen, + PictFormatPtr pFormat, + int ndef, + xColorItem *pdef) +{ + miIndexedPtr pIndexed = pFormat->index.devPrivate; + + if (pIndexed) + { + while (ndef--) + { + pIndexed->rgba[pdef->pixel] = (0xff000000 | + ((pdef->red & 0xff00) << 8) | + ((pdef->green & 0xff00) ) | + ((pdef->blue & 0xff00) >> 8)); + pdef++; + } + } +} + +#endif /* _MIINDEX_H_ */ diff --git a/render/mipict.c b/render/mipict.c new file mode 100644 index 000000000..3971a8f6e --- /dev/null +++ b/render/mipict.c @@ -0,0 +1,516 @@ +/* + * $XFree86: xc/programs/Xserver/render/mipict.c,v 1.14 2002/11/06 22:45:36 keithp Exp $ + * + * Copyright © 1999 Keith Packard + * + * 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 Keith Packard not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Keith Packard makes no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL KEITH PACKARD 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. + */ + +#include "scrnintstr.h" +#include "gcstruct.h" +#include "pixmapstr.h" +#include "windowstr.h" +#include "mi.h" +#include "picturestr.h" +#include "mipict.h" + +#ifndef __GNUC__ +#define __inline +#endif + +int +miCreatePicture (PicturePtr pPicture) +{ + return Success; +} + +void +miDestroyPicture (PicturePtr pPicture) +{ + if (pPicture->freeCompClip) + REGION_DESTROY(pPicture->pDrawable->pScreen, pPicture->pCompositeClip); +} + +void +miDestroyPictureClip (PicturePtr pPicture) +{ + switch (pPicture->clientClipType) { + case CT_NONE: + return; + case CT_PIXMAP: + (*pPicture->pDrawable->pScreen->DestroyPixmap) ((PixmapPtr) (pPicture->clientClip)); + break; + default: + /* + * we know we'll never have a list of rectangles, since ChangeClip + * immediately turns them into a region + */ + REGION_DESTROY(pPicture->pDrawable->pScreen, pPicture->clientClip); + break; + } + pPicture->clientClip = NULL; + pPicture->clientClipType = CT_NONE; +} + +int +miChangePictureClip (PicturePtr pPicture, + int type, + pointer value, + int n) +{ + ScreenPtr pScreen = pPicture->pDrawable->pScreen; + PictureScreenPtr ps = GetPictureScreen(pScreen); + pointer clientClip; + int clientClipType; + + switch (type) { + case CT_PIXMAP: + /* convert the pixmap to a region */ + clientClip = (pointer) BITMAP_TO_REGION(pScreen, (PixmapPtr) value); + if (!clientClip) + return BadAlloc; + clientClipType = CT_REGION; + (*pScreen->DestroyPixmap) ((PixmapPtr) value); + break; + case CT_REGION: + clientClip = value; + clientClipType = CT_REGION; + break; + case CT_NONE: + clientClip = 0; + clientClipType = CT_NONE; + break; + default: + clientClip = (pointer) RECTS_TO_REGION(pScreen, n, + (xRectangle *) value, + type); + if (!clientClip) + return BadAlloc; + clientClipType = CT_REGION; + xfree(value); + break; + } + (*ps->DestroyPictureClip) (pPicture); + pPicture->clientClip = clientClip; + pPicture->clientClipType = clientClipType; + pPicture->stateChanges |= CPClipMask; + return Success; +} + +void +miChangePicture (PicturePtr pPicture, + Mask mask) +{ + return; +} + +void +miValidatePicture (PicturePtr pPicture, + Mask mask) +{ + DrawablePtr pDrawable = pPicture->pDrawable; + + if ((mask & (CPClipXOrigin|CPClipYOrigin|CPClipMask|CPSubwindowMode)) || + (pDrawable->serialNumber != (pPicture->serialNumber & DRAWABLE_SERIAL_BITS))) + { + if (pDrawable->type == DRAWABLE_WINDOW) + { + WindowPtr pWin = (WindowPtr) pDrawable; + RegionPtr pregWin; + Bool freeTmpClip, freeCompClip; + + if (pPicture->subWindowMode == IncludeInferiors) + { + pregWin = NotClippedByChildren(pWin); + freeTmpClip = TRUE; + } + else + { + pregWin = &pWin->clipList; + freeTmpClip = FALSE; + } + freeCompClip = pPicture->freeCompClip; + + /* + * if there is no client clip, we can get by with just keeping the + * pointer we got, and remembering whether or not should destroy + * (or maybe re-use) it later. this way, we avoid unnecessary + * copying of regions. (this wins especially if many clients clip + * by children and have no client clip.) + */ + if (pPicture->clientClipType == CT_NONE) + { + if (freeCompClip) + REGION_DESTROY(pScreen, pPicture->pCompositeClip); + pPicture->pCompositeClip = pregWin; + pPicture->freeCompClip = freeTmpClip; + } + else + { + /* + * we need one 'real' region to put into the composite clip. if + * pregWin the current composite clip are real, we can get rid of + * one. if pregWin is real and the current composite clip isn't, + * use pregWin for the composite clip. if the current composite + * clip is real and pregWin isn't, use the current composite + * clip. if neither is real, create a new region. + */ + + REGION_TRANSLATE(pScreen, pPicture->clientClip, + pDrawable->x + pPicture->clipOrigin.x, + pDrawable->y + pPicture->clipOrigin.y); + + if (freeCompClip) + { + REGION_INTERSECT(pPicture->pScreen, pPicture->pCompositeClip, + pregWin, pPicture->clientClip); + if (freeTmpClip) + REGION_DESTROY(pScreen, pregWin); + } + else if (freeTmpClip) + { + REGION_INTERSECT(pScreen, pregWin, pregWin, pPicture->clientClip); + pPicture->pCompositeClip = pregWin; + } + else + { + pPicture->pCompositeClip = REGION_CREATE(pScreen, NullBox, 0); + REGION_INTERSECT(pScreen, pPicture->pCompositeClip, + pregWin, pPicture->clientClip); + } + pPicture->freeCompClip = TRUE; + REGION_TRANSLATE(pScreen, pPicture->clientClip, + -(pDrawable->x + pPicture->clipOrigin.x), + -(pDrawable->y + pPicture->clipOrigin.y)); + } + } /* end of composite clip for a window */ + else + { + BoxRec pixbounds; + + /* XXX should we translate by drawable.x/y here ? */ + /* If you want pixmaps in offscreen memory, yes */ + pixbounds.x1 = pDrawable->x; + pixbounds.y1 = pDrawable->y; + pixbounds.x2 = pDrawable->x + pDrawable->width; + pixbounds.y2 = pDrawable->y + pDrawable->height; + + if (pPicture->freeCompClip) + { + REGION_RESET(pScreen, pPicture->pCompositeClip, &pixbounds); + } + else + { + pPicture->freeCompClip = TRUE; + pPicture->pCompositeClip = REGION_CREATE(pScreen, &pixbounds, 1); + } + + if (pPicture->clientClipType == CT_REGION) + { + if(pDrawable->x || pDrawable->y) { + REGION_TRANSLATE(pScreen, pPicture->clientClip, + pDrawable->x + pPicture->clipOrigin.x, + pDrawable->y + pPicture->clipOrigin.y); + REGION_INTERSECT(pScreen, pPicture->pCompositeClip, + pPicture->pCompositeClip, pPicture->clientClip); + REGION_TRANSLATE(pScreen, pPicture->clientClip, + -(pDrawable->x + pPicture->clipOrigin.x), + -(pDrawable->y + pPicture->clipOrigin.y)); + } else { + REGION_TRANSLATE(pScreen, pPicture->pCompositeClip, + -pPicture->clipOrigin.x, -pPicture->clipOrigin.y); + REGION_INTERSECT(pScreen, pPicture->pCompositeClip, + pPicture->pCompositeClip, pPicture->clientClip); + REGION_TRANSLATE(pScreen, pPicture->pCompositeClip, + pPicture->clipOrigin.x, pPicture->clipOrigin.y); + } + } + } /* end of composite clip for pixmap */ + } +} + +#define BOUND(v) (INT16) ((v) < MINSHORT ? MINSHORT : (v) > MAXSHORT ? MAXSHORT : (v)) + +static __inline Bool +miClipPictureReg (RegionPtr pRegion, + RegionPtr pClip, + int dx, + int dy) +{ + if (REGION_NUM_RECTS(pRegion) == 1 && + REGION_NUM_RECTS(pClip) == 1) + { + BoxPtr pRbox = REGION_RECTS(pRegion); + BoxPtr pCbox = REGION_RECTS(pClip); + int v; + + if (pRbox->x1 < (v = pCbox->x1 + dx)) + pRbox->x1 = BOUND(v); + if (pRbox->x2 > (v = pCbox->x2 + dx)) + pRbox->x2 = BOUND(v); + if (pRbox->y1 < (v = pCbox->y1 + dy)) + pRbox->y1 = BOUND(v); + if (pRbox->y2 > (v = pCbox->y2 + dy)) + pRbox->y2 = BOUND(v); + if (pRbox->x1 >= pRbox->x2 || + pRbox->y1 >= pRbox->y2) + { + REGION_EMPTY(pScreen, pRegion); + } + } + else + { + REGION_TRANSLATE(pScreen, pRegion, dx, dy); + if (!REGION_INTERSECT (pScreen, pRegion, pRegion, pClip)) + return FALSE; + REGION_TRANSLATE(pScreen, pRegion, -dx, -dy); + } + return TRUE; +} + +static __inline Bool +miClipPictureSrc (RegionPtr pRegion, + PicturePtr pPicture, + int dx, + int dy) +{ + /* XXX what to do with clipping from transformed pictures? */ + if (pPicture->transform) + return TRUE; + if (pPicture->repeat) + { + if (pPicture->clientClipType != CT_NONE) + { + REGION_TRANSLATE(pScreen, pRegion, + dx - pPicture->clipOrigin.x, + dy - pPicture->clipOrigin.y); + if (!REGION_INTERSECT (pScreen, pRegion, pRegion, + (RegionPtr) pPicture->clientClip)) + return FALSE; + REGION_TRANSLATE(pScreen, pRegion, + - (dx - pPicture->clipOrigin.x), + - (dy - pPicture->clipOrigin.y)); + } + return TRUE; + } + else + { + return miClipPictureReg (pRegion, + pPicture->pCompositeClip, + dx, + dy); + } +} + +Bool +miComputeCompositeRegion (RegionPtr pRegion, + PicturePtr pSrc, + PicturePtr pMask, + PicturePtr pDst, + INT16 xSrc, + INT16 ySrc, + INT16 xMask, + INT16 yMask, + INT16 xDst, + INT16 yDst, + CARD16 width, + CARD16 height) +{ + int v; + + pRegion->extents.x1 = xDst; + v = xDst + width; + pRegion->extents.x2 = BOUND(v); + pRegion->extents.y1 = yDst; + v = yDst + height; + pRegion->extents.y2 = BOUND(v); + pRegion->data = 0; + /* Check for empty operation */ + if (pRegion->extents.x1 >= pRegion->extents.x2 || + pRegion->extents.y1 >= pRegion->extents.y2) + { + REGION_EMPTY (pDst->pDrawable->pScreen, pRegion); + return TRUE; + } + /* clip against src */ + if (!miClipPictureSrc (pRegion, pSrc, xDst - xSrc, yDst - ySrc)) + { + REGION_UNINIT (pScreen, pRegion); + return FALSE; + } + if (pSrc->alphaMap) + { + if (!miClipPictureSrc (pRegion, pSrc->alphaMap, + xDst - (xSrc + pSrc->alphaOrigin.x), + yDst - (ySrc + pSrc->alphaOrigin.y))) + { + REGION_UNINIT (pScreen, pRegion); + return FALSE; + } + } + /* clip against mask */ + if (pMask) + { + if (!miClipPictureSrc (pRegion, pMask, xDst - xMask, yDst - yMask)) + { + REGION_UNINIT (pScreen, pRegion); + return FALSE; + } + if (pMask->alphaMap) + { + if (!miClipPictureSrc (pRegion, pMask->alphaMap, + xDst - (xMask + pMask->alphaOrigin.x), + yDst - (yMask + pMask->alphaOrigin.y))) + { + REGION_UNINIT (pScreen, pRegion); + return FALSE; + } + } + } + if (!miClipPictureReg (pRegion, pDst->pCompositeClip, 0, 0)) + { + REGION_UNINIT (pScreen, pRegion); + return FALSE; + } + if (pDst->alphaMap) + { + if (!miClipPictureReg (pRegion, pDst->alphaMap->pCompositeClip, + -pDst->alphaOrigin.x, + -pDst->alphaOrigin.y)) + { + REGION_UNINIT (pScreen, pRegion); + return FALSE; + } + } + return TRUE; +} + +void +miRenderColorToPixel (PictFormatPtr format, + xRenderColor *color, + CARD32 *pixel) +{ + CARD32 r, g, b, a; + miIndexedPtr pIndexed; + + switch (format->type) { + case PictTypeDirect: + r = color->red >> (16 - Ones (format->direct.redMask)); + g = color->green >> (16 - Ones (format->direct.greenMask)); + b = color->blue >> (16 - Ones (format->direct.blueMask)); + a = color->alpha >> (16 - Ones (format->direct.alphaMask)); + r = r << format->direct.red; + g = g << format->direct.green; + b = b << format->direct.blue; + a = a << format->direct.alpha; + *pixel = r|g|b|a; + break; + case PictTypeIndexed: + pIndexed = (miIndexedPtr) (format->index.devPrivate); + if (pIndexed->color) + { + r = color->red >> 11; + g = color->green >> 11; + b = color->blue >> 11; + *pixel = miIndexToEnt15 (pIndexed, (r << 10) | (g << 5) | b); + } + else + { + r = color->red >> 8; + g = color->green >> 8; + b = color->blue >> 8; + *pixel = miIndexToEntY24 (pIndexed, (r << 16) | (g << 8) | b); + } + break; + } +} + +static CARD16 +miFillColor (CARD32 pixel, int bits) +{ + while (bits < 16) + { + pixel |= pixel << bits; + bits <<= 1; + } + return (CARD16) pixel; +} + +void +miRenderPixelToColor (PictFormatPtr format, + CARD32 pixel, + xRenderColor *color) +{ + CARD32 r, g, b, a; + miIndexedPtr pIndexed; + + switch (format->type) { + case PictTypeDirect: + r = (pixel >> format->direct.red) & format->direct.redMask; + g = (pixel >> format->direct.green) & format->direct.greenMask; + b = (pixel >> format->direct.blue) & format->direct.blueMask; + a = (pixel >> format->direct.alpha) & format->direct.alphaMask; + color->red = miFillColor (r, Ones (format->direct.redMask)); + color->green = miFillColor (r, Ones (format->direct.greenMask)); + color->blue = miFillColor (r, Ones (format->direct.blueMask)); + color->alpha = miFillColor (r, Ones (format->direct.alphaMask)); + break; + case PictTypeIndexed: + pIndexed = (miIndexedPtr) (format->index.devPrivate); + pixel = pIndexed->rgba[pixel & (MI_MAX_INDEXED-1)]; + r = (pixel >> 16) & 0xff; + g = (pixel >> 8) & 0xff; + b = (pixel ) & 0xff; + color->red = miFillColor (r, 8); + color->green = miFillColor (g, 8); + color->blue = miFillColor (b, 8); + color->alpha = 0xffff; + break; + } +} + +Bool +miPictureInit (ScreenPtr pScreen, PictFormatPtr formats, int nformats) +{ + PictureScreenPtr ps; + + if (!PictureInit (pScreen, formats, nformats)) + return FALSE; + ps = GetPictureScreen(pScreen); + ps->CreatePicture = miCreatePicture; + ps->DestroyPicture = miDestroyPicture; + ps->ChangePictureClip = miChangePictureClip; + ps->DestroyPictureClip = miDestroyPictureClip; + ps->ChangePicture = miChangePicture; + ps->ValidatePicture = miValidatePicture; + ps->InitIndexed = miInitIndexed; + ps->CloseIndexed = miCloseIndexed; + ps->UpdateIndexed = miUpdateIndexed; + + /* MI rendering routines */ + ps->Composite = 0; /* requires DDX support */ + ps->Glyphs = miGlyphs; + ps->CompositeRects = miCompositeRects; + ps->Trapezoids = miTrapezoids; + ps->Triangles = miTriangles; + ps->TriStrip = miTriStrip; + ps->TriFan = miTriFan; + + return TRUE; +} diff --git a/render/mipict.h b/render/mipict.h new file mode 100644 index 000000000..0154fb5f0 --- /dev/null +++ b/render/mipict.h @@ -0,0 +1,210 @@ +/* + * $XFree86: xc/programs/Xserver/render/mipict.h,v 1.13 2002/11/06 22:45:36 keithp Exp $ + * + * Copyright © 2000 SuSE, Inc. + * + * 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 SuSE not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. SuSE makes no representations about the + * suitability of this software for any purpose. It is provided "as is" + * without express or implied warranty. + * + * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE + * 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. + * + * Author: Keith Packard, SuSE, Inc. + */ + +#ifndef _MIPICT_H_ +#define _MIPICT_H_ + +#include "picturestr.h" + +#define MI_MAX_INDEXED 256 /* XXX depth must be <= 8 */ + +#if MI_MAX_INDEXED <= 256 +typedef CARD8 miIndexType; +#endif + +typedef struct _miIndexed { + Bool color; + CARD32 rgba[MI_MAX_INDEXED]; + miIndexType ent[32768]; +} miIndexedRec, *miIndexedPtr; + +#define miCvtR8G8B8to15(s) ((((s) >> 3) & 0x001f) | \ + (((s) >> 6) & 0x03e0) | \ + (((s) >> 9) & 0x7c00)) +#define miIndexToEnt15(mif,rgb15) ((mif)->ent[rgb15]) +#define miIndexToEnt24(mif,rgb24) miIndexToEnt15(mif,miCvtR8G8B8to15(rgb24)) + +#define miIndexToEntY24(mif,rgb24) ((mif)->ent[CvtR8G8B8toY15(rgb24)]) + +int +miCreatePicture (PicturePtr pPicture); + +void +miDestroyPicture (PicturePtr pPicture); + +void +miDestroyPictureClip (PicturePtr pPicture); + +int +miChangePictureClip (PicturePtr pPicture, + int type, + pointer value, + int n); + +void +miChangePicture (PicturePtr pPicture, + Mask mask); + +void +miValidatePicture (PicturePtr pPicture, + Mask mask); + + +Bool +miClipPicture (RegionPtr pRegion, + PicturePtr pPicture, + INT16 xReg, + INT16 yReg, + INT16 xPict, + INT16 yPict); + +Bool +miComputeCompositeRegion (RegionPtr pRegion, + PicturePtr pSrc, + PicturePtr pMask, + PicturePtr pDst, + INT16 xSrc, + INT16 ySrc, + INT16 xMask, + INT16 yMask, + INT16 xDst, + INT16 yDst, + CARD16 width, + CARD16 height); + +Bool +miPictureInit (ScreenPtr pScreen, PictFormatPtr formats, int nformats); + +void +miGlyphExtents (int nlist, + GlyphListPtr list, + GlyphPtr *glyphs, + BoxPtr extents); + +void +miGlyphs (CARD8 op, + PicturePtr pSrc, + PicturePtr pDst, + PictFormatPtr maskFormat, + INT16 xSrc, + INT16 ySrc, + int nlist, + GlyphListPtr list, + GlyphPtr *glyphs); + +void +miRenderColorToPixel (PictFormatPtr pPict, + xRenderColor *color, + CARD32 *pixel); + +void +miRenderPixelToColor (PictFormatPtr pPict, + CARD32 pixel, + xRenderColor *color); + +void +miCompositeRects (CARD8 op, + PicturePtr pDst, + xRenderColor *color, + int nRect, + xRectangle *rects); + +void +miTrapezoidBounds (int ntrap, xTrapezoid *traps, BoxPtr box); + +void +miTrapezoids (CARD8 op, + PicturePtr pSrc, + PicturePtr pDst, + PictFormatPtr maskFormat, + INT16 xSrc, + INT16 ySrc, + int ntrap, + xTrapezoid *traps); + +void +miPointFixedBounds (int npoint, xPointFixed *points, BoxPtr bounds); + +void +miTriangleBounds (int ntri, xTriangle *tris, BoxPtr bounds); + +void +miRasterizeTriangle (PicturePtr pMask, + xTriangle *tri, + int x_off, + int y_off); + +void +miTriangles (CARD8 op, + PicturePtr pSrc, + PicturePtr pDst, + PictFormatPtr maskFormat, + INT16 xSrc, + INT16 ySrc, + int ntri, + xTriangle *tris); + +void +miTriStrip (CARD8 op, + PicturePtr pSrc, + PicturePtr pDst, + PictFormatPtr maskFormat, + INT16 xSrc, + INT16 ySrc, + int npoint, + xPointFixed *points); + +void +miTriFan (CARD8 op, + PicturePtr pSrc, + PicturePtr pDst, + PictFormatPtr maskFormat, + INT16 xSrc, + INT16 ySrc, + int npoint, + xPointFixed *points); + +PicturePtr +miCreateAlphaPicture (ScreenPtr pScreen, + PicturePtr pDst, + PictFormatPtr pPictFormat, + CARD16 width, + CARD16 height); + +Bool +miInitIndexed (ScreenPtr pScreen, + PictFormatPtr pFormat); + +void +miCloseIndexed (ScreenPtr pScreen, + PictFormatPtr pFormat); + +void +miUpdateIndexed (ScreenPtr pScreen, + PictFormatPtr pFormat, + int ndef, + xColorItem *pdef); + +#endif /* _MIPICT_H_ */ diff --git a/render/mirect.c b/render/mirect.c new file mode 100644 index 000000000..33c7a9f14 --- /dev/null +++ b/render/mirect.c @@ -0,0 +1,181 @@ +/* + * $XFree86: xc/programs/Xserver/render/mirect.c,v 1.4 2001/06/08 19:36:34 keithp Exp $ + * + * Copyright © 2000 Keith Packard, member of The XFree86 Project, Inc. + * + * 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 Keith Packard not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Keith Packard makes no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL KEITH PACKARD 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. + */ + +#include "scrnintstr.h" +#include "gcstruct.h" +#include "pixmapstr.h" +#include "windowstr.h" +#include "mi.h" +#include "picturestr.h" +#include "mipict.h" + +static void +miColorRects (PicturePtr pDst, + PicturePtr pClipPict, + xRenderColor *color, + int nRect, + xRectangle *rects, + int xoff, + int yoff) +{ + ScreenPtr pScreen = pDst->pDrawable->pScreen; + CARD32 pixel; + GCPtr pGC; + CARD32 tmpval[4]; + RegionPtr pClip; + unsigned long mask; + + miRenderColorToPixel (pDst->pFormat, color, &pixel); + + pGC = GetScratchGC (pDst->pDrawable->depth, pScreen); + if (!pGC) + return; + tmpval[0] = GXcopy; + tmpval[1] = pixel; + mask = GCFunction | GCForeground; + if (pClipPict->clientClipType == CT_REGION) + { + tmpval[2] = pDst->clipOrigin.x - xoff; + tmpval[3] = pDst->clipOrigin.y - yoff; + mask |= CPClipXOrigin|CPClipYOrigin; + + pClip = REGION_CREATE (pScreen, NULL, 1); + REGION_COPY (pScreen, pClip, + (RegionPtr) pClipPict->clientClip); + (*pGC->funcs->ChangeClip) (pGC, CT_REGION, pClip, 0); + } + + ChangeGC (pGC, mask, tmpval); + ValidateGC (pDst->pDrawable, pGC); + if (xoff || yoff) + { + int i; + for (i = 0; i < nRect; i++) + { + rects[i].x -= xoff; + rects[i].y -= yoff; + } + } + (*pGC->ops->PolyFillRect) (pDst->pDrawable, pGC, nRect, rects); + if (xoff || yoff) + { + int i; + for (i = 0; i < nRect; i++) + { + rects[i].x += xoff; + rects[i].y += yoff; + } + } + FreeScratchGC (pGC); +} + +void +miCompositeRects (CARD8 op, + PicturePtr pDst, + xRenderColor *color, + int nRect, + xRectangle *rects) +{ + ScreenPtr pScreen = pDst->pDrawable->pScreen; + + if (color->alpha == 0xffff) + { + if (op == PictOpOver) + op = PictOpSrc; + } + if (op == PictOpClear) + color->red = color->green = color->blue = color->alpha = 0; + + if (op == PictOpSrc || op == PictOpClear) + { + miColorRects (pDst, pDst, color, nRect, rects, 0, 0); + if (pDst->alphaMap) + miColorRects (pDst->alphaMap, pDst, + color, nRect, rects, + pDst->alphaOrigin.x, + pDst->alphaOrigin.y); + } + else + { + PictFormatPtr rgbaFormat; + PixmapPtr pPixmap; + PicturePtr pSrc; + xRectangle one; + int error; + Pixel pixel; + GCPtr pGC; + CARD32 tmpval[2]; + + rgbaFormat = PictureMatchFormat (pScreen, 32, PICT_a8r8g8b8); + if (!rgbaFormat) + goto bail1; + + pPixmap = (*pScreen->CreatePixmap) (pScreen, 1, 1, + rgbaFormat->depth); + if (!pPixmap) + goto bail2; + + miRenderColorToPixel (rgbaFormat, color, &pixel); + + pGC = GetScratchGC (rgbaFormat->depth, pScreen); + if (!pGC) + goto bail3; + tmpval[0] = GXcopy; + tmpval[1] = pixel; + + ChangeGC (pGC, GCFunction | GCForeground, tmpval); + ValidateGC (&pPixmap->drawable, pGC); + one.x = 0; + one.y = 0; + one.width = 1; + one.height = 1; + (*pGC->ops->PolyFillRect) (&pPixmap->drawable, pGC, 1, &one); + + tmpval[0] = xTrue; + pSrc = CreatePicture (0, &pPixmap->drawable, rgbaFormat, + CPRepeat, tmpval, 0, &error); + + if (!pSrc) + goto bail4; + + while (nRect--) + { + CompositePicture (op, pSrc, 0, pDst, 0, 0, 0, 0, + rects->x, + rects->y, + rects->width, + rects->height); + rects++; + } + + FreePicture ((pointer) pSrc, 0); +bail4: + FreeScratchGC (pGC); +bail3: + (*pScreen->DestroyPixmap) (pPixmap); +bail2: +bail1: + ; + } +} diff --git a/render/mitrap.c b/render/mitrap.c new file mode 100644 index 000000000..7f592ccd4 --- /dev/null +++ b/render/mitrap.c @@ -0,0 +1,196 @@ +/* + * $XFree86: xc/programs/Xserver/render/mitrap.c,v 1.9 2002/11/05 23:39:16 keithp Exp $ + * + * Copyright © 2002 Keith Packard, member of The XFree86 Project, Inc. + * + * 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 Keith Packard not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Keith Packard makes no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL KEITH PACKARD 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. + */ + +#include "scrnintstr.h" +#include "gcstruct.h" +#include "pixmapstr.h" +#include "windowstr.h" +#include "servermd.h" +#include "mi.h" +#include "picturestr.h" +#include "mipict.h" + +PicturePtr +miCreateAlphaPicture (ScreenPtr pScreen, + PicturePtr pDst, + PictFormatPtr pPictFormat, + CARD16 width, + CARD16 height) +{ + PixmapPtr pPixmap; + PicturePtr pPicture; + GCPtr pGC; + int error; + xRectangle rect; + + if (width > 32767 || height > 32767) + return 0; + + if (!pPictFormat) + { + if (pDst->polyEdge == PolyEdgeSharp) + pPictFormat = PictureMatchFormat (pScreen, 1, PICT_a1); + else + pPictFormat = PictureMatchFormat (pScreen, 8, PICT_a8); + if (!pPictFormat) + return 0; + } + + pPixmap = (*pScreen->CreatePixmap) (pScreen, width, height, + pPictFormat->depth); + if (!pPixmap) + return 0; + pGC = GetScratchGC (pPixmap->drawable.depth, pScreen); + if (!pGC) + { + (*pScreen->DestroyPixmap) (pPixmap); + return 0; + } + ValidateGC (&pPixmap->drawable, pGC); + rect.x = 0; + rect.y = 0; + rect.width = width; + rect.height = height; + (*pGC->ops->PolyFillRect)(&pPixmap->drawable, pGC, 1, &rect); + FreeScratchGC (pGC); + pPicture = CreatePicture (0, &pPixmap->drawable, pPictFormat, + 0, 0, serverClient, &error); + (*pScreen->DestroyPixmap) (pPixmap); + return pPicture; +} + +static xFixed +miLineFixedX (xLineFixed *l, xFixed y, Bool ceil) +{ + xFixed dx = l->p2.x - l->p1.x; + xFixed_32_32 ex = (xFixed_32_32) (y - l->p1.y) * dx; + xFixed dy = l->p2.y - l->p1.y; + if (ceil) + ex += (dy - 1); + return l->p1.x + (xFixed) (ex / dy); +} + +void +miTrapezoidBounds (int ntrap, xTrapezoid *traps, BoxPtr box) +{ + box->y1 = MAXSHORT; + box->y2 = MINSHORT; + box->x1 = MAXSHORT; + box->x2 = MINSHORT; + for (; ntrap; ntrap--, traps++) + { + INT16 x1, y1, x2, y2; + + if (!xTrapezoidValid(traps)) + continue; + y1 = xFixedToInt (traps->top); + if (y1 < box->y1) + box->y1 = y1; + + y2 = xFixedToInt (xFixedCeil (traps->bottom)); + if (y2 > box->y2) + box->y2 = y2; + + x1 = xFixedToInt (min (miLineFixedX (&traps->left, traps->top, FALSE), + miLineFixedX (&traps->left, traps->bottom, FALSE))); + if (x1 < box->x1) + box->x1 = x1; + + x2 = xFixedToInt (xFixedCeil (max (miLineFixedX (&traps->right, traps->top, TRUE), + miLineFixedX (&traps->right, traps->bottom, TRUE)))); + if (x2 > box->x2) + box->x2 = x2; + } +} + +void +miTrapezoids (CARD8 op, + PicturePtr pSrc, + PicturePtr pDst, + PictFormatPtr maskFormat, + INT16 xSrc, + INT16 ySrc, + int ntrap, + xTrapezoid *traps) +{ + ScreenPtr pScreen = pDst->pDrawable->pScreen; + PictureScreenPtr ps = GetPictureScreen(pScreen); + PicturePtr pPicture = 0; + BoxRec bounds; + INT16 xDst, yDst; + INT16 xRel, yRel; + + xDst = traps[0].left.p1.x >> 16; + yDst = traps[0].left.p1.y >> 16; + + if (maskFormat) + { + miTrapezoidBounds (ntrap, traps, &bounds); + if (bounds.y1 >= bounds.y2 || bounds.x1 >= bounds.x2) + return; + pPicture = miCreateAlphaPicture (pScreen, pDst, maskFormat, + bounds.x2 - bounds.x1, + bounds.y2 - bounds.y1); + if (!pPicture) + return; + } + for (; ntrap; ntrap--, traps++) + { + if (!xTrapezoidValid(traps)) + continue; + if (!maskFormat) + { + miTrapezoidBounds (1, traps, &bounds); + if (bounds.y1 >= bounds.y2 || bounds.x1 >= bounds.x2) + continue; + pPicture = miCreateAlphaPicture (pScreen, pDst, maskFormat, + bounds.x2 - bounds.x1, + bounds.y2 - bounds.y1); + if (!pPicture) + continue; + } + (*ps->RasterizeTrapezoid) (pPicture, traps, + -bounds.x1, -bounds.y1); + if (!maskFormat) + { + xRel = bounds.x1 + xSrc - xDst; + yRel = bounds.y1 + ySrc - yDst; + CompositePicture (op, pSrc, pPicture, pDst, + xRel, yRel, 0, 0, bounds.x1, bounds.y1, + bounds.x2 - bounds.x1, + bounds.y2 - bounds.y1); + FreePicture (pPicture, 0); + } + } + if (maskFormat) + { + xRel = bounds.x1 + xSrc - xDst; + yRel = bounds.y1 + ySrc - yDst; + CompositePicture (op, pSrc, pPicture, pDst, + xRel, yRel, 0, 0, bounds.x1, bounds.y1, + bounds.x2 - bounds.x1, + bounds.y2 - bounds.y1); + FreePicture (pPicture, 0); + } +} diff --git a/render/mitri.c b/render/mitri.c new file mode 100644 index 000000000..fc706f117 --- /dev/null +++ b/render/mitri.c @@ -0,0 +1,352 @@ +/* + * $XFree86: xc/programs/Xserver/render/mitri.c,v 1.6 2002/08/12 04:03:21 keithp Exp $ + * + * Copyright © 2002 Keith Packard, member of The XFree86 Project, Inc. + * + * 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 Keith Packard not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Keith Packard makes no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL KEITH PACKARD 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. + */ + +#include "scrnintstr.h" +#include "gcstruct.h" +#include "pixmapstr.h" +#include "windowstr.h" +#include "mi.h" +#include "picturestr.h" +#include "mipict.h" + +void +miPointFixedBounds (int npoint, xPointFixed *points, BoxPtr bounds) +{ + bounds->x1 = xFixedToInt (points->x); + bounds->x2 = xFixedToInt (xFixedCeil (points->x)); + bounds->y1 = xFixedToInt (points->y); + bounds->y2 = xFixedToInt (xFixedCeil (points->y)); + points++; + npoint--; + while (npoint-- > 0) + { + INT16 x1 = xFixedToInt (points->x); + INT16 x2 = xFixedToInt (xFixedCeil (points->x)); + INT16 y1 = xFixedToInt (points->y); + INT16 y2 = xFixedToInt (xFixedCeil (points->y)); + + if (x1 < bounds->x1) + bounds->x1 = x1; + else if (x2 > bounds->x2) + bounds->x2 = x2; + if (y1 < bounds->y1) + bounds->y1 = y1; + else if (y2 > bounds->y2) + bounds->y2 = y2; + points++; + } +} + +void +miTriangleBounds (int ntri, xTriangle *tris, BoxPtr bounds) +{ + miPointFixedBounds (ntri * 3, (xPointFixed *) tris, bounds); +} + +void +miRasterizeTriangle (PicturePtr pPicture, + xTriangle *tri, + int x_off, + int y_off) +{ + ScreenPtr pScreen = pPicture->pDrawable->pScreen; + PictureScreenPtr ps = GetPictureScreen(pScreen); + xPointFixed *top, *left, *right, *t; + xTrapezoid trap[2]; + + top = &tri->p1; + left = &tri->p2; + right = &tri->p3; + if (left->y < top->y) { + t = left; left = top; top = t; + } + if (right->y < top->y) { + t = right; right = top; top = t; + } + if (right->x < left->x) { + t = right; right = left; left = t; + } + + /* + * Two cases: + * + * + + + * / \ / \ + * / \ / \ + * / + + \ + * / -- -- \ + * / -- -- \ + * / --- --- \ + * +-- --+ + */ + + trap[0].top = top->y; + + trap[0].left.p1.x = top->x; + trap[0].left.p1.y = trap[0].top; + trap[0].left.p2.x = left->x; + trap[0].left.p2.y = left->y; + + trap[0].right.p1 = trap[0].left.p1; + trap[0].right.p2.x = right->x; + trap[0].right.p2.y = right->y; + + if (right->y < left->y) + { + trap[0].bottom = trap[0].right.p2.y; + + trap[1].top = trap[0].bottom; + trap[1].bottom = trap[0].left.p2.y; + + trap[1].left = trap[0].left; + trap[1].right.p1 = trap[0].right.p2; + trap[1].right.p2 = trap[0].left.p2; + } + else + { + trap[0].bottom = trap[0].left.p2.y; + + trap[1].top = trap[0].bottom; + trap[1].bottom = trap[0].right.p2.y; + + trap[1].right = trap[0].right; + trap[1].left.p1 = trap[0].left.p2; + trap[1].left.p2 = trap[0].right.p2; + } + if (trap[0].top != trap[0].bottom) + (*ps->RasterizeTrapezoid) (pPicture, &trap[0], x_off, y_off); + if (trap[1].top != trap[1].bottom) + (*ps->RasterizeTrapezoid) (pPicture, &trap[1], x_off, y_off); +} + +void +miTriangles (CARD8 op, + PicturePtr pSrc, + PicturePtr pDst, + PictFormatPtr maskFormat, + INT16 xSrc, + INT16 ySrc, + int ntri, + xTriangle *tris) +{ + ScreenPtr pScreen = pDst->pDrawable->pScreen; + BoxRec bounds; + PicturePtr pPicture = 0; + INT16 xDst, yDst; + INT16 xRel, yRel; + + xDst = tris[0].p1.x >> 16; + yDst = tris[0].p1.y >> 16; + + if (maskFormat) + { + miTriangleBounds (ntri, tris, &bounds); + if (bounds.x2 <= bounds.x1 || bounds.y2 <= bounds.y1) + return; + pPicture = miCreateAlphaPicture (pScreen, pDst, maskFormat, + bounds.x2 - bounds.x1, + bounds.y2 - bounds.y1); + if (!pPicture) + return; + } + for (; ntri; ntri--, tris++) + { + if (!maskFormat) + { + miTriangleBounds (1, tris, &bounds); + if (bounds.x2 <= bounds.x1 || bounds.y2 <= bounds.y1) + continue; + pPicture = miCreateAlphaPicture (pScreen, pDst, maskFormat, + bounds.x2 - bounds.x1, + bounds.y2 - bounds.y1); + if (!pPicture) + break; + } + miRasterizeTriangle (pPicture, tris, -bounds.x1, -bounds.y1); + if (!maskFormat) + { + xRel = bounds.x1 + xSrc - xDst; + yRel = bounds.y1 + ySrc - yDst; + CompositePicture (op, pSrc, pPicture, pDst, + xRel, yRel, 0, 0, bounds.x1, bounds.y1, + bounds.x2 - bounds.x1, bounds.y2 - bounds.y1); + FreePicture (pPicture, 0); + } + /* XXX adjust xSrc and ySrc */ + } + if (maskFormat) + { + xRel = bounds.x1 + xSrc - xDst; + yRel = bounds.y1 + ySrc - yDst; + CompositePicture (op, pSrc, pPicture, pDst, + xRel, yRel, 0, 0, bounds.x1, bounds.y1, + bounds.x2 - bounds.x1, bounds.y2 - bounds.y1); + FreePicture (pPicture, 0); + } +} + +void +miTriStrip (CARD8 op, + PicturePtr pSrc, + PicturePtr pDst, + PictFormatPtr maskFormat, + INT16 xSrc, + INT16 ySrc, + int npoint, + xPointFixed *points) +{ + ScreenPtr pScreen = pDst->pDrawable->pScreen; + xTriangle tri; + BoxRec bounds; + PicturePtr pPicture = 0; + INT16 xDst, yDst; + INT16 xRel, yRel; + + xDst = points[0].x >> 16; + yDst = points[0].y >> 16; + + if (npoint < 3) + return; + if (maskFormat) + { + miPointFixedBounds (npoint, points, &bounds); + if (bounds.x2 <= bounds.x1 || bounds.y2 <= bounds.y1) + return; + pPicture = miCreateAlphaPicture (pScreen, pDst, maskFormat, + bounds.x2 - bounds.x1, + bounds.y2 - bounds.y1); + if (!pPicture) + return; + } + for (; npoint >= 3; npoint--, points++) + { + tri.p1 = points[0]; + tri.p2 = points[1]; + tri.p3 = points[2]; + if (!maskFormat) + { + miTriangleBounds (1, &tri, &bounds); + if (bounds.x2 <= bounds.x1 || bounds.y2 <= bounds.y1) + continue; + pPicture = miCreateAlphaPicture (pScreen, pDst, maskFormat, + bounds.x2 - bounds.x1, + bounds.y2 - bounds.y1); + if (!pPicture) + continue; + } + miRasterizeTriangle (pPicture, &tri, -bounds.x1, -bounds.y1); + if (!maskFormat) + { + xRel = bounds.x1 + xSrc - xDst; + yRel = bounds.y1 + ySrc - yDst; + CompositePicture (op, pSrc, pPicture, pDst, + xRel, yRel, 0, 0, bounds.x1, bounds.y1, + bounds.x2 - bounds.x1, bounds.y2 - bounds.y1); + FreePicture (pPicture, 0); + } + } + if (maskFormat) + { + xRel = bounds.x1 + xSrc - xDst; + yRel = bounds.y1 + ySrc - yDst; + CompositePicture (op, pSrc, pPicture, pDst, + xRel, yRel, 0, 0, bounds.x1, bounds.y1, + bounds.x2 - bounds.x1, bounds.y2 - bounds.y1); + FreePicture (pPicture, 0); + } +} + +void +miTriFan (CARD8 op, + PicturePtr pSrc, + PicturePtr pDst, + PictFormatPtr maskFormat, + INT16 xSrc, + INT16 ySrc, + int npoint, + xPointFixed *points) +{ + ScreenPtr pScreen = pDst->pDrawable->pScreen; + xTriangle tri; + BoxRec bounds; + PicturePtr pPicture = 0; + xPointFixed *first; + INT16 xDst, yDst; + INT16 xRel, yRel; + + xDst = points[0].x >> 16; + yDst = points[0].y >> 16; + + if (npoint < 3) + return; + if (maskFormat) + { + miPointFixedBounds (npoint, points, &bounds); + if (bounds.x2 <= bounds.x1 || bounds.y2 <= bounds.y1) + return; + pPicture = miCreateAlphaPicture (pScreen, pDst, maskFormat, + bounds.x2 - bounds.x1, + bounds.y2 - bounds.y1); + if (!pPicture) + return; + } + first = points++; + npoint--; + for (; npoint >= 2; npoint--, points++) + { + tri.p1 = *first; + tri.p2 = points[0]; + tri.p3 = points[1]; + if (!maskFormat) + { + miTriangleBounds (1, &tri, &bounds); + if (bounds.x2 <= bounds.x1 || bounds.y2 <= bounds.y1) + continue; + pPicture = miCreateAlphaPicture (pScreen, pDst, maskFormat, + bounds.x2 - bounds.x1, + bounds.y2 - bounds.y1); + if (!pPicture) + continue; + } + miRasterizeTriangle (pPicture, &tri, -bounds.x1, -bounds.y1); + if (!maskFormat) + { + xRel = bounds.x1 + xSrc - xDst; + yRel = bounds.y1 + ySrc - yDst; + CompositePicture (op, pSrc, pPicture, pDst, + xRel, yRel, 0, 0, bounds.x1, bounds.y1, + bounds.x2 - bounds.x1, bounds.y2 - bounds.y1); + FreePicture (pPicture, 0); + } + } + if (maskFormat) + { + xRel = bounds.x1 + xSrc - xDst; + yRel = bounds.y1 + ySrc - yDst; + CompositePicture (op, pSrc, pPicture, pDst, + xRel, yRel, 0, 0, bounds.x1, bounds.y1, + bounds.x2 - bounds.x1, bounds.y2 - bounds.y1); + FreePicture (pPicture, 0); + } +} diff --git a/render/picture.c b/render/picture.c new file mode 100644 index 000000000..b2ef69bdf --- /dev/null +++ b/render/picture.c @@ -0,0 +1,1305 @@ +/* + * $XFree86: xc/programs/Xserver/render/picture.c,v 1.30 2003/01/26 16:40:43 eich Exp $ + * + * Copyright © 2000 SuSE, Inc. + * + * 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 SuSE not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. SuSE makes no representations about the + * suitability of this software for any purpose. It is provided "as is" + * without express or implied warranty. + * + * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE + * 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. + * + * Author: Keith Packard, SuSE, Inc. + */ + +#include "misc.h" +#include "scrnintstr.h" +#include "os.h" +#include "regionstr.h" +#include "validate.h" +#include "windowstr.h" +#include "input.h" +#include "resource.h" +#include "colormapst.h" +#include "cursorstr.h" +#include "dixstruct.h" +#include "gcstruct.h" +#include "servermd.h" +#include "picturestr.h" + +int PictureScreenPrivateIndex = -1; +int PictureWindowPrivateIndex; +int PictureGeneration; +RESTYPE PictureType; +RESTYPE PictFormatType; +RESTYPE GlyphSetType; +int PictureCmapPolicy = PictureCmapPolicyDefault; + +Bool +PictureDestroyWindow (WindowPtr pWindow) +{ + ScreenPtr pScreen = pWindow->drawable.pScreen; + PicturePtr pPicture; + PictureScreenPtr ps = GetPictureScreen(pScreen); + Bool ret; + + while ((pPicture = GetPictureWindow(pWindow))) + { + SetPictureWindow(pWindow, pPicture->pNext); + if (pPicture->id) + FreeResource (pPicture->id, PictureType); + FreePicture ((pointer) pPicture, pPicture->id); + } + pScreen->DestroyWindow = ps->DestroyWindow; + ret = (*pScreen->DestroyWindow) (pWindow); + ps->DestroyWindow = pScreen->DestroyWindow; + pScreen->DestroyWindow = PictureDestroyWindow; + return ret; +} + +Bool +PictureCloseScreen (int index, ScreenPtr pScreen) +{ + PictureScreenPtr ps = GetPictureScreen(pScreen); + Bool ret; + int n; + + pScreen->CloseScreen = ps->CloseScreen; + ret = (*pScreen->CloseScreen) (index, pScreen); + PictureResetFilters (pScreen); + for (n = 0; n < ps->nformats; n++) + if (ps->formats[n].type == PictTypeIndexed) + (*ps->CloseIndexed) (pScreen, &ps->formats[n]); + SetPictureScreen(pScreen, 0); + xfree (ps->formats); + xfree (ps); + return ret; +} + +void +PictureStoreColors (ColormapPtr pColormap, int ndef, xColorItem *pdef) +{ + ScreenPtr pScreen = pColormap->pScreen; + PictureScreenPtr ps = GetPictureScreen(pScreen); + + pScreen->StoreColors = ps->StoreColors; + (*pScreen->StoreColors) (pColormap, ndef, pdef); + ps->StoreColors = pScreen->StoreColors; + pScreen->StoreColors = PictureStoreColors; + + if (pColormap->class == PseudoColor || pColormap->class == GrayScale) + { + PictFormatPtr format = ps->formats; + int nformats = ps->nformats; + + while (nformats--) + { + if (format->type == PictTypeIndexed && + format->index.pColormap == pColormap) + { + (*ps->UpdateIndexed) (pScreen, format, ndef, pdef); + break; + } + format++; + } + } +} + +static int +visualDepth (ScreenPtr pScreen, VisualPtr pVisual) +{ + int d, v; + DepthPtr pDepth; + + for (d = 0; d < pScreen->numDepths; d++) + { + pDepth = &pScreen->allowedDepths[d]; + for (v = 0; v < pDepth->numVids; v++) + if (pDepth->vids[v] == pVisual->vid) + return pDepth->depth; + } + return 0; +} + +typedef struct _formatInit { + CARD32 format; + CARD8 depth; +} FormatInitRec, *FormatInitPtr; + +static int +addFormat (FormatInitRec formats[256], + int nformat, + CARD32 format, + CARD8 depth) +{ + int n; + + for (n = 0; n < nformat; n++) + if (formats[n].format == format && formats[n].depth == depth) + return nformat; + formats[nformat].format = format; + formats[nformat].depth = depth; + return ++nformat; +} + +#define Mask(n) ((n) == 32 ? 0xffffffff : ((1 << (n))-1)) + +PictFormatPtr +PictureCreateDefaultFormats (ScreenPtr pScreen, int *nformatp) +{ + int nformats, f; + PictFormatPtr pFormats; + FormatInitRec formats[1024]; + CARD32 format; + CARD8 depth; + VisualPtr pVisual; + int v; + int bpp; + int type; + int r, g, b; + int d; + DepthPtr pDepth; + + nformats = 0; + /* formats required by protocol */ + formats[nformats].format = PICT_a1; + formats[nformats].depth = 1; + nformats++; + formats[nformats].format = PICT_a8; + formats[nformats].depth = 8; + nformats++; + formats[nformats].format = PICT_a4; + formats[nformats].depth = 4; + nformats++; + formats[nformats].format = PICT_a8r8g8b8; + formats[nformats].depth = 32; + nformats++; + formats[nformats].format = PICT_x8r8g8b8; + formats[nformats].depth = 32; + nformats++; + + /* now look through the depths and visuals adding other formats */ + for (v = 0; v < pScreen->numVisuals; v++) + { + pVisual = &pScreen->visuals[v]; + depth = visualDepth (pScreen, pVisual); + if (!depth) + continue; + bpp = BitsPerPixel (depth); + switch (pVisual->class) { + case DirectColor: + case TrueColor: + r = Ones (pVisual->redMask); + g = Ones (pVisual->greenMask); + b = Ones (pVisual->blueMask); + type = PICT_TYPE_OTHER; + /* + * Current rendering code supports only two direct formats, + * fields must be packed together at the bottom of the pixel + * and must be either RGB or BGR + */ + if (pVisual->offsetBlue == 0 && + pVisual->offsetGreen == b && + pVisual->offsetRed == b + g) + { + type = PICT_TYPE_ARGB; + } + else if (pVisual->offsetRed == 0 && + pVisual->offsetGreen == r && + pVisual->offsetBlue == r + g) + { + type = PICT_TYPE_ABGR; + } + if (type != PICT_TYPE_OTHER) + { + format = PICT_FORMAT(bpp, type, 0, r, g, b); + nformats = addFormat (formats, nformats, format, depth); + } + break; + case StaticColor: + case PseudoColor: + format = PICT_VISFORMAT (bpp, PICT_TYPE_COLOR, v); + nformats = addFormat (formats, nformats, format, depth); + break; + case StaticGray: + case GrayScale: + format = PICT_VISFORMAT (bpp, PICT_TYPE_GRAY, v); + nformats = addFormat (formats, nformats, format, depth); + break; + } + } + /* + * Walk supported depths and add useful Direct formats + */ + for (d = 0; d < pScreen->numDepths; d++) + { + pDepth = &pScreen->allowedDepths[d]; + bpp = BitsPerPixel (pDepth->depth); + format = 0; + switch (bpp) { + case 16: + /* depth 12 formats */ + if (pDepth->depth >= 12) + { + nformats = addFormat (formats, nformats, + PICT_x4r4g4b4, pDepth->depth); + nformats = addFormat (formats, nformats, + PICT_x4b4g4r4, pDepth->depth); + } + /* depth 15 formats */ + if (pDepth->depth >= 15) + { + nformats = addFormat (formats, nformats, + PICT_x1r5g5b5, pDepth->depth); + nformats = addFormat (formats, nformats, + PICT_x1b5g5r5, pDepth->depth); + } + /* depth 16 formats */ + if (pDepth->depth >= 16) + { + nformats = addFormat (formats, nformats, + PICT_a1r5g5b5, pDepth->depth); + nformats = addFormat (formats, nformats, + PICT_a1b5g5r5, pDepth->depth); + nformats = addFormat (formats, nformats, + PICT_r5g6b5, pDepth->depth); + nformats = addFormat (formats, nformats, + PICT_b5g6r5, pDepth->depth); + nformats = addFormat (formats, nformats, + PICT_a4r4g4b4, pDepth->depth); + nformats = addFormat (formats, nformats, + PICT_a4b4g4r4, pDepth->depth); + } + break; + case 24: + if (pDepth->depth >= 24) + { + nformats = addFormat (formats, nformats, + PICT_r8g8b8, pDepth->depth); + nformats = addFormat (formats, nformats, + PICT_b8g8r8, pDepth->depth); + } + break; + case 32: + if (pDepth->depth >= 24) + { + nformats = addFormat (formats, nformats, + PICT_x8r8g8b8, pDepth->depth); + nformats = addFormat (formats, nformats, + PICT_x8b8g8r8, pDepth->depth); + } + break; + } + } + + + pFormats = (PictFormatPtr) xalloc (nformats * sizeof (PictFormatRec)); + if (!pFormats) + return 0; + memset (pFormats, '\0', nformats * sizeof (PictFormatRec)); + for (f = 0; f < nformats; f++) + { + pFormats[f].id = FakeClientID (0); + pFormats[f].depth = formats[f].depth; + format = formats[f].format; + pFormats[f].format = format; + switch (PICT_FORMAT_TYPE(format)) { + case PICT_TYPE_ARGB: + pFormats[f].type = PictTypeDirect; + + pFormats[f].direct.alphaMask = Mask(PICT_FORMAT_A(format)); + if (pFormats[f].direct.alphaMask) + pFormats[f].direct.alpha = (PICT_FORMAT_R(format) + + PICT_FORMAT_G(format) + + PICT_FORMAT_B(format)); + + pFormats[f].direct.redMask = Mask(PICT_FORMAT_R(format)); + pFormats[f].direct.red = (PICT_FORMAT_G(format) + + PICT_FORMAT_B(format)); + + pFormats[f].direct.greenMask = Mask(PICT_FORMAT_G(format)); + pFormats[f].direct.green = PICT_FORMAT_B(format); + + pFormats[f].direct.blueMask = Mask(PICT_FORMAT_B(format)); + pFormats[f].direct.blue = 0; + break; + + case PICT_TYPE_ABGR: + pFormats[f].type = PictTypeDirect; + + pFormats[f].direct.alphaMask = Mask(PICT_FORMAT_A(format)); + if (pFormats[f].direct.alphaMask) + pFormats[f].direct.alpha = (PICT_FORMAT_B(format) + + PICT_FORMAT_G(format) + + PICT_FORMAT_R(format)); + + pFormats[f].direct.blueMask = Mask(PICT_FORMAT_B(format)); + pFormats[f].direct.blue = (PICT_FORMAT_G(format) + + PICT_FORMAT_R(format)); + + pFormats[f].direct.greenMask = Mask(PICT_FORMAT_G(format)); + pFormats[f].direct.green = PICT_FORMAT_R(format); + + pFormats[f].direct.redMask = Mask(PICT_FORMAT_R(format)); + pFormats[f].direct.red = 0; + break; + + case PICT_TYPE_A: + pFormats[f].type = PictTypeDirect; + + pFormats[f].direct.alpha = 0; + pFormats[f].direct.alphaMask = Mask(PICT_FORMAT_A(format)); + + /* remaining fields already set to zero */ + break; + + case PICT_TYPE_COLOR: + case PICT_TYPE_GRAY: + pFormats[f].type = PictTypeIndexed; + pFormats[f].index.pVisual = &pScreen->visuals[PICT_FORMAT_VIS(format)]; + break; + } + } + *nformatp = nformats; + return pFormats; +} + +Bool +PictureInitIndexedFormats (ScreenPtr pScreen) +{ + PictureScreenPtr ps = GetPictureScreenIfSet(pScreen); + PictFormatPtr format; + int nformat; + + if (!ps) + return FALSE; + format = ps->formats; + nformat = ps->nformats; + while (nformat--) + { + if (format->type == PictTypeIndexed && !format->index.pColormap) + { + if (format->index.pVisual->vid == pScreen->rootVisual) + format->index.pColormap = (ColormapPtr) LookupIDByType(pScreen->defColormap, + RT_COLORMAP); + else + { + if (CreateColormap (FakeClientID (0), pScreen, + format->index.pVisual, + &format->index.pColormap, AllocNone, + 0) != Success) + { + return FALSE; + } + } + if (!(*ps->InitIndexed) (pScreen, format)) + return FALSE; + } + format++; + } + return TRUE; +} + +Bool +PictureFinishInit (void) +{ + int s; + + for (s = 0; s < screenInfo.numScreens; s++) + { + if (!PictureInitIndexedFormats (screenInfo.screens[s])) + return FALSE; + (void) AnimCurInit (screenInfo.screens[s]); + } + + return TRUE; +} + +Bool +PictureSetSubpixelOrder (ScreenPtr pScreen, int subpixel) +{ + PictureScreenPtr ps = GetPictureScreenIfSet(pScreen); + + if (!ps) + return FALSE; + ps->subpixel = subpixel; + return TRUE; + +} + +int +PictureGetSubpixelOrder (ScreenPtr pScreen) +{ + PictureScreenPtr ps = GetPictureScreenIfSet(pScreen); + + if (!ps) + return SubPixelUnknown; + return ps->subpixel; +} + +PictFormatPtr +PictureMatchVisual (ScreenPtr pScreen, int depth, VisualPtr pVisual) +{ + PictureScreenPtr ps = GetPictureScreenIfSet(pScreen); + PictFormatPtr format; + int nformat; + int type; + + if (!ps) + return 0; + format = ps->formats; + nformat = ps->nformats; + switch (pVisual->class) { + case StaticGray: + case GrayScale: + case StaticColor: + case PseudoColor: + type = PictTypeIndexed; + break; + case TrueColor: + type = PictTypeDirect; + break; + case DirectColor: + default: + return 0; + } + while (nformat--) + { + if (format->depth == depth && format->type == type) + { + if (type == PictTypeIndexed) + { + if (format->index.pVisual == pVisual) + return format; + } + else + { + if (format->direct.redMask << format->direct.red == + pVisual->redMask && + format->direct.greenMask << format->direct.green == + pVisual->greenMask && + format->direct.blueMask << format->direct.blue == + pVisual->blueMask) + { + return format; + } + } + } + format++; + } + return 0; +} + +PictFormatPtr +PictureMatchFormat (ScreenPtr pScreen, int depth, CARD32 f) +{ + PictureScreenPtr ps = GetPictureScreenIfSet(pScreen); + PictFormatPtr format; + int nformat; + + if (!ps) + return 0; + format = ps->formats; + nformat = ps->nformats; + while (nformat--) + { + if (format->depth == depth && format->format == (f & 0xffffff)) + return format; + format++; + } + return 0; +} + +int +PictureParseCmapPolicy (const char *name) +{ + if ( strcmp (name, "default" ) == 0) + return PictureCmapPolicyDefault; + else if ( strcmp (name, "mono" ) == 0) + return PictureCmapPolicyMono; + else if ( strcmp (name, "gray" ) == 0) + return PictureCmapPolicyGray; + else if ( strcmp (name, "color" ) == 0) + return PictureCmapPolicyColor; + else if ( strcmp (name, "all" ) == 0) + return PictureCmapPolicyAll; + else + return PictureCmapPolicyInvalid; +} + +Bool +PictureInit (ScreenPtr pScreen, PictFormatPtr formats, int nformats) +{ + PictureScreenPtr ps; + int n; + CARD32 type, a, r, g, b; + + if (PictureGeneration != serverGeneration) + { + PictureType = CreateNewResourceType (FreePicture); + if (!PictureType) + return FALSE; + PictFormatType = CreateNewResourceType (FreePictFormat); + if (!PictFormatType) + return FALSE; + GlyphSetType = CreateNewResourceType (FreeGlyphSet); + if (!GlyphSetType) + return FALSE; + PictureScreenPrivateIndex = AllocateScreenPrivateIndex(); + if (PictureScreenPrivateIndex < 0) + return FALSE; + PictureWindowPrivateIndex = AllocateWindowPrivateIndex(); + PictureGeneration = serverGeneration; +#ifdef XResExtension + RegisterResourceName (PictureType, "PICTURE"); + RegisterResourceName (PictFormatType, "PICTFORMAT"); + RegisterResourceName (GlyphSetType, "GLYPHSET"); +#endif + } + if (!AllocateWindowPrivate (pScreen, PictureWindowPrivateIndex, 0)) + return FALSE; + + if (!formats) + { + formats = PictureCreateDefaultFormats (pScreen, &nformats); + if (!formats) + return FALSE; + } + for (n = 0; n < nformats; n++) + { + if (!AddResource (formats[n].id, PictFormatType, (pointer) (formats+n))) + { + xfree (formats); + return FALSE; + } + if (formats[n].type == PictTypeIndexed) + { + if ((formats[n].index.pVisual->class | DynamicClass) == PseudoColor) + type = PICT_TYPE_COLOR; + else + type = PICT_TYPE_GRAY; + a = r = g = b = 0; + } + else + { + if ((formats[n].direct.redMask| + formats[n].direct.blueMask| + formats[n].direct.greenMask) == 0) + type = PICT_TYPE_A; + else if (formats[n].direct.red > formats[n].direct.blue) + type = PICT_TYPE_ARGB; + else + type = PICT_TYPE_ABGR; + a = Ones (formats[n].direct.alphaMask); + r = Ones (formats[n].direct.redMask); + g = Ones (formats[n].direct.greenMask); + b = Ones (formats[n].direct.blueMask); + } + formats[n].format = PICT_FORMAT(0,type,a,r,g,b); + } + ps = (PictureScreenPtr) xalloc (sizeof (PictureScreenRec)); + if (!ps) + { + xfree (formats); + return FALSE; + } + SetPictureScreen(pScreen, ps); + if (!GlyphInit (pScreen)) + { + SetPictureScreen(pScreen, 0); + xfree (formats); + xfree (ps); + return FALSE; + } + + ps->totalPictureSize = sizeof (PictureRec); + ps->PicturePrivateSizes = 0; + ps->PicturePrivateLen = 0; + + ps->formats = formats; + ps->fallback = formats; + ps->nformats = nformats; + + ps->filters = 0; + ps->nfilters = 0; + ps->filterAliases = 0; + ps->nfilterAliases = 0; + + ps->subpixel = SubPixelUnknown; + + ps->CloseScreen = pScreen->CloseScreen; + ps->DestroyWindow = pScreen->DestroyWindow; + ps->StoreColors = pScreen->StoreColors; + pScreen->DestroyWindow = PictureDestroyWindow; + pScreen->CloseScreen = PictureCloseScreen; + pScreen->StoreColors = PictureStoreColors; + + if (!PictureSetDefaultFilters (pScreen)) + { + PictureResetFilters (pScreen); + SetPictureScreen(pScreen, 0); + xfree (formats); + xfree (ps); + return FALSE; + } + + return TRUE; +} + +void +SetPictureToDefaults (PicturePtr pPicture) +{ + pPicture->refcnt = 1; + pPicture->repeat = 0; + pPicture->graphicsExposures = FALSE; + pPicture->subWindowMode = ClipByChildren; + pPicture->polyEdge = PolyEdgeSharp; + pPicture->polyMode = PolyModePrecise; + pPicture->freeCompClip = FALSE; + pPicture->clientClipType = CT_NONE; + pPicture->componentAlpha = FALSE; + + pPicture->alphaMap = 0; + pPicture->alphaOrigin.x = 0; + pPicture->alphaOrigin.y = 0; + + pPicture->clipOrigin.x = 0; + pPicture->clipOrigin.y = 0; + pPicture->clientClip = 0; + + pPicture->transform = 0; + + pPicture->dither = None; + pPicture->filter = PictureGetFilterId (FilterNearest, -1, TRUE); + pPicture->filter_params = 0; + pPicture->filter_nparams = 0; + + pPicture->serialNumber = GC_CHANGE_SERIAL_BIT; + pPicture->stateChanges = (1 << (CPLastBit+1)) - 1; +} + +PicturePtr +AllocatePicture (ScreenPtr pScreen) +{ + PictureScreenPtr ps = GetPictureScreen(pScreen); + PicturePtr pPicture; + char *ptr; + DevUnion *ppriv; + unsigned int *sizes; + unsigned int size; + int i; + + pPicture = (PicturePtr) xalloc (ps->totalPictureSize); + if (!pPicture) + return 0; + ppriv = (DevUnion *)(pPicture + 1); + pPicture->devPrivates = ppriv; + sizes = ps->PicturePrivateSizes; + ptr = (char *)(ppriv + ps->PicturePrivateLen); + for (i = ps->PicturePrivateLen; --i >= 0; ppriv++, sizes++) + { + if ( (size = *sizes) ) + { + ppriv->ptr = (pointer)ptr; + ptr += size; + } + else + ppriv->ptr = (pointer)NULL; + } + return pPicture; +} + +PicturePtr +CreatePicture (Picture pid, + DrawablePtr pDrawable, + PictFormatPtr pFormat, + Mask vmask, + XID *vlist, + ClientPtr client, + int *error) +{ + PicturePtr pPicture; + PictureScreenPtr ps = GetPictureScreen(pDrawable->pScreen); + + pPicture = AllocatePicture (pDrawable->pScreen); + if (!pPicture) + { + *error = BadAlloc; + return 0; + } + + pPicture->id = pid; + pPicture->pDrawable = pDrawable; + pPicture->pFormat = pFormat; + pPicture->format = pFormat->format | (pDrawable->bitsPerPixel << 24); + if (pDrawable->type == DRAWABLE_PIXMAP) + { + ++((PixmapPtr)pDrawable)->refcnt; + pPicture->pNext = 0; + } + else + { + pPicture->pNext = GetPictureWindow(((WindowPtr) pDrawable)); + SetPictureWindow(((WindowPtr) pDrawable), pPicture); + } + + SetPictureToDefaults (pPicture); + + if (vmask) + *error = ChangePicture (pPicture, vmask, vlist, 0, client); + else + *error = Success; + if (*error == Success) + *error = (*ps->CreatePicture) (pPicture); + if (*error != Success) + { + FreePicture (pPicture, (XID) 0); + pPicture = 0; + } + return pPicture; +} + +#define NEXT_VAL(_type) (vlist ? (_type) *vlist++ : (_type) ulist++->val) + +#define NEXT_PTR(_type) ((_type) ulist++->ptr) + +int +ChangePicture (PicturePtr pPicture, + Mask vmask, + XID *vlist, + DevUnion *ulist, + ClientPtr client) +{ + ScreenPtr pScreen = pPicture->pDrawable->pScreen; + PictureScreenPtr ps = GetPictureScreen(pScreen); + BITS32 index2; + int error = 0; + BITS32 maskQ; + + pPicture->serialNumber |= GC_CHANGE_SERIAL_BIT; + maskQ = vmask; + while (vmask && !error) + { + index2 = (BITS32) lowbit (vmask); + vmask &= ~index2; + pPicture->stateChanges |= index2; + switch (index2) + { + case CPRepeat: + { + unsigned int newr; + newr = NEXT_VAL(unsigned int); + if (newr <= xTrue) + pPicture->repeat = newr; + else + { + client->errorValue = newr; + error = BadValue; + } + } + break; + case CPAlphaMap: + { + PicturePtr pAlpha; + + if (vlist) + { + Picture pid = NEXT_VAL(Picture); + + if (pid == None) + pAlpha = 0; + else + { + pAlpha = (PicturePtr) SecurityLookupIDByType(client, + pid, + PictureType, + SecurityWriteAccess|SecurityReadAccess); + if (!pAlpha) + { + client->errorValue = pid; + error = BadPixmap; + break; + } + if (pAlpha->pDrawable->type != DRAWABLE_PIXMAP) + { + client->errorValue = pid; + error = BadMatch; + break; + } + } + } + else + pAlpha = NEXT_PTR(PicturePtr); + if (!error) + { + if (pAlpha && pAlpha->pDrawable->type == DRAWABLE_PIXMAP) + pAlpha->refcnt++; + if (pPicture->alphaMap) + FreePicture ((pointer) pPicture->alphaMap, (XID) 0); + pPicture->alphaMap = pAlpha; + } + } + break; + case CPAlphaXOrigin: + pPicture->alphaOrigin.x = NEXT_VAL(INT16); + break; + case CPAlphaYOrigin: + pPicture->alphaOrigin.y = NEXT_VAL(INT16); + break; + case CPClipXOrigin: + pPicture->clipOrigin.x = NEXT_VAL(INT16); + break; + case CPClipYOrigin: + pPicture->clipOrigin.y = NEXT_VAL(INT16); + break; + case CPClipMask: + { + Pixmap pid; + PixmapPtr pPixmap; + int clipType; + + if (vlist) + { + pid = NEXT_VAL(Pixmap); + if (pid == None) + { + clipType = CT_NONE; + pPixmap = NullPixmap; + } + else + { + clipType = CT_PIXMAP; + pPixmap = (PixmapPtr)SecurityLookupIDByType(client, + pid, + RT_PIXMAP, + SecurityReadAccess); + if (!pPixmap) + { + client->errorValue = pid; + error = BadPixmap; + break; + } + } + } + else + { + pPixmap = NEXT_PTR(PixmapPtr); + if (pPixmap) + clipType = CT_PIXMAP; + else + clipType = CT_NONE; + } + + if (pPixmap) + { + if ((pPixmap->drawable.depth != 1) || + (pPixmap->drawable.pScreen != pScreen)) + { + error = BadMatch; + break; + } + else + { + clipType = CT_PIXMAP; + pPixmap->refcnt++; + } + } + error = (*ps->ChangePictureClip)(pPicture, clipType, + (pointer)pPixmap, 0); + break; + } + case CPGraphicsExposure: + { + unsigned int newe; + newe = NEXT_VAL(unsigned int); + if (newe <= xTrue) + pPicture->graphicsExposures = newe; + else + { + client->errorValue = newe; + error = BadValue; + } + } + break; + case CPSubwindowMode: + { + unsigned int news; + news = NEXT_VAL(unsigned int); + if (news == ClipByChildren || news == IncludeInferiors) + pPicture->subWindowMode = news; + else + { + client->errorValue = news; + error = BadValue; + } + } + break; + case CPPolyEdge: + { + unsigned int newe; + newe = NEXT_VAL(unsigned int); + if (newe == PolyEdgeSharp || newe == PolyEdgeSmooth) + pPicture->polyEdge = newe; + else + { + client->errorValue = newe; + error = BadValue; + } + } + break; + case CPPolyMode: + { + unsigned int newm; + newm = NEXT_VAL(unsigned int); + if (newm == PolyModePrecise || newm == PolyModeImprecise) + pPicture->polyMode = newm; + else + { + client->errorValue = newm; + error = BadValue; + } + } + break; + case CPDither: + pPicture->dither = NEXT_VAL(Atom); + break; + case CPComponentAlpha: + { + unsigned int newca; + + newca = NEXT_VAL (unsigned int); + if (newca <= xTrue) + pPicture->componentAlpha = newca; + else + { + client->errorValue = newca; + error = BadValue; + } + } + break; + default: + client->errorValue = maskQ; + error = BadValue; + break; + } + } + (*ps->ChangePicture) (pPicture, maskQ); + return error; +} + +int +SetPictureClipRects (PicturePtr pPicture, + int xOrigin, + int yOrigin, + int nRect, + xRectangle *rects) +{ + ScreenPtr pScreen = pPicture->pDrawable->pScreen; + PictureScreenPtr ps = GetPictureScreen(pScreen); + RegionPtr clientClip; + int result; + + clientClip = RECTS_TO_REGION(pScreen, + nRect, rects, CT_UNSORTED); + if (!clientClip) + return BadAlloc; + result =(*ps->ChangePictureClip) (pPicture, CT_REGION, + (pointer) clientClip, 0); + if (result == Success) + { + pPicture->clipOrigin.x = xOrigin; + pPicture->clipOrigin.y = yOrigin; + pPicture->stateChanges |= CPClipXOrigin|CPClipYOrigin|CPClipMask; + pPicture->serialNumber |= GC_CHANGE_SERIAL_BIT; + } + return result; +} + +int +SetPictureTransform (PicturePtr pPicture, + PictTransform *transform) +{ + static const PictTransform identity = { { + { xFixed1, 0x00000, 0x00000 }, + { 0x00000, xFixed1, 0x00000 }, + { 0x00000, 0x00000, xFixed1 }, + } }; + + if (transform && memcmp (transform, &identity, sizeof (PictTransform)) == 0) + transform = 0; + + if (transform) + { + if (!pPicture->transform) + { + pPicture->transform = (PictTransform *) xalloc (sizeof (PictTransform)); + if (!pPicture->transform) + return BadAlloc; + } + *pPicture->transform = *transform; + } + else + { + if (pPicture->transform) + { + xfree (pPicture->transform); + pPicture->transform = 0; + } + } + return Success; +} + +static void +ValidateOnePicture (PicturePtr pPicture) +{ + if (pPicture->serialNumber != pPicture->pDrawable->serialNumber) + { + PictureScreenPtr ps = GetPictureScreen(pPicture->pDrawable->pScreen); + + (*ps->ValidatePicture) (pPicture, pPicture->stateChanges); + pPicture->stateChanges = 0; + pPicture->serialNumber = pPicture->pDrawable->serialNumber; + } +} + +void +ValidatePicture(PicturePtr pPicture) +{ + ValidateOnePicture (pPicture); + if (pPicture->alphaMap) + ValidateOnePicture (pPicture->alphaMap); +} + +int +FreePicture (pointer value, + XID pid) +{ + PicturePtr pPicture = (PicturePtr) value; + + if (--pPicture->refcnt == 0) + { + ScreenPtr pScreen = pPicture->pDrawable->pScreen; + PictureScreenPtr ps = GetPictureScreen(pScreen); + + if (pPicture->alphaMap) + FreePicture ((pointer) pPicture->alphaMap, (XID) 0); + (*ps->DestroyPicture) (pPicture); + (*ps->DestroyPictureClip) (pPicture); + if (pPicture->transform) + xfree (pPicture->transform); + if (pPicture->pDrawable->type == DRAWABLE_WINDOW) + { + WindowPtr pWindow = (WindowPtr) pPicture->pDrawable; + PicturePtr *pPrev; + + for (pPrev = (PicturePtr *) &((pWindow)->devPrivates[PictureWindowPrivateIndex].ptr); + *pPrev; + pPrev = &(*pPrev)->pNext) + { + if (*pPrev == pPicture) + { + *pPrev = pPicture->pNext; + break; + } + } + } + else if (pPicture->pDrawable->type == DRAWABLE_PIXMAP) + { + (*pScreen->DestroyPixmap) ((PixmapPtr)pPicture->pDrawable); + } + xfree (pPicture); + } + return Success; +} + +int +FreePictFormat (pointer pPictFormat, + XID pid) +{ + return Success; +} + +void +CompositePicture (CARD8 op, + PicturePtr pSrc, + PicturePtr pMask, + PicturePtr pDst, + INT16 xSrc, + INT16 ySrc, + INT16 xMask, + INT16 yMask, + INT16 xDst, + INT16 yDst, + CARD16 width, + CARD16 height) +{ + PictureScreenPtr ps = GetPictureScreen(pDst->pDrawable->pScreen); + + ValidatePicture (pSrc); + if (pMask) + ValidatePicture (pMask); + ValidatePicture (pDst); + (*ps->Composite) (op, + pSrc, + pMask, + pDst, + xSrc, + ySrc, + xMask, + yMask, + xDst, + yDst, + width, + height); +} + +void +CompositeGlyphs (CARD8 op, + PicturePtr pSrc, + PicturePtr pDst, + PictFormatPtr maskFormat, + INT16 xSrc, + INT16 ySrc, + int nlist, + GlyphListPtr lists, + GlyphPtr *glyphs) +{ + PictureScreenPtr ps = GetPictureScreen(pDst->pDrawable->pScreen); + + ValidatePicture (pSrc); + ValidatePicture (pDst); + (*ps->Glyphs) (op, pSrc, pDst, maskFormat, xSrc, ySrc, nlist, lists, glyphs); +} + +void +CompositeRects (CARD8 op, + PicturePtr pDst, + xRenderColor *color, + int nRect, + xRectangle *rects) +{ + PictureScreenPtr ps = GetPictureScreen(pDst->pDrawable->pScreen); + + ValidatePicture (pDst); + (*ps->CompositeRects) (op, pDst, color, nRect, rects); +} + +void +CompositeTrapezoids (CARD8 op, + PicturePtr pSrc, + PicturePtr pDst, + PictFormatPtr maskFormat, + INT16 xSrc, + INT16 ySrc, + int ntrap, + xTrapezoid *traps) +{ + PictureScreenPtr ps = GetPictureScreen(pDst->pDrawable->pScreen); + + ValidatePicture (pSrc); + ValidatePicture (pDst); + (*ps->Trapezoids) (op, pSrc, pDst, maskFormat, xSrc, ySrc, ntrap, traps); +} + +void +CompositeTriangles (CARD8 op, + PicturePtr pSrc, + PicturePtr pDst, + PictFormatPtr maskFormat, + INT16 xSrc, + INT16 ySrc, + int ntriangles, + xTriangle *triangles) +{ + PictureScreenPtr ps = GetPictureScreen(pDst->pDrawable->pScreen); + + ValidatePicture (pSrc); + ValidatePicture (pDst); + (*ps->Triangles) (op, pSrc, pDst, maskFormat, xSrc, ySrc, ntriangles, triangles); +} + +void +CompositeTriStrip (CARD8 op, + PicturePtr pSrc, + PicturePtr pDst, + PictFormatPtr maskFormat, + INT16 xSrc, + INT16 ySrc, + int npoints, + xPointFixed *points) +{ + PictureScreenPtr ps = GetPictureScreen(pDst->pDrawable->pScreen); + + ValidatePicture (pSrc); + ValidatePicture (pDst); + (*ps->TriStrip) (op, pSrc, pDst, maskFormat, xSrc, ySrc, npoints, points); +} + +void +CompositeTriFan (CARD8 op, + PicturePtr pSrc, + PicturePtr pDst, + PictFormatPtr maskFormat, + INT16 xSrc, + INT16 ySrc, + int npoints, + xPointFixed *points) +{ + PictureScreenPtr ps = GetPictureScreen(pDst->pDrawable->pScreen); + + ValidatePicture (pSrc); + ValidatePicture (pDst); + (*ps->TriFan) (op, pSrc, pDst, maskFormat, xSrc, ySrc, npoints, points); +} + +typedef xFixed_32_32 xFixed_48_16; + +#define MAX_FIXED_48_16 ((xFixed_48_16) 0x7fffffff) +#define MIN_FIXED_48_16 (-((xFixed_48_16) 1 << 31)) + +Bool +PictureTransformPoint (PictTransformPtr transform, + PictVectorPtr vector) +{ + PictVector result; + int i, j; + xFixed_32_32 partial; + xFixed_48_16 v; + + for (j = 0; j < 3; j++) + { + v = 0; + for (i = 0; i < 3; i++) + { + partial = ((xFixed_48_16) transform->matrix[j][i] * + (xFixed_48_16) vector->vector[i]); + v += partial >> 16; + } + if (v > MAX_FIXED_48_16 || v < MIN_FIXED_48_16) + return FALSE; + result.vector[j] = (xFixed) v; + } + if (!result.vector[2]) + return FALSE; + for (j = 0; j < 2; j++) + { + partial = (xFixed_48_16) result.vector[j] << 16; + v = partial / result.vector[2]; + if (v > MAX_FIXED_48_16 || v < MIN_FIXED_48_16) + return FALSE; + vector->vector[j] = (xFixed) v; + } + vector->vector[2] = xFixed1; + return TRUE; +} diff --git a/render/picture.h b/render/picture.h new file mode 100644 index 000000000..2c2b1b3b4 --- /dev/null +++ b/render/picture.h @@ -0,0 +1,228 @@ +/* + * $XFree86: xc/programs/Xserver/render/picture.h,v 1.18 2002/11/06 22:45:36 keithp Exp $ + * + * Copyright © 2000 SuSE, Inc. + * + * 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 SuSE not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. SuSE makes no representations about the + * suitability of this software for any purpose. It is provided "as is" + * without express or implied warranty. + * + * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE + * 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. + * + * Author: Keith Packard, SuSE, Inc. + */ + +#ifndef _PICTURE_H_ +#define _PICTURE_H_ + +typedef struct _DirectFormat *DirectFormatPtr; +typedef struct _PictFormat *PictFormatPtr; +typedef struct _Picture *PicturePtr; + +/* + * While the protocol is generous in format support, the + * sample implementation allows only packed RGB and GBR + * representations for data to simplify software rendering, + */ +#define PICT_FORMAT(bpp,type,a,r,g,b) (((bpp) << 24) | \ + ((type) << 16) | \ + ((a) << 12) | \ + ((r) << 8) | \ + ((g) << 4) | \ + ((b))) + +/* + * gray/color formats use a visual index instead of argb + */ +#define PICT_VISFORMAT(bpp,type,vi) (((bpp) << 24) | \ + ((type) << 16) | \ + ((vi))) + +#define PICT_FORMAT_BPP(f) (((f) >> 24) ) +#define PICT_FORMAT_TYPE(f) (((f) >> 16) & 0xff) +#define PICT_FORMAT_A(f) (((f) >> 12) & 0x0f) +#define PICT_FORMAT_R(f) (((f) >> 8) & 0x0f) +#define PICT_FORMAT_G(f) (((f) >> 4) & 0x0f) +#define PICT_FORMAT_B(f) (((f) ) & 0x0f) +#define PICT_FORMAT_RGB(f) (((f) ) & 0xfff) +#define PICT_FORMAT_VIS(f) (((f) ) & 0xffff) + +#define PICT_TYPE_OTHER 0 +#define PICT_TYPE_A 1 +#define PICT_TYPE_ARGB 2 +#define PICT_TYPE_ABGR 3 +#define PICT_TYPE_COLOR 4 +#define PICT_TYPE_GRAY 5 + +#define PICT_FORMAT_COLOR(f) (PICT_FORMAT_TYPE(f) & 2) + +/* 32bpp formats */ +#define PICT_a8r8g8b8 PICT_FORMAT(32,PICT_TYPE_ARGB,8,8,8,8) +#define PICT_x8r8g8b8 PICT_FORMAT(32,PICT_TYPE_ARGB,0,8,8,8) +#define PICT_a8b8g8r8 PICT_FORMAT(32,PICT_TYPE_ABGR,8,8,8,8) +#define PICT_x8b8g8r8 PICT_FORMAT(32,PICT_TYPE_ABGR,0,8,8,8) + +/* 24bpp formats */ +#define PICT_r8g8b8 PICT_FORMAT(24,PICT_TYPE_ARGB,0,8,8,8) +#define PICT_b8g8r8 PICT_FORMAT(24,PICT_TYPE_ABGR,0,8,8,8) + +/* 16bpp formats */ +#define PICT_r5g6b5 PICT_FORMAT(16,PICT_TYPE_ARGB,0,5,6,5) +#define PICT_b5g6r5 PICT_FORMAT(16,PICT_TYPE_ABGR,0,5,6,5) + +#define PICT_a1r5g5b5 PICT_FORMAT(16,PICT_TYPE_ARGB,1,5,5,5) +#define PICT_x1r5g5b5 PICT_FORMAT(16,PICT_TYPE_ARGB,0,5,5,5) +#define PICT_a1b5g5r5 PICT_FORMAT(16,PICT_TYPE_ABGR,1,5,5,5) +#define PICT_x1b5g5r5 PICT_FORMAT(16,PICT_TYPE_ABGR,0,5,5,5) +#define PICT_a4r4g4b4 PICT_FORMAT(16,PICT_TYPE_ARGB,4,4,4,4) +#define PICT_x4r4g4b4 PICT_FORMAT(16,PICT_TYPE_ARGB,4,4,4,4) +#define PICT_a4b4g4r4 PICT_FORMAT(16,PICT_TYPE_ARGB,4,4,4,4) +#define PICT_x4b4g4r4 PICT_FORMAT(16,PICT_TYPE_ARGB,4,4,4,4) + +/* 8bpp formats */ +#define PICT_a8 PICT_FORMAT(8,PICT_TYPE_A,8,0,0,0) +#define PICT_r3g3b2 PICT_FORMAT(8,PICT_TYPE_ARGB,0,3,3,2) +#define PICT_b2g3r3 PICT_FORMAT(8,PICT_TYPE_ABGR,0,3,3,2) +#define PICT_a2r2g2b2 PICT_FORMAT(8,PICT_TYPE_ARGB,2,2,2,2) +#define PICT_a2b2g2r2 PICT_FORMAT(8,PICT_TYPE_ABGR,2,2,2,2) + +#define PICT_c8 PICT_FORMAT(8,PICT_TYPE_COLOR,0,0,0,0) +#define PICT_g8 PICT_FORMAT(8,PICT_TYPE_GRAY,0,0,0,0) + +/* 4bpp formats */ +#define PICT_a4 PICT_FORMAT(4,PICT_TYPE_A,4,0,0,0) +#define PICT_r1g2b1 PICT_FORMAT(4,PICT_TYPE_ARGB,0,1,2,1) +#define PICT_b1g2r1 PICT_FORMAT(4,PICT_TYPE_ABGR,0,1,2,1) +#define PICT_a1r1g1b1 PICT_FORMAT(4,PICT_TYPE_ARGB,1,1,1,1) +#define PICT_a1b1g1r1 PICT_FORMAT(4,PICT_TYPE_ABGR,1,1,1,1) + +#define PICT_c4 PICT_FORMAT(4,PICT_TYPE_COLOR,0,0,0,0) +#define PICT_g4 PICT_FORMAT(4,PICT_TYPE_GRAY,0,0,0,0) + +/* 1bpp formats */ +#define PICT_a1 PICT_FORMAT(1,PICT_TYPE_A,1,0,0,0) + +#define PICT_g1 PICT_FORMAT(1,PICT_TYPE_GRAY,0,0,0,0) + +/* + * For dynamic indexed visuals (GrayScale and PseudoColor), these control the + * selection of colors allocated for drawing to Pictures. The default + * policy depends on the size of the colormap: + * + * Size Default Policy + * ---------------------------- + * < 64 PolicyMono + * < 256 PolicyGray + * 256 PolicyColor (only on PseudoColor) + * + * The actual allocation code lives in miindex.c, and so is + * austensibly server dependent, but that code does: + * + * PolicyMono Allocate no additional colors, use black and white + * PolicyGray Allocate 13 gray levels (11 cells used) + * PolicyColor Allocate a 4x4x4 cube and 13 gray levels (71 cells used) + * PolicyAll Allocate as big a cube as possible, fill with gray (all) + * + * Here's a picture to help understand how many colors are + * actually allocated (this is just the gray ramp): + * + * gray level + * all 0000 1555 2aaa 4000 5555 6aaa 8000 9555 aaaa bfff d555 eaaa ffff + * b/w 0000 ffff + * 4x4x4 5555 aaaa + * extra 1555 2aaa 4000 6aaa 8000 9555 bfff d555 eaaa + * + * The default colormap supplies two gray levels (black/white), the + * 4x4x4 cube allocates another two and nine more are allocated to fill + * in the 13 levels. When the 4x4x4 cube is not allocated, a total of + * 11 cells are allocated. + */ + +#define PictureCmapPolicyInvalid -1 +#define PictureCmapPolicyDefault 0 +#define PictureCmapPolicyMono 1 +#define PictureCmapPolicyGray 2 +#define PictureCmapPolicyColor 3 +#define PictureCmapPolicyAll 4 + +extern int PictureCmapPolicy; + +int PictureParseCmapPolicy (const char *name); + +/* Fixed point updates from Carl Worth, USC, Information Sciences Institute */ + +#ifdef WIN32 +typedef __int64 xFixed_32_32; +#else +# if defined(__alpha__) || defined(__alpha) || \ + defined(ia64) || defined(__ia64__) || \ + defined(__sparc64__) || \ + defined(__s390x__) || \ + defined(x86_64) || defined (__x86_64__) +typedef long xFixed_32_32; +# else +# if defined(__GNUC__) && \ + ((__GNUC__ > 2) || \ + ((__GNUC__ == 2) && defined(__GNUC_MINOR__) && (__GNUC_MINOR__ > 7))) +__extension__ +# endif +typedef long long int xFixed_32_32; +# endif +#endif + +typedef CARD32 xFixed_1_31; +typedef CARD32 xFixed_1_16; +typedef INT32 xFixed_16_16; + +/* + * An unadorned "xFixed" is the same as xFixed_16_16, + * (since it's quite common in the code) + */ +typedef xFixed_16_16 xFixed; +#define XFIXED_BITS 16 + +#define xFixedToInt(f) (int) ((f) >> XFIXED_BITS) +#define IntToxFixed(i) ((xFixed) (i) << XFIXED_BITS) +#define xFixedE ((xFixed) 1) +#define xFixed1 (IntToxFixed(1)) +#define xFixed1MinusE (xFixed1 - xFixedE) +#define xFixedFrac(f) ((f) & xFixed1MinusE) +#define xFixedFloor(f) ((f) & ~xFixed1MinusE) +#define xFixedCeil(f) xFixedFloor((f) + xFixed1MinusE) + +#define xFixedFraction(f) ((f) & xFixed1MinusE) +#define xFixedMod2(f) ((f) & (xFixed1 | xFixed1MinusE)) + +/* whether 't' is a well defined not obviously empty trapezoid */ +#define xTrapezoidValid(t) ((t)->left.p1.y != (t)->left.p2.y && \ + (t)->right.p1.y != (t)->right.p2.y && \ + (int) ((t)->bottom - (t)->top) > 0) + +/* + * Standard NTSC luminance conversions: + * + * y = r * 0.299 + g * 0.587 + b * 0.114 + * + * Approximate this for a bit more speed: + * + * y = (r * 153 + g * 301 + b * 58) / 512 + * + * This gives 17 bits of luminance; to get 15 bits, lop the low two + */ + +#define CvtR8G8B8toY15(s) (((((s) >> 16) & 0xff) * 153 + \ + (((s) >> 8) & 0xff) * 301 + \ + (((s) ) & 0xff) * 58) >> 2) + +#endif /* _PICTURE_H_ */ diff --git a/render/picturestr.h b/render/picturestr.h new file mode 100644 index 000000000..cb5ea0ac9 --- /dev/null +++ b/render/picturestr.h @@ -0,0 +1,501 @@ +/* + * $XFree86: xc/programs/Xserver/render/picturestr.h,v 1.22 2002/11/23 02:38:15 keithp Exp $ + * + * Copyright © 2000 SuSE, Inc. + * + * 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 SuSE not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. SuSE makes no representations about the + * suitability of this software for any purpose. It is provided "as is" + * without express or implied warranty. + * + * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE + * 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. + * + * Author: Keith Packard, SuSE, Inc. + */ + +#ifndef _PICTURESTR_H_ +#define _PICTURESTR_H_ + +#include "glyphstr.h" +#include "scrnintstr.h" +#include "resource.h" + +typedef struct _DirectFormat { + CARD16 red, redMask; + CARD16 green, greenMask; + CARD16 blue, blueMask; + CARD16 alpha, alphaMask; +} DirectFormatRec; + +typedef struct _IndexFormat { + VisualPtr pVisual; + ColormapPtr pColormap; + int nvalues; + xIndexValue *pValues; + void *devPrivate; +} IndexFormatRec; + +typedef struct _PictFormat { + CARD32 id; + CARD32 format; /* except bpp */ + unsigned char type; + unsigned char depth; + DirectFormatRec direct; + IndexFormatRec index; +} PictFormatRec; + +typedef struct _PictVector { + xFixed vector[3]; +} PictVector, *PictVectorPtr; + +typedef struct _PictTransform { + xFixed matrix[3][3]; +} PictTransform, *PictTransformPtr; + +typedef struct _Picture { + DrawablePtr pDrawable; + PictFormatPtr pFormat; + CARD32 format; /* PICT_FORMAT */ + int refcnt; + CARD32 id; + PicturePtr pNext; /* chain on same drawable */ + + unsigned int repeat : 1; + unsigned int graphicsExposures : 1; + unsigned int subWindowMode : 1; + unsigned int polyEdge : 1; + unsigned int polyMode : 1; + unsigned int freeCompClip : 1; + unsigned int clientClipType : 2; + unsigned int componentAlpha : 1; + unsigned int unused : 23; + + PicturePtr alphaMap; + DDXPointRec alphaOrigin; + + DDXPointRec clipOrigin; + pointer clientClip; + + Atom dither; + + unsigned long stateChanges; + unsigned long serialNumber; + + RegionPtr pCompositeClip; + + DevUnion *devPrivates; + + PictTransform *transform; + + int filter; + xFixed *filter_params; + int filter_nparams; +} PictureRec; + +typedef struct { + char *name; + xFixed *params; + int nparams; + int id; +} PictFilterRec, *PictFilterPtr; + +#define PictFilterNearest 0 +#define PictFilterBilinear 1 + +#define PictFilterFast 2 +#define PictFilterGood 3 +#define PictFilterBest 4 + +typedef struct { + char *alias; + int alias_id; + int filter_id; +} PictFilterAliasRec, *PictFilterAliasPtr; + +typedef int (*CreatePictureProcPtr) (PicturePtr pPicture); +typedef void (*DestroyPictureProcPtr) (PicturePtr pPicture); +typedef int (*ChangePictureClipProcPtr) (PicturePtr pPicture, + int clipType, + pointer value, + int n); +typedef void (*DestroyPictureClipProcPtr)(PicturePtr pPicture); + +typedef int (*ChangePictureTransformProcPtr) (PicturePtr pPicture, + PictTransform *transform); + +typedef int (*ChangePictureFilterProcPtr) (PicturePtr pPicture, + int filter, + xFixed *params, + int nparams); + +typedef void (*DestroyPictureFilterProcPtr) (PicturePtr pPicture); + +typedef void (*ChangePictureProcPtr) (PicturePtr pPicture, + Mask mask); +typedef void (*ValidatePictureProcPtr) (PicturePtr pPicture, + Mask mask); +typedef void (*CompositeProcPtr) (CARD8 op, + PicturePtr pSrc, + PicturePtr pMask, + PicturePtr pDst, + INT16 xSrc, + INT16 ySrc, + INT16 xMask, + INT16 yMask, + INT16 xDst, + INT16 yDst, + CARD16 width, + CARD16 height); + +typedef void (*GlyphsProcPtr) (CARD8 op, + PicturePtr pSrc, + PicturePtr pDst, + PictFormatPtr maskFormat, + INT16 xSrc, + INT16 ySrc, + int nlists, + GlyphListPtr lists, + GlyphPtr *glyphs); + +typedef void (*CompositeRectsProcPtr) (CARD8 op, + PicturePtr pDst, + xRenderColor *color, + int nRect, + xRectangle *rects); + +typedef void (*RasterizeTrapezoidProcPtr)(PicturePtr pMask, + xTrapezoid *trap, + int x_off, + int y_off); + +typedef void (*TrapezoidsProcPtr) (CARD8 op, + PicturePtr pSrc, + PicturePtr pDst, + PictFormatPtr maskFormat, + INT16 xSrc, + INT16 ySrc, + int ntrap, + xTrapezoid *traps); + +typedef void (*TrianglesProcPtr) (CARD8 op, + PicturePtr pSrc, + PicturePtr pDst, + PictFormatPtr maskFormat, + INT16 xSrc, + INT16 ySrc, + int ntri, + xTriangle *tris); + +typedef void (*TriStripProcPtr) (CARD8 op, + PicturePtr pSrc, + PicturePtr pDst, + PictFormatPtr maskFormat, + INT16 xSrc, + INT16 ySrc, + int npoint, + xPointFixed *points); + +typedef void (*TriFanProcPtr) (CARD8 op, + PicturePtr pSrc, + PicturePtr pDst, + PictFormatPtr maskFormat, + INT16 xSrc, + INT16 ySrc, + int npoint, + xPointFixed *points); + +typedef Bool (*InitIndexedProcPtr) (ScreenPtr pScreen, + PictFormatPtr pFormat); + +typedef void (*CloseIndexedProcPtr) (ScreenPtr pScreen, + PictFormatPtr pFormat); + +typedef void (*UpdateIndexedProcPtr) (ScreenPtr pScreen, + PictFormatPtr pFormat, + int ndef, + xColorItem *pdef); + +typedef struct _PictureScreen { + int totalPictureSize; + unsigned int *PicturePrivateSizes; + int PicturePrivateLen; + + PictFormatPtr formats; + PictFormatPtr fallback; + int nformats; + + CreatePictureProcPtr CreatePicture; + DestroyPictureProcPtr DestroyPicture; + ChangePictureClipProcPtr ChangePictureClip; + DestroyPictureClipProcPtr DestroyPictureClip; + + ChangePictureProcPtr ChangePicture; + ValidatePictureProcPtr ValidatePicture; + + CompositeProcPtr Composite; + GlyphsProcPtr Glyphs; + CompositeRectsProcPtr CompositeRects; + + DestroyWindowProcPtr DestroyWindow; + CloseScreenProcPtr CloseScreen; + + StoreColorsProcPtr StoreColors; + + InitIndexedProcPtr InitIndexed; + CloseIndexedProcPtr CloseIndexed; + UpdateIndexedProcPtr UpdateIndexed; + + int subpixel; + + PictFilterPtr filters; + int nfilters; + PictFilterAliasPtr filterAliases; + int nfilterAliases; + + ChangePictureTransformProcPtr ChangePictureTransform; + ChangePictureFilterProcPtr ChangePictureFilter; + DestroyPictureFilterProcPtr DestroyPictureFilter; + + TrapezoidsProcPtr Trapezoids; + TrianglesProcPtr Triangles; + TriStripProcPtr TriStrip; + TriFanProcPtr TriFan; + + RasterizeTrapezoidProcPtr RasterizeTrapezoid; +} PictureScreenRec, *PictureScreenPtr; + +extern int PictureScreenPrivateIndex; +extern int PictureWindowPrivateIndex; +extern RESTYPE PictureType; +extern RESTYPE PictFormatType; +extern RESTYPE GlyphSetType; + +#define GetPictureScreen(s) ((PictureScreenPtr) ((s)->devPrivates[PictureScreenPrivateIndex].ptr)) +#define GetPictureScreenIfSet(s) ((PictureScreenPrivateIndex != -1) ? GetPictureScreen(s) : NULL) +#define SetPictureScreen(s,p) ((s)->devPrivates[PictureScreenPrivateIndex].ptr = (pointer) (p)) +#define GetPictureWindow(w) ((PicturePtr) ((w)->devPrivates[PictureWindowPrivateIndex].ptr)) +#define SetPictureWindow(w,p) ((w)->devPrivates[PictureWindowPrivateIndex].ptr = (pointer) (p)) + +#define VERIFY_PICTURE(pPicture, pid, client, mode, err) {\ + pPicture = SecurityLookupIDByType(client, pid, PictureType, mode);\ + if (!pPicture) { \ + client->errorValue = pid; \ + return err; \ + } \ +} + +#define VERIFY_ALPHA(pPicture, pid, client, mode, err) {\ + if (pid == None) \ + pPicture = 0; \ + else { \ + VERIFY_PICTURE(pPicture, pid, client, mode, err); \ + } \ +} \ + +Bool +PictureDestroyWindow (WindowPtr pWindow); + +Bool +PictureCloseScreen (int Index, ScreenPtr pScreen); + +void +PictureStoreColors (ColormapPtr pColormap, int ndef, xColorItem *pdef); + +Bool +PictureInitIndexedFormats (ScreenPtr pScreen); + +Bool +PictureSetSubpixelOrder (ScreenPtr pScreen, int subpixel); + +int +PictureGetSubpixelOrder (ScreenPtr pScreen); + +PictFormatPtr +PictureCreateDefaultFormats (ScreenPtr pScreen, int *nformatp); + +PictFormatPtr +PictureMatchVisual (ScreenPtr pScreen, int depth, VisualPtr pVisual); + +PictFormatPtr +PictureMatchFormat (ScreenPtr pScreen, int depth, CARD32 format); + +Bool +PictureInit (ScreenPtr pScreen, PictFormatPtr formats, int nformats); + +int +PictureGetFilterId (char *filter, int len, Bool makeit); + +char * +PictureGetFilterName (int id); + +int +PictureAddFilter (ScreenPtr pScreen, char *filter, xFixed *params, int nparams); + +Bool +PictureSetFilterAlias (ScreenPtr pScreen, char *filter, char *alias); + +Bool +PictureSetDefaultFilters (ScreenPtr pScreen); + +void +PictureResetFilters (ScreenPtr pScreen); + +PictFilterPtr +PictureFindFilter (ScreenPtr pScreen, char *name, int len); + +int +SetPictureFilter (PicturePtr pPicture, char *name, int len, xFixed *params, int nparams); + +Bool +PictureFinishInit (void); + +void +SetPictureToDefaults (PicturePtr pPicture); + +PicturePtr +AllocatePicture (ScreenPtr pScreen); + +#if 0 +Bool +miPictureInit (ScreenPtr pScreen, PictFormatPtr formats, int nformats); +#endif + + +PicturePtr +CreatePicture (Picture pid, + DrawablePtr pDrawable, + PictFormatPtr pFormat, + Mask mask, + XID *list, + ClientPtr client, + int *error); + +int +ChangePicture (PicturePtr pPicture, + Mask vmask, + XID *vlist, + DevUnion *ulist, + ClientPtr client); + +int +SetPictureClipRects (PicturePtr pPicture, + int xOrigin, + int yOrigin, + int nRect, + xRectangle *rects); + +int +SetPictureTransform (PicturePtr pPicture, + PictTransform *transform); + +void +ValidatePicture(PicturePtr pPicture); + +int +FreePicture (pointer pPicture, + XID pid); + +int +FreePictFormat (pointer pPictFormat, + XID pid); + +void +CompositePicture (CARD8 op, + PicturePtr pSrc, + PicturePtr pMask, + PicturePtr pDst, + INT16 xSrc, + INT16 ySrc, + INT16 xMask, + INT16 yMask, + INT16 xDst, + INT16 yDst, + CARD16 width, + CARD16 height); + +void +CompositeGlyphs (CARD8 op, + PicturePtr pSrc, + PicturePtr pDst, + PictFormatPtr maskFormat, + INT16 xSrc, + INT16 ySrc, + int nlist, + GlyphListPtr lists, + GlyphPtr *glyphs); + +void +CompositeRects (CARD8 op, + PicturePtr pDst, + xRenderColor *color, + int nRect, + xRectangle *rects); + +void +CompositeTrapezoids (CARD8 op, + PicturePtr pSrc, + PicturePtr pDst, + PictFormatPtr maskFormat, + INT16 xSrc, + INT16 ySrc, + int ntrap, + xTrapezoid *traps); + +void +CompositeTriangles (CARD8 op, + PicturePtr pSrc, + PicturePtr pDst, + PictFormatPtr maskFormat, + INT16 xSrc, + INT16 ySrc, + int ntriangles, + xTriangle *triangles); + +void +CompositeTriStrip (CARD8 op, + PicturePtr pSrc, + PicturePtr pDst, + PictFormatPtr maskFormat, + INT16 xSrc, + INT16 ySrc, + int npoints, + xPointFixed *points); + +void +CompositeTriFan (CARD8 op, + PicturePtr pSrc, + PicturePtr pDst, + PictFormatPtr maskFormat, + INT16 xSrc, + INT16 ySrc, + int npoints, + xPointFixed *points); + +Bool +PictureTransformPoint (PictTransformPtr transform, + PictVectorPtr vector); + +void RenderExtensionInit (void); + +Bool +AnimCurInit (ScreenPtr pScreen); + +int +AnimCursorCreate (CursorPtr *cursors, CARD32 *deltas, int ncursor, CursorPtr *ppCursor); + +#ifdef PANORAMIX +void PanoramiXRenderInit (void); +void PanoramiXRenderReset (void); +#endif + +#endif /* _PICTURESTR_H_ */ diff --git a/render/render.c b/render/render.c new file mode 100644 index 000000000..a4f90ea77 --- /dev/null +++ b/render/render.c @@ -0,0 +1,2584 @@ +/* + * $XFree86: xc/programs/Xserver/render/render.c,v 1.26 2003/02/14 18:15:21 dawes Exp $ + * + * Copyright © 2000 SuSE, Inc. + * + * 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 SuSE not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. SuSE makes no representations about the + * suitability of this software for any purpose. It is provided "as is" + * without express or implied warranty. + * + * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE + * 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. + * + * Author: Keith Packard, SuSE, Inc. + */ + +#define NEED_REPLIES +#define NEED_EVENTS +#include "X.h" +#include "Xproto.h" +#include "misc.h" +#include "os.h" +#include "dixstruct.h" +#include "resource.h" +#include "scrnintstr.h" +#include "windowstr.h" +#include "pixmapstr.h" +#include "colormapst.h" +#include "extnsionst.h" +#include "servermd.h" +#include "render.h" +#include "renderproto.h" +#include "picturestr.h" +#include "glyphstr.h" +#include "Xfuncproto.h" +#include "cursorstr.h" +#ifdef EXTMODULE +#include "xf86_ansic.h" +#endif + +static int ProcRenderQueryVersion (ClientPtr pClient); +static int ProcRenderQueryPictFormats (ClientPtr pClient); +static int ProcRenderQueryPictIndexValues (ClientPtr pClient); +static int ProcRenderQueryDithers (ClientPtr pClient); +static int ProcRenderCreatePicture (ClientPtr pClient); +static int ProcRenderChangePicture (ClientPtr pClient); +static int ProcRenderSetPictureClipRectangles (ClientPtr pClient); +static int ProcRenderFreePicture (ClientPtr pClient); +static int ProcRenderComposite (ClientPtr pClient); +static int ProcRenderScale (ClientPtr pClient); +static int ProcRenderTrapezoids (ClientPtr pClient); +static int ProcRenderTriangles (ClientPtr pClient); +static int ProcRenderTriStrip (ClientPtr pClient); +static int ProcRenderTriFan (ClientPtr pClient); +static int ProcRenderColorTrapezoids (ClientPtr pClient); +static int ProcRenderColorTriangles (ClientPtr pClient); +static int ProcRenderTransform (ClientPtr pClient); +static int ProcRenderCreateGlyphSet (ClientPtr pClient); +static int ProcRenderReferenceGlyphSet (ClientPtr pClient); +static int ProcRenderFreeGlyphSet (ClientPtr pClient); +static int ProcRenderAddGlyphs (ClientPtr pClient); +static int ProcRenderAddGlyphsFromPicture (ClientPtr pClient); +static int ProcRenderFreeGlyphs (ClientPtr pClient); +static int ProcRenderCompositeGlyphs (ClientPtr pClient); +static int ProcRenderFillRectangles (ClientPtr pClient); +static int ProcRenderCreateCursor (ClientPtr pClient); +static int ProcRenderSetPictureTransform (ClientPtr pClient); +static int ProcRenderQueryFilters (ClientPtr pClient); +static int ProcRenderSetPictureFilter (ClientPtr pClient); +static int ProcRenderCreateAnimCursor (ClientPtr pClient); + +static int ProcRenderDispatch (ClientPtr pClient); + +static int SProcRenderQueryVersion (ClientPtr pClient); +static int SProcRenderQueryPictFormats (ClientPtr pClient); +static int SProcRenderQueryPictIndexValues (ClientPtr pClient); +static int SProcRenderQueryDithers (ClientPtr pClient); +static int SProcRenderCreatePicture (ClientPtr pClient); +static int SProcRenderChangePicture (ClientPtr pClient); +static int SProcRenderSetPictureClipRectangles (ClientPtr pClient); +static int SProcRenderFreePicture (ClientPtr pClient); +static int SProcRenderComposite (ClientPtr pClient); +static int SProcRenderScale (ClientPtr pClient); +static int SProcRenderTrapezoids (ClientPtr pClient); +static int SProcRenderTriangles (ClientPtr pClient); +static int SProcRenderTriStrip (ClientPtr pClient); +static int SProcRenderTriFan (ClientPtr pClient); +static int SProcRenderColorTrapezoids (ClientPtr pClient); +static int SProcRenderColorTriangles (ClientPtr pClient); +static int SProcRenderTransform (ClientPtr pClient); +static int SProcRenderCreateGlyphSet (ClientPtr pClient); +static int SProcRenderReferenceGlyphSet (ClientPtr pClient); +static int SProcRenderFreeGlyphSet (ClientPtr pClient); +static int SProcRenderAddGlyphs (ClientPtr pClient); +static int SProcRenderAddGlyphsFromPicture (ClientPtr pClient); +static int SProcRenderFreeGlyphs (ClientPtr pClient); +static int SProcRenderCompositeGlyphs (ClientPtr pClient); +static int SProcRenderFillRectangles (ClientPtr pClient); +static int SProcRenderCreateCursor (ClientPtr pClient); +static int SProcRenderSetPictureTransform (ClientPtr pClient); +static int SProcRenderQueryFilters (ClientPtr pClient); +static int SProcRenderSetPictureFilter (ClientPtr pClient); +static int SProcRenderCreateAnimCursor (ClientPtr pClient); + +static int SProcRenderDispatch (ClientPtr pClient); + +int (*ProcRenderVector[RenderNumberRequests])(ClientPtr) = { + ProcRenderQueryVersion, + ProcRenderQueryPictFormats, + ProcRenderQueryPictIndexValues, + ProcRenderQueryDithers, + ProcRenderCreatePicture, + ProcRenderChangePicture, + ProcRenderSetPictureClipRectangles, + ProcRenderFreePicture, + ProcRenderComposite, + ProcRenderScale, + ProcRenderTrapezoids, + ProcRenderTriangles, + ProcRenderTriStrip, + ProcRenderTriFan, + ProcRenderColorTrapezoids, + ProcRenderColorTriangles, + ProcRenderTransform, + ProcRenderCreateGlyphSet, + ProcRenderReferenceGlyphSet, + ProcRenderFreeGlyphSet, + ProcRenderAddGlyphs, + ProcRenderAddGlyphsFromPicture, + ProcRenderFreeGlyphs, + ProcRenderCompositeGlyphs, + ProcRenderCompositeGlyphs, + ProcRenderCompositeGlyphs, + ProcRenderFillRectangles, + ProcRenderCreateCursor, + ProcRenderSetPictureTransform, + ProcRenderQueryFilters, + ProcRenderSetPictureFilter, + ProcRenderCreateAnimCursor, +}; + +int (*SProcRenderVector[RenderNumberRequests])(ClientPtr) = { + SProcRenderQueryVersion, + SProcRenderQueryPictFormats, + SProcRenderQueryPictIndexValues, + SProcRenderQueryDithers, + SProcRenderCreatePicture, + SProcRenderChangePicture, + SProcRenderSetPictureClipRectangles, + SProcRenderFreePicture, + SProcRenderComposite, + SProcRenderScale, + SProcRenderTrapezoids, + SProcRenderTriangles, + SProcRenderTriStrip, + SProcRenderTriFan, + SProcRenderColorTrapezoids, + SProcRenderColorTriangles, + SProcRenderTransform, + SProcRenderCreateGlyphSet, + SProcRenderReferenceGlyphSet, + SProcRenderFreeGlyphSet, + SProcRenderAddGlyphs, + SProcRenderAddGlyphsFromPicture, + SProcRenderFreeGlyphs, + SProcRenderCompositeGlyphs, + SProcRenderCompositeGlyphs, + SProcRenderCompositeGlyphs, + SProcRenderFillRectangles, + SProcRenderCreateCursor, + SProcRenderSetPictureTransform, + SProcRenderQueryFilters, + SProcRenderSetPictureFilter, + SProcRenderCreateAnimCursor, +}; + +static void +RenderResetProc (ExtensionEntry *extEntry); + +static CARD8 RenderReqCode; +int RenderErrBase; +int RenderClientPrivateIndex; + +typedef struct _RenderClient { + int major_version; + int minor_version; +} RenderClientRec, *RenderClientPtr; + +#define GetRenderClient(pClient) ((RenderClientPtr) (pClient)->devPrivates[RenderClientPrivateIndex].ptr) + +static void +RenderClientCallback (CallbackListPtr *list, + pointer closure, + pointer data) +{ + NewClientInfoRec *clientinfo = (NewClientInfoRec *) data; + ClientPtr pClient = clientinfo->client; + RenderClientPtr pRenderClient = GetRenderClient (pClient); + + pRenderClient->major_version = 0; + pRenderClient->minor_version = 0; +} + +void +RenderExtensionInit (void) +{ + ExtensionEntry *extEntry; + + if (!PictureType) + return; + if (!PictureFinishInit ()) + return; + RenderClientPrivateIndex = AllocateClientPrivateIndex (); + if (!AllocateClientPrivate (RenderClientPrivateIndex, + sizeof (RenderClientRec))) + return; + if (!AddCallback (&ClientStateCallback, RenderClientCallback, 0)) + return; + + extEntry = AddExtension (RENDER_NAME, 0, RenderNumberErrors, + ProcRenderDispatch, SProcRenderDispatch, + RenderResetProc, StandardMinorOpcode); + if (!extEntry) + return; + RenderReqCode = (CARD8) extEntry->base; + RenderErrBase = extEntry->errorBase; +} + +static void +RenderResetProc (ExtensionEntry *extEntry) +{ +} + +static int +ProcRenderQueryVersion (ClientPtr client) +{ + RenderClientPtr pRenderClient = GetRenderClient (client); + xRenderQueryVersionReply rep; + register int n; + REQUEST(xRenderQueryVersionReq); + + pRenderClient->major_version = stuff->majorVersion; + pRenderClient->minor_version = stuff->minorVersion; + + REQUEST_SIZE_MATCH(xRenderQueryVersionReq); + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + rep.majorVersion = RENDER_MAJOR; + rep.minorVersion = RENDER_MINOR; + if (client->swapped) { + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + swapl(&rep.majorVersion, n); + swapl(&rep.minorVersion, n); + } + WriteToClient(client, sizeof(xRenderQueryVersionReply), (char *)&rep); + return (client->noClientException); +} + +#if 0 +static int +VisualDepth (ScreenPtr pScreen, VisualPtr pVisual) +{ + DepthPtr pDepth; + int d, v; + + for (d = 0; d < pScreen->numDepths; d++) + { + pDepth = pScreen->allowedDepths + d; + for (v = 0; v < pDepth->numVids; v++) + { + if (pDepth->vids[v] == pVisual->vid) + return pDepth->depth; + } + } + return 0; +} +#endif + +static VisualPtr +findVisual (ScreenPtr pScreen, VisualID vid) +{ + VisualPtr pVisual; + int v; + + for (v = 0; v < pScreen->numVisuals; v++) + { + pVisual = pScreen->visuals + v; + if (pVisual->vid == vid) + return pVisual; + } + return 0; +} + +extern char *ConnectionInfo; + +static int +ProcRenderQueryPictFormats (ClientPtr client) +{ + RenderClientPtr pRenderClient = GetRenderClient (client); + xRenderQueryPictFormatsReply *reply; + xPictScreen *pictScreen; + xPictDepth *pictDepth; + xPictVisual *pictVisual; + xPictFormInfo *pictForm; + CARD32 *pictSubpixel; + ScreenPtr pScreen; + VisualPtr pVisual; + DepthPtr pDepth; + int v, d; + PictureScreenPtr ps; + PictFormatPtr pFormat; + int nformat; + int ndepth; + int nvisual; + int rlength; + int s; + int n; + int numScreens; + int numSubpixel; +/* REQUEST(xRenderQueryPictFormatsReq); */ + + REQUEST_SIZE_MATCH(xRenderQueryPictFormatsReq); + +#ifdef PANORAMIX + if (noPanoramiXExtension) + numScreens = screenInfo.numScreens; + else + numScreens = ((xConnSetup *)ConnectionInfo)->numRoots; +#else + numScreens = screenInfo.numScreens; +#endif + ndepth = nformat = nvisual = 0; + for (s = 0; s < numScreens; s++) + { + pScreen = screenInfo.screens[s]; + for (d = 0; d < pScreen->numDepths; d++) + { + pDepth = pScreen->allowedDepths + d; + ++ndepth; + + for (v = 0; v < pDepth->numVids; v++) + { + pVisual = findVisual (pScreen, pDepth->vids[v]); + if (pVisual && PictureMatchVisual (pScreen, pDepth->depth, pVisual)) + ++nvisual; + } + } + ps = GetPictureScreenIfSet(pScreen); + if (ps) + nformat += ps->nformats; + } + if (pRenderClient->major_version == 0 && pRenderClient->minor_version < 6) + numSubpixel = 0; + else + numSubpixel = numScreens; + + rlength = (sizeof (xRenderQueryPictFormatsReply) + + nformat * sizeof (xPictFormInfo) + + numScreens * sizeof (xPictScreen) + + ndepth * sizeof (xPictDepth) + + nvisual * sizeof (xPictVisual) + + numSubpixel * sizeof (CARD32)); + reply = (xRenderQueryPictFormatsReply *) xalloc (rlength); + if (!reply) + return BadAlloc; + reply->type = X_Reply; + reply->sequenceNumber = client->sequence; + reply->length = (rlength - sizeof(xGenericReply)) >> 2; + reply->numFormats = nformat; + reply->numScreens = numScreens; + reply->numDepths = ndepth; + reply->numVisuals = nvisual; + reply->numSubpixel = numSubpixel; + + pictForm = (xPictFormInfo *) (reply + 1); + + for (s = 0; s < numScreens; s++) + { + pScreen = screenInfo.screens[s]; + ps = GetPictureScreenIfSet(pScreen); + if (ps) + { + for (nformat = 0, pFormat = ps->formats; + nformat < ps->nformats; + nformat++, pFormat++) + { + pictForm->id = pFormat->id; + pictForm->type = pFormat->type; + pictForm->depth = pFormat->depth; + pictForm->direct.red = pFormat->direct.red; + pictForm->direct.redMask = pFormat->direct.redMask; + pictForm->direct.green = pFormat->direct.green; + pictForm->direct.greenMask = pFormat->direct.greenMask; + pictForm->direct.blue = pFormat->direct.blue; + pictForm->direct.blueMask = pFormat->direct.blueMask; + pictForm->direct.alpha = pFormat->direct.alpha; + pictForm->direct.alphaMask = pFormat->direct.alphaMask; + if (pFormat->type == PictTypeIndexed && pFormat->index.pColormap) + pictForm->colormap = pFormat->index.pColormap->mid; + else + pictForm->colormap = None; + if (client->swapped) + { + swapl (&pictForm->id, n); + swaps (&pictForm->direct.red, n); + swaps (&pictForm->direct.redMask, n); + swaps (&pictForm->direct.green, n); + swaps (&pictForm->direct.greenMask, n); + swaps (&pictForm->direct.blue, n); + swaps (&pictForm->direct.blueMask, n); + swaps (&pictForm->direct.alpha, n); + swaps (&pictForm->direct.alphaMask, n); + swapl (&pictForm->colormap, n); + } + pictForm++; + } + } + } + + pictScreen = (xPictScreen *) pictForm; + for (s = 0; s < numScreens; s++) + { + pScreen = screenInfo.screens[s]; + pictDepth = (xPictDepth *) (pictScreen + 1); + ndepth = 0; + for (d = 0; d < pScreen->numDepths; d++) + { + pictVisual = (xPictVisual *) (pictDepth + 1); + pDepth = pScreen->allowedDepths + d; + + nvisual = 0; + for (v = 0; v < pDepth->numVids; v++) + { + pVisual = findVisual (pScreen, pDepth->vids[v]); + if (pVisual && (pFormat = PictureMatchVisual (pScreen, + pDepth->depth, + pVisual))) + { + pictVisual->visual = pVisual->vid; + pictVisual->format = pFormat->id; + if (client->swapped) + { + swapl (&pictVisual->visual, n); + swapl (&pictVisual->format, n); + } + pictVisual++; + nvisual++; + } + } + pictDepth->depth = pDepth->depth; + pictDepth->nPictVisuals = nvisual; + if (client->swapped) + { + swaps (&pictDepth->nPictVisuals, n); + } + ndepth++; + pictDepth = (xPictDepth *) pictVisual; + } + pictScreen->nDepth = ndepth; + ps = GetPictureScreenIfSet(pScreen); + if (ps) + pictScreen->fallback = ps->fallback->id; + else + pictScreen->fallback = 0; + if (client->swapped) + { + swapl (&pictScreen->nDepth, n); + swapl (&pictScreen->fallback, n); + } + pictScreen = (xPictScreen *) pictDepth; + } + pictSubpixel = (CARD32 *) pictScreen; + + for (s = 0; s < numSubpixel; s++) + { + pScreen = screenInfo.screens[s]; + ps = GetPictureScreenIfSet(pScreen); + if (ps) + *pictSubpixel = ps->subpixel; + else + *pictSubpixel = SubPixelUnknown; + if (client->swapped) + { + swapl (pictSubpixel, n); + } + ++pictSubpixel; + } + + if (client->swapped) + { + swaps (&reply->sequenceNumber, n); + swapl (&reply->length, n); + swapl (&reply->numFormats, n); + swapl (&reply->numScreens, n); + swapl (&reply->numDepths, n); + swapl (&reply->numVisuals, n); + swapl (&reply->numSubpixel, n); + } + WriteToClient(client, rlength, (char *) reply); + xfree (reply); + return client->noClientException; +} + +static int +ProcRenderQueryPictIndexValues (ClientPtr client) +{ + PictFormatPtr pFormat; + int num; + int rlength; + int i, n; + REQUEST(xRenderQueryPictIndexValuesReq); + xRenderQueryPictIndexValuesReply *reply; + xIndexValue *values; + + REQUEST_AT_LEAST_SIZE(xRenderQueryPictIndexValuesReq); + + pFormat = (PictFormatPtr) SecurityLookupIDByType (client, + stuff->format, + PictFormatType, + SecurityReadAccess); + + if (!pFormat) + { + client->errorValue = stuff->format; + return RenderErrBase + BadPictFormat; + } + if (pFormat->type != PictTypeIndexed) + { + client->errorValue = stuff->format; + return BadMatch; + } + num = pFormat->index.nvalues; + rlength = (sizeof (xRenderQueryPictIndexValuesReply) + + num * sizeof(xIndexValue)); + reply = (xRenderQueryPictIndexValuesReply *) xalloc (rlength); + if (!reply) + return BadAlloc; + + reply->type = X_Reply; + reply->sequenceNumber = client->sequence; + reply->length = (rlength - sizeof(xGenericReply)) >> 2; + reply->numIndexValues = num; + + values = (xIndexValue *) (reply + 1); + + memcpy (reply + 1, pFormat->index.pValues, num * sizeof (xIndexValue)); + + if (client->swapped) + { + for (i = 0; i < num; i++) + { + swapl (&values[i].pixel, n); + swaps (&values[i].red, n); + swaps (&values[i].green, n); + swaps (&values[i].blue, n); + swaps (&values[i].alpha, n); + } + swaps (&reply->sequenceNumber, n); + swapl (&reply->length, n); + swapl (&reply->numIndexValues, n); + } + + WriteToClient(client, rlength, (char *) reply); + xfree(reply); + return (client->noClientException); +} + +static int +ProcRenderQueryDithers (ClientPtr client) +{ + return BadImplementation; +} + +static int +ProcRenderCreatePicture (ClientPtr client) +{ + PicturePtr pPicture; + DrawablePtr pDrawable; + PictFormatPtr pFormat; + int len; + int error; + REQUEST(xRenderCreatePictureReq); + + REQUEST_AT_LEAST_SIZE(xRenderCreatePictureReq); + + LEGAL_NEW_RESOURCE(stuff->pid, client); + SECURITY_VERIFY_DRAWABLE(pDrawable, stuff->drawable, client, + SecurityWriteAccess); + pFormat = (PictFormatPtr) SecurityLookupIDByType (client, + stuff->format, + PictFormatType, + SecurityReadAccess); + if (!pFormat) + { + client->errorValue = stuff->format; + return RenderErrBase + BadPictFormat; + } + if (pFormat->depth != pDrawable->depth) + return BadMatch; + len = client->req_len - (sizeof(xRenderCreatePictureReq) >> 2); + if (Ones(stuff->mask) != len) + return BadLength; + + pPicture = CreatePicture (stuff->pid, + pDrawable, + pFormat, + stuff->mask, + (XID *) (stuff + 1), + client, + &error); + if (!pPicture) + return error; + if (!AddResource (stuff->pid, PictureType, (pointer)pPicture)) + return BadAlloc; + return Success; +} + +static int +ProcRenderChangePicture (ClientPtr client) +{ + PicturePtr pPicture; + REQUEST(xRenderChangePictureReq); + int len; + + REQUEST_AT_LEAST_SIZE(xRenderChangePictureReq); + VERIFY_PICTURE (pPicture, stuff->picture, client, SecurityWriteAccess, + RenderErrBase + BadPicture); + len = client->req_len - (sizeof(xRenderChangePictureReq) >> 2); + if (Ones(stuff->mask) != len) + return BadLength; + + return ChangePicture (pPicture, stuff->mask, (XID *) (stuff + 1), + (DevUnion *) 0, client); +} + +static int +ProcRenderSetPictureClipRectangles (ClientPtr client) +{ + REQUEST(xRenderSetPictureClipRectanglesReq); + PicturePtr pPicture; + int nr; + int result; + + REQUEST_AT_LEAST_SIZE(xRenderSetPictureClipRectanglesReq); + VERIFY_PICTURE (pPicture, stuff->picture, client, SecurityWriteAccess, + RenderErrBase + BadPicture); + nr = (client->req_len << 2) - sizeof(xRenderChangePictureReq); + if (nr & 4) + return BadLength; + nr >>= 3; + result = SetPictureClipRects (pPicture, + stuff->xOrigin, stuff->yOrigin, + nr, (xRectangle *) &stuff[1]); + if (client->noClientException != Success) + return(client->noClientException); + else + return(result); +} + +static int +ProcRenderFreePicture (ClientPtr client) +{ + PicturePtr pPicture; + REQUEST(xRenderFreePictureReq); + + REQUEST_SIZE_MATCH(xRenderFreePictureReq); + + VERIFY_PICTURE (pPicture, stuff->picture, client, SecurityDestroyAccess, + RenderErrBase + BadPicture); + FreeResource (stuff->picture, RT_NONE); + return(client->noClientException); +} + +static Bool +PictOpValid (CARD8 op) +{ + if (/*PictOpMinimum <= op && */ op <= PictOpMaximum) + return TRUE; + if (PictOpDisjointMinimum <= op && op <= PictOpDisjointMaximum) + return TRUE; + if (PictOpConjointMinimum <= op && op <= PictOpConjointMaximum) + return TRUE; + return FALSE; +} + +static int +ProcRenderComposite (ClientPtr client) +{ + PicturePtr pSrc, pMask, pDst; + REQUEST(xRenderCompositeReq); + + REQUEST_SIZE_MATCH(xRenderCompositeReq); + if (!PictOpValid (stuff->op)) + { + client->errorValue = stuff->op; + return BadValue; + } + VERIFY_PICTURE (pSrc, stuff->src, client, SecurityReadAccess, + RenderErrBase + BadPicture); + VERIFY_ALPHA (pMask, stuff->mask, client, SecurityReadAccess, + RenderErrBase + BadPicture); + VERIFY_PICTURE (pDst, stuff->dst, client, SecurityWriteAccess, + RenderErrBase + BadPicture); + if (pSrc->pDrawable->pScreen != pDst->pDrawable->pScreen || + (pMask && pSrc->pDrawable->pScreen != pMask->pDrawable->pScreen)) + return BadMatch; + CompositePicture (stuff->op, + pSrc, + pMask, + pDst, + stuff->xSrc, + stuff->ySrc, + stuff->xMask, + stuff->yMask, + stuff->xDst, + stuff->yDst, + stuff->width, + stuff->height); + return Success; +} + +static int +ProcRenderScale (ClientPtr client) +{ + return BadImplementation; +} + +static int +ProcRenderTrapezoids (ClientPtr client) +{ + int ntraps; + PicturePtr pSrc, pDst; + PictFormatPtr pFormat; + REQUEST(xRenderTrapezoidsReq); + + REQUEST_AT_LEAST_SIZE(xRenderTrapezoidsReq); + if (!PictOpValid (stuff->op)) + { + client->errorValue = stuff->op; + return BadValue; + } + VERIFY_PICTURE (pSrc, stuff->src, client, SecurityReadAccess, + RenderErrBase + BadPicture); + VERIFY_PICTURE (pDst, stuff->dst, client, SecurityWriteAccess, + RenderErrBase + BadPicture); + if (pSrc->pDrawable->pScreen != pDst->pDrawable->pScreen) + return BadMatch; + if (stuff->maskFormat) + { + pFormat = (PictFormatPtr) SecurityLookupIDByType (client, + stuff->maskFormat, + PictFormatType, + SecurityReadAccess); + if (!pFormat) + { + client->errorValue = stuff->maskFormat; + return RenderErrBase + BadPictFormat; + } + } + else + pFormat = 0; + ntraps = (client->req_len << 2) - sizeof (xRenderTrapezoidsReq); + if (ntraps % sizeof (xTrapezoid)) + return BadLength; + ntraps /= sizeof (xTrapezoid); + if (ntraps) + CompositeTrapezoids (stuff->op, pSrc, pDst, pFormat, + stuff->xSrc, stuff->ySrc, + ntraps, (xTrapezoid *) &stuff[1]); + return client->noClientException; +} + +static int +ProcRenderTriangles (ClientPtr client) +{ + int ntris; + PicturePtr pSrc, pDst; + PictFormatPtr pFormat; + REQUEST(xRenderTrianglesReq); + + REQUEST_AT_LEAST_SIZE(xRenderTrianglesReq); + if (!PictOpValid (stuff->op)) + { + client->errorValue = stuff->op; + return BadValue; + } + VERIFY_PICTURE (pSrc, stuff->src, client, SecurityReadAccess, + RenderErrBase + BadPicture); + VERIFY_PICTURE (pDst, stuff->dst, client, SecurityWriteAccess, + RenderErrBase + BadPicture); + if (pSrc->pDrawable->pScreen != pDst->pDrawable->pScreen) + return BadMatch; + if (stuff->maskFormat) + { + pFormat = (PictFormatPtr) SecurityLookupIDByType (client, + stuff->maskFormat, + PictFormatType, + SecurityReadAccess); + if (!pFormat) + { + client->errorValue = stuff->maskFormat; + return RenderErrBase + BadPictFormat; + } + } + else + pFormat = 0; + ntris = (client->req_len << 2) - sizeof (xRenderTrianglesReq); + if (ntris % sizeof (xTriangle)) + return BadLength; + ntris /= sizeof (xTriangle); + if (ntris) + CompositeTriangles (stuff->op, pSrc, pDst, pFormat, + stuff->xSrc, stuff->ySrc, + ntris, (xTriangle *) &stuff[1]); + return client->noClientException; +} + +static int +ProcRenderTriStrip (ClientPtr client) +{ + int npoints; + PicturePtr pSrc, pDst; + PictFormatPtr pFormat; + REQUEST(xRenderTrianglesReq); + + REQUEST_AT_LEAST_SIZE(xRenderTrianglesReq); + if (!PictOpValid (stuff->op)) + { + client->errorValue = stuff->op; + return BadValue; + } + VERIFY_PICTURE (pSrc, stuff->src, client, SecurityReadAccess, + RenderErrBase + BadPicture); + VERIFY_PICTURE (pDst, stuff->dst, client, SecurityWriteAccess, + RenderErrBase + BadPicture); + if (pSrc->pDrawable->pScreen != pDst->pDrawable->pScreen) + return BadMatch; + if (stuff->maskFormat) + { + pFormat = (PictFormatPtr) SecurityLookupIDByType (client, + stuff->maskFormat, + PictFormatType, + SecurityReadAccess); + if (!pFormat) + { + client->errorValue = stuff->maskFormat; + return RenderErrBase + BadPictFormat; + } + } + else + pFormat = 0; + npoints = ((client->req_len << 2) - sizeof (xRenderTriStripReq)); + if (npoints & 4) + return(BadLength); + npoints >>= 3; + if (npoints >= 3) + CompositeTriStrip (stuff->op, pSrc, pDst, pFormat, + stuff->xSrc, stuff->ySrc, + npoints, (xPointFixed *) &stuff[1]); + return client->noClientException; +} + +static int +ProcRenderTriFan (ClientPtr client) +{ + int npoints; + PicturePtr pSrc, pDst; + PictFormatPtr pFormat; + REQUEST(xRenderTrianglesReq); + + REQUEST_AT_LEAST_SIZE(xRenderTrianglesReq); + if (!PictOpValid (stuff->op)) + { + client->errorValue = stuff->op; + return BadValue; + } + VERIFY_PICTURE (pSrc, stuff->src, client, SecurityReadAccess, + RenderErrBase + BadPicture); + VERIFY_PICTURE (pDst, stuff->dst, client, SecurityWriteAccess, + RenderErrBase + BadPicture); + if (pSrc->pDrawable->pScreen != pDst->pDrawable->pScreen) + return BadMatch; + if (stuff->maskFormat) + { + pFormat = (PictFormatPtr) SecurityLookupIDByType (client, + stuff->maskFormat, + PictFormatType, + SecurityReadAccess); + if (!pFormat) + { + client->errorValue = stuff->maskFormat; + return RenderErrBase + BadPictFormat; + } + } + else + pFormat = 0; + npoints = ((client->req_len << 2) - sizeof (xRenderTriStripReq)); + if (npoints & 4) + return(BadLength); + npoints >>= 3; + if (npoints >= 3) + CompositeTriFan (stuff->op, pSrc, pDst, pFormat, + stuff->xSrc, stuff->ySrc, + npoints, (xPointFixed *) &stuff[1]); + return client->noClientException; +} + +static int +ProcRenderColorTrapezoids (ClientPtr client) +{ + return BadImplementation; +} + +static int +ProcRenderColorTriangles (ClientPtr client) +{ + return BadImplementation; +} + +static int +ProcRenderTransform (ClientPtr client) +{ + return BadImplementation; +} + +static int +ProcRenderCreateGlyphSet (ClientPtr client) +{ + GlyphSetPtr glyphSet; + PictFormatPtr format; + int f; + REQUEST(xRenderCreateGlyphSetReq); + + REQUEST_SIZE_MATCH(xRenderCreateGlyphSetReq); + + LEGAL_NEW_RESOURCE(stuff->gsid, client); + format = (PictFormatPtr) SecurityLookupIDByType (client, + stuff->format, + PictFormatType, + SecurityReadAccess); + if (!format) + { + client->errorValue = stuff->format; + return RenderErrBase + BadPictFormat; + } + switch (format->depth) { + case 1: + f = GlyphFormat1; + break; + case 4: + f = GlyphFormat4; + break; + case 8: + f = GlyphFormat8; + break; + case 16: + f = GlyphFormat16; + break; + case 32: + f = GlyphFormat32; + break; + default: + return BadMatch; + } + if (format->type != PictTypeDirect) + return BadMatch; + glyphSet = AllocateGlyphSet (f, format); + if (!glyphSet) + return BadAlloc; + if (!AddResource (stuff->gsid, GlyphSetType, (pointer)glyphSet)) + return BadAlloc; + return Success; +} + +static int +ProcRenderReferenceGlyphSet (ClientPtr client) +{ + GlyphSetPtr glyphSet; + REQUEST(xRenderReferenceGlyphSetReq); + + REQUEST_SIZE_MATCH(xRenderReferenceGlyphSetReq); + + LEGAL_NEW_RESOURCE(stuff->gsid, client); + + glyphSet = (GlyphSetPtr) SecurityLookupIDByType (client, + stuff->existing, + GlyphSetType, + SecurityWriteAccess); + if (!glyphSet) + { + client->errorValue = stuff->existing; + return RenderErrBase + BadGlyphSet; + } + glyphSet->refcnt++; + if (!AddResource (stuff->gsid, GlyphSetType, (pointer)glyphSet)) + return BadAlloc; + return client->noClientException; +} + +#define NLOCALDELTA 64 +#define NLOCALGLYPH 256 + +static int +ProcRenderFreeGlyphSet (ClientPtr client) +{ + GlyphSetPtr glyphSet; + REQUEST(xRenderFreeGlyphSetReq); + + REQUEST_SIZE_MATCH(xRenderFreeGlyphSetReq); + glyphSet = (GlyphSetPtr) SecurityLookupIDByType (client, + stuff->glyphset, + GlyphSetType, + SecurityDestroyAccess); + if (!glyphSet) + { + client->errorValue = stuff->glyphset; + return RenderErrBase + BadGlyphSet; + } + FreeResource (stuff->glyphset, RT_NONE); + return client->noClientException; +} + +typedef struct _GlyphNew { + Glyph id; + GlyphPtr glyph; +} GlyphNewRec, *GlyphNewPtr; + +static int +ProcRenderAddGlyphs (ClientPtr client) +{ + GlyphSetPtr glyphSet; + REQUEST(xRenderAddGlyphsReq); + GlyphNewRec glyphsLocal[NLOCALGLYPH]; + GlyphNewPtr glyphsBase, glyphs; + GlyphPtr glyph; + int remain, nglyphs; + CARD32 *gids; + xGlyphInfo *gi; + CARD8 *bits; + int size; + int err = BadAlloc; + + REQUEST_AT_LEAST_SIZE(xRenderAddGlyphsReq); + glyphSet = (GlyphSetPtr) SecurityLookupIDByType (client, + stuff->glyphset, + GlyphSetType, + SecurityWriteAccess); + if (!glyphSet) + { + client->errorValue = stuff->glyphset; + return RenderErrBase + BadGlyphSet; + } + + nglyphs = stuff->nglyphs; + if (nglyphs <= NLOCALGLYPH) + glyphsBase = glyphsLocal; + else + { + glyphsBase = (GlyphNewPtr) ALLOCATE_LOCAL (nglyphs * sizeof (GlyphNewRec)); + if (!glyphsBase) + return BadAlloc; + } + + remain = (client->req_len << 2) - sizeof (xRenderAddGlyphsReq); + + glyphs = glyphsBase; + + gids = (CARD32 *) (stuff + 1); + gi = (xGlyphInfo *) (gids + nglyphs); + bits = (CARD8 *) (gi + nglyphs); + remain -= (sizeof (CARD32) + sizeof (xGlyphInfo)) * nglyphs; + while (remain >= 0 && nglyphs) + { + glyph = AllocateGlyph (gi, glyphSet->fdepth); + if (!glyph) + { + err = BadAlloc; + goto bail; + } + + glyphs->glyph = glyph; + glyphs->id = *gids; + + size = glyph->size - sizeof (xGlyphInfo); + if (remain < size) + break; + memcpy ((CARD8 *) (glyph + 1), bits, size); + + if (size & 3) + size += 4 - (size & 3); + bits += size; + remain -= size; + gi++; + gids++; + glyphs++; + nglyphs--; + } + if (nglyphs || remain) + { + err = BadLength; + goto bail; + } + nglyphs = stuff->nglyphs; + if (!ResizeGlyphSet (glyphSet, nglyphs)) + { + err = BadAlloc; + goto bail; + } + glyphs = glyphsBase; + while (nglyphs--) + AddGlyph (glyphSet, glyphs->glyph, glyphs->id); + + if (glyphsBase != glyphsLocal) + DEALLOCATE_LOCAL (glyphsBase); + return client->noClientException; +bail: + while (glyphs != glyphsBase) + { + --glyphs; + xfree (glyphs->glyph); + } + if (glyphsBase != glyphsLocal) + DEALLOCATE_LOCAL (glyphsBase); + return err; +} + +static int +ProcRenderAddGlyphsFromPicture (ClientPtr client) +{ + return BadImplementation; +} + +static int +ProcRenderFreeGlyphs (ClientPtr client) +{ + REQUEST(xRenderFreeGlyphsReq); + GlyphSetPtr glyphSet; + int nglyph; + CARD32 *gids; + CARD32 glyph; + + REQUEST_AT_LEAST_SIZE(xRenderFreeGlyphsReq); + glyphSet = (GlyphSetPtr) SecurityLookupIDByType (client, + stuff->glyphset, + GlyphSetType, + SecurityWriteAccess); + if (!glyphSet) + { + client->errorValue = stuff->glyphset; + return RenderErrBase + BadGlyphSet; + } + nglyph = ((client->req_len << 2) - sizeof (xRenderFreeGlyphsReq)) >> 2; + gids = (CARD32 *) (stuff + 1); + while (nglyph-- > 0) + { + glyph = *gids++; + if (!DeleteGlyph (glyphSet, glyph)) + { + client->errorValue = glyph; + return RenderErrBase + BadGlyph; + } + } + return client->noClientException; +} + +static int +ProcRenderCompositeGlyphs (ClientPtr client) +{ + GlyphSetPtr glyphSet; + GlyphSet gs; + PicturePtr pSrc, pDst; + PictFormatPtr pFormat; + GlyphListRec listsLocal[NLOCALDELTA]; + GlyphListPtr lists, listsBase; + GlyphPtr glyphsLocal[NLOCALGLYPH]; + Glyph glyph; + GlyphPtr *glyphs, *glyphsBase; + xGlyphElt *elt; + CARD8 *buffer, *end; + int nglyph; + int nlist; + int space; + int size; + int n; + + REQUEST(xRenderCompositeGlyphsReq); + + REQUEST_AT_LEAST_SIZE(xRenderCompositeGlyphsReq); + + switch (stuff->renderReqType) { + default: size = 1; break; + case X_RenderCompositeGlyphs16: size = 2; break; + case X_RenderCompositeGlyphs32: size = 4; break; + } + + if (!PictOpValid (stuff->op)) + { + client->errorValue = stuff->op; + return BadValue; + } + VERIFY_PICTURE (pSrc, stuff->src, client, SecurityReadAccess, + RenderErrBase + BadPicture); + VERIFY_PICTURE (pDst, stuff->dst, client, SecurityWriteAccess, + RenderErrBase + BadPicture); + if (pSrc->pDrawable->pScreen != pDst->pDrawable->pScreen) + return BadMatch; + if (stuff->maskFormat) + { + pFormat = (PictFormatPtr) SecurityLookupIDByType (client, + stuff->maskFormat, + PictFormatType, + SecurityReadAccess); + if (!pFormat) + { + client->errorValue = stuff->maskFormat; + return RenderErrBase + BadPictFormat; + } + } + else + pFormat = 0; + + glyphSet = (GlyphSetPtr) SecurityLookupIDByType (client, + stuff->glyphset, + GlyphSetType, + SecurityReadAccess); + if (!glyphSet) + { + client->errorValue = stuff->glyphset; + return RenderErrBase + BadGlyphSet; + } + + buffer = (CARD8 *) (stuff + 1); + end = (CARD8 *) stuff + (client->req_len << 2); + nglyph = 0; + nlist = 0; + while (buffer + sizeof (xGlyphElt) < end) + { + elt = (xGlyphElt *) buffer; + buffer += sizeof (xGlyphElt); + + if (elt->len == 0xff) + { + buffer += 4; + } + else + { + nlist++; + nglyph += elt->len; + space = size * elt->len; + if (space & 3) + space += 4 - (space & 3); + buffer += space; + } + } + if (nglyph <= NLOCALGLYPH) + glyphsBase = glyphsLocal; + else + { + glyphsBase = (GlyphPtr *) ALLOCATE_LOCAL (nglyph * sizeof (GlyphPtr)); + if (!glyphsBase) + return BadAlloc; + } + if (nlist <= NLOCALDELTA) + listsBase = listsLocal; + else + { + listsBase = (GlyphListPtr) ALLOCATE_LOCAL (nlist * sizeof (GlyphListRec)); + if (!listsBase) + return BadAlloc; + } + buffer = (CARD8 *) (stuff + 1); + glyphs = glyphsBase; + lists = listsBase; + while (buffer + sizeof (xGlyphElt) < end) + { + elt = (xGlyphElt *) buffer; + buffer += sizeof (xGlyphElt); + + if (elt->len == 0xff) + { + if (buffer + sizeof (GlyphSet) < end) + { + gs = *(GlyphSet *) buffer; + glyphSet = (GlyphSetPtr) SecurityLookupIDByType (client, + gs, + GlyphSetType, + SecurityReadAccess); + if (!glyphSet) + { + client->errorValue = gs; + if (glyphsBase != glyphsLocal) + DEALLOCATE_LOCAL (glyphsBase); + if (listsBase != listsLocal) + DEALLOCATE_LOCAL (listsBase); + return RenderErrBase + BadGlyphSet; + } + } + buffer += 4; + } + else + { + lists->xOff = elt->deltax; + lists->yOff = elt->deltay; + lists->format = glyphSet->format; + lists->len = 0; + n = elt->len; + while (n--) + { + if (buffer + size <= end) + { + switch (size) { + case 1: + glyph = *((CARD8 *)buffer); break; + case 2: + glyph = *((CARD16 *)buffer); break; + case 4: + default: + glyph = *((CARD32 *)buffer); break; + } + if ((*glyphs = FindGlyph (glyphSet, glyph))) + { + lists->len++; + glyphs++; + } + } + buffer += size; + } + space = size * elt->len; + if (space & 3) + buffer += 4 - (space & 3); + lists++; + } + } + if (buffer > end) + return BadLength; + + CompositeGlyphs (stuff->op, + pSrc, + pDst, + pFormat, + stuff->xSrc, + stuff->ySrc, + nlist, + listsBase, + glyphsBase); + + if (glyphsBase != glyphsLocal) + DEALLOCATE_LOCAL (glyphsBase); + if (listsBase != listsLocal) + DEALLOCATE_LOCAL (listsBase); + + return client->noClientException; +} + +static int +ProcRenderFillRectangles (ClientPtr client) +{ + PicturePtr pDst; + int things; + REQUEST(xRenderFillRectanglesReq); + + REQUEST_AT_LEAST_SIZE (xRenderFillRectanglesReq); + if (!PictOpValid (stuff->op)) + { + client->errorValue = stuff->op; + return BadValue; + } + VERIFY_PICTURE (pDst, stuff->dst, client, SecurityWriteAccess, + RenderErrBase + BadPicture); + + things = (client->req_len << 2) - sizeof(xRenderFillRectanglesReq); + if (things & 4) + return(BadLength); + things >>= 3; + + CompositeRects (stuff->op, + pDst, + &stuff->color, + things, + (xRectangle *) &stuff[1]); + + return client->noClientException; +} + +static void +SetBit (unsigned char *line, int x, int bit) +{ + unsigned char mask; + + if (screenInfo.bitmapBitOrder == LSBFirst) + mask = (1 << (x & 7)); + else + mask = (0x80 >> (x & 7)); + /* XXX assumes byte order is host byte order */ + line += (x >> 3); + if (bit) + *line |= mask; + else + *line &= ~mask; +} + +#define DITHER_DIM 2 + +static CARD32 orderedDither[DITHER_DIM][DITHER_DIM] = { + { 1, 3, }, + { 4, 2, }, +}; + +#define DITHER_SIZE ((sizeof orderedDither / sizeof orderedDither[0][0]) + 1) + +static int +ProcRenderCreateCursor (ClientPtr client) +{ + REQUEST(xRenderCreateCursorReq); + PicturePtr pSrc; + ScreenPtr pScreen; + unsigned short width, height; + CARD32 *argbbits, *argb; + unsigned char *srcbits, *srcline; + unsigned char *mskbits, *mskline; + int stride; + int x, y; + int nbytes_mono; + CursorMetricRec cm; + CursorPtr pCursor; + CARD32 twocolor[3]; + int ncolor; + + REQUEST_SIZE_MATCH (xRenderCreateCursorReq); + LEGAL_NEW_RESOURCE(stuff->cid, client); + + VERIFY_PICTURE (pSrc, stuff->src, client, SecurityReadAccess, + RenderErrBase + BadPicture); + pScreen = pSrc->pDrawable->pScreen; + width = pSrc->pDrawable->width; + height = pSrc->pDrawable->height; + if ( stuff->x > width + || stuff->y > height ) + return (BadMatch); + argbbits = xalloc (width * height * sizeof (CARD32)); + if (!argbbits) + return (BadAlloc); + + stride = BitmapBytePad(width); + nbytes_mono = stride*height; + srcbits = (unsigned char *)xalloc(nbytes_mono); + if (!srcbits) + { + xfree (argbbits); + return (BadAlloc); + } + mskbits = (unsigned char *)xalloc(nbytes_mono); + if (!mskbits) + { + xfree(argbbits); + xfree(srcbits); + return (BadAlloc); + } + bzero ((char *) mskbits, nbytes_mono); + bzero ((char *) srcbits, nbytes_mono); + + if (pSrc->format == PICT_a8r8g8b8) + { + (*pScreen->GetImage) (pSrc->pDrawable, + 0, 0, width, height, ZPixmap, + 0xffffffff, (pointer) argbbits); + } + else + { + PixmapPtr pPixmap; + PicturePtr pPicture; + PictFormatPtr pFormat; + int error; + + pFormat = PictureMatchFormat (pScreen, 32, PICT_a8r8g8b8); + if (!pFormat) + { + xfree (argbbits); + xfree (srcbits); + xfree (mskbits); + return (BadImplementation); + } + pPixmap = (*pScreen->CreatePixmap) (pScreen, width, height, 32); + if (!pPixmap) + { + xfree (argbbits); + xfree (srcbits); + xfree (mskbits); + return (BadAlloc); + } + pPicture = CreatePicture (0, &pPixmap->drawable, pFormat, 0, 0, + client, &error); + if (!pPicture); + { + xfree (argbbits); + xfree (srcbits); + xfree (mskbits); + return error; + } + (*pScreen->DestroyPixmap) (pPixmap); + CompositePicture (PictOpSrc, + pSrc, 0, pPicture, + 0, 0, 0, 0, 0, 0, width, height); + (*pScreen->GetImage) (pPicture->pDrawable, + 0, 0, width, height, ZPixmap, + 0xffffffff, (pointer) argbbits); + FreePicture (pPicture, 0); + } + /* + * Check whether the cursor can be directly supported by + * the core cursor code + */ + ncolor = 0; + argb = argbbits; + for (y = 0; ncolor <= 2 && y < height; y++) + { + for (x = 0; ncolor <= 2 && x < width; x++) + { + CARD32 p = *argb++; + CARD32 a = (p >> 24); + + if (a == 0) /* transparent */ + continue; + if (a == 0xff) /* opaque */ + { + int n; + for (n = 0; n < ncolor; n++) + if (p == twocolor[n]) + break; + if (n == ncolor) + twocolor[ncolor++] = p; + } + else + ncolor = 3; + } + } + + /* + * Convert argb image to two plane cursor + */ + srcline = srcbits; + mskline = mskbits; + argb = argbbits; + for (y = 0; y < height; y++) + { + for (x = 0; x < width; x++) + { + CARD32 p = *argb++; + + if (ncolor <= 2) + { + CARD32 a = ((p >> 24)); + + SetBit (mskline, x, a != 0); + SetBit (srcline, x, a != 0 && p == twocolor[0]); + } + else + { + CARD32 a = ((p >> 24) * DITHER_SIZE + 127) / 255; + CARD32 i = ((CvtR8G8B8toY15(p) >> 7) * DITHER_SIZE + 127) / 255; + CARD32 d = orderedDither[y&(DITHER_DIM-1)][x&(DITHER_DIM-1)]; + /* Set mask from dithered alpha value */ + SetBit(mskline, x, a > d); + /* Set src from dithered intensity value */ + SetBit(srcline, x, a > d && i <= d); + } + } + srcline += stride; + mskline += stride; + } + /* + * Dither to white and black if the cursor has more than two colors + */ + if (ncolor > 2) + { + twocolor[0] = 0xff000000; + twocolor[1] = 0xffffffff; + } + else + { + xfree (argbbits); + argbbits = 0; + } + +#define GetByte(p,s) (((p) >> (s)) & 0xff) +#define GetColor(p,s) (GetByte(p,s) | (GetByte(p,s) << 8)) + + cm.width = width; + cm.height = height; + cm.xhot = stuff->x; + cm.yhot = stuff->y; + pCursor = AllocCursorARGB (srcbits, mskbits, argbbits, &cm, + GetColor(twocolor[0], 16), + GetColor(twocolor[0], 8), + GetColor(twocolor[0], 0), + GetColor(twocolor[1], 16), + GetColor(twocolor[1], 8), + GetColor(twocolor[1], 0)); + if (pCursor && AddResource(stuff->cid, RT_CURSOR, (pointer)pCursor)) + return (client->noClientException); + return BadAlloc; +} + +static int +ProcRenderSetPictureTransform (ClientPtr client) +{ + REQUEST(xRenderSetPictureTransformReq); + PicturePtr pPicture; + int result; + + REQUEST_SIZE_MATCH(xRenderSetPictureTransformReq); + VERIFY_PICTURE (pPicture, stuff->picture, client, SecurityWriteAccess, + RenderErrBase + BadPicture); + result = SetPictureTransform (pPicture, (PictTransform *) &stuff->transform); + if (client->noClientException != Success) + return(client->noClientException); + else + return(result); +} + +static int +ProcRenderQueryFilters (ClientPtr client) +{ + REQUEST (xRenderQueryFiltersReq); + DrawablePtr pDrawable; + xRenderQueryFiltersReply *reply; + int nbytesName; + int nnames; + ScreenPtr pScreen; + PictureScreenPtr ps; + int i, j; + int len; + int total_bytes; + INT16 *aliases; + char *names; + + REQUEST_SIZE_MATCH(xRenderQueryFiltersReq); + SECURITY_VERIFY_DRAWABLE(pDrawable, stuff->drawable, client, SecurityReadAccess); + + pScreen = pDrawable->pScreen; + nbytesName = 0; + nnames = 0; + ps = GetPictureScreenIfSet(pScreen); + if (ps) + { + for (i = 0; i < ps->nfilters; i++) + nbytesName += 1 + strlen (ps->filters[i].name); + for (i = 0; i < ps->nfilterAliases; i++) + nbytesName += 1 + strlen (ps->filterAliases[i].alias); + nnames = ps->nfilters + ps->nfilterAliases; + } + len = ((nnames + 1) >> 1) + ((nbytesName + 3) >> 2); + total_bytes = sizeof (xRenderQueryFiltersReply) + (len << 2); + reply = (xRenderQueryFiltersReply *) xalloc (total_bytes); + if (!reply) + return BadAlloc; + aliases = (INT16 *) (reply + 1); + names = (char *) (aliases + ((nnames + 1) & ~1)); + + reply->type = X_Reply; + reply->sequenceNumber = client->sequence; + reply->length = len; + reply->numAliases = nnames; + reply->numFilters = nnames; + if (ps) + { + + /* fill in alias values */ + for (i = 0; i < ps->nfilters; i++) + aliases[i] = FilterAliasNone; + for (i = 0; i < ps->nfilterAliases; i++) + { + for (j = 0; j < ps->nfilters; j++) + if (ps->filterAliases[i].filter_id == ps->filters[j].id) + break; + if (j == ps->nfilters) + { + for (j = 0; j < ps->nfilterAliases; j++) + if (ps->filterAliases[i].filter_id == + ps->filterAliases[j].alias_id) + { + break; + } + if (j == ps->nfilterAliases) + j = FilterAliasNone; + else + j = j + ps->nfilters; + } + aliases[i + ps->nfilters] = j; + } + + /* fill in filter names */ + for (i = 0; i < ps->nfilters; i++) + { + j = strlen (ps->filters[i].name); + *names++ = j; + strncpy (names, ps->filters[i].name, j); + names += j; + } + + /* fill in filter alias names */ + for (i = 0; i < ps->nfilterAliases; i++) + { + j = strlen (ps->filterAliases[i].alias); + *names++ = j; + strncpy (names, ps->filterAliases[i].alias, j); + names += j; + } + } + + if (client->swapped) + { + register int n; + + for (i = 0; i < reply->numAliases; i++) + { + swaps (&aliases[i], n); + } + swaps(&reply->sequenceNumber, n); + swapl(&reply->length, n); + swapl(&reply->numAliases, n); + swapl(&reply->numFilters, n); + } + WriteToClient(client, total_bytes, (char *) reply); + xfree (reply); + + return(client->noClientException); +} + +static int +ProcRenderSetPictureFilter (ClientPtr client) +{ + REQUEST (xRenderSetPictureFilterReq); + PicturePtr pPicture; + int result; + xFixed *params; + int nparams; + char *name; + + REQUEST_AT_LEAST_SIZE (xRenderSetPictureFilterReq); + VERIFY_PICTURE (pPicture, stuff->picture, client, SecurityWriteAccess, + RenderErrBase + BadPicture); + name = (char *) (stuff + 1); + params = (xFixed *) (name + ((stuff->nbytes + 3) & ~3)); + nparams = ((xFixed *) stuff + client->req_len) - params; + result = SetPictureFilter (pPicture, name, stuff->nbytes, params, nparams); + return result; +} + +static int +ProcRenderCreateAnimCursor (ClientPtr client) +{ + REQUEST(xRenderCreateAnimCursorReq); + CursorPtr *cursors; + CARD32 *deltas; + CursorPtr pCursor; + int ncursor; + xAnimCursorElt *elt; + int i; + int ret; + + REQUEST_AT_LEAST_SIZE(xRenderCreateAnimCursorReq); + LEGAL_NEW_RESOURCE(stuff->cid, client); + if (client->req_len & 1) + return BadLength; + ncursor = (client->req_len - (SIZEOF(xRenderCreateAnimCursorReq) >> 2)) >> 1; + cursors = xalloc (ncursor * (sizeof (CursorPtr) + sizeof (CARD32))); + if (!cursors) + return BadAlloc; + deltas = (CARD32 *) (cursors + ncursor); + elt = (xAnimCursorElt *) (stuff + 1); + for (i = 0; i < ncursor; i++) + { + cursors[i] = (CursorPtr)SecurityLookupIDByType(client, elt->cursor, + RT_CURSOR, SecurityReadAccess); + if (!cursors[i]) + { + xfree (cursors); + client->errorValue = elt->cursor; + return BadCursor; + } + deltas[i] = elt->delay; + elt++; + } + ret = AnimCursorCreate (cursors, deltas, ncursor, &pCursor); + xfree (cursors); + if (ret != Success) + return ret; + + if (AddResource (stuff->cid, RT_CURSOR, (pointer)pCursor)) + return client->noClientException; + return BadAlloc; +} + +static int +ProcRenderDispatch (ClientPtr client) +{ + REQUEST(xReq); + + if (stuff->data < RenderNumberRequests) + return (*ProcRenderVector[stuff->data]) (client); + else + return BadRequest; +} + +static int +SProcRenderQueryVersion (ClientPtr client) +{ + register int n; + REQUEST(xRenderQueryVersionReq); + + swaps(&stuff->length, n); + swapl(&stuff->majorVersion, n); + swapl(&stuff->minorVersion, n); + return (*ProcRenderVector[stuff->renderReqType])(client); +} + +static int +SProcRenderQueryPictFormats (ClientPtr client) +{ + register int n; + REQUEST(xRenderQueryPictFormatsReq); + swaps(&stuff->length, n); + return (*ProcRenderVector[stuff->renderReqType]) (client); +} + +static int +SProcRenderQueryPictIndexValues (ClientPtr client) +{ + register int n; + REQUEST(xRenderQueryPictIndexValuesReq); + swaps(&stuff->length, n); + swapl(&stuff->format, n); + return (*ProcRenderVector[stuff->renderReqType]) (client); +} + +static int +SProcRenderQueryDithers (ClientPtr client) +{ + return BadImplementation; +} + +static int +SProcRenderCreatePicture (ClientPtr client) +{ + register int n; + REQUEST(xRenderCreatePictureReq); + swaps(&stuff->length, n); + swapl(&stuff->pid, n); + swapl(&stuff->drawable, n); + swapl(&stuff->format, n); + swapl(&stuff->mask, n); + SwapRestL(stuff); + return (*ProcRenderVector[stuff->renderReqType]) (client); +} + +static int +SProcRenderChangePicture (ClientPtr client) +{ + register int n; + REQUEST(xRenderChangePictureReq); + swaps(&stuff->length, n); + swapl(&stuff->picture, n); + swapl(&stuff->mask, n); + SwapRestL(stuff); + return (*ProcRenderVector[stuff->renderReqType]) (client); +} + +static int +SProcRenderSetPictureClipRectangles (ClientPtr client) +{ + register int n; + REQUEST(xRenderSetPictureClipRectanglesReq); + swaps(&stuff->length, n); + swapl(&stuff->picture, n); + SwapRestS(stuff); + return (*ProcRenderVector[stuff->renderReqType]) (client); +} + +static int +SProcRenderFreePicture (ClientPtr client) +{ + register int n; + REQUEST(xRenderFreePictureReq); + swaps(&stuff->length, n); + swapl(&stuff->picture, n); + return (*ProcRenderVector[stuff->renderReqType]) (client); +} + +static int +SProcRenderComposite (ClientPtr client) +{ + register int n; + REQUEST(xRenderCompositeReq); + swaps(&stuff->length, n); + swapl(&stuff->src, n); + swapl(&stuff->mask, n); + swapl(&stuff->dst, n); + swaps(&stuff->xSrc, n); + swaps(&stuff->ySrc, n); + swaps(&stuff->xMask, n); + swaps(&stuff->yMask, n); + swaps(&stuff->xDst, n); + swaps(&stuff->yDst, n); + swaps(&stuff->width, n); + swaps(&stuff->height, n); + return (*ProcRenderVector[stuff->renderReqType]) (client); +} + +static int +SProcRenderScale (ClientPtr client) +{ + register int n; + REQUEST(xRenderScaleReq); + swaps(&stuff->length, n); + swapl(&stuff->src, n); + swapl(&stuff->dst, n); + swapl(&stuff->colorScale, n); + swapl(&stuff->alphaScale, n); + swaps(&stuff->xSrc, n); + swaps(&stuff->ySrc, n); + swaps(&stuff->xDst, n); + swaps(&stuff->yDst, n); + swaps(&stuff->width, n); + swaps(&stuff->height, n); + return (*ProcRenderVector[stuff->renderReqType]) (client); +} + +static int +SProcRenderTrapezoids (ClientPtr client) +{ + register int n; + REQUEST(xRenderTrapezoidsReq); + + REQUEST_AT_LEAST_SIZE(xRenderTrapezoidsReq); + swaps (&stuff->length, n); + swapl (&stuff->src, n); + swapl (&stuff->dst, n); + swapl (&stuff->maskFormat, n); + swaps (&stuff->xSrc, n); + swaps (&stuff->ySrc, n); + SwapRestL(stuff); + return (*ProcRenderVector[stuff->renderReqType]) (client); +} + +static int +SProcRenderTriangles (ClientPtr client) +{ + register int n; + REQUEST(xRenderTrianglesReq); + + REQUEST_AT_LEAST_SIZE(xRenderTrianglesReq); + swaps (&stuff->length, n); + swapl (&stuff->src, n); + swapl (&stuff->dst, n); + swapl (&stuff->maskFormat, n); + swaps (&stuff->xSrc, n); + swaps (&stuff->ySrc, n); + SwapRestL(stuff); + return (*ProcRenderVector[stuff->renderReqType]) (client); +} + +static int +SProcRenderTriStrip (ClientPtr client) +{ + register int n; + REQUEST(xRenderTriStripReq); + + REQUEST_AT_LEAST_SIZE(xRenderTriStripReq); + swaps (&stuff->length, n); + swapl (&stuff->src, n); + swapl (&stuff->dst, n); + swapl (&stuff->maskFormat, n); + swaps (&stuff->xSrc, n); + swaps (&stuff->ySrc, n); + SwapRestL(stuff); + return (*ProcRenderVector[stuff->renderReqType]) (client); +} + +static int +SProcRenderTriFan (ClientPtr client) +{ + register int n; + REQUEST(xRenderTriFanReq); + + REQUEST_AT_LEAST_SIZE(xRenderTriFanReq); + swaps (&stuff->length, n); + swapl (&stuff->src, n); + swapl (&stuff->dst, n); + swapl (&stuff->maskFormat, n); + swaps (&stuff->xSrc, n); + swaps (&stuff->ySrc, n); + SwapRestL(stuff); + return (*ProcRenderVector[stuff->renderReqType]) (client); +} + +static int +SProcRenderColorTrapezoids (ClientPtr client) +{ + return BadImplementation; +} + +static int +SProcRenderColorTriangles (ClientPtr client) +{ + return BadImplementation; +} + +static int +SProcRenderTransform (ClientPtr client) +{ + return BadImplementation; +} + +static int +SProcRenderCreateGlyphSet (ClientPtr client) +{ + register int n; + REQUEST(xRenderCreateGlyphSetReq); + swaps(&stuff->length, n); + swapl(&stuff->gsid, n); + swapl(&stuff->format, n); + return (*ProcRenderVector[stuff->renderReqType]) (client); +} + +static int +SProcRenderReferenceGlyphSet (ClientPtr client) +{ + register int n; + REQUEST(xRenderReferenceGlyphSetReq); + swaps(&stuff->length, n); + swapl(&stuff->gsid, n); + swapl(&stuff->existing, n); + return (*ProcRenderVector[stuff->renderReqType]) (client); +} + +static int +SProcRenderFreeGlyphSet (ClientPtr client) +{ + register int n; + REQUEST(xRenderFreeGlyphSetReq); + swaps(&stuff->length, n); + swapl(&stuff->glyphset, n); + return (*ProcRenderVector[stuff->renderReqType]) (client); +} + +static int +SProcRenderAddGlyphs (ClientPtr client) +{ + register int n; + register int i; + CARD32 *gids; + void *end; + xGlyphInfo *gi; + REQUEST(xRenderAddGlyphsReq); + swaps(&stuff->length, n); + swapl(&stuff->glyphset, n); + swapl(&stuff->nglyphs, n); + if (stuff->nglyphs & 0xe0000000) + return BadLength; + end = (CARD8 *) stuff + (client->req_len << 2); + gids = (CARD32 *) (stuff + 1); + gi = (xGlyphInfo *) (gids + stuff->nglyphs); + if ((char *) end - (char *) (gids + stuff->nglyphs) < 0) + return BadLength; + if ((char *) end - (char *) (gi + stuff->nglyphs) < 0) + return BadLength; + for (i = 0; i < stuff->nglyphs; i++) + { + swapl (&gids[i], n); + swaps (&gi[i].width, n); + swaps (&gi[i].height, n); + swaps (&gi[i].x, n); + swaps (&gi[i].y, n); + swaps (&gi[i].xOff, n); + swaps (&gi[i].yOff, n); + } + return (*ProcRenderVector[stuff->renderReqType]) (client); +} + +static int +SProcRenderAddGlyphsFromPicture (ClientPtr client) +{ + return BadImplementation; +} + +static int +SProcRenderFreeGlyphs (ClientPtr client) +{ + register int n; + REQUEST(xRenderFreeGlyphsReq); + swaps(&stuff->length, n); + swapl(&stuff->glyphset, n); + SwapRestL(stuff); + return (*ProcRenderVector[stuff->renderReqType]) (client); +} + +static int +SProcRenderCompositeGlyphs (ClientPtr client) +{ + register int n; + xGlyphElt *elt; + CARD8 *buffer; + CARD8 *end; + int space; + int i; + int size; + + REQUEST(xRenderCompositeGlyphsReq); + + switch (stuff->renderReqType) { + default: size = 1; break; + case X_RenderCompositeGlyphs16: size = 2; break; + case X_RenderCompositeGlyphs32: size = 4; break; + } + + swaps(&stuff->length, n); + swapl(&stuff->src, n); + swapl(&stuff->dst, n); + swapl(&stuff->maskFormat, n); + swapl(&stuff->glyphset, n); + swaps(&stuff->xSrc, n); + swaps(&stuff->ySrc, n); + buffer = (CARD8 *) (stuff + 1); + end = (CARD8 *) stuff + (client->req_len << 2); + while (buffer + sizeof (xGlyphElt) < end) + { + elt = (xGlyphElt *) buffer; + buffer += sizeof (xGlyphElt); + + swaps (&elt->deltax, n); + swaps (&elt->deltay, n); + + i = elt->len; + if (i == 0xff) + { + swapl (buffer, n); + buffer += 4; + } + else + { + space = size * i; + switch (size) { + case 1: + buffer += i; + break; + case 2: + while (i--) + { + swaps (buffer, n); + buffer += 2; + } + break; + case 4: + while (i--) + { + swapl (buffer, n); + buffer += 4; + } + break; + } + if (space & 3) + buffer += 4 - (space & 3); + } + } + return (*ProcRenderVector[stuff->renderReqType]) (client); +} + +static int +SProcRenderFillRectangles (ClientPtr client) +{ + register int n; + REQUEST(xRenderFillRectanglesReq); + + REQUEST_AT_LEAST_SIZE (xRenderFillRectanglesReq); + swaps(&stuff->length, n); + swapl(&stuff->dst, n); + swaps(&stuff->color.red, n); + swaps(&stuff->color.green, n); + swaps(&stuff->color.blue, n); + swaps(&stuff->color.alpha, n); + SwapRestS(stuff); + return (*ProcRenderVector[stuff->renderReqType]) (client); +} + +static int +SProcRenderCreateCursor (ClientPtr client) +{ + register int n; + REQUEST(xRenderCreateCursorReq); + REQUEST_SIZE_MATCH (xRenderCreateCursorReq); + + swaps(&stuff->length, n); + swapl(&stuff->cid, n); + swapl(&stuff->src, n); + swaps(&stuff->x, n); + swaps(&stuff->y, n); + return (*ProcRenderVector[stuff->renderReqType]) (client); +} + +static int +SProcRenderSetPictureTransform (ClientPtr client) +{ + register int n; + REQUEST(xRenderSetPictureTransformReq); + REQUEST_SIZE_MATCH(xRenderSetPictureTransformReq); + + swaps(&stuff->length, n); + swapl(&stuff->picture, n); + swapl(&stuff->transform.matrix11, n); + swapl(&stuff->transform.matrix12, n); + swapl(&stuff->transform.matrix13, n); + swapl(&stuff->transform.matrix21, n); + swapl(&stuff->transform.matrix22, n); + swapl(&stuff->transform.matrix23, n); + swapl(&stuff->transform.matrix31, n); + swapl(&stuff->transform.matrix32, n); + swapl(&stuff->transform.matrix33, n); + return (*ProcRenderVector[stuff->renderReqType]) (client); +} + +static int +SProcRenderQueryFilters (ClientPtr client) +{ + register int n; + REQUEST (xRenderQueryFiltersReq); + REQUEST_SIZE_MATCH (xRenderQueryFiltersReq); + + swaps(&stuff->length, n); + swapl(&stuff->drawable, n); + return (*ProcRenderVector[stuff->renderReqType]) (client); +} + +static int +SProcRenderSetPictureFilter (ClientPtr client) +{ + register int n; + REQUEST (xRenderSetPictureFilterReq); + REQUEST_AT_LEAST_SIZE (xRenderSetPictureFilterReq); + + swaps(&stuff->length, n); + swapl(&stuff->picture, n); + swaps(&stuff->nbytes, n); + return (*ProcRenderVector[stuff->renderReqType]) (client); +} + +static int +SProcRenderCreateAnimCursor (ClientPtr client) +{ + register int n; + REQUEST (xRenderCreateAnimCursorReq); + REQUEST_AT_LEAST_SIZE (xRenderCreateAnimCursorReq); + + swaps(&stuff->length, n); + swapl(&stuff->cid, n); + SwapRestL(stuff); + return (*ProcRenderVector[stuff->renderReqType]) (client); +} + +static int +SProcRenderDispatch (ClientPtr client) +{ + REQUEST(xReq); + + if (stuff->data < RenderNumberRequests) + return (*SProcRenderVector[stuff->data]) (client); + else + return BadRequest; +} + +#ifdef PANORAMIX +#include "panoramiX.h" +#include "panoramiXsrv.h" + +#define VERIFY_XIN_PICTURE(pPicture, pid, client, mode, err) {\ + pPicture = SecurityLookupIDByType(client, pid, XRT_PICTURE, mode);\ + if (!pPicture) { \ + client->errorValue = pid; \ + return err; \ + } \ +} + +#define VERIFY_XIN_ALPHA(pPicture, pid, client, mode, err) {\ + if (pid == None) \ + pPicture = 0; \ + else { \ + VERIFY_XIN_PICTURE(pPicture, pid, client, mode, err); \ + } \ +} \ + +int (*PanoramiXSaveRenderVector[RenderNumberRequests])(ClientPtr); + +unsigned long XRT_PICTURE; + +static int +PanoramiXRenderCreatePicture (ClientPtr client) +{ + REQUEST(xRenderCreatePictureReq); + PanoramiXRes *refDraw, *newPict; + int result = Success, j; + + REQUEST_AT_LEAST_SIZE(xRenderCreatePictureReq); + if(!(refDraw = (PanoramiXRes *)SecurityLookupIDByClass( + client, stuff->drawable, XRC_DRAWABLE, SecurityWriteAccess))) + return BadDrawable; + if(!(newPict = (PanoramiXRes *) xalloc(sizeof(PanoramiXRes)))) + return BadAlloc; + newPict->type = XRT_PICTURE; + newPict->info[0].id = stuff->pid; + + if (refDraw->type == XRT_WINDOW && + stuff->drawable == WindowTable[0]->drawable.id) + { + newPict->u.pict.root = TRUE; + } + else + newPict->u.pict.root = FALSE; + + for(j = 1; j < PanoramiXNumScreens; j++) + newPict->info[j].id = FakeClientID(client->index); + + FOR_NSCREENS_BACKWARD(j) { + stuff->pid = newPict->info[j].id; + stuff->drawable = refDraw->info[j].id; + result = (*PanoramiXSaveRenderVector[X_RenderCreatePicture]) (client); + if(result != Success) break; + } + + if (result == Success) + AddResource(newPict->info[0].id, XRT_PICTURE, newPict); + else + xfree(newPict); + + return (result); +} + +static int +PanoramiXRenderChangePicture (ClientPtr client) +{ + PanoramiXRes *pict; + int result = Success, j; + REQUEST(xRenderChangePictureReq); + + REQUEST_AT_LEAST_SIZE(xChangeWindowAttributesReq); + + VERIFY_XIN_PICTURE(pict, stuff->picture, client, SecurityWriteAccess, + RenderErrBase + BadPicture); + + FOR_NSCREENS_BACKWARD(j) { + stuff->picture = pict->info[j].id; + result = (*PanoramiXSaveRenderVector[X_RenderChangePicture]) (client); + if(result != Success) break; + } + + return (result); +} + +static int +PanoramiXRenderSetPictureClipRectangles (ClientPtr client) +{ + REQUEST(xRenderSetPictureClipRectanglesReq); + int result = Success, j; + PanoramiXRes *pict; + + REQUEST_AT_LEAST_SIZE(xRenderSetPictureClipRectanglesReq); + + VERIFY_XIN_PICTURE(pict, stuff->picture, client, SecurityWriteAccess, + RenderErrBase + BadPicture); + + FOR_NSCREENS_BACKWARD(j) { + stuff->picture = pict->info[j].id; + result = (*PanoramiXSaveRenderVector[X_RenderSetPictureClipRectangles]) (client); + if(result != Success) break; + } + + return (result); +} + +static int +PanoramiXRenderFreePicture (ClientPtr client) +{ + PanoramiXRes *pict; + int result = Success, j; + REQUEST(xRenderFreePictureReq); + + REQUEST_SIZE_MATCH(xRenderFreePictureReq); + + client->errorValue = stuff->picture; + + VERIFY_XIN_PICTURE(pict, stuff->picture, client, SecurityDestroyAccess, + RenderErrBase + BadPicture); + + + FOR_NSCREENS_BACKWARD(j) { + stuff->picture = pict->info[j].id; + result = (*PanoramiXSaveRenderVector[X_RenderFreePicture]) (client); + if(result != Success) break; + } + + /* Since ProcRenderFreePicture is using FreeResource, it will free + our resource for us on the last pass through the loop above */ + + return (result); +} + +static int +PanoramiXRenderComposite (ClientPtr client) +{ + PanoramiXRes *src, *msk, *dst; + int result = Success, j; + xRenderCompositeReq orig; + REQUEST(xRenderCompositeReq); + + REQUEST_SIZE_MATCH(xRenderCompositeReq); + + VERIFY_XIN_PICTURE (src, stuff->src, client, SecurityReadAccess, + RenderErrBase + BadPicture); + VERIFY_XIN_ALPHA (msk, stuff->mask, client, SecurityReadAccess, + RenderErrBase + BadPicture); + VERIFY_XIN_PICTURE (dst, stuff->dst, client, SecurityWriteAccess, + RenderErrBase + BadPicture); + + orig = *stuff; + + FOR_NSCREENS_FORWARD(j) { + stuff->src = src->info[j].id; + if (src->u.pict.root) + { + stuff->xSrc = orig.xSrc - panoramiXdataPtr[j].x; + stuff->ySrc = orig.ySrc - panoramiXdataPtr[j].y; + } + stuff->dst = dst->info[j].id; + if (dst->u.pict.root) + { + stuff->xDst = orig.xDst - panoramiXdataPtr[j].x; + stuff->yDst = orig.yDst - panoramiXdataPtr[j].y; + } + if (msk) + { + stuff->mask = msk->info[j].id; + if (msk->u.pict.root) + { + stuff->xMask = orig.xMask - panoramiXdataPtr[j].x; + stuff->yMask = orig.yMask - panoramiXdataPtr[j].y; + } + } + result = (*PanoramiXSaveRenderVector[X_RenderComposite]) (client); + if(result != Success) break; + } + + return result; +} + +static int +PanoramiXRenderCompositeGlyphs (ClientPtr client) +{ + PanoramiXRes *src, *dst; + int result = Success, j; + REQUEST(xRenderCompositeGlyphsReq); + xGlyphElt origElt, *elt; + INT16 xSrc, ySrc; + + REQUEST_AT_LEAST_SIZE(xRenderCompositeGlyphsReq); + VERIFY_XIN_PICTURE (src, stuff->src, client, SecurityReadAccess, + RenderErrBase + BadPicture); + VERIFY_XIN_PICTURE (dst, stuff->dst, client, SecurityWriteAccess, + RenderErrBase + BadPicture); + + if (client->req_len << 2 >= (sizeof (xRenderCompositeGlyphsReq) + + sizeof (xGlyphElt))) + { + elt = (xGlyphElt *) (stuff + 1); + origElt = *elt; + xSrc = stuff->xSrc; + ySrc = stuff->ySrc; + FOR_NSCREENS_FORWARD(j) { + stuff->src = src->info[j].id; + if (src->u.pict.root) + { + stuff->xSrc = xSrc - panoramiXdataPtr[j].x; + stuff->ySrc = ySrc - panoramiXdataPtr[j].y; + } + stuff->dst = dst->info[j].id; + if (dst->u.pict.root) + { + elt->deltax = origElt.deltax - panoramiXdataPtr[j].x; + elt->deltay = origElt.deltay - panoramiXdataPtr[j].y; + } + result = (*PanoramiXSaveRenderVector[stuff->renderReqType]) (client); + if(result != Success) break; + } + } + + return result; +} + +static int +PanoramiXRenderFillRectangles (ClientPtr client) +{ + PanoramiXRes *dst; + int result = Success, j; + REQUEST(xRenderFillRectanglesReq); + char *extra; + int extra_len; + + REQUEST_AT_LEAST_SIZE (xRenderFillRectanglesReq); + VERIFY_XIN_PICTURE (dst, stuff->dst, client, SecurityWriteAccess, + RenderErrBase + BadPicture); + extra_len = (client->req_len << 2) - sizeof (xRenderFillRectanglesReq); + if (extra_len && + (extra = (char *) ALLOCATE_LOCAL (extra_len))) + { + memcpy (extra, stuff + 1, extra_len); + FOR_NSCREENS_FORWARD(j) { + if (j) memcpy (stuff + 1, extra, extra_len); + if (dst->u.pict.root) + { + int x_off = panoramiXdataPtr[j].x; + int y_off = panoramiXdataPtr[j].y; + + if(x_off || y_off) { + xRectangle *rects = (xRectangle *) (stuff + 1); + int i = extra_len / sizeof (xRectangle); + + while (i--) + { + rects->x -= x_off; + rects->y -= y_off; + rects++; + } + } + } + stuff->dst = dst->info[j].id; + result = (*PanoramiXSaveRenderVector[X_RenderFillRectangles]) (client); + if(result != Success) break; + } + DEALLOCATE_LOCAL(extra); + } + + return result; +} + +void +PanoramiXRenderInit (void) +{ + int i; + + XRT_PICTURE = CreateNewResourceType (XineramaDeleteResource); + for (i = 0; i < RenderNumberRequests; i++) + PanoramiXSaveRenderVector[i] = ProcRenderVector[i]; + /* + * Stuff in Xinerama aware request processing hooks + */ + ProcRenderVector[X_RenderCreatePicture] = PanoramiXRenderCreatePicture; + ProcRenderVector[X_RenderChangePicture] = PanoramiXRenderChangePicture; + ProcRenderVector[X_RenderSetPictureClipRectangles] = PanoramiXRenderSetPictureClipRectangles; + ProcRenderVector[X_RenderFreePicture] = PanoramiXRenderFreePicture; + ProcRenderVector[X_RenderComposite] = PanoramiXRenderComposite; + ProcRenderVector[X_RenderCompositeGlyphs8] = PanoramiXRenderCompositeGlyphs; + ProcRenderVector[X_RenderCompositeGlyphs16] = PanoramiXRenderCompositeGlyphs; + ProcRenderVector[X_RenderCompositeGlyphs32] = PanoramiXRenderCompositeGlyphs; + ProcRenderVector[X_RenderFillRectangles] = PanoramiXRenderFillRectangles; +} + +void +PanoramiXRenderReset (void) +{ + int i; + for (i = 0; i < RenderNumberRequests; i++) + ProcRenderVector[i] = PanoramiXSaveRenderVector[i]; +} + +#endif /* PANORAMIX */ -- cgit v1.2.3