diff options
Diffstat (limited to 'xorg-server/hw/xgl/xglcmap.c')
-rw-r--r-- | xorg-server/hw/xgl/xglcmap.c | 466 |
1 files changed, 466 insertions, 0 deletions
diff --git a/xorg-server/hw/xgl/xglcmap.c b/xorg-server/hw/xgl/xglcmap.c new file mode 100644 index 000000000..b96308ddf --- /dev/null +++ b/xorg-server/hw/xgl/xglcmap.c @@ -0,0 +1,466 @@ +/* + * 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 (); +} |