update to 9.0.3
[profile/ivi/mesa.git] / src / gallium / state_trackers / xorg / xorg_exa.c
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
54 static INLINE void
55 exa_debug_printf(const char *format, ...) _util_printf_format(1,2);
56
57 static INLINE void
58 exa_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  */
73 struct render_format_str {
74    int format;
75    const char *name;
76 };
77 static 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 };
123 static 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
133 static void
134 exa_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
177 static void
178 ExaWaitMarker(ScreenPtr pScreen, int marker)
179 {
180    /* Nothing to do, handled in the PrepareAccess hook */
181 }
182
183 static int
184 ExaMarkSync(ScreenPtr pScreen)
185 {
186    return 1;
187 }
188
189
190 /***********************************************************************
191  * Screen upload/download
192  */
193
194 static Bool
195 ExaDownloadFromScreen(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 = xf86ScreenToScrn(pScreen);
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
226 static Bool
227 ExaUploadToScreen(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 = xf86ScreenToScrn(pScreen);
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
258 static Bool
259 ExaPrepareAccess(PixmapPtr pPix, int index)
260 {
261     ScreenPtr pScreen = pPix->drawable.pScreen;
262     ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
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
310 static void
311 ExaFinishAccess(PixmapPtr pPix, int index)
312 {
313     ScreenPtr pScreen = pPix->drawable.pScreen;
314     ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
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
343 static Bool
344 ExaPrepareSolid(PixmapPtr pPixmap, int alu, Pixel planeMask, Pixel fg)
345 {
346     ScrnInfoPtr pScrn = xf86ScreenToScrn(pPixmap->drawable.pScreen);
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
377 static void
378 ExaSolid(PixmapPtr pPixmap, int x0, int y0, int x1, int y1)
379 {
380     ScrnInfoPtr pScrn = xf86ScreenToScrn(pPixmap->drawable.pScreen);
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
402 static void
403 ExaDoneSolid(PixmapPtr pPixmap)
404 {
405     ScrnInfoPtr pScrn = xf86ScreenToScrn(pPixmap->drawable.pScreen);
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
422 static Bool
423 ExaPrepareCopy(PixmapPtr pSrcPixmap, PixmapPtr pDstPixmap, int xdir,
424                int ydir, int alu, Pixel planeMask)
425 {
426     ScrnInfoPtr pScrn = xf86ScreenToScrn(pDstPixmap->drawable.pScreen);
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     return TRUE;
466 }
467
468 static void
469 ExaCopy(PixmapPtr pDstPixmap, int srcX, int srcY, int dstX, int dstY,
470         int width, int height)
471 {
472    ScrnInfoPtr pScrn = xf86ScreenToScrn(pDstPixmap->drawable.pScreen);
473    modesettingPtr ms = modesettingPTR(pScrn);
474    struct exa_context *exa = ms->exa;
475    struct pipe_box src_box;
476
477    exa_debug_printf("\tExaCopy(srcx=%d, srcy=%d, dstX=%d, dstY=%d, w=%d, h=%d)\n",
478                 srcX, srcY, dstX, dstY, width, height);
479
480    debug_assert(exaGetPixmapDriverPrivate(pDstPixmap) == exa->copy.dst);
481
482    u_box_2d(srcX, srcY, width, height, &src_box);
483
484    /* If source and destination overlap, we have to copy to/from a scratch
485     * pixmap.
486     */
487    if (exa->copy.dst == exa->copy.src &&
488        !((dstX + width) < srcX || dstX > (srcX + width) ||
489          (dstY + height) < srcY || dstY > (srcY + height))) {
490       struct exa_pixmap_priv *tmp_priv;
491
492       if (!exa->copy.tmp_pix) {
493          exa->copy.tmp_pix = pScrn->pScreen->CreatePixmap(pScrn->pScreen,
494                                                          pDstPixmap->drawable.width,
495                                                          pDstPixmap->drawable.height,
496                                                          pDstPixmap->drawable.depth,
497                                                          pDstPixmap->drawable.width);
498          exaMoveInPixmap(exa->copy.tmp_pix);
499       }
500
501       tmp_priv = exaGetPixmapDriverPrivate(exa->copy.tmp_pix);
502
503       exa->pipe->resource_copy_region( exa->pipe,
504                                        tmp_priv->tex,
505                                        0,
506                                        srcX, srcY, 0,
507                                        exa->copy.src->tex,
508                                        0, &src_box);
509       exa->pipe->resource_copy_region( exa->pipe,
510                                        exa->copy.dst->tex,
511                                        0,
512                                        dstX, dstY, 0,
513                                        tmp_priv->tex,
514                                        0, &src_box);
515    } else
516       exa->pipe->resource_copy_region( exa->pipe,
517                                        exa->copy.dst->tex,
518                                        0,
519                                        dstX, dstY, 0,
520                                        exa->copy.src->tex,
521                                        0, &src_box);
522 }
523
524 static void
525 ExaDoneCopy(PixmapPtr pPixmap)
526 {
527     ScrnInfoPtr pScrn = xf86ScreenToScrn(pPixmap->drawable.pScreen);
528     modesettingPtr ms = modesettingPTR(pScrn);
529     struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pPixmap);
530     struct exa_context *exa = ms->exa;
531
532     if (!priv)
533         return;
534
535    exa_debug_printf("ExaDoneCopy\n");
536
537    if (exa->copy.tmp_pix) {
538       pScrn->pScreen->DestroyPixmap(exa->copy.tmp_pix);
539       exa->copy.tmp_pix = NULL;
540    }
541    exa->copy.src = NULL;
542    exa->copy.dst = NULL;
543
544    exa_debug_printf("ExaDoneCopy done\n");
545 }
546
547
548
549 static Bool
550 picture_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
588 static Bool
589 ExaCheckComposite(int op,
590                   PicturePtr pSrcPicture, PicturePtr pMaskPicture,
591                   PicturePtr pDstPicture)
592 {
593    ScrnInfoPtr pScrn = xf86ScreenToScrn(pDstPicture->pDrawable->pScreen);
594    modesettingPtr ms = modesettingPTR(pScrn);
595    struct exa_context *exa = ms->exa;
596    Bool accelerated = exa->accel && xorg_composite_accelerated(op,
597                                      pSrcPicture,
598                                      pMaskPicture,
599                                      pDstPicture);
600
601    exa_debug_printf("ExaCheckComposite(%d, %p, %p, %p) = %d\n",
602                 op, pSrcPicture, pMaskPicture, pDstPicture, accelerated);
603
604    return accelerated;
605 }
606
607
608 static Bool
609 ExaPrepareComposite(int op, PicturePtr pSrcPicture,
610                     PicturePtr pMaskPicture, PicturePtr pDstPicture,
611                     PixmapPtr pSrc, PixmapPtr pMask, PixmapPtr pDst)
612 {
613    ScrnInfoPtr pScrn = xf86ScreenToScrn(pDst->drawable.pScreen);
614    modesettingPtr ms = modesettingPTR(pScrn);
615    struct exa_context *exa = ms->exa;
616    struct exa_pixmap_priv *priv;
617
618    if (!exa->accel)
619        return FALSE;
620
621    exa_debug_printf("ExaPrepareComposite(%d, src=0x%p, mask=0x%p, dst=0x%p)\n",
622                 op, pSrcPicture, pMaskPicture, pDstPicture);
623    exa_debug_printf("\tFormats: src(%s), mask(%s), dst(%s)\n",
624                 pSrcPicture ? render_format_name(pSrcPicture->format) : "none",
625                 pMaskPicture ? render_format_name(pMaskPicture->format) : "none",
626                 pDstPicture ? render_format_name(pDstPicture->format) : "none");
627
628    if (!exa->pipe)
629       XORG_FALLBACK("accel not enabled");
630
631    priv = exaGetPixmapDriverPrivate(pDst);
632    if (!priv || !priv->tex)
633       XORG_FALLBACK("pDst %s", !priv ? "!priv" : "!priv->tex");
634
635    if (!exa->scrn->is_format_supported(exa->scrn, priv->tex->format,
636                                        priv->tex->target, 0,
637                                        PIPE_BIND_RENDER_TARGET))
638       XORG_FALLBACK("pDst format: %s", util_format_name(priv->tex->format));
639
640    if (priv->picture_format != pDstPicture->format)
641       XORG_FALLBACK("pDst pic_format: %s != %s",
642                     render_format_name(priv->picture_format),
643                     render_format_name(pDstPicture->format));
644
645    if (pSrc) {
646       priv = exaGetPixmapDriverPrivate(pSrc);
647       if (!priv || !priv->tex)
648          XORG_FALLBACK("pSrc %s", !priv ? "!priv" : "!priv->tex");
649
650       if (!exa->scrn->is_format_supported(exa->scrn, priv->tex->format,
651                                           priv->tex->target, 0,
652                                           PIPE_BIND_SAMPLER_VIEW))
653          XORG_FALLBACK("pSrc format: %s", util_format_name(priv->tex->format));
654
655       if (!picture_check_formats(priv, pSrcPicture))
656          XORG_FALLBACK("pSrc pic_format: %s != %s",
657                        render_format_name(priv->picture_format),
658                        render_format_name(pSrcPicture->format));
659
660    }
661
662    if (pMask) {
663       priv = exaGetPixmapDriverPrivate(pMask);
664       if (!priv || !priv->tex)
665          XORG_FALLBACK("pMask %s", !priv ? "!priv" : "!priv->tex");
666
667       if (!exa->scrn->is_format_supported(exa->scrn, priv->tex->format,
668                                           priv->tex->target, 0,
669                                           PIPE_BIND_SAMPLER_VIEW))
670          XORG_FALLBACK("pMask format: %s", util_format_name(priv->tex->format));
671
672       if (!picture_check_formats(priv, pMaskPicture))
673          XORG_FALLBACK("pMask pic_format: %s != %s",
674                        render_format_name(priv->picture_format),
675                        render_format_name(pMaskPicture->format));
676    }
677
678    return xorg_composite_bind_state(exa, op, pSrcPicture, pMaskPicture,
679                                     pDstPicture,
680                                     pSrc ? exaGetPixmapDriverPrivate(pSrc) : NULL,
681                                     pMask ? exaGetPixmapDriverPrivate(pMask) : NULL,
682                                     exaGetPixmapDriverPrivate(pDst));
683 }
684
685 static void
686 ExaComposite(PixmapPtr pDst, int srcX, int srcY, int maskX, int maskY,
687              int dstX, int dstY, int width, int height)
688 {
689    ScrnInfoPtr pScrn = xf86ScreenToScrn(pDst->drawable.pScreen);
690    modesettingPtr ms = modesettingPTR(pScrn);
691    struct exa_context *exa = ms->exa;
692    struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pDst);
693
694    exa_debug_printf("\tExaComposite(src[%d,%d], mask=[%d, %d], dst=[%d, %d], dim=[%d, %d])\n",
695                 srcX, srcY, maskX, maskY, dstX, dstY, width, height);
696    exa_debug_printf("\t   Num bound samplers = %d\n",
697                 exa->num_bound_samplers);
698
699    xorg_composite(exa, priv, srcX, srcY, maskX, maskY,
700                   dstX, dstY, width, height);
701 }
702
703
704
705 static void
706 ExaDoneComposite(PixmapPtr pPixmap)
707 {
708    ScrnInfoPtr pScrn = xf86ScreenToScrn(pPixmap->drawable.pScreen);
709    modesettingPtr ms = modesettingPTR(pScrn);
710    struct exa_context *exa = ms->exa;
711
712    xorg_composite_done(exa);
713 }
714
715
716 /***********************************************************************
717  * Pixmaps
718  */
719
720 static void *
721 ExaCreatePixmap(ScreenPtr pScreen, int size, int align)
722 {
723     struct exa_pixmap_priv *priv;
724
725     priv = calloc(1, sizeof(struct exa_pixmap_priv));
726     if (!priv)
727         return NULL;
728
729     return priv;
730 }
731
732 static void
733 ExaDestroyPixmap(ScreenPtr pScreen, void *dPriv)
734 {
735     struct exa_pixmap_priv *priv = (struct exa_pixmap_priv *)dPriv;
736
737     if (!priv)
738         return;
739
740     pipe_resource_reference(&priv->tex, NULL);
741
742     free(priv);
743 }
744
745 static Bool
746 ExaPixmapIsOffscreen(PixmapPtr pPixmap)
747 {
748     struct exa_pixmap_priv *priv;
749
750     priv = exaGetPixmapDriverPrivate(pPixmap);
751
752     if (!priv)
753         return FALSE;
754
755     if (priv->tex)
756         return TRUE;
757
758     return FALSE;
759 }
760
761 int
762 xorg_exa_set_displayed_usage(PixmapPtr pPixmap)
763 {
764     struct exa_pixmap_priv *priv;
765     priv = exaGetPixmapDriverPrivate(pPixmap);
766
767     if (!priv) {
768         FatalError("NO PIXMAP PRIVATE\n");
769         return 0;
770     }
771
772     priv->flags |= PIPE_BIND_SCANOUT;
773
774     return 0;
775 }
776
777 int
778 xorg_exa_set_shared_usage(PixmapPtr pPixmap)
779 {
780     struct exa_pixmap_priv *priv;
781     priv = exaGetPixmapDriverPrivate(pPixmap);
782
783     if (!priv) {
784         FatalError("NO PIXMAP PRIVATE\n");
785         return 0;
786     }
787
788     priv->flags |= PIPE_BIND_SHARED;
789
790     return 0;
791 }
792
793
794
795 static Bool
796 size_match( int width, int tex_width )
797 {
798 #if ROUND_UP_TEXTURES
799    if (width > tex_width)
800       return FALSE;
801
802    if (width * 2 < tex_width)
803       return FALSE;
804
805    return TRUE;
806 #else
807    return width == tex_width;
808 #endif
809 }
810
811 static Bool
812 ExaModifyPixmapHeader(PixmapPtr pPixmap, int width, int height,
813                       int depth, int bitsPerPixel, int devKind,
814                       pointer pPixData)
815 {
816     ScreenPtr pScreen = pPixmap->drawable.pScreen;
817     ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
818     struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pPixmap);
819     modesettingPtr ms = modesettingPTR(pScrn);
820     struct exa_context *exa = ms->exa;
821
822     if (!priv || pPixData)
823         return FALSE;
824
825     if (0) {
826        debug_printf("%s pixmap %p sz %dx%dx%d devKind %d\n",
827                     __FUNCTION__, pPixmap, width, height, bitsPerPixel, devKind);
828        
829        if (priv->tex)
830           debug_printf("  ==> old texture %dx%d\n",
831                        priv->tex->width0, 
832                        priv->tex->height0);
833     }
834
835
836     if (depth <= 0)
837         depth = pPixmap->drawable.depth;
838
839     if (bitsPerPixel <= 0)
840         bitsPerPixel = pPixmap->drawable.bitsPerPixel;
841
842     if (width <= 0)
843         width = pPixmap->drawable.width;
844
845     if (height <= 0)
846         height = pPixmap->drawable.height;
847
848     if (width <= 0 || height <= 0 || depth <= 0)
849         return FALSE;
850
851     miModifyPixmapHeader(pPixmap, width, height, depth,
852                              bitsPerPixel, devKind, NULL);
853
854     priv->width = width;
855     priv->height = height;
856
857     /* Deal with screen resize */
858     if ((exa->accel || priv->flags) &&
859         (!priv->tex ||
860          !size_match(width, priv->tex->width0) ||
861          !size_match(height, priv->tex->height0) ||
862          priv->tex_flags != priv->flags)) {
863         struct pipe_resource *texture = NULL;
864         struct pipe_resource template;
865
866         memset(&template, 0, sizeof(template));
867         template.target = PIPE_TEXTURE_2D;
868         exa_get_pipe_format(depth, &template.format, &bitsPerPixel, &priv->picture_format);
869         if (ROUND_UP_TEXTURES && priv->flags == 0) {
870            template.width0 = util_next_power_of_two(width);
871            template.height0 = util_next_power_of_two(height);
872         }
873         else {
874            template.width0 = width;
875            template.height0 = height;
876         }
877
878         template.depth0 = 1;
879         template.array_size = 1;
880         template.last_level = 0;
881         template.bind = PIPE_BIND_RENDER_TARGET | priv->flags;
882         priv->tex_flags = priv->flags;
883         texture = exa->scrn->resource_create(exa->scrn, &template);
884
885         if (priv->tex) {
886             struct pipe_box src_box;
887             u_box_origin_2d(min(width, texture->width0),
888                             min(height, texture->height0),
889                             &src_box);
890             exa->pipe->resource_copy_region(exa->pipe, texture,
891                                             0, 0, 0, 0,
892                                             priv->tex,
893                                             0, &src_box);
894         }
895
896         pipe_resource_reference(&priv->tex, texture);
897         /* the texture we create has one reference */
898         pipe_resource_reference(&texture, NULL);
899     }
900
901     return TRUE;
902 }
903
904 struct pipe_resource *
905 xorg_exa_get_texture(PixmapPtr pPixmap)
906 {
907    struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pPixmap);
908    struct pipe_resource *tex = NULL;
909    pipe_resource_reference(&tex, priv->tex);
910    return tex;
911 }
912
913 Bool
914 xorg_exa_set_texture(PixmapPtr pPixmap, struct  pipe_resource *tex)
915 {
916     struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pPixmap);
917
918     int mask = PIPE_BIND_SHARED | PIPE_BIND_SCANOUT;
919
920     if (!priv)
921         return FALSE;
922
923     if (pPixmap->drawable.width != tex->width0 ||
924         pPixmap->drawable.height != tex->height0)
925         return FALSE;
926
927     pipe_resource_reference(&priv->tex, tex);
928     priv->tex_flags = tex->bind & mask;
929
930     return TRUE;
931 }
932
933 struct pipe_resource *
934 xorg_exa_create_root_texture(ScrnInfoPtr pScrn,
935                              int width, int height,
936                              int depth, int bitsPerPixel)
937 {
938     modesettingPtr ms = modesettingPTR(pScrn);
939     struct exa_context *exa = ms->exa;
940     struct pipe_resource template;
941     int dummy;
942
943     memset(&template, 0, sizeof(template));
944     template.target = PIPE_TEXTURE_2D;
945     exa_get_pipe_format(depth, &template.format, &bitsPerPixel, &dummy);
946     template.width0 = width;
947     template.height0 = height;
948     template.depth0 = 1;
949     template.array_size = 1;
950     template.last_level = 0;
951     template.bind |= PIPE_BIND_RENDER_TARGET;
952     template.bind |= PIPE_BIND_SCANOUT;
953     template.bind |= PIPE_BIND_SHARED;
954
955     return exa->scrn->resource_create(exa->scrn, &template);
956 }
957
958 void
959 xorg_exa_close(ScrnInfoPtr pScrn)
960 {
961    modesettingPtr ms = modesettingPTR(pScrn);
962    struct exa_context *exa = ms->exa;
963
964    pipe_sampler_view_reference(&exa->bound_sampler_views[0], NULL);
965    pipe_sampler_view_reference(&exa->bound_sampler_views[1], NULL);
966
967    renderer_destroy(exa->renderer);
968
969    xorg_exa_finish(exa);
970
971    if (exa->pipe)
972       exa->pipe->destroy(exa->pipe);
973    exa->pipe = NULL;
974    /* Since this was shared be proper with the pointer */
975    ms->ctx = NULL;
976
977    exaDriverFini(pScrn->pScreen);
978    free(exa);
979    ms->exa = NULL;
980 }
981
982 void *
983 xorg_exa_init(ScrnInfoPtr pScrn, Bool accel)
984 {
985    modesettingPtr ms = modesettingPTR(pScrn);
986    struct exa_context *exa;
987    ExaDriverPtr pExa;
988    CustomizerPtr cust = ms->cust;
989
990    exa = calloc(1, sizeof(struct exa_context));
991    if (!exa)
992       return NULL;
993
994    exa->scrn = ms->screen;
995    exa->pipe = exa->scrn->context_create(exa->scrn, NULL);
996    if (exa->pipe == NULL)
997       goto out_err;
998
999    pExa = exaDriverAlloc();
1000    if (!pExa) {
1001       goto out_err;
1002    }
1003
1004    pExa->exa_major         = 2;
1005    pExa->exa_minor         = 2;
1006    pExa->memoryBase        = 0;
1007    pExa->memorySize        = 0;
1008    pExa->offScreenBase     = 0;
1009    pExa->pixmapOffsetAlign = 0;
1010    pExa->pixmapPitchAlign  = 1;
1011    pExa->flags             = EXA_OFFSCREEN_PIXMAPS | EXA_HANDLES_PIXMAPS;
1012 #ifdef EXA_SUPPORTS_PREPARE_AUX
1013    pExa->flags            |= EXA_SUPPORTS_PREPARE_AUX;
1014 #endif
1015 #ifdef EXA_MIXED_PIXMAPS
1016    pExa->flags            |= EXA_MIXED_PIXMAPS;
1017 #endif
1018
1019    pExa->maxX = pExa->maxY =
1020    1 << (exa->scrn->get_param(exa->scrn, PIPE_CAP_MAX_TEXTURE_2D_LEVELS) - 1);
1021
1022    pExa->WaitMarker         = ExaWaitMarker;
1023    pExa->MarkSync           = ExaMarkSync;
1024    pExa->PrepareSolid       = ExaPrepareSolid;
1025    pExa->Solid              = ExaSolid;
1026    pExa->DoneSolid          = ExaDoneSolid;
1027    pExa->PrepareCopy        = ExaPrepareCopy;
1028    pExa->Copy               = ExaCopy;
1029    pExa->DoneCopy           = ExaDoneCopy;
1030    pExa->CheckComposite     = ExaCheckComposite;
1031    pExa->PrepareComposite   = ExaPrepareComposite;
1032    pExa->Composite          = ExaComposite;
1033    pExa->DoneComposite      = ExaDoneComposite;
1034    pExa->PixmapIsOffscreen  = ExaPixmapIsOffscreen;
1035    pExa->DownloadFromScreen = ExaDownloadFromScreen;
1036    pExa->UploadToScreen     = ExaUploadToScreen;
1037    pExa->PrepareAccess      = ExaPrepareAccess;
1038    pExa->FinishAccess       = ExaFinishAccess;
1039    pExa->CreatePixmap       = ExaCreatePixmap;
1040    pExa->DestroyPixmap      = ExaDestroyPixmap;
1041    pExa->ModifyPixmapHeader = ExaModifyPixmapHeader;
1042
1043    if (!exaDriverInit(pScrn->pScreen, pExa)) {
1044       goto out_err;
1045    }
1046
1047    /* Share context with DRI */
1048    ms->ctx = exa->pipe;
1049    if (cust && cust->winsys_context_throttle)
1050        cust->winsys_context_throttle(cust, ms->ctx, THROTTLE_RENDER);
1051
1052    exa->renderer = renderer_create(exa->pipe);
1053    exa->accel = accel;
1054
1055    return (void *)exa;
1056
1057 out_err:
1058    xorg_exa_close(pScrn);
1059    free(exa);
1060
1061    return NULL;
1062 }
1063
1064 struct pipe_surface *
1065 xorg_gpu_surface(struct pipe_context *pipe, struct exa_pixmap_priv *priv)
1066 {
1067    struct pipe_surface surf_tmpl;
1068    memset(&surf_tmpl, 0, sizeof(surf_tmpl));
1069    u_surface_default_template(&surf_tmpl, priv->tex,
1070                               PIPE_BIND_RENDER_TARGET);
1071
1072    return pipe->create_surface(pipe, priv->tex, &surf_tmpl);
1073
1074 }
1075
1076 void xorg_exa_flush(struct exa_context *exa,
1077                     struct pipe_fence_handle **fence)
1078 {
1079    exa->pipe->flush(exa->pipe, fence);
1080 }
1081
1082 void xorg_exa_finish(struct exa_context *exa)
1083 {
1084    struct pipe_fence_handle *fence = NULL;
1085
1086    xorg_exa_flush(exa, &fence);
1087
1088    exa->pipe->screen->fence_finish(exa->pipe->screen, fence,
1089                                    PIPE_TIMEOUT_INFINITE);
1090    exa->pipe->screen->fence_reference(exa->pipe->screen, &fence, NULL);
1091 }
1092