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
exa_debug_printf(const char * format,...)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 };
render_format_name(int format)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
exa_get_pipe_format(int depth,enum pipe_format * format,int * bbp,int * picture_format)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
ExaWaitMarker(ScreenPtr pScreen,int marker)178 ExaWaitMarker(ScreenPtr pScreen, int marker)
179 {
180    /* Nothing to do, handled in the PrepareAccess hook */
181 }
182 
183 static int
ExaMarkSync(ScreenPtr pScreen)184 ExaMarkSync(ScreenPtr pScreen)
185 {
186    return 1;
187 }
188 
189 
190 /***********************************************************************
191  * Screen upload/download
192  */
193 
194 static Bool
ExaDownloadFromScreen(PixmapPtr pPix,int x,int y,int w,int h,char * dst,int dst_pitch)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
ExaUploadToScreen(PixmapPtr pPix,int x,int y,int w,int h,char * src,int src_pitch)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
ExaPrepareAccess(PixmapPtr pPix,int index)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
ExaFinishAccess(PixmapPtr pPix,int index)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
ExaPrepareSolid(PixmapPtr pPixmap,int alu,Pixel planeMask,Pixel fg)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
ExaSolid(PixmapPtr pPixmap,int x0,int y0,int x1,int y1)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
ExaDoneSolid(PixmapPtr pPixmap)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
ExaPrepareCopy(PixmapPtr pSrcPixmap,PixmapPtr pDstPixmap,int xdir,int ydir,int alu,Pixel planeMask)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
ExaCopy(PixmapPtr pDstPixmap,int srcX,int srcY,int dstX,int dstY,int width,int height)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
ExaDoneCopy(PixmapPtr pPixmap)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
picture_check_formats(struct exa_pixmap_priv * pSrc,PicturePtr pSrcPicture)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
ExaCheckComposite(int op,PicturePtr pSrcPicture,PicturePtr pMaskPicture,PicturePtr pDstPicture)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
ExaPrepareComposite(int op,PicturePtr pSrcPicture,PicturePtr pMaskPicture,PicturePtr pDstPicture,PixmapPtr pSrc,PixmapPtr pMask,PixmapPtr pDst)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
ExaComposite(PixmapPtr pDst,int srcX,int srcY,int maskX,int maskY,int dstX,int dstY,int width,int height)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
ExaDoneComposite(PixmapPtr pPixmap)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 *
ExaCreatePixmap(ScreenPtr pScreen,int size,int align)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
ExaDestroyPixmap(ScreenPtr pScreen,void * dPriv)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
ExaPixmapIsOffscreen(PixmapPtr pPixmap)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
xorg_exa_set_displayed_usage(PixmapPtr pPixmap)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
xorg_exa_set_shared_usage(PixmapPtr pPixmap)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
size_match(int width,int tex_width)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
ExaModifyPixmapHeader(PixmapPtr pPixmap,int width,int height,int depth,int bitsPerPixel,int devKind,pointer pPixData)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 *
xorg_exa_get_texture(PixmapPtr pPixmap)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
xorg_exa_set_texture(PixmapPtr pPixmap,struct pipe_resource * tex)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 *
xorg_exa_create_root_texture(ScrnInfoPtr pScrn,int width,int height,int depth,int bitsPerPixel)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
xorg_exa_close(ScrnInfoPtr pScrn)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 *
xorg_exa_init(ScrnInfoPtr pScrn,Bool accel)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 *
xorg_gpu_surface(struct pipe_context * pipe,struct exa_pixmap_priv * priv)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 
xorg_exa_flush(struct exa_context * exa,struct pipe_fence_handle ** fence)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 
xorg_exa_finish(struct exa_context * exa)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 
1093