xenocara/xserver/hw/xgl/xglcmap.c
2006-11-26 18:13:41 +00:00

467 lines
9.2 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 "colormapst.h"
#include "micmap.h"
#include "fb.h"
static xglPixelFormatRec xglPixelFormats[] = {
{
8, 8,
{
8,
0x000000ff,
0x00000000,
0x00000000,
0x00000000
}
}, {
15, 5,
{
16,
0x00000000,
0x00007c00,
0x000003e0,
0x0000001f
}
}, {
16, 6,
{
16,
0x00000000,
0x0000f800,
0x000007e0,
0x0000001f
}
}, {
24, 8,
{
32,
0x00000000,
0x00ff0000,
0x0000ff00,
0x000000ff
}
}, {
32, 8,
{
32,
0xff000000,
0x00ff0000,
0x0000ff00,
0x000000ff
}
}
};
#define NUM_XGL_PIXEL_FORMATS \
(sizeof (xglPixelFormats) / sizeof (xglPixelFormats[0]))
xglVisualPtr xglVisuals = NULL;
void
xglSetVisualTypes (int depth,
int visuals,
int redSize,
int greenSize,
int blueSize)
{
xglPixelFormatPtr pBestFormat = 0;
int i, rs, gs, bs, diff, bestDiff = 0;
for (i = 0; i < NUM_XGL_PIXEL_FORMATS; i++)
{
if (xglPixelFormats[i].depth == depth)
{
if (visuals)
{
rs = Ones (xglPixelFormats[i].masks.red_mask);
gs = Ones (xglPixelFormats[i].masks.green_mask);
bs = Ones (xglPixelFormats[i].masks.blue_mask);
if (redSize >= rs &&
greenSize >= gs &&
blueSize >= bs)
{
diff = (redSize - rs) + (greenSize - gs) + (blueSize - bs);
if (pBestFormat)
{
if (diff < bestDiff)
{
pBestFormat = &xglPixelFormats[i];
bestDiff = diff;
}
}
else
{
pBestFormat = &xglPixelFormats[i];
bestDiff = diff;
}
}
}
else
{
pBestFormat = &xglPixelFormats[i];
break;
}
}
}
if (pBestFormat)
{
xglVisualPtr new, *prev, v;
unsigned int bitsPerRGB;
Pixel rm, gm, bm;
new = xalloc (sizeof (xglVisualRec));
if (!new)
return;
new->next = 0;
new->format.surface = 0;
new->format.drawable = 0;
new->pPixel = pBestFormat;
new->vid = 0;
bitsPerRGB = pBestFormat->bitsPerRGB;
rm = pBestFormat->masks.red_mask;
gm = pBestFormat->masks.green_mask;
bm = pBestFormat->masks.blue_mask;
fbSetVisualTypesAndMasks (depth, visuals, bitsPerRGB, rm, gm, bm);
for (prev = &xglVisuals; (v = *prev); prev = &v->next);
*prev = new;
}
else
{
fbSetVisualTypesAndMasks (depth, 0, 0, 0, 0, 0);
}
}
Bool
xglHasVisualTypes (xglVisualPtr pVisual,
int depth)
{
xglVisualPtr v;
for (v = pVisual; v; v = v->next)
if (v->pPixel->depth == depth)
return TRUE;
return FALSE;
}
glitz_format_t *
xglFindBestSurfaceFormat (ScreenPtr pScreen,
xglPixelFormatPtr pPixel)
{
glitz_format_t templ, *format, *best = 0;
unsigned int mask;
unsigned short rs, gs, bs, as;
int i = 0;
XGL_SCREEN_PRIV (pScreen);
rs = Ones (pPixel->masks.red_mask);
gs = Ones (pPixel->masks.green_mask);
bs = Ones (pPixel->masks.blue_mask);
as = Ones (pPixel->masks.alpha_mask);
templ.color.fourcc = GLITZ_FOURCC_RGB;
mask = GLITZ_FORMAT_FOURCC_MASK;
do {
format = glitz_find_format (pScreenPriv->drawable, mask, &templ, i++);
if (format)
{
if (format->color.red_size >= rs &&
format->color.green_size >= gs &&
format->color.blue_size >= bs &&
format->color.alpha_size >= as)
{
if (best)
{
if (((format->color.red_size - rs) +
(format->color.green_size - gs) +
(format->color.blue_size - bs)) <
((best->color.red_size - rs) +
(best->color.green_size - gs) +
(best->color.blue_size - bs)))
best = format;
}
else
{
best = format;
}
}
}
} while (format);
return best;
}
static Bool
xglInitVisual (ScreenPtr pScreen,
xglVisualPtr pVisual,
xglPixelFormatPtr pPixel,
VisualID vid)
{
glitz_format_t *format;
XGL_SCREEN_PRIV (pScreen);
format = xglFindBestSurfaceFormat (pScreen, pPixel);
if (format)
{
glitz_drawable_format_t templ;
unsigned long mask;
templ.color = format->color;
templ.depth_size = 0;
templ.stencil_size = 0;
templ.doublebuffer = 0;
templ.samples = 1;
mask =
GLITZ_FORMAT_FOURCC_MASK |
GLITZ_FORMAT_RED_SIZE_MASK |
GLITZ_FORMAT_GREEN_SIZE_MASK |
GLITZ_FORMAT_BLUE_SIZE_MASK |
GLITZ_FORMAT_ALPHA_SIZE_MASK |
GLITZ_FORMAT_DEPTH_SIZE_MASK |
GLITZ_FORMAT_STENCIL_SIZE_MASK |
GLITZ_FORMAT_DOUBLEBUFFER_MASK |
GLITZ_FORMAT_SAMPLES_MASK;
pVisual->next = 0;
pVisual->vid = vid;
pVisual->pPixel = pPixel;
pVisual->pbuffer = FALSE;
pVisual->format.surface = format;
pVisual->format.drawable =
glitz_find_drawable_format (pScreenPriv->drawable,
mask, &templ, 0);
return TRUE;
}
return FALSE;
}
static Bool
xglInitPbufferVisual (ScreenPtr pScreen,
xglVisualPtr pVisual,
xglPixelFormatPtr pPixel,
VisualID vid)
{
glitz_format_t *format;
XGL_SCREEN_PRIV (pScreen);
format = xglFindBestSurfaceFormat (pScreen, pPixel);
if (format)
{
glitz_drawable_format_t templ, *screenFormat;
unsigned long mask;
/* use same drawable format as screen for pbuffers */
screenFormat = glitz_drawable_get_format (pScreenPriv->drawable);
templ.id = screenFormat->id;
templ.color = format->color;
templ.samples = 1;
mask =
GLITZ_FORMAT_ID_MASK |
GLITZ_FORMAT_FOURCC_MASK |
GLITZ_FORMAT_RED_SIZE_MASK |
GLITZ_FORMAT_GREEN_SIZE_MASK |
GLITZ_FORMAT_BLUE_SIZE_MASK |
GLITZ_FORMAT_SAMPLES_MASK;
pVisual->next = 0;
pVisual->vid = vid;
pVisual->pPixel = pPixel;
pVisual->pbuffer = TRUE;
pVisual->format.surface = format;
pVisual->format.drawable =
glitz_find_pbuffer_format (pScreenPriv->drawable,
mask, &templ, 0);
if (pVisual->format.drawable)
return TRUE;
}
return FALSE;
}
void
xglInitVisuals (ScreenPtr pScreen)
{
xglVisualPtr pVisual, v, new, *prev;
int i;
XGL_SCREEN_PRIV (pScreen);
for (i = 0; i < pScreen->numVisuals; i++)
{
for (pVisual = xglVisuals; pVisual; pVisual = pVisual->next)
if (pVisual->pPixel->depth == pScreen->visuals[i].nplanes)
break;
if (pVisual)
{
new = xalloc (sizeof (xglVisualRec));
if (new)
{
if (xglInitVisual (pScreen, new, pVisual->pPixel,
pScreen->visuals[i].vid))
{
new->next = 0;
prev = &pScreenPriv->pVisual;
while ((v = *prev))
prev = &v->next;
*prev = new;
}
else
{
xfree (new);
}
}
new = xalloc (sizeof (xglVisualRec));
if (new)
{
if (xglInitPbufferVisual (pScreen, new, pVisual->pPixel,
pScreen->visuals[i].vid))
{
new->next = 0;
prev = &pScreenPriv->pVisual;
while ((v = *prev))
prev = &v->next;
*prev = new;
}
else
{
xfree (new);
}
}
}
}
/* Add additional Xgl visuals for pixmap formats */
for (i = 0; i < screenInfo.numPixmapFormats; i++)
{
if (!xglHasVisualTypes (pScreenPriv->pVisual,
screenInfo.formats[i].depth))
{
for (v = xglVisuals; v; v = v->next)
if (v->pPixel->depth == screenInfo.formats[i].depth)
break;
if (v)
{
new = xalloc (sizeof (xglVisualRec));
if (new)
{
if (xglInitVisual (pScreen, new, v->pPixel, 0))
{
new->next = 0;
prev = &pScreenPriv->pVisual;
while ((v = *prev))
prev = &v->next;
*prev = new;
}
else
{
xfree (new);
}
}
}
}
}
}
xglVisualPtr
xglFindVisualWithDepth (ScreenPtr pScreen,
int depth)
{
xglVisualPtr v;
XGL_SCREEN_PRIV (pScreen);
for (v = pScreenPriv->pVisual; v; v = v->next)
{
if (v->pPixel->depth == depth)
return v;
}
return 0;
}
xglVisualPtr
xglFindVisualWithId (ScreenPtr pScreen,
int vid)
{
xglVisualPtr v;
XGL_SCREEN_PRIV (pScreen);
for (v = pScreenPriv->pVisual; v; v = v->next)
{
if (v->vid == vid)
return v;
}
return 0;
}
void
xglClearVisualTypes (void)
{
xglVisualPtr v;
while (xglVisuals)
{
v = xglVisuals;
xglVisuals = v->next;
xfree (v);
}
miClearVisualTypes ();
}