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