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