123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425 |
- /*
- *
- * Copyright © 2000 SuSE, Inc.
- *
- * Permission to use, copy, modify, distribute, and sell this software and its
- * documentation for any purpose is hereby granted without fee, provided that
- * the above copyright notice appear in all copies and that both that
- * copyright notice and this permission notice appear in supporting
- * documentation, and that the name of SuSE not be used in advertising or
- * publicity pertaining to distribution of the software without specific,
- * written prior permission. SuSE makes no representations about the
- * suitability of this software for any purpose. It is provided "as is"
- * without express or implied warranty.
- *
- * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE
- * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- *
- * Author: Keith Packard, SuSE, Inc.
- */
- #ifdef HAVE_DIX_CONFIG_H
- #include <dix-config.h>
- #endif
- #include <stdlib.h>
- #include "fb.h"
- #include "fboverlay.h"
- #include "shmint.h"
- int fbOverlayGeneration;
- static int fbOverlayScreenPrivateIndex = -1;
- int
- fbOverlayGetScreenPrivateIndex(void)
- {
- return fbOverlayScreenPrivateIndex;
- }
- /*
- * Replace this if you want something supporting
- * multiple overlays with the same depth
- */
- Bool
- fbOverlayCreateWindow(WindowPtr pWin)
- {
- FbOverlayScrPrivPtr pScrPriv = fbOverlayGetScrPriv(pWin->drawable.pScreen);
- int i;
- PixmapPtr pPixmap;
- if (pWin->drawable.class != InputOutput)
- return TRUE;
- if (pWin->drawable.bitsPerPixel == 32)
- pWin->drawable.bitsPerPixel =
- fbGetScreenPrivate(pWin->drawable.pScreen)->win32bpp;
- for (i = 0; i < pScrPriv->nlayers; i++) {
- pPixmap = pScrPriv->layer[i].u.run.pixmap;
- if (pWin->drawable.depth == pPixmap->drawable.depth) {
- pWin->devPrivates[fbWinPrivateIndex].ptr = (pointer) pPixmap;
- /*
- * Make sure layer keys are written correctly by
- * having non-root layers set to full while the
- * root layer is set to empty. This will cause
- * all of the layers to get painted when the root
- * is mapped
- */
- if (!pWin->parent) {
- REGION_EMPTY(
- &pScrPriv->layer[i].u.run.region);
- }
- return TRUE;
- }
- }
- return FALSE;
- }
- Bool
- fbOverlayCloseScreen(int iScreen, ScreenPtr pScreen)
- {
- FbOverlayScrPrivPtr pScrPriv = fbOverlayGetScrPriv(pScreen);
- int i;
- for (i = 0; i < pScrPriv->nlayers; i++) {
- (*pScreen->DestroyPixmap) (pScrPriv->layer[i].u.run.pixmap);
- REGION_UNINIT(&pScrPriv->layer[i].u.run.region);
- }
- return TRUE;
- }
- /*
- * Return layer containing this window
- */
- int
- fbOverlayWindowLayer(WindowPtr pWin)
- {
- FbOverlayScrPrivPtr pScrPriv = fbOverlayGetScrPriv(pWin->drawable.pScreen);
- int i;
- for (i = 0; i < pScrPriv->nlayers; i++)
- if (pWin->devPrivates[fbWinPrivateIndex].ptr ==
- (pointer) pScrPriv->layer[i].u.run.pixmap)
- return i;
- return 0;
- }
- Bool
- fbOverlayCreateScreenResources(ScreenPtr pScreen)
- {
- int i;
- FbOverlayScrPrivPtr pScrPriv = fbOverlayGetScrPriv(pScreen);
- PixmapPtr pPixmap;
- pointer pbits;
- int width;
- int depth;
- BoxRec box;
- if (!miCreateScreenResources(pScreen))
- return FALSE;
- box.x1 = 0;
- box.y1 = 0;
- box.x2 = pScreen->width;
- box.y2 = pScreen->height;
- for (i = 0; i < pScrPriv->nlayers; i++) {
- pbits = pScrPriv->layer[i].u.init.pbits;
- width = pScrPriv->layer[i].u.init.width;
- depth = pScrPriv->layer[i].u.init.depth;
- pPixmap = (*pScreen->CreatePixmap) (pScreen, 0, 0, depth);
- if (!pPixmap)
- return FALSE;
- if (!(*pScreen->ModifyPixmapHeader) (pPixmap, pScreen->width,
- pScreen->height, depth,
- BitsPerPixel(depth),
- PixmapBytePad(width, depth),
- pbits))
- return FALSE;
- pScrPriv->layer[i].u.run.pixmap = pPixmap;
- REGION_INIT(&pScrPriv->layer[i].u.run.region, &box, 0);
- }
- pScreen->devPrivate = pScrPriv->layer[0].u.run.pixmap;
- return TRUE;
- }
- void
- fbOverlayPaintKey(DrawablePtr pDrawable,
- RegionPtr pRegion, CARD32 pixel, int layer)
- {
- fbFillRegionSolid(pDrawable, pRegion, 0,
- fbReplicatePixel(pixel, pDrawable->bitsPerPixel));
- }
- /*
- * Track visible region for each layer
- */
- void
- fbOverlayUpdateLayerRegion(ScreenPtr pScreen, int layer, RegionPtr prgn)
- {
- FbOverlayScrPrivPtr pScrPriv = fbOverlayGetScrPriv(pScreen);
- int i;
- RegionRec rgnNew;
- if (!prgn || !REGION_NOTEMPTY(prgn))
- return;
- for (i = 0; i < pScrPriv->nlayers; i++) {
- if (i == layer) {
- /* add new piece to this fb */
- REGION_UNION(&pScrPriv->layer[i].u.run.region,
- &pScrPriv->layer[i].u.run.region, prgn);
- }
- else if (REGION_NOTEMPTY(&pScrPriv->layer[i].u.run.region)) {
- /* paint new piece with chroma key */
- REGION_NULL(&rgnNew);
- REGION_INTERSECT(&rgnNew, prgn, &pScrPriv->layer[i].u.run.region);
- (*pScrPriv->PaintKey) (&pScrPriv->layer[i].u.run.pixmap->drawable,
- &rgnNew, pScrPriv->layer[i].key, i);
- REGION_UNINIT(&rgnNew);
- /* remove piece from other fbs */
- REGION_SUBTRACT(
- &pScrPriv->layer[i].u.run.region,
- &pScrPriv->layer[i].u.run.region, prgn);
- }
- }
- }
- /*
- * Copy only areas in each layer containing real bits
- */
- void
- fbOverlayCopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg, RegionPtr prgnSrc)
- {
- ScreenPtr pScreen = pWin->drawable.pScreen;
- FbOverlayScrPrivPtr pScrPriv = fbOverlayGetScrPriv(pWin->drawable.pScreen);
- RegionRec rgnDst;
- int dx, dy;
- int i;
- RegionRec layerRgn[FB_OVERLAY_MAX];
- PixmapPtr pPixmap;
- dx = ptOldOrg.x - pWin->drawable.x;
- dy = ptOldOrg.y - pWin->drawable.y;
- /*
- * Clip to existing bits
- */
- REGION_TRANSLATE(prgnSrc, -dx, -dy);
- REGION_NULL(&rgnDst);
- REGION_INTERSECT(&rgnDst, &pWin->borderClip, prgnSrc);
- REGION_TRANSLATE(&rgnDst, dx, dy);
- /*
- * Compute the portion of each fb affected by this copy
- */
- for (i = 0; i < pScrPriv->nlayers; i++) {
- REGION_NULL(&layerRgn[i]);
- REGION_INTERSECT(&layerRgn[i], &rgnDst,
- &pScrPriv->layer[i].u.run.region);
- if (REGION_NOTEMPTY(&layerRgn[i])) {
- REGION_TRANSLATE(&layerRgn[i], -dx, -dy);
- pPixmap = pScrPriv->layer[i].u.run.pixmap;
- fbCopyRegion(&pPixmap->drawable, &pPixmap->drawable,
- 0,
- &layerRgn[i], dx, dy, pScrPriv->CopyWindow, 0,
- (void *) (long) i);
- }
- }
- /*
- * Update regions
- */
- for (i = 0; i < pScrPriv->nlayers; i++) {
- if (REGION_NOTEMPTY(&layerRgn[i]))
- fbOverlayUpdateLayerRegion(pScreen, i, &layerRgn[i]);
- REGION_UNINIT(&layerRgn[i]);
- }
- REGION_UNINIT(&rgnDst);
- }
- void
- fbOverlayWindowExposures(WindowPtr pWin,
- RegionPtr prgn, RegionPtr other_exposed)
- {
- fbOverlayUpdateLayerRegion(pWin->drawable.pScreen,
- fbOverlayWindowLayer(pWin), prgn);
- miWindowExposures(pWin, prgn, other_exposed);
- }
- void
- fbOverlayPaintWindow(WindowPtr pWin, RegionPtr pRegion, int what)
- {
- if (what == PW_BORDER)
- fbOverlayUpdateLayerRegion(pWin->drawable.pScreen,
- fbOverlayWindowLayer(pWin), pRegion);
- fbPaintWindow(pWin, pRegion, what);
- }
- Bool
- fbOverlaySetupScreen(ScreenPtr pScreen,
- pointer pbits1,
- pointer pbits2,
- int xsize,
- int ysize,
- int dpix,
- int dpiy, int width1, int width2, int bpp1, int bpp2)
- {
- return fbSetupScreen(pScreen,
- pbits1, xsize, ysize, dpix, dpiy, width1, bpp1);
- }
- static Bool
- fb24_32OverlayCreateScreenResources(ScreenPtr pScreen)
- {
- FbOverlayScrPrivPtr pScrPriv = fbOverlayGetScrPriv(pScreen);
- int pitch;
- Bool retval;
- int i;
- if ((retval = fbOverlayCreateScreenResources(pScreen))) {
- for (i = 0; i < pScrPriv->nlayers; i++) {
- /* fix the screen pixmap */
- PixmapPtr pPix = (PixmapPtr) pScrPriv->layer[i].u.run.pixmap;
- if (pPix->drawable.bitsPerPixel == 32) {
- pPix->drawable.bitsPerPixel = 24;
- pitch = BitmapBytePad(pPix->drawable.width * 24);
- pPix->devKind = pitch;
- }
- }
- }
- return retval;
- }
- Bool
- fbOverlayFinishScreenInit(ScreenPtr pScreen,
- pointer pbits1,
- pointer pbits2,
- int xsize,
- int ysize,
- int dpix,
- int dpiy,
- int width1,
- int width2,
- int bpp1, int bpp2, int depth1, int depth2)
- {
- VisualPtr visuals;
- DepthPtr depths;
- int nvisuals;
- int ndepths;
- int bpp = 0, imagebpp = 32;
- VisualID defaultVisual;
- FbOverlayScrPrivPtr pScrPriv;
- if (fbOverlayGeneration != serverGeneration) {
- fbOverlayScreenPrivateIndex = AllocateScreenPrivateIndex();
- fbOverlayGeneration = serverGeneration;
- }
- pScrPriv = malloc(sizeof(FbOverlayScrPrivRec));
- if (!pScrPriv)
- return FALSE;
- if (bpp1 == 32 || bpp2 == 32)
- bpp = 32;
- else if (bpp1 == 24 || bpp2 == 24)
- bpp = 24;
- if (bpp == 24) {
- int f;
- imagebpp = 32;
- /*
- * Check to see if we're advertising a 24bpp image format,
- * in which case windows will use it in preference to a 32 bit
- * format.
- */
- for (f = 0; f < screenInfo.numPixmapFormats; f++) {
- if (screenInfo.formats[f].bitsPerPixel == 24) {
- imagebpp = 24;
- break;
- }
- }
- }
- if (imagebpp == 32) {
- fbGetScreenPrivate(pScreen)->win32bpp = bpp;
- fbGetScreenPrivate(pScreen)->pix32bpp = bpp;
- }
- else {
- fbGetScreenPrivate(pScreen)->win32bpp = 32;
- fbGetScreenPrivate(pScreen)->pix32bpp = 32;
- }
- if (!fbInitVisuals(&visuals, &depths, &nvisuals, &ndepths, &depth1,
- &defaultVisual, ((unsigned long) 1 << (bpp1 - 1)) |
- ((unsigned long) 1 << (bpp2 - 1)), 8))
- return FALSE;
- if (!miScreenInit(pScreen, 0, xsize, ysize, dpix, dpiy, 0,
- depth1, ndepths, depths, defaultVisual, nvisuals, visuals
- ))
- return FALSE;
- /* MI thinks there's no frame buffer */
- ShmRegisterFbFuncs(pScreen);
- pScreen->minInstalledCmaps = 1;
- pScreen->maxInstalledCmaps = 2;
- pScrPriv->nlayers = 2;
- pScrPriv->PaintKey = fbOverlayPaintKey;
- pScrPriv->CopyWindow = fbCopyWindowProc;
- pScrPriv->layer[0].u.init.pbits = pbits1;
- pScrPriv->layer[0].u.init.width = width1;
- pScrPriv->layer[0].u.init.depth = depth1;
- pScrPriv->layer[1].u.init.pbits = pbits2;
- pScrPriv->layer[1].u.init.width = width2;
- pScrPriv->layer[1].u.init.depth = depth2;
- pScreen->devPrivates[fbOverlayScreenPrivateIndex].ptr = (pointer) pScrPriv;
- /* overwrite miCloseScreen with our own */
- pScreen->CloseScreen = fbOverlayCloseScreen;
- pScreen->CreateScreenResources = fbOverlayCreateScreenResources;
- pScreen->CreateWindow = fbOverlayCreateWindow;
- pScreen->WindowExposures = fbOverlayWindowExposures;
- pScreen->CopyWindow = fbOverlayCopyWindow;
- pScreen->PaintWindowBorder = fbOverlayPaintWindow;
- if (bpp == 24 && imagebpp == 32) {
- pScreen->ModifyPixmapHeader = fb24_32ModifyPixmapHeader;
- pScreen->CreateScreenResources = fb24_32OverlayCreateScreenResources;
- }
- return TRUE;
- }
|