1d514b0f3Smrg/*
2d514b0f3Smrg * Copyright 2008 Red Hat, Inc.
3d514b0f3Smrg *
4d514b0f3Smrg * Permission is hereby granted, free of charge, to any person obtaining a
5d514b0f3Smrg * copy of this software and associated documentation files (the "Software"),
6d514b0f3Smrg * to deal in the Software without restriction, including without limitation
7d514b0f3Smrg * on the rights to use, copy, modify, merge, publish, distribute, sub
8d514b0f3Smrg * license, and/or sell copies of the Software, and to permit persons to whom
9d514b0f3Smrg * the Software is furnished to do so, subject to the following conditions:
10d514b0f3Smrg *
11d514b0f3Smrg * The above copyright notice and this permission notice (including the next
12d514b0f3Smrg * paragraph) shall be included in all copies or substantial portions of the
13d514b0f3Smrg * Software.
14d514b0f3Smrg *
15d514b0f3Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16d514b0f3Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17d514b0f3Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.  IN NO EVENT SHALL
18d514b0f3Smrg * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19d514b0f3Smrg * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20d514b0f3Smrg * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21d514b0f3Smrg */
22d514b0f3Smrg
23d514b0f3Smrg/** \file qxl_driver.c
24d514b0f3Smrg * \author Adam Jackson <ajax@redhat.com>
25d514b0f3Smrg * \author Søren Sandmann <sandmann@redhat.com>
26d514b0f3Smrg *
27d514b0f3Smrg * This is qxl, a driver for the Qumranet paravirtualized graphics device
28d514b0f3Smrg * in qemu.
29d514b0f3Smrg */
30d514b0f3Smrg
31d514b0f3Smrg
32d514b0f3Smrg#ifdef HAVE_CONFIG_H
33d514b0f3Smrg#include "config.h"
34d514b0f3Smrg#endif
35d514b0f3Smrg
36d514b0f3Smrg#include "qxl.h"
37d514b0f3Smrg#include "dfps.h"
38d514b0f3Smrg#include <spice/protocol.h>
39d514b0f3Smrg
40d514b0f3Smrg#if HAS_DEVPRIVATEKEYREC
41d514b0f3SmrgDevPrivateKeyRec uxa_pixmap_index;
42d514b0f3Smrg#else
43d514b0f3Smrgint uxa_pixmap_index;
44d514b0f3Smrg#endif
45d514b0f3Smrg
46d514b0f3Smrgstatic Bool
47d514b0f3Smrgqxl_prepare_access (PixmapPtr pixmap, RegionPtr region, uxa_access_t access)
48d514b0f3Smrg{
49d514b0f3Smrg    return qxl_surface_prepare_access (get_surface (pixmap),
50d514b0f3Smrg                                       pixmap, region, access);
51d514b0f3Smrg}
52d514b0f3Smrg
53d514b0f3Smrgstatic void
54d514b0f3Smrgqxl_finish_access (PixmapPtr pixmap)
55d514b0f3Smrg{
56d514b0f3Smrg    qxl_surface_finish_access (get_surface (pixmap), pixmap);
57d514b0f3Smrg}
58d514b0f3Smrg
59d514b0f3Smrgstatic Bool
60d514b0f3Smrgqxl_pixmap_is_offscreen (PixmapPtr pixmap)
61d514b0f3Smrg{
62d514b0f3Smrg    return !!get_surface (pixmap);
63d514b0f3Smrg}
64d514b0f3Smrg
65d514b0f3Smrgstatic Bool
66d514b0f3Smrggood_alu_and_pm (DrawablePtr drawable, int alu, Pixel planemask)
67d514b0f3Smrg{
68d514b0f3Smrg    if (!UXA_PM_IS_SOLID (drawable, planemask))
69d514b0f3Smrg	return FALSE;
70d514b0f3Smrg
71d514b0f3Smrg    if (alu != GXcopy)
72d514b0f3Smrg	return FALSE;
73d514b0f3Smrg
74d514b0f3Smrg    return TRUE;
75d514b0f3Smrg}
76d514b0f3Smrg
77d514b0f3Smrg/*
78d514b0f3Smrg * Solid fill
79d514b0f3Smrg */
80d514b0f3Smrgstatic Bool
81d514b0f3Smrgqxl_check_solid (DrawablePtr drawable, int alu, Pixel planemask)
82d514b0f3Smrg{
83d514b0f3Smrg    if (!good_alu_and_pm (drawable, alu, planemask))
84d514b0f3Smrg	return FALSE;
85d514b0f3Smrg
86d514b0f3Smrg    return TRUE;
87d514b0f3Smrg}
88d514b0f3Smrg
89d514b0f3Smrgstatic Bool
90d514b0f3Smrgqxl_prepare_solid (PixmapPtr pixmap, int alu, Pixel planemask, Pixel fg)
91d514b0f3Smrg{
92d514b0f3Smrg    qxl_surface_t *surface;
93d514b0f3Smrg
94d514b0f3Smrg    if (!(surface = get_surface (pixmap)))
95d514b0f3Smrg	return FALSE;
96d514b0f3Smrg
97d514b0f3Smrg    return qxl_surface_prepare_solid (surface, fg);
98d514b0f3Smrg}
99d514b0f3Smrg
100d514b0f3Smrgstatic void
101d514b0f3Smrgqxl_solid (PixmapPtr pixmap, int x1, int y1, int x2, int y2)
102d514b0f3Smrg{
103d514b0f3Smrg    qxl_surface_solid (get_surface (pixmap), x1, y1, x2, y2);
104d514b0f3Smrg}
105d514b0f3Smrg
106d514b0f3Smrgstatic void
107d514b0f3Smrgqxl_done_solid (PixmapPtr pixmap)
108d514b0f3Smrg{
109d514b0f3Smrg}
110d514b0f3Smrg
111d514b0f3Smrg/*
112d514b0f3Smrg * Copy
113d514b0f3Smrg */
114d514b0f3Smrgstatic Bool
115d514b0f3Smrgqxl_check_copy (PixmapPtr source, PixmapPtr dest,
116d514b0f3Smrg                int alu, Pixel planemask)
117d514b0f3Smrg{
118d514b0f3Smrg    if (!good_alu_and_pm ((DrawablePtr)source, alu, planemask))
119d514b0f3Smrg	return FALSE;
120d514b0f3Smrg
121d514b0f3Smrg    if (source->drawable.bitsPerPixel != dest->drawable.bitsPerPixel)
122d514b0f3Smrg    {
123d514b0f3Smrg	ErrorF ("differing bitsperpixel - this shouldn't happen\n");
124d514b0f3Smrg	return FALSE;
125d514b0f3Smrg    }
126d514b0f3Smrg
127d514b0f3Smrg    return TRUE;
128d514b0f3Smrg}
129d514b0f3Smrg
130d514b0f3Smrgstatic Bool
131d514b0f3Smrgqxl_prepare_copy (PixmapPtr source, PixmapPtr dest,
132d514b0f3Smrg                  int xdir, int ydir, int alu,
133d514b0f3Smrg                  Pixel planemask)
134d514b0f3Smrg{
135d514b0f3Smrg    return qxl_surface_prepare_copy (get_surface (dest), get_surface (source));
136d514b0f3Smrg}
137d514b0f3Smrg
138d514b0f3Smrgstatic void
139d514b0f3Smrgqxl_copy (PixmapPtr dest,
140d514b0f3Smrg          int src_x1, int src_y1,
141d514b0f3Smrg          int dest_x1, int dest_y1,
142d514b0f3Smrg          int width, int height)
143d514b0f3Smrg{
144d514b0f3Smrg    qxl_surface_copy (get_surface (dest),
145d514b0f3Smrg                      src_x1, src_y1,
146d514b0f3Smrg                      dest_x1, dest_y1,
147d514b0f3Smrg                      width, height);
148d514b0f3Smrg}
149d514b0f3Smrg
150d514b0f3Smrgstatic void
151d514b0f3Smrgqxl_done_copy (PixmapPtr dest)
152d514b0f3Smrg{
153d514b0f3Smrg}
154d514b0f3Smrg
155d514b0f3Smrg/*
156d514b0f3Smrg * Composite
157d514b0f3Smrg */
158d514b0f3Smrgstatic Bool
159d514b0f3Smrgcan_accelerate_picture (qxl_screen_t *qxl, PicturePtr pict)
160d514b0f3Smrg{
161d514b0f3Smrg    if (!pict)
162d514b0f3Smrg	return TRUE;
163d514b0f3Smrg
164d514b0f3Smrg    if (pict->format != PICT_a8r8g8b8		&&
165d514b0f3Smrg	pict->format != PICT_x8r8g8b8		&&
166d514b0f3Smrg	pict->format != PICT_a8)
167d514b0f3Smrg    {
168d514b0f3Smrg        if (qxl->debug_render_fallbacks)
169d514b0f3Smrg        {
170d514b0f3Smrg            ErrorF ("Image with format %x can't be accelerated \n",
171d514b0f3Smrg                    pict->format);
172d514b0f3Smrg        }
173d514b0f3Smrg
174d514b0f3Smrg        return FALSE;
175d514b0f3Smrg    }
176d514b0f3Smrg
177d514b0f3Smrg    if (!pict->pDrawable)
178d514b0f3Smrg    {
179d514b0f3Smrg        if (qxl->debug_render_fallbacks)
180d514b0f3Smrg        {
181d514b0f3Smrg            ErrorF ("Source image (of type %d) can't be accelerated\n",
182d514b0f3Smrg                    pict->pSourcePict->type);
183d514b0f3Smrg        }
184d514b0f3Smrg
185d514b0f3Smrg	return FALSE;
186d514b0f3Smrg    }
187d514b0f3Smrg
188d514b0f3Smrg    if (pict->transform)
189d514b0f3Smrg    {
190d514b0f3Smrg	if (pict->transform->matrix[2][0] != 0	||
191d514b0f3Smrg	    pict->transform->matrix[2][1] != 0	||
192d514b0f3Smrg	    pict->transform->matrix[2][2] != pixman_int_to_fixed (1))
193d514b0f3Smrg	{
194d514b0f3Smrg            if (qxl->debug_render_fallbacks)
195d514b0f3Smrg                ErrorF ("Image with non-affine transform can't be accelerated\n");
196d514b0f3Smrg
197d514b0f3Smrg	    return FALSE;
198d514b0f3Smrg	}
199d514b0f3Smrg    }
200d514b0f3Smrg
201d514b0f3Smrg    if (pict->filter != PictFilterBilinear	&&
202d514b0f3Smrg	pict->filter != PictFilterNearest)
203d514b0f3Smrg    {
204d514b0f3Smrg        if (qxl->debug_render_fallbacks)
205d514b0f3Smrg        {
206d514b0f3Smrg            ErrorF ("Image with filter type %d can't be accelerated\n",
207d514b0f3Smrg                    pict->filter);
208d514b0f3Smrg        }
209d514b0f3Smrg
210d514b0f3Smrg        return FALSE;
211d514b0f3Smrg    }
212d514b0f3Smrg
213d514b0f3Smrg    return TRUE;
214d514b0f3Smrg}
215d514b0f3Smrg
216d514b0f3Smrg#define QXL_HAS_CAP(qxl, cap)						\
217d514b0f3Smrg    (((qxl)->rom->client_capabilities[(cap) / 8]) & (1 << ((cap) % 8)))
218d514b0f3Smrg
219d514b0f3Smrgstatic Bool
220d514b0f3Smrgqxl_has_composite (qxl_screen_t *qxl)
221d514b0f3Smrg{
222d514b0f3Smrg#ifdef XF86DRM_MODE
223d514b0f3Smrg    if (qxl->kms_enabled) {
224d514b0f3Smrg#if 0 /* KMS Composite support seems broken - needs better hw support */
225d514b0f3Smrg	static Bool result, checked;
226d514b0f3Smrg	if (!checked) {
227d514b0f3Smrg	    result = qxl_kms_check_cap(qxl, SPICE_DISPLAY_CAP_COMPOSITE);
228d514b0f3Smrg	    checked = TRUE;
229d514b0f3Smrg	}
230d514b0f3Smrg	return result;
231d514b0f3Smrg#else
232d514b0f3Smrg	return FALSE;
233d514b0f3Smrg#endif
234d514b0f3Smrg    }
235d514b0f3Smrg#endif
236d514b0f3Smrg#ifndef XSPICE
237d514b0f3Smrg    return
238d514b0f3Smrg	qxl->pci->revision >= 4			&&
239d514b0f3Smrg	QXL_HAS_CAP (qxl, SPICE_DISPLAY_CAP_COMPOSITE);
240d514b0f3Smrg#else
241d514b0f3Smrg    /* FIXME */
242d514b0f3Smrg    return FALSE;
243d514b0f3Smrg#endif
244d514b0f3Smrg}
245d514b0f3Smrg
246d514b0f3Smrgstatic Bool
247d514b0f3Smrgqxl_has_a8_surfaces (qxl_screen_t *qxl)
248d514b0f3Smrg{
249d514b0f3Smrg#ifdef XF86DRM_MODE
250d514b0f3Smrg    if (qxl->kms_enabled) {
251d514b0f3Smrg#if 0 /* KMS Composite support seems broken - needs better hw support */
252d514b0f3Smrg        static Bool result, checked;
253d514b0f3Smrg	if (!checked) {
254d514b0f3Smrg            result = qxl_kms_check_cap(qxl, SPICE_DISPLAY_CAP_A8_SURFACE);
255d514b0f3Smrg	    checked = TRUE;
256d514b0f3Smrg	}
257d514b0f3Smrg	return result;
258d514b0f3Smrg#else
259d514b0f3Smrg	return FALSE;
260d514b0f3Smrg#endif
261d514b0f3Smrg    }
262d514b0f3Smrg#endif
263d514b0f3Smrg#ifndef XSPICE
264d514b0f3Smrg    if (qxl->pci->revision < 4)
265d514b0f3Smrg    {
266d514b0f3Smrg        if (qxl->debug_render_fallbacks)
267d514b0f3Smrg        {
268d514b0f3Smrg            ErrorF ("No a8 surface due to revision being %d, which is < 4\n",
269d514b0f3Smrg                    qxl->pci->revision);
270d514b0f3Smrg        }
271d514b0f3Smrg
272d514b0f3Smrg        return FALSE;
273d514b0f3Smrg    }
274d514b0f3Smrg
275d514b0f3Smrg    if (!QXL_HAS_CAP (qxl, SPICE_DISPLAY_CAP_COMPOSITE))
276d514b0f3Smrg    {
277d514b0f3Smrg        if (qxl->debug_render_fallbacks)
278d514b0f3Smrg        {
279d514b0f3Smrg            ErrorF ("No composite due to client not providing SPICE_DISPLAY_CAP_A8_SURFACE\n");
280d514b0f3Smrg        }
281d514b0f3Smrg
282d514b0f3Smrg        return FALSE;
283d514b0f3Smrg    }
284d514b0f3Smrg
285d514b0f3Smrg    return TRUE;
286d514b0f3Smrg
287d514b0f3Smrg#else
288d514b0f3Smrg    /* FIXME */
289d514b0f3Smrg    return FALSE;
290d514b0f3Smrg#endif
291d514b0f3Smrg}
292d514b0f3Smrg
293d514b0f3Smrgstatic Bool
294d514b0f3Smrgqxl_check_composite (int op,
295d514b0f3Smrg		     PicturePtr pSrcPicture,
296d514b0f3Smrg		     PicturePtr pMaskPicture,
297d514b0f3Smrg		     PicturePtr pDstPicture,
298d514b0f3Smrg		     int width, int height)
299d514b0f3Smrg{
300d514b0f3Smrg    int i;
301d514b0f3Smrg    ScreenPtr pScreen = pDstPicture->pDrawable->pScreen;
302d514b0f3Smrg    ScrnInfoPtr pScrn = xf86ScreenToScrn (pScreen);
303d514b0f3Smrg    qxl_screen_t *qxl = pScrn->driverPrivate;
304d514b0f3Smrg
305d514b0f3Smrg    static const int accelerated_ops[] =
306d514b0f3Smrg    {
307d514b0f3Smrg	PictOpClear, PictOpSrc, PictOpDst, PictOpOver, PictOpOverReverse,
308d514b0f3Smrg	PictOpIn, PictOpInReverse, PictOpOut, PictOpOutReverse,
309d514b0f3Smrg	PictOpAtop, PictOpAtopReverse, PictOpXor, PictOpAdd,
310d514b0f3Smrg	PictOpSaturate, PictOpMultiply, PictOpScreen, PictOpOverlay,
311d514b0f3Smrg	PictOpDarken, PictOpLighten, PictOpColorDodge, PictOpColorBurn,
312d514b0f3Smrg	PictOpHardLight, PictOpSoftLight, PictOpDifference, PictOpExclusion,
313d514b0f3Smrg	PictOpHSLHue, PictOpHSLSaturation, PictOpHSLColor, PictOpHSLLuminosity,
314d514b0f3Smrg    };
315d514b0f3Smrg
316d514b0f3Smrg    if (!qxl_has_composite (qxl))
317d514b0f3Smrg	return FALSE;
318d514b0f3Smrg
319d514b0f3Smrg    if (!can_accelerate_picture (qxl, pSrcPicture)	||
320d514b0f3Smrg	!can_accelerate_picture (qxl, pMaskPicture)	||
321d514b0f3Smrg	!can_accelerate_picture (qxl, pDstPicture))
322d514b0f3Smrg    {
323d514b0f3Smrg	return FALSE;
324d514b0f3Smrg    }
325d514b0f3Smrg
326d514b0f3Smrg    for (i = 0; i < sizeof (accelerated_ops) / sizeof (accelerated_ops[0]); ++i)
327d514b0f3Smrg    {
328d514b0f3Smrg	if (accelerated_ops[i] == op)
329d514b0f3Smrg	    goto found;
330d514b0f3Smrg    }
331d514b0f3Smrg
332d514b0f3Smrg    if (qxl->debug_render_fallbacks)
333d514b0f3Smrg        ErrorF ("Compositing operator %d can't be accelerated\n", op);
334d514b0f3Smrg
335d514b0f3Smrg    return FALSE;
336d514b0f3Smrg
337d514b0f3Smrgfound:
338d514b0f3Smrg    return TRUE;
339d514b0f3Smrg}
340d514b0f3Smrg
341d514b0f3Smrgstatic Bool
342d514b0f3Smrgqxl_check_composite_target (PixmapPtr pixmap)
343d514b0f3Smrg{
344d514b0f3Smrg    return TRUE;
345d514b0f3Smrg}
346d514b0f3Smrg
347d514b0f3Smrgstatic Bool
348d514b0f3Smrgqxl_check_composite_texture (ScreenPtr screen,
349d514b0f3Smrg			     PicturePtr pPicture)
350d514b0f3Smrg{
351d514b0f3Smrg    return TRUE;
352d514b0f3Smrg}
353d514b0f3Smrg
354d514b0f3Smrgstatic Bool
355d514b0f3Smrgqxl_prepare_composite (int op,
356d514b0f3Smrg		       PicturePtr pSrcPicture,
357d514b0f3Smrg		       PicturePtr pMaskPicture,
358d514b0f3Smrg		       PicturePtr pDstPicture,
359d514b0f3Smrg		       PixmapPtr pSrc,
360d514b0f3Smrg		       PixmapPtr pMask,
361d514b0f3Smrg		       PixmapPtr pDst)
362d514b0f3Smrg{
363d514b0f3Smrg    return qxl_surface_prepare_composite (
364d514b0f3Smrg	op, pSrcPicture, pMaskPicture, pDstPicture,
365d514b0f3Smrg	get_surface (pSrc),
366d514b0f3Smrg	pMask? get_surface (pMask) : NULL,
367d514b0f3Smrg	get_surface (pDst));
368d514b0f3Smrg}
369d514b0f3Smrg
370d514b0f3Smrgstatic void
371d514b0f3Smrgqxl_composite (PixmapPtr pDst,
372d514b0f3Smrg	       int src_x, int src_y,
373d514b0f3Smrg	       int mask_x, int mask_y,
374d514b0f3Smrg	       int dst_x, int dst_y,
375d514b0f3Smrg	       int width, int height)
376d514b0f3Smrg{
377d514b0f3Smrg    qxl_surface_composite (
378d514b0f3Smrg	get_surface (pDst),
379d514b0f3Smrg	src_x, src_y,
380d514b0f3Smrg	mask_x, mask_y,
381d514b0f3Smrg	dst_x, dst_y, width, height);
382d514b0f3Smrg}
383d514b0f3Smrg
384d514b0f3Smrgstatic void
385d514b0f3Smrgqxl_done_composite (PixmapPtr pDst)
386d514b0f3Smrg{
387d514b0f3Smrg    ;
388d514b0f3Smrg}
389d514b0f3Smrg
390d514b0f3Smrgstatic Bool
391d514b0f3Smrgqxl_put_image (PixmapPtr pDst, int x, int y, int w, int h,
392d514b0f3Smrg               char *src, int src_pitch)
393d514b0f3Smrg{
394d514b0f3Smrg    qxl_surface_t *surface = get_surface (pDst);
395d514b0f3Smrg
396d514b0f3Smrg    if (surface)
397d514b0f3Smrg	return qxl_surface_put_image (surface, x, y, w, h, src, src_pitch);
398d514b0f3Smrg
399d514b0f3Smrg    return FALSE;
400d514b0f3Smrg}
401d514b0f3Smrg
402d514b0f3Smrgstatic void
403d514b0f3Smrgqxl_set_screen_pixmap (PixmapPtr pixmap)
404d514b0f3Smrg{
405d514b0f3Smrg    pixmap->drawable.pScreen->devPrivate = pixmap;
406d514b0f3Smrg}
407d514b0f3Smrg
408d514b0f3Smrgstatic PixmapPtr
409d514b0f3Smrgqxl_create_pixmap (ScreenPtr screen, int w, int h, int depth, unsigned usage)
410d514b0f3Smrg{
411d514b0f3Smrg    ScrnInfoPtr    scrn = xf86ScreenToScrn (screen);
412d514b0f3Smrg    PixmapPtr      pixmap;
413d514b0f3Smrg    qxl_screen_t * qxl = scrn->driverPrivate;
414d514b0f3Smrg    qxl_surface_t *surface;
415d514b0f3Smrg
416d514b0f3Smrg    if (w > 32767 || h > 32767)
417d514b0f3Smrg	return NULL;
418d514b0f3Smrg
419d514b0f3Smrg    qxl_surface_cache_sanity_check (qxl->surface_cache);
420d514b0f3Smrg
421d514b0f3Smrg#if 0
422d514b0f3Smrg    ErrorF ("Create pixmap: %d %d @ %d (usage: %d)\n", w, h, depth, usage);
423d514b0f3Smrg#endif
424d514b0f3Smrg
425d514b0f3Smrg    if (qxl->kms_enabled)
426d514b0f3Smrg	goto fallback;
427d514b0f3Smrg    if (uxa_swapped_out (screen))
428d514b0f3Smrg	goto fallback;
429d514b0f3Smrg
430d514b0f3Smrg    if (depth == 8 && !qxl_has_a8_surfaces (qxl))
431d514b0f3Smrg    {
432d514b0f3Smrg	/* FIXME: When we detect a _change_ in the property of having a8
433d514b0f3Smrg	 * surfaces, we should copy all existing a8 surface to host memory
434d514b0f3Smrg	 * and then destroy the ones on the device.
435d514b0f3Smrg	 */
436d514b0f3Smrg	goto fallback;
437d514b0f3Smrg    }
438d514b0f3Smrg
439d514b0f3Smrg    if (!w || !h)
440d514b0f3Smrg      goto fallback;
441d514b0f3Smrg
442d514b0f3Smrg    surface = qxl->bo_funcs->create_surface (qxl, w, h, depth);
443d514b0f3Smrg    if (surface)
444d514b0f3Smrg    {
445d514b0f3Smrg	/* ErrorF ("   Successfully created surface in video memory\n"); */
446d514b0f3Smrg
447d514b0f3Smrg	pixmap = fbCreatePixmap (screen, 0, 0, depth, usage);
448d514b0f3Smrg
449d514b0f3Smrg	screen->ModifyPixmapHeader (pixmap, w, h,
450d514b0f3Smrg	                            -1, -1, -1,
451d514b0f3Smrg	                            NULL);
452d514b0f3Smrg
453d514b0f3Smrg#if 0
454d514b0f3Smrg	ErrorF ("Create pixmap %p with surface %p\n", pixmap, surface);
455d514b0f3Smrg#endif
456d514b0f3Smrg	set_surface (pixmap, surface);
457d514b0f3Smrg	qxl_surface_set_pixmap (surface, pixmap);
458d514b0f3Smrg
459d514b0f3Smrg	qxl_surface_cache_sanity_check (qxl->surface_cache);
460d514b0f3Smrg    }
461d514b0f3Smrg    else
462d514b0f3Smrg    {
463d514b0f3Smrg#if 0
464d514b0f3Smrg	ErrorF ("   Couldn't allocate %d x %d @ %d surface in video memory\n",
465d514b0f3Smrg	        w, h, depth);
466d514b0f3Smrg#endif
467d514b0f3Smrg    fallback:
468d514b0f3Smrg	pixmap = fbCreatePixmap (screen, w, h, depth, usage);
469d514b0f3Smrg
470d514b0f3Smrg#if 0
471d514b0f3Smrg	ErrorF ("Create pixmap %p without surface\n", pixmap);
472d514b0f3Smrg#endif
473d514b0f3Smrg    }
474d514b0f3Smrg
475d514b0f3Smrg    return pixmap;
476d514b0f3Smrg}
477d514b0f3Smrg
478d514b0f3Smrgstatic Bool
479d514b0f3Smrgqxl_destroy_pixmap (PixmapPtr pixmap)
480d514b0f3Smrg{
481d514b0f3Smrg    ScreenPtr      screen = pixmap->drawable.pScreen;
482d514b0f3Smrg    ScrnInfoPtr    scrn = xf86ScreenToScrn (screen);
483d514b0f3Smrg    qxl_screen_t * qxl = scrn->driverPrivate;
484d514b0f3Smrg    qxl_surface_t *surface = NULL;
485d514b0f3Smrg
486d514b0f3Smrg    qxl_surface_cache_sanity_check (qxl->surface_cache);
487d514b0f3Smrg
488d514b0f3Smrg    if (pixmap->refcnt == 1)
489d514b0f3Smrg    {
490d514b0f3Smrg	surface = get_surface (pixmap);
491d514b0f3Smrg
492d514b0f3Smrg#if 0
493d514b0f3Smrg	ErrorF ("- Destroy %p (had surface %p)\n", pixmap, surface);
494d514b0f3Smrg#endif
495d514b0f3Smrg
496d514b0f3Smrg	if (surface)
497d514b0f3Smrg	{
498d514b0f3Smrg	    qxl->bo_funcs->destroy_surface(surface);
499d514b0f3Smrg	    set_surface (pixmap, NULL);
500d514b0f3Smrg
501d514b0f3Smrg	    qxl_surface_cache_sanity_check (qxl->surface_cache);
502d514b0f3Smrg	}
503d514b0f3Smrg    }
504d514b0f3Smrg
505d514b0f3Smrg    fbDestroyPixmap (pixmap);
506d514b0f3Smrg    return TRUE;
507d514b0f3Smrg}
508d514b0f3Smrg
509d514b0f3Smrgstatic void
510d514b0f3Smrgset_uxa_functions(qxl_screen_t *qxl, ScreenPtr screen)
511d514b0f3Smrg{
512d514b0f3Smrg    /* Solid fill */
513d514b0f3Smrg    qxl->uxa->check_solid = qxl_check_solid;
514d514b0f3Smrg    qxl->uxa->prepare_solid = qxl_prepare_solid;
515d514b0f3Smrg    qxl->uxa->solid = qxl_solid;
516d514b0f3Smrg    qxl->uxa->done_solid = qxl_done_solid;
517d514b0f3Smrg
518d514b0f3Smrg    /* Copy */
519d514b0f3Smrg    qxl->uxa->check_copy = qxl_check_copy;
520d514b0f3Smrg    qxl->uxa->prepare_copy = qxl_prepare_copy;
521d514b0f3Smrg    qxl->uxa->copy = qxl_copy;
522d514b0f3Smrg    qxl->uxa->done_copy = qxl_done_copy;
523d514b0f3Smrg
524d514b0f3Smrg    /* Composite */
525d514b0f3Smrg    qxl->uxa->check_composite = qxl_check_composite;
526d514b0f3Smrg    qxl->uxa->check_composite_target = qxl_check_composite_target;
527d514b0f3Smrg    qxl->uxa->check_composite_texture = qxl_check_composite_texture;
528d514b0f3Smrg    qxl->uxa->prepare_composite = qxl_prepare_composite;
529d514b0f3Smrg    qxl->uxa->composite = qxl_composite;
530d514b0f3Smrg    qxl->uxa->done_composite = qxl_done_composite;
531d514b0f3Smrg
532d514b0f3Smrg    /* PutImage */
533d514b0f3Smrg    qxl->uxa->put_image = qxl_put_image;
534d514b0f3Smrg
535d514b0f3Smrg    /* Prepare access */
536d514b0f3Smrg    qxl->uxa->prepare_access = qxl_prepare_access;
537d514b0f3Smrg    qxl->uxa->finish_access = qxl_finish_access;
538d514b0f3Smrg
539d514b0f3Smrg    qxl->uxa->pixmap_is_offscreen = qxl_pixmap_is_offscreen;
540d514b0f3Smrg
541d514b0f3Smrg    screen->SetScreenPixmap = qxl_set_screen_pixmap;
542d514b0f3Smrg    screen->CreatePixmap = qxl_create_pixmap;
543d514b0f3Smrg    screen->DestroyPixmap = qxl_destroy_pixmap;
544d514b0f3Smrg}
545d514b0f3Smrg
546d514b0f3SmrgBool
547d514b0f3Smrgqxl_uxa_init (qxl_screen_t *qxl, ScreenPtr screen)
548d514b0f3Smrg{
549d514b0f3Smrg    ScrnInfoPtr scrn = xf86ScreenToScrn (screen);
550d514b0f3Smrg
551d514b0f3Smrg#if HAS_DIXREGISTERPRIVATEKEY
552d514b0f3Smrg    if (!dixRegisterPrivateKey (&uxa_pixmap_index, PRIVATE_PIXMAP, 0))
553d514b0f3Smrg	return FALSE;
554d514b0f3Smrg#else
555d514b0f3Smrg    if (!dixRequestPrivate (&uxa_pixmap_index, 0))
556d514b0f3Smrg	return FALSE;
557d514b0f3Smrg#endif
558d514b0f3Smrg
559d514b0f3Smrg    qxl->uxa = uxa_driver_alloc ();
560d514b0f3Smrg    if (qxl->uxa == NULL)
561d514b0f3Smrg	return FALSE;
562d514b0f3Smrg
563d514b0f3Smrg    memset (qxl->uxa, 0, sizeof (*qxl->uxa));
564d514b0f3Smrg
565d514b0f3Smrg    qxl->uxa->uxa_major = 1;
566d514b0f3Smrg    qxl->uxa->uxa_minor = 0;
567d514b0f3Smrg
568d514b0f3Smrg    if (qxl->deferred_fps)
569d514b0f3Smrg        dfps_set_uxa_functions(qxl, screen);
570d514b0f3Smrg    else
571d514b0f3Smrg        set_uxa_functions(qxl, screen);
572d514b0f3Smrg
573d514b0f3Smrg    if (!uxa_driver_init (screen, qxl->uxa))
574d514b0f3Smrg    {
575d514b0f3Smrg	xf86DrvMsg (scrn->scrnIndex, X_ERROR,
576d514b0f3Smrg	            "UXA initialization failed\n");
577d514b0f3Smrg	free (qxl->uxa);
578d514b0f3Smrg	return FALSE;
579d514b0f3Smrg    }
580d514b0f3Smrg
581d514b0f3Smrg#if 0
582d514b0f3Smrg    uxa_set_fallback_debug (screen, FALSE);
583d514b0f3Smrg#endif
584d514b0f3Smrg
585d514b0f3Smrg#if 0
586d514b0f3Smrg    if (!uxa_driver_init (screen, qxl->uxa))
587d514b0f3Smrg	return FALSE;
588d514b0f3Smrg#endif
589d514b0f3Smrg
590d514b0f3Smrg    return TRUE;
591d514b0f3Smrg}
592