[Spice-devel] [PATCH 1/7] qxl: split uxa related code into separate file

airlied at gmail.com airlied at gmail.com
Sun Feb 24 21:31:09 PST 2013


From: Dave Airlie <airlied at gmail.com>

qxl_driver.c is insane, it needs to be split out like other X.org drivers.

This is step one, move the uxa interfacing code into its own file.

Signed-off-by: Dave Airlie <airlied at redhat.com>
---
 src/qxl_uxa.c | 502 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 502 insertions(+)
 create mode 100644 src/qxl_uxa.c

diff --git a/src/qxl_uxa.c b/src/qxl_uxa.c
new file mode 100644
index 0000000..a6e528c
--- /dev/null
+++ b/src/qxl_uxa.c
@@ -0,0 +1,502 @@
+/*
+ * Copyright 2008 Red Hat, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, and/or sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/** \file qxl_driver.c
+ * \author Adam Jackson <ajax at redhat.com>
+ * \author Søren Sandmann <sandmann at redhat.com>
+ *
+ * This is qxl, a driver for the Qumranet paravirtualized graphics device
+ * in qemu.
+ */
+
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "qxl.h"
+#include <spice/protocol.h>
+
+#if HAS_DEVPRIVATEKEYREC
+DevPrivateKeyRec uxa_pixmap_index;
+#else
+int uxa_pixmap_index;
+#endif
+
+static Bool
+qxl_prepare_access (PixmapPtr pixmap, RegionPtr region, uxa_access_t access)
+{
+    return qxl_surface_prepare_access (get_surface (pixmap),
+                                       pixmap, region, access);
+}
+
+static void
+qxl_finish_access (PixmapPtr pixmap)
+{
+    qxl_surface_finish_access (get_surface (pixmap), pixmap);
+}
+
+static Bool
+qxl_pixmap_is_offscreen (PixmapPtr pixmap)
+{
+    return !!get_surface (pixmap);
+}
+
+static Bool
+good_alu_and_pm (DrawablePtr drawable, int alu, Pixel planemask)
+{
+    if (!UXA_PM_IS_SOLID (drawable, planemask))
+	return FALSE;
+    
+    if (alu != GXcopy)
+	return FALSE;
+    
+    return TRUE;
+}
+
+/*
+ * Solid fill
+ */
+static Bool
+qxl_check_solid (DrawablePtr drawable, int alu, Pixel planemask)
+{
+    if (!good_alu_and_pm (drawable, alu, planemask))
+	return FALSE;
+    
+    return TRUE;
+}
+
+static Bool
+qxl_prepare_solid (PixmapPtr pixmap, int alu, Pixel planemask, Pixel fg)
+{
+    qxl_surface_t *surface;
+    
+    if (!(surface = get_surface (pixmap)))
+	return FALSE;
+    
+    return qxl_surface_prepare_solid (surface, fg);
+}
+
+static void
+qxl_solid (PixmapPtr pixmap, int x1, int y1, int x2, int y2)
+{
+    qxl_surface_solid (get_surface (pixmap), x1, y1, x2, y2);
+}
+
+static void
+qxl_done_solid (PixmapPtr pixmap)
+{
+}
+
+/*
+ * Copy
+ */
+static Bool
+qxl_check_copy (PixmapPtr source, PixmapPtr dest,
+                int alu, Pixel planemask)
+{
+    if (!good_alu_and_pm ((DrawablePtr)source, alu, planemask))
+	return FALSE;
+    
+    if (source->drawable.bitsPerPixel != dest->drawable.bitsPerPixel)
+    {
+	ErrorF ("differing bitsperpixel - this shouldn't happen\n");
+	return FALSE;
+    }
+    
+    return TRUE;
+}
+
+static Bool
+qxl_prepare_copy (PixmapPtr source, PixmapPtr dest,
+                  int xdir, int ydir, int alu,
+                  Pixel planemask)
+{
+    return qxl_surface_prepare_copy (get_surface (dest), get_surface (source));
+}
+
+static void
+qxl_copy (PixmapPtr dest,
+          int src_x1, int src_y1,
+          int dest_x1, int dest_y1,
+          int width, int height)
+{
+    qxl_surface_copy (get_surface (dest),
+                      src_x1, src_y1,
+                      dest_x1, dest_y1,
+                      width, height);
+}
+
+static void
+qxl_done_copy (PixmapPtr dest)
+{
+}
+
+/*
+ * Composite
+ */
+static Bool
+can_accelerate_picture (PicturePtr pict)
+{
+    if (!pict)
+	return TRUE;
+
+    if (pict->format != PICT_a8r8g8b8		&&
+	pict->format != PICT_x8r8g8b8		&&
+	pict->format != PICT_a8)
+    {
+	return FALSE;
+    }
+
+    if (!pict->pDrawable)
+	return FALSE;
+
+    if (pict->transform)
+    {
+	if (pict->transform->matrix[2][0] != 0	||
+	    pict->transform->matrix[2][1] != 0	||
+	    pict->transform->matrix[2][2] != pixman_int_to_fixed (1))
+	{
+	    return FALSE;
+	}
+    }
+
+    if (pict->filter != PictFilterBilinear	&&
+	pict->filter != PictFilterNearest)
+    {
+	return FALSE;
+    }
+    
+    return TRUE;
+}
+
+#define QXL_HAS_CAP(qxl, cap)						\
+    (((qxl)->rom->client_capabilities[(cap) / 8]) & (1 << ((cap) % 8)))
+
+static Bool
+qxl_has_composite (qxl_screen_t *qxl)
+{
+#ifndef XSPICE
+    return
+	qxl->pci->revision >= 4			&&
+	QXL_HAS_CAP (qxl, SPICE_DISPLAY_CAP_COMPOSITE);
+#else
+    /* FIXME */
+    return FALSE;
+#endif
+}
+
+static Bool
+qxl_has_a8_surfaces (qxl_screen_t *qxl)
+{
+#ifndef XSPICE
+    return
+	qxl->pci->revision >= 4			&&
+	QXL_HAS_CAP (qxl, SPICE_DISPLAY_CAP_A8_SURFACE);
+#else
+    /* FIXME */
+    return FALSE;
+#endif
+}
+
+static Bool
+qxl_check_composite (int op,
+		     PicturePtr pSrcPicture,
+		     PicturePtr pMaskPicture,
+		     PicturePtr pDstPicture,
+		     int width, int height)
+{
+    int i;
+    ScreenPtr pScreen = pDstPicture->pDrawable->pScreen;
+    ScrnInfoPtr pScrn = xf86ScreenToScrn (pScreen);
+    qxl_screen_t *qxl = pScrn->driverPrivate;
+    
+    static const int accelerated_ops[] =
+    {
+	PictOpClear, PictOpSrc, PictOpDst, PictOpOver, PictOpOverReverse,
+	PictOpIn, PictOpInReverse, PictOpOut, PictOpOutReverse,
+	PictOpAtop, PictOpAtopReverse, PictOpXor, PictOpAdd,
+	PictOpSaturate, PictOpMultiply, PictOpScreen, PictOpOverlay,
+	PictOpDarken, PictOpLighten, PictOpColorDodge, PictOpColorBurn,
+	PictOpHardLight, PictOpSoftLight, PictOpDifference, PictOpExclusion,
+	PictOpHSLHue, PictOpHSLSaturation, PictOpHSLColor, PictOpHSLLuminosity,
+    };
+
+    if (!qxl_has_composite (qxl))
+	return FALSE;
+    
+    if (!can_accelerate_picture (pSrcPicture)	||
+	!can_accelerate_picture (pMaskPicture)	||
+	!can_accelerate_picture (pDstPicture))
+    {
+	return FALSE;
+    }
+
+    for (i = 0; i < sizeof (accelerated_ops) / sizeof (accelerated_ops[0]); ++i)
+    {
+	if (accelerated_ops[i] == op)
+	    goto found;
+    }
+    return FALSE;
+
+found:
+    return TRUE;
+}
+
+static Bool
+qxl_check_composite_target (PixmapPtr pixmap)
+{
+    return TRUE;
+}
+
+static Bool
+qxl_check_composite_texture (ScreenPtr screen,
+			     PicturePtr pPicture)
+{
+    return TRUE;
+}
+
+static Bool
+qxl_prepare_composite (int op,
+		       PicturePtr pSrcPicture,
+		       PicturePtr pMaskPicture,
+		       PicturePtr pDstPicture,
+		       PixmapPtr pSrc,
+		       PixmapPtr pMask,
+		       PixmapPtr pDst)
+{
+    return qxl_surface_prepare_composite (
+	op, pSrcPicture, pMaskPicture, pDstPicture,
+	get_surface (pSrc),
+	pMask? get_surface (pMask) : NULL,
+	get_surface (pDst));
+}
+
+static void
+qxl_composite (PixmapPtr pDst,
+	       int src_x, int src_y,
+	       int mask_x, int mask_y,
+	       int dst_x, int dst_y,
+	       int width, int height)
+{
+    qxl_surface_composite (
+	get_surface (pDst),
+	src_x, src_y,
+	mask_x, mask_y,
+	dst_x, dst_y, width, height);
+}
+
+static void
+qxl_done_composite (PixmapPtr pDst)
+{
+    ;
+}
+
+static Bool
+qxl_put_image (PixmapPtr pDst, int x, int y, int w, int h,
+               char *src, int src_pitch)
+{
+    qxl_surface_t *surface = get_surface (pDst);
+    
+    if (surface)
+	return qxl_surface_put_image (surface, x, y, w, h, src, src_pitch);
+    
+    return FALSE;
+}
+
+static void
+qxl_set_screen_pixmap (PixmapPtr pixmap)
+{
+    pixmap->drawable.pScreen->devPrivate = pixmap;
+}
+
+static PixmapPtr
+qxl_create_pixmap (ScreenPtr screen, int w, int h, int depth, unsigned usage)
+{
+    ScrnInfoPtr    scrn = xf86ScreenToScrn (screen);
+    PixmapPtr      pixmap;
+    qxl_screen_t * qxl = scrn->driverPrivate;
+    qxl_surface_t *surface;
+    
+    if (w > 32767 || h > 32767)
+	return NULL;
+    
+    qxl_surface_cache_sanity_check (qxl->surface_cache);
+    
+#if 0
+    ErrorF ("Create pixmap: %d %d @ %d (usage: %d)\n", w, h, depth, usage);
+#endif
+    
+    if (uxa_swapped_out (screen))
+	goto fallback;
+
+    if (depth == 8 && !qxl_has_a8_surfaces (qxl))
+    {
+	/* FIXME: When we detect a _change_ in the property of having a8
+	 * surfaces, we should copy all existing a8 surface to host memory
+	 * and then destroy the ones on the device.
+	 */
+	goto fallback;
+    }
+    
+    surface = qxl_surface_create (qxl->surface_cache, w, h, depth);
+    
+    if (surface)
+    {
+	/* ErrorF ("   Successfully created surface in video memory\n"); */
+	
+	pixmap = fbCreatePixmap (screen, 0, 0, depth, usage);
+	
+	screen->ModifyPixmapHeader (pixmap, w, h,
+	                            -1, -1, -1,
+	                            NULL);
+	
+#if 0
+	ErrorF ("Create pixmap %p with surface %p\n", pixmap, surface);
+#endif
+	set_surface (pixmap, surface);
+	qxl_surface_set_pixmap (surface, pixmap);
+	
+	qxl_surface_cache_sanity_check (qxl->surface_cache);
+    }
+    else
+    {
+#if 0
+	ErrorF ("   Couldn't allocate %d x %d @ %d surface in video memory\n",
+	        w, h, depth);
+#endif
+    fallback:
+	pixmap = fbCreatePixmap (screen, w, h, depth, usage);
+	
+#if 0
+	ErrorF ("Create pixmap %p without surface\n", pixmap);
+#endif
+    }
+    
+    return pixmap;
+}
+
+static Bool
+qxl_destroy_pixmap (PixmapPtr pixmap)
+{
+    ScreenPtr      screen = pixmap->drawable.pScreen;
+    ScrnInfoPtr    scrn = xf86ScreenToScrn (screen);
+    qxl_screen_t * qxl = scrn->driverPrivate;
+    qxl_surface_t *surface = NULL;
+    
+    qxl_surface_cache_sanity_check (qxl->surface_cache);
+    
+    if (pixmap->refcnt == 1)
+    {
+	surface = get_surface (pixmap);
+	
+#if 0
+	ErrorF ("- Destroy %p (had surface %p)\n", pixmap, surface);
+#endif
+	
+	if (surface)
+	{
+	    qxl_surface_kill (surface);
+	    set_surface (pixmap, NULL);
+	    
+	    qxl_surface_cache_sanity_check (qxl->surface_cache);
+	}
+    }
+    
+    fbDestroyPixmap (pixmap);
+    return TRUE;
+}
+
+Bool
+qxl_uxa_init (qxl_screen_t *qxl, ScreenPtr screen)
+{
+    ScrnInfoPtr scrn = xf86ScreenToScrn (screen);
+    
+#if HAS_DIXREGISTERPRIVATEKEY
+    if (!dixRegisterPrivateKey (&uxa_pixmap_index, PRIVATE_PIXMAP, 0))
+	return FALSE;
+#else
+    if (!dixRequestPrivate (&uxa_pixmap_index, 0))
+	return FALSE;
+#endif
+    
+    qxl->uxa = uxa_driver_alloc ();
+    if (qxl->uxa == NULL)
+	return FALSE;
+    
+    memset (qxl->uxa, 0, sizeof (*qxl->uxa));
+    
+    qxl->uxa->uxa_major = 1;
+    qxl->uxa->uxa_minor = 0;
+    
+    /* Solid fill */
+    qxl->uxa->check_solid = qxl_check_solid;
+    qxl->uxa->prepare_solid = qxl_prepare_solid;
+    qxl->uxa->solid = qxl_solid;
+    qxl->uxa->done_solid = qxl_done_solid;
+    
+    /* Copy */
+    qxl->uxa->check_copy = qxl_check_copy;
+    qxl->uxa->prepare_copy = qxl_prepare_copy;
+    qxl->uxa->copy = qxl_copy;
+    qxl->uxa->done_copy = qxl_done_copy;
+    
+    /* Composite */
+    qxl->uxa->check_composite = qxl_check_composite;
+    qxl->uxa->check_composite_target = qxl_check_composite_target;
+    qxl->uxa->check_composite_texture = qxl_check_composite_texture;
+    qxl->uxa->prepare_composite = qxl_prepare_composite;
+    qxl->uxa->composite = qxl_composite;
+    qxl->uxa->done_composite = qxl_done_composite;
+    
+    /* PutImage */
+    qxl->uxa->put_image = qxl_put_image;
+    
+    /* Prepare access */
+    qxl->uxa->prepare_access = qxl_prepare_access;
+    qxl->uxa->finish_access = qxl_finish_access;
+    
+    qxl->uxa->pixmap_is_offscreen = qxl_pixmap_is_offscreen;
+    
+    screen->SetScreenPixmap = qxl_set_screen_pixmap;
+    screen->CreatePixmap = qxl_create_pixmap;
+    screen->DestroyPixmap = qxl_destroy_pixmap;
+    
+    if (!uxa_driver_init (screen, qxl->uxa))
+    {
+	xf86DrvMsg (scrn->scrnIndex, X_ERROR,
+	            "UXA initialization failed\n");
+	free (qxl->uxa);
+	return FALSE;
+    }
+    
+#if 0
+    uxa_set_fallback_debug (screen, FALSE);
+#endif
+    
+#if 0
+    if (!uxa_driver_init (screen, qxl->uxa))
+	return FALSE;
+#endif
+    
+    return TRUE;
+}
-- 
1.8.1.2



More information about the Spice-devel mailing list