788 lines
20 KiB
C
788 lines
20 KiB
C
/*
|
|
* Copyright © 2004 David Reveman
|
|
*
|
|
* 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
|
|
* David Reveman not be used in advertising or publicity pertaining to
|
|
* distribution of the software without specific, written prior permission.
|
|
* David Reveman makes no representations about the suitability of this
|
|
* software for any purpose. It is provided "as is" without express or
|
|
* implied warranty.
|
|
*
|
|
* DAVID REVEMAN DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
|
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
|
|
* NO EVENT SHALL DAVID REVEMAN 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: David Reveman <davidr@novell.com>
|
|
*/
|
|
|
|
#include "xgl.h"
|
|
#include "fb.h"
|
|
|
|
#ifdef RENDER
|
|
|
|
#include "fbpict.h"
|
|
|
|
#define XGL_PICTURE_FALLBACK_PROLOGUE(pPicture, func) \
|
|
xglSyncDamageBoxBits (pPicture->pDrawable); \
|
|
XGL_PICTURE_SCREEN_UNWRAP (func)
|
|
|
|
#define XGL_PICTURE_FALLBACK_EPILOGUE(pPicture, func, xglfunc) \
|
|
XGL_PICTURE_SCREEN_WRAP (func, xglfunc); \
|
|
xglAddCurrentSurfaceDamage (pPicture->pDrawable)
|
|
|
|
void
|
|
xglComposite (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 pPictureScreen;
|
|
ScreenPtr pScreen = pDst->pDrawable->pScreen;
|
|
|
|
XGL_SCREEN_PRIV (pScreen);
|
|
|
|
if (xglCompositeGeneral (op,
|
|
pSrc, pMask, pDst, NULL,
|
|
xSrc, ySrc,
|
|
xMask, yMask,
|
|
xDst + pDst->pDrawable->x,
|
|
yDst + pDst->pDrawable->y,
|
|
width, height))
|
|
{
|
|
xglAddCurrentBitDamage (pDst->pDrawable);
|
|
return;
|
|
}
|
|
|
|
pPictureScreen = GetPictureScreen (pScreen);
|
|
|
|
if (pSrc->pDrawable)
|
|
{
|
|
if (!xglSyncBits (pSrc->pDrawable, NullBox))
|
|
FatalError (XGL_SW_FAILURE_STRING);
|
|
}
|
|
|
|
if (pMask && pMask->pDrawable)
|
|
{
|
|
if (!xglSyncBits (pMask->pDrawable, NullBox))
|
|
FatalError (XGL_SW_FAILURE_STRING);
|
|
}
|
|
|
|
if (op == PictOpSrc)
|
|
{
|
|
XGL_DRAWABLE_PIXMAP (pDst->pDrawable);
|
|
|
|
if (!xglMapPixmapBits (pPixmap))
|
|
FatalError (XGL_SW_FAILURE_STRING);
|
|
} else
|
|
xglSyncDamageBoxBits (pDst->pDrawable);
|
|
|
|
XGL_PICTURE_SCREEN_UNWRAP (Composite);
|
|
(*pPictureScreen->Composite) (op, pSrc, pMask, pDst,
|
|
xSrc, ySrc, xMask, yMask, xDst, yDst,
|
|
width, height);
|
|
XGL_PICTURE_SCREEN_WRAP (Composite, xglComposite);
|
|
|
|
if (op == PictOpSrc)
|
|
{
|
|
RegionRec region;
|
|
|
|
xDst += pDst->pDrawable->x;
|
|
yDst += pDst->pDrawable->y;
|
|
|
|
if (pSrc->pDrawable)
|
|
{
|
|
xSrc += pSrc->pDrawable->x;
|
|
ySrc += pSrc->pDrawable->y;
|
|
}
|
|
|
|
if (pMask && pMask->pDrawable)
|
|
{
|
|
xMask += pMask->pDrawable->x;
|
|
yMask += pMask->pDrawable->y;
|
|
}
|
|
|
|
if (!miComputeCompositeRegion (®ion, pSrc, pMask, pDst,
|
|
xSrc, ySrc, xMask, yMask, xDst, yDst,
|
|
width, height))
|
|
return;
|
|
|
|
xglAddSurfaceDamage (pDst->pDrawable, ®ion);
|
|
REGION_UNINIT (pDst->pDrawable->pScreen, ®ion);
|
|
} else
|
|
xglAddCurrentSurfaceDamage (pDst->pDrawable);
|
|
}
|
|
|
|
void
|
|
xglAddTriangles (PicturePtr pDst,
|
|
INT16 xOff,
|
|
INT16 yOff,
|
|
int ntri,
|
|
xTriangle *tris)
|
|
{
|
|
PictureScreenPtr pPictureScreen;
|
|
ScreenPtr pScreen = pDst->pDrawable->pScreen;
|
|
|
|
XGL_SCREEN_PRIV (pScreen);
|
|
XGL_DRAWABLE_PIXMAP_PRIV (pDst->pDrawable);
|
|
|
|
pPictureScreen = GetPictureScreen (pScreen);
|
|
|
|
pPixmapPriv->damageBox.x1 = 0;
|
|
pPixmapPriv->damageBox.y1 = 0;
|
|
pPixmapPriv->damageBox.x2 = pDst->pDrawable->width;
|
|
pPixmapPriv->damageBox.y2 = pDst->pDrawable->height;
|
|
|
|
XGL_PICTURE_FALLBACK_PROLOGUE (pDst, AddTriangles);
|
|
(*pPictureScreen->AddTriangles) (pDst, xOff, yOff, ntri, tris);
|
|
XGL_PICTURE_FALLBACK_EPILOGUE (pDst, AddTriangles, xglAddTriangles);
|
|
}
|
|
|
|
|
|
void
|
|
xglChangePicture (PicturePtr pPicture,
|
|
Mask mask)
|
|
{
|
|
PictureScreenPtr pPictureScreen;
|
|
ScreenPtr pScreen = pPicture->pDrawable->pScreen;
|
|
|
|
XGL_SCREEN_PRIV (pScreen);
|
|
XGL_DRAWABLE_PIXMAP_PRIV (pPicture->pDrawable);
|
|
|
|
pPictureScreen = GetPictureScreen (pScreen);
|
|
|
|
if (pPicture->stateChanges & CPRepeat)
|
|
pPixmapPriv->pictureMask |= xglPCFillMask;
|
|
|
|
if (pPicture->stateChanges & CPComponentAlpha)
|
|
pPixmapPriv->pictureMask |= xglPCComponentAlphaMask;
|
|
|
|
if (pPicture->stateChanges & CPDither)
|
|
pPixmapPriv->pictureMask |= xglPCDitherMask;
|
|
|
|
XGL_PICTURE_SCREEN_UNWRAP (ChangePicture);
|
|
(*pPictureScreen->ChangePicture) (pPicture, mask);
|
|
XGL_PICTURE_SCREEN_WRAP (ChangePicture, xglChangePicture);
|
|
}
|
|
|
|
int
|
|
xglChangePictureTransform (PicturePtr pPicture,
|
|
PictTransform *transform)
|
|
{
|
|
PictureScreenPtr pPictureScreen;
|
|
ScreenPtr pScreen = pPicture->pDrawable->pScreen;
|
|
int ret;
|
|
|
|
XGL_SCREEN_PRIV (pScreen);
|
|
XGL_DRAWABLE_PIXMAP_PRIV (pPicture->pDrawable);
|
|
|
|
pPictureScreen = GetPictureScreen (pScreen);
|
|
|
|
if (transform != pPicture->transform ||
|
|
(transform && memcmp (transform, &pPicture->transform,
|
|
sizeof (PictTransform))))
|
|
pPixmapPriv->pictureMask |= xglPCTransformMask;
|
|
|
|
XGL_PICTURE_SCREEN_UNWRAP (ChangePictureTransform);
|
|
ret = (*pPictureScreen->ChangePictureTransform) (pPicture, transform);
|
|
XGL_PICTURE_SCREEN_WRAP (ChangePictureTransform,
|
|
xglChangePictureTransform);
|
|
|
|
return ret;
|
|
}
|
|
|
|
int
|
|
xglChangePictureFilter (PicturePtr pPicture,
|
|
int filter,
|
|
xFixed *params,
|
|
int nparams)
|
|
{
|
|
PictureScreenPtr pPictureScreen;
|
|
ScreenPtr pScreen = pPicture->pDrawable->pScreen;
|
|
int ret;
|
|
|
|
XGL_SCREEN_PRIV (pScreen);
|
|
XGL_DRAWABLE_PIXMAP_PRIV (pPicture->pDrawable);
|
|
|
|
pPictureScreen = GetPictureScreen (pScreen);
|
|
|
|
pPixmapPriv->pictureMask |= xglPCFilterMask;
|
|
|
|
XGL_PICTURE_SCREEN_UNWRAP (ChangePictureFilter);
|
|
ret = (*pPictureScreen->ChangePictureFilter) (pPicture, filter,
|
|
params, nparams);
|
|
XGL_PICTURE_SCREEN_WRAP (ChangePictureFilter, xglChangePictureFilter);
|
|
|
|
return ret;
|
|
}
|
|
|
|
static void
|
|
xglDestroyDevicePicture (PicturePtr pPicture)
|
|
{
|
|
if (pPicture->pSourcePict->source.devPrivate.ptr)
|
|
glitz_surface_destroy (pPicture->pSourcePict->source.devPrivate.ptr);
|
|
}
|
|
|
|
PicturePtr
|
|
xglCreateDevicePicture (pointer data)
|
|
{
|
|
PicturePtr pPicture;
|
|
int error;
|
|
|
|
pPicture = CreateDevicePicture (0, &error);
|
|
if (!pPicture)
|
|
return 0;
|
|
|
|
pPicture->pSourcePict->source.devPrivate.ptr = data;
|
|
pPicture->pSourcePict->source.Destroy = xglDestroyDevicePicture;
|
|
|
|
return pPicture;
|
|
}
|
|
|
|
static int fillMode[] = {
|
|
GLITZ_FILL_TRANSPARENT, /* RepeatNone */
|
|
GLITZ_FILL_REPEAT, /* RepeatNormal */
|
|
GLITZ_FILL_NEAREST, /* RepeatPad */
|
|
GLITZ_FILL_REFLECT /* RepeatReflect */
|
|
};
|
|
|
|
static void
|
|
xglUpdatePicture (PicturePtr pPicture)
|
|
{
|
|
glitz_surface_t *surface;
|
|
|
|
XGL_DRAWABLE_PIXMAP_PRIV (pPicture->pDrawable);
|
|
|
|
surface = pPixmapPriv->surface;
|
|
|
|
if (pPixmapPriv->pictureMask & xglPCFillMask)
|
|
{
|
|
glitz_surface_set_fill (surface, fillMode[pPicture->repeat]);
|
|
}
|
|
|
|
if (pPixmapPriv->pictureMask & xglPCFilterMask)
|
|
{
|
|
switch (pPicture->filter) {
|
|
case PictFilterNearest:
|
|
case PictFilterFast:
|
|
glitz_surface_set_filter (surface, GLITZ_FILTER_NEAREST, NULL, 0);
|
|
break;
|
|
case PictFilterGood:
|
|
case PictFilterBest:
|
|
case PictFilterBilinear:
|
|
glitz_surface_set_filter (surface, GLITZ_FILTER_BILINEAR, NULL, 0);
|
|
break;
|
|
case PictFilterConvolution:
|
|
glitz_surface_set_filter (surface, GLITZ_FILTER_CONVOLUTION,
|
|
(glitz_fixed16_16_t *)
|
|
pPicture->filter_params,
|
|
pPicture->filter_nparams);
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (pPixmapPriv->pictureMask & xglPCTransformMask)
|
|
{
|
|
glitz_surface_set_transform (surface, (glitz_transform_t *)
|
|
pPicture->transform);
|
|
}
|
|
|
|
if (pPixmapPriv->pictureMask & xglPCComponentAlphaMask)
|
|
{
|
|
glitz_surface_set_component_alpha (surface, pPicture->componentAlpha);
|
|
}
|
|
|
|
if (pPixmapPriv->pictureMask & xglPCDitherMask)
|
|
{
|
|
glitz_surface_set_dither (surface, pPicture->dither);
|
|
}
|
|
|
|
pPixmapPriv->pictureMask &= ~XGL_PICTURE_CHANGES (~0);
|
|
}
|
|
|
|
#define N_STACK_PARAM 256
|
|
|
|
static int gradientNParam[] = {
|
|
0, /* SourcePictTypeSolidFill */
|
|
4, /* SourcePictTypeLinear */
|
|
6, /* SourcePictTypeRadial */
|
|
4, /* SourcePictTypeConical */
|
|
};
|
|
|
|
Bool
|
|
xglSyncPicture (ScreenPtr pScreen,
|
|
PicturePtr pPicture,
|
|
INT16 x,
|
|
INT16 y,
|
|
CARD16 width,
|
|
CARD16 height,
|
|
INT16 *xOff,
|
|
INT16 *yOff)
|
|
{
|
|
xglPixmapPtr pPixmapPriv;
|
|
|
|
XGL_SCREEN_PRIV (pScreen);
|
|
|
|
*xOff = *yOff = 0;
|
|
|
|
if (pPicture->pSourcePict)
|
|
{
|
|
if (pPicture->pSourcePict->source.devPrivate.ptr)
|
|
return TRUE;
|
|
|
|
if (pPicture->pDrawable)
|
|
{
|
|
(*pScreen->DestroyPixmap) ((PixmapPtr) pPicture->pDrawable);
|
|
pPicture->pDrawable = (DrawablePtr) 0;
|
|
}
|
|
|
|
switch (pPicture->pSourcePict->source.type) {
|
|
case SourcePictTypeSolidFill:
|
|
x = y = 0;
|
|
width = height = 1;
|
|
break;
|
|
case SourcePictTypeLinear:
|
|
case SourcePictTypeRadial: {
|
|
glitz_fixed16_16_t stackParam[N_STACK_PARAM];
|
|
glitz_fixed16_16_t *param;
|
|
int nParam, nStop, size, i;
|
|
CARD32 *pixel;
|
|
PictGradientStopPtr pStop;
|
|
glitz_buffer_t *buffer;
|
|
glitz_format_t *format;
|
|
glitz_surface_t *surface;
|
|
static glitz_pixel_format_t pixelFormat = {
|
|
GLITZ_FOURCC_RGB,
|
|
{
|
|
32,
|
|
0xff000000,
|
|
0x00ff0000,
|
|
0x0000ff00,
|
|
0x000000ff
|
|
},
|
|
0, 0, 0,
|
|
GLITZ_PIXEL_SCANLINE_ORDER_BOTTOM_UP
|
|
};
|
|
|
|
if (!(pScreenPriv->features & GLITZ_FEATURE_FRAGMENT_PROGRAM_MASK))
|
|
break;
|
|
|
|
format = glitz_find_standard_format (pScreenPriv->drawable,
|
|
GLITZ_STANDARD_ARGB32);
|
|
if (!format)
|
|
break;
|
|
|
|
nParam = gradientNParam[pPicture->pSourcePict->gradient.type];
|
|
pStop = pPicture->pSourcePict->gradient.stops;
|
|
nStop = pPicture->pSourcePict->gradient.nstops;
|
|
|
|
size = nParam + nStop * 4;
|
|
if (size > N_STACK_PARAM)
|
|
{
|
|
param = malloc (sizeof (xFixed) * size);
|
|
if (!param)
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
param = stackParam;
|
|
}
|
|
|
|
pixel = (CARD32 *) (param + nParam + nStop * 3);
|
|
|
|
buffer = glitz_buffer_create_for_data (pixel);
|
|
if (!buffer)
|
|
{
|
|
if (size > N_STACK_PARAM)
|
|
free (param);
|
|
|
|
break;
|
|
}
|
|
|
|
surface = glitz_surface_create (pScreenPriv->drawable,
|
|
format, nStop, 1, 0, NULL);
|
|
if (!surface)
|
|
{
|
|
glitz_buffer_destroy (buffer);
|
|
if (size > N_STACK_PARAM)
|
|
free (param);
|
|
|
|
break;
|
|
}
|
|
|
|
for (i = 0; i < nStop; i++)
|
|
{
|
|
pixel[i] = pStop[i].color;
|
|
|
|
param[nParam + 3 * i + 0] = pStop[i].x;
|
|
param[nParam + 3 * i + 1] = i << 16;
|
|
param[nParam + 3 * i + 2] = 0;
|
|
}
|
|
|
|
glitz_set_pixels (surface, 0, 0, nStop, 1, &pixelFormat, buffer);
|
|
|
|
glitz_buffer_destroy (buffer);
|
|
|
|
switch (pPicture->pSourcePict->source.type) {
|
|
case SourcePictTypeLinear:
|
|
param[0] = pPicture->pSourcePict->linear.p1.x;
|
|
param[1] = pPicture->pSourcePict->linear.p1.y;
|
|
param[2] = pPicture->pSourcePict->linear.p2.x;
|
|
param[3] = pPicture->pSourcePict->linear.p2.y;
|
|
|
|
glitz_surface_set_filter (surface,
|
|
GLITZ_FILTER_LINEAR_GRADIENT,
|
|
param, nParam + nStop * 3);
|
|
break;
|
|
case SourcePictTypeRadial:
|
|
param[0] = pPicture->pSourcePict->radial.inner.x;
|
|
param[1] = pPicture->pSourcePict->radial.inner.y;
|
|
param[2] = pPicture->pSourcePict->radial.inner_radius;
|
|
param[3] = pPicture->pSourcePict->radial.outer.x;
|
|
param[4] = pPicture->pSourcePict->radial.outer.y;
|
|
param[5] = pPicture->pSourcePict->radial.outer_radius;
|
|
|
|
glitz_surface_set_filter (surface,
|
|
GLITZ_FILTER_RADIAL_GRADIENT,
|
|
param, nParam + nStop * 3);
|
|
break;
|
|
}
|
|
|
|
glitz_surface_set_fill (surface, fillMode[pPicture->repeat]);
|
|
glitz_surface_set_transform (surface, (glitz_transform_t *)
|
|
pPicture->transform);
|
|
|
|
pPicture->pSourcePict->gradient.devPrivate.ptr = surface;
|
|
pPicture->pSourcePict->gradient.Destroy = xglDestroyDevicePicture;
|
|
|
|
if (size > N_STACK_PARAM)
|
|
free (param);
|
|
|
|
return TRUE;
|
|
} break;
|
|
case SourcePictTypeConical:
|
|
default:
|
|
break;
|
|
}
|
|
|
|
if (!pPicture->pDrawable)
|
|
{
|
|
PictFormatPtr pFormat;
|
|
PixmapPtr pPixmap;
|
|
PicturePtr pTmp;
|
|
RegionRec region;
|
|
BoxRec box;
|
|
int error;
|
|
|
|
pFormat = PictureMatchFormat (pScreen, 32, PICT_a8r8g8b8);
|
|
if (!pFormat)
|
|
return FALSE;
|
|
|
|
pPixmap = (*pScreen->CreatePixmap) (pScreen, width, height,
|
|
pFormat->depth);
|
|
if (!pPixmap)
|
|
return FALSE;
|
|
|
|
pTmp = CreatePicture (0, &pPixmap->drawable, pFormat, 0, NULL,
|
|
serverClient, &error);
|
|
if (!pTmp)
|
|
{
|
|
(*pScreen->DestroyPixmap) (pPixmap);
|
|
return FALSE;
|
|
}
|
|
|
|
ValidatePicture (pTmp);
|
|
|
|
if (!xglSyncBits (pTmp->pDrawable, NullBox))
|
|
FatalError (XGL_SW_FAILURE_STRING);
|
|
|
|
fbCompositeGeneral (PictOpSrc,
|
|
pPicture, 0, pTmp,
|
|
x, y, 0, 0, 0, 0,
|
|
width, height);
|
|
|
|
FreePicture ((pointer) pTmp, (XID) 0);
|
|
|
|
box.x1 = 0;
|
|
box.y1 = 0;
|
|
box.x2 = width;
|
|
box.y2 = height;
|
|
|
|
REGION_INIT (pScreen, ®ion, &box, 1);
|
|
xglAddSurfaceDamage (&pPixmap->drawable, ®ion);
|
|
REGION_UNINIT (pDrawable->pScreen, ®ion);
|
|
|
|
pPicture->pDrawable = &pPixmap->drawable;
|
|
|
|
*xOff = x;
|
|
*yOff = y;
|
|
|
|
XGL_GET_PIXMAP_PRIV (pPixmap)->pictureMask &=
|
|
~(xglPCFillMask | xglPCFilterMask | xglPCTransformMask);
|
|
}
|
|
}
|
|
|
|
#ifdef XV
|
|
switch (pPicture->format) {
|
|
case PICT_yuy2:
|
|
xglSetPixmapVisual ((PixmapPtr) pPicture->pDrawable,
|
|
&pScreenPriv->pXvVisual[XGL_XV_FORMAT_YUY2]);
|
|
break;
|
|
case PICT_yv12:
|
|
xglSetPixmapVisual ((PixmapPtr) pPicture->pDrawable,
|
|
&pScreenPriv->pXvVisual[XGL_XV_FORMAT_YV12]);
|
|
default:
|
|
break;
|
|
}
|
|
#endif
|
|
|
|
if (!xglSyncSurface (pPicture->pDrawable))
|
|
return FALSE;
|
|
|
|
pPixmapPriv = XGL_GET_PIXMAP_PRIV ((PixmapPtr) pPicture->pDrawable);
|
|
if (XGL_PICTURE_CHANGES (pPixmapPriv->pictureMask))
|
|
xglUpdatePicture (pPicture);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
static int
|
|
xglVisualDepth (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;
|
|
}
|
|
|
|
typedef struct _xglformatInit {
|
|
CARD32 format;
|
|
CARD8 depth;
|
|
} xglFormatInitRec, *xglFormatInitPtr;
|
|
|
|
static int
|
|
xglAddFormat (xglFormatInitPtr formats,
|
|
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))
|
|
|
|
Bool
|
|
xglPictureInit (ScreenPtr pScreen)
|
|
{
|
|
int f, nformats = 0;
|
|
PictFormatPtr pFormats;
|
|
xglFormatInitRec formats[64];
|
|
CARD32 format;
|
|
CARD8 depth;
|
|
VisualPtr pVisual;
|
|
int v;
|
|
int bpp;
|
|
int r, g, b;
|
|
int d;
|
|
DepthPtr pDepth;
|
|
|
|
/* formats required by protocol */
|
|
formats[nformats].format = PICT_a1;
|
|
formats[nformats].depth = 1;
|
|
nformats++;
|
|
formats[nformats].format = PICT_a4;
|
|
formats[nformats].depth = 4;
|
|
nformats++;
|
|
formats[nformats].format = PICT_a8;
|
|
formats[nformats].depth = 8;
|
|
nformats++;
|
|
formats[nformats].format = PICT_a8r8g8b8;
|
|
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 = xglVisualDepth (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);
|
|
if (pVisual->offsetBlue == 0 &&
|
|
pVisual->offsetGreen == b &&
|
|
pVisual->offsetRed == b + g)
|
|
{
|
|
format = PICT_FORMAT (bpp, PICT_TYPE_ARGB, 0, r, g, b);
|
|
nformats = xglAddFormat (formats, nformats, format, depth);
|
|
}
|
|
break;
|
|
case StaticColor:
|
|
case PseudoColor:
|
|
case StaticGray:
|
|
case GrayScale:
|
|
break;
|
|
}
|
|
}
|
|
|
|
/* walk supported depths and add missing Direct formats */
|
|
for (d = 0; d < pScreen->numDepths; d++)
|
|
{
|
|
pDepth = &pScreen->allowedDepths[d];
|
|
bpp = BitsPerPixel (pDepth->depth);
|
|
format = 0;
|
|
switch (bpp) {
|
|
case 16:
|
|
if (pDepth->depth == 15)
|
|
nformats = xglAddFormat (formats, nformats,
|
|
PICT_x1r5g5b5, pDepth->depth);
|
|
if (pDepth->depth == 16)
|
|
nformats = xglAddFormat (formats, nformats,
|
|
PICT_r5g6b5, pDepth->depth);
|
|
break;
|
|
case 24:
|
|
if (pDepth->depth == 24)
|
|
nformats = xglAddFormat (formats, nformats,
|
|
PICT_r8g8b8, pDepth->depth);
|
|
break;
|
|
case 32:
|
|
if (pDepth->depth == 24)
|
|
nformats = xglAddFormat (formats, nformats,
|
|
PICT_x8r8g8b8, pDepth->depth);
|
|
break;
|
|
}
|
|
}
|
|
|
|
/* add YUV formats */
|
|
nformats = xglAddFormat (formats, nformats, PICT_yuy2, 16);
|
|
nformats = xglAddFormat (formats, nformats, PICT_yv12, 12);
|
|
|
|
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_A:
|
|
pFormats[f].type = PictTypeDirect;
|
|
pFormats[f].direct.alpha = 0;
|
|
pFormats[f].direct.alphaMask = Mask (PICT_FORMAT_A (format));
|
|
break;
|
|
case PICT_TYPE_COLOR:
|
|
case PICT_TYPE_GRAY:
|
|
pFormats[f].type = PictTypeDirect;
|
|
break;
|
|
case PICT_TYPE_YUY2:
|
|
case PICT_TYPE_YV12:
|
|
pFormats[f].type = PictTypeOther;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (!fbPictureInit (pScreen, pFormats, nformats))
|
|
return FALSE;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
void
|
|
xglPictureClipExtents (PicturePtr pPicture,
|
|
BoxPtr extents)
|
|
{
|
|
if (pPicture->clientClipType != CT_NONE)
|
|
{
|
|
BoxPtr clip = REGION_EXTENTS (pPicture->pDrawable->pScreen,
|
|
(RegionPtr) pPicture->clientClip);
|
|
|
|
if (extents->x1 < pPicture->clipOrigin.x + clip->x1)
|
|
extents->x1 = pPicture->clipOrigin.x + clip->x1;
|
|
|
|
if (extents->y1 < pPicture->clipOrigin.y + clip->y1)
|
|
extents->y1 = pPicture->clipOrigin.y + clip->y1;
|
|
|
|
if (extents->x2 > pPicture->clipOrigin.x + clip->x2)
|
|
extents->x2 = pPicture->clipOrigin.x + clip->x2;
|
|
|
|
if (extents->y2 > pPicture->clipOrigin.y + clip->y2)
|
|
extents->y2 = pPicture->clipOrigin.y + clip->y2;
|
|
}
|
|
else
|
|
{
|
|
if (extents->x1 < 0)
|
|
extents->x1 = 0;
|
|
|
|
if (extents->y1 < 0)
|
|
extents->y1 = 0;
|
|
|
|
if (extents->x2 > pPicture->pDrawable->width)
|
|
extents->x2 = pPicture->pDrawable->width;
|
|
|
|
if (extents->y2 > pPicture->pDrawable->height)
|
|
extents->y2 = pPicture->pDrawable->height;
|
|
}
|
|
}
|
|
|
|
#endif
|