aboutsummaryrefslogtreecommitdiff
path: root/xorg-server/hw/xgl/xglcmap.c
diff options
context:
space:
mode:
Diffstat (limited to 'xorg-server/hw/xgl/xglcmap.c')
-rw-r--r--xorg-server/hw/xgl/xglcmap.c466
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 ();
+}