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