467 lines
9.2 KiB
C
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 ();
|
||
|
}
|