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