Initial code release
[profile/ivi/xorg-x11-drv-intel.git] / uxa / uxa.c
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
43 DevPrivateKeyRec uxa_screen_index;
44 #else
45 int 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  */
59 PixmapPtr 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  */
73 void
74 uxa_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  */
101 Bool 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  */
116 Bool 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   */
125 PixmapPtr 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  */
143 Bool 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  */
163 void uxa_finish_access(DrawablePtr pDrawable)
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);
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  */
183 static void
184 uxa_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 #ifdef FB_24_32BIT
192         if ((changes & GCTile) && fbGetRotatedPixmap(pGC)) {
193                 (*pGC->pScreen->DestroyPixmap) (fbGetRotatedPixmap(pGC));
194                 fbGetRotatedPixmap(pGC) = 0;
195         }
196
197         if (pGC->fillStyle == FillTiled) {
198                 PixmapPtr pOldTile, pNewTile;
199
200                 pOldTile = pGC->tile.pixmap;
201                 if (pOldTile->drawable.bitsPerPixel != pDrawable->bitsPerPixel) {
202                         pNewTile = fbGetRotatedPixmap(pGC);
203                         if (!pNewTile ||
204                             pNewTile->drawable.bitsPerPixel !=
205                             pDrawable->bitsPerPixel) {
206                                 if (pNewTile)
207                                         (*pGC->pScreen->
208                                          DestroyPixmap) (pNewTile);
209                                 /* fb24_32ReformatTile will do direct access
210                                  * of a newly-allocated pixmap.  This isn't a
211                                  * problem yet, since we don't put pixmaps in
212                                  * FB until at least one accelerated UXA op.
213                                  */
214                                 if (uxa_prepare_access
215                                     (&pOldTile->drawable, UXA_ACCESS_RO)) {
216                                         pNewTile =
217                                             fb24_32ReformatTile(pOldTile,
218                                                                 pDrawable->
219                                                                 bitsPerPixel);
220                                         uxa_finish_access(&pOldTile->drawable);
221                                 }
222                         }
223                         if (pNewTile) {
224                                 fbGetRotatedPixmap(pGC) = pOldTile;
225                                 pGC->tile.pixmap = pNewTile;
226                                 changes |= GCTile;
227                         }
228                 }
229         }
230 #endif
231         if (changes & GCTile) {
232                 if (!pGC->tileIsPixel
233                     && FbEvenTile(pGC->tile.pixmap->drawable.width *
234                                   pDrawable->bitsPerPixel)) {
235                         if (uxa_prepare_access
236                             (&pGC->tile.pixmap->drawable, UXA_ACCESS_RW)) {
237                                 fbPadPixmap(pGC->tile.pixmap);
238                                 uxa_finish_access(&pGC->tile.pixmap->drawable);
239                         }
240                 }
241                 /* Mask out the GCTile change notification, now that we've
242                  * done FB's job for it.
243                  */
244                 changes &= ~GCTile;
245         }
246
247         if (changes & GCStipple && pGC->stipple) {
248                 /* We can't inline stipple handling like we do for GCTile
249                  * because it sets fbgc privates.
250                  */
251                 if (uxa_prepare_access(&pGC->stipple->drawable, UXA_ACCESS_RW)) {
252                         fbValidateGC(pGC, changes, pDrawable);
253                         uxa_finish_access(&pGC->stipple->drawable);
254                 }
255         } else {
256                 fbValidateGC(pGC, changes, pDrawable);
257         }
258
259         pGC->ops = (GCOps *) & uxa_ops;
260 }
261
262 static GCFuncs uxaGCFuncs = {
263         uxa_validate_gc,
264         miChangeGC,
265         miCopyGC,
266         miDestroyGC,
267         miChangeClip,
268         miDestroyClip,
269         miCopyClip
270 };
271
272 /**
273  * uxa_create_gc makes a new GC and hooks up its funcs handler, so that
274  * uxa_validate_gc() will get called.
275  */
276 static int uxa_create_gc(GCPtr pGC)
277 {
278         if (!fbCreateGC(pGC))
279                 return FALSE;
280
281         pGC->funcs = &uxaGCFuncs;
282
283         return TRUE;
284 }
285
286 Bool uxa_prepare_access_window(WindowPtr pWin)
287 {
288         if (pWin->backgroundState == BackgroundPixmap) {
289                 if (!uxa_prepare_access
290                     (&pWin->background.pixmap->drawable, UXA_ACCESS_RO))
291                         return FALSE;
292         }
293
294         if (pWin->borderIsPixel == FALSE) {
295                 if (!uxa_prepare_access
296                     (&pWin->border.pixmap->drawable, UXA_ACCESS_RO)) {
297                         if (pWin->backgroundState == BackgroundPixmap)
298                                 uxa_finish_access(&pWin->background.pixmap->
299                                                   drawable);
300                         return FALSE;
301                 }
302         }
303         return TRUE;
304 }
305
306 void uxa_finish_access_window(WindowPtr pWin)
307 {
308         if (pWin->backgroundState == BackgroundPixmap)
309                 uxa_finish_access(&pWin->background.pixmap->drawable);
310
311         if (pWin->borderIsPixel == FALSE)
312                 uxa_finish_access(&pWin->border.pixmap->drawable);
313 }
314
315 static Bool uxa_change_window_attributes(WindowPtr pWin, unsigned long mask)
316 {
317         Bool ret;
318
319         if (!uxa_prepare_access_window(pWin))
320                 return FALSE;
321         ret = fbChangeWindowAttributes(pWin, mask);
322         uxa_finish_access_window(pWin);
323         return ret;
324 }
325
326 static RegionPtr uxa_bitmap_to_region(PixmapPtr pPix)
327 {
328         RegionPtr ret;
329         if (!uxa_prepare_access(&pPix->drawable, UXA_ACCESS_RO))
330                 return NULL;
331         ret = fbPixmapToRegion(pPix);
332         uxa_finish_access(&pPix->drawable);
333         return ret;
334 }
335
336 static void uxa_xorg_enable_disable_fb_access(int index, Bool enable)
337 {
338         ScreenPtr screen = screenInfo.screens[index];
339         uxa_screen_t *uxa_screen = uxa_get_screen(screen);
340
341         if (!enable && uxa_screen->disableFbCount++ == 0)
342                 uxa_screen->swappedOut = TRUE;
343
344         if (enable && --uxa_screen->disableFbCount == 0)
345                 uxa_screen->swappedOut = FALSE;
346
347         if (uxa_screen->SavedEnableDisableFBAccess)
348                 uxa_screen->SavedEnableDisableFBAccess(index, enable);
349 }
350
351 void uxa_set_fallback_debug(ScreenPtr screen, Bool enable)
352 {
353         uxa_screen_t *uxa_screen = uxa_get_screen(screen);
354
355         uxa_screen->fallback_debug = enable;
356 }
357
358 void uxa_set_force_fallback(ScreenPtr screen, Bool value)
359 {
360         uxa_screen_t *uxa_screen = uxa_get_screen(screen);
361
362         uxa_screen->force_fallback = value;
363 }
364
365 /**
366  * uxa_close_screen() unwraps its wrapped screen functions and tears down UXA's
367  * screen private, before calling down to the next CloseSccreen.
368  */
369 static Bool uxa_close_screen(int i, ScreenPtr pScreen)
370 {
371         uxa_screen_t *uxa_screen = uxa_get_screen(pScreen);
372         ScrnInfoPtr scrn = xf86Screens[pScreen->myNum];
373 #ifdef RENDER
374         PictureScreenPtr ps = GetPictureScreenIfSet(pScreen);
375 #endif
376         int n;
377
378         if (uxa_screen->solid_clear)
379                 FreePicture(uxa_screen->solid_clear, 0);
380         if (uxa_screen->solid_black)
381                 FreePicture(uxa_screen->solid_black, 0);
382         if (uxa_screen->solid_white)
383                 FreePicture(uxa_screen->solid_white, 0);
384         for (n = 0; n < uxa_screen->solid_cache_size; n++)
385                 FreePicture(uxa_screen->solid_cache[n].picture, 0);
386
387         uxa_glyphs_fini(pScreen);
388
389         if (pScreen->devPrivate) {
390                 /* Destroy the pixmap created by miScreenInit() *before*
391                  * chaining up as we finalize ourselves here and so this
392                  * is the last chance we have of releasing our resources
393                  * associated with the Pixmap. So do it first.
394                  */
395                 (void) (*pScreen->DestroyPixmap) (pScreen->devPrivate);
396                 pScreen->devPrivate = NULL;
397         }
398
399         pScreen->CreateGC = uxa_screen->SavedCreateGC;
400         pScreen->CloseScreen = uxa_screen->SavedCloseScreen;
401         pScreen->GetImage = uxa_screen->SavedGetImage;
402         pScreen->GetSpans = uxa_screen->SavedGetSpans;
403         pScreen->CreatePixmap = uxa_screen->SavedCreatePixmap;
404         pScreen->DestroyPixmap = uxa_screen->SavedDestroyPixmap;
405         pScreen->CopyWindow = uxa_screen->SavedCopyWindow;
406         pScreen->ChangeWindowAttributes =
407             uxa_screen->SavedChangeWindowAttributes;
408         pScreen->BitmapToRegion = uxa_screen->SavedBitmapToRegion;
409         scrn->EnableDisableFBAccess = uxa_screen->SavedEnableDisableFBAccess;
410 #ifdef RENDER
411         if (ps) {
412                 ps->Composite = uxa_screen->SavedComposite;
413                 ps->CompositeRects = uxa_screen->SavedCompositeRects;
414                 ps->Glyphs = uxa_screen->SavedGlyphs;
415                 ps->Trapezoids = uxa_screen->SavedTrapezoids;
416                 ps->AddTraps = uxa_screen->SavedAddTraps;
417                 ps->Triangles = uxa_screen->SavedTriangles;
418
419                 ps->UnrealizeGlyph = uxa_screen->SavedUnrealizeGlyph;
420         }
421 #endif
422
423         free(uxa_screen);
424
425         return (*pScreen->CloseScreen) (i, pScreen);
426 }
427
428 /**
429  * This function allocates a driver structure for UXA drivers to fill in.  By
430  * having UXA allocate the structure, the driver structure can be extended
431  * without breaking ABI between UXA and the drivers.  The driver's
432  * responsibility is to check beforehand that the UXA module has a matching
433  * major number and sufficient minor.  Drivers are responsible for freeing the
434  * driver structure using free().
435  *
436  * @return a newly allocated, zero-filled driver structure
437  */
438 uxa_driver_t *uxa_driver_alloc(void)
439 {
440         return calloc(1, sizeof(uxa_driver_t));
441 }
442
443 /**
444  * @param pScreen screen being initialized
445  * @param pScreenInfo UXA driver record
446  *
447  * uxa_driver_init sets up UXA given a driver record filled in by the driver.
448  * pScreenInfo should have been allocated by uxa_driver_alloc().  See the
449  * comments in _UxaDriver for what must be filled in and what is optional.
450  *
451  * @return TRUE if UXA was successfully initialized.
452  */
453 Bool uxa_driver_init(ScreenPtr screen, uxa_driver_t * uxa_driver)
454 {
455         uxa_screen_t *uxa_screen;
456         ScrnInfoPtr scrn = xf86Screens[screen->myNum];
457
458         if (!uxa_driver)
459                 return FALSE;
460
461         if (uxa_driver->uxa_major != UXA_VERSION_MAJOR ||
462             uxa_driver->uxa_minor > UXA_VERSION_MINOR) {
463                 LogMessage(X_ERROR,
464                            "UXA(%d): driver's UXA version requirements "
465                            "(%d.%d) are incompatible with UXA version (%d.%d)\n",
466                            screen->myNum, uxa_driver->uxa_major,
467                            uxa_driver->uxa_minor, UXA_VERSION_MAJOR,
468                            UXA_VERSION_MINOR);
469                 return FALSE;
470         }
471
472         if (!uxa_driver->prepare_solid) {
473                 LogMessage(X_ERROR,
474                            "UXA(%d): uxa_driver_t::prepare_solid must be "
475                            "non-NULL\n", screen->myNum);
476                 return FALSE;
477         }
478
479         if (!uxa_driver->prepare_copy) {
480                 LogMessage(X_ERROR,
481                            "UXA(%d): uxa_driver_t::prepare_copy must be "
482                            "non-NULL\n", screen->myNum);
483                 return FALSE;
484         }
485 #if HAS_DIXREGISTERPRIVATEKEY
486         if (!dixRegisterPrivateKey(&uxa_screen_index, PRIVATE_SCREEN, 0))
487             return FALSE;
488 #endif
489         uxa_screen = calloc(sizeof(uxa_screen_t), 1);
490
491         if (!uxa_screen) {
492                 LogMessage(X_WARNING,
493                            "UXA(%d): Failed to allocate screen private\n",
494                            screen->myNum);
495                 return FALSE;
496         }
497
498         uxa_screen->info = uxa_driver;
499
500         dixSetPrivate(&screen->devPrivates, &uxa_screen_index, uxa_screen);
501
502         uxa_screen->force_fallback = FALSE;
503
504         uxa_screen->solid_cache_size = 0;
505         uxa_screen->solid_clear = 0;
506         uxa_screen->solid_black = 0;
507         uxa_screen->solid_white = 0;
508
509 //    exaDDXDriverInit(screen);
510
511         /*
512          * Replace various fb screen functions
513          */
514         uxa_screen->SavedCloseScreen = screen->CloseScreen;
515         screen->CloseScreen = uxa_close_screen;
516
517         uxa_screen->SavedCreateGC = screen->CreateGC;
518         screen->CreateGC = uxa_create_gc;
519
520         uxa_screen->SavedGetImage = screen->GetImage;
521         screen->GetImage = uxa_get_image;
522
523         uxa_screen->SavedGetSpans = screen->GetSpans;
524         screen->GetSpans = uxa_check_get_spans;
525
526         uxa_screen->SavedCopyWindow = screen->CopyWindow;
527         screen->CopyWindow = uxa_copy_window;
528
529         uxa_screen->SavedChangeWindowAttributes =
530             screen->ChangeWindowAttributes;
531         screen->ChangeWindowAttributes = uxa_change_window_attributes;
532
533         uxa_screen->SavedBitmapToRegion = screen->BitmapToRegion;
534         screen->BitmapToRegion = uxa_bitmap_to_region;
535
536         uxa_screen->SavedEnableDisableFBAccess = scrn->EnableDisableFBAccess;
537         scrn->EnableDisableFBAccess = uxa_xorg_enable_disable_fb_access;
538
539 #ifdef RENDER
540         {
541                 PictureScreenPtr ps = GetPictureScreenIfSet(screen);
542                 if (ps) {
543                         uxa_screen->SavedComposite = ps->Composite;
544                         ps->Composite = uxa_composite;
545
546                         uxa_screen->SavedCompositeRects = ps->CompositeRects;
547                         ps->CompositeRects = uxa_solid_rects;
548
549                         uxa_screen->SavedGlyphs = ps->Glyphs;
550                         ps->Glyphs = uxa_glyphs;
551
552                         uxa_screen->SavedUnrealizeGlyph = ps->UnrealizeGlyph;
553                         ps->UnrealizeGlyph = uxa_glyph_unrealize;
554
555                         uxa_screen->SavedTriangles = ps->Triangles;
556                         ps->Triangles = uxa_triangles;
557
558                         uxa_screen->SavedTrapezoids = ps->Trapezoids;
559                         ps->Trapezoids = uxa_trapezoids;
560
561                         uxa_screen->SavedAddTraps = ps->AddTraps;
562                         ps->AddTraps = uxa_check_add_traps;
563                 }
564         }
565 #endif
566
567         LogMessage(X_INFO,
568                    "UXA(%d): Driver registered support for the following"
569                    " operations:\n", screen->myNum);
570         assert(uxa_driver->prepare_solid != NULL);
571         LogMessage(X_INFO, "        solid\n");
572         assert(uxa_driver->prepare_copy != NULL);
573         LogMessage(X_INFO, "        copy\n");
574         if (uxa_driver->prepare_composite != NULL) {
575                 LogMessage(X_INFO, "        composite (RENDER acceleration)\n");
576         }
577         if (uxa_driver->put_image != NULL) {
578                 LogMessage(X_INFO, "        put_image\n");
579         }
580         if (uxa_driver->get_image != NULL) {
581                 LogMessage(X_INFO, "        get_image\n");
582         }
583
584         return TRUE;
585 }
586
587 Bool uxa_resources_init(ScreenPtr screen)
588 {
589         if (!uxa_glyphs_init(screen))
590                 return FALSE;
591
592         return TRUE;
593 }
594
595 /**
596  * uxa_driver_fini tears down UXA on a given screen.
597  *
598  * @param pScreen screen being torn down.
599  */
600 void uxa_driver_fini(ScreenPtr pScreen)
601 {
602         /*right now does nothing */
603 }