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