st/xorg: Don't segfault when debug printing
[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 #include "pipe/p_inlines.h"
45
46 #include "util/u_rect.h"
47
48 #define DEBUG_PRINT 0
49 #define ACCEL_ENABLED TRUE
50
51 /*
52 * Helper functions
53 */
54 #if DEBUG_PRINT
55 struct render_format_str {
56 int format;
57 const char *name;
58 };
59 static const struct render_format_str formats_info[] =
60 {
61 {PICT_a2r10g10b10, "PICT_a2r10g10b10"},
62 {PICT_x2r10g10b10, "PICT_x2r10g10b10"},
63 {PICT_a2b10g10r10, "PICT_a2b10g10r10"},
64 {PICT_x2b10g10r10, "PICT_x2b10g10r10"},
65 {PICT_a8r8g8b8, "PICT_a8r8g8b8"},
66 {PICT_x8r8g8b8, "PICT_x8r8g8b8"},
67 {PICT_a8b8g8r8, "PICT_a8b8g8r8"},
68 {PICT_x8b8g8r8, "PICT_x8b8g8r8"},
69 {PICT_b8g8r8a8, "PICT_b8g8r8a8"},
70 {PICT_b8g8r8x8, "PICT_b8g8r8x8"},
71 {PICT_r8g8b8, "PICT_r8g8b8"},
72 {PICT_b8g8r8, "PICT_b8g8r8"},
73 {PICT_r5g6b5, "PICT_r5g6b5"},
74 {PICT_b5g6r5, "PICT_b5g6r5"},
75 {PICT_a1r5g5b5, "PICT_a1r5g5b5"},
76 {PICT_x1r5g5b5, "PICT_x1r5g5b5"},
77 {PICT_a1b5g5r5, "PICT_a1b5g5r5"},
78 {PICT_x1b5g5r5, "PICT_x1b5g5r5"},
79 {PICT_a4r4g4b4, "PICT_a4r4g4b4"},
80 {PICT_x4r4g4b4, "PICT_x4r4g4b4"},
81 {PICT_a4b4g4r4, "PICT_a4b4g4r4"},
82 {PICT_x4b4g4r4, "PICT_x4b4g4r4"},
83 {PICT_a8, "PICT_a8"},
84 {PICT_r3g3b2, "PICT_r3g3b2"},
85 {PICT_b2g3r3, "PICT_b2g3r3"},
86 {PICT_a2r2g2b2, "PICT_a2r2g2b2"},
87 {PICT_a2b2g2r2, "PICT_a2b2g2r2"},
88 {PICT_c8, "PICT_c8"},
89 {PICT_g8, "PICT_g8"},
90 {PICT_x4a4, "PICT_x4a4"},
91 {PICT_x4c4, "PICT_x4c4"},
92 {PICT_x4g4, "PICT_x4g4"},
93 {PICT_a4, "PICT_a4"},
94 {PICT_r1g2b1, "PICT_r1g2b1"},
95 {PICT_b1g2r1, "PICT_b1g2r1"},
96 {PICT_a1r1g1b1, "PICT_a1r1g1b1"},
97 {PICT_a1b1g1r1, "PICT_a1b1g1r1"},
98 {PICT_c4, "PICT_c4"},
99 {PICT_g4, "PICT_g4"},
100 {PICT_a1, "PICT_a1"},
101 {PICT_g1, "PICT_g1"}
102 };
103 static const char *render_format_name(int format)
104 {
105 int i = 0;
106 for (i = 0; i < sizeof(formats_info)/sizeof(formats_info[0]); ++i) {
107 if (formats_info[i].format == format)
108 return formats_info[i].name;
109 }
110 return NULL;
111 }
112 #endif
113
114 static void
115 exa_get_pipe_format(int depth, enum pipe_format *format, int *bbp)
116 {
117 switch (depth) {
118 case 32:
119 *format = PIPE_FORMAT_A8R8G8B8_UNORM;
120 assert(*bbp == 32);
121 break;
122 case 24:
123 *format = PIPE_FORMAT_X8R8G8B8_UNORM;
124 assert(*bbp == 32);
125 break;
126 case 16:
127 *format = PIPE_FORMAT_R5G6B5_UNORM;
128 assert(*bbp == 16);
129 break;
130 case 15:
131 *format = PIPE_FORMAT_A1R5G5B5_UNORM;
132 assert(*bbp == 16);
133 break;
134 case 8:
135 *format = PIPE_FORMAT_L8_UNORM;
136 assert(*bbp == 8);
137 break;
138 case 4:
139 case 1:
140 *format = PIPE_FORMAT_A8R8G8B8_UNORM; /* bad bad bad */
141 break;
142 default:
143 assert(0);
144 break;
145 }
146 }
147
148 static void
149 xorg_exa_common_done(struct exa_context *exa)
150 {
151 renderer_draw_flush(exa->renderer);
152
153 exa->copy.src = NULL;
154 exa->copy.dst = NULL;
155 exa->transform.has_src = FALSE;
156 exa->transform.has_mask = FALSE;
157 exa->has_solid_color = FALSE;
158 exa->num_bound_samplers = 0;
159 }
160
161 /*
162 * Static exported EXA functions
163 */
164
165 static void
166 ExaWaitMarker(ScreenPtr pScreen, int marker)
167 {
168 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
169 modesettingPtr ms = modesettingPTR(pScrn);
170 struct exa_context *exa = ms->exa;
171
172 #if 0
173 xorg_exa_flush(exa, PIPE_FLUSH_RENDER_CACHE, NULL);
174 #else
175 xorg_exa_finish(exa);
176 #endif
177 }
178
179 static int
180 ExaMarkSync(ScreenPtr pScreen)
181 {
182 return 1;
183 }
184
185 static Bool
186 ExaDownloadFromScreen(PixmapPtr pPix, int x, int y, int w, int h, char *dst,
187 int dst_pitch)
188 {
189 ScreenPtr pScreen = pPix->drawable.pScreen;
190 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
191 modesettingPtr ms = modesettingPTR(pScrn);
192 struct exa_context *exa = ms->exa;
193 struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pPix);
194 struct pipe_transfer *transfer;
195
196 if (!priv || !priv->tex)
197 return FALSE;
198
199 if (exa->pipe->is_texture_referenced(exa->pipe, priv->tex, 0, 0) &
200 PIPE_REFERENCED_FOR_WRITE)
201 exa->pipe->flush(exa->pipe, 0, NULL);
202
203 transfer = exa->scrn->get_tex_transfer(exa->scrn, priv->tex, 0, 0, 0,
204 PIPE_TRANSFER_READ, x, y, w, h);
205 if (!transfer)
206 return FALSE;
207
208 #if DEBUG_PRINT
209 debug_printf("------ ExaDownloadFromScreen(%d, %d, %d, %d, %d)\n",
210 x, y, w, h, dst_pitch);
211 #endif
212
213 util_copy_rect((unsigned char*)dst, &priv->tex->block, dst_pitch, 0, 0,
214 w, h, exa->scrn->transfer_map(exa->scrn, transfer),
215 transfer->stride, 0, 0);
216
217 exa->scrn->transfer_unmap(exa->scrn, transfer);
218 exa->scrn->tex_transfer_destroy(transfer);
219
220 return TRUE;
221 }
222
223 static Bool
224 ExaUploadToScreen(PixmapPtr pPix, int x, int y, int w, int h, char *src,
225 int src_pitch)
226 {
227 ScreenPtr pScreen = pPix->drawable.pScreen;
228 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
229 modesettingPtr ms = modesettingPTR(pScrn);
230 struct exa_context *exa = ms->exa;
231 struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pPix);
232 struct pipe_transfer *transfer;
233
234 if (!priv || !priv->tex)
235 return FALSE;
236
237 transfer = exa->scrn->get_tex_transfer(exa->scrn, priv->tex, 0, 0, 0,
238 PIPE_TRANSFER_WRITE, x, y, w, h);
239 if (!transfer)
240 return FALSE;
241
242 #if DEBUG_PRINT
243 debug_printf("++++++ ExaUploadToScreen(%d, %d, %d, %d, %d)\n",
244 x, y, w, h, src_pitch);
245 #endif
246
247 util_copy_rect(exa->scrn->transfer_map(exa->scrn, transfer),
248 &priv->tex->block, transfer->stride, 0, 0, w, h,
249 (unsigned char*)src, src_pitch, 0, 0);
250
251 exa->scrn->transfer_unmap(exa->scrn, transfer);
252 exa->scrn->tex_transfer_destroy(transfer);
253
254 return TRUE;
255 }
256
257 static Bool
258 ExaPrepareAccess(PixmapPtr pPix, int index)
259 {
260 ScreenPtr pScreen = pPix->drawable.pScreen;
261 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
262 modesettingPtr ms = modesettingPTR(pScrn);
263 struct exa_context *exa = ms->exa;
264 struct exa_pixmap_priv *priv;
265
266 priv = exaGetPixmapDriverPrivate(pPix);
267
268 if (!priv)
269 return FALSE;
270
271 if (!priv->tex)
272 return FALSE;
273
274 if (priv->map_count == 0)
275 {
276 if (exa->pipe->is_texture_referenced(exa->pipe, priv->tex, 0, 0) &
277 PIPE_REFERENCED_FOR_WRITE)
278 exa->pipe->flush(exa->pipe, 0, NULL);
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, priv->tex->width[0], priv->tex->height[0]);
287 if (!priv->map_transfer)
288 #ifdef EXA_MIXED_PIXMAPS
289 return FALSE;
290 #else
291 FatalError("failed to create transfer\n");
292 #endif
293
294 pPix->devPrivate.ptr =
295 exa->scrn->transfer_map(exa->scrn, priv->map_transfer);
296 pPix->devKind = priv->map_transfer->stride;
297 }
298
299 priv->map_count++;
300
301 return TRUE;
302 }
303
304 static void
305 ExaFinishAccess(PixmapPtr pPix, int index)
306 {
307 ScreenPtr pScreen = pPix->drawable.pScreen;
308 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
309 modesettingPtr ms = modesettingPTR(pScrn);
310 struct exa_context *exa = ms->exa;
311 struct exa_pixmap_priv *priv;
312 priv = exaGetPixmapDriverPrivate(pPix);
313
314 if (!priv)
315 return;
316
317 if (!priv->map_transfer)
318 return;
319
320 if (--priv->map_count == 0) {
321 assert(priv->map_transfer);
322 exa->scrn->transfer_unmap(exa->scrn, priv->map_transfer);
323 exa->scrn->tex_transfer_destroy(priv->map_transfer);
324 priv->map_transfer = NULL;
325 pPix->devPrivate.ptr = NULL;
326 }
327 }
328
329 static void
330 ExaDone(PixmapPtr pPixmap)
331 {
332 ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum];
333 modesettingPtr ms = modesettingPTR(pScrn);
334 struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pPixmap);
335 struct exa_context *exa = ms->exa;
336
337 if (!priv)
338 return;
339
340 xorg_exa_common_done(exa);
341 }
342
343 static void
344 ExaDoneComposite(PixmapPtr pPixmap)
345 {
346 ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum];
347 modesettingPtr ms = modesettingPTR(pScrn);
348 struct exa_context *exa = ms->exa;
349
350 xorg_exa_common_done(exa);
351 }
352
353 static Bool
354 ExaPrepareSolid(PixmapPtr pPixmap, int alu, Pixel planeMask, Pixel fg)
355 {
356 ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum];
357 modesettingPtr ms = modesettingPTR(pScrn);
358 struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pPixmap);
359 struct exa_context *exa = ms->exa;
360
361 #if DEBUG_PRINT
362 debug_printf("ExaPrepareSolid(0x%x)\n", fg);
363 #endif
364 if (!exa->pipe)
365 XORG_FALLBACK("accle not enabled");
366
367 if (!priv || !priv->tex)
368 XORG_FALLBACK("%s", !priv ? "!priv" : "!priv->tex");
369
370 if (!EXA_PM_IS_SOLID(&pPixmap->drawable, planeMask))
371 XORG_FALLBACK("planeMask is not solid");
372
373 if (alu != GXcopy)
374 XORG_FALLBACK("not GXcopy");
375
376 if (!exa->scrn->is_format_supported(exa->scrn, priv->tex->format,
377 priv->tex->target,
378 PIPE_TEXTURE_USAGE_RENDER_TARGET, 0)) {
379 XORG_FALLBACK("format %s", pf_name(priv->tex->format));
380 }
381
382 return ACCEL_ENABLED && xorg_solid_bind_state(exa, priv, fg);
383 }
384
385 static void
386 ExaSolid(PixmapPtr pPixmap, int x0, int y0, int x1, int y1)
387 {
388 ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum];
389 modesettingPtr ms = modesettingPTR(pScrn);
390 struct exa_context *exa = ms->exa;
391 struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pPixmap);
392
393 #if DEBUG_PRINT
394 debug_printf("\tExaSolid(%d, %d, %d, %d)\n", x0, y0, x1, y1);
395 #endif
396
397 xorg_solid(exa, priv, x0, y0, x1, y1) ;
398 }
399
400 static Bool
401 ExaPrepareCopy(PixmapPtr pSrcPixmap, PixmapPtr pDstPixmap, int xdir,
402 int ydir, int alu, Pixel planeMask)
403 {
404 ScrnInfoPtr pScrn = xf86Screens[pDstPixmap->drawable.pScreen->myNum];
405 modesettingPtr ms = modesettingPTR(pScrn);
406 struct exa_context *exa = ms->exa;
407 struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pDstPixmap);
408 struct exa_pixmap_priv *src_priv = exaGetPixmapDriverPrivate(pSrcPixmap);
409
410 #if DEBUG_PRINT
411 debug_printf("ExaPrepareCopy\n");
412 #endif
413 if (!exa->pipe)
414 XORG_FALLBACK("accle not enabled");
415
416 if (!priv || !priv->tex)
417 XORG_FALLBACK("pDst %s", !priv ? "!priv" : "!priv->tex");
418
419 if (!src_priv || !src_priv->tex)
420 XORG_FALLBACK("pSrc %s", !src_priv ? "!priv" : "!priv->tex");
421
422 if (!EXA_PM_IS_SOLID(&pSrcPixmap->drawable, planeMask))
423 XORG_FALLBACK("planeMask is not solid");
424
425 if (alu != GXcopy)
426 XORG_FALLBACK("alu not GXcopy");
427
428 if (!exa->scrn->is_format_supported(exa->scrn, priv->tex->format,
429 priv->tex->target,
430 PIPE_TEXTURE_USAGE_RENDER_TARGET, 0))
431 XORG_FALLBACK("pDst format %s", pf_name(priv->tex->format));
432
433 if (!exa->scrn->is_format_supported(exa->scrn, src_priv->tex->format,
434 src_priv->tex->target,
435 PIPE_TEXTURE_USAGE_SAMPLER, 0))
436 XORG_FALLBACK("pSrc format %s", pf_name(src_priv->tex->format));
437
438 exa->copy.src = src_priv;
439 exa->copy.dst = priv;
440
441 return ACCEL_ENABLED;
442 }
443
444 static void
445 ExaCopy(PixmapPtr pDstPixmap, int srcX, int srcY, int dstX, int dstY,
446 int width, int height)
447 {
448 ScrnInfoPtr pScrn = xf86Screens[pDstPixmap->drawable.pScreen->myNum];
449 modesettingPtr ms = modesettingPTR(pScrn);
450 struct exa_context *exa = ms->exa;
451 struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pDstPixmap);
452
453 #if DEBUG_PRINT
454 debug_printf("\tExaCopy(srcx=%d, srcy=%d, dstX=%d, dstY=%d, w=%d, h=%d)\n",
455 srcX, srcY, dstX, dstY, width, height);
456 #endif
457
458 debug_assert(priv == exa->copy.dst);
459
460 renderer_copy_pixmap(exa->renderer, exa->copy.dst, dstX, dstY,
461 exa->copy.src, srcX, srcY,
462 width, height);
463 }
464
465 static Bool
466 ExaPrepareComposite(int op, PicturePtr pSrcPicture,
467 PicturePtr pMaskPicture, PicturePtr pDstPicture,
468 PixmapPtr pSrc, PixmapPtr pMask, PixmapPtr pDst)
469 {
470 ScrnInfoPtr pScrn = xf86Screens[pDst->drawable.pScreen->myNum];
471 modesettingPtr ms = modesettingPTR(pScrn);
472 struct exa_context *exa = ms->exa;
473 struct exa_pixmap_priv *priv;
474
475 #if DEBUG_PRINT
476 debug_printf("ExaPrepareComposite(%d, src=0x%p, mask=0x%p, dst=0x%p)\n",
477 op, pSrcPicture, pMaskPicture, pDstPicture);
478 debug_printf("\tFormats: src(%s), mask(%s), dst(%s)\n",
479 pSrcPicture ? render_format_name(pSrcPicture->format) : "none",
480 pMaskPicture ? render_format_name(pMaskPicture->format) : "none",
481 pDstPicture ? render_format_name(pDstPicture->format) : "none");
482 #endif
483 if (!exa->pipe)
484 XORG_FALLBACK("accle not enabled");
485
486 priv = exaGetPixmapDriverPrivate(pDst);
487 if (!priv || !priv->tex)
488 XORG_FALLBACK("pDst %s", !priv ? "!priv" : "!priv->tex");
489
490 if (!exa->scrn->is_format_supported(exa->scrn, priv->tex->format,
491 priv->tex->target,
492 PIPE_TEXTURE_USAGE_RENDER_TARGET, 0))
493 XORG_FALLBACK("pDst format: %s", pf_name(priv->tex->format));
494
495 if (pSrc) {
496 priv = exaGetPixmapDriverPrivate(pSrc);
497 if (!priv || !priv->tex)
498 XORG_FALLBACK("pSrc %s", !priv ? "!priv" : "!priv->tex");
499
500 if (!exa->scrn->is_format_supported(exa->scrn, priv->tex->format,
501 priv->tex->target,
502 PIPE_TEXTURE_USAGE_SAMPLER, 0))
503 XORG_FALLBACK("pSrc format: %s", pf_name(priv->tex->format));
504 }
505
506 if (pMask) {
507 priv = exaGetPixmapDriverPrivate(pMask);
508 if (!priv || !priv->tex)
509 XORG_FALLBACK("pMask %s", !priv ? "!priv" : "!priv->tex");
510
511 if (!exa->scrn->is_format_supported(exa->scrn, priv->tex->format,
512 priv->tex->target,
513 PIPE_TEXTURE_USAGE_SAMPLER, 0))
514 XORG_FALLBACK("pMask format: %s", pf_name(priv->tex->format));
515 }
516
517 return ACCEL_ENABLED &&
518 xorg_composite_bind_state(exa, op, pSrcPicture, pMaskPicture,
519 pDstPicture,
520 pSrc ? exaGetPixmapDriverPrivate(pSrc) : NULL,
521 pMask ? exaGetPixmapDriverPrivate(pMask) : NULL,
522 exaGetPixmapDriverPrivate(pDst));
523 }
524
525 static void
526 ExaComposite(PixmapPtr pDst, int srcX, int srcY, int maskX, int maskY,
527 int dstX, int dstY, int width, int height)
528 {
529 ScrnInfoPtr pScrn = xf86Screens[pDst->drawable.pScreen->myNum];
530 modesettingPtr ms = modesettingPTR(pScrn);
531 struct exa_context *exa = ms->exa;
532 struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pDst);
533
534 #if DEBUG_PRINT
535 debug_printf("\tExaComposite(src[%d,%d], mask=[%d, %d], dst=[%d, %d], dim=[%d, %d])\n",
536 srcX, srcY, maskX, maskY, dstX, dstY, width, height);
537 debug_printf("\t Num bound samplers = %d\n",
538 exa->num_bound_samplers);
539 #endif
540
541 xorg_composite(exa, priv, srcX, srcY, maskX, maskY,
542 dstX, dstY, width, height);
543 }
544
545 static Bool
546 ExaCheckComposite(int op,
547 PicturePtr pSrcPicture, PicturePtr pMaskPicture,
548 PicturePtr pDstPicture)
549 {
550 boolean accelerated = xorg_composite_accelerated(op,
551 pSrcPicture,
552 pMaskPicture,
553 pDstPicture);
554 #if DEBUG_PRINT
555 debug_printf("ExaCheckComposite(%d, %p, %p, %p) = %d\n",
556 op, pSrcPicture, pMaskPicture, pDstPicture, accelerated);
557 #endif
558 return ACCEL_ENABLED && accelerated;
559 }
560
561 static void *
562 ExaCreatePixmap(ScreenPtr pScreen, int size, int align)
563 {
564 struct exa_pixmap_priv *priv;
565
566 priv = xcalloc(1, sizeof(struct exa_pixmap_priv));
567 if (!priv)
568 return NULL;
569
570 return priv;
571 }
572
573 static void
574 ExaDestroyPixmap(ScreenPtr pScreen, void *dPriv)
575 {
576 struct exa_pixmap_priv *priv = (struct exa_pixmap_priv *)dPriv;
577
578 if (!priv)
579 return;
580
581 pipe_texture_reference(&priv->tex, NULL);
582
583 xfree(priv);
584 }
585
586 static Bool
587 ExaPixmapIsOffscreen(PixmapPtr pPixmap)
588 {
589 struct exa_pixmap_priv *priv;
590
591 priv = exaGetPixmapDriverPrivate(pPixmap);
592
593 if (!priv)
594 return FALSE;
595
596 if (priv->tex)
597 return TRUE;
598
599 return FALSE;
600 }
601
602 int
603 xorg_exa_set_displayed_usage(PixmapPtr pPixmap)
604 {
605 struct exa_pixmap_priv *priv;
606 priv = exaGetPixmapDriverPrivate(pPixmap);
607
608 if (!priv) {
609 FatalError("NO PIXMAP PRIVATE\n");
610 return 0;
611 }
612
613 priv->flags |= PIPE_TEXTURE_USAGE_PRIMARY;
614
615 return 0;
616 }
617
618 int
619 xorg_exa_set_shared_usage(PixmapPtr pPixmap)
620 {
621 struct exa_pixmap_priv *priv;
622 priv = exaGetPixmapDriverPrivate(pPixmap);
623
624 if (!priv) {
625 FatalError("NO PIXMAP PRIVATE\n");
626 return 0;
627 }
628
629 priv->flags |= PIPE_TEXTURE_USAGE_DISPLAY_TARGET;
630
631 return 0;
632 }
633
634 unsigned
635 xorg_exa_get_pixmap_handle(PixmapPtr pPixmap, unsigned *stride_out)
636 {
637 ScreenPtr pScreen = pPixmap->drawable.pScreen;
638 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
639 modesettingPtr ms = modesettingPTR(pScrn);
640 struct exa_pixmap_priv *priv;
641 unsigned handle;
642 unsigned stride;
643
644 if (!ms->exa) {
645 FatalError("NO MS->EXA\n");
646 return 0;
647 }
648
649 priv = exaGetPixmapDriverPrivate(pPixmap);
650
651 if (!priv) {
652 FatalError("NO PIXMAP PRIVATE\n");
653 return 0;
654 }
655
656 ms->api->local_handle_from_texture(ms->api, ms->screen, priv->tex, &stride, &handle);
657 if (stride_out)
658 *stride_out = stride;
659
660 return handle;
661 }
662
663 static Bool
664 ExaModifyPixmapHeader(PixmapPtr pPixmap, int width, int height,
665 int depth, int bitsPerPixel, int devKind,
666 pointer pPixData)
667 {
668 ScreenPtr pScreen = pPixmap->drawable.pScreen;
669 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
670 struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pPixmap);
671 modesettingPtr ms = modesettingPTR(pScrn);
672 struct exa_context *exa = ms->exa;
673
674 if (!priv || pPixData)
675 return FALSE;
676
677 if (depth <= 0)
678 depth = pPixmap->drawable.depth;
679
680 if (bitsPerPixel <= 0)
681 bitsPerPixel = pPixmap->drawable.bitsPerPixel;
682
683 if (width <= 0)
684 width = pPixmap->drawable.width;
685
686 if (height <= 0)
687 height = pPixmap->drawable.height;
688
689 if (width <= 0 || height <= 0 || depth <= 0)
690 return FALSE;
691
692 miModifyPixmapHeader(pPixmap, width, height, depth,
693 bitsPerPixel, devKind, NULL);
694
695 /* Deal with screen resize */
696 if (!priv->tex ||
697 (priv->tex->width[0] != width ||
698 priv->tex->height[0] != height ||
699 priv->tex_flags != priv->flags)) {
700 struct pipe_texture *texture = NULL;
701 struct pipe_texture template;
702
703 memset(&template, 0, sizeof(template));
704 template.target = PIPE_TEXTURE_2D;
705 exa_get_pipe_format(depth, &template.format, &bitsPerPixel);
706 pf_get_block(template.format, &template.block);
707 template.width[0] = width;
708 template.height[0] = height;
709 template.depth[0] = 1;
710 template.last_level = 0;
711 template.tex_usage = PIPE_TEXTURE_USAGE_RENDER_TARGET | priv->flags;
712 priv->tex_flags = priv->flags;
713 texture = exa->scrn->texture_create(exa->scrn, &template);
714
715 if (priv->tex) {
716 struct pipe_surface *dst_surf;
717 struct pipe_surface *src_surf;
718
719 dst_surf = exa->scrn->get_tex_surface(
720 exa->scrn, texture, 0, 0, 0, PIPE_BUFFER_USAGE_GPU_WRITE);
721 src_surf = xorg_gpu_surface(exa->pipe->screen, priv);
722 if (exa->pipe->surface_copy) {
723 exa->pipe->surface_copy(exa->pipe, dst_surf, 0, 0, src_surf,
724 0, 0, min(width, texture->width[0]),
725 min(height, texture->height[0]));
726 } else {
727 util_surface_copy(exa->pipe, FALSE, dst_surf, 0, 0, src_surf,
728 0, 0, min(width, texture->width[0]),
729 min(height, texture->height[0]));
730 }
731 exa->scrn->tex_surface_destroy(dst_surf);
732 exa->scrn->tex_surface_destroy(src_surf);
733 }
734
735 pipe_texture_reference(&priv->tex, texture);
736 /* the texture we create has one reference */
737 pipe_texture_reference(&texture, NULL);
738 }
739
740 return TRUE;
741 }
742
743 struct pipe_texture *
744 xorg_exa_get_texture(PixmapPtr pPixmap)
745 {
746 struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pPixmap);
747 struct pipe_texture *tex = NULL;
748 pipe_texture_reference(&tex, priv->tex);
749 return tex;
750 }
751
752 Bool
753 xorg_exa_set_texture(PixmapPtr pPixmap, struct pipe_texture *tex)
754 {
755 struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pPixmap);
756
757 int mask = PIPE_TEXTURE_USAGE_PRIMARY | PIPE_TEXTURE_USAGE_DISPLAY_TARGET;
758
759 if (!priv)
760 return FALSE;
761
762 if (pPixmap->drawable.width != tex->width[0] ||
763 pPixmap->drawable.height != tex->height[0])
764 return FALSE;
765
766 pipe_texture_reference(&priv->tex, tex);
767 priv->tex_flags = tex->tex_usage & mask;
768
769 return TRUE;
770 }
771
772 struct pipe_texture *
773 xorg_exa_create_root_texture(ScrnInfoPtr pScrn,
774 int width, int height,
775 int depth, int bitsPerPixel)
776 {
777 modesettingPtr ms = modesettingPTR(pScrn);
778 struct exa_context *exa = ms->exa;
779 struct pipe_texture template;
780
781 memset(&template, 0, sizeof(template));
782 template.target = PIPE_TEXTURE_2D;
783 exa_get_pipe_format(depth, &template.format, &bitsPerPixel);
784 pf_get_block(template.format, &template.block);
785 template.width[0] = width;
786 template.height[0] = height;
787 template.depth[0] = 1;
788 template.last_level = 0;
789 template.tex_usage |= PIPE_TEXTURE_USAGE_RENDER_TARGET;
790 template.tex_usage |= PIPE_TEXTURE_USAGE_PRIMARY;
791 template.tex_usage |= PIPE_TEXTURE_USAGE_DISPLAY_TARGET;
792
793 return exa->scrn->texture_create(exa->scrn, &template);
794 }
795
796 void
797 xorg_exa_close(ScrnInfoPtr pScrn)
798 {
799 modesettingPtr ms = modesettingPTR(pScrn);
800 struct exa_context *exa = ms->exa;
801
802 renderer_destroy(exa->renderer);
803
804 if (exa->pipe)
805 exa->pipe->destroy(exa->pipe);
806
807 exaDriverFini(pScrn->pScreen);
808 xfree(exa);
809 ms->exa = NULL;
810 }
811
812 void *
813 xorg_exa_init(ScrnInfoPtr pScrn)
814 {
815 modesettingPtr ms = modesettingPTR(pScrn);
816 struct exa_context *exa;
817 ExaDriverPtr pExa;
818
819 exa = xcalloc(1, sizeof(struct exa_context));
820 if (!exa)
821 return NULL;
822
823 pExa = exaDriverAlloc();
824 if (!pExa) {
825 goto out_err;
826 }
827
828 memset(pExa, 0, sizeof(*pExa));
829
830 pExa->exa_major = 2;
831 pExa->exa_minor = 2;
832 pExa->memoryBase = 0;
833 pExa->memorySize = 0;
834 pExa->offScreenBase = 0;
835 pExa->pixmapOffsetAlign = 0;
836 pExa->pixmapPitchAlign = 1;
837 pExa->flags = EXA_OFFSCREEN_PIXMAPS | EXA_HANDLES_PIXMAPS;
838 #ifdef EXA_SUPPORTS_PREPARE_AUX
839 pExa->flags |= EXA_SUPPORTS_PREPARE_AUX;
840 #endif
841 #ifdef EXA_MIXED_PIXMAPS
842 pExa->flags |= EXA_MIXED_PIXMAPS;
843 #endif
844 pExa->maxX = 8191; /* FIXME */
845 pExa->maxY = 8191; /* FIXME */
846
847 pExa->WaitMarker = ExaWaitMarker;
848 pExa->MarkSync = ExaMarkSync;
849 pExa->PrepareSolid = ExaPrepareSolid;
850 pExa->Solid = ExaSolid;
851 pExa->DoneSolid = ExaDone;
852 pExa->PrepareCopy = ExaPrepareCopy;
853 pExa->Copy = ExaCopy;
854 pExa->DoneCopy = ExaDone;
855 pExa->CheckComposite = ExaCheckComposite;
856 pExa->PrepareComposite = ExaPrepareComposite;
857 pExa->Composite = ExaComposite;
858 pExa->DoneComposite = ExaDoneComposite;
859 pExa->PixmapIsOffscreen = ExaPixmapIsOffscreen;
860 pExa->DownloadFromScreen = ExaDownloadFromScreen;
861 pExa->UploadToScreen = ExaUploadToScreen;
862 pExa->PrepareAccess = ExaPrepareAccess;
863 pExa->FinishAccess = ExaFinishAccess;
864 pExa->CreatePixmap = ExaCreatePixmap;
865 pExa->DestroyPixmap = ExaDestroyPixmap;
866 pExa->ModifyPixmapHeader = ExaModifyPixmapHeader;
867
868 if (!exaDriverInit(pScrn->pScreen, pExa)) {
869 goto out_err;
870 }
871
872 exa->scrn = ms->screen;
873 exa->pipe = ms->api->create_context(ms->api, exa->scrn);
874 /* Share context with DRI */
875 ms->ctx = exa->pipe;
876
877 exa->renderer = renderer_create(exa->pipe);
878
879 return (void *)exa;
880
881 out_err:
882 xorg_exa_close(pScrn);
883
884 return NULL;
885 }
886
887 struct pipe_surface *
888 xorg_gpu_surface(struct pipe_screen *scrn, struct exa_pixmap_priv *priv)
889 {
890 return scrn->get_tex_surface(scrn, priv->tex, 0, 0, 0,
891 PIPE_BUFFER_USAGE_GPU_READ |
892 PIPE_BUFFER_USAGE_GPU_WRITE);
893
894 }
895
896 void xorg_exa_flush(struct exa_context *exa, uint pipeFlushFlags,
897 struct pipe_fence_handle **fence)
898 {
899 exa->pipe->flush(exa->pipe, pipeFlushFlags, fence);
900 }
901
902 void xorg_exa_finish(struct exa_context *exa)
903 {
904 struct pipe_fence_handle *fence = NULL;
905
906 xorg_exa_flush(exa, PIPE_FLUSH_RENDER_CACHE, &fence);
907
908 exa->pipe->screen->fence_finish(exa->pipe->screen, fence, 0);
909 exa->pipe->screen->fence_reference(exa->pipe->screen, &fence, NULL);
910 }
911