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 ();
 | 
						|
}
 |