st/xorg: Don't always fall back for solid fills.
[mesa.git] / src / gallium / state_trackers / xorg / xorg_exa.c
1 /*
2 * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
3 * All Rights Reserved.
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the
7 * "Software"), to deal in the Software without restriction, including
8 * without limitation the rights to use, copy, modify, merge, publish,
9 * distribute, sub license, and/or sell copies of the Software, and to
10 * permit persons to whom the Software is furnished to do so, subject to
11 * the following conditions:
12 *
13 * The above copyright notice and this permission notice (including the
14 * next paragraph) shall be included in all copies or substantial portions
15 * of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
20 * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
21 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
22 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
23 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 *
25 *
26 * Author: Alan Hourihane <alanh@tungstengraphics.com>
27 * Author: Jakob Bornecrantz <wallbraker@gmail.com>
28 *
29 */
30
31 #include "xorg_exa.h"
32 #include "xorg_tracker.h"
33 #include "xorg_composite.h"
34 #include "xorg_exa_tgsi.h"
35
36 #include <xorg-server.h>
37 #include <xf86.h>
38 #include <picturestr.h>
39 #include <picture.h>
40
41 #include "pipe/p_format.h"
42 #include "pipe/p_context.h"
43 #include "pipe/p_state.h"
44 #include "pipe/p_inlines.h"
45
46 #include "cso_cache/cso_context.h"
47
48 #include "util/u_rect.h"
49
50 /*
51 * Helper functions
52 */
53
54 static void
55 exa_get_pipe_format(int depth, enum pipe_format *format, int *bbp)
56 {
57 switch (depth) {
58 case 32:
59 *format = PIPE_FORMAT_A8R8G8B8_UNORM;
60 assert(*bbp == 32);
61 break;
62 case 24:
63 *format = PIPE_FORMAT_X8R8G8B8_UNORM;
64 assert(*bbp == 32);
65 break;
66 case 16:
67 *format = PIPE_FORMAT_R5G6B5_UNORM;
68 assert(*bbp == 16);
69 break;
70 case 15:
71 *format = PIPE_FORMAT_A1R5G5B5_UNORM;
72 assert(*bbp == 16);
73 break;
74 case 8:
75 case 4:
76 case 1:
77 *format = PIPE_FORMAT_A8R8G8B8_UNORM; /* bad bad bad */
78 break;
79 default:
80 assert(0);
81 break;
82 }
83 }
84
85 /*
86 * Static exported EXA functions
87 */
88
89 static void
90 ExaWaitMarker(ScreenPtr pScreen, int marker)
91 {
92 }
93
94 static int
95 ExaMarkSync(ScreenPtr pScreen)
96 {
97 return 1;
98 }
99
100 static Bool
101 ExaPrepareAccess(PixmapPtr pPix, int index)
102 {
103 ScreenPtr pScreen = pPix->drawable.pScreen;
104 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
105 modesettingPtr ms = modesettingPTR(pScrn);
106 struct exa_context *exa = ms->exa;
107 struct exa_pixmap_priv *priv;
108
109 priv = exaGetPixmapDriverPrivate(pPix);
110
111 if (!priv)
112 return FALSE;
113
114 if (!priv->tex)
115 return FALSE;
116
117 if (priv->map_count++ == 0)
118 {
119 if (exa->ctx->is_texture_referenced(exa->ctx, priv->tex, 0, 0) &
120 PIPE_REFERENCED_FOR_WRITE)
121 exa->ctx->flush(exa->ctx, 0, NULL);
122
123 priv->map_transfer =
124 exa->scrn->get_tex_transfer(exa->scrn, priv->tex, 0, 0, 0,
125 PIPE_TRANSFER_READ_WRITE,
126 0, 0, priv->tex->width[0], priv->tex->height[0]);
127
128 pPix->devPrivate.ptr =
129 exa->scrn->transfer_map(exa->scrn, priv->map_transfer);
130 pPix->devKind = priv->map_transfer->stride;
131 }
132
133 return TRUE;
134 }
135
136 static void
137 ExaFinishAccess(PixmapPtr pPix, int index)
138 {
139 ScreenPtr pScreen = pPix->drawable.pScreen;
140 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
141 modesettingPtr ms = modesettingPTR(pScrn);
142 struct exa_context *exa = ms->exa;
143 struct exa_pixmap_priv *priv;
144 priv = exaGetPixmapDriverPrivate(pPix);
145
146 if (!priv)
147 return;
148
149 if (!priv->map_transfer)
150 return;
151
152 if (--priv->map_count == 0) {
153 assert(priv->map_transfer);
154 exa->scrn->transfer_unmap(exa->scrn, priv->map_transfer);
155 exa->scrn->tex_transfer_destroy(priv->map_transfer);
156 priv->map_transfer = NULL;
157 pPix->devPrivate.ptr = NULL;
158 }
159 }
160
161 static void
162 ExaDone(PixmapPtr pPixmap)
163 {
164 ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum];
165 modesettingPtr ms = modesettingPTR(pScrn);
166 struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pPixmap);
167 struct exa_context *exa = ms->exa;
168
169 if (!priv)
170 return;
171
172 if (priv->src_surf)
173 exa->scrn->tex_surface_destroy(priv->src_surf);
174 priv->src_surf = NULL;
175 }
176
177 static void
178 ExaDoneComposite(PixmapPtr pPixmap)
179 {
180
181 }
182
183 static Bool
184 ExaPrepareSolid(PixmapPtr pPixmap, int alu, Pixel planeMask, Pixel fg)
185 {
186 ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum];
187 modesettingPtr ms = modesettingPTR(pScrn);
188 struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pPixmap);
189 struct exa_context *exa = ms->exa;
190
191 if (pPixmap->drawable.depth < 15)
192 return FALSE;
193
194 if (!EXA_PM_IS_SOLID(&pPixmap->drawable, planeMask))
195 return FALSE;
196
197 if (!priv || !priv->tex)
198 return FALSE;
199
200 if (alu != GXcopy)
201 return FALSE;
202
203 if (!exa->ctx || !exa->ctx->surface_fill)
204 return FALSE;
205
206 priv->color = fg;
207
208 return TRUE;
209 }
210
211 static void
212 ExaSolid(PixmapPtr pPixmap, int x0, int y0, int x1, int y1)
213 {
214 ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum];
215 modesettingPtr ms = modesettingPTR(pScrn);
216 struct exa_context *exa = ms->exa;
217 struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pPixmap);
218 struct pipe_surface *surf = exa_gpu_surface(exa, priv);
219
220 exa->ctx->surface_fill(exa->ctx, surf, x0, y0, x1 - x0, y1 - y0,
221 priv->color);
222
223 exa->scrn->tex_surface_destroy(surf);
224 }
225
226 static Bool
227 ExaPrepareCopy(PixmapPtr pSrcPixmap, PixmapPtr pDstPixmap, int xdir,
228 int ydir, int alu, Pixel planeMask)
229 {
230 ScrnInfoPtr pScrn = xf86Screens[pDstPixmap->drawable.pScreen->myNum];
231 modesettingPtr ms = modesettingPTR(pScrn);
232 struct exa_context *exa = ms->exa;
233 struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pDstPixmap);
234 struct exa_pixmap_priv *src_priv = exaGetPixmapDriverPrivate(pSrcPixmap);
235
236 if (alu != GXcopy)
237 return FALSE;
238
239 if (pSrcPixmap->drawable.depth < 15 || pDstPixmap->drawable.depth < 15)
240 return FALSE;
241
242 if (!EXA_PM_IS_SOLID(&pSrcPixmap->drawable, planeMask))
243 return FALSE;
244
245 if (!priv || !src_priv)
246 return FALSE;
247
248 if (!priv->tex || !src_priv->tex)
249 return FALSE;
250
251 if (!exa->ctx || !exa->ctx->surface_copy)
252 return FALSE;
253
254 priv->src_surf = exa_gpu_surface(exa, src_priv);
255
256 return TRUE;
257 }
258
259 static void
260 ExaCopy(PixmapPtr pDstPixmap, int srcX, int srcY, int dstX, int dstY,
261 int width, int height)
262 {
263 ScrnInfoPtr pScrn = xf86Screens[pDstPixmap->drawable.pScreen->myNum];
264 modesettingPtr ms = modesettingPTR(pScrn);
265 struct exa_context *exa = ms->exa;
266 struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pDstPixmap);
267 struct pipe_surface *surf = exa_gpu_surface(exa, priv);
268
269 exa->ctx->surface_copy(exa->ctx, surf, dstX, dstY, priv->src_surf,
270 srcX, srcY, width, height);
271 exa->scrn->tex_surface_destroy(surf);
272 }
273
274 static Bool
275 ExaPrepareComposite(int op, PicturePtr pSrcPicture,
276 PicturePtr pMaskPicture, PicturePtr pDstPicture,
277 PixmapPtr pSrc, PixmapPtr pMask, PixmapPtr pDst)
278 {
279 ScrnInfoPtr pScrn = xf86Screens[pDst->drawable.pScreen->myNum];
280 modesettingPtr ms = modesettingPTR(pScrn);
281 struct exa_context *exa = ms->exa;
282
283 return xorg_composite_bind_state(exa, op, pSrcPicture, pMaskPicture,
284 pDstPicture,
285 exaGetPixmapDriverPrivate(pSrc),
286 exaGetPixmapDriverPrivate(pMask),
287 exaGetPixmapDriverPrivate(pDst));
288 }
289
290 static void
291 ExaComposite(PixmapPtr pDst, int srcX, int srcY, int maskX, int maskY,
292 int dstX, int dstY, int width, int height)
293 {
294 ScrnInfoPtr pScrn = xf86Screens[pDst->drawable.pScreen->myNum];
295 modesettingPtr ms = modesettingPTR(pScrn);
296 struct exa_context *exa = ms->exa;
297 struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pDst);
298
299 xorg_composite(exa, priv, srcX, srcY, maskX, maskY,
300 dstX, dstY, width, height);
301 }
302
303 static Bool
304 ExaCheckComposite(int op,
305 PicturePtr pSrcPicture, PicturePtr pMaskPicture,
306 PicturePtr pDstPicture)
307 {
308 return xorg_composite_accelerated(op,
309 pSrcPicture,
310 pMaskPicture,
311 pDstPicture);
312 }
313
314 static void *
315 ExaCreatePixmap(ScreenPtr pScreen, int size, int align)
316 {
317 struct exa_pixmap_priv *priv;
318
319 priv = xcalloc(1, sizeof(struct exa_pixmap_priv));
320 if (!priv)
321 return NULL;
322
323 return priv;
324 }
325
326 static void
327 ExaDestroyPixmap(ScreenPtr pScreen, void *dPriv)
328 {
329 struct exa_pixmap_priv *priv = (struct exa_pixmap_priv *)dPriv;
330 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
331 modesettingPtr ms = modesettingPTR(pScrn);
332
333 if (!priv)
334 return;
335
336 if (priv->tex)
337 ms->screen->texture_destroy(priv->tex);
338
339 xfree(priv);
340 }
341
342 static Bool
343 ExaPixmapIsOffscreen(PixmapPtr pPixmap)
344 {
345 struct exa_pixmap_priv *priv;
346
347 priv = exaGetPixmapDriverPrivate(pPixmap);
348
349 if (!priv)
350 return FALSE;
351
352 if (priv->tex)
353 return TRUE;
354
355 return FALSE;
356 }
357
358 int
359 xorg_exa_set_displayed_usage(PixmapPtr pPixmap)
360 {
361 struct exa_pixmap_priv *priv;
362 priv = exaGetPixmapDriverPrivate(pPixmap);
363
364 if (!priv) {
365 FatalError("NO PIXMAP PRIVATE\n");
366 return 0;
367 }
368
369 priv->flags |= PIPE_TEXTURE_USAGE_PRIMARY;
370
371 return 0;
372 }
373
374 int
375 xorg_exa_set_shared_usage(PixmapPtr pPixmap)
376 {
377 struct exa_pixmap_priv *priv;
378 priv = exaGetPixmapDriverPrivate(pPixmap);
379
380 if (!priv) {
381 FatalError("NO PIXMAP PRIVATE\n");
382 return 0;
383 }
384
385 priv->flags |= PIPE_TEXTURE_USAGE_DISPLAY_TARGET;
386
387 return 0;
388 }
389
390 unsigned
391 xorg_exa_get_pixmap_handle(PixmapPtr pPixmap, unsigned *stride_out)
392 {
393 ScreenPtr pScreen = pPixmap->drawable.pScreen;
394 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
395 modesettingPtr ms = modesettingPTR(pScrn);
396 struct exa_pixmap_priv *priv;
397 unsigned handle;
398 unsigned stride;
399
400 if (!ms->exa) {
401 FatalError("NO MS->EXA\n");
402 return 0;
403 }
404
405 priv = exaGetPixmapDriverPrivate(pPixmap);
406
407 if (!priv) {
408 FatalError("NO PIXMAP PRIVATE\n");
409 return 0;
410 }
411
412 ms->api->local_handle_from_texture(ms->api, ms->screen, priv->tex, &stride, &handle);
413 if (stride_out)
414 *stride_out = stride;
415
416 return handle;
417 }
418
419 static Bool
420 ExaModifyPixmapHeader(PixmapPtr pPixmap, int width, int height,
421 int depth, int bitsPerPixel, int devKind,
422 pointer pPixData)
423 {
424 ScreenPtr pScreen = pPixmap->drawable.pScreen;
425 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
426 struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pPixmap);
427 modesettingPtr ms = modesettingPTR(pScrn);
428 struct exa_context *exa = ms->exa;
429
430 if (!priv)
431 return FALSE;
432
433 if (depth <= 0)
434 depth = pPixmap->drawable.depth;
435
436 if (bitsPerPixel <= 0)
437 bitsPerPixel = pPixmap->drawable.bitsPerPixel;
438
439 if (width <= 0)
440 width = pPixmap->drawable.width;
441
442 if (height <= 0)
443 height = pPixmap->drawable.height;
444
445 if (width <= 0 || height <= 0 || depth <= 0)
446 return FALSE;
447
448 miModifyPixmapHeader(pPixmap, width, height, depth,
449 bitsPerPixel, devKind, NULL);
450
451 /* Deal with screen resize */
452 if (priv->tex && (priv->tex->width[0] != width ||
453 priv->tex->height[0] != height ||
454 priv->tex_flags != priv->flags)) {
455 pipe_texture_reference(&priv->tex, NULL);
456 }
457
458 if (!priv->tex
459 #ifdef DRM_MODE_FEATURE_DIRTYFB
460 && priv->flags
461 #endif
462 ) {
463 struct pipe_texture template;
464
465 memset(&template, 0, sizeof(template));
466 template.target = PIPE_TEXTURE_2D;
467 exa_get_pipe_format(depth, &template.format, &bitsPerPixel);
468 pf_get_block(template.format, &template.block);
469 template.width[0] = width;
470 template.height[0] = height;
471 template.depth[0] = 1;
472 template.last_level = 0;
473 template.tex_usage = PIPE_TEXTURE_USAGE_RENDER_TARGET | priv->flags;
474 priv->tex_flags = priv->flags;
475 priv->tex = exa->scrn->texture_create(exa->scrn, &template);
476 }
477
478 #ifdef DRM_MODE_FEATURE_DIRTYFB
479 if (!priv->tex) {
480 if (pPixData)
481 pPixmap->devPrivate.ptr = pPixData;
482 else
483 pPixmap->devPrivate.ptr = xalloc(pPixmap->drawable.height * pPixmap->devKind);
484 } else
485 #endif
486 if (pPixData) {
487 struct pipe_transfer *transfer =
488 exa->scrn->get_tex_transfer(exa->scrn, priv->tex, 0, 0, 0,
489 PIPE_TRANSFER_WRITE,
490 0, 0, width, height);
491 util_copy_rect(exa->scrn->transfer_map(exa->scrn, transfer),
492 &priv->tex->block, transfer->stride, 0, 0,
493 width, height, pPixData, pPixmap->devKind, 0, 0);
494 exa->scrn->transfer_unmap(exa->scrn, transfer);
495 exa->scrn->tex_transfer_destroy(transfer);
496 } else if (priv->tex && pPixmap->devPrivate.ptr) {
497 struct pipe_transfer *transfer;
498
499 if (priv->map_count != 0)
500 FatalError("doing ExaModifyPixmapHeader on mapped buffer\n");
501
502 transfer =
503 exa->scrn->get_tex_transfer(exa->scrn, priv->tex, 0, 0, 0,
504 PIPE_TRANSFER_WRITE,
505 0, 0, width, height);
506 util_copy_rect(exa->scrn->transfer_map(exa->scrn, transfer),
507 &priv->tex->block, transfer->stride, 0, 0,
508 width, height, pPixmap->devPrivate.ptr, pPixmap->devKind, 0, 0);
509 exa->scrn->transfer_unmap(exa->scrn, transfer);
510 exa->scrn->tex_transfer_destroy(transfer);
511 }
512
513 return TRUE;
514 }
515
516 struct pipe_texture *
517 xorg_exa_get_texture(PixmapPtr pPixmap)
518 {
519 struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pPixmap);
520 struct pipe_texture *tex = NULL;
521 pipe_texture_reference(&tex, priv->tex);
522 return tex;
523 }
524
525 void
526 xorg_exa_close(ScrnInfoPtr pScrn)
527 {
528 modesettingPtr ms = modesettingPTR(pScrn);
529 struct exa_context *exa = ms->exa;
530 struct pipe_constant_buffer *vsbuf = &exa->vs_const_buffer;
531 struct pipe_constant_buffer *fsbuf = &exa->fs_const_buffer;
532
533 if (exa->shaders) {
534 xorg_shaders_destroy(exa->shaders);
535 }
536
537 if (vsbuf && vsbuf->buffer)
538 pipe_buffer_reference(&vsbuf->buffer, NULL);
539
540 if (fsbuf && fsbuf->buffer)
541 pipe_buffer_reference(&fsbuf->buffer, NULL);
542
543 if (exa->cso) {
544 cso_release_all(exa->cso);
545 cso_destroy_context(exa->cso);
546 }
547
548 if (exa->ctx)
549 exa->ctx->destroy(exa->ctx);
550
551 exaDriverFini(pScrn->pScreen);
552 xfree(exa);
553 ms->exa = NULL;
554 }
555
556 void *
557 xorg_exa_init(ScrnInfoPtr pScrn)
558 {
559 modesettingPtr ms = modesettingPTR(pScrn);
560 struct exa_context *exa;
561 ExaDriverPtr pExa;
562
563 exa = xcalloc(1, sizeof(struct exa_context));
564 if (!exa)
565 return NULL;
566
567 pExa = exaDriverAlloc();
568 if (!pExa) {
569 goto out_err;
570 }
571
572 memset(pExa, 0, sizeof(*pExa));
573
574 pExa->exa_major = 2;
575 pExa->exa_minor = 2;
576 pExa->memoryBase = 0;
577 pExa->memorySize = 0;
578 pExa->offScreenBase = 0;
579 pExa->pixmapOffsetAlign = 0;
580 pExa->pixmapPitchAlign = 1;
581 pExa->flags = EXA_OFFSCREEN_PIXMAPS | EXA_HANDLES_PIXMAPS;
582 pExa->maxX = 8191; /* FIXME */
583 pExa->maxY = 8191; /* FIXME */
584
585 pExa->WaitMarker = ExaWaitMarker;
586 pExa->MarkSync = ExaMarkSync;
587 pExa->PrepareSolid = ExaPrepareSolid;
588 pExa->Solid = ExaSolid;
589 pExa->DoneSolid = ExaDone;
590 pExa->PrepareCopy = ExaPrepareCopy;
591 pExa->Copy = ExaCopy;
592 pExa->DoneCopy = ExaDone;
593 pExa->CheckComposite = ExaCheckComposite;
594 pExa->PrepareComposite = ExaPrepareComposite;
595 pExa->Composite = ExaComposite;
596 pExa->DoneComposite = ExaDoneComposite;
597 pExa->PixmapIsOffscreen = ExaPixmapIsOffscreen;
598 pExa->PrepareAccess = ExaPrepareAccess;
599 pExa->FinishAccess = ExaFinishAccess;
600 pExa->CreatePixmap = ExaCreatePixmap;
601 pExa->DestroyPixmap = ExaDestroyPixmap;
602 pExa->ModifyPixmapHeader = ExaModifyPixmapHeader;
603
604 if (!exaDriverInit(pScrn->pScreen, pExa)) {
605 goto out_err;
606 }
607
608 exa->scrn = ms->screen;
609 exa->ctx = ms->api->create_context(ms->api, exa->scrn);
610 /* Share context with DRI */
611 ms->ctx = exa->ctx;
612
613 exa->cso = cso_create_context(exa->ctx);
614 exa->shaders = xorg_shaders_create(exa);
615
616 return (void *)exa;
617
618 out_err:
619 xorg_exa_close(pScrn);
620
621 return NULL;
622 }
623
624 struct pipe_surface *
625 exa_gpu_surface(struct exa_context *exa, struct exa_pixmap_priv *priv)
626 {
627 return exa->scrn->get_tex_surface(exa->scrn, priv->tex, 0, 0, 0,
628 PIPE_BUFFER_USAGE_GPU_READ |
629 PIPE_BUFFER_USAGE_GPU_WRITE);
630
631 }
632