static Bool RootlessAllocatePrivates(ScreenPtr pScreen) { RootlessScreenRec *s; static unsigned long rootlessGeneration = 0; if (rootlessGeneration != serverGeneration) { rootlessScreenPrivateIndex = AllocateScreenPrivateIndex(); if (rootlessScreenPrivateIndex == -1) return FALSE; rootlessGCPrivateIndex = AllocateGCPrivateIndex(); if (rootlessGCPrivateIndex == -1) return FALSE; rootlessWindowPrivateIndex = AllocateWindowPrivateIndex(); if (rootlessWindowPrivateIndex == -1) return FALSE; rootlessGeneration = serverGeneration; } // no allocation needed for screen privates if (!AllocateGCPrivate(pScreen, rootlessGCPrivateIndex, sizeof(RootlessGCRec))) return FALSE; if (!AllocateWindowPrivate(pScreen, rootlessWindowPrivateIndex, 0)) return FALSE; s = xalloc(sizeof(RootlessScreenRec)); if (! s) return FALSE; SCREENREC(pScreen) = s; return TRUE; }
ColormapPtr RootlessGetColormap (ScreenPtr pScreen) { RootlessScreenRec *s = SCREENREC (pScreen); return s->colormap; }
/* * RootlessUpdateScreenPixmap * miCreateScreenResources does not like a null framebuffer pointer, * it leaves the screen pixmap with an uninitialized data pointer. * Thus, rootless implementations typically set the framebuffer width * to zero so that miCreateScreenResources does not allocate a screen * pixmap for us. We allocate our own screen pixmap here since we need * the screen pixmap to be valid (e.g. CopyArea from the root window). */ void RootlessUpdateScreenPixmap(ScreenPtr pScreen) { RootlessScreenRec *s = SCREENREC(pScreen); PixmapPtr pPix; unsigned int rowbytes; pPix = (*pScreen->GetScreenPixmap)(pScreen); if (pPix == NULL) { pPix = (*pScreen->CreatePixmap)(pScreen, 0, 0, pScreen->rootDepth, 0); (*pScreen->SetScreenPixmap)(pPix); } rowbytes = PixmapBytePad(pScreen->width, pScreen->rootDepth); if (s->pixmap_data_size < rowbytes) { free(s->pixmap_data); s->pixmap_data_size = rowbytes; s->pixmap_data = malloc(s->pixmap_data_size); if (s->pixmap_data == NULL) return; memset(s->pixmap_data, 0xFF, s->pixmap_data_size); pScreen->ModifyPixmapHeader(pPix, pScreen->width, pScreen->height, pScreen->rootDepth, BitsPerPixel(pScreen->rootDepth), 0, s->pixmap_data); /* ModifyPixmapHeader ignores zero arguments, so install rowbytes by hand. */ pPix->devKind = 0; } }
static void RootlessComposite(CARD8 op, PicturePtr pSrc, PicturePtr pMask, PicturePtr pDst, INT16 xSrc, INT16 ySrc, INT16 xMask, INT16 yMask, INT16 xDst, INT16 yDst, CARD16 width, CARD16 height) { ScreenPtr pScreen = pDst->pDrawable->pScreen; PictureScreenPtr ps = GetPictureScreen(pScreen); WindowPtr dstWin; dstWin = (pDst->pDrawable->type == DRAWABLE_WINDOW) ? (WindowPtr)pDst->pDrawable : NULL; // SCREEN_UNWRAP(ps, Composite); ps->Composite = SCREENREC(pScreen)->Composite; ps->Composite(op, pSrc, pMask, pDst, xSrc, ySrc, xMask, yMask, xDst, yDst, width, height); if (dstWin && IsFramedWindow(dstWin)) { RootlessDamageRect(dstWin, xDst, yDst, width, height); } ps->Composite = RootlessComposite; // SCREEN_WRAP(ps, Composite); }
/* * RootlessBlockHandler * If the redisplay timer has expired, flush drawing before blocking * on select(). */ static void RootlessBlockHandler(pointer pbdata, OSTimePtr pTimeout, pointer pReadmask) { ScreenPtr pScreen = pbdata; RootlessScreenRec *screenRec = SCREENREC(pScreen); if (screenRec->redisplay_expired) { screenRec->redisplay_expired = FALSE; RootlessRedisplayScreen(pScreen); } }
static void RootlessWrap(ScreenPtr pScreen) { RootlessScreenRec *s = SCREENREC(pScreen); #define WRAP(a) \ if (pScreen->a) { \ s->a = pScreen->a; \ } else { \ RL_DEBUG_MSG("null screen fn " #a "\n"); \ s->a = NULL; \ } \ pScreen->a = Rootless##a WRAP(CreateScreenResources); WRAP(CloseScreen); WRAP(CreateGC); WRAP(CopyWindow); WRAP(GetImage); WRAP(SourceValidate); WRAP(CreateWindow); WRAP(DestroyWindow); WRAP(RealizeWindow); WRAP(UnrealizeWindow); WRAP(MoveWindow); WRAP(PositionWindow); WRAP(ResizeWindow); WRAP(RestackWindow); WRAP(ReparentWindow); WRAP(ChangeBorderWidth); WRAP(MarkOverlappedWindows); WRAP(ValidateTree); WRAP(ChangeWindowAttributes); WRAP(InstallColormap); WRAP(UninstallColormap); WRAP(StoreColors); WRAP(SetShape); { // Composite and Glyphs don't use normal screen wrapping PictureScreenPtr ps = GetPictureScreen(pScreen); s->Composite = ps->Composite; ps->Composite = RootlessComposite; s->Glyphs = ps->Glyphs; ps->Glyphs = RootlessGlyphs; } // WRAP(ClearToBackground); fixme put this back? useful for shaped wins? #undef WRAP }
static Bool RootlessCloseScreen(int i, ScreenPtr pScreen) { RootlessScreenRec *s; s = SCREENREC(pScreen); // fixme unwrap everything that was wrapped? pScreen->CloseScreen = s->CloseScreen; xfree(s); return pScreen->CloseScreen(i, pScreen); }
static void RootlessUninstallColormap (ColormapPtr pMap) { ScreenPtr pScreen = pMap->pScreen; RootlessScreenRec *s = SCREENREC (pScreen); SCREEN_UNWRAP(pScreen, UninstallColormap); if (s->colormap == pMap) s->colormap = NULL; pScreen->UninstallColormap (pMap); SCREEN_WRAP(pScreen, UninstallColormap); }
/* * RootlessQueueRedisplay * Queue a redisplay after a timer delay to ensure we do not redisplay * too frequently. */ void RootlessQueueRedisplay(ScreenPtr pScreen) { RootlessScreenRec *screenRec = SCREENREC(pScreen); screenRec->redisplay_queued = TRUE; if (screenRec->redisplay_timer_set) return; screenRec->redisplay_timer = TimerSet(screenRec->redisplay_timer, 0, ROOTLESS_REDISPLAY_DELAY, RootlessRedisplayCallback, screenRec); screenRec->redisplay_timer_set = TRUE; }
static void RootlessStoreColors (ColormapPtr pMap, int ndef, xColorItem *pdef) { ScreenPtr pScreen = pMap->pScreen; RootlessScreenRec *s = SCREENREC (pScreen); SCREEN_UNWRAP(pScreen, StoreColors); if (s->colormap == pMap && ndef > 0) { s->colormap_changed = TRUE; RootlessQueueRedisplay (pScreen); } pScreen->StoreColors (pMap, ndef, pdef); SCREEN_WRAP(pScreen, StoreColors); }
static void RootlessInstallColormap (ColormapPtr pMap) { ScreenPtr pScreen = pMap->pScreen; RootlessScreenRec *s = SCREENREC (pScreen); SCREEN_UNWRAP(pScreen, InstallColormap); if (s->colormap != pMap) { s->colormap = pMap; s->colormap_changed = TRUE; RootlessQueueRedisplay (pScreen); } pScreen->InstallColormap (pMap); SCREEN_WRAP (pScreen, InstallColormap); }
static Bool RootlessCloseScreen(int i, ScreenPtr pScreen) { RootlessScreenRec *s; s = SCREENREC(pScreen); // fixme unwrap everything that was wrapped? pScreen->CloseScreen = s->CloseScreen; if (s->pixmap_data != NULL) { free(s->pixmap_data); s->pixmap_data = NULL; s->pixmap_data_size = 0; } free(s); return pScreen->CloseScreen(i, pScreen); }
/* * Screen function to create a graphics context */ Bool RootlessCreateGC(GCPtr pGC) { RootlessGCRec *gcrec; RootlessScreenRec *s; Bool result; SCREEN_UNWRAP(pGC->pScreen, CreateGC); s = SCREENREC(pGC->pScreen); result = s->CreateGC(pGC); gcrec = (RootlessGCRec *) dixLookupPrivate(&pGC->devPrivates, rootlessGCPrivateKey); gcrec->originalOps = NULL; // don't wrap ops yet gcrec->originalFuncs = pGC->funcs; pGC->funcs = &rootlessGCFuncs; SCREEN_WRAP(pGC->pScreen, CreateGC); return result; }
static void RootlessGlyphs(CARD8 op, PicturePtr pSrc, PicturePtr pDst, PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc, int nlist, GlyphListPtr list, GlyphPtr *glyphs) { ScreenPtr pScreen = pDst->pDrawable->pScreen; PictureScreenPtr ps = GetPictureScreen(pScreen); int x, y; int n; GlyphPtr glyph; WindowPtr dstWin; dstWin = (pDst->pDrawable->type == DRAWABLE_WINDOW) ? (WindowPtr)pDst->pDrawable : NULL; //SCREEN_UNWRAP(ps, Glyphs); ps->Glyphs = SCREENREC(pScreen)->Glyphs; ps->Glyphs(op, pSrc, pDst, maskFormat, xSrc, ySrc, nlist, list, glyphs); ps->Glyphs = RootlessGlyphs; //SCREEN_WRAP(ps, Glyphs); if (dstWin && IsFramedWindow(dstWin)) { x = xSrc; y = ySrc; while (nlist--) { x += list->xOff; y += list->yOff; n = list->len; while (n--) { glyph = *glyphs++; RootlessDamageRect(dstWin, x - glyph->info.x, y - glyph->info.y, glyph->info.width, glyph->info.height); x += glyph->info.xOff; y += glyph->info.yOff; } list++; } } }
/* * RootlessInit * Called by the rootless implementation to initialize the rootless layer. * Rootless wraps lots of stuff and needs a bunch of devPrivates. */ Bool RootlessInit(ScreenPtr pScreen, RootlessFrameProcsPtr procs) { RootlessScreenRec *s; if (!RootlessAllocatePrivates(pScreen)) return FALSE; s = SCREENREC(pScreen); s->imp = procs; s->colormap = NULL; s->redisplay_expired = FALSE; RootlessWrap(pScreen); if (!RegisterBlockAndWakeupHandlers(RootlessBlockHandler, RootlessWakeupHandler, (pointer) pScreen)) { return FALSE; } return TRUE; }
/* Optimized version of fbCompositeSolidMask_nx8x8888 */ void SafeAlphaCompositeSolidMask_nx8x8888( CARD8 op, PicturePtr pSrc, PicturePtr pMask, PicturePtr pDst, INT16 xSrc, INT16 ySrc, INT16 xMask, INT16 yMask, INT16 xDst, INT16 yDst, CARD16 width, CARD16 height) { CARD32 src, srca; CARD32 *dstLine, *dst, d, dstMask; CARD8 *maskLine, *mask, m; FbStride dstStride, maskStride; CARD16 w; fbComposeGetSolid(pSrc, src, pDst->format); dstMask = FbFullMask (pDst->pDrawable->depth); srca = src >> 24; if (src == 0) return; fbComposeGetStart (pDst, xDst, yDst, CARD32, dstStride, dstLine, 1); fbComposeGetStart (pMask, xMask, yMask, CARD8, maskStride, maskLine, 1); if (dstMask == FB_ALLONES && pDst->pDrawable->bitsPerPixel == 32 && width * height > rootless_CompositePixels_threshold && SCREENREC(pDst->pDrawable->pScreen)->imp->CompositePixels) { void *srcp[2], *destp[2]; unsigned int dest_rowbytes[2]; unsigned int fn; srcp[0] = &src; srcp[1] = &src; /* null rowbytes pointer means use first value as a constant */ destp[0] = dstLine; destp[1] = dstLine; dest_rowbytes[0] = dstStride * 4; dest_rowbytes[1] = dest_rowbytes[0]; fn = RL_COMPOSITE_FUNCTION(RL_COMPOSITE_OVER, RL_DEPTH_ARGB8888, RL_DEPTH_A8, RL_DEPTH_ARGB8888); if (SCREENREC(pDst->pDrawable->pScreen)->imp->CompositePixels( width, height, fn, srcp, NULL, maskLine, maskStride, destp, dest_rowbytes) == Success) { return; } } while (height--) { dst = dstLine; dstLine += dstStride; mask = maskLine; maskLine += maskStride; w = width; while (w--) { m = *mask++; if (m == 0xff) { if (srca == 0xff) *dst = src & dstMask; else *dst = fbOver (src, *dst) & dstMask; } else if (m) { d = fbIn (src, m); *dst = fbOver (d, *dst) & dstMask; } dst++; } } }
static void RootlessGlyphs(CARD8 op, PicturePtr pSrc, PicturePtr pDst, PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc, int nlist, GlyphListPtr list, GlyphPtr *glyphs) { ScreenPtr pScreen = pDst->pDrawable->pScreen; PictureScreenPtr ps = GetPictureScreen(pScreen); int x, y; int n; GlyphPtr glyph; WindowPtr srcWin, dstWin; srcWin = (pSrc->pDrawable && pSrc->pDrawable->type == DRAWABLE_WINDOW) ? (WindowPtr)pSrc->pDrawable : NULL; dstWin = (pDst->pDrawable->type == DRAWABLE_WINDOW) ? (WindowPtr)pDst->pDrawable : NULL; if (srcWin && IsFramedWindow(srcWin)) RootlessStartDrawing(srcWin); if (dstWin && IsFramedWindow(dstWin)) RootlessStartDrawing(dstWin); //SCREEN_UNWRAP(ps, Glyphs); ps->Glyphs = SCREENREC(pScreen)->Glyphs; ps->Glyphs(op, pSrc, pDst, maskFormat, xSrc, ySrc, nlist, list, glyphs); ps->Glyphs = RootlessGlyphs; //SCREEN_WRAP(ps, Glyphs); if (dstWin && IsFramedWindow(dstWin)) { x = xSrc; y = ySrc; while (nlist--) { x += list->xOff; y += list->yOff; n = list->len; /* Calling DamageRect for the bounding box of each glyph is inefficient. So compute the union of all glyphs in a list and damage that. */ if (n > 0) { BoxRec box; glyph = *glyphs++; box.x1 = x - glyph->info.x; box.y1 = y - glyph->info.y; box.x2 = box.x1 + glyph->info.width; box.y2 = box.y1 + glyph->info.height; x += glyph->info.xOff; y += glyph->info.yOff; while (--n > 0) { short x1, y1, x2, y2; glyph = *glyphs++; x1 = x - glyph->info.x; y1 = y - glyph->info.y; x2 = x1 + glyph->info.width; y2 = y1 + glyph->info.height; box.x1 = max (box.x1, x1); box.y1 = max (box.y1, y1); box.x2 = max (box.x2, x2); box.y2 = max (box.y2, y2); x += glyph->info.xOff; y += glyph->info.yOff; } RootlessDamageBox(dstWin, &box); } list++; } } }