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