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