xorg_exa.c revision 6dd284f7c8fac22f64c13fdf9909094f5ec59086
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
45#include "util/u_rect.h"
46#include "util/u_math.h"
47#include "util/u_debug.h"
48#include "util/u_format.h"
49#include "util/u_box.h"
50#include "util/u_surface.h"
51
52#define ROUND_UP_TEXTURES 1
53
54static INLINE void
55exa_debug_printf(const char *format, ...) _util_printf_format(1,2);
56
57static INLINE void
58exa_debug_printf(const char *format, ...)
59{
60#if 0
61   va_list ap;
62   va_start(ap, format);
63   _debug_vprintf(format, ap);
64   va_end(ap);
65#else
66   (void) format; /* silence warning */
67#endif
68}
69
70/*
71 * Helper functions
72 */
73struct render_format_str {
74   int format;
75   const char *name;
76};
77static const struct render_format_str formats_info[] =
78{
79   {PICT_a8r8g8b8, "PICT_a8r8g8b8"},
80   {PICT_x8r8g8b8, "PICT_x8r8g8b8"},
81   {PICT_a8b8g8r8, "PICT_a8b8g8r8"},
82   {PICT_x8b8g8r8, "PICT_x8b8g8r8"},
83#ifdef PICT_TYPE_BGRA
84   {PICT_b8g8r8a8, "PICT_b8g8r8a8"},
85   {PICT_b8g8r8x8, "PICT_b8g8r8x8"},
86   {PICT_a2r10g10b10, "PICT_a2r10g10b10"},
87   {PICT_x2r10g10b10, "PICT_x2r10g10b10"},
88   {PICT_a2b10g10r10, "PICT_a2b10g10r10"},
89   {PICT_x2b10g10r10, "PICT_x2b10g10r10"},
90#endif
91   {PICT_r8g8b8, "PICT_r8g8b8"},
92   {PICT_b8g8r8, "PICT_b8g8r8"},
93   {PICT_r5g6b5, "PICT_r5g6b5"},
94   {PICT_b5g6r5, "PICT_b5g6r5"},
95   {PICT_a1r5g5b5, "PICT_a1r5g5b5"},
96   {PICT_x1r5g5b5, "PICT_x1r5g5b5"},
97   {PICT_a1b5g5r5, "PICT_a1b5g5r5"},
98   {PICT_x1b5g5r5, "PICT_x1b5g5r5"},
99   {PICT_a4r4g4b4, "PICT_a4r4g4b4"},
100   {PICT_x4r4g4b4, "PICT_x4r4g4b4"},
101   {PICT_a4b4g4r4, "PICT_a4b4g4r4"},
102   {PICT_x4b4g4r4, "PICT_x4b4g4r4"},
103   {PICT_a8, "PICT_a8"},
104   {PICT_r3g3b2, "PICT_r3g3b2"},
105   {PICT_b2g3r3, "PICT_b2g3r3"},
106   {PICT_a2r2g2b2, "PICT_a2r2g2b2"},
107   {PICT_a2b2g2r2, "PICT_a2b2g2r2"},
108   {PICT_c8, "PICT_c8"},
109   {PICT_g8, "PICT_g8"},
110   {PICT_x4a4, "PICT_x4a4"},
111   {PICT_x4c4, "PICT_x4c4"},
112   {PICT_x4g4, "PICT_x4g4"},
113   {PICT_a4, "PICT_a4"},
114   {PICT_r1g2b1, "PICT_r1g2b1"},
115   {PICT_b1g2r1, "PICT_b1g2r1"},
116   {PICT_a1r1g1b1, "PICT_a1r1g1b1"},
117   {PICT_a1b1g1r1, "PICT_a1b1g1r1"},
118   {PICT_c4, "PICT_c4"},
119   {PICT_g4, "PICT_g4"},
120   {PICT_a1, "PICT_a1"},
121   {PICT_g1, "PICT_g1"}
122};
123static const char *render_format_name(int format)
124{
125   int i = 0;
126   for (i = 0; i < sizeof(formats_info)/sizeof(formats_info[0]); ++i) {
127      if (formats_info[i].format == format)
128         return formats_info[i].name;
129   }
130   return NULL;
131}
132
133static void
134exa_get_pipe_format(int depth, enum pipe_format *format, int *bbp, int *picture_format)
135{
136    switch (depth) {
137    case 32:
138	*format = PIPE_FORMAT_B8G8R8A8_UNORM;
139	*picture_format = PICT_a8r8g8b8;
140	assert(*bbp == 32);
141	break;
142    case 24:
143	*format = PIPE_FORMAT_B8G8R8X8_UNORM;
144	*picture_format = PICT_x8r8g8b8;
145	assert(*bbp == 32);
146	break;
147    case 16:
148	*format = PIPE_FORMAT_B5G6R5_UNORM;
149	*picture_format = PICT_r5g6b5;
150	assert(*bbp == 16);
151	break;
152    case 15:
153	*format = PIPE_FORMAT_B5G5R5A1_UNORM;
154	*picture_format = PICT_x1r5g5b5;
155	assert(*bbp == 16);
156	break;
157    case 8:
158	*format = PIPE_FORMAT_L8_UNORM;
159	*picture_format = PICT_a8;
160	assert(*bbp == 8);
161	break;
162    case 4:
163    case 1:
164	*format = PIPE_FORMAT_B8G8R8A8_UNORM; /* bad bad bad */
165	break;
166    default:
167	assert(0);
168	break;
169    }
170}
171
172
173/*
174 * Static exported EXA functions
175 */
176
177static void
178ExaWaitMarker(ScreenPtr pScreen, int marker)
179{
180   /* Nothing to do, handled in the PrepareAccess hook */
181}
182
183static int
184ExaMarkSync(ScreenPtr pScreen)
185{
186   return 1;
187}
188
189
190/***********************************************************************
191 * Screen upload/download
192 */
193
194static Bool
195ExaDownloadFromScreen(PixmapPtr pPix, int x,  int y, int w,  int h, char *dst,
196		      int dst_pitch)
197{
198    ScreenPtr pScreen = pPix->drawable.pScreen;
199    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
200    modesettingPtr ms = modesettingPTR(pScrn);
201    struct exa_context *exa = ms->exa;
202    struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pPix);
203    struct pipe_transfer *transfer;
204
205    if (!priv || !priv->tex)
206	return FALSE;
207
208    transfer = pipe_get_transfer(exa->pipe, priv->tex, 0, 0,
209                                 PIPE_TRANSFER_READ, x, y, w, h);
210    if (!transfer)
211	return FALSE;
212
213    exa_debug_printf("------ ExaDownloadFromScreen(%d, %d, %d, %d, %d)\n",
214                 x, y, w, h, dst_pitch);
215
216    util_copy_rect((unsigned char*)dst, priv->tex->format, dst_pitch, 0, 0,
217		   w, h, exa->pipe->transfer_map(exa->pipe, transfer),
218		   transfer->stride, 0, 0);
219
220    exa->pipe->transfer_unmap(exa->pipe, transfer);
221    exa->pipe->transfer_destroy(exa->pipe, transfer);
222
223    return TRUE;
224}
225
226static Bool
227ExaUploadToScreen(PixmapPtr pPix, int x, int y, int w, int h, char *src,
228		  int src_pitch)
229{
230    ScreenPtr pScreen = pPix->drawable.pScreen;
231    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
232    modesettingPtr ms = modesettingPTR(pScrn);
233    struct exa_context *exa = ms->exa;
234    struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pPix);
235    struct pipe_transfer *transfer;
236
237    if (!priv || !priv->tex)
238	return FALSE;
239
240    transfer = pipe_get_transfer(exa->pipe, priv->tex, 0, 0,
241                                 PIPE_TRANSFER_WRITE, x, y, w, h);
242    if (!transfer)
243	return FALSE;
244
245    exa_debug_printf("++++++ ExaUploadToScreen(%d, %d, %d, %d, %d)\n",
246                 x, y, w, h, src_pitch);
247
248    util_copy_rect(exa->pipe->transfer_map(exa->pipe, transfer),
249		   priv->tex->format, transfer->stride, 0, 0, w, h,
250		   (unsigned char*)src, src_pitch, 0, 0);
251
252    exa->pipe->transfer_unmap(exa->pipe, transfer);
253    exa->pipe->transfer_destroy(exa->pipe, transfer);
254
255    return TRUE;
256}
257
258static Bool
259ExaPrepareAccess(PixmapPtr pPix, int index)
260{
261    ScreenPtr pScreen = pPix->drawable.pScreen;
262    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
263    modesettingPtr ms = modesettingPTR(pScrn);
264    struct exa_context *exa = ms->exa;
265    struct exa_pixmap_priv *priv;
266
267    priv = exaGetPixmapDriverPrivate(pPix);
268
269    if (!priv)
270	return FALSE;
271
272    if (!priv->tex)
273	return FALSE;
274
275    exa_debug_printf("ExaPrepareAccess %d\n", index);
276
277    if (priv->map_count == 0)
278    {
279        assert(pPix->drawable.width <= priv->tex->width0);
280        assert(pPix->drawable.height <= priv->tex->height0);
281
282	priv->map_transfer =
283	   pipe_get_transfer(exa->pipe, priv->tex, 0, 0,
284#ifdef EXA_MIXED_PIXMAPS
285					PIPE_TRANSFER_MAP_DIRECTLY |
286#endif
287					PIPE_TRANSFER_READ_WRITE,
288					0, 0,
289                                        pPix->drawable.width,
290                                        pPix->drawable.height );
291	if (!priv->map_transfer)
292#ifdef EXA_MIXED_PIXMAPS
293	    return FALSE;
294#else
295	    FatalError("failed to create transfer\n");
296#endif
297
298	pPix->devPrivate.ptr =
299	    exa->pipe->transfer_map(exa->pipe, priv->map_transfer);
300	pPix->devKind = priv->map_transfer->stride;
301    }
302
303    priv->map_count++;
304
305    exa_debug_printf("ExaPrepareAccess %d prepared\n", index);
306
307    return TRUE;
308}
309
310static void
311ExaFinishAccess(PixmapPtr pPix, int index)
312{
313    ScreenPtr pScreen = pPix->drawable.pScreen;
314    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
315    modesettingPtr ms = modesettingPTR(pScrn);
316    struct exa_context *exa = ms->exa;
317    struct exa_pixmap_priv *priv;
318    priv = exaGetPixmapDriverPrivate(pPix);
319
320    if (!priv)
321	return;
322
323    if (!priv->map_transfer)
324	return;
325
326    exa_debug_printf("ExaFinishAccess %d\n", index);
327
328    if (--priv->map_count == 0) {
329	assert(priv->map_transfer);
330	exa->pipe->transfer_unmap(exa->pipe, priv->map_transfer);
331	exa->pipe->transfer_destroy(exa->pipe, priv->map_transfer);
332	priv->map_transfer = NULL;
333	pPix->devPrivate.ptr = NULL;
334    }
335
336    exa_debug_printf("ExaFinishAccess %d finished\n", index);
337}
338
339/***********************************************************************
340 * Solid Fills
341 */
342
343static Bool
344ExaPrepareSolid(PixmapPtr pPixmap, int alu, Pixel planeMask, Pixel fg)
345{
346    ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum];
347    modesettingPtr ms = modesettingPTR(pScrn);
348    struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pPixmap);
349    struct exa_context *exa = ms->exa;
350
351    exa_debug_printf("ExaPrepareSolid(0x%x)\n", fg);
352
353    if (!exa->accel)
354	return FALSE;
355
356    if (!exa->pipe)
357	XORG_FALLBACK("accel not enabled");
358
359    if (!priv || !priv->tex)
360	XORG_FALLBACK("%s", !priv ? "!priv" : "!priv->tex");
361
362    if (!EXA_PM_IS_SOLID(&pPixmap->drawable, planeMask))
363	XORG_FALLBACK("planeMask is not solid");
364
365    if (alu != GXcopy)
366	XORG_FALLBACK("not GXcopy");
367
368    if (!exa->scrn->is_format_supported(exa->scrn, priv->tex->format,
369                                        priv->tex->target, 0,
370                                        PIPE_BIND_RENDER_TARGET)) {
371	XORG_FALLBACK("format %s", util_format_name(priv->tex->format));
372    }
373
374    return xorg_solid_bind_state(exa, priv, fg);
375}
376
377static void
378ExaSolid(PixmapPtr pPixmap, int x0, int y0, int x1, int y1)
379{
380    ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum];
381    modesettingPtr ms = modesettingPTR(pScrn);
382    struct exa_context *exa = ms->exa;
383    struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pPixmap);
384
385    exa_debug_printf("\tExaSolid(%d, %d, %d, %d)\n", x0, y0, x1, y1);
386
387    if (x0 == 0 && y0 == 0 &&
388        x1 == pPixmap->drawable.width && y1 == pPixmap->drawable.height) {
389       union pipe_color_union solid_color;
390       solid_color.f[0] = exa->solid_color[0];
391       solid_color.f[1] = exa->solid_color[1];
392       solid_color.f[2] = exa->solid_color[2];
393       solid_color.f[3] = exa->solid_color[3];
394       exa->pipe->clear(exa->pipe, PIPE_CLEAR_COLOR, &solid_color, 0.0, 0);
395       return;
396    }
397
398    xorg_solid(exa, priv, x0, y0, x1, y1) ;
399}
400
401
402static void
403ExaDoneSolid(PixmapPtr pPixmap)
404{
405    ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum];
406    modesettingPtr ms = modesettingPTR(pScrn);
407    struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pPixmap);
408    struct exa_context *exa = ms->exa;
409
410    if (!priv)
411	return;
412
413    exa_debug_printf("ExaDoneSolid\n");
414    xorg_composite_done(exa);
415    exa_debug_printf("ExaDoneSolid done\n");
416}
417
418/***********************************************************************
419 * Copy Blits
420 */
421
422static Bool
423ExaPrepareCopy(PixmapPtr pSrcPixmap, PixmapPtr pDstPixmap, int xdir,
424	       int ydir, int alu, Pixel planeMask)
425{
426    ScrnInfoPtr pScrn = xf86Screens[pDstPixmap->drawable.pScreen->myNum];
427    modesettingPtr ms = modesettingPTR(pScrn);
428    struct exa_context *exa = ms->exa;
429    struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pDstPixmap);
430    struct exa_pixmap_priv *src_priv = exaGetPixmapDriverPrivate(pSrcPixmap);
431
432    exa_debug_printf("ExaPrepareCopy\n");
433
434    if (!exa->accel)
435	return FALSE;
436
437    if (!exa->pipe)
438	XORG_FALLBACK("accel not enabled");
439
440    if (!priv || !priv->tex)
441	XORG_FALLBACK("pDst %s", !priv ? "!priv" : "!priv->tex");
442
443    if (!src_priv || !src_priv->tex)
444	XORG_FALLBACK("pSrc %s", !src_priv ? "!priv" : "!priv->tex");
445
446    if (!EXA_PM_IS_SOLID(&pSrcPixmap->drawable, planeMask))
447	XORG_FALLBACK("planeMask is not solid");
448
449    if (alu != GXcopy)
450	XORG_FALLBACK("alu not GXcopy");
451
452    if (!exa->scrn->is_format_supported(exa->scrn, priv->tex->format,
453                                        priv->tex->target, 0,
454                                        PIPE_BIND_RENDER_TARGET))
455	XORG_FALLBACK("pDst format %s", util_format_name(priv->tex->format));
456
457    if (!exa->scrn->is_format_supported(exa->scrn, src_priv->tex->format,
458                                        src_priv->tex->target, 0,
459                                        PIPE_BIND_SAMPLER_VIEW))
460	XORG_FALLBACK("pSrc format %s", util_format_name(src_priv->tex->format));
461
462    exa->copy.src = src_priv;
463    exa->copy.dst = priv;
464
465    /* XXX this used to use resource_copy_region for same-surface copies,
466     * but they were redefined to not allow overlaps (some of the util code
467     * always assumed this anyway).
468     * Drivers should implement accelerated resource_copy_region or it will
469     * be slow - disable for now.
470     */
471    if (0 && exa->copy.src != exa->copy.dst) {
472       exa->copy.use_surface_copy = TRUE;
473    }
474    else {
475       struct pipe_surface surf_tmpl;
476       exa->copy.use_surface_copy = FALSE;
477
478       if (exa->copy.dst == exa->copy.src)
479          exa->copy.src_texture = renderer_clone_texture( exa->renderer,
480                                                          exa->copy.src->tex );
481       else
482          pipe_resource_reference(&exa->copy.src_texture,
483                                 exa->copy.src->tex);
484
485       memset(&surf_tmpl, 0, sizeof(surf_tmpl));
486       u_surface_default_template(&surf_tmpl, exa->copy.dst->tex,
487                                  PIPE_BIND_RENDER_TARGET);
488       exa->copy.dst_surface =
489          exa->pipe->create_surface(exa->pipe,
490                                    exa->copy.dst->tex,
491                                    &surf_tmpl);
492
493
494       renderer_copy_prepare(exa->renderer,
495                             exa->copy.dst_surface,
496                             exa->copy.src_texture );
497    }
498
499
500    return TRUE;
501}
502
503static void
504ExaCopy(PixmapPtr pDstPixmap, int srcX, int srcY, int dstX, int dstY,
505	int width, int height)
506{
507   ScrnInfoPtr pScrn = xf86Screens[pDstPixmap->drawable.pScreen->myNum];
508   modesettingPtr ms = modesettingPTR(pScrn);
509   struct exa_context *exa = ms->exa;
510   struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pDstPixmap);
511
512   exa_debug_printf("\tExaCopy(srcx=%d, srcy=%d, dstX=%d, dstY=%d, w=%d, h=%d)\n",
513                srcX, srcY, dstX, dstY, width, height);
514
515   debug_assert(priv == exa->copy.dst);
516   (void) priv;
517
518   if (exa->copy.use_surface_copy) {
519      struct pipe_box src_box;
520      u_box_2d(srcX, srcY, width, height, &src_box);
521      exa->pipe->resource_copy_region( exa->pipe,
522                                       exa->copy.dst->tex,
523                                       0,
524                                       dstX, dstY, 0,
525                                       exa->copy.src->tex,
526                                       0, &src_box);
527   }
528   else {
529      renderer_copy_pixmap(exa->renderer,
530                           dstX, dstY,
531                           srcX, srcY,
532                           width, height,
533                           exa->copy.src_texture->width0,
534                           exa->copy.src_texture->height0);
535   }
536}
537
538static void
539ExaDoneCopy(PixmapPtr pPixmap)
540{
541    ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum];
542    modesettingPtr ms = modesettingPTR(pScrn);
543    struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pPixmap);
544    struct exa_context *exa = ms->exa;
545
546    if (!priv)
547	return;
548
549   exa_debug_printf("ExaDoneCopy\n");
550
551   renderer_draw_flush(exa->renderer);
552
553   exa->copy.src = NULL;
554   exa->copy.dst = NULL;
555   pipe_surface_reference(&exa->copy.dst_surface, NULL);
556   pipe_resource_reference(&exa->copy.src_texture, NULL);
557
558   exa_debug_printf("ExaDoneCopy done\n");
559}
560
561
562
563static Bool
564picture_check_formats(struct exa_pixmap_priv *pSrc, PicturePtr pSrcPicture)
565{
566   if (pSrc->picture_format == pSrcPicture->format)
567      return TRUE;
568
569   if (pSrc->picture_format != PICT_a8r8g8b8)
570      return FALSE;
571
572   /* pSrc->picture_format == PICT_a8r8g8b8 */
573   switch (pSrcPicture->format) {
574   case PICT_a8r8g8b8:
575   case PICT_x8r8g8b8:
576   case PICT_a8b8g8r8:
577   case PICT_x8b8g8r8:
578   /* just treat these two as x8... */
579   case PICT_r8g8b8:
580   case PICT_b8g8r8:
581      return TRUE;
582#ifdef PICT_TYPE_BGRA
583   case PICT_b8g8r8a8:
584   case PICT_b8g8r8x8:
585      return FALSE; /* does not support swizzleing the alpha channel yet */
586   case PICT_a2r10g10b10:
587   case PICT_x2r10g10b10:
588   case PICT_a2b10g10r10:
589   case PICT_x2b10g10r10:
590      return FALSE;
591#endif
592   default:
593      return FALSE;
594   }
595   return FALSE;
596}
597
598/***********************************************************************
599 * Composite entrypoints
600 */
601
602static Bool
603ExaCheckComposite(int op,
604		  PicturePtr pSrcPicture, PicturePtr pMaskPicture,
605		  PicturePtr pDstPicture)
606{
607   ScrnInfoPtr pScrn = xf86Screens[pDstPicture->pDrawable->pScreen->myNum];
608   modesettingPtr ms = modesettingPTR(pScrn);
609   struct exa_context *exa = ms->exa;
610   Bool accelerated = exa->accel && xorg_composite_accelerated(op,
611				     pSrcPicture,
612				     pMaskPicture,
613				     pDstPicture);
614
615   exa_debug_printf("ExaCheckComposite(%d, %p, %p, %p) = %d\n",
616                op, pSrcPicture, pMaskPicture, pDstPicture, accelerated);
617
618   return accelerated;
619}
620
621
622static Bool
623ExaPrepareComposite(int op, PicturePtr pSrcPicture,
624		    PicturePtr pMaskPicture, PicturePtr pDstPicture,
625		    PixmapPtr pSrc, PixmapPtr pMask, PixmapPtr pDst)
626{
627   ScrnInfoPtr pScrn = xf86Screens[pDst->drawable.pScreen->myNum];
628   modesettingPtr ms = modesettingPTR(pScrn);
629   struct exa_context *exa = ms->exa;
630   struct exa_pixmap_priv *priv;
631
632   if (!exa->accel)
633       return FALSE;
634
635   exa_debug_printf("ExaPrepareComposite(%d, src=0x%p, mask=0x%p, dst=0x%p)\n",
636                op, pSrcPicture, pMaskPicture, pDstPicture);
637   exa_debug_printf("\tFormats: src(%s), mask(%s), dst(%s)\n",
638                pSrcPicture ? render_format_name(pSrcPicture->format) : "none",
639                pMaskPicture ? render_format_name(pMaskPicture->format) : "none",
640                pDstPicture ? render_format_name(pDstPicture->format) : "none");
641
642   if (!exa->pipe)
643      XORG_FALLBACK("accel not enabled");
644
645   priv = exaGetPixmapDriverPrivate(pDst);
646   if (!priv || !priv->tex)
647      XORG_FALLBACK("pDst %s", !priv ? "!priv" : "!priv->tex");
648
649   if (!exa->scrn->is_format_supported(exa->scrn, priv->tex->format,
650                                       priv->tex->target, 0,
651                                       PIPE_BIND_RENDER_TARGET))
652      XORG_FALLBACK("pDst format: %s", util_format_name(priv->tex->format));
653
654   if (priv->picture_format != pDstPicture->format)
655      XORG_FALLBACK("pDst pic_format: %s != %s",
656                    render_format_name(priv->picture_format),
657                    render_format_name(pDstPicture->format));
658
659   if (pSrc) {
660      priv = exaGetPixmapDriverPrivate(pSrc);
661      if (!priv || !priv->tex)
662         XORG_FALLBACK("pSrc %s", !priv ? "!priv" : "!priv->tex");
663
664      if (!exa->scrn->is_format_supported(exa->scrn, priv->tex->format,
665                                          priv->tex->target, 0,
666                                          PIPE_BIND_SAMPLER_VIEW))
667         XORG_FALLBACK("pSrc format: %s", util_format_name(priv->tex->format));
668
669      if (!picture_check_formats(priv, pSrcPicture))
670         XORG_FALLBACK("pSrc pic_format: %s != %s",
671                       render_format_name(priv->picture_format),
672                       render_format_name(pSrcPicture->format));
673
674   }
675
676   if (pMask) {
677      priv = exaGetPixmapDriverPrivate(pMask);
678      if (!priv || !priv->tex)
679         XORG_FALLBACK("pMask %s", !priv ? "!priv" : "!priv->tex");
680
681      if (!exa->scrn->is_format_supported(exa->scrn, priv->tex->format,
682                                          priv->tex->target, 0,
683                                          PIPE_BIND_SAMPLER_VIEW))
684         XORG_FALLBACK("pMask format: %s", util_format_name(priv->tex->format));
685
686      if (!picture_check_formats(priv, pMaskPicture))
687         XORG_FALLBACK("pMask pic_format: %s != %s",
688                       render_format_name(priv->picture_format),
689                       render_format_name(pMaskPicture->format));
690   }
691
692   return xorg_composite_bind_state(exa, op, pSrcPicture, pMaskPicture,
693                                    pDstPicture,
694                                    pSrc ? exaGetPixmapDriverPrivate(pSrc) : NULL,
695                                    pMask ? exaGetPixmapDriverPrivate(pMask) : NULL,
696                                    exaGetPixmapDriverPrivate(pDst));
697}
698
699static void
700ExaComposite(PixmapPtr pDst, int srcX, int srcY, int maskX, int maskY,
701	     int dstX, int dstY, int width, int height)
702{
703   ScrnInfoPtr pScrn = xf86Screens[pDst->drawable.pScreen->myNum];
704   modesettingPtr ms = modesettingPTR(pScrn);
705   struct exa_context *exa = ms->exa;
706   struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pDst);
707
708   exa_debug_printf("\tExaComposite(src[%d,%d], mask=[%d, %d], dst=[%d, %d], dim=[%d, %d])\n",
709                srcX, srcY, maskX, maskY, dstX, dstY, width, height);
710   exa_debug_printf("\t   Num bound samplers = %d\n",
711                exa->num_bound_samplers);
712
713   xorg_composite(exa, priv, srcX, srcY, maskX, maskY,
714                  dstX, dstY, width, height);
715}
716
717
718
719static void
720ExaDoneComposite(PixmapPtr pPixmap)
721{
722   ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum];
723   modesettingPtr ms = modesettingPTR(pScrn);
724   struct exa_context *exa = ms->exa;
725
726   xorg_composite_done(exa);
727}
728
729
730/***********************************************************************
731 * Pixmaps
732 */
733
734static void *
735ExaCreatePixmap(ScreenPtr pScreen, int size, int align)
736{
737    struct exa_pixmap_priv *priv;
738
739    priv = calloc(1, sizeof(struct exa_pixmap_priv));
740    if (!priv)
741	return NULL;
742
743    return priv;
744}
745
746static void
747ExaDestroyPixmap(ScreenPtr pScreen, void *dPriv)
748{
749    struct exa_pixmap_priv *priv = (struct exa_pixmap_priv *)dPriv;
750
751    if (!priv)
752	return;
753
754    pipe_resource_reference(&priv->tex, NULL);
755
756    free(priv);
757}
758
759static Bool
760ExaPixmapIsOffscreen(PixmapPtr pPixmap)
761{
762    struct exa_pixmap_priv *priv;
763
764    priv = exaGetPixmapDriverPrivate(pPixmap);
765
766    if (!priv)
767	return FALSE;
768
769    if (priv->tex)
770	return TRUE;
771
772    return FALSE;
773}
774
775int
776xorg_exa_set_displayed_usage(PixmapPtr pPixmap)
777{
778    struct exa_pixmap_priv *priv;
779    priv = exaGetPixmapDriverPrivate(pPixmap);
780
781    if (!priv) {
782	FatalError("NO PIXMAP PRIVATE\n");
783	return 0;
784    }
785
786    priv->flags |= PIPE_BIND_SCANOUT;
787
788    return 0;
789}
790
791int
792xorg_exa_set_shared_usage(PixmapPtr pPixmap)
793{
794    struct exa_pixmap_priv *priv;
795    priv = exaGetPixmapDriverPrivate(pPixmap);
796
797    if (!priv) {
798	FatalError("NO PIXMAP PRIVATE\n");
799	return 0;
800    }
801
802    priv->flags |= PIPE_BIND_SHARED;
803
804    return 0;
805}
806
807
808
809static Bool
810size_match( int width, int tex_width )
811{
812#if ROUND_UP_TEXTURES
813   if (width > tex_width)
814      return FALSE;
815
816   if (width * 2 < tex_width)
817      return FALSE;
818
819   return TRUE;
820#else
821   return width == tex_width;
822#endif
823}
824
825static Bool
826ExaModifyPixmapHeader(PixmapPtr pPixmap, int width, int height,
827		      int depth, int bitsPerPixel, int devKind,
828		      pointer pPixData)
829{
830    ScreenPtr pScreen = pPixmap->drawable.pScreen;
831    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
832    struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pPixmap);
833    modesettingPtr ms = modesettingPTR(pScrn);
834    struct exa_context *exa = ms->exa;
835
836    if (!priv || pPixData)
837	return FALSE;
838
839    if (0) {
840       debug_printf("%s pixmap %p sz %dx%dx%d devKind %d\n",
841                    __FUNCTION__, pPixmap, width, height, bitsPerPixel, devKind);
842
843       if (priv->tex)
844          debug_printf("  ==> old texture %dx%d\n",
845                       priv->tex->width0,
846                       priv->tex->height0);
847    }
848
849
850    if (depth <= 0)
851	depth = pPixmap->drawable.depth;
852
853    if (bitsPerPixel <= 0)
854	bitsPerPixel = pPixmap->drawable.bitsPerPixel;
855
856    if (width <= 0)
857	width = pPixmap->drawable.width;
858
859    if (height <= 0)
860	height = pPixmap->drawable.height;
861
862    if (width <= 0 || height <= 0 || depth <= 0)
863	return FALSE;
864
865    miModifyPixmapHeader(pPixmap, width, height, depth,
866			     bitsPerPixel, devKind, NULL);
867
868    priv->width = width;
869    priv->height = height;
870
871    /* Deal with screen resize */
872    if ((exa->accel || priv->flags) &&
873        (!priv->tex ||
874         !size_match(width, priv->tex->width0) ||
875         !size_match(height, priv->tex->height0) ||
876         priv->tex_flags != priv->flags)) {
877	struct pipe_resource *texture = NULL;
878	struct pipe_resource template;
879
880	memset(&template, 0, sizeof(template));
881	template.target = PIPE_TEXTURE_2D;
882	exa_get_pipe_format(depth, &template.format, &bitsPerPixel, &priv->picture_format);
883        if (ROUND_UP_TEXTURES && priv->flags == 0) {
884           template.width0 = util_next_power_of_two(width);
885           template.height0 = util_next_power_of_two(height);
886        }
887        else {
888           template.width0 = width;
889           template.height0 = height;
890        }
891
892	template.depth0 = 1;
893	template.array_size = 1;
894	template.last_level = 0;
895	template.bind = PIPE_BIND_RENDER_TARGET | priv->flags;
896	priv->tex_flags = priv->flags;
897	texture = exa->scrn->resource_create(exa->scrn, &template);
898
899	if (priv->tex) {
900            struct pipe_box src_box;
901            u_box_origin_2d(min(width, texture->width0),
902                            min(height, texture->height0),
903                            &src_box);
904            exa->pipe->resource_copy_region(exa->pipe, texture,
905                                            0, 0, 0, 0,
906                                            priv->tex,
907                                            0, &src_box);
908	}
909
910	pipe_resource_reference(&priv->tex, texture);
911	/* the texture we create has one reference */
912	pipe_resource_reference(&texture, NULL);
913    }
914
915    return TRUE;
916}
917
918struct pipe_resource *
919xorg_exa_get_texture(PixmapPtr pPixmap)
920{
921   struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pPixmap);
922   struct pipe_resource *tex = NULL;
923   pipe_resource_reference(&tex, priv->tex);
924   return tex;
925}
926
927Bool
928xorg_exa_set_texture(PixmapPtr pPixmap, struct  pipe_resource *tex)
929{
930    struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pPixmap);
931
932    int mask = PIPE_BIND_SHARED | PIPE_BIND_SCANOUT;
933
934    if (!priv)
935	return FALSE;
936
937    if (pPixmap->drawable.width != tex->width0 ||
938	pPixmap->drawable.height != tex->height0)
939	return FALSE;
940
941    pipe_resource_reference(&priv->tex, tex);
942    priv->tex_flags = tex->bind & mask;
943
944    return TRUE;
945}
946
947struct pipe_resource *
948xorg_exa_create_root_texture(ScrnInfoPtr pScrn,
949			     int width, int height,
950			     int depth, int bitsPerPixel)
951{
952    modesettingPtr ms = modesettingPTR(pScrn);
953    struct exa_context *exa = ms->exa;
954    struct pipe_resource template;
955    int dummy;
956
957    memset(&template, 0, sizeof(template));
958    template.target = PIPE_TEXTURE_2D;
959    exa_get_pipe_format(depth, &template.format, &bitsPerPixel, &dummy);
960    template.width0 = width;
961    template.height0 = height;
962    template.depth0 = 1;
963    template.array_size = 1;
964    template.last_level = 0;
965    template.bind |= PIPE_BIND_RENDER_TARGET;
966    template.bind |= PIPE_BIND_SCANOUT;
967    template.bind |= PIPE_BIND_SHARED;
968
969    return exa->scrn->resource_create(exa->scrn, &template);
970}
971
972void
973xorg_exa_close(ScrnInfoPtr pScrn)
974{
975   modesettingPtr ms = modesettingPTR(pScrn);
976   struct exa_context *exa = ms->exa;
977
978   pipe_sampler_view_reference(&exa->bound_sampler_views[0], NULL);
979   pipe_sampler_view_reference(&exa->bound_sampler_views[1], NULL);
980
981   renderer_destroy(exa->renderer);
982
983   xorg_exa_finish(exa);
984
985   if (exa->pipe)
986      exa->pipe->destroy(exa->pipe);
987   exa->pipe = NULL;
988   /* Since this was shared be proper with the pointer */
989   ms->ctx = NULL;
990
991   exaDriverFini(pScrn->pScreen);
992   free(exa);
993   ms->exa = NULL;
994}
995
996void *
997xorg_exa_init(ScrnInfoPtr pScrn, Bool accel)
998{
999   modesettingPtr ms = modesettingPTR(pScrn);
1000   struct exa_context *exa;
1001   ExaDriverPtr pExa;
1002   CustomizerPtr cust = ms->cust;
1003
1004   exa = calloc(1, sizeof(struct exa_context));
1005   if (!exa)
1006      return NULL;
1007
1008   pExa = exaDriverAlloc();
1009   if (!pExa) {
1010      goto out_err;
1011   }
1012
1013   memset(pExa, 0, sizeof(*pExa));
1014
1015   pExa->exa_major         = 2;
1016   pExa->exa_minor         = 2;
1017   pExa->memoryBase        = 0;
1018   pExa->memorySize        = 0;
1019   pExa->offScreenBase     = 0;
1020   pExa->pixmapOffsetAlign = 0;
1021   pExa->pixmapPitchAlign  = 1;
1022   pExa->flags             = EXA_OFFSCREEN_PIXMAPS | EXA_HANDLES_PIXMAPS;
1023#ifdef EXA_SUPPORTS_PREPARE_AUX
1024   pExa->flags            |= EXA_SUPPORTS_PREPARE_AUX;
1025#endif
1026#ifdef EXA_MIXED_PIXMAPS
1027   pExa->flags            |= EXA_MIXED_PIXMAPS;
1028#endif
1029   pExa->maxX              = 8191; /* FIXME */
1030   pExa->maxY              = 8191; /* FIXME */
1031
1032   pExa->WaitMarker         = ExaWaitMarker;
1033   pExa->MarkSync           = ExaMarkSync;
1034   pExa->PrepareSolid       = ExaPrepareSolid;
1035   pExa->Solid              = ExaSolid;
1036   pExa->DoneSolid          = ExaDoneSolid;
1037   pExa->PrepareCopy        = ExaPrepareCopy;
1038   pExa->Copy               = ExaCopy;
1039   pExa->DoneCopy           = ExaDoneCopy;
1040   pExa->CheckComposite     = ExaCheckComposite;
1041   pExa->PrepareComposite   = ExaPrepareComposite;
1042   pExa->Composite          = ExaComposite;
1043   pExa->DoneComposite      = ExaDoneComposite;
1044   pExa->PixmapIsOffscreen  = ExaPixmapIsOffscreen;
1045   pExa->DownloadFromScreen = ExaDownloadFromScreen;
1046   pExa->UploadToScreen     = ExaUploadToScreen;
1047   pExa->PrepareAccess      = ExaPrepareAccess;
1048   pExa->FinishAccess       = ExaFinishAccess;
1049   pExa->CreatePixmap       = ExaCreatePixmap;
1050   pExa->DestroyPixmap      = ExaDestroyPixmap;
1051   pExa->ModifyPixmapHeader = ExaModifyPixmapHeader;
1052
1053   if (!exaDriverInit(pScrn->pScreen, pExa)) {
1054      goto out_err;
1055   }
1056
1057   exa->scrn = ms->screen;
1058   exa->pipe = exa->scrn->context_create(exa->scrn, NULL);
1059   if (exa->pipe == NULL)
1060      goto out_err;
1061
1062   /* Share context with DRI */
1063   ms->ctx = exa->pipe;
1064   if (cust && cust->winsys_context_throttle)
1065       cust->winsys_context_throttle(cust, ms->ctx, THROTTLE_RENDER);
1066
1067   exa->renderer = renderer_create(exa->pipe);
1068   exa->accel = accel;
1069
1070   return (void *)exa;
1071
1072out_err:
1073   xorg_exa_close(pScrn);
1074   free(exa);
1075
1076   return NULL;
1077}
1078
1079struct pipe_surface *
1080xorg_gpu_surface(struct pipe_context *pipe, struct exa_pixmap_priv *priv)
1081{
1082   struct pipe_surface surf_tmpl;
1083   memset(&surf_tmpl, 0, sizeof(surf_tmpl));
1084   u_surface_default_template(&surf_tmpl, priv->tex,
1085                              PIPE_BIND_RENDER_TARGET);
1086
1087   return pipe->create_surface(pipe, priv->tex, &surf_tmpl);
1088
1089}
1090
1091void xorg_exa_flush(struct exa_context *exa,
1092                    struct pipe_fence_handle **fence)
1093{
1094   exa->pipe->flush(exa->pipe, fence);
1095}
1096
1097void xorg_exa_finish(struct exa_context *exa)
1098{
1099   struct pipe_fence_handle *fence = NULL;
1100
1101   xorg_exa_flush(exa, &fence);
1102
1103   exa->pipe->screen->fence_finish(exa->pipe->screen, fence,
1104                                   PIPE_TIMEOUT_INFINITE);
1105   exa->pipe->screen->fence_reference(exa->pipe->screen, &fence, NULL);
1106}
1107
1108