xorg: revert bad merge
[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
35 #include <xorg-server.h>
36 #include <xf86.h>
37 #include <picturestr.h>
38 #include <picture.h>
39
40 #include "pipe/p_format.h"
41 #include "pipe/p_context.h"
42 #include "pipe/p_state.h"
43 #include "pipe/p_inlines.h"
44
45 #include "cso_cache/cso_context.h"
46
47 #include "util/u_rect.h"
48
49 /*
50 * Helper functions
51 */
52
53 static void
54 exa_get_pipe_format(int depth, enum pipe_format *format, int *bbp)
55 {
56 switch (depth) {
57 case 32:
58 *format = PIPE_FORMAT_A8R8G8B8_UNORM;
59 assert(*bbp == 32);
60 break;
61 case 24:
62 *format = PIPE_FORMAT_X8R8G8B8_UNORM;
63 assert(*bbp == 32);
64 break;
65 case 16:
66 *format = PIPE_FORMAT_R5G6B5_UNORM;
67 assert(*bbp == 16);
68 break;
69 case 15:
70 *format = PIPE_FORMAT_A1R5G5B5_UNORM;
71 assert(*bbp == 16);
72 break;
73 case 8:
74 case 4:
75 case 1:
76 *format = PIPE_FORMAT_A8R8G8B8_UNORM; /* bad bad bad */
77 break;
78 default:
79 assert(0);
80 break;
81 }
82 }
83
84 /*
85 * Static exported EXA functions
86 */
87
88 static void
89 ExaWaitMarker(ScreenPtr pScreen, int marker)
90 {
91 }
92
93 static int
94 ExaMarkSync(ScreenPtr pScreen)
95 {
96 return 1;
97 }
98
99 static Bool
100 ExaPrepareAccess(PixmapPtr pPix, int index)
101 {
102 ScreenPtr pScreen = pPix->drawable.pScreen;
103 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
104 modesettingPtr ms = modesettingPTR(pScrn);
105 struct exa_context *exa = ms->exa;
106 struct exa_pixmap_priv *priv;
107
108 priv = exaGetPixmapDriverPrivate(pPix);
109
110 if (!priv)
111 return FALSE;
112
113 if (!priv->tex)
114 return FALSE;
115
116 if (priv->map_count++ == 0)
117 {
118 priv->map_transfer =
119 exa->scrn->get_tex_transfer(exa->scrn, priv->tex, 0, 0, 0,
120 PIPE_TRANSFER_READ_WRITE,
121 0, 0, priv->tex->width[0], priv->tex->height[0]);
122
123 pPix->devPrivate.ptr =
124 exa->scrn->transfer_map(exa->scrn, priv->map_transfer);
125 pPix->devKind = priv->map_transfer->stride;
126 }
127
128 return TRUE;
129 }
130
131 static void
132 ExaFinishAccess(PixmapPtr pPix, int index)
133 {
134 ScreenPtr pScreen = pPix->drawable.pScreen;
135 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
136 modesettingPtr ms = modesettingPTR(pScrn);
137 struct exa_context *exa = ms->exa;
138 struct exa_pixmap_priv *priv;
139 priv = exaGetPixmapDriverPrivate(pPix);
140
141 if (!priv)
142 return;
143
144 if (!priv->map_transfer)
145 return;
146
147 if (--priv->map_count == 0) {
148 assert(priv->map_transfer);
149 exa->scrn->transfer_unmap(exa->scrn, priv->map_transfer);
150 exa->scrn->tex_transfer_destroy(priv->map_transfer);
151 priv->map_transfer = NULL;
152 }
153 }
154
155 static void
156 ExaDone(PixmapPtr pPixmap)
157 {
158 ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum];
159 modesettingPtr ms = modesettingPTR(pScrn);
160 struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pPixmap);
161 struct exa_context *exa = ms->exa;
162
163 if (!priv)
164 return;
165
166 if (priv->src_surf)
167 exa->scrn->tex_surface_destroy(priv->src_surf);
168 priv->src_surf = NULL;
169 }
170
171 static void
172 ExaDoneComposite(PixmapPtr pPixmap)
173 {
174
175 }
176
177 static Bool
178 ExaPrepareSolid(PixmapPtr pPixmap, int alu, Pixel planeMask, Pixel fg)
179 {
180 ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum];
181 modesettingPtr ms = modesettingPTR(pScrn);
182 struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pPixmap);
183 struct exa_context *exa = ms->exa;
184
185 if (1)
186 return FALSE;
187
188 if (pPixmap->drawable.depth < 15)
189 return FALSE;
190
191 if (!EXA_PM_IS_SOLID(&pPixmap->drawable, planeMask))
192 return FALSE;
193
194 if (!priv || !priv->tex)
195 return FALSE;
196
197 if (alu != GXcopy)
198 return FALSE;
199
200 if (!exa->ctx || !exa->ctx->surface_fill)
201 return FALSE;
202
203 priv->color = fg;
204
205 return TRUE;
206 }
207
208 static void
209 ExaSolid(PixmapPtr pPixmap, int x0, int y0, int x1, int y1)
210 {
211 ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum];
212 modesettingPtr ms = modesettingPTR(pScrn);
213 struct exa_context *exa = ms->exa;
214 struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pPixmap);
215 struct pipe_surface *surf =
216 exa->scrn->get_tex_surface(exa->scrn, priv->tex, 0, 0, 0,
217 PIPE_BUFFER_USAGE_GPU_READ |
218 PIPE_BUFFER_USAGE_GPU_WRITE);
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 (1)
237 return FALSE;
238
239 if (alu != GXcopy)
240 return FALSE;
241
242 if (pSrcPixmap->drawable.depth < 15 || pDstPixmap->drawable.depth < 15)
243 return FALSE;
244
245 if (!EXA_PM_IS_SOLID(&pSrcPixmap->drawable, planeMask))
246 return FALSE;
247
248 if (!priv || !src_priv)
249 return FALSE;
250
251 if (!priv->tex || !src_priv->tex)
252 return FALSE;
253
254 if (!exa->ctx || !exa->ctx->surface_copy)
255 return FALSE;
256
257 priv->src_surf =
258 exa->scrn->get_tex_surface(exa->scrn, src_priv->tex, 0, 0, 0,
259 PIPE_BUFFER_USAGE_GPU_READ |
260 PIPE_BUFFER_USAGE_GPU_WRITE);
261
262 return TRUE;
263 }
264
265 static void
266 ExaCopy(PixmapPtr pDstPixmap, int srcX, int srcY, int dstX, int dstY,
267 int width, int height)
268 {
269 ScrnInfoPtr pScrn = xf86Screens[pDstPixmap->drawable.pScreen->myNum];
270 modesettingPtr ms = modesettingPTR(pScrn);
271 struct exa_context *exa = ms->exa;
272 struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pDstPixmap);
273 struct pipe_surface *surf =
274 exa->scrn->get_tex_surface(exa->scrn, priv->tex, 0, 0, 0,
275 PIPE_BUFFER_USAGE_GPU_READ |
276 PIPE_BUFFER_USAGE_GPU_WRITE);
277
278 exa->ctx->surface_copy(exa->ctx, surf, dstX, dstY, priv->src_surf,
279 srcX, srcY, width, height);
280 exa->scrn->tex_surface_destroy(surf);
281 }
282
283 static Bool
284 ExaPrepareComposite(int op, PicturePtr pSrcPicture,
285 PicturePtr pMaskPicture, PicturePtr pDstPicture,
286 PixmapPtr pSrc, PixmapPtr pMask, PixmapPtr pDst)
287 {
288 ScrnInfoPtr pScrn = xf86Screens[pDst->drawable.pScreen->myNum];
289 modesettingPtr ms = modesettingPTR(pScrn);
290 struct exa_context *exa = ms->exa;
291
292 return xorg_composite_bind_state(exa, op, pSrcPicture, pMaskPicture,
293 pDstPicture);
294 }
295
296 static void
297 ExaComposite(PixmapPtr pDst, int srcX, int srcY, int maskX, int maskY,
298 int dstX, int dstY, int width, int height)
299 {
300 ScrnInfoPtr pScrn = xf86Screens[pDst->drawable.pScreen->myNum];
301 modesettingPtr ms = modesettingPTR(pScrn);
302 struct exa_context *exa = ms->exa;
303 struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pDst);
304
305 xorg_composite(exa, priv, srcX, srcY, maskX, maskY,
306 dstX, dstY, width, height);
307 }
308
309 static Bool
310 ExaCheckComposite(int op,
311 PicturePtr pSrcPicture, PicturePtr pMaskPicture,
312 PicturePtr pDstPicture)
313 {
314 return xorg_composite_accelerated(op,
315 pSrcPicture,
316 pMaskPicture,
317 pDstPicture);
318 }
319
320 static void *
321 ExaCreatePixmap(ScreenPtr pScreen, int size, int align)
322 {
323 struct exa_pixmap_priv *priv;
324
325 priv = xcalloc(1, sizeof(struct exa_pixmap_priv));
326 if (!priv)
327 return NULL;
328
329 return priv;
330 }
331
332 static void
333 ExaDestroyPixmap(ScreenPtr pScreen, void *dPriv)
334 {
335 struct exa_pixmap_priv *priv = (struct exa_pixmap_priv *)dPriv;
336 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
337 modesettingPtr ms = modesettingPTR(pScrn);
338
339 if (!priv)
340 return;
341
342 if (priv->tex)
343 ms->screen->texture_destroy(priv->tex);
344
345 xfree(priv);
346 }
347
348 static Bool
349 ExaPixmapIsOffscreen(PixmapPtr pPixmap)
350 {
351 struct exa_pixmap_priv *priv;
352
353 priv = exaGetPixmapDriverPrivate(pPixmap);
354
355 if (!priv)
356 return FALSE;
357
358 if (priv->tex)
359 return TRUE;
360
361 return FALSE;
362 }
363
364 int
365 xorg_exa_set_displayed_usage(PixmapPtr pPixmap)
366 {
367 struct exa_pixmap_priv *priv;
368 priv = exaGetPixmapDriverPrivate(pPixmap);
369
370 if (!priv) {
371 FatalError("NO PIXMAP PRIVATE\n");
372 return 0;
373 }
374
375 if (priv->flags & ~PIPE_TEXTURE_USAGE_PRIMARY) {
376 FatalError("BAD FLAGS\n");
377 return 0;
378 }
379 priv->flags = PIPE_TEXTURE_USAGE_PRIMARY;
380
381 return 0;
382 }
383
384 int
385 xorg_exa_set_shared_usage(PixmapPtr pPixmap)
386 {
387 struct exa_pixmap_priv *priv;
388 priv = exaGetPixmapDriverPrivate(pPixmap);
389
390 if (!priv) {
391 FatalError("NO PIXMAP PRIVATE\n");
392 return 0;
393 }
394
395 if (priv->flags & ~PIPE_TEXTURE_USAGE_DISPLAY_TARGET) {
396 FatalError("BAD FLAGS\n");
397 return 0;
398 }
399 priv->flags = PIPE_TEXTURE_USAGE_DISPLAY_TARGET;
400
401 return 0;
402 }
403
404 unsigned
405 xorg_exa_get_pixmap_handle(PixmapPtr pPixmap, unsigned *stride_out)
406 {
407 ScreenPtr pScreen = pPixmap->drawable.pScreen;
408 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
409 modesettingPtr ms = modesettingPTR(pScrn);
410 struct exa_pixmap_priv *priv;
411 struct pipe_buffer *buffer = NULL;
412 unsigned handle;
413 unsigned stride;
414
415 if (!ms->exa) {
416 FatalError("NO MS->EXA\n");
417 return 0;
418 }
419
420 priv = exaGetPixmapDriverPrivate(pPixmap);
421
422 if (!priv) {
423 FatalError("NO PIXMAP PRIVATE\n");
424 return 0;
425 }
426
427 ms->api->buffer_from_texture(ms->api, priv->tex, &buffer, &stride);
428 ms->api->handle_from_buffer(ms->api, ms->screen, buffer, &handle);
429 pipe_buffer_reference(&buffer, NULL);
430 if (stride_out)
431 *stride_out = stride;
432
433 return handle;
434 }
435
436 static Bool
437 ExaModifyPixmapHeader(PixmapPtr pPixmap, int width, int height,
438 int depth, int bitsPerPixel, int devKind,
439 pointer pPixData)
440 {
441 ScreenPtr pScreen = pPixmap->drawable.pScreen;
442 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
443 struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pPixmap);
444 modesettingPtr ms = modesettingPTR(pScrn);
445 struct exa_context *exa = ms->exa;
446
447 if (!priv)
448 return FALSE;
449
450 if (depth <= 0)
451 depth = pPixmap->drawable.depth;
452
453 if (bitsPerPixel <= 0)
454 bitsPerPixel = pPixmap->drawable.bitsPerPixel;
455
456 if (width <= 0)
457 width = pPixmap->drawable.width;
458
459 if (height <= 0)
460 height = pPixmap->drawable.height;
461
462 if (width <= 0 || height <= 0 || depth <= 0)
463 return FALSE;
464
465 miModifyPixmapHeader(pPixmap, width, height, depth,
466 bitsPerPixel, devKind, NULL);
467
468 /* Deal with screen resize */
469 if (priv->tex && (priv->tex->width[0] != width ||
470 priv->tex->height[0] != height ||
471 priv->tex_flags != priv->flags)) {
472 pipe_texture_reference(&priv->tex, NULL);
473 }
474
475 if (!priv->tex) {
476 struct pipe_texture template;
477
478 memset(&template, 0, sizeof(template));
479 template.target = PIPE_TEXTURE_2D;
480 exa_get_pipe_format(depth, &template.format, &bitsPerPixel);
481 pf_get_block(template.format, &template.block);
482 template.width[0] = width;
483 template.height[0] = height;
484 template.depth[0] = 1;
485 template.last_level = 0;
486 template.tex_usage = PIPE_TEXTURE_USAGE_RENDER_TARGET | priv->flags;
487 priv->tex_flags = priv->flags;
488 priv->tex = exa->scrn->texture_create(exa->scrn, &template);
489 }
490
491 if (pPixData) {
492 struct pipe_transfer *transfer =
493 exa->scrn->get_tex_transfer(exa->scrn, priv->tex, 0, 0, 0,
494 PIPE_TRANSFER_WRITE,
495 0, 0, width, height);
496 util_copy_rect(exa->scrn->transfer_map(exa->scrn, transfer),
497 &priv->tex->block, transfer->stride, 0, 0,
498 width, height, pPixData, pPixmap->devKind, 0, 0);
499 exa->scrn->transfer_unmap(exa->scrn, transfer);
500 exa->scrn->tex_transfer_destroy(transfer);
501 }
502
503 return TRUE;
504 }
505
506 struct pipe_texture *
507 xorg_exa_get_texture(PixmapPtr pPixmap)
508 {
509 struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pPixmap);
510 struct pipe_texture *tex = NULL;
511 pipe_texture_reference(&tex, priv->tex);
512 return tex;
513 }
514
515 void
516 xorg_exa_close(ScrnInfoPtr pScrn)
517 {
518 modesettingPtr ms = modesettingPTR(pScrn);
519 struct exa_context *exa = ms->exa;
520
521 if (exa->cso) {
522 cso_release_all(exa->cso);
523 cso_destroy_context(exa->cso);
524 }
525
526 if (exa->ctx)
527 exa->ctx->destroy(exa->ctx);
528
529 exaDriverFini(pScrn->pScreen);
530 xfree(exa);
531 ms->exa = NULL;
532 }
533
534 void *
535 xorg_exa_init(ScrnInfoPtr pScrn)
536 {
537 modesettingPtr ms = modesettingPTR(pScrn);
538 struct exa_context *exa;
539 ExaDriverPtr pExa;
540
541 exa = xcalloc(1, sizeof(struct exa_context));
542 if (!exa)
543 return NULL;
544
545 pExa = exaDriverAlloc();
546 if (!pExa) {
547 goto out_err;
548 }
549
550 memset(pExa, 0, sizeof(*pExa));
551
552 pExa->exa_major = 2;
553 pExa->exa_minor = 2;
554 pExa->memoryBase = 0;
555 pExa->memorySize = 0;
556 pExa->offScreenBase = 0;
557 pExa->pixmapOffsetAlign = 0;
558 pExa->pixmapPitchAlign = 1;
559 pExa->flags = EXA_OFFSCREEN_PIXMAPS | EXA_HANDLES_PIXMAPS;
560 pExa->maxX = 8191; /* FIXME */
561 pExa->maxY = 8191; /* FIXME */
562
563 pExa->WaitMarker = ExaWaitMarker;
564 pExa->MarkSync = ExaMarkSync;
565 pExa->PrepareSolid = ExaPrepareSolid;
566 pExa->Solid = ExaSolid;
567 pExa->DoneSolid = ExaDone;
568 pExa->PrepareCopy = ExaPrepareCopy;
569 pExa->Copy = ExaCopy;
570 pExa->DoneCopy = ExaDone;
571 pExa->CheckComposite = ExaCheckComposite;
572 pExa->PrepareComposite = ExaPrepareComposite;
573 pExa->Composite = ExaComposite;
574 pExa->DoneComposite = ExaDoneComposite;
575 pExa->PixmapIsOffscreen = ExaPixmapIsOffscreen;
576 pExa->PrepareAccess = ExaPrepareAccess;
577 pExa->FinishAccess = ExaFinishAccess;
578 pExa->CreatePixmap = ExaCreatePixmap;
579 pExa->DestroyPixmap = ExaDestroyPixmap;
580 pExa->ModifyPixmapHeader = ExaModifyPixmapHeader;
581
582 if (!exaDriverInit(pScrn->pScreen, pExa)) {
583 goto out_err;
584 }
585
586 exa->scrn = ms->screen;
587 exa->ctx = ms->api->create_context(ms->api, exa->scrn);
588 /* Share context with DRI */
589 ms->ctx = exa->ctx;
590
591 exa->cso = cso_create_context(exa->ctx);
592
593 return (void *)exa;
594
595 out_err:
596 xorg_exa_close(pScrn);
597
598 return NULL;
599 }
600
601 /* vim: set sw=4 ts=8 sts=4: */