1/*
2 * Copyright © 2001 Keith Packard
3 *
4 * Partly based on code that is Copyright © The XFree86 Project Inc.
5 *
6 * Permission to use, copy, modify, distribute, and sell this software and its
7 * documentation for any purpose is hereby granted without fee, provided that
8 * the above copyright notice appear in all copies and that both that
9 * copyright notice and this permission notice appear in supporting
10 * documentation, and that the name of Keith Packard not be used in
11 * advertising or publicity pertaining to distribution of the software without
12 * specific, written prior permission.  Keith Packard makes no
13 * representations about the suitability of this software for any purpose.  It
14 * is provided "as is" without express or implied warranty.
15 *
16 * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
17 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
18 * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
19 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
20 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
21 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
22 * PERFORMANCE OF THIS SOFTWARE.
23 */
24
25/** @file
26 * This file covers the initialization and teardown of UXA, and has various
27 * functions not responsible for performing rendering, pixmap migration, or
28 * memory management.
29 */
30
31#ifdef HAVE_DIX_CONFIG_H
32#include <dix-config.h>
33#endif
34
35#include <stdlib.h>
36
37#include "uxa-priv.h"
38#include <X11/fonts/fontstruct.h>
39#include "dixfontstr.h"
40#include "uxa.h"
41
42#if HAS_DEVPRIVATEKEYREC
43DevPrivateKeyRec uxa_screen_index;
44#else
45int uxa_screen_index;
46#endif
47
48/**
49 * uxa_get_drawable_pixmap() returns a backing pixmap for a given drawable.
50 *
51 * @param pDrawable the drawable being requested.
52 *
53 * This function returns the backing pixmap for a drawable, whether it is a
54 * redirected window, unredirected window, or already a pixmap.  Note that
55 * coordinate translation is needed when drawing to the backing pixmap of a
56 * redirected window, and the translation coordinates are provided by calling
57 * uxa_get_drawable_pixmap() on the drawable.
58 */
59PixmapPtr uxa_get_drawable_pixmap(DrawablePtr pDrawable)
60{
61	if (pDrawable->type == DRAWABLE_WINDOW)
62		return pDrawable->pScreen->
63		    GetWindowPixmap((WindowPtr) pDrawable);
64	else
65		return (PixmapPtr) pDrawable;
66}
67
68/**
69 * Sets the offsets to add to coordinates to make them address the same bits in
70 * the backing drawable. These coordinates are nonzero only for redirected
71 * windows.
72 */
73void
74uxa_get_drawable_deltas(DrawablePtr pDrawable, PixmapPtr pPixmap,
75			int *xp, int *yp)
76{
77#ifdef COMPOSITE
78	if (pDrawable->type == DRAWABLE_WINDOW) {
79		*xp = -pPixmap->screen_x;
80		*yp = -pPixmap->screen_y;
81		return;
82	}
83#endif
84
85	*xp = 0;
86	*yp = 0;
87}
88
89/**
90 * uxa_pixmap_is_offscreen() is used to determine if a pixmap is in offscreen
91 * memory, meaning that acceleration could probably be done to it, and that it
92 * will need to be wrapped by PrepareAccess()/FinishAccess() when accessing it
93 * with the CPU.
94 *
95 * Note that except for UploadToScreen()/DownloadFromScreen() (which explicitly
96 * deal with moving pixmaps in and out of system memory), UXA will give drivers
97 * pixmaps as arguments for which uxa_pixmap_is_offscreen() is TRUE.
98 *
99 * @return TRUE if the given drawable is in framebuffer memory.
100 */
101Bool uxa_pixmap_is_offscreen(PixmapPtr p)
102{
103	ScreenPtr pScreen = p->drawable.pScreen;
104	uxa_screen_t *uxa_screen = uxa_get_screen(pScreen);
105
106	if (uxa_screen->info->pixmap_is_offscreen)
107		return uxa_screen->info->pixmap_is_offscreen(p);
108
109	return FALSE;
110}
111
112/**
113 * uxa_drawable_is_offscreen() is a convenience wrapper for
114 * uxa_pixmap_is_offscreen().
115 */
116Bool uxa_drawable_is_offscreen(DrawablePtr pDrawable)
117{
118	return uxa_pixmap_is_offscreen(uxa_get_drawable_pixmap(pDrawable));
119}
120
121/**
122  * Returns the pixmap which backs a drawable, and the offsets to add to
123  * coordinates to make them address the same bits in the backing drawable.
124  */
125PixmapPtr uxa_get_offscreen_pixmap(DrawablePtr drawable, int *xp, int *yp)
126{
127	PixmapPtr pixmap = uxa_get_drawable_pixmap(drawable);
128
129	uxa_get_drawable_deltas(drawable, pixmap, xp, yp);
130
131	if (uxa_pixmap_is_offscreen(pixmap))
132		return pixmap;
133	else
134		return NULL;
135}
136
137/**
138 * uxa_prepare_access() is UXA's wrapper for the driver's PrepareAccess() handler.
139 *
140 * It deals with waiting for synchronization with the card, determining if
141 * PrepareAccess() is necessary, and working around PrepareAccess() failure.
142 */
143Bool uxa_prepare_access(DrawablePtr pDrawable, uxa_access_t access)
144{
145	ScreenPtr pScreen = pDrawable->pScreen;
146	uxa_screen_t *uxa_screen = uxa_get_screen(pScreen);
147	PixmapPtr pPixmap = uxa_get_drawable_pixmap(pDrawable);
148	Bool offscreen = uxa_pixmap_is_offscreen(pPixmap);
149
150	if (!offscreen)
151		return TRUE;
152
153	if (uxa_screen->info->prepare_access)
154		return (*uxa_screen->info->prepare_access) (pPixmap, access);
155	return TRUE;
156}
157
158/**
159 * uxa_finish_access() is UXA's wrapper for the driver's finish_access() handler.
160 *
161 * It deals with calling the driver's finish_access() only if necessary.
162 */
163void uxa_finish_access(DrawablePtr pDrawable, uxa_access_t access)
164{
165	ScreenPtr pScreen = pDrawable->pScreen;
166	uxa_screen_t *uxa_screen = uxa_get_screen(pScreen);
167	PixmapPtr pPixmap;
168
169	if (uxa_screen->info->finish_access == NULL)
170		return;
171
172	pPixmap = uxa_get_drawable_pixmap(pDrawable);
173	if (!uxa_pixmap_is_offscreen(pPixmap))
174		return;
175
176	(*uxa_screen->info->finish_access) (pPixmap, access);
177}
178
179/**
180 * uxa_validate_gc() sets the ops to UXA's implementations, which may be
181 * accelerated or may sync the card and fall back to fb.
182 */
183static void
184uxa_validate_gc(GCPtr pGC, unsigned long changes, DrawablePtr pDrawable)
185{
186	/* fbValidateGC will do direct access to pixmaps if the tiling has
187	 * changed.
188	 * Preempt fbValidateGC by doing its work and masking the change out, so
189	 * that we can do the Prepare/finish_access.
190	 */
191
192#ifdef FB_24_32BIT
193	if ((changes & GCTile) && fbGetRotatedPixmap(pGC)) {
194		(*pGC->pScreen->DestroyPixmap) (fbGetRotatedPixmap(pGC));
195		fbGetRotatedPixmap(pGC) = 0;
196	}
197
198	if (pGC->fillStyle == FillTiled) {
199		PixmapPtr pOldTile, pNewTile;
200
201		pOldTile = pGC->tile.pixmap;
202		if (pOldTile->drawable.bitsPerPixel != pDrawable->bitsPerPixel) {
203			pNewTile = fbGetRotatedPixmap(pGC);
204			if (!pNewTile ||
205			    pNewTile->drawable.bitsPerPixel !=
206			    pDrawable->bitsPerPixel) {
207				if (pNewTile)
208					(*pGC->pScreen->
209					 DestroyPixmap) (pNewTile);
210				/* fb24_32ReformatTile will do direct access
211				 * of a newly-allocated pixmap.  This isn't a
212				 * problem yet, since we don't put pixmaps in
213				 * FB until at least one accelerated UXA op.
214				 */
215				if (uxa_prepare_access
216				    (&pOldTile->drawable, UXA_ACCESS_RO)) {
217					pNewTile =
218					    fb24_32ReformatTile(pOldTile,
219								pDrawable->
220								bitsPerPixel);
221					uxa_finish_access(&pOldTile->drawable, UXA_ACCESS_RO);
222				}
223			}
224			if (pNewTile) {
225				fbGetRotatedPixmap(pGC) = pOldTile;
226				pGC->tile.pixmap = pNewTile;
227				changes |= GCTile;
228			}
229		}
230	}
231#endif
232	if (changes & GCTile) {
233		if (!pGC->tileIsPixel
234		    && FbEvenTile(pGC->tile.pixmap->drawable.width *
235				  pDrawable->bitsPerPixel)) {
236			if (uxa_prepare_access
237			    (&pGC->tile.pixmap->drawable, UXA_ACCESS_RW)) {
238				fbPadPixmap(pGC->tile.pixmap);
239				uxa_finish_access(&pGC->tile.pixmap->drawable, UXA_ACCESS_RW);
240			}
241		}
242		/* Mask out the GCTile change notification, now that we've
243		 * done FB's job for it.
244		 */
245		changes &= ~GCTile;
246	}
247
248	if (changes & GCStipple && pGC->stipple) {
249		/* We can't inline stipple handling like we do for GCTile
250		 * because it sets fbgc privates.
251		 */
252		if (uxa_prepare_access(&pGC->stipple->drawable, UXA_ACCESS_RW)) {
253			fbValidateGC(pGC, changes, pDrawable);
254			uxa_finish_access(&pGC->stipple->drawable, UXA_ACCESS_RW);
255		}
256	} else {
257		fbValidateGC(pGC, changes, pDrawable);
258	}
259
260	pGC->ops = (GCOps *) & uxa_ops;
261}
262
263static GCFuncs uxaGCFuncs = {
264	uxa_validate_gc,
265	miChangeGC,
266	miCopyGC,
267	miDestroyGC,
268	miChangeClip,
269	miDestroyClip,
270	miCopyClip
271};
272
273/**
274 * uxa_create_gc makes a new GC and hooks up its funcs handler, so that
275 * uxa_validate_gc() will get called.
276 */
277static int uxa_create_gc(GCPtr pGC)
278{
279	if (!fbCreateGC(pGC))
280		return FALSE;
281
282	pGC->funcs = &uxaGCFuncs;
283
284	return TRUE;
285}
286
287Bool uxa_prepare_access_window(WindowPtr pWin)
288{
289	if (pWin->backgroundState == BackgroundPixmap) {
290		if (!uxa_prepare_access
291		    (&pWin->background.pixmap->drawable, UXA_ACCESS_RO))
292			return FALSE;
293	}
294
295	if (pWin->borderIsPixel == FALSE) {
296		if (!uxa_prepare_access
297		    (&pWin->border.pixmap->drawable, UXA_ACCESS_RO)) {
298			if (pWin->backgroundState == BackgroundPixmap)
299				uxa_finish_access(&pWin->background.pixmap->
300						  drawable, UXA_ACCESS_RO);
301			return FALSE;
302		}
303	}
304	return TRUE;
305}
306
307void uxa_finish_access_window(WindowPtr pWin)
308{
309	if (pWin->backgroundState == BackgroundPixmap)
310		uxa_finish_access(&pWin->background.pixmap->drawable, UXA_ACCESS_RO);
311
312	if (pWin->borderIsPixel == FALSE)
313		uxa_finish_access(&pWin->border.pixmap->drawable, UXA_ACCESS_RO);
314}
315
316static Bool uxa_change_window_attributes(WindowPtr pWin, unsigned long mask)
317{
318	Bool ret;
319
320	if (!uxa_prepare_access_window(pWin))
321		return FALSE;
322	ret = fbChangeWindowAttributes(pWin, mask);
323	uxa_finish_access_window(pWin);
324	return ret;
325}
326
327static RegionPtr uxa_bitmap_to_region(PixmapPtr pPix)
328{
329	RegionPtr ret;
330	if (!uxa_prepare_access(&pPix->drawable, UXA_ACCESS_RO))
331		return NULL;
332	ret = fbPixmapToRegion(pPix);
333	uxa_finish_access(&pPix->drawable, UXA_ACCESS_RO);
334	return ret;
335}
336
337void uxa_set_fallback_debug(ScreenPtr screen, Bool enable)
338{
339	uxa_screen_t *uxa_screen = uxa_get_screen(screen);
340
341	uxa_screen->fallback_debug = enable;
342}
343
344void uxa_set_force_fallback(ScreenPtr screen, Bool value)
345{
346	uxa_screen_t *uxa_screen = uxa_get_screen(screen);
347
348	uxa_screen->force_fallback = value;
349}
350
351/**
352 * uxa_close_screen() unwraps its wrapped screen functions and tears down UXA's
353 * screen private, before calling down to the next CloseSccreen.
354 */
355static Bool uxa_close_screen(CLOSE_SCREEN_ARGS_DECL)
356{
357	uxa_screen_t *uxa_screen = uxa_get_screen(screen);
358#ifdef RENDER
359	PictureScreenPtr ps = GetPictureScreenIfSet(screen);
360#endif
361	int n;
362
363	if (uxa_screen->solid_clear)
364		FreePicture(uxa_screen->solid_clear, 0);
365	if (uxa_screen->solid_black)
366		FreePicture(uxa_screen->solid_black, 0);
367	if (uxa_screen->solid_white)
368		FreePicture(uxa_screen->solid_white, 0);
369	for (n = 0; n < uxa_screen->solid_cache_size; n++)
370		FreePicture(uxa_screen->solid_cache[n].picture, 0);
371
372	uxa_glyphs_fini(screen);
373
374#if XORG_VERSION_CURRENT < XORG_VERSION_NUMERIC(1,15,99,903,0)
375	if (screen->devPrivate) {
376		/* Destroy the pixmap created by miScreenInit() *before*
377		 * chaining up as we finalize ourselves here and so this
378		 * is the last chance we have of releasing our resources
379		 * associated with the Pixmap. So do it first.
380		 */
381		(void) (*screen->DestroyPixmap) (screen->devPrivate);
382		screen->devPrivate = NULL;
383	}
384#endif
385
386	screen->CreateGC = uxa_screen->SavedCreateGC;
387	screen->CloseScreen = uxa_screen->SavedCloseScreen;
388	screen->GetImage = uxa_screen->SavedGetImage;
389	screen->GetSpans = uxa_screen->SavedGetSpans;
390	screen->CreatePixmap = uxa_screen->SavedCreatePixmap;
391	screen->DestroyPixmap = uxa_screen->SavedDestroyPixmap;
392	screen->CopyWindow = uxa_screen->SavedCopyWindow;
393	screen->ChangeWindowAttributes =
394	    uxa_screen->SavedChangeWindowAttributes;
395	screen->BitmapToRegion = uxa_screen->SavedBitmapToRegion;
396#ifdef RENDER
397	if (ps) {
398		ps->Composite = uxa_screen->SavedComposite;
399		ps->Glyphs = uxa_screen->SavedGlyphs;
400		ps->Trapezoids = uxa_screen->SavedTrapezoids;
401		ps->AddTraps = uxa_screen->SavedAddTraps;
402		ps->Triangles = uxa_screen->SavedTriangles;
403
404		ps->UnrealizeGlyph = uxa_screen->SavedUnrealizeGlyph;
405	}
406#endif
407
408	free(uxa_screen);
409
410	return (*screen->CloseScreen) (CLOSE_SCREEN_ARGS);
411}
412
413/**
414 * This function allocates a driver structure for UXA drivers to fill in.  By
415 * having UXA allocate the structure, the driver structure can be extended
416 * without breaking ABI between UXA and the drivers.  The driver's
417 * responsibility is to check beforehand that the UXA module has a matching
418 * major number and sufficient minor.  Drivers are responsible for freeing the
419 * driver structure using free().
420 *
421 * @return a newly allocated, zero-filled driver structure
422 */
423uxa_driver_t *uxa_driver_alloc(void)
424{
425	return calloc(1, sizeof(uxa_driver_t));
426}
427
428/**
429 * @param screen screen being initialized
430 * @param pScreenInfo UXA driver record
431 *
432 * uxa_driver_init sets up UXA given a driver record filled in by the driver.
433 * pScreenInfo should have been allocated by uxa_driver_alloc().  See the
434 * comments in _UxaDriver for what must be filled in and what is optional.
435 *
436 * @return TRUE if UXA was successfully initialized.
437 */
438Bool uxa_driver_init(ScreenPtr screen, uxa_driver_t * uxa_driver)
439{
440	uxa_screen_t *uxa_screen;
441
442	if (!uxa_driver)
443		return FALSE;
444
445	if (uxa_driver->uxa_major != UXA_VERSION_MAJOR ||
446	    uxa_driver->uxa_minor > UXA_VERSION_MINOR) {
447		LogMessage(X_ERROR,
448			   "UXA(%d): driver's UXA version requirements "
449			   "(%d.%d) are incompatible with UXA version (%d.%d)\n",
450			   screen->myNum, uxa_driver->uxa_major,
451			   uxa_driver->uxa_minor, UXA_VERSION_MAJOR,
452			   UXA_VERSION_MINOR);
453		return FALSE;
454	}
455
456	if (!uxa_driver->prepare_solid) {
457		LogMessage(X_ERROR,
458			   "UXA(%d): uxa_driver_t::prepare_solid must be "
459			   "non-NULL\n", screen->myNum);
460		return FALSE;
461	}
462
463	if (!uxa_driver->prepare_copy) {
464		LogMessage(X_ERROR,
465			   "UXA(%d): uxa_driver_t::prepare_copy must be "
466			   "non-NULL\n", screen->myNum);
467		return FALSE;
468	}
469#if HAS_DIXREGISTERPRIVATEKEY
470	if (!dixRegisterPrivateKey(&uxa_screen_index, PRIVATE_SCREEN, 0))
471	    return FALSE;
472#endif
473	uxa_screen = calloc(sizeof(uxa_screen_t), 1);
474
475	if (!uxa_screen) {
476		LogMessage(X_WARNING,
477			   "UXA(%d): Failed to allocate screen private\n",
478			   screen->myNum);
479		return FALSE;
480	}
481
482	uxa_screen->info = uxa_driver;
483
484	dixSetPrivate(&screen->devPrivates, &uxa_screen_index, uxa_screen);
485
486	uxa_screen->force_fallback = FALSE;
487
488	uxa_screen->solid_cache_size = 0;
489	uxa_screen->solid_clear = 0;
490	uxa_screen->solid_black = 0;
491	uxa_screen->solid_white = 0;
492
493//    exaDDXDriverInit(screen);
494
495	/*
496	 * Replace various fb screen functions
497	 */
498	uxa_screen->SavedCloseScreen = screen->CloseScreen;
499	screen->CloseScreen = uxa_close_screen;
500
501	uxa_screen->SavedCreateGC = screen->CreateGC;
502	screen->CreateGC = uxa_create_gc;
503
504	uxa_screen->SavedGetImage = screen->GetImage;
505	screen->GetImage = uxa_get_image;
506
507	uxa_screen->SavedGetSpans = screen->GetSpans;
508	screen->GetSpans = uxa_get_spans;
509
510	uxa_screen->SavedCopyWindow = screen->CopyWindow;
511	screen->CopyWindow = uxa_copy_window;
512
513	uxa_screen->SavedChangeWindowAttributes =
514	    screen->ChangeWindowAttributes;
515	screen->ChangeWindowAttributes = uxa_change_window_attributes;
516
517	uxa_screen->SavedBitmapToRegion = screen->BitmapToRegion;
518	screen->BitmapToRegion = uxa_bitmap_to_region;
519
520#ifdef RENDER
521	{
522		PictureScreenPtr ps = GetPictureScreenIfSet(screen);
523		if (ps) {
524			uxa_screen->SavedComposite = ps->Composite;
525			ps->Composite = uxa_composite;
526
527			uxa_screen->SavedGlyphs = ps->Glyphs;
528			ps->Glyphs = uxa_glyphs;
529
530			uxa_screen->SavedUnrealizeGlyph = ps->UnrealizeGlyph;
531			ps->UnrealizeGlyph = uxa_glyph_unrealize;
532
533			uxa_screen->SavedTriangles = ps->Triangles;
534			ps->Triangles = uxa_triangles;
535
536			uxa_screen->SavedTrapezoids = ps->Trapezoids;
537			ps->Trapezoids = uxa_trapezoids;
538
539			uxa_screen->SavedAddTraps = ps->AddTraps;
540			ps->AddTraps = uxa_add_traps;
541		}
542	}
543#endif
544
545	LogMessage(X_INFO,
546		   "UXA(%d): Driver registered support for the following"
547		   " operations:\n", screen->myNum);
548	assert(uxa_driver->prepare_solid != NULL);
549	LogMessage(X_INFO, "        solid\n");
550	assert(uxa_driver->prepare_copy != NULL);
551	LogMessage(X_INFO, "        copy\n");
552	if (uxa_driver->prepare_composite != NULL) {
553		LogMessage(X_INFO, "        composite (RENDER acceleration)\n");
554	}
555	if (uxa_driver->put_image != NULL) {
556		LogMessage(X_INFO, "        put_image\n");
557	}
558	if (uxa_driver->get_image != NULL) {
559		LogMessage(X_INFO, "        get_image\n");
560	}
561
562	return TRUE;
563}
564
565Bool uxa_resources_init(ScreenPtr screen)
566{
567	if (!uxa_glyphs_init(screen))
568		return FALSE;
569
570	return TRUE;
571}
572
573/**
574 * uxa_driver_fini tears down UXA on a given screen.
575 *
576 * @param pScreen screen being torn down.
577 */
578void uxa_driver_fini(ScreenPtr pScreen)
579{
580	/*right now does nothing */
581}
582