xorg_exa.c revision c712f3374626d96f9c08c3571a5572bcee60a5f2
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
50/*
51 * Helper functions
52 */
53struct render_format_str {
54   int format;
55   const char *name;
56};
57static const struct render_format_str formats_info[] =
58{
59   {PICT_a8r8g8b8, "PICT_a8r8g8b8"},
60   {PICT_x8r8g8b8, "PICT_x8r8g8b8"},
61   {PICT_a8b8g8r8, "PICT_a8b8g8r8"},
62   {PICT_x8b8g8r8, "PICT_x8b8g8r8"},
63#ifdef PICT_TYPE_BGRA
64   {PICT_b8g8r8a8, "PICT_b8g8r8a8"},
65   {PICT_b8g8r8x8, "PICT_b8g8r8x8"},
66   {PICT_a2r10g10b10, "PICT_a2r10g10b10"},
67   {PICT_x2r10g10b10, "PICT_x2r10g10b10"},
68   {PICT_a2b10g10r10, "PICT_a2b10g10r10"},
69   {PICT_x2b10g10r10, "PICT_x2b10g10r10"},
70#endif
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
113static void
114exa_get_pipe_format(int depth, enum pipe_format *format, int *bbp, int *picture_format)
115{
116    switch (depth) {
117    case 32:
118	*format = PIPE_FORMAT_A8R8G8B8_UNORM;
119	*picture_format = PICT_a8r8g8b8;
120	assert(*bbp == 32);
121	break;
122    case 24:
123	*format = PIPE_FORMAT_X8R8G8B8_UNORM;
124	*picture_format = PICT_x8r8g8b8;
125	assert(*bbp == 32);
126	break;
127    case 16:
128	*format = PIPE_FORMAT_R5G6B5_UNORM;
129	*picture_format = PICT_r5g6b5;
130	assert(*bbp == 16);
131	break;
132    case 15:
133	*format = PIPE_FORMAT_A1R5G5B5_UNORM;
134	*picture_format = PICT_x1r5g5b5;
135	assert(*bbp == 16);
136	break;
137    case 8:
138	*format = PIPE_FORMAT_L8_UNORM;
139	*picture_format = PICT_a8;
140	assert(*bbp == 8);
141	break;
142    case 4:
143    case 1:
144	*format = PIPE_FORMAT_A8R8G8B8_UNORM; /* bad bad bad */
145	break;
146    default:
147	assert(0);
148	break;
149    }
150}
151
152static void
153xorg_exa_common_done(struct exa_context *exa)
154{
155   renderer_draw_flush(exa->renderer);
156
157   exa->copy.src = NULL;
158   exa->copy.dst = NULL;
159   pipe_surface_reference(&exa->copy.src_surface, NULL);
160   pipe_surface_reference(&exa->copy.dst_surface, NULL);
161   exa->transform.has_src = FALSE;
162   exa->transform.has_mask = FALSE;
163   exa->has_solid_color = FALSE;
164   exa->num_bound_samplers = 0;
165}
166
167/*
168 * Static exported EXA functions
169 */
170
171static void
172ExaWaitMarker(ScreenPtr pScreen, int marker)
173{
174   /* Nothing to do, handled in the PrepareAccess hook */
175}
176
177static int
178ExaMarkSync(ScreenPtr pScreen)
179{
180   return 1;
181}
182
183static Bool
184ExaDownloadFromScreen(PixmapPtr pPix, int x,  int y, int w,  int h, char *dst,
185		      int dst_pitch)
186{
187    ScreenPtr pScreen = pPix->drawable.pScreen;
188    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
189    modesettingPtr ms = modesettingPTR(pScrn);
190    struct exa_context *exa = ms->exa;
191    struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pPix);
192    struct pipe_transfer *transfer;
193
194    if (!priv || !priv->tex)
195	return FALSE;
196
197    if (exa->pipe->is_texture_referenced(exa->pipe, priv->tex, 0, 0) &
198	PIPE_REFERENCED_FOR_WRITE)
199	exa->pipe->flush(exa->pipe, 0, NULL);
200
201    transfer = exa->scrn->get_tex_transfer(exa->scrn, priv->tex, 0, 0, 0,
202					   PIPE_TRANSFER_READ, x, y, w, h);
203    if (!transfer)
204	return FALSE;
205
206#if DEBUG_PRINT
207    debug_printf("------ ExaDownloadFromScreen(%d, %d, %d, %d, %d)\n",
208                 x, y, w, h, dst_pitch);
209#endif
210
211    util_copy_rect((unsigned char*)dst, &priv->tex->block, dst_pitch, 0, 0,
212		   w, h, exa->scrn->transfer_map(exa->scrn, transfer),
213		   transfer->stride, 0, 0);
214
215    exa->scrn->transfer_unmap(exa->scrn, transfer);
216    exa->scrn->tex_transfer_destroy(transfer);
217
218    return TRUE;
219}
220
221static Bool
222ExaUploadToScreen(PixmapPtr pPix, int x, int y, int w, int h, char *src,
223		  int src_pitch)
224{
225    ScreenPtr pScreen = pPix->drawable.pScreen;
226    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
227    modesettingPtr ms = modesettingPTR(pScrn);
228    struct exa_context *exa = ms->exa;
229    struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pPix);
230    struct pipe_transfer *transfer;
231
232    if (!priv || !priv->tex)
233	return FALSE;
234
235    /* make sure that any pending operations are flushed to hardware */
236    if (exa->pipe->is_texture_referenced(exa->pipe, priv->tex, 0, 0) &
237	(PIPE_REFERENCED_FOR_READ | PIPE_REFERENCED_FOR_WRITE))
238	xorg_exa_flush(exa, 0, NULL);
239
240    transfer = exa->scrn->get_tex_transfer(exa->scrn, priv->tex, 0, 0, 0,
241					   PIPE_TRANSFER_WRITE, x, y, w, h);
242    if (!transfer)
243	return FALSE;
244
245#if DEBUG_PRINT
246    debug_printf("++++++ ExaUploadToScreen(%d, %d, %d, %d, %d)\n",
247                 x, y, w, h, src_pitch);
248#endif
249
250    util_copy_rect(exa->scrn->transfer_map(exa->scrn, transfer),
251		   &priv->tex->block, transfer->stride, 0, 0, w, h,
252		   (unsigned char*)src, src_pitch, 0, 0);
253
254    exa->scrn->transfer_unmap(exa->scrn, transfer);
255    exa->scrn->tex_transfer_destroy(transfer);
256
257    return TRUE;
258}
259
260static Bool
261ExaPrepareAccess(PixmapPtr pPix, int index)
262{
263    ScreenPtr pScreen = pPix->drawable.pScreen;
264    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
265    modesettingPtr ms = modesettingPTR(pScrn);
266    struct exa_context *exa = ms->exa;
267    struct exa_pixmap_priv *priv;
268
269    priv = exaGetPixmapDriverPrivate(pPix);
270
271    if (!priv)
272	return FALSE;
273
274    if (!priv->tex)
275	return FALSE;
276
277    if (priv->map_count == 0)
278    {
279	if (exa->pipe->is_texture_referenced(exa->pipe, priv->tex, 0, 0) &
280	    PIPE_REFERENCED_FOR_WRITE)
281	    exa->pipe->flush(exa->pipe, 0, NULL);
282
283	priv->map_transfer =
284	    exa->scrn->get_tex_transfer(exa->scrn, priv->tex, 0, 0, 0,
285#ifdef EXA_MIXED_PIXMAPS
286					PIPE_TRANSFER_MAP_DIRECTLY |
287#endif
288					PIPE_TRANSFER_READ_WRITE,
289					0, 0, priv->tex->width[0], priv->tex->height[0]);
290	if (!priv->map_transfer)
291#ifdef EXA_MIXED_PIXMAPS
292	    return FALSE;
293#else
294	    FatalError("failed to create transfer\n");
295#endif
296
297	pPix->devPrivate.ptr =
298	    exa->scrn->transfer_map(exa->scrn, priv->map_transfer);
299	pPix->devKind = priv->map_transfer->stride;
300    }
301
302    priv->map_count++;
303
304    return TRUE;
305}
306
307static void
308ExaFinishAccess(PixmapPtr pPix, int index)
309{
310    ScreenPtr pScreen = pPix->drawable.pScreen;
311    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
312    modesettingPtr ms = modesettingPTR(pScrn);
313    struct exa_context *exa = ms->exa;
314    struct exa_pixmap_priv *priv;
315    priv = exaGetPixmapDriverPrivate(pPix);
316
317    if (!priv)
318	return;
319
320    if (!priv->map_transfer)
321	return;
322
323    if (--priv->map_count == 0) {
324	assert(priv->map_transfer);
325	exa->scrn->transfer_unmap(exa->scrn, priv->map_transfer);
326	exa->scrn->tex_transfer_destroy(priv->map_transfer);
327	priv->map_transfer = NULL;
328	pPix->devPrivate.ptr = NULL;
329    }
330}
331
332static void
333ExaDone(PixmapPtr pPixmap)
334{
335    ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum];
336    modesettingPtr ms = modesettingPTR(pScrn);
337    struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pPixmap);
338    struct exa_context *exa = ms->exa;
339
340    if (!priv)
341	return;
342
343    xorg_exa_common_done(exa);
344}
345
346static void
347ExaDoneComposite(PixmapPtr pPixmap)
348{
349   ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum];
350   modesettingPtr ms = modesettingPTR(pScrn);
351   struct exa_context *exa = ms->exa;
352
353   xorg_exa_common_done(exa);
354}
355
356static Bool
357ExaPrepareSolid(PixmapPtr pPixmap, int alu, Pixel planeMask, Pixel fg)
358{
359    ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum];
360    modesettingPtr ms = modesettingPTR(pScrn);
361    struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pPixmap);
362    struct exa_context *exa = ms->exa;
363
364#if DEBUG_PRINT
365    debug_printf("ExaPrepareSolid(0x%x)\n", fg);
366#endif
367    if (!exa->pipe)
368	XORG_FALLBACK("accle not enabled");
369
370    if (!priv || !priv->tex)
371	XORG_FALLBACK("%s", !priv ? "!priv" : "!priv->tex");
372
373    if (!EXA_PM_IS_SOLID(&pPixmap->drawable, planeMask))
374	XORG_FALLBACK("planeMask is not solid");
375
376    if (alu != GXcopy)
377	XORG_FALLBACK("not GXcopy");
378
379    if (!exa->scrn->is_format_supported(exa->scrn, priv->tex->format,
380                                        priv->tex->target,
381                                        PIPE_TEXTURE_USAGE_RENDER_TARGET, 0)) {
382	XORG_FALLBACK("format %s", pf_name(priv->tex->format));
383    }
384
385    return exa->accel && xorg_solid_bind_state(exa, priv, fg);
386}
387
388static void
389ExaSolid(PixmapPtr pPixmap, int x0, int y0, int x1, int y1)
390{
391    ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum];
392    modesettingPtr ms = modesettingPTR(pScrn);
393    struct exa_context *exa = ms->exa;
394    struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pPixmap);
395
396#if DEBUG_PRINT
397    debug_printf("\tExaSolid(%d, %d, %d, %d)\n", x0, y0, x1, y1);
398#endif
399
400    xorg_solid(exa, priv, x0, y0, x1, y1) ;
401}
402
403static Bool
404ExaPrepareCopy(PixmapPtr pSrcPixmap, PixmapPtr pDstPixmap, int xdir,
405	       int ydir, int alu, Pixel planeMask)
406{
407    ScrnInfoPtr pScrn = xf86Screens[pDstPixmap->drawable.pScreen->myNum];
408    modesettingPtr ms = modesettingPTR(pScrn);
409    struct exa_context *exa = ms->exa;
410    struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pDstPixmap);
411    struct exa_pixmap_priv *src_priv = exaGetPixmapDriverPrivate(pSrcPixmap);
412
413#if DEBUG_PRINT
414    debug_printf("ExaPrepareCopy\n");
415#endif
416    if (!exa->pipe)
417	XORG_FALLBACK("accle not enabled");
418
419    if (!priv || !priv->tex)
420	XORG_FALLBACK("pDst %s", !priv ? "!priv" : "!priv->tex");
421
422    if (!src_priv || !src_priv->tex)
423	XORG_FALLBACK("pSrc %s", !src_priv ? "!priv" : "!priv->tex");
424
425    if (!EXA_PM_IS_SOLID(&pSrcPixmap->drawable, planeMask))
426	XORG_FALLBACK("planeMask is not solid");
427
428    if (alu != GXcopy)
429	XORG_FALLBACK("alu not GXcopy");
430
431    if (!exa->scrn->is_format_supported(exa->scrn, priv->tex->format,
432                                        priv->tex->target,
433                                        PIPE_TEXTURE_USAGE_RENDER_TARGET, 0))
434	XORG_FALLBACK("pDst format %s", pf_name(priv->tex->format));
435
436    if (!exa->scrn->is_format_supported(exa->scrn, src_priv->tex->format,
437                                        src_priv->tex->target,
438                                        PIPE_TEXTURE_USAGE_SAMPLER, 0))
439	XORG_FALLBACK("pSrc format %s", pf_name(src_priv->tex->format));
440
441    exa->copy.src = src_priv;
442    exa->copy.dst = priv;
443
444    if (exa->pipe->surface_copy) {
445       exa->copy.src_surface =
446          exa->scrn->get_tex_surface( exa->scrn,
447                                      exa->copy.src->tex,
448                                      0, 0, 0,
449                                      PIPE_BUFFER_USAGE_GPU_READ);
450
451       exa->copy.dst_surface =
452          exa->scrn->get_tex_surface( exa->scrn,
453                                      exa->copy.dst->tex,
454                                      0, 0, 0,
455                                      PIPE_BUFFER_USAGE_GPU_WRITE );
456    }
457
458
459    return exa->accel;
460}
461
462static void
463ExaCopy(PixmapPtr pDstPixmap, int srcX, int srcY, int dstX, int dstY,
464	int width, int height)
465{
466   ScrnInfoPtr pScrn = xf86Screens[pDstPixmap->drawable.pScreen->myNum];
467   modesettingPtr ms = modesettingPTR(pScrn);
468   struct exa_context *exa = ms->exa;
469   struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pDstPixmap);
470
471#if DEBUG_PRINT
472   debug_printf("\tExaCopy(srcx=%d, srcy=%d, dstX=%d, dstY=%d, w=%d, h=%d)\n",
473                srcX, srcY, dstX, dstY, width, height);
474#endif
475
476   debug_assert(priv == exa->copy.dst);
477
478   if (exa->copy.src_surface && exa->copy.dst_surface) {
479      /* XXX: consider exposing >1 box in surface_copy interface.
480       */
481      exa->pipe->surface_copy( exa->pipe,
482                             exa->copy.dst_surface,
483                             dstX, dstY,
484                             exa->copy.src_surface,
485                             srcX, srcY,
486                             width, height );
487   }
488   else {
489      renderer_copy_pixmap(exa->renderer, exa->copy.dst, dstX, dstY,
490                           exa->copy.src, srcX, srcY,
491                           width, height);
492   }
493}
494
495
496static Bool
497picture_check_formats(struct exa_pixmap_priv *pSrc, PicturePtr pSrcPicture)
498{
499   if (pSrc->picture_format == pSrcPicture->format)
500      return TRUE;
501
502   if (pSrc->picture_format != PICT_a8r8g8b8)
503      return FALSE;
504
505   /* pSrc->picture_format == PICT_a8r8g8b8 */
506   switch (pSrcPicture->format) {
507   case PICT_a8r8g8b8:
508   case PICT_x8r8g8b8:
509   case PICT_a8b8g8r8:
510   case PICT_x8b8g8r8:
511   /* just treat these two as x8... */
512   case PICT_r8g8b8:
513   case PICT_b8g8r8:
514      return TRUE;
515#ifdef PICT_TYPE_BGRA
516   case PICT_b8g8r8a8:
517   case PICT_b8g8r8x8:
518      return FALSE; /* does not support swizzleing the alpha channel yet */
519   case PICT_a2r10g10b10:
520   case PICT_x2r10g10b10:
521   case PICT_a2b10g10r10:
522   case PICT_x2b10g10r10:
523      return FALSE;
524#endif
525   default:
526      return FALSE;
527   }
528   return FALSE;
529}
530
531static Bool
532ExaPrepareComposite(int op, PicturePtr pSrcPicture,
533		    PicturePtr pMaskPicture, PicturePtr pDstPicture,
534		    PixmapPtr pSrc, PixmapPtr pMask, PixmapPtr pDst)
535{
536   ScrnInfoPtr pScrn = xf86Screens[pDst->drawable.pScreen->myNum];
537   modesettingPtr ms = modesettingPTR(pScrn);
538   struct exa_context *exa = ms->exa;
539   struct exa_pixmap_priv *priv;
540
541#if DEBUG_PRINT
542   debug_printf("ExaPrepareComposite(%d, src=0x%p, mask=0x%p, dst=0x%p)\n",
543                op, pSrcPicture, pMaskPicture, pDstPicture);
544   debug_printf("\tFormats: src(%s), mask(%s), dst(%s)\n",
545                pSrcPicture ? render_format_name(pSrcPicture->format) : "none",
546                pMaskPicture ? render_format_name(pMaskPicture->format) : "none",
547                pDstPicture ? render_format_name(pDstPicture->format) : "none");
548#endif
549   if (!exa->pipe)
550      XORG_FALLBACK("accle not enabled");
551
552   priv = exaGetPixmapDriverPrivate(pDst);
553   if (!priv || !priv->tex)
554      XORG_FALLBACK("pDst %s", !priv ? "!priv" : "!priv->tex");
555
556   if (!exa->scrn->is_format_supported(exa->scrn, priv->tex->format,
557                                       priv->tex->target,
558                                       PIPE_TEXTURE_USAGE_RENDER_TARGET, 0))
559      XORG_FALLBACK("pDst format: %s", pf_name(priv->tex->format));
560
561   if (priv->picture_format != pDstPicture->format)
562      XORG_FALLBACK("pDst pic_format: %s != %s",
563                    render_format_name(priv->picture_format),
564                    render_format_name(pDstPicture->format));
565
566   if (pSrc) {
567      priv = exaGetPixmapDriverPrivate(pSrc);
568      if (!priv || !priv->tex)
569         XORG_FALLBACK("pSrc %s", !priv ? "!priv" : "!priv->tex");
570
571      if (!exa->scrn->is_format_supported(exa->scrn, priv->tex->format,
572                                          priv->tex->target,
573                                          PIPE_TEXTURE_USAGE_SAMPLER, 0))
574         XORG_FALLBACK("pSrc format: %s", pf_name(priv->tex->format));
575
576      if (!picture_check_formats(priv, pSrcPicture))
577         XORG_FALLBACK("pSrc pic_format: %s != %s",
578                       render_format_name(priv->picture_format),
579                       render_format_name(pSrcPicture->format));
580
581   }
582
583   if (pMask) {
584      priv = exaGetPixmapDriverPrivate(pMask);
585      if (!priv || !priv->tex)
586         XORG_FALLBACK("pMask %s", !priv ? "!priv" : "!priv->tex");
587
588      if (!exa->scrn->is_format_supported(exa->scrn, priv->tex->format,
589                                          priv->tex->target,
590                                          PIPE_TEXTURE_USAGE_SAMPLER, 0))
591         XORG_FALLBACK("pMask format: %s", pf_name(priv->tex->format));
592
593      if (!picture_check_formats(priv, pMaskPicture))
594         XORG_FALLBACK("pMask pic_format: %s != %s",
595                       render_format_name(priv->picture_format),
596                       render_format_name(pMaskPicture->format));
597   }
598
599   return exa->accel &&
600          xorg_composite_bind_state(exa, op, pSrcPicture, pMaskPicture,
601                                    pDstPicture,
602                                    pSrc ? exaGetPixmapDriverPrivate(pSrc) : NULL,
603                                    pMask ? exaGetPixmapDriverPrivate(pMask) : NULL,
604                                    exaGetPixmapDriverPrivate(pDst));
605}
606
607static void
608ExaComposite(PixmapPtr pDst, int srcX, int srcY, int maskX, int maskY,
609	     int dstX, int dstY, int width, int height)
610{
611   ScrnInfoPtr pScrn = xf86Screens[pDst->drawable.pScreen->myNum];
612   modesettingPtr ms = modesettingPTR(pScrn);
613   struct exa_context *exa = ms->exa;
614   struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pDst);
615
616#if DEBUG_PRINT
617   debug_printf("\tExaComposite(src[%d,%d], mask=[%d, %d], dst=[%d, %d], dim=[%d, %d])\n",
618                srcX, srcY, maskX, maskY, dstX, dstY, width, height);
619   debug_printf("\t   Num bound samplers = %d\n",
620                exa->num_bound_samplers);
621#endif
622
623   xorg_composite(exa, priv, srcX, srcY, maskX, maskY,
624                  dstX, dstY, width, height);
625}
626
627static Bool
628ExaCheckComposite(int op,
629		  PicturePtr pSrcPicture, PicturePtr pMaskPicture,
630		  PicturePtr pDstPicture)
631{
632   ScrnInfoPtr pScrn = xf86Screens[pDstPicture->pDrawable->pScreen->myNum];
633   modesettingPtr ms = modesettingPTR(pScrn);
634   struct exa_context *exa = ms->exa;
635   boolean accelerated = xorg_composite_accelerated(op,
636                                                    pSrcPicture,
637                                                    pMaskPicture,
638                                                    pDstPicture);
639#if DEBUG_PRINT
640   debug_printf("ExaCheckComposite(%d, %p, %p, %p) = %d\n",
641                op, pSrcPicture, pMaskPicture, pDstPicture, accelerated);
642#endif
643   return exa->accel && accelerated;
644}
645
646static void *
647ExaCreatePixmap(ScreenPtr pScreen, int size, int align)
648{
649    struct exa_pixmap_priv *priv;
650
651    priv = xcalloc(1, sizeof(struct exa_pixmap_priv));
652    if (!priv)
653	return NULL;
654
655    return priv;
656}
657
658static void
659ExaDestroyPixmap(ScreenPtr pScreen, void *dPriv)
660{
661    struct exa_pixmap_priv *priv = (struct exa_pixmap_priv *)dPriv;
662
663    if (!priv)
664	return;
665
666    pipe_texture_reference(&priv->tex, NULL);
667
668    xfree(priv);
669}
670
671static Bool
672ExaPixmapIsOffscreen(PixmapPtr pPixmap)
673{
674    struct exa_pixmap_priv *priv;
675
676    priv = exaGetPixmapDriverPrivate(pPixmap);
677
678    if (!priv)
679	return FALSE;
680
681    if (priv->tex)
682	return TRUE;
683
684    return FALSE;
685}
686
687int
688xorg_exa_set_displayed_usage(PixmapPtr pPixmap)
689{
690    struct exa_pixmap_priv *priv;
691    priv = exaGetPixmapDriverPrivate(pPixmap);
692
693    if (!priv) {
694	FatalError("NO PIXMAP PRIVATE\n");
695	return 0;
696    }
697
698    priv->flags |= PIPE_TEXTURE_USAGE_PRIMARY;
699
700    return 0;
701}
702
703int
704xorg_exa_set_shared_usage(PixmapPtr pPixmap)
705{
706    struct exa_pixmap_priv *priv;
707    priv = exaGetPixmapDriverPrivate(pPixmap);
708
709    if (!priv) {
710	FatalError("NO PIXMAP PRIVATE\n");
711	return 0;
712    }
713
714    priv->flags |= PIPE_TEXTURE_USAGE_DISPLAY_TARGET;
715
716    return 0;
717}
718
719unsigned
720xorg_exa_get_pixmap_handle(PixmapPtr pPixmap, unsigned *stride_out)
721{
722    ScreenPtr pScreen = pPixmap->drawable.pScreen;
723    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
724    modesettingPtr ms = modesettingPTR(pScrn);
725    struct exa_pixmap_priv *priv;
726    unsigned handle;
727    unsigned stride;
728
729    if (!ms->exa) {
730	FatalError("NO MS->EXA\n");
731	return 0;
732    }
733
734    priv = exaGetPixmapDriverPrivate(pPixmap);
735
736    if (!priv) {
737	FatalError("NO PIXMAP PRIVATE\n");
738	return 0;
739    }
740
741    ms->api->local_handle_from_texture(ms->api, ms->screen, priv->tex, &stride, &handle);
742    if (stride_out)
743	*stride_out = stride;
744
745    return handle;
746}
747
748static Bool
749ExaModifyPixmapHeader(PixmapPtr pPixmap, int width, int height,
750		      int depth, int bitsPerPixel, int devKind,
751		      pointer pPixData)
752{
753    ScreenPtr pScreen = pPixmap->drawable.pScreen;
754    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
755    struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pPixmap);
756    modesettingPtr ms = modesettingPTR(pScrn);
757    struct exa_context *exa = ms->exa;
758
759    if (!priv || pPixData)
760	return FALSE;
761
762    if (depth <= 0)
763	depth = pPixmap->drawable.depth;
764
765    if (bitsPerPixel <= 0)
766	bitsPerPixel = pPixmap->drawable.bitsPerPixel;
767
768    if (width <= 0)
769	width = pPixmap->drawable.width;
770
771    if (height <= 0)
772	height = pPixmap->drawable.height;
773
774    if (width <= 0 || height <= 0 || depth <= 0)
775	return FALSE;
776
777    miModifyPixmapHeader(pPixmap, width, height, depth,
778			     bitsPerPixel, devKind, NULL);
779
780    /* Deal with screen resize */
781    if ((exa->accel || priv->flags) &&
782        (!priv->tex ||
783         (priv->tex->width[0] != width ||
784          priv->tex->height[0] != height ||
785          priv->tex_flags != priv->flags))) {
786	struct pipe_texture *texture = NULL;
787	struct pipe_texture template;
788
789	memset(&template, 0, sizeof(template));
790	template.target = PIPE_TEXTURE_2D;
791	exa_get_pipe_format(depth, &template.format, &bitsPerPixel, &priv->picture_format);
792	pf_get_block(template.format, &template.block);
793	template.width[0] = width;
794	template.height[0] = height;
795	template.depth[0] = 1;
796	template.last_level = 0;
797	template.tex_usage = PIPE_TEXTURE_USAGE_RENDER_TARGET | priv->flags;
798	priv->tex_flags = priv->flags;
799	texture = exa->scrn->texture_create(exa->scrn, &template);
800
801	if (priv->tex) {
802	    struct pipe_surface *dst_surf;
803	    struct pipe_surface *src_surf;
804
805	    dst_surf = exa->scrn->get_tex_surface(
806		exa->scrn, texture, 0, 0, 0, PIPE_BUFFER_USAGE_GPU_WRITE);
807	    src_surf = xorg_gpu_surface(exa->pipe->screen, priv);
808        if (exa->pipe->surface_copy) {
809            exa->pipe->surface_copy(exa->pipe, dst_surf, 0, 0, src_surf,
810                        0, 0, min(width, texture->width[0]),
811                        min(height, texture->height[0]));
812        } else {
813            util_surface_copy(exa->pipe, FALSE, dst_surf, 0, 0, src_surf,
814                        0, 0, min(width, texture->width[0]),
815                        min(height, texture->height[0]));
816        }
817	    exa->scrn->tex_surface_destroy(dst_surf);
818	    exa->scrn->tex_surface_destroy(src_surf);
819	}
820
821	pipe_texture_reference(&priv->tex, texture);
822	/* the texture we create has one reference */
823	pipe_texture_reference(&texture, NULL);
824    }
825
826    return TRUE;
827}
828
829struct pipe_texture *
830xorg_exa_get_texture(PixmapPtr pPixmap)
831{
832   struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pPixmap);
833   struct pipe_texture *tex = NULL;
834   pipe_texture_reference(&tex, priv->tex);
835   return tex;
836}
837
838Bool
839xorg_exa_set_texture(PixmapPtr pPixmap, struct  pipe_texture *tex)
840{
841    struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pPixmap);
842
843    int mask = PIPE_TEXTURE_USAGE_PRIMARY | PIPE_TEXTURE_USAGE_DISPLAY_TARGET;
844
845    if (!priv)
846	return FALSE;
847
848    if (pPixmap->drawable.width != tex->width[0] ||
849	pPixmap->drawable.height != tex->height[0])
850	return FALSE;
851
852    pipe_texture_reference(&priv->tex, tex);
853    priv->tex_flags = tex->tex_usage & mask;
854
855    return TRUE;
856}
857
858struct pipe_texture *
859xorg_exa_create_root_texture(ScrnInfoPtr pScrn,
860			     int width, int height,
861			     int depth, int bitsPerPixel)
862{
863    modesettingPtr ms = modesettingPTR(pScrn);
864    struct exa_context *exa = ms->exa;
865    struct pipe_texture template;
866    int dummy;
867
868    memset(&template, 0, sizeof(template));
869    template.target = PIPE_TEXTURE_2D;
870    exa_get_pipe_format(depth, &template.format, &bitsPerPixel, &dummy);
871    pf_get_block(template.format, &template.block);
872    template.width[0] = width;
873    template.height[0] = height;
874    template.depth[0] = 1;
875    template.last_level = 0;
876    template.tex_usage |= PIPE_TEXTURE_USAGE_RENDER_TARGET;
877    template.tex_usage |= PIPE_TEXTURE_USAGE_PRIMARY;
878    template.tex_usage |= PIPE_TEXTURE_USAGE_DISPLAY_TARGET;
879
880    return exa->scrn->texture_create(exa->scrn, &template);
881}
882
883void
884xorg_exa_close(ScrnInfoPtr pScrn)
885{
886   modesettingPtr ms = modesettingPTR(pScrn);
887   struct exa_context *exa = ms->exa;
888
889   renderer_destroy(exa->renderer);
890
891   if (exa->pipe)
892      exa->pipe->destroy(exa->pipe);
893
894   exaDriverFini(pScrn->pScreen);
895   xfree(exa);
896   ms->exa = NULL;
897}
898
899void *
900xorg_exa_init(ScrnInfoPtr pScrn, Bool accel)
901{
902   modesettingPtr ms = modesettingPTR(pScrn);
903   struct exa_context *exa;
904   ExaDriverPtr pExa;
905
906   exa = xcalloc(1, sizeof(struct exa_context));
907   if (!exa)
908      return NULL;
909
910   pExa = exaDriverAlloc();
911   if (!pExa) {
912      goto out_err;
913   }
914
915   memset(pExa, 0, sizeof(*pExa));
916
917   pExa->exa_major         = 2;
918   pExa->exa_minor         = 2;
919   pExa->memoryBase        = 0;
920   pExa->memorySize        = 0;
921   pExa->offScreenBase     = 0;
922   pExa->pixmapOffsetAlign = 0;
923   pExa->pixmapPitchAlign  = 1;
924   pExa->flags             = EXA_OFFSCREEN_PIXMAPS | EXA_HANDLES_PIXMAPS;
925#ifdef EXA_SUPPORTS_PREPARE_AUX
926   pExa->flags            |= EXA_SUPPORTS_PREPARE_AUX;
927#endif
928#ifdef EXA_MIXED_PIXMAPS
929   pExa->flags            |= EXA_MIXED_PIXMAPS;
930#endif
931   pExa->maxX              = 8191; /* FIXME */
932   pExa->maxY              = 8191; /* FIXME */
933
934   pExa->WaitMarker         = ExaWaitMarker;
935   pExa->MarkSync           = ExaMarkSync;
936   pExa->PrepareSolid       = ExaPrepareSolid;
937   pExa->Solid              = ExaSolid;
938   pExa->DoneSolid          = ExaDone;
939   pExa->PrepareCopy        = ExaPrepareCopy;
940   pExa->Copy               = ExaCopy;
941   pExa->DoneCopy           = ExaDone;
942   pExa->CheckComposite     = ExaCheckComposite;
943   pExa->PrepareComposite   = ExaPrepareComposite;
944   pExa->Composite          = ExaComposite;
945   pExa->DoneComposite      = ExaDoneComposite;
946   pExa->PixmapIsOffscreen  = ExaPixmapIsOffscreen;
947   pExa->DownloadFromScreen = ExaDownloadFromScreen;
948   pExa->UploadToScreen     = ExaUploadToScreen;
949   pExa->PrepareAccess      = ExaPrepareAccess;
950   pExa->FinishAccess       = ExaFinishAccess;
951   pExa->CreatePixmap       = ExaCreatePixmap;
952   pExa->DestroyPixmap      = ExaDestroyPixmap;
953   pExa->ModifyPixmapHeader = ExaModifyPixmapHeader;
954
955   if (!exaDriverInit(pScrn->pScreen, pExa)) {
956      goto out_err;
957   }
958
959   exa->scrn = ms->screen;
960   exa->pipe = ms->api->create_context(ms->api, exa->scrn);
961   /* Share context with DRI */
962   ms->ctx = exa->pipe;
963
964   exa->renderer = renderer_create(exa->pipe);
965   exa->accel = accel;
966
967   return (void *)exa;
968
969out_err:
970   xorg_exa_close(pScrn);
971
972   return NULL;
973}
974
975struct pipe_surface *
976xorg_gpu_surface(struct pipe_screen *scrn, struct exa_pixmap_priv *priv)
977{
978   return scrn->get_tex_surface(scrn, priv->tex, 0, 0, 0,
979                                PIPE_BUFFER_USAGE_GPU_READ |
980                                PIPE_BUFFER_USAGE_GPU_WRITE);
981
982}
983
984void xorg_exa_flush(struct exa_context *exa, uint pipeFlushFlags,
985                    struct pipe_fence_handle **fence)
986{
987   exa->pipe->flush(exa->pipe, pipeFlushFlags, fence);
988}
989
990void xorg_exa_finish(struct exa_context *exa)
991{
992   struct pipe_fence_handle *fence = NULL;
993
994   xorg_exa_flush(exa, PIPE_FLUSH_RENDER_CACHE, &fence);
995
996   exa->pipe->screen->fence_finish(exa->pipe->screen, fence, 0);
997   exa->pipe->screen->fence_reference(exa->pipe->screen, &fence, NULL);
998}
999
1000