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