xorg_exa.c revision 3a8d525373c50c6cdc9ae5dd00e7298ab58df8c6
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_I8_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					PIPE_TRANSFER_READ_WRITE,
214					0, 0, priv->tex->width[0], priv->tex->height[0]);
215
216	pPix->devPrivate.ptr =
217	    exa->scrn->transfer_map(exa->scrn, priv->map_transfer);
218	pPix->devKind = priv->map_transfer->stride;
219    }
220
221    return TRUE;
222}
223
224static void
225ExaFinishAccess(PixmapPtr pPix, int index)
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;
232    priv = exaGetPixmapDriverPrivate(pPix);
233
234    if (!priv)
235	return;
236
237    if (!priv->map_transfer)
238	return;
239
240    if (--priv->map_count == 0) {
241	assert(priv->map_transfer);
242	exa->scrn->transfer_unmap(exa->scrn, priv->map_transfer);
243	exa->scrn->tex_transfer_destroy(priv->map_transfer);
244	priv->map_transfer = NULL;
245	pPix->devPrivate.ptr = NULL;
246    }
247}
248
249static void
250ExaDone(PixmapPtr pPixmap)
251{
252    ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum];
253    modesettingPtr ms = modesettingPTR(pScrn);
254    struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pPixmap);
255    struct exa_context *exa = ms->exa;
256
257    if (!priv)
258	return;
259
260#if 1
261    xorg_exa_flush(exa, PIPE_FLUSH_RENDER_CACHE, NULL);
262#else
263    xorg_exa_finish(exa);
264#endif
265    xorg_exa_common_done(exa);
266}
267
268static void
269ExaDoneComposite(PixmapPtr pPixmap)
270{
271   ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum];
272   modesettingPtr ms = modesettingPTR(pScrn);
273   struct exa_context *exa = ms->exa;
274
275   xorg_exa_common_done(exa);
276}
277
278static Bool
279ExaPrepareSolid(PixmapPtr pPixmap, int alu, Pixel planeMask, Pixel fg)
280{
281    ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum];
282    modesettingPtr ms = modesettingPTR(pScrn);
283    struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pPixmap);
284    struct exa_context *exa = ms->exa;
285
286#if DEBUG_PRINT
287    debug_printf("ExaPrepareSolid(0x%x)\n", fg);
288#endif
289    if (!exa->pipe)
290	XORG_FALLBACK("solid accle not enabled");
291
292    if (!priv || !priv->tex)
293	XORG_FALLBACK("solid !priv || !priv->tex");
294
295    if (!EXA_PM_IS_SOLID(&pPixmap->drawable, planeMask))
296	XORG_FALLBACK("solid planeMask is not solid");
297
298    if (alu != GXcopy)
299	XORG_FALLBACK("solid not GXcopy");
300
301    if (!exa->scrn->is_format_supported(exa->scrn, priv->tex->format,
302                                        priv->tex->target,
303                                        PIPE_TEXTURE_USAGE_RENDER_TARGET, 0)) {
304	XORG_FALLBACK("solid bad format %s", pf_name(priv->tex->format));
305    }
306
307#if DEBUG_SOLID
308    fg = 0xffff0000;
309#endif
310
311#if DISABLE_ACCEL
312    return FALSE;
313#else
314    return xorg_solid_bind_state(exa, priv, fg);
315#endif
316}
317
318static void
319ExaSolid(PixmapPtr pPixmap, int x0, int y0, int x1, int y1)
320{
321    ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum];
322    modesettingPtr ms = modesettingPTR(pScrn);
323    struct exa_context *exa = ms->exa;
324    struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pPixmap);
325
326#if DEBUG_PRINT
327    debug_printf("\tExaSolid(%d, %d, %d, %d)\n", x0, y0, x1, y1);
328#endif
329
330#if 0
331    if (x0 == 0 && y0 == 0 &&
332        x1 == priv->tex->width[0] &&
333        y1 == priv->tex->height[0]) {
334       exa->ctx->clear(exa->pipe, PIPE_CLEAR_COLOR,
335                       exa->solid_color, 1., 0);
336    } else
337#endif
338
339#if DEBUG_SOLID
340       exa->solid_color[0] = 0.f;
341       exa->solid_color[1] = 1.f;
342       exa->solid_color[2] = 0.f;
343       exa->solid_color[3] = 1.f;
344    xorg_solid(exa, priv, 0, 0, 1024, 768);
345       exa->solid_color[0] = 1.f;
346       exa->solid_color[1] = 0.f;
347       exa->solid_color[2] = 0.f;
348       exa->solid_color[3] = 1.f;
349       xorg_solid(exa, priv, 0, 0, 300, 300);
350       xorg_solid(exa, priv, 300, 300, 350, 350);
351       xorg_solid(exa, priv, 350, 350, 500, 500);
352
353       xorg_solid(exa, priv,
354               priv->tex->width[0] - 10,
355               priv->tex->height[0] - 10,
356               priv->tex->width[0],
357               priv->tex->height[0]);
358
359    exa->solid_color[0] = 0.f;
360    exa->solid_color[1] = 0.f;
361    exa->solid_color[2] = 1.f;
362    exa->solid_color[3] = 1.f;
363
364    exa->has_solid_color = FALSE;
365    ExaPrepareCopy(pPixmap, pPixmap, 0, 0, GXcopy, 0xffffffff);
366    ExaCopy(pPixmap, 0, 0, 50, 50, 500, 500);
367#else
368    xorg_solid(exa, priv, x0, y0, x1, y1) ;
369#endif
370}
371
372static Bool
373ExaPrepareCopy(PixmapPtr pSrcPixmap, PixmapPtr pDstPixmap, int xdir,
374	       int ydir, int alu, Pixel planeMask)
375{
376    ScrnInfoPtr pScrn = xf86Screens[pDstPixmap->drawable.pScreen->myNum];
377    modesettingPtr ms = modesettingPTR(pScrn);
378    struct exa_context *exa = ms->exa;
379    struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pDstPixmap);
380    struct exa_pixmap_priv *src_priv = exaGetPixmapDriverPrivate(pSrcPixmap);
381
382#if DEBUG_PRINT
383    debug_printf("ExaPrepareCopy\n");
384#endif
385    if (!exa->pipe)
386	XORG_FALLBACK("copy accle not enabled");
387
388    if (!priv || !src_priv)
389	XORG_FALLBACK("copy !priv || !src_priv");
390
391    if (!priv->tex || !src_priv->tex)
392	XORG_FALLBACK("copy !priv->tex || !src_priv->tex");
393
394    if (!EXA_PM_IS_SOLID(&pSrcPixmap->drawable, planeMask))
395	XORG_FALLBACK("copy planeMask is not solid");
396
397    if (alu != GXcopy)
398	XORG_FALLBACK("copy alu not GXcopy");
399
400    if (!exa->scrn->is_format_supported(exa->scrn, priv->tex->format,
401                                        priv->tex->target,
402                                        PIPE_TEXTURE_USAGE_RENDER_TARGET, 0))
403	XORG_FALLBACK("copy pDst format %s", pf_name(priv->tex->format));
404
405    if (!exa->scrn->is_format_supported(exa->scrn, src_priv->tex->format,
406                                        src_priv->tex->target,
407                                        PIPE_TEXTURE_USAGE_SAMPLER, 0))
408	XORG_FALLBACK("copy pSrc format %s", pf_name(src_priv->tex->format));
409
410    exa->copy.src = src_priv;
411    exa->copy.dst = priv;
412
413#if DISABLE_ACCEL
414    return FALSE;
415#else
416    return TRUE;
417#endif
418}
419
420static void
421ExaCopy(PixmapPtr pDstPixmap, int srcX, int srcY, int dstX, int dstY,
422	int width, int height)
423{
424   ScrnInfoPtr pScrn = xf86Screens[pDstPixmap->drawable.pScreen->myNum];
425   modesettingPtr ms = modesettingPTR(pScrn);
426   struct exa_context *exa = ms->exa;
427   struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pDstPixmap);
428
429#if DEBUG_PRINT
430   debug_printf("\tExaCopy(srcx=%d, srcy=%d, dstX=%d, dstY=%d, w=%d, h=%d)\n",
431                srcX, srcY, dstX, dstY, width, height);
432#endif
433
434   debug_assert(priv == exa->copy.dst);
435
436   xorg_copy_pixmap(exa, exa->copy.dst, dstX, dstY,
437                    exa->copy.src, srcX, srcY,
438                    width, height);
439}
440
441static Bool
442ExaPrepareComposite(int op, PicturePtr pSrcPicture,
443		    PicturePtr pMaskPicture, PicturePtr pDstPicture,
444		    PixmapPtr pSrc, PixmapPtr pMask, PixmapPtr pDst)
445{
446   ScrnInfoPtr pScrn = xf86Screens[pDst->drawable.pScreen->myNum];
447   modesettingPtr ms = modesettingPTR(pScrn);
448   struct exa_context *exa = ms->exa;
449   struct exa_pixmap_priv *priv;
450
451#if DEBUG_PRINT
452   debug_printf("ExaPrepareComposite\n");
453#endif
454   if (!exa->pipe)
455      XORG_FALLBACK("comp accle not enabled");
456
457   priv = exaGetPixmapDriverPrivate(pDst);
458   if (!priv || !priv->tex)
459      XORG_FALLBACK("comp pDst %s", !priv ? "!priv" : "!priv->tex");
460
461   if (!exa->scrn->is_format_supported(exa->scrn, priv->tex->format,
462                                       priv->tex->target,
463                                       PIPE_TEXTURE_USAGE_RENDER_TARGET, 0))
464      XORG_FALLBACK("copy pDst format: %s", pf_name(priv->tex->format));
465
466   if (pSrc) {
467      priv = exaGetPixmapDriverPrivate(pSrc);
468      if (!priv || !priv->tex)
469         XORG_FALLBACK("comp pSrc %s", !priv ? "!priv" : "!priv->tex");
470
471      if (!exa->scrn->is_format_supported(exa->scrn, priv->tex->format,
472                                          priv->tex->target,
473                                          PIPE_TEXTURE_USAGE_SAMPLER, 0))
474         XORG_FALLBACK("copy pSrc format: %s", pf_name(priv->tex->format));
475   }
476
477   if (pMask) {
478      priv = exaGetPixmapDriverPrivate(pMask);
479      if (!priv || !priv->tex)
480         XORG_FALLBACK("comp pMask %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("copy pMask format: %s", pf_name(priv->tex->format));
486   }
487
488#if DISABLE_ACCEL
489   (void) exa;
490   return FALSE;
491#else
492   return xorg_composite_bind_state(exa, op, pSrcPicture, pMaskPicture,
493                                    pDstPicture,
494                                    pSrc ? exaGetPixmapDriverPrivate(pSrc) : NULL,
495                                    pMask ? exaGetPixmapDriverPrivate(pMask) : NULL,
496                                    exaGetPixmapDriverPrivate(pDst));
497#endif
498}
499
500static void
501ExaComposite(PixmapPtr pDst, int srcX, int srcY, int maskX, int maskY,
502	     int dstX, int dstY, int width, int height)
503{
504   ScrnInfoPtr pScrn = xf86Screens[pDst->drawable.pScreen->myNum];
505   modesettingPtr ms = modesettingPTR(pScrn);
506   struct exa_context *exa = ms->exa;
507   struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pDst);
508
509#if DEBUG_PRINT
510   debug_printf("\tExaComposite\n");
511#endif
512
513   xorg_composite(exa, priv, srcX, srcY, maskX, maskY,
514                  dstX, dstY, width, height);
515}
516
517static Bool
518ExaCheckComposite(int op,
519		  PicturePtr pSrcPicture, PicturePtr pMaskPicture,
520		  PicturePtr pDstPicture)
521{
522   boolean accelerated = xorg_composite_accelerated(op,
523                                                    pSrcPicture,
524                                                    pMaskPicture,
525                                                    pDstPicture);
526#if DEBUG_PRINT
527   debug_printf("ExaCheckComposite(%d, %p, %p, %p) = %d\n",
528                op, pSrcPicture, pMaskPicture, pDstPicture, accelerated);
529#endif
530   return accelerated;
531}
532
533static void *
534ExaCreatePixmap(ScreenPtr pScreen, int size, int align)
535{
536    struct exa_pixmap_priv *priv;
537
538    priv = xcalloc(1, sizeof(struct exa_pixmap_priv));
539    if (!priv)
540	return NULL;
541
542    return priv;
543}
544
545static void
546ExaDestroyPixmap(ScreenPtr pScreen, void *dPriv)
547{
548    struct exa_pixmap_priv *priv = (struct exa_pixmap_priv *)dPriv;
549
550    if (!priv)
551	return;
552
553    pipe_texture_reference(&priv->tex, NULL);
554
555    xfree(priv);
556}
557
558static Bool
559ExaPixmapIsOffscreen(PixmapPtr pPixmap)
560{
561    struct exa_pixmap_priv *priv;
562
563    priv = exaGetPixmapDriverPrivate(pPixmap);
564
565    if (!priv)
566	return FALSE;
567
568    if (priv->tex)
569	return TRUE;
570
571    return FALSE;
572}
573
574int
575xorg_exa_set_displayed_usage(PixmapPtr pPixmap)
576{
577    struct exa_pixmap_priv *priv;
578    priv = exaGetPixmapDriverPrivate(pPixmap);
579
580    if (!priv) {
581	FatalError("NO PIXMAP PRIVATE\n");
582	return 0;
583    }
584
585    priv->flags |= PIPE_TEXTURE_USAGE_PRIMARY;
586
587    return 0;
588}
589
590int
591xorg_exa_set_shared_usage(PixmapPtr pPixmap)
592{
593    struct exa_pixmap_priv *priv;
594    priv = exaGetPixmapDriverPrivate(pPixmap);
595
596    if (!priv) {
597	FatalError("NO PIXMAP PRIVATE\n");
598	return 0;
599    }
600
601    priv->flags |= PIPE_TEXTURE_USAGE_DISPLAY_TARGET;
602
603    return 0;
604}
605
606unsigned
607xorg_exa_get_pixmap_handle(PixmapPtr pPixmap, unsigned *stride_out)
608{
609    ScreenPtr pScreen = pPixmap->drawable.pScreen;
610    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
611    modesettingPtr ms = modesettingPTR(pScrn);
612    struct exa_pixmap_priv *priv;
613    unsigned handle;
614    unsigned stride;
615
616    if (!ms->exa) {
617	FatalError("NO MS->EXA\n");
618	return 0;
619    }
620
621    priv = exaGetPixmapDriverPrivate(pPixmap);
622
623    if (!priv) {
624	FatalError("NO PIXMAP PRIVATE\n");
625	return 0;
626    }
627
628    ms->api->local_handle_from_texture(ms->api, ms->screen, priv->tex, &stride, &handle);
629    if (stride_out)
630	*stride_out = stride;
631
632    return handle;
633}
634
635static Bool
636ExaModifyPixmapHeader(PixmapPtr pPixmap, int width, int height,
637		      int depth, int bitsPerPixel, int devKind,
638		      pointer pPixData)
639{
640    ScreenPtr pScreen = pPixmap->drawable.pScreen;
641    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
642    struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pPixmap);
643    modesettingPtr ms = modesettingPTR(pScrn);
644    struct exa_context *exa = ms->exa;
645
646    if (!priv || pPixData)
647	return FALSE;
648
649    if (depth <= 0)
650	depth = pPixmap->drawable.depth;
651
652    if (bitsPerPixel <= 0)
653	bitsPerPixel = pPixmap->drawable.bitsPerPixel;
654
655    if (width <= 0)
656	width = pPixmap->drawable.width;
657
658    if (height <= 0)
659	height = pPixmap->drawable.height;
660
661    if (width <= 0 || height <= 0 || depth <= 0)
662	return FALSE;
663
664    miModifyPixmapHeader(pPixmap, width, height, depth,
665			     bitsPerPixel, devKind, NULL);
666
667    /* Deal with screen resize */
668    if (!priv->tex ||
669        (priv->tex->width[0] != width ||
670         priv->tex->height[0] != height ||
671         priv->tex_flags != priv->flags)) {
672	struct pipe_texture *texture = NULL;
673
674#ifdef DRM_MODE_FEATURE_DIRTYFB
675	if (priv->flags)
676#endif
677	{
678	    struct pipe_texture template;
679
680	    memset(&template, 0, sizeof(template));
681	    template.target = PIPE_TEXTURE_2D;
682	    exa_get_pipe_format(depth, &template.format, &bitsPerPixel);
683	    pf_get_block(template.format, &template.block);
684	    template.width[0] = width;
685	    template.height[0] = height;
686	    template.depth[0] = 1;
687	    template.last_level = 0;
688	    template.tex_usage = PIPE_TEXTURE_USAGE_RENDER_TARGET | priv->flags;
689	    priv->tex_flags = priv->flags;
690	    texture = exa->scrn->texture_create(exa->scrn, &template);
691
692	    if (priv->tex) {
693		struct pipe_surface *dst_surf;
694                struct pipe_surface *src_surf;
695
696		dst_surf = exa->scrn->get_tex_surface(
697                   exa->scrn, texture, 0, 0, 0, PIPE_BUFFER_USAGE_GPU_WRITE);
698		src_surf = exa_gpu_surface(exa, priv);
699		exa->pipe->surface_copy(exa->pipe, dst_surf, 0, 0, src_surf,
700                                        0, 0, min(width, texture->width[0]),
701                                        min(height, texture->height[0]));
702		exa->scrn->tex_surface_destroy(dst_surf);
703		exa->scrn->tex_surface_destroy(src_surf);
704	    } else if (pPixmap->devPrivate.ptr) {
705		struct pipe_transfer *transfer;
706
707		if (priv->map_count != 0)
708		     FatalError("doing ExaModifyPixmapHeader on mapped buffer\n");
709
710		transfer =
711		    exa->scrn->get_tex_transfer(exa->scrn, texture, 0, 0, 0,
712						PIPE_TRANSFER_WRITE,
713						0, 0, width, height);
714		util_copy_rect(exa->scrn->transfer_map(exa->scrn, transfer),
715			       &texture->block, transfer->stride, 0, 0,
716			       width, height, pPixmap->devPrivate.ptr,
717			       pPixmap->devKind, 0, 0);
718		exa->scrn->transfer_unmap(exa->scrn, transfer);
719		exa->scrn->tex_transfer_destroy(transfer);
720
721		xfree(pPixmap->devPrivate.ptr);
722		pPixmap->devPrivate.ptr = NULL;
723	    }
724	}
725#ifdef DRM_MODE_FEATURE_DIRTYFB
726	else {
727	    xfree(pPixmap->devPrivate.ptr);
728	    pPixmap->devPrivate.ptr = xalloc(pPixmap->drawable.height *
729					     pPixmap->devKind);
730	}
731#endif
732
733	pipe_texture_reference(&priv->tex, texture);
734	/* the texture we create has one reference */
735	pipe_texture_reference(&texture, NULL);
736    }
737
738    return TRUE;
739}
740
741struct pipe_texture *
742xorg_exa_get_texture(PixmapPtr pPixmap)
743{
744   struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pPixmap);
745   struct pipe_texture *tex = NULL;
746   pipe_texture_reference(&tex, priv->tex);
747   return tex;
748}
749
750void
751xorg_exa_close(ScrnInfoPtr pScrn)
752{
753   modesettingPtr ms = modesettingPTR(pScrn);
754   struct exa_context *exa = ms->exa;
755   struct pipe_constant_buffer *vsbuf = &exa->vs_const_buffer;
756   struct pipe_constant_buffer *fsbuf = &exa->fs_const_buffer;
757
758   if (exa->shaders) {
759      xorg_shaders_destroy(exa->shaders);
760   }
761
762   if (vsbuf && vsbuf->buffer)
763      pipe_buffer_reference(&vsbuf->buffer, NULL);
764
765   if (fsbuf && fsbuf->buffer)
766      pipe_buffer_reference(&fsbuf->buffer, NULL);
767
768   if (exa->cso) {
769      cso_release_all(exa->cso);
770      cso_destroy_context(exa->cso);
771   }
772
773   if (exa->pipe)
774      exa->pipe->destroy(exa->pipe);
775
776   exaDriverFini(pScrn->pScreen);
777   xfree(exa);
778   ms->exa = NULL;
779}
780
781void *
782xorg_exa_init(ScrnInfoPtr pScrn)
783{
784   modesettingPtr ms = modesettingPTR(pScrn);
785   struct exa_context *exa;
786   ExaDriverPtr pExa;
787
788   exa = xcalloc(1, sizeof(struct exa_context));
789   if (!exa)
790      return NULL;
791
792   pExa = exaDriverAlloc();
793   if (!pExa) {
794      goto out_err;
795   }
796
797   memset(pExa, 0, sizeof(*pExa));
798
799   pExa->exa_major         = 2;
800   pExa->exa_minor         = 2;
801   pExa->memoryBase        = 0;
802   pExa->memorySize        = 0;
803   pExa->offScreenBase     = 0;
804   pExa->pixmapOffsetAlign = 0;
805   pExa->pixmapPitchAlign  = 1;
806   pExa->flags             = EXA_OFFSCREEN_PIXMAPS | EXA_HANDLES_PIXMAPS;
807#ifdef EXA_SUPPORTS_PREPARE_AUX
808   pExa->flags            |= EXA_SUPPORTS_PREPARE_AUX;
809#endif
810#ifdef EXA_MIXED_PIXMAPS
811   pExa->flags            |= EXA_MIXED_PIXMAPS;
812#endif
813   pExa->maxX              = 8191; /* FIXME */
814   pExa->maxY              = 8191; /* FIXME */
815
816   pExa->WaitMarker         = ExaWaitMarker;
817   pExa->MarkSync           = ExaMarkSync;
818   pExa->PrepareSolid       = ExaPrepareSolid;
819   pExa->Solid              = ExaSolid;
820   pExa->DoneSolid          = ExaDone;
821   pExa->PrepareCopy        = ExaPrepareCopy;
822   pExa->Copy               = ExaCopy;
823   pExa->DoneCopy           = ExaDone;
824   pExa->CheckComposite     = ExaCheckComposite;
825   pExa->PrepareComposite   = ExaPrepareComposite;
826   pExa->Composite          = ExaComposite;
827   pExa->DoneComposite      = ExaDoneComposite;
828   pExa->PixmapIsOffscreen  = ExaPixmapIsOffscreen;
829   pExa->DownloadFromScreen = ExaDownloadFromScreen;
830   pExa->UploadToScreen     = ExaUploadToScreen;
831   pExa->PrepareAccess      = ExaPrepareAccess;
832   pExa->FinishAccess       = ExaFinishAccess;
833   pExa->CreatePixmap       = ExaCreatePixmap;
834   pExa->DestroyPixmap      = ExaDestroyPixmap;
835   pExa->ModifyPixmapHeader = ExaModifyPixmapHeader;
836
837   if (!exaDriverInit(pScrn->pScreen, pExa)) {
838      goto out_err;
839   }
840
841   exa->scrn = ms->screen;
842   exa->pipe = ms->api->create_context(ms->api, exa->scrn);
843   /* Share context with DRI */
844   ms->ctx = exa->pipe;
845
846   exa->cso = cso_create_context(exa->pipe);
847   exa->shaders = xorg_shaders_create(exa);
848
849   xorg_exa_init_state(exa);
850
851   return (void *)exa;
852
853out_err:
854   xorg_exa_close(pScrn);
855
856   return NULL;
857}
858
859struct pipe_surface *
860exa_gpu_surface(struct exa_context *exa, struct exa_pixmap_priv *priv)
861{
862   return exa->scrn->get_tex_surface(exa->scrn, priv->tex, 0, 0, 0,
863                                     PIPE_BUFFER_USAGE_GPU_READ |
864                                     PIPE_BUFFER_USAGE_GPU_WRITE);
865
866}
867
868void xorg_exa_flush(struct exa_context *exa, uint pipeFlushFlags,
869                    struct pipe_fence_handle **fence)
870{
871   exa->pipe->flush(exa->pipe, pipeFlushFlags, fence);
872}
873
874void xorg_exa_finish(struct exa_context *exa)
875{
876   struct pipe_fence_handle *fence = NULL;
877
878   xorg_exa_flush(exa, PIPE_FLUSH_RENDER_CACHE, &fence);
879
880   exa->pipe->screen->fence_finish(exa->pipe->screen, fence, 0);
881   exa->pipe->screen->fence_reference(exa->pipe->screen, &fence, NULL);
882}
883
884