st/xorg: Clean up xorg_exa.c a bit
[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 "xf86.h"
32 #include "xorg_tracker.h"
33
34 #include "pipe/p_format.h"
35 #include "pipe/p_context.h"
36 #include "pipe/p_state.h"
37 #include "pipe/p_inlines.h"
38
39 struct exa_entity
40 {
41 ExaDriverPtr pExa;
42 struct pipe_context *ctx;
43 struct pipe_screen *scrn;
44 };
45
46 struct PixmapPriv
47 {
48 int flags;
49 struct pipe_texture *tex;
50 unsigned int color;
51 struct pipe_surface *src_surf; /* for copies */
52
53 struct pipe_transfer *map_transfer;
54 unsigned map_count;
55 };
56
57 /*
58 * Helper functions
59 */
60
61 static void
62 exa_get_pipe_format(int depth, enum pipe_format *format, int *bbp)
63 {
64 switch (depth) {
65 case 32:
66 *format = PIPE_FORMAT_A8R8G8B8_UNORM;
67 assert(*bbp == 32);
68 break;
69 case 24:
70 *format = PIPE_FORMAT_X8R8G8B8_UNORM;
71 assert(*bbp == 32);
72 break;
73 case 16:
74 *format = PIPE_FORMAT_R5G6B5_UNORM;
75 assert(*bbp == 16);
76 break;
77 case 15:
78 *format = PIPE_FORMAT_A1R5G5B5_UNORM;
79 assert(*bbp == 16);
80 break;
81 case 8:
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
92 /*
93 * Static exported EXA functions
94 */
95
96 static void
97 ExaWaitMarker(ScreenPtr pScreen, int marker)
98 {
99 }
100
101 static int
102 ExaMarkSync(ScreenPtr pScreen)
103 {
104 return 1;
105 }
106
107 static Bool
108 ExaPrepareAccess(PixmapPtr pPix, int index)
109 {
110 ScreenPtr pScreen = pPix->drawable.pScreen;
111 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
112 modesettingPtr ms = modesettingPTR(pScrn);
113 struct exa_entity *exa = ms->exa;
114 struct PixmapPriv *priv;
115
116 priv = exaGetPixmapDriverPrivate(pPix);
117
118 if (!priv)
119 return FALSE;
120
121 if (!priv->tex)
122 return FALSE;
123
124 if (priv->map_count++ == 0)
125 {
126 priv->map_transfer =
127 exa->scrn->get_tex_transfer(exa->scrn, priv->tex, 0, 0, 0,
128 PIPE_TRANSFER_READ_WRITE,
129 0, 0, priv->tex->width[0], priv->tex->height[0]);
130
131 pPix->devPrivate.ptr =
132 exa->scrn->transfer_map(exa->scrn, priv->map_transfer);
133 pPix->devKind = priv->map_transfer->stride;
134 }
135
136 return TRUE;
137 }
138
139 static void
140 ExaFinishAccess(PixmapPtr pPix, int index)
141 {
142 ScreenPtr pScreen = pPix->drawable.pScreen;
143 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
144 modesettingPtr ms = modesettingPTR(pScrn);
145 struct exa_entity *exa = ms->exa;
146 struct PixmapPriv *priv;
147 priv = exaGetPixmapDriverPrivate(pPix);
148
149 if (!priv)
150 return;
151
152 if (!priv->map_transfer)
153 return;
154
155 if (--priv->map_count == 0) {
156 assert(priv->map_transfer);
157 exa->scrn->transfer_unmap(exa->scrn, priv->map_transfer);
158 exa->scrn->tex_transfer_destroy(priv->map_transfer);
159 priv->map_transfer = NULL;
160 }
161 }
162
163 static void
164 ExaDone(PixmapPtr pPixmap)
165 {
166 ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum];
167 modesettingPtr ms = modesettingPTR(pScrn);
168 struct PixmapPriv *priv = exaGetPixmapDriverPrivate(pPixmap);
169 struct exa_entity *exa = ms->exa;
170
171 if (!priv)
172 return;
173
174 if (priv->src_surf)
175 exa->scrn->tex_surface_destroy(priv->src_surf);
176 priv->src_surf = NULL;
177 }
178
179 static void
180 ExaDoneComposite(PixmapPtr pPixmap)
181 {
182
183 }
184
185 static Bool
186 ExaPrepareSolid(PixmapPtr pPixmap, int alu, Pixel planeMask, Pixel fg)
187 {
188 ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum];
189 modesettingPtr ms = modesettingPTR(pScrn);
190 struct PixmapPriv *priv = exaGetPixmapDriverPrivate(pPixmap);
191 struct exa_entity *exa = ms->exa;
192
193 if (1)
194 return FALSE;
195
196 if (pPixmap->drawable.depth < 15)
197 return FALSE;
198
199 if (!EXA_PM_IS_SOLID(&pPixmap->drawable, planeMask))
200 return FALSE;
201
202 if (!priv || !priv->tex)
203 return FALSE;
204
205 if (alu != GXcopy)
206 return FALSE;
207
208 if (!exa->ctx || !exa->ctx->surface_fill)
209 return FALSE;
210
211 priv->color = fg;
212
213 return TRUE;
214 }
215
216 static void
217 ExaSolid(PixmapPtr pPixmap, int x0, int y0, int x1, int y1)
218 {
219 ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum];
220 modesettingPtr ms = modesettingPTR(pScrn);
221 struct exa_entity *exa = ms->exa;
222 struct PixmapPriv *priv = exaGetPixmapDriverPrivate(pPixmap);
223 struct pipe_surface *surf =
224 exa->scrn->get_tex_surface(exa->scrn, priv->tex, 0, 0, 0,
225 PIPE_BUFFER_USAGE_GPU_READ |
226 PIPE_BUFFER_USAGE_GPU_WRITE);
227
228 exa->ctx->surface_fill(exa->ctx, surf, x0, y0, x1 - x0, y1 - y0,
229 priv->color);
230
231 exa->scrn->tex_surface_destroy(surf);
232 }
233
234 static Bool
235 ExaPrepareCopy(PixmapPtr pSrcPixmap, PixmapPtr pDstPixmap, int xdir,
236 int ydir, int alu, Pixel planeMask)
237 {
238 ScrnInfoPtr pScrn = xf86Screens[pDstPixmap->drawable.pScreen->myNum];
239 modesettingPtr ms = modesettingPTR(pScrn);
240 struct exa_entity *exa = ms->exa;
241 struct PixmapPriv *priv = exaGetPixmapDriverPrivate(pDstPixmap);
242 struct PixmapPriv *src_priv = exaGetPixmapDriverPrivate(pSrcPixmap);
243
244 if (1)
245 return FALSE;
246
247 if (alu != GXcopy)
248 return FALSE;
249
250 if (pSrcPixmap->drawable.depth < 15 || pDstPixmap->drawable.depth < 15)
251 return FALSE;
252
253 if (!EXA_PM_IS_SOLID(&pSrcPixmap->drawable, planeMask))
254 return FALSE;
255
256 if (!priv || !src_priv)
257 return FALSE;
258
259 if (!priv->tex || !src_priv->tex)
260 return FALSE;
261
262 if (!exa->ctx || !exa->ctx->surface_copy)
263 return FALSE;
264
265 priv->src_surf =
266 exa->scrn->get_tex_surface(exa->scrn, src_priv->tex, 0, 0, 0,
267 PIPE_BUFFER_USAGE_GPU_READ |
268 PIPE_BUFFER_USAGE_GPU_WRITE);
269
270 return TRUE;
271 }
272
273 static void
274 ExaCopy(PixmapPtr pDstPixmap, int srcX, int srcY, int dstX, int dstY,
275 int width, int height)
276 {
277 ScrnInfoPtr pScrn = xf86Screens[pDstPixmap->drawable.pScreen->myNum];
278 modesettingPtr ms = modesettingPTR(pScrn);
279 struct exa_entity *exa = ms->exa;
280 struct PixmapPriv *priv = exaGetPixmapDriverPrivate(pDstPixmap);
281 struct pipe_surface *surf =
282 exa->scrn->get_tex_surface(exa->scrn, priv->tex, 0, 0, 0,
283 PIPE_BUFFER_USAGE_GPU_READ |
284 PIPE_BUFFER_USAGE_GPU_WRITE);
285
286 exa->ctx->surface_copy(exa->ctx, 0, surf, dstX, dstY, priv->src_surf,
287 srcX, srcY, width, height);
288 exa->scrn->tex_surface_destroy(surf);
289 }
290
291 static Bool
292 ExaPrepareComposite(int op, PicturePtr pSrcPicture,
293 PicturePtr pMaskPicture, PicturePtr pDstPicture,
294 PixmapPtr pSrc, PixmapPtr pMask, PixmapPtr pDst)
295 {
296 return FALSE;
297 }
298
299 static void
300 ExaComposite(PixmapPtr pDst, int srcX, int srcY, int maskX, int maskY,
301 int dstX, int dstY, int width, int height)
302 {
303 }
304
305 static Bool
306 ExaCheckComposite(int op,
307 PicturePtr pSrcPicture, PicturePtr pMaskPicture,
308 PicturePtr pDstPicture)
309 {
310 return FALSE;
311 }
312
313 static void *
314 ExaCreatePixmap(ScreenPtr pScreen, int size, int align)
315 {
316 struct PixmapPriv *priv;
317
318 priv = xcalloc(1, sizeof(struct PixmapPriv));
319 if (!priv)
320 return NULL;
321
322 return priv;
323 }
324
325 static void
326 ExaDestroyPixmap(ScreenPtr pScreen, void *dPriv)
327 {
328 struct PixmapPriv *priv = (struct PixmapPriv *)dPriv;
329 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
330 modesettingPtr ms = modesettingPTR(pScrn);
331
332 if (!priv)
333 return;
334
335 if (priv->tex)
336 ms->screen->texture_destroy(priv->tex);
337
338 xfree(priv);
339 }
340
341 static Bool
342 ExaPixmapIsOffscreen(PixmapPtr pPixmap)
343 {
344 struct PixmapPriv *priv;
345
346 priv = exaGetPixmapDriverPrivate(pPixmap);
347
348 if (!priv)
349 return FALSE;
350
351 if (priv->tex)
352 return TRUE;
353
354 return FALSE;
355 }
356
357 unsigned
358 xorg_exa_get_pixmap_handle(PixmapPtr pPixmap)
359 {
360 ScreenPtr pScreen = pPixmap->drawable.pScreen;
361 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
362 modesettingPtr ms = modesettingPTR(pScrn);
363 struct PixmapPriv *priv;
364 struct pipe_buffer *buffer = NULL;
365 unsigned handle;
366 unsigned stride;
367
368 if (!ms->exa) {
369 FatalError("NO MS->EXA\n");
370 return 0;
371 }
372
373 priv = exaGetPixmapDriverPrivate(pPixmap);
374
375 if (!priv) {
376 FatalError("NO PIXMAP PRIVATE\n");
377 return 0;
378 }
379
380 drm_api_hooks.buffer_from_texture(priv->tex, &buffer, &stride);
381 drm_api_hooks.handle_from_buffer(ms->screen, buffer, &handle);
382 pipe_buffer_reference(&buffer, NULL);
383 return handle;
384 }
385
386 static Bool
387 ExaModifyPixmapHeader(PixmapPtr pPixmap, int width, int height,
388 int depth, int bitsPerPixel, int devKind,
389 pointer pPixData)
390 {
391 ScreenPtr pScreen = pPixmap->drawable.pScreen;
392 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
393 struct PixmapPriv *priv = exaGetPixmapDriverPrivate(pPixmap);
394 modesettingPtr ms = modesettingPTR(pScrn);
395 struct exa_entity *exa = ms->exa;
396
397 if (!priv)
398 return FALSE;
399
400 if (depth <= 0)
401 depth = pPixmap->drawable.depth;
402
403 if (bitsPerPixel <= 0)
404 bitsPerPixel = pPixmap->drawable.bitsPerPixel;
405
406 if (width <= 0)
407 width = pPixmap->drawable.width;
408
409 if (height <= 0)
410 height = pPixmap->drawable.height;
411
412 if (width <= 0 || height <= 0 || depth <= 0)
413 return FALSE;
414
415 miModifyPixmapHeader(pPixmap, width, height, depth,
416 bitsPerPixel, devKind, NULL);
417
418 /* Deal with screen resize */
419 if (priv->tex && (priv->tex->width[0] != width || priv->tex->height[0] != height)) {
420 pipe_texture_reference(&priv->tex, NULL);
421 }
422
423 if (!priv->tex) {
424 struct pipe_texture template;
425
426 memset(&template, 0, sizeof(template));
427 template.target = PIPE_TEXTURE_2D;
428 template.compressed = 0;
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: */