xorg_exa.c revision 3201c655e4c393d5ae794e6373de8ef705b979a4
1/*
2 * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
3 * All Rights Reserved.
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the
7 * "Software"), to deal in the Software without restriction, including
8 * without limitation the rights to use, copy, modify, merge, publish,
9 * distribute, sub license, and/or sell copies of the Software, and to
10 * permit persons to whom the Software is furnished to do so, subject to
11 * the following conditions:
12 *
13 * The above copyright notice and this permission notice (including the
14 * next paragraph) shall be included in all copies or substantial portions
15 * of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
20 * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
21 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
22 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
23 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 *
25 *
26 * Author: Alan Hourihane <alanh@tungstengraphics.com>
27 * Author: Jakob Bornecrantz <wallbraker@gmail.com>
28 *
29 */
30
31#include "xorg_exa.h"
32#include "xorg_tracker.h"
33#include "xorg_composite.h"
34#include "xorg_exa_tgsi.h"
35
36#include <xorg-server.h>
37#include <xf86.h>
38#include <picturestr.h>
39#include <picture.h>
40
41#include "pipe/p_format.h"
42#include "pipe/p_context.h"
43#include "pipe/p_state.h"
44#include "pipe/p_inlines.h"
45
46#include "util/u_rect.h"
47
48#define DEBUG_PRINT 0
49#define ACCEL_ENABLED TRUE
50
51/*
52 * Helper functions
53 */
54#if DEBUG_PRINT
55struct render_format_str {
56   int format;
57   const char *name;
58};
59static const struct render_format_str formats_info[] =
60{
61   {PICT_a2r10g10b10, "PICT_a2r10g10b10"},
62   {PICT_x2r10g10b10, "PICT_x2r10g10b10"},
63   {PICT_a2b10g10r10, "PICT_a2b10g10r10"},
64   {PICT_x2b10g10r10, "PICT_x2b10g10r10"},
65   {PICT_a8r8g8b8, "PICT_a8r8g8b8"},
66   {PICT_x8r8g8b8, "PICT_x8r8g8b8"},
67   {PICT_a8b8g8r8, "PICT_a8b8g8r8"},
68   {PICT_x8b8g8r8, "PICT_x8b8g8r8"},
69   {PICT_b8g8r8a8, "PICT_b8g8r8a8"},
70   {PICT_b8g8r8x8, "PICT_b8g8r8x8"},
71   {PICT_r8g8b8, "PICT_r8g8b8"},
72   {PICT_b8g8r8, "PICT_b8g8r8"},
73   {PICT_r5g6b5, "PICT_r5g6b5"},
74   {PICT_b5g6r5, "PICT_b5g6r5"},
75   {PICT_a1r5g5b5, "PICT_a1r5g5b5"},
76   {PICT_x1r5g5b5, "PICT_x1r5g5b5"},
77   {PICT_a1b5g5r5, "PICT_a1b5g5r5"},
78   {PICT_x1b5g5r5, "PICT_x1b5g5r5"},
79   {PICT_a4r4g4b4, "PICT_a4r4g4b4"},
80   {PICT_x4r4g4b4, "PICT_x4r4g4b4"},
81   {PICT_a4b4g4r4, "PICT_a4b4g4r4"},
82   {PICT_x4b4g4r4, "PICT_x4b4g4r4"},
83   {PICT_a8, "PICT_a8"},
84   {PICT_r3g3b2, "PICT_r3g3b2"},
85   {PICT_b2g3r3, "PICT_b2g3r3"},
86   {PICT_a2r2g2b2, "PICT_a2r2g2b2"},
87   {PICT_a2b2g2r2, "PICT_a2b2g2r2"},
88   {PICT_c8, "PICT_c8"},
89   {PICT_g8, "PICT_g8"},
90   {PICT_x4a4, "PICT_x4a4"},
91   {PICT_x4c4, "PICT_x4c4"},
92   {PICT_x4g4, "PICT_x4g4"},
93   {PICT_a4, "PICT_a4"},
94   {PICT_r1g2b1, "PICT_r1g2b1"},
95   {PICT_b1g2r1, "PICT_b1g2r1"},
96   {PICT_a1r1g1b1, "PICT_a1r1g1b1"},
97   {PICT_a1b1g1r1, "PICT_a1b1g1r1"},
98   {PICT_c4, "PICT_c4"},
99   {PICT_g4, "PICT_g4"},
100   {PICT_a1, "PICT_a1"},
101   {PICT_g1, "PICT_g1"}
102};
103static const char *render_format_name(int format)
104{
105   int i = 0;
106   for (i = 0; i < sizeof(formats_info)/sizeof(formats_info[0]); ++i) {
107      if (formats_info[i].format == format)
108         return formats_info[i].name;
109   }
110   return NULL;
111}
112#endif
113
114static void
115exa_get_pipe_format(int depth, enum pipe_format *format, int *bbp)
116{
117    switch (depth) {
118    case 32:
119	*format = PIPE_FORMAT_A8R8G8B8_UNORM;
120	assert(*bbp == 32);
121	break;
122    case 24:
123	*format = PIPE_FORMAT_X8R8G8B8_UNORM;
124	assert(*bbp == 32);
125	break;
126    case 16:
127	*format = PIPE_FORMAT_R5G6B5_UNORM;
128	assert(*bbp == 16);
129	break;
130    case 15:
131	*format = PIPE_FORMAT_A1R5G5B5_UNORM;
132	assert(*bbp == 16);
133	break;
134    case 8:
135	*format = PIPE_FORMAT_L8_UNORM;
136	assert(*bbp == 8);
137	break;
138    case 4:
139    case 1:
140	*format = PIPE_FORMAT_A8R8G8B8_UNORM; /* bad bad bad */
141	break;
142    default:
143	assert(0);
144	break;
145    }
146}
147
148static void
149xorg_exa_common_done(struct exa_context *exa)
150{
151   renderer_draw_flush(exa->renderer);
152
153   exa->copy.src = NULL;
154   exa->copy.dst = NULL;
155   exa->transform.has_src = FALSE;
156   exa->transform.has_mask = FALSE;
157   exa->has_solid_color = FALSE;
158   exa->num_bound_samplers = 0;
159}
160
161/*
162 * Static exported EXA functions
163 */
164
165static void
166ExaWaitMarker(ScreenPtr pScreen, int marker)
167{
168   ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
169   modesettingPtr ms = modesettingPTR(pScrn);
170   struct exa_context *exa = ms->exa;
171
172#if 0
173   xorg_exa_flush(exa, PIPE_FLUSH_RENDER_CACHE, NULL);
174#else
175   xorg_exa_finish(exa);
176#endif
177}
178
179static int
180ExaMarkSync(ScreenPtr pScreen)
181{
182   return 1;
183}
184
185static Bool
186ExaDownloadFromScreen(PixmapPtr pPix, int x,  int y, int w,  int h, char *dst,
187		      int dst_pitch)
188{
189    ScreenPtr pScreen = pPix->drawable.pScreen;
190    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
191    modesettingPtr ms = modesettingPTR(pScrn);
192    struct exa_context *exa = ms->exa;
193    struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pPix);
194    struct pipe_transfer *transfer;
195
196    if (!priv || !priv->tex)
197	return FALSE;
198
199    if (exa->pipe->is_texture_referenced(exa->pipe, priv->tex, 0, 0) &
200	PIPE_REFERENCED_FOR_WRITE)
201	exa->pipe->flush(exa->pipe, 0, NULL);
202
203    transfer = exa->scrn->get_tex_transfer(exa->scrn, priv->tex, 0, 0, 0,
204					   PIPE_TRANSFER_READ, x, y, w, h);
205    if (!transfer)
206	return FALSE;
207
208#if DEBUG_PRINT
209    debug_printf("------ ExaDownloadFromScreen(%d, %d, %d, %d, %d)\n",
210                 x, y, w, h, dst_pitch);
211#endif
212
213    util_copy_rect((unsigned char*)dst, &priv->tex->block, dst_pitch, 0, 0,
214		   w, h, exa->scrn->transfer_map(exa->scrn, transfer),
215		   transfer->stride, 0, 0);
216
217    exa->scrn->transfer_unmap(exa->scrn, transfer);
218    exa->scrn->tex_transfer_destroy(transfer);
219
220    return TRUE;
221}
222
223static Bool
224ExaUploadToScreen(PixmapPtr pPix, int x, int y, int w, int h, char *src,
225		  int src_pitch)
226{
227    ScreenPtr pScreen = pPix->drawable.pScreen;
228    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
229    modesettingPtr ms = modesettingPTR(pScrn);
230    struct exa_context *exa = ms->exa;
231    struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pPix);
232    struct pipe_transfer *transfer;
233
234    if (!priv || !priv->tex)
235	return FALSE;
236
237    transfer = exa->scrn->get_tex_transfer(exa->scrn, priv->tex, 0, 0, 0,
238					   PIPE_TRANSFER_WRITE, x, y, w, h);
239    if (!transfer)
240	return FALSE;
241
242#if DEBUG_PRINT
243    debug_printf("++++++ ExaUploadToScreen(%d, %d, %d, %d, %d)\n",
244                 x, y, w, h, src_pitch);
245#endif
246
247    util_copy_rect(exa->scrn->transfer_map(exa->scrn, transfer),
248		   &priv->tex->block, transfer->stride, 0, 0, w, h,
249		   (unsigned char*)src, src_pitch, 0, 0);
250
251    exa->scrn->transfer_unmap(exa->scrn, transfer);
252    exa->scrn->tex_transfer_destroy(transfer);
253
254    return TRUE;
255}
256
257static Bool
258ExaPrepareAccess(PixmapPtr pPix, int index)
259{
260    ScreenPtr pScreen = pPix->drawable.pScreen;
261    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
262    modesettingPtr ms = modesettingPTR(pScrn);
263    struct exa_context *exa = ms->exa;
264    struct exa_pixmap_priv *priv;
265
266    priv = exaGetPixmapDriverPrivate(pPix);
267
268    if (!priv)
269	return FALSE;
270
271    if (!priv->tex)
272	return FALSE;
273
274    if (priv->map_count == 0)
275    {
276	if (exa->pipe->is_texture_referenced(exa->pipe, priv->tex, 0, 0) &
277	    PIPE_REFERENCED_FOR_WRITE)
278	    exa->pipe->flush(exa->pipe, 0, NULL);
279
280	priv->map_transfer =
281	    exa->scrn->get_tex_transfer(exa->scrn, priv->tex, 0, 0, 0,
282#ifdef EXA_MIXED_PIXMAPS
283					PIPE_TRANSFER_MAP_DIRECTLY |
284#endif
285					PIPE_TRANSFER_READ_WRITE,
286					0, 0, priv->tex->width[0], priv->tex->height[0]);
287	if (!priv->map_transfer)
288#ifdef EXA_MIXED_PIXMAPS
289	    return FALSE;
290#else
291	    FatalError("failed to create transfer\n");
292#endif
293
294	pPix->devPrivate.ptr =
295	    exa->scrn->transfer_map(exa->scrn, priv->map_transfer);
296	pPix->devKind = priv->map_transfer->stride;
297    }
298
299    priv->map_count++;
300
301    return TRUE;
302}
303
304static void
305ExaFinishAccess(PixmapPtr pPix, int index)
306{
307    ScreenPtr pScreen = pPix->drawable.pScreen;
308    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
309    modesettingPtr ms = modesettingPTR(pScrn);
310    struct exa_context *exa = ms->exa;
311    struct exa_pixmap_priv *priv;
312    priv = exaGetPixmapDriverPrivate(pPix);
313
314    if (!priv)
315	return;
316
317    if (!priv->map_transfer)
318	return;
319
320    if (--priv->map_count == 0) {
321	assert(priv->map_transfer);
322	exa->scrn->transfer_unmap(exa->scrn, priv->map_transfer);
323	exa->scrn->tex_transfer_destroy(priv->map_transfer);
324	priv->map_transfer = NULL;
325	pPix->devPrivate.ptr = NULL;
326    }
327}
328
329static void
330ExaDone(PixmapPtr pPixmap)
331{
332    ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum];
333    modesettingPtr ms = modesettingPTR(pScrn);
334    struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pPixmap);
335    struct exa_context *exa = ms->exa;
336
337    if (!priv)
338	return;
339
340    xorg_exa_common_done(exa);
341}
342
343static void
344ExaDoneComposite(PixmapPtr pPixmap)
345{
346   ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum];
347   modesettingPtr ms = modesettingPTR(pScrn);
348   struct exa_context *exa = ms->exa;
349
350   xorg_exa_common_done(exa);
351}
352
353static Bool
354ExaPrepareSolid(PixmapPtr pPixmap, int alu, Pixel planeMask, Pixel fg)
355{
356    ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum];
357    modesettingPtr ms = modesettingPTR(pScrn);
358    struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pPixmap);
359    struct exa_context *exa = ms->exa;
360
361#if DEBUG_PRINT
362    debug_printf("ExaPrepareSolid(0x%x)\n", fg);
363#endif
364    if (!exa->pipe)
365	XORG_FALLBACK("accle not enabled");
366
367    if (!priv || !priv->tex)
368	XORG_FALLBACK("%s", !priv ? "!priv" : "!priv->tex");
369
370    if (!EXA_PM_IS_SOLID(&pPixmap->drawable, planeMask))
371	XORG_FALLBACK("planeMask is not solid");
372
373    if (alu != GXcopy)
374	XORG_FALLBACK("not GXcopy");
375
376    if (!exa->scrn->is_format_supported(exa->scrn, priv->tex->format,
377                                        priv->tex->target,
378                                        PIPE_TEXTURE_USAGE_RENDER_TARGET, 0)) {
379	XORG_FALLBACK("format %s", pf_name(priv->tex->format));
380    }
381
382    return ACCEL_ENABLED && xorg_solid_bind_state(exa, priv, fg);
383}
384
385static void
386ExaSolid(PixmapPtr pPixmap, int x0, int y0, int x1, int y1)
387{
388    ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum];
389    modesettingPtr ms = modesettingPTR(pScrn);
390    struct exa_context *exa = ms->exa;
391    struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pPixmap);
392
393#if DEBUG_PRINT
394    debug_printf("\tExaSolid(%d, %d, %d, %d)\n", x0, y0, x1, y1);
395#endif
396
397    xorg_solid(exa, priv, x0, y0, x1, y1) ;
398}
399
400static Bool
401ExaPrepareCopy(PixmapPtr pSrcPixmap, PixmapPtr pDstPixmap, int xdir,
402	       int ydir, int alu, Pixel planeMask)
403{
404    ScrnInfoPtr pScrn = xf86Screens[pDstPixmap->drawable.pScreen->myNum];
405    modesettingPtr ms = modesettingPTR(pScrn);
406    struct exa_context *exa = ms->exa;
407    struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pDstPixmap);
408    struct exa_pixmap_priv *src_priv = exaGetPixmapDriverPrivate(pSrcPixmap);
409
410#if DEBUG_PRINT
411    debug_printf("ExaPrepareCopy\n");
412#endif
413    if (!exa->pipe)
414	XORG_FALLBACK("accle not enabled");
415
416    if (!priv || !priv->tex)
417	XORG_FALLBACK("pDst %s", !priv ? "!priv" : "!priv->tex");
418
419    if (!src_priv || !src_priv->tex)
420	XORG_FALLBACK("pSrc %s", !src_priv ? "!priv" : "!priv->tex");
421
422    if (!EXA_PM_IS_SOLID(&pSrcPixmap->drawable, planeMask))
423	XORG_FALLBACK("planeMask is not solid");
424
425    if (alu != GXcopy)
426	XORG_FALLBACK("alu not GXcopy");
427
428    if (!exa->scrn->is_format_supported(exa->scrn, priv->tex->format,
429                                        priv->tex->target,
430                                        PIPE_TEXTURE_USAGE_RENDER_TARGET, 0))
431	XORG_FALLBACK("pDst format %s", pf_name(priv->tex->format));
432
433    if (!exa->scrn->is_format_supported(exa->scrn, src_priv->tex->format,
434                                        src_priv->tex->target,
435                                        PIPE_TEXTURE_USAGE_SAMPLER, 0))
436	XORG_FALLBACK("pSrc format %s", pf_name(src_priv->tex->format));
437
438    exa->copy.src = src_priv;
439    exa->copy.dst = priv;
440
441    return ACCEL_ENABLED;
442}
443
444static void
445ExaCopy(PixmapPtr pDstPixmap, int srcX, int srcY, int dstX, int dstY,
446	int width, int height)
447{
448   ScrnInfoPtr pScrn = xf86Screens[pDstPixmap->drawable.pScreen->myNum];
449   modesettingPtr ms = modesettingPTR(pScrn);
450   struct exa_context *exa = ms->exa;
451   struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pDstPixmap);
452
453#if DEBUG_PRINT
454   debug_printf("\tExaCopy(srcx=%d, srcy=%d, dstX=%d, dstY=%d, w=%d, h=%d)\n",
455                srcX, srcY, dstX, dstY, width, height);
456#endif
457
458   debug_assert(priv == exa->copy.dst);
459
460   renderer_copy_pixmap(exa->renderer, exa->copy.dst, dstX, dstY,
461                        exa->copy.src, srcX, srcY,
462                        width, height);
463}
464
465static Bool
466ExaPrepareComposite(int op, PicturePtr pSrcPicture,
467		    PicturePtr pMaskPicture, PicturePtr pDstPicture,
468		    PixmapPtr pSrc, PixmapPtr pMask, PixmapPtr pDst)
469{
470   ScrnInfoPtr pScrn = xf86Screens[pDst->drawable.pScreen->myNum];
471   modesettingPtr ms = modesettingPTR(pScrn);
472   struct exa_context *exa = ms->exa;
473   struct exa_pixmap_priv *priv;
474
475#if DEBUG_PRINT
476   debug_printf("ExaPrepareComposite(%d, src=0x%p, mask=0x%p, dst=0x%p)\n",
477                op, pSrcPicture, pMaskPicture, pDstPicture);
478   debug_printf("\tFormats: src(%s), mask(%s), dst(%s)\n",
479                pSrcPicture ? render_format_name(pSrcPicture->format) : "none",
480                pMaskPicture ? render_format_name(pMaskPicture->format) : "none",
481                pDstPicture ? render_format_name(pDstPicture->format) : "none");
482#endif
483   if (!exa->pipe)
484      XORG_FALLBACK("accle not enabled");
485
486   priv = exaGetPixmapDriverPrivate(pDst);
487   if (!priv || !priv->tex)
488      XORG_FALLBACK("pDst %s", !priv ? "!priv" : "!priv->tex");
489
490   if (!exa->scrn->is_format_supported(exa->scrn, priv->tex->format,
491                                       priv->tex->target,
492                                       PIPE_TEXTURE_USAGE_RENDER_TARGET, 0))
493      XORG_FALLBACK("pDst format: %s", pf_name(priv->tex->format));
494
495   if (pSrc) {
496      priv = exaGetPixmapDriverPrivate(pSrc);
497      if (!priv || !priv->tex)
498         XORG_FALLBACK("pSrc %s", !priv ? "!priv" : "!priv->tex");
499
500      if (!exa->scrn->is_format_supported(exa->scrn, priv->tex->format,
501                                          priv->tex->target,
502                                          PIPE_TEXTURE_USAGE_SAMPLER, 0))
503         XORG_FALLBACK("pSrc format: %s", pf_name(priv->tex->format));
504   }
505
506   if (pMask) {
507      priv = exaGetPixmapDriverPrivate(pMask);
508      if (!priv || !priv->tex)
509         XORG_FALLBACK("pMask %s", !priv ? "!priv" : "!priv->tex");
510
511      if (!exa->scrn->is_format_supported(exa->scrn, priv->tex->format,
512                                          priv->tex->target,
513                                          PIPE_TEXTURE_USAGE_SAMPLER, 0))
514         XORG_FALLBACK("pMask format: %s", pf_name(priv->tex->format));
515   }
516
517   return ACCEL_ENABLED &&
518          xorg_composite_bind_state(exa, op, pSrcPicture, pMaskPicture,
519                                    pDstPicture,
520                                    pSrc ? exaGetPixmapDriverPrivate(pSrc) : NULL,
521                                    pMask ? exaGetPixmapDriverPrivate(pMask) : NULL,
522                                    exaGetPixmapDriverPrivate(pDst));
523}
524
525static void
526ExaComposite(PixmapPtr pDst, int srcX, int srcY, int maskX, int maskY,
527	     int dstX, int dstY, int width, int height)
528{
529   ScrnInfoPtr pScrn = xf86Screens[pDst->drawable.pScreen->myNum];
530   modesettingPtr ms = modesettingPTR(pScrn);
531   struct exa_context *exa = ms->exa;
532   struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pDst);
533
534#if DEBUG_PRINT
535   debug_printf("\tExaComposite(src[%d,%d], mask=[%d, %d], dst=[%d, %d], dim=[%d, %d])\n",
536                srcX, srcY, maskX, maskY, dstX, dstY, width, height);
537   debug_printf("\t   Num bound samplers = %d\n",
538                exa->num_bound_samplers);
539#endif
540
541   xorg_composite(exa, priv, srcX, srcY, maskX, maskY,
542                  dstX, dstY, width, height);
543}
544
545static Bool
546ExaCheckComposite(int op,
547		  PicturePtr pSrcPicture, PicturePtr pMaskPicture,
548		  PicturePtr pDstPicture)
549{
550   boolean accelerated = xorg_composite_accelerated(op,
551                                                    pSrcPicture,
552                                                    pMaskPicture,
553                                                    pDstPicture);
554#if DEBUG_PRINT
555   debug_printf("ExaCheckComposite(%d, %p, %p, %p) = %d\n",
556                op, pSrcPicture, pMaskPicture, pDstPicture, accelerated);
557#endif
558   return ACCEL_ENABLED && accelerated;
559}
560
561static void *
562ExaCreatePixmap(ScreenPtr pScreen, int size, int align)
563{
564    struct exa_pixmap_priv *priv;
565
566    priv = xcalloc(1, sizeof(struct exa_pixmap_priv));
567    if (!priv)
568	return NULL;
569
570    return priv;
571}
572
573static void
574ExaDestroyPixmap(ScreenPtr pScreen, void *dPriv)
575{
576    struct exa_pixmap_priv *priv = (struct exa_pixmap_priv *)dPriv;
577
578    if (!priv)
579	return;
580
581    pipe_texture_reference(&priv->tex, NULL);
582
583    xfree(priv);
584}
585
586static Bool
587ExaPixmapIsOffscreen(PixmapPtr pPixmap)
588{
589    struct exa_pixmap_priv *priv;
590
591    priv = exaGetPixmapDriverPrivate(pPixmap);
592
593    if (!priv)
594	return FALSE;
595
596    if (priv->tex)
597	return TRUE;
598
599    return FALSE;
600}
601
602int
603xorg_exa_set_displayed_usage(PixmapPtr pPixmap)
604{
605    struct exa_pixmap_priv *priv;
606    priv = exaGetPixmapDriverPrivate(pPixmap);
607
608    if (!priv) {
609	FatalError("NO PIXMAP PRIVATE\n");
610	return 0;
611    }
612
613    priv->flags |= PIPE_TEXTURE_USAGE_PRIMARY;
614
615    return 0;
616}
617
618int
619xorg_exa_set_shared_usage(PixmapPtr pPixmap)
620{
621    struct exa_pixmap_priv *priv;
622    priv = exaGetPixmapDriverPrivate(pPixmap);
623
624    if (!priv) {
625	FatalError("NO PIXMAP PRIVATE\n");
626	return 0;
627    }
628
629    priv->flags |= PIPE_TEXTURE_USAGE_DISPLAY_TARGET;
630
631    return 0;
632}
633
634unsigned
635xorg_exa_get_pixmap_handle(PixmapPtr pPixmap, unsigned *stride_out)
636{
637    ScreenPtr pScreen = pPixmap->drawable.pScreen;
638    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
639    modesettingPtr ms = modesettingPTR(pScrn);
640    struct exa_pixmap_priv *priv;
641    unsigned handle;
642    unsigned stride;
643
644    if (!ms->exa) {
645	FatalError("NO MS->EXA\n");
646	return 0;
647    }
648
649    priv = exaGetPixmapDriverPrivate(pPixmap);
650
651    if (!priv) {
652	FatalError("NO PIXMAP PRIVATE\n");
653	return 0;
654    }
655
656    ms->api->local_handle_from_texture(ms->api, ms->screen, priv->tex, &stride, &handle);
657    if (stride_out)
658	*stride_out = stride;
659
660    return handle;
661}
662
663static Bool
664ExaModifyPixmapHeader(PixmapPtr pPixmap, int width, int height,
665		      int depth, int bitsPerPixel, int devKind,
666		      pointer pPixData)
667{
668    ScreenPtr pScreen = pPixmap->drawable.pScreen;
669    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
670    struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pPixmap);
671    modesettingPtr ms = modesettingPTR(pScrn);
672    struct exa_context *exa = ms->exa;
673
674    if (!priv || pPixData)
675	return FALSE;
676
677    if (depth <= 0)
678	depth = pPixmap->drawable.depth;
679
680    if (bitsPerPixel <= 0)
681	bitsPerPixel = pPixmap->drawable.bitsPerPixel;
682
683    if (width <= 0)
684	width = pPixmap->drawable.width;
685
686    if (height <= 0)
687	height = pPixmap->drawable.height;
688
689    if (width <= 0 || height <= 0 || depth <= 0)
690	return FALSE;
691
692    miModifyPixmapHeader(pPixmap, width, height, depth,
693			     bitsPerPixel, devKind, NULL);
694
695    /* Deal with screen resize */
696    if (!priv->tex ||
697        (priv->tex->width[0] != width ||
698         priv->tex->height[0] != height ||
699         priv->tex_flags != priv->flags)) {
700	struct pipe_texture *texture = NULL;
701	struct pipe_texture template;
702
703	memset(&template, 0, sizeof(template));
704	template.target = PIPE_TEXTURE_2D;
705	exa_get_pipe_format(depth, &template.format, &bitsPerPixel);
706	pf_get_block(template.format, &template.block);
707	template.width[0] = width;
708	template.height[0] = height;
709	template.depth[0] = 1;
710	template.last_level = 0;
711	template.tex_usage = PIPE_TEXTURE_USAGE_RENDER_TARGET | priv->flags;
712	priv->tex_flags = priv->flags;
713	texture = exa->scrn->texture_create(exa->scrn, &template);
714
715	if (priv->tex) {
716	    struct pipe_surface *dst_surf;
717	    struct pipe_surface *src_surf;
718
719	    dst_surf = exa->scrn->get_tex_surface(
720		exa->scrn, texture, 0, 0, 0, PIPE_BUFFER_USAGE_GPU_WRITE);
721	    src_surf = xorg_gpu_surface(exa->pipe->screen, priv);
722        if (exa->pipe->surface_copy) {
723            exa->pipe->surface_copy(exa->pipe, dst_surf, 0, 0, src_surf,
724                        0, 0, min(width, texture->width[0]),
725                        min(height, texture->height[0]));
726        } else {
727            util_surface_copy(exa->pipe, FALSE, dst_surf, 0, 0, src_surf,
728                        0, 0, min(width, texture->width[0]),
729                        min(height, texture->height[0]));
730        }
731	    exa->scrn->tex_surface_destroy(dst_surf);
732	    exa->scrn->tex_surface_destroy(src_surf);
733	}
734
735	pipe_texture_reference(&priv->tex, texture);
736	/* the texture we create has one reference */
737	pipe_texture_reference(&texture, NULL);
738    }
739
740    return TRUE;
741}
742
743struct pipe_texture *
744xorg_exa_get_texture(PixmapPtr pPixmap)
745{
746   struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pPixmap);
747   struct pipe_texture *tex = NULL;
748   pipe_texture_reference(&tex, priv->tex);
749   return tex;
750}
751
752Bool
753xorg_exa_set_texture(PixmapPtr pPixmap, struct  pipe_texture *tex)
754{
755    struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pPixmap);
756
757    int mask = PIPE_TEXTURE_USAGE_PRIMARY | PIPE_TEXTURE_USAGE_DISPLAY_TARGET;
758
759    if (!priv)
760	return FALSE;
761
762    if (pPixmap->drawable.width != tex->width[0] ||
763	pPixmap->drawable.height != tex->height[0])
764	return FALSE;
765
766    pipe_texture_reference(&priv->tex, tex);
767    priv->tex_flags = tex->tex_usage & mask;
768
769    return TRUE;
770}
771
772struct pipe_texture *
773xorg_exa_create_root_texture(ScrnInfoPtr pScrn,
774			     int width, int height,
775			     int depth, int bitsPerPixel)
776{
777    modesettingPtr ms = modesettingPTR(pScrn);
778    struct exa_context *exa = ms->exa;
779    struct pipe_texture template;
780
781    memset(&template, 0, sizeof(template));
782    template.target = PIPE_TEXTURE_2D;
783    exa_get_pipe_format(depth, &template.format, &bitsPerPixel);
784    pf_get_block(template.format, &template.block);
785    template.width[0] = width;
786    template.height[0] = height;
787    template.depth[0] = 1;
788    template.last_level = 0;
789    template.tex_usage |= PIPE_TEXTURE_USAGE_RENDER_TARGET;
790    template.tex_usage |= PIPE_TEXTURE_USAGE_PRIMARY;
791    template.tex_usage |= PIPE_TEXTURE_USAGE_DISPLAY_TARGET;
792
793    return exa->scrn->texture_create(exa->scrn, &template);
794}
795
796void
797xorg_exa_close(ScrnInfoPtr pScrn)
798{
799   modesettingPtr ms = modesettingPTR(pScrn);
800   struct exa_context *exa = ms->exa;
801
802   renderer_destroy(exa->renderer);
803
804   if (exa->pipe)
805      exa->pipe->destroy(exa->pipe);
806
807   exaDriverFini(pScrn->pScreen);
808   xfree(exa);
809   ms->exa = NULL;
810}
811
812void *
813xorg_exa_init(ScrnInfoPtr pScrn)
814{
815   modesettingPtr ms = modesettingPTR(pScrn);
816   struct exa_context *exa;
817   ExaDriverPtr pExa;
818
819   exa = xcalloc(1, sizeof(struct exa_context));
820   if (!exa)
821      return NULL;
822
823   pExa = exaDriverAlloc();
824   if (!pExa) {
825      goto out_err;
826   }
827
828   memset(pExa, 0, sizeof(*pExa));
829
830   pExa->exa_major         = 2;
831   pExa->exa_minor         = 2;
832   pExa->memoryBase        = 0;
833   pExa->memorySize        = 0;
834   pExa->offScreenBase     = 0;
835   pExa->pixmapOffsetAlign = 0;
836   pExa->pixmapPitchAlign  = 1;
837   pExa->flags             = EXA_OFFSCREEN_PIXMAPS | EXA_HANDLES_PIXMAPS;
838#ifdef EXA_SUPPORTS_PREPARE_AUX
839   pExa->flags            |= EXA_SUPPORTS_PREPARE_AUX;
840#endif
841#ifdef EXA_MIXED_PIXMAPS
842   pExa->flags            |= EXA_MIXED_PIXMAPS;
843#endif
844   pExa->maxX              = 8191; /* FIXME */
845   pExa->maxY              = 8191; /* FIXME */
846
847   pExa->WaitMarker         = ExaWaitMarker;
848   pExa->MarkSync           = ExaMarkSync;
849   pExa->PrepareSolid       = ExaPrepareSolid;
850   pExa->Solid              = ExaSolid;
851   pExa->DoneSolid          = ExaDone;
852   pExa->PrepareCopy        = ExaPrepareCopy;
853   pExa->Copy               = ExaCopy;
854   pExa->DoneCopy           = ExaDone;
855   pExa->CheckComposite     = ExaCheckComposite;
856   pExa->PrepareComposite   = ExaPrepareComposite;
857   pExa->Composite          = ExaComposite;
858   pExa->DoneComposite      = ExaDoneComposite;
859   pExa->PixmapIsOffscreen  = ExaPixmapIsOffscreen;
860   pExa->DownloadFromScreen = ExaDownloadFromScreen;
861   pExa->UploadToScreen     = ExaUploadToScreen;
862   pExa->PrepareAccess      = ExaPrepareAccess;
863   pExa->FinishAccess       = ExaFinishAccess;
864   pExa->CreatePixmap       = ExaCreatePixmap;
865   pExa->DestroyPixmap      = ExaDestroyPixmap;
866   pExa->ModifyPixmapHeader = ExaModifyPixmapHeader;
867
868   if (!exaDriverInit(pScrn->pScreen, pExa)) {
869      goto out_err;
870   }
871
872   exa->scrn = ms->screen;
873   exa->pipe = ms->api->create_context(ms->api, exa->scrn);
874   /* Share context with DRI */
875   ms->ctx = exa->pipe;
876
877   exa->renderer = renderer_create(exa->pipe);
878
879   return (void *)exa;
880
881out_err:
882   xorg_exa_close(pScrn);
883
884   return NULL;
885}
886
887struct pipe_surface *
888xorg_gpu_surface(struct pipe_screen *scrn, struct exa_pixmap_priv *priv)
889{
890   return scrn->get_tex_surface(scrn, priv->tex, 0, 0, 0,
891                                PIPE_BUFFER_USAGE_GPU_READ |
892                                PIPE_BUFFER_USAGE_GPU_WRITE);
893
894}
895
896void xorg_exa_flush(struct exa_context *exa, uint pipeFlushFlags,
897                    struct pipe_fence_handle **fence)
898{
899   exa->pipe->flush(exa->pipe, pipeFlushFlags, fence);
900}
901
902void xorg_exa_finish(struct exa_context *exa)
903{
904   struct pipe_fence_handle *fence = NULL;
905
906   xorg_exa_flush(exa, PIPE_FLUSH_RENDER_CACHE, &fence);
907
908   exa->pipe->screen->fence_finish(exa->pipe->screen, fence, 0);
909   exa->pipe->screen->fence_reference(exa->pipe->screen, &fence, NULL);
910}
911
912