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