diff options
author | Owain G. Ainsworth <oga@openbsd.org> | 2010-07-18 16:01:48 +0100 |
---|---|---|
committer | Owain G. Ainsworth <oga@openbsd.org> | 2010-07-18 16:01:48 +0100 |
commit | 9290ad77c5eef438ba02fc26334fd85ab3caa009 (patch) | |
tree | a2ac0f1be6786545821e7aa75ecbf4bbc332a1f4 | |
parent | 09c5b49b691132d0085c29b74decb45e0d4215e9 (diff) | |
parent | b2f4de3b7fb73bd51b1fd1b2b044862839c9a6ea (diff) |
Merge branch 'bleeding_edge-oga' into 2.9.1-oga
Conflicts:
src/i830_display.c
This has now been commited to cvs, so the branch gets pulled.
44 files changed, 5413 insertions, 3280 deletions
@@ -1,12 +1,165 @@ -This is a stub file. This package has not yet had its complete licensing -information compiled. Please see the individual source files for details on -your rights to use and modify this software. +Copyright 2002 Tungsten Graphics, Inc., Cedar Park, Texas. +Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas. +Copyright 2005 Tungsten Graphics, Inc., Cedar Park, Texas. +All Rights Reserved. -Please submit updated COPYING files to the Xorg bugzilla: +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sub license, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: -https://bugs.freedesktop.org/enter_bug.cgi?product=xorg +The above copyright notice and this permission notice (including the +next paragraph) shall be included in all copies or substantial portions +of the Software. -All licensing questions regarding this software should be directed at the -Xorg mailing list: +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. +IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR +ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Copyright (c) 2005 Jesse Barnes <jbarnes@virtuousgeek.org> +Copyright © 2002 David Dawes +Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas. + +All Rights Reserved. + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sub license, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice (including the +next paragraph) shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. +IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR +ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Copyright © 2006 Intel Corporation +Copyright © 2006,2010 Intel Corporation +Copyright © 2007 Intel Corporation +Copyright © 2008 Intel Corporation +Copyright © 2009 Intel Corporation +Copyright © 2007 Red Hat, Inc. + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation +the rights to use, copy, modify, merge, publish, distribute, sublicense, +and/or sell copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice (including the next +paragraph) shall be included in all copies or substantial portions of the +Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +Copyright 2000 by Alan Hourihane, Sychdyn, North Wales, UK. + +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 Alan Hourihane not be used in +advertising or publicity pertaining to distribution of the software without +specific, written prior permission. Alan Hourihane makes no representations +about the suitability of this software for any purpose. It is provided +"as is" without express or implied warranty. + +ALAN HOURIHANE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, +INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO +EVENT SHALL ALAN HOURIHANE 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. + +Copyright 2000 Intel Corporation. All Rights Reserved. + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sub license, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice (including the +next paragraph) shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. +IN NO EVENT SHALL INTEL, AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, +DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR +THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Copyright 2001 VA Linux Systems Inc., Fremont, California. +Copyright © 2002 by David Dawes + +All Rights Reserved. + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation +on the rights to use, copy, modify, merge, publish, distribute, sub +license, and/or sell copies of the Software, and to permit persons to whom +the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice (including the next +paragraph) shall be included in all copies or substantial portions of the +Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL +ATI, VA LINUX SYSTEMS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, +DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +USE OR OTHER DEALINGS IN THE SOFTWARE. + +Copyright © 1999 Keith Packard +Copyright ® 2001 Keith Packard +Copyright © 2000, 2008 Keith Packard + +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 Keith Packard not be used in +advertising or publicity pertaining to distribution of the software without +specific, written prior permission. Keith Packard makes no +representations about the suitability of this software for any purpose. It +is provided "as is" without express or implied warranty. + +KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, +INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO +EVENT SHALL KEITH PACKARD 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. -http://lists.freedesktop.org/mailman/listinfo/xorg diff --git a/src/common.h b/src/common.h index 73b4d05f..6f35d56d 100644 --- a/src/common.h +++ b/src/common.h @@ -412,6 +412,7 @@ intel_host_bridge (void); enum { INTEL_CREATE_PIXMAP_TILING_X = 0x10000000, INTEL_CREATE_PIXMAP_TILING_Y, + INTEL_CREATE_PIXMAP_TILING_NONE, }; #endif /* _INTEL_COMMON_H_ */ diff --git a/src/drmmode_display.c b/src/drmmode_display.c index e0df3961..de40fe9b 100644 --- a/src/drmmode_display.c +++ b/src/drmmode_display.c @@ -336,7 +336,7 @@ drmmode_set_mode_major(xf86CrtcPtr crtc, DisplayModePtr mode, crtc->y = y; crtc->rotation = rotation; - output_ids = xcalloc(sizeof(uint32_t), xf86_config->num_output); + output_ids = calloc(sizeof(uint32_t), xf86_config->num_output); if (!output_ids) { ret = FALSE; goto done; @@ -729,7 +729,7 @@ static int drmmode_output_lvds_edid(xf86OutputPtr output, * device. This is similar to what we have done in i830_lvds.c */ edid_mon = NULL; - edid_mon = xcalloc(1, sizeof(xf86Monitor)); + edid_mon = calloc(1, sizeof(xf86Monitor)); if (!edid_mon) { xf86DrvMsg(output->scrn->scrnIndex, X_ERROR, "Can't allocate memory for edid_mon.\n"); @@ -869,17 +869,17 @@ drmmode_output_destroy(xf86OutputPtr output) drmModeFreePropertyBlob(drmmode_output->edid_blob); for (i = 0; i < drmmode_output->num_props; i++) { drmModeFreeProperty(drmmode_output->props[i].mode_prop); - xfree(drmmode_output->props[i].atoms); + free(drmmode_output->props[i].atoms); } - xfree(drmmode_output->props); + free(drmmode_output->props); drmModeFreeConnector(drmmode_output->mode_output); if (drmmode_output->private_data) { - xfree(drmmode_output->private_data); + free(drmmode_output->private_data); drmmode_output->private_data = NULL; } if (drmmode_output->backlight_iface) drmmode_backlight_set(output, drmmode_output->backlight_active_level); - xfree(drmmode_output); + free(drmmode_output); output->driver_private = NULL; } @@ -970,7 +970,7 @@ drmmode_output_create_resources(xf86OutputPtr output) drmModePropertyPtr drmmode_prop; int i, j, err; - drmmode_output->props = xcalloc(mode_output->count_props, sizeof(drmmode_prop_rec)); + drmmode_output->props = calloc(mode_output->count_props, sizeof(drmmode_prop_rec)); if (!drmmode_output->props) return; @@ -995,7 +995,7 @@ drmmode_output_create_resources(xf86OutputPtr output) INT32 range[2]; p->num_atoms = 1; - p->atoms = xcalloc(p->num_atoms, sizeof(Atom)); + p->atoms = calloc(p->num_atoms, sizeof(Atom)); if (!p->atoms) continue; p->atoms[0] = MakeAtom(drmmode_prop->name, strlen(drmmode_prop->name), TRUE); @@ -1017,7 +1017,7 @@ drmmode_output_create_resources(xf86OutputPtr output) } } else if (drmmode_prop->flags & DRM_MODE_PROP_ENUM) { p->num_atoms = drmmode_prop->count_enums + 1; - p->atoms = xcalloc(p->num_atoms, sizeof(Atom)); + p->atoms = calloc(p->num_atoms, sizeof(Atom)); if (!p->atoms) continue; p->atoms[0] = MakeAtom(drmmode_prop->name, strlen(drmmode_prop->name), TRUE); @@ -1262,7 +1262,7 @@ drmmode_output_init(ScrnInfoPtr scrn, drmmode_ptr drmmode, int num) return; } - drmmode_output = xcalloc(sizeof(drmmode_output_private_rec), 1); + drmmode_output = calloc(sizeof(drmmode_output_private_rec), 1); if (!drmmode_output) { xf86OutputDestroy(output); drmModeFreeConnector(koutput); @@ -1276,7 +1276,7 @@ drmmode_output_init(ScrnInfoPtr scrn, drmmode_ptr drmmode, int num) */ drmmode_output->private_data = NULL; if (koutput->connector_type == DRM_MODE_CONNECTOR_LVDS) { - drmmode_output->private_data = xcalloc( + drmmode_output->private_data = calloc( sizeof(struct fixed_panel_lvds), 1); if (!drmmode_output->private_data) xf86DrvMsg(scrn->scrnIndex, X_ERROR, diff --git a/src/i810_dga.c b/src/i810_dga.c index 3f530579..52a01b76 100644 --- a/src/i810_dga.c +++ b/src/i810_dga.c @@ -84,10 +84,10 @@ I810DGAInit(ScreenPtr pScreen) while (pMode) { - newmodes = xrealloc(modes, (num + 1) * sizeof(DGAModeRec)); + newmodes = realloc(modes, (num + 1) * sizeof(DGAModeRec)); if (!newmodes) { - xfree(modes); + free(modes); return FALSE; } modes = newmodes; diff --git a/src/i810_dri.c b/src/i810_dri.c index e566acf6..c4022423 100644 --- a/src/i810_dri.c +++ b/src/i810_dri.c @@ -172,25 +172,25 @@ I810InitVisualConfigs(ScreenPtr pScreen) numConfigs = 8; pConfigs = - (__GLXvisualConfig *) xcalloc(sizeof(__GLXvisualConfig), + (__GLXvisualConfig *) calloc(sizeof(__GLXvisualConfig), numConfigs); if (!pConfigs) return FALSE; pI810Configs = - (I810ConfigPrivPtr) xcalloc(sizeof(I810ConfigPrivRec), + (I810ConfigPrivPtr) calloc(sizeof(I810ConfigPrivRec), numConfigs); if (!pI810Configs) { - xfree(pConfigs); + free(pConfigs); return FALSE; } pI810ConfigPtrs = - (I810ConfigPrivPtr *) xcalloc(sizeof(I810ConfigPrivPtr), + (I810ConfigPrivPtr *) calloc(sizeof(I810ConfigPrivPtr), numConfigs); if (!pI810ConfigPtrs) { - xfree(pConfigs); - xfree(pI810Configs); + free(pConfigs); + free(pI810Configs); return FALSE; } @@ -338,7 +338,7 @@ I810DRIScreenInit(ScreenPtr pScreen) if (xf86LoaderCheckSymbol("DRICreatePCIBusID")) { pDRIInfo->busIdString = DRICreatePCIBusID(pI810->PciInfo); } else { - pDRIInfo->busIdString = xalloc(64); + pDRIInfo->busIdString = malloc(64); sprintf(pDRIInfo->busIdString, "PCI:%d:%d:%d", ((pI810->PciInfo->domain << 8) | pI810->PciInfo->bus), pI810->PciInfo->dev, pI810->PciInfo->func @@ -370,7 +370,7 @@ I810DRIScreenInit(ScreenPtr pScreen) } pDRIInfo->SAREASize = SAREA_MAX; - if (!(pI810DRI = (I810DRIPtr) xcalloc(sizeof(I810DRIRec), 1))) { + if (!(pI810DRI = (I810DRIPtr) calloc(sizeof(I810DRIRec), 1))) { DRIDestroyInfoRec(pI810->pDRIInfo); pI810->pDRIInfo = NULL; return FALSE; @@ -399,7 +399,7 @@ I810DRIScreenInit(ScreenPtr pScreen) if (!DRIScreenInit(pScreen, pDRIInfo, &pI810->drmSubFD)) { xf86DrvMsg(pScreen->myNum, X_ERROR, "[dri] DRIScreenInit failed. Disabling DRI.\n"); - xfree(pDRIInfo->devPrivate); + free(pDRIInfo->devPrivate); pDRIInfo->devPrivate = NULL; DRIDestroyInfoRec(pI810->pDRIInfo); pI810->pDRIInfo = NULL; @@ -1055,16 +1055,16 @@ I810DRICloseScreen(ScreenPtr pScreen) if (pI810->pDRIInfo) { if (pI810->pDRIInfo->devPrivate) { - xfree(pI810->pDRIInfo->devPrivate); + free(pI810->pDRIInfo->devPrivate); pI810->pDRIInfo->devPrivate = NULL; } DRIDestroyInfoRec(pI810->pDRIInfo); pI810->pDRIInfo = NULL; } if (pI810->pVisualConfigs) - xfree(pI810->pVisualConfigs); + free(pI810->pVisualConfigs); if (pI810->pVisualConfigsPriv) - xfree(pI810->pVisualConfigsPriv); + free(pI810->pVisualConfigsPriv); } static Bool @@ -1202,12 +1202,12 @@ I810DRIMoveBuffers(WindowPtr pParent, DDXPointRec ptOldOrg, if (nbox > 1) { /* Keep ordering in each band, reverse order of bands */ - pboxNew1 = (BoxPtr) xalloc(sizeof(BoxRec) * nbox); + pboxNew1 = (BoxPtr) malloc(sizeof(BoxRec) * nbox); if (!pboxNew1) return; - pptNew1 = (DDXPointPtr) xalloc(sizeof(DDXPointRec) * nbox); + pptNew1 = (DDXPointPtr) malloc(sizeof(DDXPointRec) * nbox); if (!pptNew1) { - xfree(pboxNew1); + free(pboxNew1); return; } pboxBase = pboxNext = pbox + nbox - 1; @@ -1238,16 +1238,16 @@ I810DRIMoveBuffers(WindowPtr pParent, DDXPointRec ptOldOrg, if (nbox > 1) { /*reverse orderof rects in each band */ - pboxNew2 = (BoxPtr) xalloc(sizeof(BoxRec) * nbox); - pptNew2 = (DDXPointPtr) xalloc(sizeof(DDXPointRec) * nbox); + pboxNew2 = (BoxPtr) malloc(sizeof(BoxRec) * nbox); + pptNew2 = (DDXPointPtr) malloc(sizeof(DDXPointRec) * nbox); if (!pboxNew2 || !pptNew2) { if (pptNew2) - xfree(pptNew2); + free(pptNew2); if (pboxNew2) - xfree(pboxNew2); + free(pboxNew2); if (pboxNew1) { - xfree(pptNew1); - xfree(pboxNew1); + free(pptNew1); + free(pboxNew1); } return; } @@ -1312,12 +1312,12 @@ I810DRIMoveBuffers(WindowPtr pParent, DDXPointRec ptOldOrg, I810EmitFlush(pScrn); if (pboxNew2) { - xfree(pptNew2); - xfree(pboxNew2); + free(pptNew2); + free(pboxNew2); } if (pboxNew1) { - xfree(pptNew1); - xfree(pboxNew1); + free(pptNew1); + free(pboxNew1); } if (pI810->AccelInfoRec) diff --git a/src/i810_driver.c b/src/i810_driver.c index 68e45bb6..345854f2 100644 --- a/src/i810_driver.c +++ b/src/i810_driver.c @@ -364,7 +364,7 @@ I810FreeRec(ScrnInfoPtr pScrn) return; if (!pScrn->driverPrivate) return; - xfree(pScrn->driverPrivate); + free(pScrn->driverPrivate); pScrn->driverPrivate = NULL; } #endif @@ -618,7 +618,7 @@ I810PreInit(ScrnInfoPtr pScrn, int flags) /* Process the options */ xf86CollectOptions(pScrn, NULL); - if (!(pI810->Options = xalloc(sizeof(I810Options)))) + if (!(pI810->Options = malloc(sizeof(I810Options)))) return FALSE; memcpy(pI810->Options, I810Options, sizeof(I810Options)); xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, pI810->Options); @@ -1914,7 +1914,7 @@ I810ScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) pI810 = I810PTR(pScrn); hwp = VGAHWPTR(pScrn); - pI810->LpRing = xcalloc(sizeof(I810RingBuffer),1); + pI810->LpRing = calloc(sizeof(I810RingBuffer),1); if (!pI810->LpRing) { xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Could not allocate lpring data structure.\n"); @@ -2326,13 +2326,13 @@ I810CloseScreen(int scrnIndex, ScreenPtr pScreen) vgaHWUnmapMem(pScrn); if (pI810->ScanlineColorExpandBuffers) { - xfree(pI810->ScanlineColorExpandBuffers); + free(pI810->ScanlineColorExpandBuffers); pI810->ScanlineColorExpandBuffers = NULL; } if (infoPtr) { if (infoPtr->ScanlineColorExpandBuffers) - xfree(infoPtr->ScanlineColorExpandBuffers); + free(infoPtr->ScanlineColorExpandBuffers); XAADestroyInfoRec(infoPtr); pI810->AccelInfoRec = NULL; } @@ -2353,7 +2353,7 @@ I810CloseScreen(int scrnIndex, ScreenPtr pScreen) */ xf86GARTCloseScreen(scrnIndex); - xfree(pI810->LpRing); + free(pI810->LpRing); pI810->LpRing = NULL; pScrn->vtSema = FALSE; diff --git a/src/i810_hwmc.c b/src/i810_hwmc.c index 1c3ffc99..724e1bea 100644 --- a/src/i810_hwmc.c +++ b/src/i810_hwmc.c @@ -230,7 +230,7 @@ void I810InitMC(ScreenPtr pScreen) * Set *num_priv to the number of 32bit words that make up the size of * of the data that priv will point to. * - * *priv = (long *) xcalloc (elements, sizeof(element)) + * *priv = (long *) calloc (elements, sizeof(element)) * *num_priv = (elements * sizeof(element)) >> 2; * **************************************************************************/ @@ -256,7 +256,7 @@ int I810XvMCCreateContext (ScrnInfoPtr pScrn, XvMCContextPtr pContext, return BadAlloc; } - *priv = xcalloc(1,sizeof(I810XvMCCreateContextRec)); + *priv = calloc(1,sizeof(I810XvMCCreateContextRec)); contextRec = (I810XvMCCreateContextRec *)*priv; if(!*priv) { @@ -268,7 +268,7 @@ int I810XvMCCreateContext (ScrnInfoPtr pScrn, XvMCContextPtr pContext, if(drmCreateContext(pI810->drmSubFD, &(contextRec->drmcontext) ) < 0) { xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "I810XvMCCreateContext: Unable to create DRMContext!\n"); - xfree(*priv); + free(*priv); return BadAlloc; } @@ -295,7 +295,7 @@ int I810XvMCCreateSurface (ScrnInfoPtr pScrn, XvMCSurfacePtr pSurf, I810Ptr pI810 = I810PTR(pScrn); int i; - *priv = (long *)xcalloc(2,sizeof(long)); + *priv = (long *)calloc(2,sizeof(long)); if(!*priv) { xf86DrvMsg(pScrn->scrnIndex, X_ERROR, @@ -341,7 +341,7 @@ int I810XvMCCreateSubpicture (ScrnInfoPtr pScrn, XvMCSubpicturePtr pSubp, I810Ptr pI810 = I810PTR(pScrn); int i; - *priv = (long *)xcalloc(1,sizeof(long)); + *priv = (long *)calloc(1,sizeof(long)); if(!*priv) { xf86DrvMsg(pScrn->scrnIndex, X_ERROR, diff --git a/src/i810_video.c b/src/i810_video.c index ee1a2326..85b5b65c 100644 --- a/src/i810_video.c +++ b/src/i810_video.c @@ -174,7 +174,7 @@ void I810InitVideo(ScreenPtr pScreen) adaptors = &newAdaptor; } else { newAdaptors = /* need to free this someplace */ - xalloc((num_adaptors + 1) * sizeof(XF86VideoAdaptorPtr*)); + malloc((num_adaptors + 1) * sizeof(XF86VideoAdaptorPtr*)); if(newAdaptors) { memcpy(newAdaptors, adaptors, num_adaptors * sizeof(XF86VideoAdaptorPtr)); @@ -189,7 +189,7 @@ void I810InitVideo(ScreenPtr pScreen) xf86XVScreenInit(pScreen, adaptors, num_adaptors); if(newAdaptors) - xfree(newAdaptors); + free(newAdaptors); } /* *INDENT-OFF* */ @@ -383,7 +383,7 @@ I810SetupImageVideo(ScreenPtr pScreen) XF86VideoAdaptorPtr adapt; I810PortPrivPtr pPriv; - if(!(adapt = xcalloc(1, sizeof(XF86VideoAdaptorRec) + + if(!(adapt = calloc(1, sizeof(XF86VideoAdaptorRec) + sizeof(I810PortPrivRec) + sizeof(DevUnion)))) return NULL; @@ -1225,18 +1225,18 @@ I810AllocateSurface( surface->width = w; surface->height = h; - if(!(surface->pitches = xalloc(sizeof(int)))) { + if(!(surface->pitches = malloc(sizeof(int)))) { xf86FreeOffscreenLinear(linear); return BadAlloc; } - if(!(surface->offsets = xalloc(sizeof(int)))) { - xfree(surface->pitches); + if(!(surface->offsets = malloc(sizeof(int)))) { + free(surface->pitches); xf86FreeOffscreenLinear(linear); return BadAlloc; } - if(!(pPriv = xalloc(sizeof(OffscreenPrivRec)))) { - xfree(surface->pitches); - xfree(surface->offsets); + if(!(pPriv = malloc(sizeof(OffscreenPrivRec)))) { + free(surface->pitches); + free(surface->offsets); xf86FreeOffscreenLinear(linear); return BadAlloc; } @@ -1286,9 +1286,9 @@ I810FreeSurface( I810StopSurface(surface); } xf86FreeOffscreenLinear(pPriv->linear); - xfree(surface->pitches); - xfree(surface->offsets); - xfree(surface->devPrivate.ptr); + free(surface->pitches); + free(surface->offsets); + free(surface->devPrivate.ptr); return Success; } @@ -1401,7 +1401,7 @@ I810InitOffscreenImages(ScreenPtr pScreen) XF86OffscreenImagePtr offscreenImages; /* need to free this someplace */ - if(!(offscreenImages = xalloc(sizeof(XF86OffscreenImageRec)))) { + if(!(offscreenImages = malloc(sizeof(XF86OffscreenImageRec)))) { return; } @@ -78,6 +78,15 @@ void i830_uxa_block_handler(ScreenPtr pScreen); Bool i830_get_aperture_space(ScrnInfoPtr scrn, drm_intel_bo ** bo_table, int num_bos); +/* XXX + * The X server gained an *almost* identical implementation in 1.9. + * + * Remove this duplicate code either in 2.16 (when we can depend upon 1.9) + * or the drivers are merged back into the xserver tree, whichever happens + * earlier. + */ + +#ifndef _LIST_H_ /* classic doubly-link circular list */ struct list { struct list *next, *prev; @@ -125,41 +134,77 @@ list_is_empty(struct list *head) { return head->next == head; } +#endif #ifndef container_of #define container_of(ptr, type, member) \ (type *)((char *)(ptr) - (char *) &((type *)0)->member) #endif +#ifndef list_entry #define list_entry(ptr, type, member) \ container_of(ptr, type, member) +#endif +#ifndef list_first_entry #define list_first_entry(ptr, type, member) \ list_entry((ptr)->next, type, member) +#endif +#ifndef list_foreach #define list_foreach(pos, head) \ for (pos = (head)->next; pos != (head); pos = pos->next) +#endif +/* XXX list.h from xserver-1.9 uses a GCC-ism to avoid having to pass type */ +#ifndef list_foreach_entry #define list_foreach_entry(pos, type, head, member) \ for (pos = list_entry((head)->next, type, member);\ &pos->member != (head); \ pos = list_entry(pos->member.next, type, member)) +#endif struct intel_pixmap { dri_bo *bo; - uint32_t tiling, stride; - uint32_t flush_write_domain; - uint32_t flush_read_domains; - uint32_t batch_write_domain; - uint32_t batch_read_domains; + struct list flush, batch, in_flight; + + uint16_t stride; + uint8_t tiling; + int8_t busy :2; + int8_t batch_write :1; }; -struct intel_pixmap *i830_get_pixmap_intel(PixmapPtr pixmap); +#if HAS_DEVPRIVATEKEYREC +extern DevPrivateKeyRec uxa_pixmap_index; +#else +extern int uxa_pixmap_index; +#endif + +static inline struct intel_pixmap *i830_get_pixmap_intel(PixmapPtr pixmap) +{ +#if HAS_DEVPRIVATEKEYREC + return dixGetPrivate(&pixmap->devPrivates, &uxa_pixmap_index); +#else + return dixLookupPrivate(&pixmap->devPrivates, &uxa_pixmap_index); +#endif +} + +static inline Bool intel_pixmap_is_busy(struct intel_pixmap *priv) +{ + if (priv->busy == -1) + priv->busy = drm_intel_bo_busy(priv->bo); + return priv->busy; +} + +static inline void i830_set_pixmap_intel(PixmapPtr pixmap, struct intel_pixmap *intel) +{ + dixSetPrivate(&pixmap->devPrivates, &uxa_pixmap_index, intel); +} static inline Bool i830_uxa_pixmap_is_dirty(PixmapPtr pixmap) { - return i830_get_pixmap_intel(pixmap)->flush_write_domain != 0; + return !list_is_empty(&i830_get_pixmap_intel(pixmap)->flush); } static inline Bool i830_pixmap_tiled(PixmapPtr pixmap) @@ -266,15 +311,6 @@ struct _i830_memory { Bool lifetime_fixed_offset; }; -typedef struct { - int tail_mask; - i830_memory *mem; - unsigned char *virtual_start; - int head; - int tail; - int space; -} I830RingBuffer; - /* store information about an Ixxx DVO */ /* The i830->i865 use multiple DVOs with multiple i2cs */ /* the i915, i945 have a single sDVO i2c bus - which is different */ @@ -459,22 +495,10 @@ typedef struct intel_screen_private { i830_memory *cursor_mem_classic[2]; /* One big buffer for all cursors for kernels that support this */ i830_memory *cursor_mem_argb[2]; - i830_memory *fake_bufmgr_mem; - - /* Regions allocated either from the above pools, or from agpgart. */ - I830RingBuffer ring; - - /** Number of bytes being emitted in the current BEGIN_LP_RING */ - unsigned int ring_emitting; - /** Number of bytes that have been emitted in the current BEGIN_LP_RING */ - unsigned int ring_used; - /** Offset in the ring for the next DWORD emit */ - uint32_t ring_next; - dri_bufmgr *bufmgr; - uint8_t *batch_ptr; + uint32_t batch_ptr[4096]; /** Byte offset in batch_ptr for the next dword to be emitted. */ unsigned int batch_used; /** Position in batch_ptr at the start of the current BEGIN_BATCH */ @@ -508,8 +532,6 @@ typedef struct intel_screen_private { i830_memory *memory_manager; /**< DRI memory manager aperture */ - Bool have_gem; - Bool need_mi_flush; Bool tiling; @@ -533,6 +555,7 @@ typedef struct intel_screen_private { CloseScreenProcPtr CloseScreen; + void (*vertex_flush) (struct intel_screen_private *intel); void (*batch_flush_notify) (ScrnInfoPtr scrn); uxa_driver_t *uxa_driver; @@ -541,6 +564,7 @@ typedef struct intel_screen_private { int accel_pixmap_offset_alignment; int accel_max_x; int accel_max_y; + int max_bo_size; int max_gtt_map_size; int max_tiling_size; @@ -573,17 +597,17 @@ typedef struct intel_screen_private { float scale_units[2][2]; /** Transform pointers for src/mask, or NULL if identity */ PictTransform *transform[2]; - float dst_coord_adjust; - float src_coord_adjust; - float mask_coord_adjust; PixmapPtr render_source, render_mask, render_dest; PicturePtr render_source_picture, render_mask_picture, render_dest_picture; CARD32 render_source_solid; CARD32 render_mask_solid; + PixmapPtr render_current_dest; Bool render_source_is_solid; Bool render_mask_is_solid; Bool needs_render_state_emit; + Bool needs_render_vertex_emit; + Bool needs_render_ca_pass; /* i830 render accel state */ uint32_t render_dest_format; @@ -599,6 +623,20 @@ typedef struct intel_screen_private { uint32_t dst_format; } i915_render_state; + uint32_t prim_offset; + void (*prim_emit)(PixmapPtr dest, + int srcX, int srcY, + int maskX, int maskY, + int dstX, int dstY, + int w, int h); + int floats_per_vertex; + int last_floats_per_vertex; + uint32_t vertex_count; + uint32_t vertex_index; + uint32_t vertex_used; + float vertex_ptr[4*1024]; + dri_bo *vertex_bo; + /* 965 render acceleration state */ struct gen4_render_state *gen4_render_state; @@ -606,6 +644,9 @@ typedef struct intel_screen_private { Bool directRenderingOpen; int drmSubFD; +#ifdef notyet + drmEventContext event_context; +#endif char *deviceName; /* Broken-out options. */ @@ -631,8 +672,6 @@ typedef struct intel_screen_private { unsigned int SaveGeneration; - OsTimerPtr devicesTimer; - int ddc2; enum backlight_control backlight_control_method; @@ -716,7 +755,6 @@ typedef struct intel_screen_private { enum last_3d last_3d; Bool use_drm_mode; - Bool kernel_exec_fencing; /** Enables logging of debug output related to mode switching. */ Bool debug_modes; @@ -763,7 +801,6 @@ unsigned long intel_get_pixmap_pitch(PixmapPtr pixmap); #include "i830_batchbuffer.h" /* I830 specific functions */ -extern int I830WaitLpRing(ScrnInfoPtr scrn, int n, int timeout_millis); extern void I830SetPIOAccess(intel_screen_private *intel); extern void I830SetMMIOAccess(intel_screen_private *intel); extern void I830InitHWCursor(ScrnInfoPtr scrn); @@ -816,6 +853,8 @@ i830_pipe_a_require_deactivate (ScrnInfoPtr scrn); Bool I830DRI2ScreenInit(ScreenPtr pScreen); void I830DRI2CloseScreen(ScreenPtr pScreen); +void I830DRI2FrameEventHandler(unsigned int frame, unsigned int tv_sec, + unsigned int tv_usec, void *user_data); extern Bool drmmode_pre_init(ScrnInfoPtr scrn, int fd, int cpp); extern int drmmode_get_pipe_from_crtc_id(drm_intel_bufmgr * bufmgr, @@ -903,8 +942,11 @@ DisplayModePtr i830_ddc_get_modes(xf86OutputPtr output); void i830_tv_init(ScrnInfoPtr scrn); /* i830_render.c */ -Bool i830_check_composite(int op, PicturePtr sourcec, PicturePtr mask, - PicturePtr dest); +Bool i830_check_composite(int op, + PicturePtr sourcec, PicturePtr mask, PicturePtr dest, + int width, int height); +Bool i830_check_composite_target(PixmapPtr pixmap); +Bool i830_check_composite_texture(ScreenPtr screen, PicturePtr picture); Bool i830_prepare_composite(int op, PicturePtr sourcec, PicturePtr mask, PicturePtr dest, PixmapPtr sourcecPixmap, PixmapPtr maskPixmap, PixmapPtr destPixmap); @@ -914,21 +956,27 @@ void i830_composite(PixmapPtr dest, int srcX, int srcY, int maskX, int maskY, int dstX, int dstY, int w, int h); void i830_done_composite(PixmapPtr dest); /* i915_render.c */ -Bool i915_check_composite(int op, PicturePtr sourcec, PicturePtr mask, - PicturePtr dest); +Bool i915_check_composite(int op, + PicturePtr sourcec, PicturePtr mask, PicturePtr dest, + int width, int height); +Bool i915_check_composite_target(PixmapPtr pixmap); +Bool i915_check_composite_texture(ScreenPtr screen, PicturePtr picture); Bool i915_prepare_composite(int op, PicturePtr sourcec, PicturePtr mask, PicturePtr dest, PixmapPtr sourcecPixmap, PixmapPtr maskPixmap, PixmapPtr destPixmap); void i915_composite(PixmapPtr dest, int srcX, int srcY, int maskX, int maskY, int dstX, int dstY, int w, int h); +void i915_vertex_flush(intel_screen_private *intel); void i915_batch_flush_notify(ScrnInfoPtr scrn); void i830_batch_flush_notify(ScrnInfoPtr scrn); /* i965_render.c */ unsigned int gen4_render_state_size(ScrnInfoPtr scrn); void gen4_render_state_init(ScrnInfoPtr scrn); void gen4_render_state_cleanup(ScrnInfoPtr scrn); -Bool i965_check_composite(int op, PicturePtr sourcec, PicturePtr mask, - PicturePtr dest); +Bool i965_check_composite(int op, + PicturePtr sourcec, PicturePtr mask, PicturePtr dest, + int width, int height); +Bool i965_check_composite_texture(ScreenPtr screen, PicturePtr picture); Bool i965_prepare_composite(int op, PicturePtr sourcec, PicturePtr mask, PicturePtr dest, PixmapPtr sourcecPixmap, PixmapPtr maskPixmap, PixmapPtr destPixmap); @@ -949,14 +997,6 @@ void i830_enter_render(ScrnInfoPtr); extern void intel_sync(ScrnInfoPtr scrn); -static inline void -i830_wait_ring_idle(ScrnInfoPtr scrn) -{ - intel_screen_private *intel = intel_get_screen_private(scrn); - - I830WaitLpRing(scrn, intel->ring.mem->size - 8, 0); -} - static inline int i830_fb_compression_supported(intel_screen_private *intel) { if (!IS_MOBILE(intel)) diff --git a/src/i830_3d.c b/src/i830_3d.c index e83cb3f7..a92da055 100644 --- a/src/i830_3d.c +++ b/src/i830_3d.c @@ -38,7 +38,7 @@ void I830EmitInvarientState(ScrnInfoPtr scrn) { intel_screen_private *intel = intel_get_screen_private(scrn); - ATOMIC_BATCH(58); + assert(intel->in_batch_atomic); OUT_BATCH(_3DSTATE_MAP_CUBE | MAP_UNIT(0)); OUT_BATCH(_3DSTATE_MAP_CUBE | MAP_UNIT(1)); @@ -222,6 +222,4 @@ void I830EmitInvarientState(ScrnInfoPtr scrn) AA_LINE_ECAAR_WIDTH_1_0 | AA_LINE_REGION_WIDTH_ENABLE | AA_LINE_REGION_WIDTH_1_0 | AA_LINE_DISABLE); - - ADVANCE_BATCH(); } diff --git a/src/i830_accel.c b/src/i830_accel.c index 0b9195f3..df4f58db 100644 --- a/src/i830_accel.c +++ b/src/i830_accel.c @@ -46,80 +46,11 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include "i830_ring.h" #include "i915_drm.h" -unsigned long intel_get_pixmap_offset(PixmapPtr pixmap) -{ - ScreenPtr pScreen = pixmap->drawable.pScreen; - ScrnInfoPtr scrn = xf86Screens[pScreen->myNum]; - intel_screen_private *intel = intel_get_screen_private(scrn); - - return (unsigned long)pixmap->devPrivate.ptr - - (unsigned long)intel->FbBase; -} - unsigned long intel_get_pixmap_pitch(PixmapPtr pixmap) { return (unsigned long)pixmap->devKind; } -int -I830WaitLpRing(ScrnInfoPtr scrn, int n, int timeout_millis) -{ - intel_screen_private *intel = intel_get_screen_private(scrn); - I830RingBuffer *ring = &intel->ring; - int iters = 0; - unsigned int start = 0; - unsigned int now = 0; - int last_head = 0; - unsigned int first = 0; - - /* If your system hasn't moved the head pointer in 2 seconds, I'm going to - * call it crashed. - */ - if (timeout_millis == 0) - timeout_millis = 2000; - - if (I810_DEBUG & DEBUG_VERBOSE_ACCEL) { - ErrorF("I830WaitLpRing %d\n", n); - first = GetTimeInMillis(); - } - - while (ring->space < n) { - ring->head = INREG(LP_RING + RING_HEAD) & I830_HEAD_MASK; - ring->space = ring->head - (ring->tail + 8); - - if (ring->space < 0) - ring->space += ring->mem->size; - - iters++; - now = GetTimeInMillis(); - if (start == 0 || now < start || ring->head != last_head) { - if (I810_DEBUG & DEBUG_VERBOSE_ACCEL) - if (now > start) - ErrorF("space: %d wanted %d\n", ring->space, n); - start = now; - last_head = ring->head; - } else if (now - start > timeout_millis) { - ErrorF("Error in I830WaitLpRing(), timeout for %d seconds\n", - timeout_millis/1000); - ErrorF("space: %d wanted %d\n", ring->space, n); - intel->uxa_driver = NULL; - FatalError("lockup\n"); - } - - DELAY(10); - } - - if (I810_DEBUG & DEBUG_VERBOSE_ACCEL) { - now = GetTimeInMillis(); - if (now - first) { - ErrorF("Elapsed %u ms\n", now - first); - ErrorF("space: %d wanted %d\n", ring->space, n); - } - } - - return iters; -} - void i830_debug_flush(ScrnInfoPtr scrn) { intel_screen_private *intel = intel_get_screen_private(scrn); @@ -128,7 +59,7 @@ void i830_debug_flush(ScrnInfoPtr scrn) intel_batch_emit_flush(scrn); if (intel->debug_flush & DEBUG_FLUSH_BATCHES) - intel_batch_submit(scrn); + intel_batch_submit(scrn, FALSE); } /* The following function sets up the supported acceleration. Call it diff --git a/src/i830_batchbuffer.c b/src/i830_batchbuffer.c index d067d480..2ef89f24 100644 --- a/src/i830_batchbuffer.c +++ b/src/i830_batchbuffer.c @@ -40,72 +40,29 @@ #define DUMP_BATCHBUFFERS NULL /* "/tmp/i915-batchbuffers.dump" */ -static int -intel_nondrm_exec(dri_bo *bo, unsigned int used, void *priv) +static void intel_end_vertex(intel_screen_private *intel) { - ScrnInfoPtr scrn = priv; - intel_screen_private *intel = intel_get_screen_private(scrn); + if (intel->vertex_bo) { + if (intel->vertex_used) + dri_bo_subdata(intel->vertex_bo, 0, intel->vertex_used*4, intel->vertex_ptr); - BEGIN_LP_RING(4); - OUT_RING(MI_BATCH_BUFFER_START | (2 << 6)); - OUT_RING(bo->offset); - OUT_RING(MI_NOOP); - OUT_RING(MI_NOOP); - ADVANCE_LP_RING(); - - return 0; -} - -static int -intel_nondrm_exec_i830(dri_bo *bo, unsigned int used, void *priv) -{ - ScrnInfoPtr scrn = priv; - intel_screen_private *intel = intel_get_screen_private(scrn); - - BEGIN_LP_RING(4); - OUT_RING(MI_BATCH_BUFFER); - OUT_RING(bo->offset); - OUT_RING(bo->offset + intel->batch_used - 4); - OUT_RING(MI_NOOP); - ADVANCE_LP_RING(); - - return 0; -} - -/** - * Creates a fence value representing a request to be passed. - * - * Stub implementation that should be avoided when DRM functions are available. - */ -static unsigned int -intel_nondrm_emit(void *priv) -{ - static unsigned int fence = 0; - - /* Match DRM in not using half the range. The fake bufmgr relies on this. */ - if (++fence >= 0x8000000) - fence = 1; - - return fence; + dri_bo_unreference(intel->vertex_bo); + intel->vertex_bo = NULL; + } } -/** - * Waits on a fence representing a request to be passed. - * - * Stub implementation that should be avoided when DRM functions are available. - */ -static void -intel_nondrm_wait(unsigned int fence, void *priv) +void intel_next_vertex(intel_screen_private *intel) { - ScrnInfoPtr scrn = priv; + intel_end_vertex(intel); - i830_wait_ring_idle(scrn); + intel->vertex_bo = + dri_bo_alloc(intel->bufmgr, "vertex", sizeof (intel->vertex_ptr), 4096); + intel->vertex_used = 0; } static void intel_next_batch(ScrnInfoPtr scrn) { intel_screen_private *intel = intel_get_screen_private(scrn); - int ret; /* The 865 has issues with larger-than-page-sized batch buffers. */ if (IS_I865G(intel)) @@ -115,12 +72,7 @@ static void intel_next_batch(ScrnInfoPtr scrn) intel->batch_bo = dri_bo_alloc(intel->bufmgr, "batch", 4096 * 4, 4096); - ret = dri_bo_map(intel->batch_bo, 1); - if (ret != 0) - FatalError("Failed to map batchbuffer: %s\n", strerror(-ret)); - intel->batch_used = 0; - intel->batch_ptr = intel->batch_bo->virtual; /* We don't know when another client has executed, so we have * to reinitialize our 3D state per batch. @@ -136,34 +88,54 @@ void intel_batch_init(ScrnInfoPtr scrn) intel->batch_emitting = 0; intel_next_batch(scrn); - - if (!intel->have_gem) { - if (IS_I830(intel) || IS_845G(intel)) { - intel_bufmgr_fake_set_exec_callback(intel->bufmgr, - intel_nondrm_exec_i830, scrn); - } else { - intel_bufmgr_fake_set_exec_callback(intel->bufmgr, - intel_nondrm_exec, scrn); - } - intel_bufmgr_fake_set_fence_callback(intel->bufmgr, - intel_nondrm_emit, intel_nondrm_wait, scrn); - } } void intel_batch_teardown(ScrnInfoPtr scrn) { intel_screen_private *intel = intel_get_screen_private(scrn); - if (intel->batch_ptr != NULL) { - dri_bo_unmap(intel->batch_bo); - intel->batch_ptr = NULL; - + if (intel->batch_bo != NULL) { dri_bo_unreference(intel->batch_bo); intel->batch_bo = NULL; + } + if (intel->last_batch_bo != NULL) { dri_bo_unreference(intel->last_batch_bo); intel->last_batch_bo = NULL; } + + if (intel->vertex_bo) { + dri_bo_unreference(intel->vertex_bo); + intel->vertex_bo = NULL; + } + + while (!list_is_empty(&intel->batch_pixmaps)) + list_del(intel->batch_pixmaps.next); + + while (!list_is_empty(&intel->flush_pixmaps)) + list_del(intel->flush_pixmaps.next); + + while (!list_is_empty(&intel->in_flight)) { + struct intel_pixmap *entry; + + entry = list_first_entry(&intel->in_flight, + struct intel_pixmap, + in_flight); + + dri_bo_unreference(entry->bo); + list_del(&entry->in_flight); + free(entry); + } +} + +void intel_batch_do_flush(ScrnInfoPtr scrn) +{ + intel_screen_private *intel = intel_get_screen_private(scrn); + + while (!list_is_empty(&intel->flush_pixmaps)) + list_del(intel->flush_pixmaps.next); + + intel->need_mi_flush = FALSE; } void intel_batch_emit_flush(ScrnInfoPtr scrn) @@ -182,55 +154,44 @@ void intel_batch_emit_flush(ScrnInfoPtr scrn) OUT_BATCH(MI_FLUSH | flags); ADVANCE_BATCH(); - while (!list_is_empty(&intel->flush_pixmaps)) { - struct intel_pixmap *entry; - - entry = list_first_entry(&intel->flush_pixmaps, - struct intel_pixmap, - flush); - - entry->flush_read_domains = entry->flush_write_domain = 0; - list_del(&entry->flush); - } - - intel->need_mi_flush = FALSE; + intel_batch_do_flush(scrn); } -void intel_batch_submit(ScrnInfoPtr scrn) +void intel_batch_submit(ScrnInfoPtr scrn, int flush) { intel_screen_private *intel = intel_get_screen_private(scrn); int ret; assert (!intel->in_batch_atomic); + if (intel->vertex_flush) + intel->vertex_flush(intel); + intel_end_vertex(intel); + + if (flush) + intel_batch_emit_flush(scrn); + if (intel->batch_used == 0) return; - /* Emit a padding dword if we aren't going to be quad-word aligned. */ - if ((intel->batch_used & 4) == 0) { - *(uint32_t *) (intel->batch_ptr + intel->batch_used) = MI_NOOP; - intel->batch_used += 4; - } - /* Mark the end of the batchbuffer. */ - *(uint32_t *) (intel->batch_ptr + intel->batch_used) = - MI_BATCH_BUFFER_END; - intel->batch_used += 4; + OUT_BATCH(MI_BATCH_BUFFER_END); + /* Emit a padding dword if we aren't going to be quad-word aligned. */ + if (intel->batch_used & 1) + OUT_BATCH(MI_NOOP); if (DUMP_BATCHBUFFERS) { FILE *file = fopen(DUMP_BATCHBUFFERS, "a"); if (file) { - fwrite (intel->batch_ptr, intel->batch_used, 1, file); + fwrite (intel->batch_ptr, intel->batch_used*4, 1, file); fclose(file); } } - dri_bo_unmap(intel->batch_bo); - intel->batch_ptr = NULL; - - ret = - dri_bo_exec(intel->batch_bo, intel->batch_used, NULL, 0, - 0xffffffff); + ret = dri_bo_subdata(intel->batch_bo, 0, intel->batch_used*4, intel->batch_ptr); + if (ret == 0) + ret = dri_bo_exec(intel->batch_bo, intel->batch_used*4, + NULL, 0, 0xffffffff); if (ret != 0) { static int once; @@ -250,25 +211,14 @@ void intel_batch_submit(ScrnInfoPtr scrn) struct intel_pixmap, batch); - entry->batch_read_domains = entry->batch_write_domain = 0; + entry->busy = -1; + entry->batch_write = 0; list_del(&entry->batch); } - /* Mark that we need to flush whatever potential rendering we've done in the - * blockhandler. We could set this less often, but it's probably not worth - * the work. - */ - intel->need_mi_flush = !list_is_empty(&intel->flush_pixmaps); - while (!list_is_empty(&intel->flush_pixmaps)) { - struct intel_pixmap *entry; - - entry = list_first_entry(&intel->flush_pixmaps, - struct intel_pixmap, - flush); - - entry->flush_read_domains = entry->flush_write_domain = 0; - list_del(&entry->flush); - } + intel->need_mi_flush |= !list_is_empty(&intel->flush_pixmaps); + while (!list_is_empty(&intel->flush_pixmaps)) + list_del(intel->flush_pixmaps.next); while (!list_is_empty(&intel->in_flight)) { struct intel_pixmap *entry; @@ -279,7 +229,7 @@ void intel_batch_submit(ScrnInfoPtr scrn) dri_bo_unreference(entry->bo); list_del(&entry->in_flight); - xfree(entry); + free(entry); } /* Save a ref to the last batch emitted, which we use for syncing @@ -306,8 +256,8 @@ void intel_batch_wait_last(ScrnInfoPtr scrn) /* Map it CPU write, which guarantees it's done. This is a completely * non performance path, so we don't need anything better. */ - drm_intel_bo_map(intel->last_batch_bo, TRUE); - drm_intel_bo_unmap(intel->last_batch_bo); + drm_intel_gem_bo_map_gtt(intel->last_batch_bo); + drm_intel_gem_bo_unmap_gtt(intel->last_batch_bo); } void intel_sync(ScrnInfoPtr scrn) @@ -320,7 +270,6 @@ void intel_sync(ScrnInfoPtr scrn) if (!scrn->vtSema || !intel->batch_bo || !intel->batch_ptr) return; - intel_batch_emit_flush(scrn); - intel_batch_submit(scrn); + intel_batch_submit(scrn, TRUE); intel_batch_wait_last(scrn); } diff --git a/src/i830_batchbuffer.h b/src/i830_batchbuffer.h index 50cb966d..30680855 100644 --- a/src/i830_batchbuffer.h +++ b/src/i830_batchbuffer.h @@ -36,12 +36,18 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. void intel_batch_init(ScrnInfoPtr scrn); void intel_batch_teardown(ScrnInfoPtr scrn); void intel_batch_emit_flush(ScrnInfoPtr scrn); -void intel_batch_submit(ScrnInfoPtr scrn); +void intel_batch_do_flush(ScrnInfoPtr scrn); +void intel_batch_submit(ScrnInfoPtr scrn, int flush); void intel_batch_wait_last(ScrnInfoPtr scrn); static inline int intel_batch_space(intel_screen_private *intel) { - return (intel->batch_bo->size - BATCH_RESERVED) - (intel->batch_used); + return (intel->batch_bo->size - BATCH_RESERVED) - (4*intel->batch_used); +} + +static inline int intel_vertex_space(intel_screen_private *intel) +{ + return intel->vertex_bo ? intel->vertex_bo->size - (4*intel->vertex_used) : 0; } static inline void @@ -49,7 +55,7 @@ intel_batch_require_space(ScrnInfoPtr scrn, intel_screen_private *intel, GLuint { assert(sz < intel->batch_bo->size - 8); if (intel_batch_space(intel) < sz) - intel_batch_submit(scrn); + intel_batch_submit(scrn, FALSE); } static inline void intel_batch_start_atomic(ScrnInfoPtr scrn, unsigned int sz) @@ -60,7 +66,7 @@ static inline void intel_batch_start_atomic(ScrnInfoPtr scrn, unsigned int sz) intel_batch_require_space(scrn, intel, sz * 4); intel->in_batch_atomic = TRUE; - intel->batch_atomic_limit = intel->batch_used + sz * 4; + intel->batch_atomic_limit = intel->batch_used + sz; } static inline void intel_batch_end_atomic(ScrnInfoPtr scrn) @@ -74,22 +80,19 @@ static inline void intel_batch_end_atomic(ScrnInfoPtr scrn) static inline void intel_batch_emit_dword(intel_screen_private *intel, uint32_t dword) { - assert(intel->batch_ptr != NULL); - assert(intel->batch_emitting); - *(uint32_t *) (intel->batch_ptr + intel->batch_used) = dword; - intel->batch_used += 4; + intel->batch_ptr[intel->batch_used++] = dword; } static inline void intel_batch_align(intel_screen_private *intel, uint32_t align) { uint32_t delta; - assert(intel->batch_ptr != NULL); + align /= 4; assert(align); if ((delta = intel->batch_used & (align - 1))) { delta = align - delta; - memset (intel->batch_ptr + intel->batch_used, 0, delta); + memset (intel->batch_ptr + intel->batch_used, 0, 4*delta); intel->batch_used += delta; } } @@ -100,20 +103,17 @@ intel_batch_emit_reloc(intel_screen_private *intel, uint32_t read_domains, uint32_t write_domains, uint32_t delta, int needs_fence) { - assert(intel_batch_space(intel) >= 4); - *(uint32_t *) (intel->batch_ptr + intel->batch_used) = - bo->offset + delta; if (needs_fence) drm_intel_bo_emit_reloc_fence(intel->batch_bo, - intel->batch_used, + intel->batch_used * 4, bo, delta, read_domains, write_domains); else - drm_intel_bo_emit_reloc(intel->batch_bo, intel->batch_used, + drm_intel_bo_emit_reloc(intel->batch_bo, intel->batch_used * 4, bo, delta, read_domains, write_domains); - intel->batch_used += 4; + intel_batch_emit_dword(intel, bo->offset + delta); } static inline void @@ -123,18 +123,14 @@ intel_batch_mark_pixmap_domains(intel_screen_private *intel, { assert (read_domains); assert (write_domain == 0 || write_domain == read_domains); - assert (write_domain == 0 || - priv->flush_write_domain == 0 || - priv->flush_write_domain == write_domain); - - priv->flush_read_domains |= read_domains; - priv->batch_read_domains |= read_domains; - priv->flush_write_domain |= write_domain; - priv->batch_write_domain |= write_domain; + if (list_is_empty(&priv->batch)) list_add(&priv->batch, &intel->batch_pixmaps); - if (list_is_empty(&priv->flush)) + if (write_domain && list_is_empty(&priv->flush)) list_add(&priv->flush, &intel->flush_pixmaps); + + priv->batch_write |= write_domain != 0; + priv->busy = 1; } static inline void @@ -142,21 +138,12 @@ intel_batch_emit_reloc_pixmap(intel_screen_private *intel, PixmapPtr pixmap, uint32_t read_domains, uint32_t write_domain, uint32_t delta, int needs_fence) { - dri_bo *bo = i830_get_pixmap_bo(pixmap); - uint32_t offset; - assert(intel->batch_ptr != NULL); - assert(intel_batch_space(intel) >= 4); - if (bo) { - struct intel_pixmap *priv = i830_get_pixmap_intel(pixmap); - intel_batch_mark_pixmap_domains(intel, priv, read_domains, - write_domain); - intel_batch_emit_reloc(intel, priv->bo, read_domains, - write_domain, delta, needs_fence); - return; - } - offset = intel_get_pixmap_offset(pixmap); - *(uint32_t *)(intel->batch_ptr + intel->batch_used) = offset + delta; - intel->batch_used += 4; + struct intel_pixmap *priv = i830_get_pixmap_intel(pixmap); + + intel_batch_mark_pixmap_domains(intel, priv, read_domains, + write_domain); + intel_batch_emit_reloc(intel, priv->bo, read_domains, + write_domain, delta, needs_fence); } #define ALIGN_BATCH(align) intel_batch_align(intel, align); @@ -189,19 +176,7 @@ do { \ "ADVANCE_BATCH\n", __FUNCTION__); \ assert(!intel->in_batch_atomic); \ intel_batch_require_space(scrn, intel, (n) * 4); \ - intel->batch_emitting = (n) * 4; \ - intel->batch_emit_start = intel->batch_used; \ -} while (0) - -/* special-case variant for when we have preallocated space */ -#define ATOMIC_BATCH(n) \ -do { \ - if (intel->batch_emitting != 0) \ - FatalError("%s: ATOMIC_BATCH called without closing " \ - "ADVANCE_BATCH\n", __FUNCTION__); \ - assert(intel->in_batch_atomic); \ - assert(intel->batch_used + (n) * 4 <= intel->batch_atomic_limit); \ - intel->batch_emitting = (n) * 4; \ + intel->batch_emitting = (n); \ intel->batch_emit_start = intel->batch_used; \ } while (0) @@ -224,9 +199,16 @@ do { \ if ((intel->batch_emitting > 8) && \ (I810_DEBUG & DEBUG_ALWAYS_SYNC)) { \ /* Note: not actually syncing, just flushing each batch. */ \ - intel_batch_submit(scrn); \ + intel_batch_submit(scrn, FALSE); \ } \ intel->batch_emitting = 0; \ } while (0) +void intel_next_vertex(intel_screen_private *intel); +static inline void intel_vertex_emit(intel_screen_private *intel, float v) +{ + intel->vertex_ptr[intel->vertex_used++] = v; +} +#define OUT_VERTEX(v) intel_vertex_emit(intel, v) + #endif /* _INTEL_BATCHBUFFER_H */ diff --git a/src/i830_bios.c b/src/i830_bios.c index b7262c79..da77cd43 100644 --- a/src/i830_bios.c +++ b/src/i830_bios.c @@ -352,7 +352,7 @@ int i830_bios_init(ScrnInfoPtr scrn) "libpciaccess reported 0 rom size, guessing %dkB\n", size / 1024); } - bios = xalloc(size); + bios = malloc(size); if (bios == NULL) return -1; @@ -361,7 +361,7 @@ int i830_bios_init(ScrnInfoPtr scrn) xf86DrvMsg(scrn->scrnIndex, X_WARNING, "libpciaccess failed to read %dkB video BIOS: %s\n", size / 1024, strerror(-ret)); - xfree(bios); + free(bios); return -1; } @@ -369,7 +369,7 @@ int i830_bios_init(ScrnInfoPtr scrn) if (vbt_off >= size) { xf86DrvMsg(scrn->scrnIndex, X_ERROR, "Bad VBT offset: 0x%x\n", vbt_off); - xfree(bios); + free(bios); return -1; } @@ -377,7 +377,7 @@ int i830_bios_init(ScrnInfoPtr scrn) if (memcmp(vbt->signature, "$VBT", 4) != 0) { xf86DrvMsg(scrn->scrnIndex, X_ERROR, "Bad VBT signature\n"); - xfree(bios); + free(bios); return -1; } @@ -390,7 +390,7 @@ int i830_bios_init(ScrnInfoPtr scrn) parse_driver_feature(intel, bdb); parse_sdvo_mapping(scrn, bdb); - xfree(bios); + free(bios); return 0; } diff --git a/src/i830_crt.c b/src/i830_crt.c index 26c9d412..b18834e7 100644 --- a/src/i830_crt.c +++ b/src/i830_crt.c @@ -500,7 +500,7 @@ static void i830_crt_destroy (xf86OutputPtr output) { if (output->driver_private) - xfree (output->driver_private); + free (output->driver_private); } #ifdef RANDR_GET_CRTC_INTERFACE @@ -537,7 +537,7 @@ i830_get_edid(xf86OutputPtr output, int gpio_reg, char *gpio_str) xf86DestroyI2CBusRec(intel_output->pDDCBus, TRUE, TRUE); intel_output->pDDCBus = NULL; if (edid_mon) { - xfree(edid_mon); + free(edid_mon); edid_mon = NULL; } } diff --git a/src/i830_display.c b/src/i830_display.c index 2358f193..c96b9d6e 100644 --- a/src/i830_display.c +++ b/src/i830_display.c @@ -701,7 +701,8 @@ intel_igdng_find_best_PLL(const intel_limit_t *limit, xf86CrtcPtr crtc, intel_clock_t clock; int max_n; Bool found = FALSE; - int err_most = (target >> 8) + (target >> 10); + /* Approximately equals target * 0.00585 */ + int err_most = (target >> 8) + (target >> 9); if (i830PipeHasType(crtc, I830_OUTPUT_LVDS)) { if ((INREG(PCH_LVDS) & LVDS_CLKB_POWER_MASK) == LVDS_CLKB_POWER_UP) @@ -2764,6 +2765,8 @@ static void i830_crtc_gamma_set(xf86CrtcPtr crtc, CARD16 *red, CARD16 *green, CARD16 *blue, int size) { + ScrnInfoPtr scrn = crtc->scrn; + intel_screen_private *intel = intel_get_screen_private(scrn); I830CrtcPrivatePtr intel_crtc = crtc->driver_private; int i; @@ -2775,7 +2778,13 @@ i830_crtc_gamma_set(xf86CrtcPtr crtc, CARD16 *red, CARD16 *green, CARD16 *blue, intel_crtc->lut_b[i] = blue[i] >> 8; } - i830_crtc_load_lut(crtc); + /* + * 855 at least really doesn't seem like like you poking its + * pallette registers other than at mode set time. so just disable + * this for now on 8xx. Stops hard machine lockups for me. + */ + if (IS_I9XX(intel)) + i830_crtc_load_lut(crtc); } /** @@ -3186,7 +3195,7 @@ i830_crtc_mode_get(ScrnInfoPtr scrn, xf86CrtcPtr crtc) int vtot = INREG((pipe == 0) ? VTOTAL_A : VTOTAL_B); int vsync = INREG((pipe == 0) ? VSYNC_A : VSYNC_B); - mode = xcalloc(1, sizeof(DisplayModeRec)); + mode = calloc(1, sizeof(DisplayModeRec)); if (mode == NULL) return NULL; diff --git a/src/i830_dri.c b/src/i830_dri.c index d6522649..ab895df7 100644 --- a/src/i830_dri.c +++ b/src/i830_dri.c @@ -44,6 +44,9 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. #include <sys/ioctl.h> #include <unistd.h> #include <fcntl.h> +#include <sys/time.h> +#include <time.h> +#include <errno.h> #include "xf86.h" #include "xf86_OSproc.h" @@ -72,6 +75,7 @@ extern XF86ModuleData dri2ModuleData; #endif typedef struct { + int refcnt; PixmapPtr pixmap; unsigned int attachment; } I830DRI2BufferPrivateRec, *I830DRI2BufferPrivatePtr; @@ -90,12 +94,12 @@ I830DRI2CreateBuffers(DrawablePtr drawable, unsigned int *attachments, I830DRI2BufferPrivatePtr privates; PixmapPtr pixmap, pDepthPixmap; - buffers = xcalloc(count, sizeof *buffers); + buffers = calloc(count, sizeof *buffers); if (buffers == NULL) return NULL; - privates = xcalloc(count, sizeof *privates); + privates = calloc(count, sizeof *privates); if (privates == NULL) { - xfree(buffers); + free(buffers); return NULL; } @@ -125,8 +129,7 @@ I830DRI2CreateBuffers(DrawablePtr drawable, unsigned int *attachments, break; } - if (!intel->tiling || - (!IS_I965G(intel) && !intel->kernel_exec_fencing)) + if (!intel->tiling) hint = 0; pixmap = screen->CreatePixmap(screen, @@ -145,14 +148,14 @@ I830DRI2CreateBuffers(DrawablePtr drawable, unsigned int *attachments, buffers[i].cpp = pixmap->drawable.bitsPerPixel / 8; buffers[i].driverPrivate = &privates[i]; buffers[i].flags = 0; /* not tiled */ + privates[i].refcnt = 1; privates[i].pixmap = pixmap; privates[i].attachment = attachments[i]; bo = i830_get_pixmap_bo(pixmap); - if (dri_bo_flink(bo, &buffers[i].name) != 0) { + if (bo != NULL && dri_bo_flink(bo, &buffers[i].name) != 0) { /* failed to name buffer */ } - } return buffers; @@ -172,12 +175,12 @@ I830DRI2CreateBuffer(DrawablePtr drawable, unsigned int attachment, I830DRI2BufferPrivatePtr privates; PixmapPtr pixmap; - buffer = xcalloc(1, sizeof *buffer); + buffer = calloc(1, sizeof *buffer); if (buffer == NULL) return NULL; - privates = xcalloc(1, sizeof *privates); + privates = calloc(1, sizeof *privates); if (privates == NULL) { - xfree(buffer); + free(buffer); return NULL; } @@ -203,8 +206,7 @@ I830DRI2CreateBuffer(DrawablePtr drawable, unsigned int attachment, break; } - if (!intel->tiling || - (!IS_I965G(intel) && !intel->kernel_exec_fencing)) + if (!intel->tiling) hint = 0; pixmap = screen->CreatePixmap(screen, @@ -213,6 +215,11 @@ I830DRI2CreateBuffer(DrawablePtr drawable, unsigned int attachment, (format != 0) ? format : drawable->depth, hint); + if (pixmap == NULL) { + free(privates); + free(buffer); + return NULL; + } } @@ -222,12 +229,17 @@ I830DRI2CreateBuffer(DrawablePtr drawable, unsigned int attachment, buffer->driverPrivate = privates; buffer->format = format; buffer->flags = 0; /* not tiled */ + privates->refcnt = 1; privates->pixmap = pixmap; privates->attachment = attachment; bo = i830_get_pixmap_bo(pixmap); - if (dri_bo_flink(bo, &buffer->name) != 0) { + if (bo == NULL || dri_bo_flink(bo, &buffer->name) != 0) { /* failed to name buffer */ + screen->DestroyPixmap(pixmap); + free(privates); + free(buffer); + return NULL; } return buffer; @@ -250,8 +262,8 @@ I830DRI2DestroyBuffers(DrawablePtr drawable, DRI2BufferPtr buffers, int count) } if (buffers) { - xfree(buffers[0].driverPrivate); - xfree(buffers); + free(buffers[0].driverPrivate); + free(buffers); } } @@ -261,17 +273,27 @@ static void I830DRI2DestroyBuffer(DrawablePtr drawable, DRI2Buffer2Ptr buffer) { if (buffer) { I830DRI2BufferPrivatePtr private = buffer->driverPrivate; - ScreenPtr screen = drawable->pScreen; + if (--private->refcnt == 0) { + ScreenPtr screen = private->pixmap->drawable.pScreen; - screen->DestroyPixmap(private->pixmap); + screen->DestroyPixmap(private->pixmap); - xfree(private); - xfree(buffer); + free(private); + free(buffer); + } } } #endif +static void I830DRI2ReferenceBuffer(DRI2Buffer2Ptr buffer) +{ + if (buffer) { + I830DRI2BufferPrivatePtr private = buffer->driverPrivate; + private->refcnt++; + } +} + static void I830DRI2CopyRegion(DrawablePtr drawable, RegionPtr pRegion, DRI2BufferPtr destBuffer, DRI2BufferPtr sourceBuffer) @@ -288,7 +310,10 @@ I830DRI2CopyRegion(DrawablePtr drawable, RegionPtr pRegion, RegionPtr pCopyClip; GCPtr gc; - gc = GetScratchGC(drawable->depth, screen); + gc = GetScratchGC(dst->depth, screen); + if (!gc) + return; + pCopyClip = REGION_CREATE(screen, NULL, 0); REGION_COPY(screen, pCopyClip, pRegion); (*gc->funcs->ChangeClip) (gc, CT_REGION, pCopyClip, 0); @@ -375,15 +400,542 @@ I830DRI2CopyRegion(DrawablePtr drawable, RegionPtr pRegion, * later. * * We can't rely on getting into the block handler before the DRI - * client gets to run again so flush now. */ - intel_batch_submit(scrn); -#if ALWAYS_SYNC - intel_sync(scrn); -#endif + * client gets to run again so flush now. + */ + intel_batch_submit(scrn, TRUE); drmCommandNone(intel->drmSubFD, DRM_I915_GEM_THROTTLE); +} + +#if DRI2INFOREC_VERSION >= 4 + +enum DRI2FrameEventType { + DRI2_SWAP, + DRI2_FLIP, + DRI2_WAITMSC, +}; + +typedef struct _DRI2FrameEvent { + XID drawable_id; + ClientPtr client; + enum DRI2FrameEventType type; + int frame; + + /* for swaps & flips only */ + DRI2SwapEventPtr event_complete; + void *event_data; + DRI2BufferPtr front; + DRI2BufferPtr back; +} DRI2FrameEventRec, *DRI2FrameEventPtr; + +static int +I830DRI2DrawablePipe(DrawablePtr pDraw) +{ + ScreenPtr pScreen = pDraw->pScreen; + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + BoxRec box, crtcbox; + xf86CrtcPtr crtc; + int pipe = -1; + + box.x1 = pDraw->x; + box.y1 = pDraw->y; + box.x2 = box.x1 + pDraw->width; + box.y2 = box.y1 + pDraw->height; + + crtc = i830_covering_crtc(pScrn, &box, NULL, &crtcbox); + + /* Make sure the CRTC is valid and this is the real front buffer */ + if (crtc != NULL && !crtc->rotatedData) + pipe = i830_crtc_to_pipe(crtc); + + return pipe; +} + +static void +I830DRI2ExchangeBuffers(DrawablePtr draw, DRI2BufferPtr front, + DRI2BufferPtr back) +{ + I830DRI2BufferPrivatePtr front_priv, back_priv; + struct intel_pixmap *front_intel, *back_intel; + ScreenPtr screen; + intel_screen_private *intel; + int tmp; + + front_priv = front->driverPrivate; + back_priv = back->driverPrivate; + + /* Swap BO names so DRI works */ + tmp = front->name; + front->name = back->name; + back->name = tmp; + + /* Swap pixmap bos */ + front_intel = i830_get_pixmap_intel(front_priv->pixmap); + back_intel = i830_get_pixmap_intel(back_priv->pixmap); + i830_set_pixmap_intel(front_priv->pixmap, back_intel); + i830_set_pixmap_intel(back_priv->pixmap, front_intel); /* should be screen */ + + /* Do we need to update the Screen? */ + screen = draw->pScreen; + intel = intel_get_screen_private(xf86Screens[screen->myNum]); + if (front_intel->bo == intel->front_buffer->bo) { + dri_bo_unreference (intel->front_buffer->bo); + intel->front_buffer->bo = back_intel->bo; + dri_bo_reference (intel->front_buffer->bo); + i830_set_pixmap_intel(screen->GetScreenPixmap(screen), + back_intel); + } +} + +#ifdef notyet +void I830DRI2FrameEventHandler(unsigned int frame, unsigned int tv_sec, + unsigned int tv_usec, void *event_data) +{ + DRI2FrameEventPtr event = event_data; + DrawablePtr drawable; + ScreenPtr screen; + ScrnInfoPtr scrn; + intel_screen_private *intel; + int status; + + status = dixLookupDrawable(&drawable, event->drawable_id, serverClient, + M_ANY, DixWriteAccess); + if (status != Success) { + I830DRI2DestroyBuffer(NULL, event->front); + I830DRI2DestroyBuffer(NULL, event->back); + free(event); + return; + } + + screen = drawable->pScreen; + scrn = xf86Screens[screen->myNum]; + intel = intel_get_screen_private(scrn); + + switch (event->type) { + case DRI2_SWAP: { + int swap_type; + + if (DRI2CanExchange(drawable)) { + I830DRI2ExchangeBuffers(drawable, + event->front, event->back); + swap_type = DRI2_EXCHANGE_COMPLETE; + } else { + BoxRec box; + RegionRec region; + + box.x1 = 0; + box.y1 = 0; + box.x2 = drawable->width; + box.y2 = drawable->height; + REGION_INIT(pScreen, ®ion, &box, 0); + + I830DRI2CopyRegion(drawable, + ®ion, event->front, event->back); + swap_type = DRI2_BLIT_COMPLETE; + } + DRI2SwapComplete(event->client, drawable, frame, tv_sec, tv_usec, + swap_type, + event->event_complete, event->event_data); + break; + } + case DRI2_WAITMSC: + DRI2WaitMSCComplete(event->client, drawable, + frame, tv_sec, tv_usec); + break; + default: + xf86DrvMsg(scrn->scrnIndex, X_WARNING, + "%s: unknown vblank event received\n", __func__); + /* Unknown type */ + break; + } + + I830DRI2DestroyBuffer(drawable, event->front); + I830DRI2DestroyBuffer(drawable, event->back); + free(event); +} + +void I830DRI2FlipEventHandler(unsigned int frame, unsigned int tv_sec, + unsigned int tv_usec, void *event_data) +{ + DRI2FrameEventPtr flip = event_data; + DrawablePtr drawable; + ScreenPtr screen; + ScrnInfoPtr scrn; + int status; + + status = dixLookupDrawable(&drawable, flip->drawable_id, serverClient, + M_ANY, DixWriteAccess); + if (status != Success) { + free(flip); + return; + } + + screen = drawable->pScreen; + scrn = xf86Screens[screen->myNum]; + + /* We assume our flips arrive in order, so we don't check the frame */ + switch (flip->type) { + case DRI2_SWAP: + DRI2SwapComplete(flip->client, drawable, frame, tv_sec, tv_usec, + DRI2_FLIP_COMPLETE, flip->event_complete, + flip->event_data); + break; + default: + xf86DrvMsg(scrn->scrnIndex, X_WARNING, + "%s: unknown vblank event received\n", __func__); + /* Unknown type */ + break; + } + + free(flip); +} + +/* + * ScheduleSwap is responsible for requesting a DRM vblank event for the + * appropriate frame. + * + * In the case of a blit (e.g. for a windowed swap) or buffer exchange, + * the vblank requested can simply be the last queued swap frame + the swap + * interval for the drawable. + * + * In the case of a page flip, we request an event for the last queued swap + * frame + swap interval - 1, since we'll need to queue the flip for the frame + * immediately following the received event. + * + * The client will be blocked if it tries to perform further GL commands + * after queueing a swap, though in the Intel case after queueing a flip, the + * client is free to queue more commands; they'll block in the kernel if + * they access buffers busy with the flip. + * + * When the swap is complete, the driver should call into the server so it + * can send any swap complete events that have been requested. + */ +static int +I830DRI2ScheduleSwap(ClientPtr client, DrawablePtr draw, DRI2BufferPtr front, + DRI2BufferPtr back, CARD64 *target_msc, CARD64 divisor, + CARD64 remainder, DRI2SwapEventPtr func, void *data) +{ + ScreenPtr screen = draw->pScreen; + ScrnInfoPtr scrn = xf86Screens[screen->myNum]; + intel_screen_private *intel = intel_get_screen_private(scrn); + drmVBlank vbl; + int ret, pipe = I830DRI2DrawablePipe(draw), flip = 0; + DRI2FrameEventPtr swap_info; + enum DRI2FrameEventType swap_type = DRI2_SWAP; + CARD64 current_msc; + BoxRec box; + RegionRec region; + + /* Truncate to match kernel interfaces; means occasional overflow + * misses, but that's generally not a big deal */ + *target_msc &= 0xffffffff; + divisor &= 0xffffffff; + remainder &= 0xffffffff; + + swap_info = calloc(1, sizeof(DRI2FrameEventRec)); + + /* Drawable not displayed... just complete the swap */ + if (pipe == -1 || !swap_info) + goto blit_fallback; + + swap_info->drawable_id = draw->id; + swap_info->client = client; + swap_info->event_complete = func; + swap_info->event_data = data; + swap_info->front = front; + swap_info->back = back; + I830DRI2ReferenceBuffer(front); + I830DRI2ReferenceBuffer(back); + + /* Get current count */ + vbl.request.type = DRM_VBLANK_RELATIVE; + if (pipe > 0) + vbl.request.type |= DRM_VBLANK_SECONDARY; + vbl.request.sequence = 0; + ret = drmWaitVBlank(intel->drmSubFD, &vbl); + if (ret) { + xf86DrvMsg(scrn->scrnIndex, X_WARNING, + "first get vblank counter failed: %s\n", + strerror(errno)); + goto blit_fallback; + } + current_msc = vbl.reply.sequence; + + swap_info->type = swap_type; + + /* Correct target_msc by 'flip' if swap_type == DRI2_FLIP. + * Do it early, so handling of different timing constraints + * for divisor, remainder and msc vs. target_msc works. + */ + if (*target_msc > 0) + *target_msc -= flip; + + /* + * If divisor is zero, or current_msc is smaller than target_msc + * we just need to make sure target_msc passes before initiating + * the swap. + */ + if (divisor == 0 || current_msc < *target_msc) { + vbl.request.type = DRM_VBLANK_ABSOLUTE | DRM_VBLANK_EVENT; + if (pipe > 0) + vbl.request.type |= DRM_VBLANK_SECONDARY; + + /* If non-pageflipping, but blitting/exchanging, we need to use + * DRM_VBLANK_NEXTONMISS to avoid unreliable timestamping later + * on. + */ + if (flip == 0) + vbl.request.type |= DRM_VBLANK_NEXTONMISS; + if (pipe > 0) + vbl.request.type |= DRM_VBLANK_SECONDARY; + + /* If target_msc already reached or passed, set it to + * current_msc to ensure we return a reasonable value back + * to the caller. This makes swap_interval logic more robust. + */ + if (current_msc >= *target_msc) + *target_msc = current_msc; + + vbl.request.sequence = *target_msc; + vbl.request.signal = (unsigned long)swap_info; + ret = drmWaitVBlank(intel->drmSubFD, &vbl); + if (ret) { + xf86DrvMsg(scrn->scrnIndex, X_WARNING, + "divisor 0 get vblank counter failed: %s\n", + strerror(errno)); + goto blit_fallback; + } + + *target_msc = vbl.reply.sequence + flip; + swap_info->frame = *target_msc; + + return TRUE; + } + + /* + * If we get here, target_msc has already passed or we don't have one, + * and we need to queue an event that will satisfy the divisor/remainder + * equation. + */ + vbl.request.type = DRM_VBLANK_ABSOLUTE | DRM_VBLANK_EVENT; + if (flip == 0) + vbl.request.type |= DRM_VBLANK_NEXTONMISS; + if (pipe > 0) + vbl.request.type |= DRM_VBLANK_SECONDARY; + + vbl.request.sequence = current_msc - (current_msc % divisor) + + remainder; + + /* + * If the calculated deadline vbl.request.sequence is smaller than + * or equal to current_msc, it means we've passed the last point + * when effective onset frame seq could satisfy + * seq % divisor == remainder, so we need to wait for the next time + * this will happen. + + * This comparison takes the 1 frame swap delay in pageflipping mode + * into account, as well as a potential DRM_VBLANK_NEXTONMISS delay + * if we are blitting/exchanging instead of flipping. + */ + if (vbl.request.sequence <= current_msc) + vbl.request.sequence += divisor; + + /* Account for 1 frame extra pageflip delay if flip > 0 */ + vbl.request.sequence -= flip; + + vbl.request.signal = (unsigned long)swap_info; + ret = drmWaitVBlank(intel->drmSubFD, &vbl); + if (ret) { + xf86DrvMsg(scrn->scrnIndex, X_WARNING, + "final get vblank counter failed: %s\n", + strerror(errno)); + goto blit_fallback; + } + + /* Adjust returned value for 1 fame pageflip offset of flip > 0 */ + *target_msc = vbl.reply.sequence + flip; + swap_info->frame = *target_msc; + + return TRUE; + +blit_fallback: + box.x1 = 0; + box.y1 = 0; + box.x2 = draw->width; + box.y2 = draw->height; + REGION_INIT(pScreen, ®ion, &box, 0); + + I830DRI2CopyRegion(draw, ®ion, front, back); + + DRI2SwapComplete(client, draw, 0, 0, 0, DRI2_BLIT_COMPLETE, func, data); + if (swap_info) { + I830DRI2DestroyBuffer(draw, swap_info->front); + I830DRI2DestroyBuffer(draw, swap_info->back); + free(swap_info); + } + *target_msc = 0; /* offscreen, so zero out target vblank count */ + return TRUE; } +/* + * Get current frame count and frame count timestamp, based on drawable's + * crtc. + */ +static int +I830DRI2GetMSC(DrawablePtr draw, CARD64 *ust, CARD64 *msc) +{ + ScreenPtr screen = draw->pScreen; + ScrnInfoPtr scrn = xf86Screens[screen->myNum]; + intel_screen_private *intel = intel_get_screen_private(scrn); + drmVBlank vbl; + int ret, pipe = I830DRI2DrawablePipe(draw); + + /* Drawable not displayed, make up a value */ + if (pipe == -1) { + *ust = 0; + *msc = 0; + return TRUE; + } + + vbl.request.type = DRM_VBLANK_RELATIVE; + if (pipe > 0) + vbl.request.type |= DRM_VBLANK_SECONDARY; + vbl.request.sequence = 0; + + ret = drmWaitVBlank(intel->drmSubFD, &vbl); + if (ret) { + xf86DrvMsg(scrn->scrnIndex, X_WARNING, + "get vblank counter failed: %s\n", strerror(errno)); + return FALSE; + } + + *ust = ((CARD64)vbl.reply.tval_sec * 1000000) + vbl.reply.tval_usec; + *msc = vbl.reply.sequence; + + return TRUE; +} + +/* + * Request a DRM event when the requested conditions will be satisfied. + * + * We need to handle the event and ask the server to wake up the client when + * we receive it. + */ +static int +I830DRI2ScheduleWaitMSC(ClientPtr client, DrawablePtr draw, CARD64 target_msc, + CARD64 divisor, CARD64 remainder) +{ + ScreenPtr screen = draw->pScreen; + ScrnInfoPtr scrn = xf86Screens[screen->myNum]; + intel_screen_private *intel = intel_get_screen_private(scrn); + DRI2FrameEventPtr wait_info; + drmVBlank vbl; + int ret, pipe = I830DRI2DrawablePipe(draw); + CARD64 current_msc; + + /* Truncate to match kernel interfaces; means occasional overflow + * misses, but that's generally not a big deal */ + target_msc &= 0xffffffff; + divisor &= 0xffffffff; + remainder &= 0xffffffff; + + /* Drawable not visible, return immediately */ + if (pipe == -1) + goto out_complete; + + wait_info = calloc(1, sizeof(DRI2FrameEventRec)); + if (!wait_info) + goto out_complete; + + wait_info->drawable_id = draw->id; + wait_info->client = client; + wait_info->type = DRI2_WAITMSC; + + /* Get current count */ + vbl.request.type = DRM_VBLANK_RELATIVE; + if (pipe > 0) + vbl.request.type |= DRM_VBLANK_SECONDARY; + vbl.request.sequence = 0; + ret = drmWaitVBlank(intel->drmSubFD, &vbl); + if (ret) { + xf86DrvMsg(scrn->scrnIndex, X_WARNING, + "get vblank counter failed: %s\n", strerror(errno)); + goto out_complete; + } + + current_msc = vbl.reply.sequence; + + /* + * If divisor is zero, or current_msc is smaller than target_msc, + * we just need to make sure target_msc passes before waking up the + * client. + */ + if (divisor == 0 || current_msc < target_msc) { + /* If target_msc already reached or passed, set it to + * current_msc to ensure we return a reasonable value back + * to the caller. This keeps the client from continually + * sending us MSC targets from the past by forcibly updating + * their count on this call. + */ + if (current_msc >= target_msc) + target_msc = current_msc; + vbl.request.type = DRM_VBLANK_ABSOLUTE | DRM_VBLANK_EVENT; + if (pipe > 0) + vbl.request.type |= DRM_VBLANK_SECONDARY; + vbl.request.sequence = target_msc; + vbl.request.signal = (unsigned long)wait_info; + ret = drmWaitVBlank(intel->drmSubFD, &vbl); + if (ret) { + xf86DrvMsg(scrn->scrnIndex, X_WARNING, + "get vblank counter failed: %s\n", strerror(errno)); + goto out_complete; + } + + wait_info->frame = vbl.reply.sequence; + DRI2BlockClient(client, draw); + return TRUE; + } + + /* + * If we get here, target_msc has already passed or we don't have one, + * so we queue an event that will satisfy the divisor/remainder equation. + */ + vbl.request.type = DRM_VBLANK_ABSOLUTE | DRM_VBLANK_EVENT; + if (pipe > 0) + vbl.request.type |= DRM_VBLANK_SECONDARY; + + vbl.request.sequence = current_msc - (current_msc % divisor) + + remainder; + + /* + * If calculated remainder is larger than requested remainder, + * it means we've passed the last point where + * seq % divisor == remainder, so we need to wait for the next time + * that will happen. + */ + if ((current_msc % divisor) >= remainder) + vbl.request.sequence += divisor; + + vbl.request.signal = (unsigned long)wait_info; + ret = drmWaitVBlank(intel->drmSubFD, &vbl); + if (ret) { + xf86DrvMsg(scrn->scrnIndex, X_WARNING, + "get vblank counter failed: %s\n", strerror(errno)); + goto out_complete; + } + + wait_info->frame = vbl.reply.sequence; + DRI2BlockClient(client, draw); + + return TRUE; + +out_complete: + DRI2WaitMSCComplete(client, draw, target_msc, 0, 0); + return TRUE; +} +#endif +#endif + Bool I830DRI2ScreenInit(ScreenPtr screen) { ScrnInfoPtr scrn = xf86Screens[screen->myNum]; @@ -393,6 +945,9 @@ Bool I830DRI2ScreenInit(ScreenPtr screen) int dri2_major = 1; int dri2_minor = 0; #endif +#if DRI2INFOREC_VERSION >= 4 + const char *driverNames[1]; +#endif #ifdef USE_DRI2_1_1_0 if (xf86LoaderCheckSymbol("DRI2Version")) { @@ -407,6 +962,7 @@ Bool I830DRI2ScreenInit(ScreenPtr screen) #endif intel->deviceName = drmGetDeviceNameFromFd(intel->drmSubFD); + memset(&info, '\0', sizeof(info)); info.fd = intel->drmSubFD; info.driverName = IS_I965G(intel) ? "i965" : "i915"; info.deviceName = intel->deviceName; @@ -430,6 +986,17 @@ Bool I830DRI2ScreenInit(ScreenPtr screen) #endif info.CopyRegion = I830DRI2CopyRegion; +#if DRI2INFOREC_VERSION >= 4 +#ifdef notyet + info.version = 4; + info.ScheduleSwap = I830DRI2ScheduleSwap; + info.GetMSC = I830DRI2GetMSC; + info.ScheduleWaitMSC = I830DRI2ScheduleWaitMSC; + info.numDrivers = 1; + info.driverNames = driverNames; + driverNames[0] = info.driverName; +#endif +#endif return DRI2ScreenInit(screen, &info); } diff --git a/src/i830_driver.c b/src/i830_driver.c index 1aa7f19e..10c3f38e 100644 --- a/src/i830_driver.c +++ b/src/i830_driver.c @@ -48,6 +48,7 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. #include <stdlib.h> #include <stdio.h> #include <errno.h> +#include <poll.h> #include "xf86.h" #include "xf86_OSproc.h" @@ -254,16 +255,12 @@ static Bool I830GetRec(ScrnInfoPtr scrn) static void I830FreeRec(ScrnInfoPtr scrn) { - intel_screen_private *intel; - if (!scrn) return; if (!scrn->driverPrivate) return; - intel = intel_get_screen_private(scrn); - - xfree(scrn->driverPrivate); + free(scrn->driverPrivate); scrn->driverPrivate = NULL; } @@ -498,10 +495,6 @@ I830MapMem(ScrnInfoPtr scrn) if (err) return FALSE; - if (intel->ring.mem != NULL) { - intel->ring.virtual_start = intel->FbBase + intel->ring.mem->offset; - } - return TRUE; } @@ -988,7 +981,7 @@ static Bool i830_kernel_mode_enabled(ScrnInfoPtr scrn) /* Be nice to the user and load fbcon too */ if (!ret) (void)xf86LoadKernelModule("fbcon"); - xfree(busIdString); + free(busIdString); if (ret) return FALSE; @@ -1258,7 +1251,7 @@ static Bool I830GetEarlyOptions(ScrnInfoPtr scrn) /* Process the options */ xf86CollectOptions(scrn, NULL); - if (!(intel->Options = xalloc(sizeof(I830Options)))) + if (!(intel->Options = malloc(sizeof(I830Options)))) return FALSE; memcpy(intel->Options, I830Options, sizeof(I830Options)); xf86ProcessOptions(scrn->scrnIndex, scrn->options, intel->Options); @@ -1349,6 +1342,25 @@ static void i830_check_dri_option(ScrnInfoPtr scrn) } } +#ifdef notyet +static void +drm_vblank_handler(int fd, unsigned int frame, unsigned int tv_sec, + unsigned int tv_usec, void *event_data) +{ + I830DRI2FrameEventHandler(frame, tv_sec, tv_usec, event_data); +} + +static void +drm_wakeup_handler(pointer data, int err, pointer p) +{ + intel_screen_private *intel = data; + fd_set *read_mask = p; + + if (err >= 0 && FD_ISSET(intel->drmSubFD, read_mask)) + drmHandleEvent(intel->drmSubFD, &intel->event_context); +} +#endif + static Bool i830_user_modesetting_init(ScrnInfoPtr scrn) { intel_screen_private *intel = intel_get_screen_private(scrn); @@ -1383,6 +1395,14 @@ static Bool i830_user_modesetting_init(ScrnInfoPtr scrn) RestoreHWState(scrn); intel->stolen_size = I830DetectMemory(scrn); +#ifdef notyet + intel->event_context.version = DRM_EVENT_CONTEXT_VERSION; + intel->event_context.vblank_handler = drm_vblank_handler; + AddGeneralSocket(intel->drmSubFD); + RegisterBlockAndWakeupHandlers((BlockHandlerProcPtr)NoopDDA, + drm_wakeup_handler, intel); +#endif + return TRUE; } @@ -1405,11 +1425,11 @@ static Bool i830_open_drm_master(ScrnInfoPtr scrn) xf86DrvMsg(scrn->scrnIndex, X_ERROR, "[drm] Failed to open DRM device for %s: %s\n", busid, strerror(errno)); - xfree(busid); + free(busid); return FALSE; } - xfree(busid); + free(busid); /* Check that what we opened was a master or a master-capable FD, * by setting the version of the interface we'll use to talk to it. @@ -1464,8 +1484,6 @@ static Bool I830DrmModeInit(ScrnInfoPtr scrn) return FALSE; } - intel->have_gem = TRUE; - i830_init_bufmgr(scrn); return TRUE; @@ -1537,7 +1555,6 @@ static Bool I830PreInit(ScrnInfoPtr scrn, int flags) intel->SaveGeneration = -1; intel->pEnt = pEnt; intel->use_drm_mode = drm_mode_setting; - intel->kernel_exec_fencing = intel->use_drm_mode; if (!I830LoadSyms(scrn)) return FALSE; @@ -1680,81 +1697,6 @@ static Bool I830PreInit(ScrnInfoPtr scrn, int flags) return TRUE; } -/* - * Reset registers that it doesn't make sense to save/restore to a sane state. - * This is basically the ring buffer and fence registers. Restoring these - * doesn't make sense without restoring GTT mappings. This is something that - * whoever gets control next should do. - */ -static void i830_stop_ring(ScrnInfoPtr scrn, Bool flush) -{ - intel_screen_private *intel = intel_get_screen_private(scrn); - unsigned long temp; - - DPRINTF(PFX, "ResetState: flush is %s\n", BOOLTOSTRING(flush)); - - /* Flush the ring buffer, then disable it. */ - temp = INREG(LP_RING + RING_LEN); - if (temp & RING_VALID) { - i830_refresh_ring(scrn); - i830_wait_ring_idle(scrn); - } - - OUTREG(LP_RING + RING_LEN, 0); - OUTREG(LP_RING + RING_HEAD, 0); - OUTREG(LP_RING + RING_TAIL, 0); - OUTREG(LP_RING + RING_START, 0); -} - -static void i830_start_ring(ScrnInfoPtr scrn) -{ - intel_screen_private *intel = intel_get_screen_private(scrn); - unsigned int itemp; - - DPRINTF(PFX, "SetRingRegs\n"); - - OUTREG(LP_RING + RING_LEN, 0); - OUTREG(LP_RING + RING_TAIL, 0); - OUTREG(LP_RING + RING_HEAD, 0); - - assert((intel->ring.mem->offset & I830_RING_START_MASK) == - intel->ring.mem->offset); - - /* Don't care about the old value. Reserved bits must be zero anyway. */ - itemp = intel->ring.mem->offset; - OUTREG(LP_RING + RING_START, itemp); - - if (((intel->ring.mem->size - 4096) & I830_RING_NR_PAGES) != - intel->ring.mem->size - 4096) { - xf86DrvMsg(scrn->scrnIndex, X_ERROR, - "I830SetRingRegs: Ring buffer size - 4096 (%lx) violates " - "its mask (%x)\n", intel->ring.mem->size - 4096, - I830_RING_NR_PAGES); - } - /* Don't care about the old value. Reserved bits must be zero anyway. */ - itemp = (intel->ring.mem->size - 4096) & I830_RING_NR_PAGES; - itemp |= (RING_NO_REPORT | RING_VALID); - OUTREG(LP_RING + RING_LEN, itemp); - i830_refresh_ring(scrn); -} - -void i830_refresh_ring(ScrnInfoPtr scrn) -{ - intel_screen_private *intel = intel_get_screen_private(scrn); - - /* If we're reaching RefreshRing as a result of grabbing the DRI lock - * before we've set up the ringbuffer, don't bother. - */ - if (intel->ring.mem == NULL) - return; - - intel->ring.head = INREG(LP_RING + RING_HEAD) & I830_HEAD_MASK; - intel->ring.tail = INREG(LP_RING + RING_TAIL); - intel->ring.space = intel->ring.head - (intel->ring.tail + 8); - if (intel->ring.space < 0) - intel->ring.space += intel->ring.mem->size; -} - enum pipe { PIPE_A = 0, PIPE_B, @@ -2226,16 +2168,10 @@ I830BlockHandler(int i, pointer blockData, pointer pTimeout, pointer pReadmask) /* Emit a flush of the rendering cache, or on the 965 and beyond * rendering results may not hit the framebuffer until significantly * later. - * - * XXX Under KMS this is only required because tfp does not have - * the appropriate synchronisation points, so that outstanding updates - * to the pixmap are flushed prior to use as a texture. The framebuffer - * should be handled by the kernel domain management... */ - if (intel->need_mi_flush || !list_is_empty(&intel->flush_pixmaps)) - intel_batch_emit_flush(scrn); - - intel_batch_submit(scrn); + intel_batch_submit(scrn, + intel->need_mi_flush || + !list_is_empty(&intel->flush_pixmaps)); drmCommandNone(intel->drmSubFD, DRM_I915_GEM_THROTTLE); } @@ -2373,24 +2309,16 @@ void i830_init_bufmgr(ScrnInfoPtr scrn) if (intel->bufmgr) return; - if (intel->have_gem) { + batch_size = 4096 * 4; - batch_size = 4096 * 4; + /* The 865 has issues with larger-than-page-sized batch buffers. */ + if (IS_I865G(intel)) + batch_size = 4096; - /* The 865 has issues with larger-than-page-sized batch buffers. */ - if (IS_I865G(intel)) - batch_size = 4096; + intel->bufmgr = intel_bufmgr_gem_init(intel->drmSubFD, batch_size); + intel_bufmgr_gem_enable_reuse(intel->bufmgr); + drm_intel_bufmgr_gem_enable_fenced_relocs(intel->bufmgr); - intel->bufmgr = intel_bufmgr_gem_init(intel->drmSubFD, batch_size); - intel_bufmgr_gem_enable_reuse(intel->bufmgr); - drm_intel_bufmgr_gem_enable_fenced_relocs(intel->bufmgr); - } else { - assert(intel->FbBase != NULL); - intel->bufmgr = intel_bufmgr_fake_init(intel->drmSubFD, - intel->fake_bufmgr_mem->offset, intel->FbBase + - intel->fake_bufmgr_mem->offset, - intel->fake_bufmgr_mem->size, NULL); - } list_init(&intel->batch_pixmaps); list_init(&intel->flush_pixmaps); list_init(&intel->in_flight); @@ -2758,11 +2686,12 @@ I830ScreenInit(int scrnIndex, ScreenPtr screen, int argc, char **argv) return FALSE; } - if (IS_I965G(intel)) + if (IS_I965G(intel)) { intel->batch_flush_notify = i965_batch_flush_notify; - else if (IS_I9XX(intel)) + } else if (IS_I9XX(intel)) { + intel->vertex_flush = i915_vertex_flush; intel->batch_flush_notify = i915_batch_flush_notify; - else + } else intel->batch_flush_notify = i830_batch_flush_notify; miInitializeBackingStore(screen); @@ -2848,7 +2777,7 @@ I830ScreenInit(int scrnIndex, ScreenPtr screen, int argc, char **argv) intel->closing = FALSE; intel->suspended = FALSE; - return TRUE; + return uxa_resources_init(screen); } static void i830AdjustFrame(int scrnIndex, int x, int y, int flags) @@ -2896,26 +2825,25 @@ static void I830LeaveVT(int scrnIndex, int flags) intel->leaving = TRUE; - if (intel->devicesTimer) - TimerFree(intel->devicesTimer); - intel->devicesTimer = NULL; - i830SetHotkeyControl(scrn, HOTKEY_BIOS_SWITCH); xf86RotateFreeShadow(scrn); xf86_hide_cursors(scrn); - intel_sync(scrn); - if (!intel->use_drm_mode) { RestoreHWState(scrn); - /* Evict everything from the bufmgr, as we're about to lose - * ownership of the graphics memory. - */ - if (!intel->have_gem) { - intel_bufmgr_fake_evict_all(intel->bufmgr); - i830_stop_ring(scrn, TRUE); + + /* console restore hack */ + if (IS_IGDNG(intel) && intel->int10 && intel->int10Mode) { + xf86Int10InfoPtr int10 = intel->int10; + + /* Use int10 to restore the console mode */ + int10->num = 0x10; + int10->ax = 0x4f02; + int10->bx = intel->int10Mode | 0x8000; + int10->cx = int10->dx = 0; + xf86ExecX86int10(int10); } /* console restore hack */ @@ -2936,7 +2864,7 @@ static void I830LeaveVT(int scrnIndex, int flags) i830_unbind_all_memory(scrn); - if (intel->have_gem && !intel->use_drm_mode) { + if (!intel->use_drm_mode) { int ret; /* Tell the kernel to evict all buffer objects and block GTT @@ -3017,12 +2945,11 @@ static Bool I830EnterVT(int scrnIndex, int flags) intel->leaving = FALSE; - if (!intel->use_drm_mode) - i830_disable_render_standby(scrn); - - if (intel->have_gem && !intel->use_drm_mode) { + if (!intel->use_drm_mode) { int ret; + i830_disable_render_standby(scrn); + /* Tell the kernel that we're back in control and ready for GTT * usage. */ @@ -3043,11 +2970,6 @@ static Bool I830EnterVT(int scrnIndex, int flags) gen4_render_state_init(scrn); if (!intel->use_drm_mode) { - /* Re-set up the ring. */ - if (!intel->have_gem) { - i830_stop_ring(scrn, FALSE); - i830_start_ring(scrn); - } I830InitHWCursor(scrn); /* Tell the BIOS that we're in control of mode setting now. */ @@ -3099,10 +3021,6 @@ static Bool I830CloseScreen(int scrnIndex, ScreenPtr screen) I830LeaveVT(scrnIndex, 0); } - if (intel->devicesTimer) - TimerFree(intel->devicesTimer); - intel->devicesTimer = NULL; - if (!intel->use_drm_mode) { DPRINTF(PFX, "\nUnmapping memory\n"); I830UnmapMem(scrn); @@ -3111,7 +3029,7 @@ static Bool I830CloseScreen(int scrnIndex, ScreenPtr screen) if (intel->uxa_driver) { uxa_driver_fini(screen); - xfree(intel->uxa_driver); + free(intel->uxa_driver); intel->uxa_driver = NULL; } if (intel->front_buffer) { diff --git a/src/i830_dvo.c b/src/i830_dvo.c index 3deb254b..bccbe7b0 100644 --- a/src/i830_dvo.c +++ b/src/i830_dvo.c @@ -302,7 +302,7 @@ i830_dvo_destroy (xf86OutputPtr output) xf86DestroyI2CBusRec (intel_output->pI2CBus, TRUE, TRUE); if (intel_output->pDDCBus) xf86DestroyI2CBusRec (intel_output->pDDCBus, TRUE, TRUE); - xfree (intel_output); + free (intel_output); } } @@ -407,7 +407,7 @@ i830_dvo_init(ScrnInfoPtr scrn) /* Set up the DDC bus */ ret = I830I2CInit(scrn, &intel_output->pDDCBus, GPIOD, "DVODDC_D"); if (!ret) { - xfree(intel_output); + free(intel_output); return; } @@ -482,7 +482,7 @@ i830_dvo_init(ScrnInfoPtr scrn) if (output == NULL) { xf86DestroyI2CBusRec(pI2CBus, TRUE, TRUE); xf86DestroyI2CBusRec(intel_output->pDDCBus, TRUE, TRUE); - xfree(intel_output); + free(intel_output); xf86UnloadSubModule(drv->modhandle); return; } @@ -517,5 +517,5 @@ i830_dvo_init(ScrnInfoPtr scrn) if (pI2CBus != NULL) xf86DestroyI2CBusRec(pI2CBus, TRUE, TRUE); xf86DestroyI2CBusRec(intel_output->pDDCBus, TRUE, TRUE); - xfree(intel_output); + free(intel_output); } diff --git a/src/i830_hdmi.c b/src/i830_hdmi.c index 3b04b0f5..41b264ec 100644 --- a/src/i830_hdmi.c +++ b/src/i830_hdmi.c @@ -231,7 +231,7 @@ i830_hdmi_detect(xf86OutputPtr output) dev_priv->has_hdmi_sink ? "HDMI" : "DVI", (dev_priv->output_reg == SDVOB) ? 1 : 2); - xfree(edid_mon); + free(edid_mon); return status; } @@ -242,7 +242,7 @@ i830_hdmi_destroy (xf86OutputPtr output) if (intel_output != NULL) { xf86DestroyI2CBusRec(intel_output->pDDCBus, FALSE, FALSE); - xfree(intel_output); + free(intel_output); } } diff --git a/src/i830_hwmc.c b/src/i830_hwmc.c index 850bf876..9aa0af33 100644 --- a/src/i830_hwmc.c +++ b/src/i830_hwmc.c @@ -62,7 +62,7 @@ static int create_context(ScrnInfoPtr scrn, XvMCContextPtr pContext, intel_screen_private *intel = intel_get_screen_private(scrn); struct intel_xvmc_hw_context *contextRec; - *priv = xcalloc(1, sizeof(struct intel_xvmc_hw_context)); + *priv = calloc(1, sizeof(struct intel_xvmc_hw_context)); contextRec = (struct intel_xvmc_hw_context *) *priv; if (!contextRec) { *num_priv = 0; @@ -207,7 +207,7 @@ Bool intel_xvmc_adaptor_init(ScreenPtr pScreen) return FALSE; } - pAdapt = xcalloc(1, sizeof(XF86MCAdaptorRec)); + pAdapt = calloc(1, sizeof(XF86MCAdaptorRec)); if (!pAdapt) { ErrorF("Allocation error.\n"); return FALSE; diff --git a/src/i830_lvds.c b/src/i830_lvds.c index 7af63ffe..651916cf 100644 --- a/src/i830_lvds.c +++ b/src/i830_lvds.c @@ -1084,7 +1084,7 @@ i830_lvds_get_modes(xf86OutputPtr output) if (!output->MonInfo) { - edid_mon = xcalloc (1, sizeof (xf86Monitor)); + edid_mon = calloc (1, sizeof (xf86Monitor)); if (edid_mon) { struct detailed_monitor_section *det_mon = edid_mon->det_mon; @@ -1135,7 +1135,7 @@ i830_lvds_destroy (xf86OutputPtr output) xf86DeleteMode (&intel->lvds_fixed_mode, intel->lvds_fixed_mode); if (intel_output) - xfree (intel_output); + free (intel_output); } #ifdef RANDR_12_INTERFACE diff --git a/src/i830_memory.c b/src/i830_memory.c index 935575dd..0e523b7c 100644 --- a/src/i830_memory.c +++ b/src/i830_memory.c @@ -198,7 +198,7 @@ static Bool i830_bind_memory(ScrnInfoPtr scrn, i830_memory *mem) if (mem == NULL || mem->bound || intel->use_drm_mode) return TRUE; - if (intel->have_gem && mem->bo != NULL) { + if (mem->bo != NULL) { if (dri_bo_pin(mem->bo, mem->alignment) != 0) { xf86DrvMsg(scrn->scrnIndex, X_ERROR, @@ -223,11 +223,6 @@ static Bool i830_bind_memory(ScrnInfoPtr scrn, i830_memory *mem) mem->bound = TRUE; } - if (mem->tiling != TILE_NONE && !intel->kernel_exec_fencing) { - mem->fence_nr = i830_set_tiling(scrn, mem->offset, mem->pitch, - mem->allocated_size, mem->tiling); - } - return TRUE; } @@ -238,10 +233,6 @@ static Bool i830_unbind_memory(ScrnInfoPtr scrn, i830_memory *mem) if (mem == NULL || !mem->bound) return TRUE; - if (mem->tiling != TILE_NONE && !intel->use_drm_mode && - !intel->kernel_exec_fencing) - i830_clear_tiling(scrn, mem->fence_nr); - if (mem->bo != NULL && !intel->use_drm_mode) { if (dri_bo_unpin(mem->bo) == 0) { mem->bound = FALSE; @@ -285,8 +276,8 @@ void i830_free_memory(ScrnInfoPtr scrn, i830_memory * mem) if (mem->next) mem->next->prev = mem->prev; } - xfree(mem->name); - xfree(mem); + free(mem->name); + free(mem); return; } /* Disconnect from the list of allocations */ @@ -300,8 +291,8 @@ void i830_free_memory(ScrnInfoPtr scrn, i830_memory * mem) mem->key = -1; } - xfree(mem->name); - xfree(mem); + free(mem->name); + free(mem); } /* Resets the state of the aperture allocator, freeing all memory that had @@ -341,8 +332,6 @@ void i830_reset_allocations(ScrnInfoPtr scrn) intel->front_buffer = NULL; intel->overlay_regs = NULL; intel->power_context = NULL; - intel->ring.mem = NULL; - intel->fake_bufmgr_mem = NULL; } /** @@ -360,25 +349,25 @@ Bool i830_allocator_init(ScrnInfoPtr scrn, unsigned long size) i830_memory *start, *end; struct drm_i915_setparam sp; - start = xcalloc(1, sizeof(*start)); + start = calloc(1, sizeof(*start)); if (start == NULL) return FALSE; start->name = xstrdup("start marker"); if (start->name == NULL) { - xfree(start); + free(start); return FALSE; } - end = xcalloc(1, sizeof(*end)); + end = calloc(1, sizeof(*end)); if (end == NULL) { - xfree(start->name); - xfree(start); + free(start->name); + free(start); return FALSE; } end->name = xstrdup("end marker"); if (end->name == NULL) { - xfree(start->name); - xfree(start); - xfree(end); + free(start->name); + free(start); + free(end); return FALSE; } @@ -442,8 +431,8 @@ Bool i830_allocator_init(ScrnInfoPtr scrn, unsigned long size) ret = drmCommandWrite(intel->drmSubFD, DRM_I915_SETPARAM, &sp, sizeof(sp)); - if (ret == 0) - intel->kernel_exec_fencing = TRUE; + if (ret != 0) + ErrorF("no kernel exec fencing, wtf?"); init.gtt_start = intel->memory_manager->offset; init.gtt_end = intel->memory_manager->offset + intel->memory_manager->size; @@ -451,15 +440,14 @@ Bool i830_allocator_init(ScrnInfoPtr scrn, unsigned long size) /* Tell the kernel to manage it */ ret = ioctl(intel->drmSubFD, DRM_IOCTL_I915_GEM_INIT, &init); - if (ret == 0) { - intel->have_gem = TRUE; - i830_init_bufmgr(scrn); - } else { + if (ret != 0) { xf86DrvMsg(scrn->scrnIndex, X_ERROR, "Failed to initialize kernel memory manager\n"); i830_free_memory(scrn, intel->memory_manager); intel->memory_manager = NULL; + return FALSE; } + i830_init_bufmgr(scrn); } else { xf86DrvMsg(scrn->scrnIndex, X_ERROR, "Failed to allocate space for kernel memory manager\n"); @@ -473,8 +461,8 @@ void i830_allocator_fini(ScrnInfoPtr scrn) { intel_screen_private *intel = intel_get_screen_private(scrn); - /* The memory manager is more special */ if - (intel->memory_manager) { + /* The memory manager is more special */ + if (intel->memory_manager) { i830_free_memory(scrn, intel->memory_manager); intel->memory_manager = NULL; } @@ -576,7 +564,7 @@ i830_allocate_aperture(ScrnInfoPtr scrn, const char *name, unsigned long size, intel_screen_private *intel = intel_get_screen_private(scrn); i830_memory *mem, *scan; - mem = xcalloc(1, sizeof(*mem)); + mem = calloc(1, sizeof(*mem)); if (mem == NULL) return NULL; @@ -585,7 +573,7 @@ i830_allocate_aperture(ScrnInfoPtr scrn, const char *name, unsigned long size, mem->name = xstrdup(name); if (mem->name == NULL) { - xfree(mem); + free(mem); return NULL; } /* Only allocate page-sized increments. */ @@ -636,8 +624,8 @@ i830_allocate_aperture(ScrnInfoPtr scrn, const char *name, unsigned long size, } if (scan->next == NULL) { /* Reached the end of the list, and didn't find space */ - xfree(mem->name); - xfree(mem); + free(mem->name); + free(mem); return NULL; } /* Insert new allocation into the list */ @@ -709,21 +697,21 @@ static i830_memory *i830_allocate_memory_bo(ScrnInfoPtr scrn, const char *name, size = ALIGN(size, GTT_PAGE_SIZE); align = i830_get_fence_alignment(intel, size); - mem = xcalloc(1, sizeof(*mem)); + mem = calloc(1, sizeof(*mem)); if (mem == NULL) return NULL; mem->name = xstrdup(name); if (mem->name == NULL) { - xfree(mem); + free(mem); return NULL; } mem->bo = dri_bo_alloc(intel->bufmgr, name, size, align); if (!mem->bo) { - xfree(mem->name); - xfree(mem); + free(mem->name); + free(mem); return NULL; } @@ -767,8 +755,8 @@ static i830_memory *i830_allocate_memory_bo(ScrnInfoPtr scrn, const char *name, if (scrn->vtSema || intel->use_drm_mode) { if (!i830_bind_memory(scrn, mem)) { dri_bo_unreference (mem->bo); - xfree(mem->name); - xfree(mem); + free(mem->name); + free(mem); return NULL; } } @@ -838,7 +826,7 @@ i830_memory *i830_allocate_memory(ScrnInfoPtr scrn, const char *name, * kernel. Under UMS, we separately reserve space for * a few objects (overlays, power context, cursors, etc). */ - if (intel->have_gem && (intel->use_drm_mode || + if ((intel->use_drm_mode || !(flags & (NEED_PHYSICAL_ADDR|NEED_LIFETIME_FIXED)))) { return i830_allocate_memory_bo(scrn, name, size, pitch, alignment, flags, tile_format); @@ -943,31 +931,6 @@ i830_describe_allocations(ScrnInfoPtr scrn, int verbosity, const char *prefix) } } -static Bool i830_allocate_ringbuffer(ScrnInfoPtr scrn) -{ - intel_screen_private *intel = intel_get_screen_private(scrn); - - if (intel->have_gem || intel->ring.mem != NULL) - return TRUE; - - /* We don't have any mechanism in the DRM yet to alert it that we've - * moved the ringbuffer since init time, so allocate it fixed for its - * lifetime. - */ - intel->ring.mem = i830_allocate_memory(scrn, "ring buffer", - PRIMARY_RINGBUFFER_SIZE, PITCH_NONE, GTT_PAGE_SIZE, - NEED_LIFETIME_FIXED, TILE_NONE); - if (intel->ring.mem == NULL) { - xf86DrvMsg(scrn->scrnIndex, X_ERROR, - "Failed to allocate Ring Buffer space\n"); - return FALSE; - } - - intel->ring.tail_mask = intel->ring.mem->size - 1; - intel->ring.virtual_start = intel->FbBase + intel->ring.mem->offset; - return TRUE; -} - /** * Allocate space for overlay registers. */ @@ -1247,10 +1210,6 @@ Bool i830_allocate_2d_memory(ScrnInfoPtr scrn) "\tthe agpgart module loaded.\n"); return FALSE; } - - /* Allocate the ring buffer first, so it ends up in stolen mem. */ - if (!i830_allocate_ringbuffer(scrn)) - return FALSE; } if (intel->fb_compression) @@ -1263,18 +1222,6 @@ Bool i830_allocate_2d_memory(ScrnInfoPtr scrn) return FALSE; } - if (!intel->have_gem) { - intel->fake_bufmgr_mem = i830_allocate_memory(scrn, - "fake bufmgr", MB(8), PITCH_NONE, GTT_PAGE_SIZE, 0, - TILE_NONE); - if (intel->fake_bufmgr_mem == NULL) { - xf86DrvMsg(scrn->scrnIndex, X_WARNING, - "Failed to allocate fake bufmgr space.\n"); - return FALSE; - } - i830_init_bufmgr(scrn); - } - if (!intel->use_drm_mode) i830_allocate_overlay(scrn); @@ -1680,53 +1627,55 @@ void i830_free_xvmc_buffer(ScrnInfoPtr scrn, i830_memory * buffer) #endif -static void i830_set_max_gtt_map_size(ScrnInfoPtr scrn) +static void i830_set_max_bo_size(intel_screen_private *intel, + const struct drm_i915_gem_get_aperture *aperture) { - intel_screen_private *intel = intel_get_screen_private(scrn); - struct drm_i915_gem_get_aperture aperture; - int ret; - - /* Default low value in case it gets used during server init. */ - intel->max_gtt_map_size = 16 * 1024 * 1024; - - if (!intel->have_gem) - return; + if (aperture->aper_available_size) + /* Large BOs will tend to hit SW fallbacks frequently, and also will + * tend to fail to successfully map when doing SW fallbacks because we + * overcommit address space for BO access, or worse cause aperture + * thrashing. + */ + intel->max_bo_size = aperture->aper_available_size / 2; + else + intel->max_bo_size = 64 * 1024 * 1024; +} - ret = - ioctl(intel->drmSubFD, DRM_IOCTL_I915_GEM_GET_APERTURE, &aperture); - if (ret == 0) { - /* Let objects up get bound up to the size where only 2 would - * fit in the aperture, but then leave slop to account for - * alignment like libdrm does. +static void i830_set_max_gtt_map_size(intel_screen_private *intel, + const struct drm_i915_gem_get_aperture *aperture) +{ + if (aperture->aper_available_size) + /* Let objects up get bound up to the size where only 2 would fit in + * the aperture, but then leave slop to account for alignment like + * libdrm does. */ intel->max_gtt_map_size = - aperture.aper_available_size * 3 / 4 / 2; - } + aperture->aper_available_size * 3 / 4 / 2; + else + intel->max_gtt_map_size = 16 * 1024 * 1024; } -static void i830_set_max_tiling_size(ScrnInfoPtr scrn) +static void i830_set_max_tiling_size(intel_screen_private *intel, + const struct drm_i915_gem_get_aperture *aperture) { - intel_screen_private *intel = intel_get_screen_private(scrn); - struct drm_i915_gem_get_aperture aperture; - int ret; - - /* Default low value in case it gets used during server init. */ - intel->max_tiling_size = 4 * 1024 * 1024; - - ret = - ioctl(intel->drmSubFD, DRM_IOCTL_I915_GEM_GET_APERTURE, &aperture); - if (ret == 0) { + if (aperture->aper_available_size) /* Let objects be tiled up to the size where only 4 would fit in * the aperture, presuming worst case alignment. */ - intel->max_tiling_size = aperture.aper_available_size / 4; - if (!IS_I965G(intel)) - intel->max_tiling_size /= 2; - } + intel->max_tiling_size = aperture->aper_available_size / 4; + else + intel->max_tiling_size = 4 * 1024 * 1024; } void i830_set_gem_max_sizes(ScrnInfoPtr scrn) { - i830_set_max_gtt_map_size(scrn); - i830_set_max_tiling_size(scrn); + intel_screen_private *intel = intel_get_screen_private(scrn); + struct drm_i915_gem_get_aperture aperture; + + aperture.aper_available_size = 0; + ioctl(intel->drmSubFD, DRM_IOCTL_I915_GEM_GET_APERTURE, &aperture); + + i830_set_max_bo_size(intel, &aperture); + i830_set_max_gtt_map_size(intel, &aperture); + i830_set_max_tiling_size(intel, &aperture); } diff --git a/src/i830_quirks.c b/src/i830_quirks.c index 1d9b681c..28585693 100644 --- a/src/i830_quirks.c +++ b/src/i830_quirks.c @@ -73,7 +73,7 @@ static void i830_dmi_store_##field(void) \ int ret;\ f = fopen(DMIID_FILE(field), "r");\ if (f == NULL) {\ - xfree(i830_dmi_data[field]); i830_dmi_data[field] = NULL;\ + free(i830_dmi_data[field]); i830_dmi_data[field] = NULL;\ return;\ }\ ret = fread(i830_dmi_data[field], 64, 1, f); \ @@ -104,11 +104,11 @@ static void i830_dmi_scan(void) int i; for (i = 0; i < dmi_data_max; i++) { - i830_dmi_data[i] = xcalloc(64, sizeof(char)); + i830_dmi_data[i] = calloc(64, sizeof(char)); if (!i830_dmi_data[i]) { int j; for (j = 0; j < i; j++) { - xfree(i830_dmi_data[j]); + free(i830_dmi_data[j]); i830_dmi_data[i] = NULL; } return; @@ -426,5 +426,5 @@ void i830_fixup_devices(ScrnInfoPtr scrn) for (i = 0; i < dmi_data_max; i++) if (i830_dmi_data[i]) - xfree(i830_dmi_data[i]); + free(i830_dmi_data[i]); } diff --git a/src/i830_render.c b/src/i830_render.c index da075d93..43f4e28b 100644 --- a/src/i830_render.c +++ b/src/i830_render.c @@ -126,19 +126,18 @@ static struct blendinfo i830_blend_op[] = { {0, 0, BLENDFACTOR_ONE, BLENDFACTOR_ONE}, }; -/* The x8* formats could use MT_32BIT_X* on 855+, but since we implement - * workarounds for 830/845 anyway, we just rely on those whether the hardware - * could handle it for us or not. - */ static struct formatinfo i830_tex_formats[] = { - {PICT_a8r8g8b8, MT_32BIT_ARGB8888}, - {PICT_x8r8g8b8, MT_32BIT_ARGB8888}, - {PICT_a8b8g8r8, MT_32BIT_ABGR8888}, - {PICT_x8b8g8r8, MT_32BIT_ABGR8888}, - {PICT_r5g6b5, MT_16BIT_RGB565}, - {PICT_a1r5g5b5, MT_16BIT_ARGB1555}, - {PICT_x1r5g5b5, MT_16BIT_ARGB1555}, - {PICT_a8, MT_8BIT_A8}, + {PICT_a8, MAPSURF_8BIT | MT_8BIT_A8}, + {PICT_a8r8g8b8, MAPSURF_32BIT | MT_32BIT_ARGB8888}, + {PICT_a8b8g8r8, MAPSURF_32BIT | MT_32BIT_ABGR8888}, + {PICT_r5g6b5, MAPSURF_16BIT | MT_16BIT_RGB565}, + {PICT_a1r5g5b5, MAPSURF_16BIT | MT_16BIT_ARGB1555}, + {PICT_a4r4g4b4, MAPSURF_16BIT | MT_16BIT_ARGB4444}, +}; + +static struct formatinfo i855_tex_formats[] = { + {PICT_x8r8g8b8, MAPSURF_32BIT | MT_32BIT_XRGB8888}, + {PICT_x8b8g8r8, MAPSURF_32BIT | MT_32BIT_XBGR8888}, }; static Bool i830_get_dest_format(PicturePtr dest_picture, uint32_t * dst_format) @@ -221,61 +220,26 @@ static Bool i830_get_blend_cntl(ScrnInfoPtr scrn, int op, PicturePtr mask, return TRUE; } -static Bool i830_check_composite_texture(ScrnInfoPtr scrn, PicturePtr picture, - int unit) +static uint32_t i8xx_get_card_format(intel_screen_private *intel, + PicturePtr picture) { - if (picture->repeatType > RepeatReflect) { - intel_debug_fallback(scrn, "Unsupported picture repeat %d\n", - picture->repeatType); - return FALSE; - } + int i; - if (picture->filter != PictFilterNearest && - picture->filter != PictFilterBilinear) { - intel_debug_fallback(scrn, "Unsupported filter 0x%x\n", - picture->filter); - return FALSE; + for (i = 0; i < sizeof(i830_tex_formats) / sizeof(i830_tex_formats[0]); + i++) { + if (i830_tex_formats[i].fmt == picture->format) + return i830_tex_formats[i].card_fmt; } - if (picture->pDrawable) { - int w, h, i; - - w = picture->pDrawable->width; - h = picture->pDrawable->height; - if ((w > 2048) || (h > 2048)) { - intel_debug_fallback(scrn, - "Picture w/h too large (%dx%d)\n", - w, h); - return FALSE; - } - - for (i = 0; - i < sizeof(i830_tex_formats) / sizeof(i830_tex_formats[0]); + if (IS_I85X(intel) || IS_I865G(intel)) { + for (i = 0; i < sizeof(i855_tex_formats) / sizeof(i855_tex_formats[0]); i++) { - if (i830_tex_formats[i].fmt == picture->format) - break; - } - if (i == sizeof(i830_tex_formats) / sizeof(i830_tex_formats[0])) - { - intel_debug_fallback(scrn, "Unsupported picture format " - "0x%x\n", - (int)picture->format); - return FALSE; + if (i855_tex_formats[i].fmt == picture->format) + return i855_tex_formats[i].card_fmt; } } - return TRUE; -} - -static uint32_t i8xx_get_card_format(PicturePtr picture) -{ - int i; - for (i = 0; i < sizeof(i830_tex_formats) / sizeof(i830_tex_formats[0]); - i++) { - if (i830_tex_formats[i].fmt == picture->format) - return i830_tex_formats[i].card_fmt; - } - FatalError("Unsupported format type %d\n", picture->format); + return 0; } static void i830_texture_setup(PicturePtr picture, PixmapPtr pixmap, int unit) @@ -297,8 +261,6 @@ static void i830_texture_setup(PicturePtr picture, PixmapPtr pixmap, int unit) else texcoordtype = TEXCOORDTYPE_HOMOGENEOUS; - format = i8xx_get_card_format(picture); - switch (picture->repeatType) { case RepeatNone: wrap_mode = TEXCOORDMODE_CLAMP_BORDER; @@ -331,63 +293,59 @@ static void i830_texture_setup(PicturePtr picture, PixmapPtr pixmap, int unit) } filter |= (MIPFILTER_NONE << TM0S3_MIP_FILTER_SHIFT); - { - if (pixmap->drawable.bitsPerPixel == 8) - format |= MAPSURF_8BIT; - else if (pixmap->drawable.bitsPerPixel == 16) - format |= MAPSURF_16BIT; - else - format |= MAPSURF_32BIT; - - if (i830_pixmap_tiled(pixmap)) { - tiling_bits = TM0S1_TILED_SURFACE; - if (i830_get_pixmap_intel(pixmap)->tiling - == I915_TILING_Y) - tiling_bits |= TM0S1_TILE_WALK; - } else - tiling_bits = 0; - - ATOMIC_BATCH(10); - OUT_BATCH(_3DSTATE_LOAD_STATE_IMMEDIATE_2 | - LOAD_TEXTURE_MAP(unit) | 4); - OUT_RELOC_PIXMAP(pixmap, I915_GEM_DOMAIN_SAMPLER, 0, 0); - OUT_BATCH(((pixmap->drawable.height - - 1) << TM0S1_HEIGHT_SHIFT) | ((pixmap->drawable.width - - 1) << - TM0S1_WIDTH_SHIFT) | - format | tiling_bits); - OUT_BATCH((pitch / 4 - 1) << TM0S2_PITCH_SHIFT | TM0S2_MAP_2D); - OUT_BATCH(filter); - OUT_BATCH(0); /* default color */ - OUT_BATCH(_3DSTATE_MAP_COORD_SET_CMD | TEXCOORD_SET(unit) | - ENABLE_TEXCOORD_PARAMS | TEXCOORDS_ARE_NORMAL | - texcoordtype | ENABLE_ADDR_V_CNTL | - TEXCOORD_ADDR_V_MODE(wrap_mode) | - ENABLE_ADDR_U_CNTL | TEXCOORD_ADDR_U_MODE(wrap_mode)); - /* map texel stream */ - OUT_BATCH(_3DSTATE_MAP_COORD_SETBIND_CMD); - if (unit == 0) - OUT_BATCH(TEXBIND_SET0(TEXCOORDSRC_VTXSET_0) | - TEXBIND_SET1(TEXCOORDSRC_KEEP) | - TEXBIND_SET2(TEXCOORDSRC_KEEP) | - TEXBIND_SET3(TEXCOORDSRC_KEEP)); - else - OUT_BATCH(TEXBIND_SET0(TEXCOORDSRC_VTXSET_0) | - TEXBIND_SET1(TEXCOORDSRC_VTXSET_1) | - TEXBIND_SET2(TEXCOORDSRC_KEEP) | - TEXBIND_SET3(TEXCOORDSRC_KEEP)); - OUT_BATCH(_3DSTATE_MAP_TEX_STREAM_CMD | (unit << 16) | - DISABLE_TEX_STREAM_BUMP | - ENABLE_TEX_STREAM_COORD_SET | - TEX_STREAM_COORD_SET(unit) | - ENABLE_TEX_STREAM_MAP_IDX | TEX_STREAM_MAP_IDX(unit)); - ADVANCE_BATCH(); - } + if (i830_pixmap_tiled(pixmap)) { + tiling_bits = TM0S1_TILED_SURFACE; + if (i830_get_pixmap_intel(pixmap)->tiling + == I915_TILING_Y) + tiling_bits |= TM0S1_TILE_WALK; + } else + tiling_bits = 0; + + format = i8xx_get_card_format(intel, picture); + + assert(intel->in_batch_atomic); + + OUT_BATCH(_3DSTATE_LOAD_STATE_IMMEDIATE_2 | + LOAD_TEXTURE_MAP(unit) | 4); + OUT_RELOC_PIXMAP(pixmap, I915_GEM_DOMAIN_SAMPLER, 0, 0); + OUT_BATCH(((pixmap->drawable.height - + 1) << TM0S1_HEIGHT_SHIFT) | ((pixmap->drawable.width - + 1) << + TM0S1_WIDTH_SHIFT) | + format | tiling_bits); + OUT_BATCH((pitch / 4 - 1) << TM0S2_PITCH_SHIFT | TM0S2_MAP_2D); + OUT_BATCH(filter); + OUT_BATCH(0); /* default color */ + OUT_BATCH(_3DSTATE_MAP_COORD_SET_CMD | TEXCOORD_SET(unit) | + ENABLE_TEXCOORD_PARAMS | TEXCOORDS_ARE_NORMAL | + texcoordtype | ENABLE_ADDR_V_CNTL | + TEXCOORD_ADDR_V_MODE(wrap_mode) | + ENABLE_ADDR_U_CNTL | TEXCOORD_ADDR_U_MODE(wrap_mode)); + /* map texel stream */ + OUT_BATCH(_3DSTATE_MAP_COORD_SETBIND_CMD); + if (unit == 0) + OUT_BATCH(TEXBIND_SET0(TEXCOORDSRC_VTXSET_0) | + TEXBIND_SET1(TEXCOORDSRC_KEEP) | + TEXBIND_SET2(TEXCOORDSRC_KEEP) | + TEXBIND_SET3(TEXCOORDSRC_KEEP)); + else + OUT_BATCH(TEXBIND_SET0(TEXCOORDSRC_VTXSET_0) | + TEXBIND_SET1(TEXCOORDSRC_VTXSET_1) | + TEXBIND_SET2(TEXCOORDSRC_KEEP) | + TEXBIND_SET3(TEXCOORDSRC_KEEP)); + OUT_BATCH(_3DSTATE_MAP_TEX_STREAM_CMD | (unit << 16) | + DISABLE_TEX_STREAM_BUMP | + ENABLE_TEX_STREAM_COORD_SET | + TEX_STREAM_COORD_SET(unit) | + ENABLE_TEX_STREAM_MAP_IDX | TEX_STREAM_MAP_IDX(unit)); } Bool -i830_check_composite(int op, PicturePtr source_picture, PicturePtr mask_picture, - PicturePtr dest_picture) +i830_check_composite(int op, + PicturePtr source_picture, + PicturePtr mask_picture, + PicturePtr dest_picture, + int width, int height) { ScrnInfoPtr scrn = xf86Screens[dest_picture->pDrawable->pScreen->myNum]; uint32_t tmp1; @@ -414,25 +372,77 @@ i830_check_composite(int op, PicturePtr source_picture, PicturePtr mask_picture, } } - if (!i830_check_composite_texture(scrn, source_picture, 0)) { - intel_debug_fallback(scrn, "Check Src picture texture\n"); + if (!i830_get_dest_format(dest_picture, &tmp1)) { + intel_debug_fallback(scrn, "Get Color buffer format\n"); return FALSE; } - if (mask_picture != NULL - && !i830_check_composite_texture(scrn, mask_picture, 1)) { - intel_debug_fallback(scrn, "Check Mask picture texture\n"); + + if (width > 2048 || height > 2048) { + intel_debug_fallback(scrn, "Operation is too large (%d, %d)\n", width, height); return FALSE; } - if (!i830_get_dest_format(dest_picture, &tmp1)) { - intel_debug_fallback(scrn, "Get Color buffer format\n"); + return TRUE; +} + +Bool +i830_check_composite_target(PixmapPtr pixmap) +{ + if (pixmap->drawable.width > 2048 || pixmap->drawable.height > 2048) + return FALSE; + + if(!intel_check_pitch_3d(pixmap)) return FALSE; - } return TRUE; } Bool +i830_check_composite_texture(ScreenPtr screen, PicturePtr picture) +{ + ScrnInfoPtr scrn = xf86Screens[screen->myNum]; + intel_screen_private *intel = intel_get_screen_private(scrn); + + if (picture->repeatType > RepeatReflect) { + intel_debug_fallback(scrn, "Unsupported picture repeat %d\n", + picture->repeatType); + return FALSE; + } + + if (picture->filter != PictFilterNearest && + picture->filter != PictFilterBilinear) { + intel_debug_fallback(scrn, "Unsupported filter 0x%x\n", + picture->filter); + return FALSE; + } + + if (picture->pDrawable) { + int w, h; + + w = picture->pDrawable->width; + h = picture->pDrawable->height; + if ((w > 2048) || (h > 2048)) { + intel_debug_fallback(scrn, + "Picture w/h too large (%dx%d)\n", + w, h); + return FALSE; + } + + /* XXX we can use the xrgb32 types if there the picture covers the clip */ + if (!i8xx_get_card_format(intel, picture)) { + intel_debug_fallback(scrn, "Unsupported picture format " + "0x%x\n", + (int)picture->format); + return FALSE; + } + + return TRUE; + } + + return FALSE; +} + +Bool i830_prepare_composite(int op, PicturePtr source_picture, PicturePtr mask_picture, PicturePtr dest_picture, PixmapPtr source, PixmapPtr mask, PixmapPtr dest) @@ -456,6 +466,20 @@ i830_prepare_composite(int op, PicturePtr source_picture, if (!intel_check_pitch_3d(source)) return FALSE; if (mask) { + if (mask_picture->componentAlpha && + PICT_FORMAT_RGB(mask_picture->format)) { + /* Check if it's component alpha that relies on a source alpha and on + * the source value. We can only get one of those into the single + * source value that we get to blend with. + */ + if (i830_blend_op[op].src_alpha && + (i830_blend_op[op].src_blend != BLENDFACTOR_ZERO)) { + intel_debug_fallback(scrn, "Component alpha not " + "supported with source alpha and " + "source value blending.\n"); + return FALSE; + } + } if (!intel_check_pitch_3d(mask)) return FALSE; } @@ -560,7 +584,7 @@ static void i830_emit_composite_state(ScrnInfoPtr scrn) IntelEmitInvarientState(scrn); intel->last_3d = LAST_3D_RENDER; - ATOMIC_BATCH(21); + assert(intel->in_batch_atomic); if (i830_pixmap_tiled(intel->render_dest)) { tiling_bits = BUF_3D_TILED_SURFACE; @@ -626,8 +650,6 @@ static void i830_emit_composite_state(ScrnInfoPtr scrn) } OUT_BATCH(_3DSTATE_VERTEX_FORMAT_2_CMD | texcoordfmt); - ADVANCE_BATCH(); - i830_texture_setup(intel->render_source_picture, intel->render_source, 0); if (intel->render_mask) { i830_texture_setup(intel->render_mask_picture, @@ -767,8 +789,6 @@ i830_emit_composite_primitive(PixmapPtr dest, num_floats = 3 * per_vertex; - ATOMIC_BATCH(1 + num_floats); - OUT_BATCH(PRIM3D_INLINE | PRIM3D_RECTLIST | (num_floats - 1)); OUT_BATCH_F(dstX + w); OUT_BATCH_F(dstY + h); @@ -814,8 +834,6 @@ i830_emit_composite_primitive(PixmapPtr dest, OUT_BATCH_F(mask_w[0]); } } - - ADVANCE_BATCH(); } /** diff --git a/src/i830_sdvo.c b/src/i830_sdvo.c index 393804ea..a9275afa 100644 --- a/src/i830_sdvo.c +++ b/src/i830_sdvo.c @@ -1723,7 +1723,7 @@ i830_sdvo_output_setup (xf86OutputPtr output, uint16_t flag) } /* if exist origin name it will be freed in xf86OutputRename() */ - dev_priv->name = xalloc(strlen(name_prefix) + strlen(name_suffix) + 1); + dev_priv->name = malloc(strlen(name_prefix) + strlen(name_suffix) + 1); strcpy (dev_priv->name, name_prefix); strcat (dev_priv->name, name_suffix); @@ -1740,11 +1740,11 @@ i830_sdvo_output_setup (xf86OutputPtr output, uint16_t flag) if (output->randr_output) { int nameLength = strlen(dev_priv->name); RROutputPtr randr_output = output->randr_output; - char *name = xalloc(nameLength + 1); + char *name = malloc(nameLength + 1); if (name) { if (randr_output->name != (char *) (randr_output + 1)) - xfree(randr_output->name); + free(randr_output->name); randr_output->name = name; randr_output->nameLength = nameLength; memcpy(randr_output->name, dev_priv->name, nameLength); @@ -1825,10 +1825,10 @@ i830_sdvo_detect(xf86OutputPtr output) /* Check EDID in DVI-I case */ edid_mon = xf86OutputGetEDID (output, intel_output->pDDCBus); if (edid_mon && !DIGITAL(edid_mon->features.input_type)) { - xfree(edid_mon); + free(edid_mon); return XF86OutputStatusDisconnected; } - xfree(edid_mon); + free(edid_mon); } return XF86OutputStatusConnected; } @@ -1898,7 +1898,7 @@ i830_sdvo_get_tv_mode(DisplayModePtr *head, int width, int height, { DisplayModePtr mode; - mode = xcalloc(1, sizeof(*mode)); + mode = calloc(1, sizeof(*mode)); if (mode == NULL) return; @@ -2020,14 +2020,14 @@ i830_sdvo_destroy (xf86OutputPtr output) RROutputPtr randr_output = output->randr_output; if (randr_output->name && randr_output->name != (char *) (randr_output + 1)) - xfree(randr_output->name); + free(randr_output->name); } if (dev_priv->sdvo_lvds_fixed_mode) xf86DeleteMode(&dev_priv->sdvo_lvds_fixed_mode, dev_priv->sdvo_lvds_fixed_mode); - xfree (intel_output); + free (intel_output); } } diff --git a/src/i830_tv.c b/src/i830_tv.c index 8f37f3c8..71fd7df2 100644 --- a/src/i830_tv.c +++ b/src/i830_tv.c @@ -1570,7 +1570,7 @@ static void i830_tv_destroy (xf86OutputPtr output) { if (output->driver_private) - xfree (output->driver_private); + free (output->driver_private); } #ifdef RANDR_12_INTERFACE @@ -1807,16 +1807,16 @@ i830_tv_set_property(xf86OutputPtr output, Atom property, memcpy (&atom, value->data, 4); name = NameForAtom (atom); - val = xalloc (strlen (name) + 1); + val = malloc (strlen (name) + 1); if (!val) return FALSE; strcpy (val, name); if (!i830_tv_mode_lookup (val)) { - xfree (val); + free (val); return FALSE; } - xfree (dev_priv->tv_format); + free (dev_priv->tv_format); dev_priv->tv_format = val; if (intel->starting || output->crtc == NULL) diff --git a/src/i830_uxa.c b/src/i830_uxa.c index 78237046..03a01372 100644 --- a/src/i830_uxa.c +++ b/src/i830_uxa.c @@ -36,6 +36,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include "i830.h" #include "i810_reg.h" #include "i915_drm.h" +#include "brw_defines.h" #include <string.h> #include <sys/mman.h> #include <errno.h> @@ -78,7 +79,31 @@ const int I830PatternROP[16] = { ROP_1 }; -static int uxa_pixmap_index; +#if HAS_DEVPRIVATEKEYREC +DevPrivateKeyRec uxa_pixmap_index; +#else +int uxa_pixmap_index; +#endif + +static void +ironlake_blt_workaround(ScrnInfoPtr scrn) +{ + intel_screen_private *intel = intel_get_screen_private(scrn); + + /* Ironlake has a limitation that a 3D or Media command can't + * be the first command after a BLT, unless it's + * non-pipelined. Instead of trying to track it and emit a + * command at the right time, we just emit a dummy + * non-pipelined 3D instruction after each blit. + */ + + if (IS_IGDNG(intel)) { + BEGIN_BATCH(2); + OUT_BATCH(CMD_POLY_STIPPLE_OFFSET << 16); + OUT_BATCH(0); + ADVANCE_BATCH(); + } +} Bool i830_get_aperture_space(ScrnInfoPtr scrn, drm_intel_bo ** bo_table, @@ -93,7 +118,7 @@ i830_get_aperture_space(ScrnInfoPtr scrn, drm_intel_bo ** bo_table, bo_table[0] = intel->batch_bo; if (drm_intel_bufmgr_check_aperture_space(bo_table, num_bos) != 0) { - intel_batch_submit(scrn); + intel_batch_submit(scrn, FALSE); bo_table[0] = intel->batch_bo; if (drm_intel_bufmgr_check_aperture_space(bo_table, num_bos) != 0) { @@ -127,14 +152,13 @@ i830_uxa_pixmap_compute_size(PixmapPtr pixmap, { ScrnInfoPtr scrn = xf86Screens[pixmap->drawable.pScreen->myNum]; intel_screen_private *intel = intel_get_screen_private(scrn); - int pitch, pitch_align; - int size; + int pitch, size; if (*tiling != I915_TILING_NONE) { /* First check whether tiling is necessary. */ - pitch_align = intel->accel_pixmap_pitch_alignment; - size = ROUND_TO((w * pixmap->drawable.bitsPerPixel + 7) / 8, - pitch_align) * ALIGN (h, 2); + pitch = (w * pixmap->drawable.bitsPerPixel + 7) / 8; + pitch = ROUND_TO(pitch, intel->accel_pixmap_pitch_alignment); + size = pitch * ALIGN (h, 2); if (!IS_I965G(intel)) { /* Older hardware requires fences to be pot size * aligned with a minimum of 1 MiB, so causes @@ -142,6 +166,12 @@ i830_uxa_pixmap_compute_size(PixmapPtr pixmap, */ if (size < 1024*1024/2) *tiling = I915_TILING_NONE; + + /* Gen 2/3 has a maximum stride for tiling of + * 8192 bytes. + */ + if (pitch > KB(8)) + *tiling = I915_TILING_NONE; } else if (size <= 4096) { /* Disable tiling beneath a page size, we will not see * any benefit from reducing TLB misses and instead @@ -154,29 +184,19 @@ i830_uxa_pixmap_compute_size(PixmapPtr pixmap, pitch = (w * pixmap->drawable.bitsPerPixel + 7) / 8; if (pitch <= 256) *tiling = I915_TILING_NONE; - repeat: - if (*tiling == I915_TILING_NONE) { - pitch_align = intel->accel_pixmap_pitch_alignment; - } else { - pitch_align = 512; - } - *stride = ROUND_TO(pitch, pitch_align); + if (*tiling != I915_TILING_NONE) { + int aligned_h; - if (*tiling == I915_TILING_NONE) { - /* Round the height up so that the GPU's access to a 2x2 aligned - * subspan doesn't address an invalid page offset beyond the - * end of the GTT. - */ - size = *stride * ALIGN(h, 2); - } else { - int aligned_h = h; if (*tiling == I915_TILING_X) aligned_h = ALIGN(h, 8); else aligned_h = ALIGN(h, 32); - *stride = i830_get_fence_pitch(intel, *stride, *tiling); + *stride = i830_get_fence_pitch(intel, + ROUND_TO(pitch, 512), + *tiling); + /* Round the object up to the size of the fence it will live in * if necessary. We could potentially make the kernel allocate * a larger aperture space and just bind the subset of pages in, @@ -184,17 +204,45 @@ i830_uxa_pixmap_compute_size(PixmapPtr pixmap, * with drm_intel_bufmgr_check_aperture(). */ size = i830_get_fence_size(intel, *stride * aligned_h); - assert(size >= *stride * aligned_h); + + if (size > intel->max_tiling_size) + *tiling = I915_TILING_NONE; } - if (*tiling != I915_TILING_NONE && size > intel->max_tiling_size) { - *tiling = I915_TILING_NONE; - goto repeat; + if (*tiling == I915_TILING_NONE) { + /* Round the height up so that the GPU's access to a 2x2 aligned + * subspan doesn't address an invalid page offset beyond the + * end of the GTT. + */ + *stride = ROUND_TO(pitch, intel->accel_pixmap_pitch_alignment); + size = *stride * ALIGN(h, 2); } return size; } +static Bool +i830_uxa_check_solid(DrawablePtr drawable, int alu, Pixel planemask) +{ + ScrnInfoPtr scrn = xf86Screens[drawable->pScreen->myNum]; + + if (!UXA_PM_IS_SOLID(drawable, planemask)) { + intel_debug_fallback(scrn, "planemask is not solid\n"); + return FALSE; + } + + switch (drawable->bitsPerPixel) { + case 8: + case 16: + case 32: + break; + default: + return FALSE; + } + + return TRUE; +} + /** * Sets up hardware state for a series of solid fills. */ @@ -203,32 +251,14 @@ i830_uxa_prepare_solid(PixmapPtr pixmap, int alu, Pixel planemask, Pixel fg) { ScrnInfoPtr scrn = xf86Screens[pixmap->drawable.pScreen->myNum]; intel_screen_private *intel = intel_get_screen_private(scrn); - unsigned long pitch; drm_intel_bo *bo_table[] = { NULL, /* batch_bo */ i830_get_pixmap_bo(pixmap), }; - if (!UXA_PM_IS_SOLID(&pixmap->drawable, planemask)) { - intel_debug_fallback(scrn, "planemask is not solid\n"); - return FALSE; - } - - if (pixmap->drawable.bitsPerPixel == 24) { - intel_debug_fallback(scrn, "solid 24bpp unsupported!\n"); - return FALSE; - } - - if (pixmap->drawable.bitsPerPixel < 8) { - intel_debug_fallback(scrn, "under 8bpp pixmaps unsupported\n"); - return FALSE; - } - if (!intel_check_pitch_2d(pixmap)) return FALSE; - pitch = i830_pixmap_pitch(pixmap); - if (!i830_pixmap_pitch_is_aligned(pixmap)) { intel_debug_fallback(scrn, "pixmap pitch not aligned"); return FALSE; @@ -248,11 +278,10 @@ i830_uxa_prepare_solid(PixmapPtr pixmap, int alu, Pixel planemask, Pixel fg) case 32: /* RGB8888 */ intel->BR[13] |= ((1 << 24) | (1 << 25)); - if (pixmap->drawable.depth == 24) - fg |= 0xff000000; break; } intel->BR[16] = fg; + return TRUE; } @@ -272,6 +301,9 @@ static void i830_uxa_solid(PixmapPtr pixmap, int x1, int y1, int x2, int y2) if (y2 > pixmap->drawable.height) y2 = pixmap->drawable.height; + if (x2 <= x1 || y2 <= y1) + return; + pitch = i830_pixmap_pitch(pixmap); { @@ -299,6 +331,8 @@ static void i830_uxa_solid(PixmapPtr pixmap, int x1, int y1, int x2, int y2) OUT_BATCH(intel->BR[16]); ADVANCE_BATCH(); } + + ironlake_blt_workaround(scrn); } static void i830_uxa_done_solid(PixmapPtr pixmap) @@ -313,39 +347,57 @@ static void i830_uxa_done_solid(PixmapPtr pixmap) * - support planemask using FULL_BLT_CMD? */ static Bool -i830_uxa_prepare_copy(PixmapPtr source, PixmapPtr dest, int xdir, - int ydir, int alu, Pixel planemask) +i830_uxa_check_copy(PixmapPtr source, PixmapPtr dest, + int alu, Pixel planemask) { ScrnInfoPtr scrn = xf86Screens[dest->drawable.pScreen->myNum]; intel_screen_private *intel = intel_get_screen_private(scrn); - drm_intel_bo *bo_table[] = { - NULL, /* batch_bo */ - i830_get_pixmap_bo(source), - i830_get_pixmap_bo(dest), - }; + if (!UXA_PM_IS_SOLID(&source->drawable, planemask)) { intel_debug_fallback(scrn, "planemask is not solid"); return FALSE; } - if (dest->drawable.bitsPerPixel < 8) { - intel_debug_fallback(scrn, "under 8bpp pixmaps unsupported\n"); + if (source->drawable.bitsPerPixel != dest->drawable.bitsPerPixel) { + intel_debug_fallback(scrn, "mixed bpp copies unsupported\n"); return FALSE; } - - if (!i830_get_aperture_space(scrn, bo_table, ARRAY_SIZE(bo_table))) + switch (source->drawable.bitsPerPixel) { + case 8: + case 16: + case 32: + break; + default: return FALSE; + } if (!intel_check_pitch_2d(source)) return FALSE; if (!intel_check_pitch_2d(dest)) return FALSE; + return TRUE; +} + +static Bool +i830_uxa_prepare_copy(PixmapPtr source, PixmapPtr dest, int xdir, + int ydir, int alu, Pixel planemask) +{ + ScrnInfoPtr scrn = xf86Screens[dest->drawable.pScreen->myNum]; + intel_screen_private *intel = intel_get_screen_private(scrn); + drm_intel_bo *bo_table[] = { + NULL, /* batch_bo */ + i830_get_pixmap_bo(source), + i830_get_pixmap_bo(dest), + }; + + if (!i830_get_aperture_space(scrn, bo_table, ARRAY_SIZE(bo_table))) + return FALSE; + intel->render_source = source; intel->BR[13] = I830CopyROP[alu] << 16; - switch (source->drawable.bitsPerPixel) { case 8: break; @@ -356,6 +408,7 @@ i830_uxa_prepare_copy(PixmapPtr source, PixmapPtr dest, int xdir, intel->BR[13] |= ((1 << 25) | (1 << 24)); break; } + return TRUE; } @@ -416,6 +469,7 @@ i830_uxa_copy(PixmapPtr dest, int src_x1, int src_y1, int dst_x1, ADVANCE_BATCH(); } + ironlake_blt_workaround(scrn); } static void i830_uxa_done_copy(PixmapPtr dest) @@ -433,6 +487,10 @@ static void i830_uxa_done_copy(PixmapPtr dest) void i830_done_composite(PixmapPtr dest) { ScrnInfoPtr scrn = xf86Screens[dest->drawable.pScreen->myNum]; + intel_screen_private *intel = intel_get_screen_private(scrn); + + if (intel->vertex_flush) + intel->vertex_flush(intel); i830_debug_flush(scrn); } @@ -518,16 +576,6 @@ Bool i830_transform_is_affine(PictTransformPtr t) return t->matrix[2][0] == 0 && t->matrix[2][1] == 0; } -struct intel_pixmap *i830_get_pixmap_intel(PixmapPtr pixmap) -{ - return dixLookupPrivate(&pixmap->devPrivates, &uxa_pixmap_index); -} - -static void i830_uxa_set_pixmap_intel(PixmapPtr pixmap, struct intel_pixmap *intel) -{ - dixSetPrivate(&pixmap->devPrivates, &uxa_pixmap_index, intel); -} - dri_bo *i830_get_pixmap_bo(PixmapPtr pixmap) { struct intel_pixmap *intel; @@ -547,21 +595,35 @@ void i830_set_pixmap_bo(PixmapPtr pixmap, dri_bo * bo) priv = i830_get_pixmap_intel(pixmap); + if (priv == NULL && bo == NULL) + return; + if (priv != NULL) { + if (priv->bo == bo) + return; + if (list_is_empty(&priv->batch)) { dri_bo_unreference(priv->bo); + } else if (!drm_intel_bo_is_reusable(priv->bo)) { + dri_bo_unreference(priv->bo); + list_del(&priv->batch); + list_del(&priv->flush); } else { list_add(&priv->in_flight, &intel->in_flight); priv = NULL; } + + if (intel->render_current_dest == pixmap) + intel->render_current_dest = NULL; } if (bo != NULL) { + uint32_t tiling; uint32_t swizzle_mode; int ret; if (priv == NULL) { - priv = xcalloc(1, sizeof (struct intel_pixmap)); + priv = calloc(1, sizeof (struct intel_pixmap)); if (priv == NULL) goto BAIL; @@ -574,21 +636,24 @@ void i830_set_pixmap_bo(PixmapPtr pixmap, dri_bo * bo) priv->stride = i830_pixmap_pitch(pixmap); ret = drm_intel_bo_get_tiling(bo, - &priv->tiling, + &tiling, &swizzle_mode); if (ret != 0) { FatalError("Couldn't get tiling on bo %p: %s\n", bo, strerror(-ret)); } + + priv->tiling = tiling; + priv->busy = -1; } else { if (priv != NULL) { - xfree(priv); + free(priv); priv = NULL; } } BAIL: - i830_uxa_set_pixmap_intel(pixmap, priv); + i830_set_pixmap_intel(pixmap, priv); } static Bool i830_uxa_prepare_access(PixmapPtr pixmap, uxa_access_t access) @@ -600,40 +665,30 @@ static Bool i830_uxa_prepare_access(PixmapPtr pixmap, uxa_access_t access) int ret; if (!list_is_empty(&priv->batch) && - (access == UXA_ACCESS_RW || priv->batch_write_domain)) - intel_batch_submit(scrn); - - if (bo) { - if (intel->kernel_exec_fencing) { - if (bo->size > intel->max_gtt_map_size || !intel->have_gem) { - ret = dri_bo_map(bo, access == UXA_ACCESS_RW); - if (ret != 0) { - xf86DrvMsg(scrn->scrnIndex, X_WARNING, - "%s: bo map failed: %s\n", - __FUNCTION__, - strerror(-ret)); - return FALSE; - } - } else { - ret = drm_intel_gem_bo_map_gtt(bo); - if (ret != 0) { - xf86DrvMsg(scrn->scrnIndex, X_WARNING, - "%s: gtt bo map failed: %s\n", - __FUNCTION__, - strerror(-ret)); - return FALSE; - } - } - pixmap->devPrivate.ptr = bo->virtual; - } else { - if (drm_intel_bo_pin(bo, 4096) != 0) - return FALSE; - drm_intel_gem_bo_start_gtt_access(bo, access == - UXA_ACCESS_RW); - pixmap->devPrivate.ptr = intel->FbBase + bo->offset; + (access == UXA_ACCESS_RW || priv->batch_write)) + intel_batch_submit(scrn, FALSE); + + if (bo->size > intel->max_gtt_map_size) { + ret = dri_bo_map(bo, access == UXA_ACCESS_RW); + if (ret != 0) { + xf86DrvMsg(scrn->scrnIndex, X_WARNING, + "%s: bo map failed: %s\n", + __FUNCTION__, + strerror(-ret)); + return FALSE; + } + } else { + ret = drm_intel_gem_bo_map_gtt(bo); + if (ret != 0) { + xf86DrvMsg(scrn->scrnIndex, X_WARNING, + "%s: gtt bo map failed: %s\n", + __FUNCTION__, + strerror(-ret)); + return FALSE; } - } else - i830_wait_ring_idle(scrn); + } + pixmap->devPrivate.ptr = bo->virtual; + priv->busy = 0; return TRUE; } @@ -648,206 +703,207 @@ static void i830_uxa_finish_access(PixmapPtr pixmap) if (bo == intel->front_buffer->bo) intel->need_flush = TRUE; - if (intel->kernel_exec_fencing) { - if (bo->size > intel->max_gtt_map_size) - dri_bo_unmap(bo); - else - drm_intel_gem_bo_unmap_gtt(bo); - pixmap->devPrivate.ptr = NULL; - } + if (bo->size > intel->max_gtt_map_size) + dri_bo_unmap(bo); + else + drm_intel_gem_bo_unmap_gtt(bo); + pixmap->devPrivate.ptr = NULL; } -static Bool i830_bo_put_image(PixmapPtr pixmap, dri_bo *bo, char *src, int src_pitch, int w, int h) +static Bool i830_uxa_pixmap_put_image(PixmapPtr pixmap, + char *src, int src_pitch, + int x, int y, int w, int h) { + struct intel_pixmap *priv = i830_get_pixmap_intel(pixmap); int stride = i830_pixmap_pitch(pixmap); - - /* fill alpha channel */ - if (pixmap->drawable.depth == 24) { - pixman_image_t *src_image, *dst_image; - - src_image = pixman_image_create_bits (PIXMAN_x8r8g8b8, - w, h, - (uint32_t *) src, src_pitch); - - dst_image = pixman_image_create_bits (PIXMAN_a8r8g8b8, - w, h, - (uint32_t *) bo->virtual, stride); - - if (src_image && dst_image) - pixman_image_composite (PictOpSrc, - src_image, NULL, dst_image, - 0, 0, - 0, 0, - 0, 0, - w, h); - - if (src_image) - pixman_image_unref (src_image); - - if (dst_image) - pixman_image_unref (dst_image); - - if (src_image == NULL || dst_image == NULL) - return FALSE; - } else if (src_pitch == stride) { - memcpy (bo->virtual, src, stride * h); - } else { - char *dst = bo->virtual; - int row_length = w * pixmap->drawable.bitsPerPixel/8; + int ret = FALSE; + + if (src_pitch == stride && w == pixmap->drawable.width && priv->tiling == I915_TILING_NONE) { + ret = drm_intel_bo_subdata(priv->bo, y * stride, stride * h, src) == 0; + } else if (drm_intel_gem_bo_map_gtt(priv->bo) == 0) { + char *dst = priv->bo->virtual; + int cpp = pixmap->drawable.bitsPerPixel/8; + int row_length = w * cpp; int num_rows = h; - while (num_rows--) { + if (row_length == src_pitch && src_pitch == stride) + num_rows = 1, row_length *= h; + dst += y * stride + x * cpp; + do { memcpy (dst, src, row_length); src += src_pitch; dst += stride; - } + } while (--num_rows); + drm_intel_gem_bo_unmap_gtt(priv->bo); + ret = TRUE; } - return TRUE; + return ret; } -static Bool -i830_uxa_pixmap_swap_bo_with_image(PixmapPtr pixmap, - char *src, int src_pitch) +static Bool i830_uxa_put_image(PixmapPtr pixmap, + int x, int y, + int w, int h, + char *src, int src_pitch) { - ScrnInfoPtr scrn = xf86Screens[pixmap->drawable.pScreen->myNum]; - intel_screen_private *intel = intel_get_screen_private(scrn); struct intel_pixmap *priv; - dri_bo *bo; - uint32_t tiling = I915_TILING_X; - int stride; - int w = pixmap->drawable.width; - int h = pixmap->drawable.height; - Bool ret; priv = i830_get_pixmap_intel(pixmap); + if (!intel_pixmap_is_busy(priv)) { + /* bo is not busy so can be replaced without a stall, upload in-place. */ + return i830_uxa_pixmap_put_image(pixmap, src, src_pitch, x, y, w, h); + } else { + ScreenPtr screen = pixmap->drawable.pScreen; + + if (x == 0 && y == 0 && + w == pixmap->drawable.width && + h == pixmap->drawable.height) + { + intel_screen_private *intel = intel_get_screen_private(xf86Screens[screen->myNum]); + uint32_t tiling = priv->tiling; + int size, stride; + dri_bo *bo; + + /* Replace busy bo. */ + size = i830_uxa_pixmap_compute_size (pixmap, w, h, + &tiling, &stride); + if (size > intel->max_gtt_map_size) + return FALSE; - if (priv->batch_read_domains || drm_intel_bo_busy(priv->bo)) { - unsigned int size; + bo = drm_intel_bo_alloc(intel->bufmgr, "pixmap", size, 0); + if (bo == NULL) + return FALSE; - size = i830_uxa_pixmap_compute_size (pixmap, w, h, - &tiling, &stride); - if (size > intel->max_gtt_map_size) - return FALSE; + if (tiling != I915_TILING_NONE) + drm_intel_bo_set_tiling(bo, &tiling, stride); - bo = drm_intel_bo_alloc(intel->bufmgr, "pixmap", size, 0); - if (bo == NULL) - return FALSE; + screen->ModifyPixmapHeader(pixmap, + w, h, + 0, 0, + stride, NULL); + i830_set_pixmap_bo(pixmap, bo); + dri_bo_unreference(bo); - if (tiling != I915_TILING_NONE) - drm_intel_bo_set_tiling(bo, &tiling, stride); + return i830_uxa_pixmap_put_image(pixmap, src, src_pitch, 0, 0, w, h); + } + else + { + PixmapPtr scratch; + Bool ret; + + /* Upload to a linear buffer and queue a blit. */ + scratch = (*screen->CreatePixmap)(screen, w, h, + pixmap->drawable.depth, + UXA_CREATE_PIXMAP_FOR_MAP); + if (!scratch) + return FALSE; - dri_bo_unreference(priv->bo); - priv->bo = bo; - priv->tiling = tiling; - priv->batch_read_domains = priv->batch_write_domain = 0; - priv->flush_read_domains = priv->flush_write_domain = 0; - list_del(&priv->batch); - list_del(&priv->flush); - pixmap->drawable.pScreen->ModifyPixmapHeader(pixmap, - w, h, - 0, 0, - stride, NULL); - } else { - bo = priv->bo; - stride = i830_pixmap_pitch(pixmap); - } + ret = i830_uxa_pixmap_put_image(scratch, src, src_pitch, 0, 0, w, h); + if (ret) { + GCPtr gc = GetScratchGC(pixmap->drawable.depth, screen); + if (gc) { + ValidateGC(&pixmap->drawable, gc); - if (drm_intel_gem_bo_map_gtt(bo)) { - xf86DrvMsg(scrn->scrnIndex, X_WARNING, - "%s: bo map failed\n", __FUNCTION__); - return FALSE; + (*gc->ops->CopyArea)(&scratch->drawable, + &pixmap->drawable, + gc, 0, 0, w, h, x, y); + + FreeScratchGC(gc); + } else + ret = FALSE; + } + + (*screen->DestroyPixmap)(scratch); + return ret; + } } +} - ret = i830_bo_put_image(pixmap, bo, src, src_pitch, w, h); +static Bool i830_uxa_pixmap_get_image(PixmapPtr pixmap, + int x, int y, int w, int h, + char *dst, int dst_pitch) +{ + struct intel_pixmap *priv = i830_get_pixmap_intel(pixmap); + int stride = i830_pixmap_pitch(pixmap); - drm_intel_gem_bo_unmap_gtt(bo); + if (dst_pitch == stride && w == pixmap->drawable.width) { + return drm_intel_bo_get_subdata(priv->bo, y * stride, stride * h, dst) == 0; + } else { + char *src; + int cpp; - return ret; + if (drm_intel_bo_map(priv->bo, FALSE)) + return FALSE; + + cpp = pixmap->drawable.bitsPerPixel/8; + src = (char *) priv->bo->virtual + y * stride + x * cpp; + w *= cpp; + do { + memcpy(dst, src, w); + src += stride; + dst += dst_pitch; + } while (--h); + + drm_intel_bo_unmap(priv->bo); + + return TRUE; + } } -static Bool i830_uxa_put_image(PixmapPtr pixmap, +static Bool i830_uxa_get_image(PixmapPtr pixmap, int x, int y, int w, int h, - char *src, int src_pitch) + char *dst, int dst_pitch) { - ScreenPtr screen = pixmap->drawable.pScreen; - ScrnInfoPtr scrn = xf86Screens[screen->myNum]; - PixmapPtr scratch; struct intel_pixmap *priv; - GCPtr gc; + PixmapPtr scratch = NULL; Bool ret; - if (x == 0 && y == 0 && - w == pixmap->drawable.width && - h == pixmap->drawable.height) - { - /* Replace GPU hot bo with new CPU data. */ - return i830_uxa_pixmap_swap_bo_with_image(pixmap, - src, src_pitch); - } + /* The presumption is that we wish to keep the target hot, so + * copy to a new bo and move that to the CPU in preference to + * causing ping-pong of the original. + * + * Also the gpu is much faster at detiling. + */ priv = i830_get_pixmap_intel(pixmap); - if (priv->batch_read_domains || - drm_intel_bo_busy(priv->bo) || - pixmap->drawable.depth == 24) { - dri_bo *bo; - - /* Partial replacement, copy incoming image to a bo and blit. */ - scratch = (*screen->CreatePixmap)(screen, w, h, - pixmap->drawable.depth, - UXA_CREATE_PIXMAP_FOR_MAP); + if (intel_pixmap_is_busy(priv) || priv->tiling != I915_TILING_NONE) { + ScreenPtr screen = pixmap->drawable.pScreen; + GCPtr gc; + + /* Copy to a linear buffer and pull. */ + scratch = screen->CreatePixmap(screen, w, h, + pixmap->drawable.depth, + INTEL_CREATE_PIXMAP_TILING_NONE); if (!scratch) return FALSE; - bo = i830_get_pixmap_bo(scratch); - if (drm_intel_gem_bo_map_gtt(bo)) { - (*screen->DestroyPixmap) (scratch); - xf86DrvMsg(scrn->scrnIndex, X_WARNING, - "%s: bo map failed\n", __FUNCTION__); + gc = GetScratchGC(pixmap->drawable.depth, screen); + if (!gc) { + screen->DestroyPixmap(scratch); return FALSE; } - ret = i830_bo_put_image(scratch, bo, src, src_pitch, w, h); + ValidateGC(&pixmap->drawable, gc); - drm_intel_gem_bo_unmap_gtt(bo); - - if (ret) { - gc = GetScratchGC(pixmap->drawable.depth, screen); - if (gc) { - ValidateGC(&pixmap->drawable, gc); + gc->ops->CopyArea(&pixmap->drawable, + &scratch->drawable, + gc, x, y, w, h, 0, 0); - (*gc->ops->CopyArea)(&scratch->drawable, - &pixmap->drawable, - gc, 0, 0, w, h, x, y); + FreeScratchGC(gc); - FreeScratchGC(gc); - } else - ret = FALSE; - } + intel_batch_submit(xf86Screens[screen->myNum], FALSE); - (*screen->DestroyPixmap)(scratch); - } else { - /* bo is not busy so can be mapped without a stall, upload in-place. */ - if (drm_intel_gem_bo_map_gtt(priv->bo)) { - xf86DrvMsg(scrn->scrnIndex, X_WARNING, - "%s: bo map failed\n", __FUNCTION__); - return FALSE; - } + x = y = 0; + pixmap = scratch; + } - pixman_blt((uint32_t *)src, priv->bo->virtual, - src_pitch / sizeof(uint32_t), - pixmap->devKind / sizeof(uint32_t), - pixmap->drawable.bitsPerPixel, - pixmap->drawable.bitsPerPixel, - 0, 0, - x, y, - w, h); + ret = i830_uxa_pixmap_get_image(pixmap, x, y, w, h, dst, dst_pitch); - drm_intel_gem_bo_unmap_gtt(priv->bo); - ret = TRUE; - } + if (scratch) + scratch->drawable.pScreen->DestroyPixmap(scratch); return ret; + } void i830_uxa_block_handler(ScreenPtr screen) @@ -883,6 +939,9 @@ i830_uxa_create_pixmap(ScreenPtr screen, int w, int h, int depth, if (w > 32767 || h > 32767) return NullPixmap; + if (depth == 1) + return fbCreatePixmap(screen, w, h, depth, usage); + if (usage == CREATE_PIXMAP_USAGE_GLYPH_PICTURE && w <= 32 && h <= 32) return fbCreatePixmap(screen, w, h, depth, usage); @@ -900,7 +959,7 @@ i830_uxa_create_pixmap(ScreenPtr screen, int w, int h, int depth, tiling = I915_TILING_X; if (usage == INTEL_CREATE_PIXMAP_TILING_Y) tiling = I915_TILING_Y; - if (usage == UXA_CREATE_PIXMAP_FOR_MAP) + if (usage == UXA_CREATE_PIXMAP_FOR_MAP || usage == INTEL_CREATE_PIXMAP_TILING_NONE) tiling = I915_TILING_NONE; if (tiling != I915_TILING_NONE) { @@ -911,21 +970,16 @@ i830_uxa_create_pixmap(ScreenPtr screen, int w, int h, int depth, } size = i830_uxa_pixmap_compute_size(pixmap, w, h, &tiling, &stride); - /* Fail very large allocations on 32-bit systems. Large BOs will - * tend to hit SW fallbacks frequently, and also will tend to fail - * to successfully map when doing SW fallbacks because we overcommit - * address space for BO access. - * - * Note that size should fit in 32 bits. We throw out >32767x32767x4, - * and pitch alignment could get us up to 32768x32767x4. + /* Fail very large allocations. Large BOs will tend to hit SW fallbacks + * frequently, and also will tend to fail to successfully map when doing + * SW fallbacks because we overcommit address space for BO access. */ - if (sizeof(unsigned long) == 4 && - size > (unsigned int)(1024 * 1024 * 1024)) { + if (size > intel->max_bo_size || stride >= KB(32)) { fbDestroyPixmap(pixmap); - return NullPixmap; + return fbCreatePixmap(screen, w, h, depth, usage); } - /* Perform a premilinary search for an in-flight bo */ + /* Perform a preliminary search for an in-flight bo */ if (usage != UXA_CREATE_PIXMAP_FOR_MAP) { int aligned_h; @@ -939,50 +993,63 @@ i830_uxa_create_pixmap(ScreenPtr screen, int w, int h, int depth, list_foreach_entry(priv, struct intel_pixmap, &intel->in_flight, in_flight) { - if (priv->tiling == tiling && - priv->stride >= stride && - priv->bo->size >= priv->stride * aligned_h) { - list_del(&priv->in_flight); - screen->ModifyPixmapHeader(pixmap, w, h, 0, 0, priv->stride, NULL); - i830_uxa_set_pixmap_intel(pixmap, priv); - return pixmap; + if (priv->tiling != tiling) + continue; + + if (tiling == I915_TILING_NONE) { + if (priv->bo->size < size) + continue; + + priv->stride = stride; + } else { + if (priv->stride < stride || + priv->bo->size < priv->stride * aligned_h) + continue; + + stride = priv->stride; } + + list_del(&priv->in_flight); + screen->ModifyPixmapHeader(pixmap, w, h, 0, 0, stride, NULL); + i830_set_pixmap_intel(pixmap, priv); + return pixmap; } } - priv = xcalloc(1, sizeof (struct intel_pixmap)); + priv = calloc(1, sizeof (struct intel_pixmap)); if (priv == NULL) { fbDestroyPixmap(pixmap); return NullPixmap; } - if (usage == UXA_CREATE_PIXMAP_FOR_MAP) + if (usage == UXA_CREATE_PIXMAP_FOR_MAP) { + priv->busy = 0; priv->bo = drm_intel_bo_alloc(intel->bufmgr, "pixmap", size, 0); - else + } else { + priv->busy = -1; priv->bo = drm_intel_bo_alloc_for_render(intel->bufmgr, "pixmap", size, 0); + } if (!priv->bo) { - xfree(priv); + free(priv); fbDestroyPixmap(pixmap); if (errno == EFBIG) return fbCreatePixmap(screen, w, h, depth, usage); return NullPixmap; } + if (tiling != I915_TILING_NONE) + drm_intel_bo_set_tiling(priv->bo, &tiling, stride); priv->stride = stride; priv->tiling = tiling; - if (priv->tiling != I915_TILING_NONE) - drm_intel_bo_set_tiling(priv->bo, - &priv->tiling, - stride); screen->ModifyPixmapHeader(pixmap, w, h, 0, 0, stride, NULL); list_init(&priv->batch); list_init(&priv->flush); - i830_uxa_set_pixmap_intel(pixmap, priv); + i830_set_pixmap_intel(pixmap, priv); } return pixmap; @@ -1006,6 +1073,7 @@ void i830_uxa_create_screen_resources(ScreenPtr screen) if (bo != NULL) { PixmapPtr pixmap = screen->GetScreenPixmap(screen); i830_set_pixmap_bo(pixmap, bo); + i830_get_pixmap_intel(pixmap)->busy = 1; } } @@ -1014,7 +1082,11 @@ Bool i830_uxa_init(ScreenPtr screen) ScrnInfoPtr scrn = xf86Screens[screen->myNum]; intel_screen_private *intel = intel_get_screen_private(scrn); +#if HAS_DIXREGISTERPRIVATEKEY + if (!dixRegisterPrivateKey(&uxa_pixmap_index, PRIVATE_PIXMAP, 0)) +#else if (!dixRequestPrivate(&uxa_pixmap_index, 0)) +#endif return FALSE; intel->uxa_driver = uxa_driver_alloc(); @@ -1027,12 +1099,21 @@ Bool i830_uxa_init(ScreenPtr screen) intel->uxa_driver->uxa_major = 1; intel->uxa_driver->uxa_minor = 0; + intel->render_current_dest = NULL; + intel->prim_offset = 0; + intel->vertex_count = 0; + intel->floats_per_vertex = 0; + intel->last_floats_per_vertex = 0; + intel->vertex_bo = NULL; + /* Solid fill */ + intel->uxa_driver->check_solid = i830_uxa_check_solid; intel->uxa_driver->prepare_solid = i830_uxa_prepare_solid; intel->uxa_driver->solid = i830_uxa_solid; intel->uxa_driver->done_solid = i830_uxa_done_solid; /* Copy */ + intel->uxa_driver->check_copy = i830_uxa_check_copy; intel->uxa_driver->prepare_copy = i830_uxa_prepare_copy; intel->uxa_driver->copy = i830_uxa_copy; intel->uxa_driver->done_copy = i830_uxa_done_copy; @@ -1040,17 +1121,22 @@ Bool i830_uxa_init(ScreenPtr screen) /* Composite */ if (!IS_I9XX(intel)) { intel->uxa_driver->check_composite = i830_check_composite; + intel->uxa_driver->check_composite_target = i830_check_composite_target; + intel->uxa_driver->check_composite_texture = i830_check_composite_texture; intel->uxa_driver->prepare_composite = i830_prepare_composite; intel->uxa_driver->composite = i830_composite; intel->uxa_driver->done_composite = i830_done_composite; } else if (IS_I915G(intel) || IS_I915GM(intel) || IS_I945G(intel) || IS_I945GM(intel) || IS_G33CLASS(intel)) { intel->uxa_driver->check_composite = i915_check_composite; + intel->uxa_driver->check_composite_target = i915_check_composite_target; + intel->uxa_driver->check_composite_texture = i915_check_composite_texture; intel->uxa_driver->prepare_composite = i915_prepare_composite; intel->uxa_driver->composite = i915_composite; intel->uxa_driver->done_composite = i830_done_composite; } else { intel->uxa_driver->check_composite = i965_check_composite; + intel->uxa_driver->check_composite_texture = i965_check_composite_texture; intel->uxa_driver->prepare_composite = i965_prepare_composite; intel->uxa_driver->composite = i965_composite; intel->uxa_driver->done_composite = i830_done_composite; @@ -1058,21 +1144,22 @@ Bool i830_uxa_init(ScreenPtr screen) /* PutImage */ intel->uxa_driver->put_image = i830_uxa_put_image; + intel->uxa_driver->get_image = i830_uxa_get_image; intel->uxa_driver->prepare_access = i830_uxa_prepare_access; intel->uxa_driver->finish_access = i830_uxa_finish_access; intel->uxa_driver->pixmap_is_offscreen = i830_uxa_pixmap_is_offscreen; + screen->CreatePixmap = i830_uxa_create_pixmap; + screen->DestroyPixmap = i830_uxa_destroy_pixmap; + if (!uxa_driver_init(screen, intel->uxa_driver)) { xf86DrvMsg(scrn->scrnIndex, X_ERROR, "UXA initialization failed\n"); - xfree(intel->uxa_driver); + free(intel->uxa_driver); return FALSE; } - screen->CreatePixmap = i830_uxa_create_pixmap; - screen->DestroyPixmap = i830_uxa_destroy_pixmap; - uxa_set_fallback_debug(screen, intel->fallback_debug); return TRUE; diff --git a/src/i830_video.c b/src/i830_video.c index 23163684..7aa16bb6 100644 --- a/src/i830_video.c +++ b/src/i830_video.c @@ -557,7 +557,7 @@ void I830InitVideo(ScreenPtr screen) * adaptors. */ newAdaptors = - xalloc((num_adaptors + 2) * sizeof(XF86VideoAdaptorPtr *)); + malloc((num_adaptors + 2) * sizeof(XF86VideoAdaptorPtr *)); if (newAdaptors == NULL) return; @@ -574,8 +574,7 @@ void I830InitVideo(ScreenPtr screen) /* Set up textured video if we can do it at this depth and we are on * supported hardware. */ - if (scrn->bitsPerPixel >= 16 && (IS_I9XX(intel) || IS_I965G(intel)) && - !(!IS_I965G(intel) && scrn->displayWidth > 2048)) { + if (scrn->bitsPerPixel >= 16 && (IS_I9XX(intel) || IS_I965G(intel))) { texturedAdaptor = I830SetupImageVideoTextured(screen); if (texturedAdaptor != NULL) { xf86DrvMsg(scrn->scrnIndex, X_INFO, @@ -619,7 +618,7 @@ void I830InitVideo(ScreenPtr screen) if (texturedAdaptor) intel_xvmc_adaptor_init(screen); #endif - xfree(adaptors); + free(adaptors); } static void @@ -818,7 +817,7 @@ static XF86VideoAdaptorPtr I830SetupImageVideoOverlay(ScreenPtr screen) OVERLAY_DEBUG("I830SetupImageVideoOverlay\n"); - if (!(adapt = xcalloc(1, sizeof(XF86VideoAdaptorRec) + + if (!(adapt = calloc(1, sizeof(XF86VideoAdaptorRec) + sizeof(intel_adaptor_private) + sizeof(DevUnion)))) return NULL; @@ -950,16 +949,16 @@ static XF86VideoAdaptorPtr I830SetupImageVideoTextured(ScreenPtr screen) nAttributes = NUM_TEXTURED_ATTRIBUTES; - adapt = xcalloc(1, sizeof(XF86VideoAdaptorRec)); - adaptor_privs = xcalloc(nports, sizeof(intel_adaptor_private)); - devUnions = xcalloc(nports, sizeof(DevUnion)); - attrs = xcalloc(nAttributes, sizeof(XF86AttributeRec)); + adapt = calloc(1, sizeof(XF86VideoAdaptorRec)); + adaptor_privs = calloc(nports, sizeof(intel_adaptor_private)); + devUnions = calloc(nports, sizeof(DevUnion)); + attrs = calloc(nAttributes, sizeof(XF86AttributeRec)); if (adapt == NULL || adaptor_privs == NULL || devUnions == NULL || attrs == NULL) { - xfree(adapt); - xfree(adaptor_privs); - xfree(devUnions); - xfree(attrs); + free(adapt); + free(adaptor_privs); + free(devUnions); + free(attrs); return NULL; } diff --git a/src/i915_3d.c b/src/i915_3d.c index 517c6851..906043b1 100644 --- a/src/i915_3d.c +++ b/src/i915_3d.c @@ -38,7 +38,7 @@ void I915EmitInvarientState(ScrnInfoPtr scrn) { intel_screen_private *intel = intel_get_screen_private(scrn); - ATOMIC_BATCH(24); + assert(intel->in_batch_atomic); OUT_BATCH(_3DSTATE_AA_CMD | AA_LINE_ECAAR_WIDTH_ENABLE | @@ -85,8 +85,13 @@ void I915EmitInvarientState(ScrnInfoPtr scrn) ENABLE_STENCIL_WRITE_MASK | STENCIL_WRITE_MASK(0xff) | ENABLE_STENCIL_TEST_MASK | STENCIL_TEST_MASK(0xff)); - OUT_BATCH(_3DSTATE_LOAD_STATE_IMMEDIATE_1 | I1_LOAD_S(3) | 0); + OUT_BATCH(_3DSTATE_LOAD_STATE_IMMEDIATE_1 | I1_LOAD_S(3) | I1_LOAD_S(4) | I1_LOAD_S(5) | 2); OUT_BATCH(0x00000000); /* Disable texture coordinate wrap-shortest */ + OUT_BATCH((1 << S4_POINT_WIDTH_SHIFT) | + S4_LINE_WIDTH_ONE | + S4_CULLMODE_NONE | + S4_VFMT_XY); + OUT_BATCH(0x00000000); /* Stencil. */ OUT_BATCH(_3DSTATE_SCISSOR_ENABLE_CMD | DISABLE_SCISSOR_RECT); OUT_BATCH(_3DSTATE_SCISSOR_RECT_0_CMD); @@ -104,6 +109,4 @@ void I915EmitInvarientState(ScrnInfoPtr scrn) OUT_BATCH(_3DSTATE_BACKFACE_STENCIL_OPS | BFO_ENABLE_STENCIL_TWO_SIDE | 0); OUT_BATCH(MI_NOOP); - - ADVANCE_BATCH(); } diff --git a/src/i915_3d.h b/src/i915_3d.h index f85780aa..04531f33 100644 --- a/src/i915_3d.h +++ b/src/i915_3d.h @@ -1,6 +1,6 @@ /* -*- c-basic-offset: 4 -*- */ /* - * Copyright © 2006 Intel Corporation + * Copyright © 2006,2010 Intel Corporation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -23,9 +23,213 @@ * * Authors: * Eric Anholt <eric@anholt.net> + * Chris Wilson <chris@chris-wilson.co.uk> * */ +/* Each instruction is 3 dwords long, though most don't require all + * this space. Maximum of 123 instructions. Smaller maxes per insn + * type. + */ +#define _3DSTATE_PIXEL_SHADER_PROGRAM (CMD_3D|(0x1d<<24)|(0x5<<16)) + +#define REG_TYPE_R 0 /* temporary regs, no need to + * dcl, must be written before + * read -- Preserved between + * phases. + */ +#define REG_TYPE_T 1 /* Interpolated values, must be + * dcl'ed before use. + * + * 0..7: texture coord, + * 8: diffuse spec, + * 9: specular color, + * 10: fog parameter in w. + */ +#define REG_TYPE_CONST 2 /* Restriction: only one const + * can be referenced per + * instruction, though it may be + * selected for multiple inputs. + * Constants not initialized + * default to zero. + */ +#define REG_TYPE_S 3 /* sampler */ +#define REG_TYPE_OC 4 /* output color (rgba) */ +#define REG_TYPE_OD 5 /* output depth (w), xyz are + * temporaries. If not written, + * interpolated depth is used? + */ +#define REG_TYPE_U 6 /* unpreserved temporaries */ +#define REG_TYPE_MASK 0x7 +#define REG_TYPE_SHIFT 4 +#define REG_NR_MASK 0xf + +/* REG_TYPE_T: +*/ +#define T_TEX0 0 +#define T_TEX1 1 +#define T_TEX2 2 +#define T_TEX3 3 +#define T_TEX4 4 +#define T_TEX5 5 +#define T_TEX6 6 +#define T_TEX7 7 +#define T_DIFFUSE 8 +#define T_SPECULAR 9 +#define T_FOG_W 10 /* interpolated fog is in W coord */ + +/* Arithmetic instructions */ + +/* .replicate_swizzle == selection and replication of a particular + * scalar channel, ie., .xxxx, .yyyy, .zzzz or .wwww + */ +#define A0_NOP (0x0<<24) /* no operation */ +#define A0_ADD (0x1<<24) /* dst = src0 + src1 */ +#define A0_MOV (0x2<<24) /* dst = src0 */ +#define A0_MUL (0x3<<24) /* dst = src0 * src1 */ +#define A0_MAD (0x4<<24) /* dst = src0 * src1 + src2 */ +#define A0_DP2ADD (0x5<<24) /* dst.xyzw = src0.xy dot src1.xy + src2.replicate_swizzle */ +#define A0_DP3 (0x6<<24) /* dst.xyzw = src0.xyz dot src1.xyz */ +#define A0_DP4 (0x7<<24) /* dst.xyzw = src0.xyzw dot src1.xyzw */ +#define A0_FRC (0x8<<24) /* dst = src0 - floor(src0) */ +#define A0_RCP (0x9<<24) /* dst.xyzw = 1/(src0.replicate_swizzle) */ +#define A0_RSQ (0xa<<24) /* dst.xyzw = 1/(sqrt(abs(src0.replicate_swizzle))) */ +#define A0_EXP (0xb<<24) /* dst.xyzw = exp2(src0.replicate_swizzle) */ +#define A0_LOG (0xc<<24) /* dst.xyzw = log2(abs(src0.replicate_swizzle)) */ +#define A0_CMP (0xd<<24) /* dst = (src0 >= 0.0) ? src1 : src2 */ +#define A0_MIN (0xe<<24) /* dst = (src0 < src1) ? src0 : src1 */ +#define A0_MAX (0xf<<24) /* dst = (src0 >= src1) ? src0 : src1 */ +#define A0_FLR (0x10<<24) /* dst = floor(src0) */ +#define A0_MOD (0x11<<24) /* dst = src0 fmod 1.0 */ +#define A0_TRC (0x12<<24) /* dst = int(src0) */ +#define A0_SGE (0x13<<24) /* dst = src0 >= src1 ? 1.0 : 0.0 */ +#define A0_SLT (0x14<<24) /* dst = src0 < src1 ? 1.0 : 0.0 */ +#define A0_DEST_SATURATE (1<<22) +#define A0_DEST_TYPE_SHIFT 19 +/* Allow: R, OC, OD, U */ +#define A0_DEST_NR_SHIFT 14 +/* Allow R: 0..15, OC,OD: 0..0, U: 0..2 */ +#define A0_DEST_CHANNEL_X (1<<10) +#define A0_DEST_CHANNEL_Y (2<<10) +#define A0_DEST_CHANNEL_Z (4<<10) +#define A0_DEST_CHANNEL_W (8<<10) +#define A0_DEST_CHANNEL_ALL (0xf<<10) +#define A0_DEST_CHANNEL_SHIFT 10 +#define A0_SRC0_TYPE_SHIFT 7 +#define A0_SRC0_NR_SHIFT 2 + +#define A0_DEST_CHANNEL_XY (A0_DEST_CHANNEL_X|A0_DEST_CHANNEL_Y) +#define A0_DEST_CHANNEL_XYZ (A0_DEST_CHANNEL_XY|A0_DEST_CHANNEL_Z) + +#define SRC_X 0 +#define SRC_Y 1 +#define SRC_Z 2 +#define SRC_W 3 +#define SRC_ZERO 4 +#define SRC_ONE 5 + +#define A1_SRC0_CHANNEL_X_NEGATE (1<<31) +#define A1_SRC0_CHANNEL_X_SHIFT 28 +#define A1_SRC0_CHANNEL_Y_NEGATE (1<<27) +#define A1_SRC0_CHANNEL_Y_SHIFT 24 +#define A1_SRC0_CHANNEL_Z_NEGATE (1<<23) +#define A1_SRC0_CHANNEL_Z_SHIFT 20 +#define A1_SRC0_CHANNEL_W_NEGATE (1<<19) +#define A1_SRC0_CHANNEL_W_SHIFT 16 +#define A1_SRC1_TYPE_SHIFT 13 +#define A1_SRC1_NR_SHIFT 8 +#define A1_SRC1_CHANNEL_X_NEGATE (1<<7) +#define A1_SRC1_CHANNEL_X_SHIFT 4 +#define A1_SRC1_CHANNEL_Y_NEGATE (1<<3) +#define A1_SRC1_CHANNEL_Y_SHIFT 0 + +#define A2_SRC1_CHANNEL_Z_NEGATE (1<<31) +#define A2_SRC1_CHANNEL_Z_SHIFT 28 +#define A2_SRC1_CHANNEL_W_NEGATE (1<<27) +#define A2_SRC1_CHANNEL_W_SHIFT 24 +#define A2_SRC2_TYPE_SHIFT 21 +#define A2_SRC2_NR_SHIFT 16 +#define A2_SRC2_CHANNEL_X_NEGATE (1<<15) +#define A2_SRC2_CHANNEL_X_SHIFT 12 +#define A2_SRC2_CHANNEL_Y_NEGATE (1<<11) +#define A2_SRC2_CHANNEL_Y_SHIFT 8 +#define A2_SRC2_CHANNEL_Z_NEGATE (1<<7) +#define A2_SRC2_CHANNEL_Z_SHIFT 4 +#define A2_SRC2_CHANNEL_W_NEGATE (1<<3) +#define A2_SRC2_CHANNEL_W_SHIFT 0 + +/* Texture instructions */ +#define T0_TEXLD (0x15<<24) /* Sample texture using predeclared + * sampler and address, and output + * filtered texel data to destination + * register */ +#define T0_TEXLDP (0x16<<24) /* Same as texld but performs a + * perspective divide of the texture + * coordinate .xyz values by .w before + * sampling. */ +#define T0_TEXLDB (0x17<<24) /* Same as texld but biases the + * computed LOD by w. Only S4.6 two's + * comp is used. This implies that a + * float to fixed conversion is + * done. */ +#define T0_TEXKILL (0x18<<24) /* Does not perform a sampling + * operation. Simply kills the pixel + * if any channel of the address + * register is < 0.0. */ +#define T0_DEST_TYPE_SHIFT 19 +/* Allow: R, OC, OD, U */ +/* Note: U (unpreserved) regs do not retain their values between + * phases (cannot be used for feedback) + * + * Note: oC and OD registers can only be used as the destination of a + * texture instruction once per phase (this is an implementation + * restriction). + */ +#define T0_DEST_NR_SHIFT 14 +/* Allow R: 0..15, OC,OD: 0..0, U: 0..2 */ +#define T0_SAMPLER_NR_SHIFT 0 /* This field ignored for TEXKILL */ +#define T0_SAMPLER_NR_MASK (0xf<<0) + +#define T1_ADDRESS_REG_TYPE_SHIFT 24 /* Reg to use as texture coord */ +/* Allow R, T, OC, OD -- R, OC, OD are 'dependent' reads, new program phase */ +#define T1_ADDRESS_REG_NR_SHIFT 17 +#define T2_MBZ 0 + +/* Declaration instructions */ +#define D0_DCL (0x19<<24) /* Declare a t (interpolated attrib) + * register or an s (sampler) + * register. */ +#define D0_SAMPLE_TYPE_SHIFT 22 +#define D0_SAMPLE_TYPE_2D (0x0<<22) +#define D0_SAMPLE_TYPE_CUBE (0x1<<22) +#define D0_SAMPLE_TYPE_VOLUME (0x2<<22) +#define D0_SAMPLE_TYPE_MASK (0x3<<22) + +#define D0_TYPE_SHIFT 19 +/* Allow: T, S */ +#define D0_NR_SHIFT 14 +/* Allow T: 0..10, S: 0..15 */ +#define D0_CHANNEL_X (1<<10) +#define D0_CHANNEL_Y (2<<10) +#define D0_CHANNEL_Z (4<<10) +#define D0_CHANNEL_W (8<<10) +#define D0_CHANNEL_ALL (0xf<<10) +#define D0_CHANNEL_NONE (0<<10) + +#define D0_CHANNEL_XY (D0_CHANNEL_X|D0_CHANNEL_Y) +#define D0_CHANNEL_XYZ (D0_CHANNEL_XY|D0_CHANNEL_Z) + +/* I915 Errata: Do not allow (xz), (xw), (xzw) combinations for diffuse + * or specular declarations. + * + * For T dcls, only allow: (x), (xy), (xyz), (w), (xyzw) + * + * Must be zero for S (sampler) dcls + */ +#define D1_MBZ 0 +#define D2_MBZ 0 + + /* MASK_* are the unshifted bitmasks of the destination mask in arithmetic * operations */ @@ -38,130 +242,101 @@ #define MASK_SATURATE 0x10 /* Temporary, undeclared regs. Preserved between phases */ -#define FS_R0 ((REG_TYPE_R << 8) | 0) -#define FS_R1 ((REG_TYPE_R << 8) | 1) -#define FS_R2 ((REG_TYPE_R << 8) | 2) -#define FS_R3 ((REG_TYPE_R << 8) | 3) +#define FS_R0 ((REG_TYPE_R << REG_TYPE_SHIFT) | 0) +#define FS_R1 ((REG_TYPE_R << REG_TYPE_SHIFT) | 1) +#define FS_R2 ((REG_TYPE_R << REG_TYPE_SHIFT) | 2) +#define FS_R3 ((REG_TYPE_R << REG_TYPE_SHIFT) | 3) /* Texture coordinate regs. Must be declared. */ -#define FS_T0 ((REG_TYPE_T << 8) | 0) -#define FS_T1 ((REG_TYPE_T << 8) | 1) -#define FS_T2 ((REG_TYPE_T << 8) | 2) -#define FS_T3 ((REG_TYPE_T << 8) | 3) -#define FS_T4 ((REG_TYPE_T << 8) | 4) -#define FS_T5 ((REG_TYPE_T << 8) | 5) -#define FS_T6 ((REG_TYPE_T << 8) | 6) -#define FS_T7 ((REG_TYPE_T << 8) | 7) -#define FS_T8 ((REG_TYPE_T << 8) | 8) -#define FS_T9 ((REG_TYPE_T << 8) | 9) -#define FS_T10 ((REG_TYPE_T << 8) | 10) +#define FS_T0 ((REG_TYPE_T << REG_TYPE_SHIFT) | 0) +#define FS_T1 ((REG_TYPE_T << REG_TYPE_SHIFT) | 1) +#define FS_T2 ((REG_TYPE_T << REG_TYPE_SHIFT) | 2) +#define FS_T3 ((REG_TYPE_T << REG_TYPE_SHIFT) | 3) +#define FS_T4 ((REG_TYPE_T << REG_TYPE_SHIFT) | 4) +#define FS_T5 ((REG_TYPE_T << REG_TYPE_SHIFT) | 5) +#define FS_T6 ((REG_TYPE_T << REG_TYPE_SHIFT) | 6) +#define FS_T7 ((REG_TYPE_T << REG_TYPE_SHIFT) | 7) +#define FS_T8 ((REG_TYPE_T << REG_TYPE_SHIFT) | 8) +#define FS_T9 ((REG_TYPE_T << REG_TYPE_SHIFT) | 9) +#define FS_T10 ((REG_TYPE_T << REG_TYPE_SHIFT) | 10) /* Constant values */ -#define FS_C0 ((REG_TYPE_CONST << 8) | 0) -#define FS_C1 ((REG_TYPE_CONST << 8) | 1) -#define FS_C2 ((REG_TYPE_CONST << 8) | 2) -#define FS_C3 ((REG_TYPE_CONST << 8) | 3) -#define FS_C4 ((REG_TYPE_CONST << 8) | 4) -#define FS_C5 ((REG_TYPE_CONST << 8) | 5) -#define FS_C6 ((REG_TYPE_CONST << 8) | 6) -#define FS_C7 ((REG_TYPE_CONST << 8) | 7) +#define FS_C0 ((REG_TYPE_CONST << REG_TYPE_SHIFT) | 0) +#define FS_C1 ((REG_TYPE_CONST << REG_TYPE_SHIFT) | 1) +#define FS_C2 ((REG_TYPE_CONST << REG_TYPE_SHIFT) | 2) +#define FS_C3 ((REG_TYPE_CONST << REG_TYPE_SHIFT) | 3) +#define FS_C4 ((REG_TYPE_CONST << REG_TYPE_SHIFT) | 4) +#define FS_C5 ((REG_TYPE_CONST << REG_TYPE_SHIFT) | 5) +#define FS_C6 ((REG_TYPE_CONST << REG_TYPE_SHIFT) | 6) +#define FS_C7 ((REG_TYPE_CONST << REG_TYPE_SHIFT) | 7) /* Sampler regs */ -#define FS_S0 ((REG_TYPE_S << 8) | 0) -#define FS_S1 ((REG_TYPE_S << 8) | 1) -#define FS_S2 ((REG_TYPE_S << 8) | 2) -#define FS_S3 ((REG_TYPE_S << 8) | 3) +#define FS_S0 ((REG_TYPE_S << REG_TYPE_SHIFT) | 0) +#define FS_S1 ((REG_TYPE_S << REG_TYPE_SHIFT) | 1) +#define FS_S2 ((REG_TYPE_S << REG_TYPE_SHIFT) | 2) +#define FS_S3 ((REG_TYPE_S << REG_TYPE_SHIFT) | 3) /* Output color */ -#define FS_OC ((REG_TYPE_OC << 8) | 0) +#define FS_OC ((REG_TYPE_OC << REG_TYPE_SHIFT) | 0) /* Output depth */ -#define FS_OD ((REG_TYPE_OD << 8) | 0) +#define FS_OD ((REG_TYPE_OD << REG_TYPE_SHIFT) | 0) /* Unpreserved temporary regs */ -#define FS_U0 ((REG_TYPE_U << 8) | 0) -#define FS_U1 ((REG_TYPE_U << 8) | 1) -#define FS_U2 ((REG_TYPE_U << 8) | 2) -#define FS_U3 ((REG_TYPE_U << 8) | 3) - -#define REG_TYPE(reg) ((reg) >> 8) -#define REG_NR(reg) ((reg) & 0xff) - -struct i915_fs_op { - uint32_t ui[3]; +#define FS_U0 ((REG_TYPE_U << REG_TYPE_SHIFT) | 0) +#define FS_U1 ((REG_TYPE_U << REG_TYPE_SHIFT) | 1) +#define FS_U2 ((REG_TYPE_U << REG_TYPE_SHIFT) | 2) +#define FS_U3 ((REG_TYPE_U << REG_TYPE_SHIFT) | 3) + +#define X_CHANNEL_SHIFT (REG_TYPE_SHIFT + 3) +#define Y_CHANNEL_SHIFT (X_CHANNEL_SHIFT + 4) +#define Z_CHANNEL_SHIFT (Y_CHANNEL_SHIFT + 4) +#define W_CHANNEL_SHIFT (Z_CHANNEL_SHIFT + 4) + +#define REG_CHANNEL_MASK 0xf + +#define REG_NR(reg) ((reg) & REG_NR_MASK) +#define REG_TYPE(reg) (((reg) >> REG_TYPE_SHIFT) & REG_TYPE_MASK) +#define REG_X(reg) (((reg) >> X_CHANNEL_SHIFT) & REG_CHANNEL_MASK) +#define REG_Y(reg) (((reg) >> Y_CHANNEL_SHIFT) & REG_CHANNEL_MASK) +#define REG_Z(reg) (((reg) >> Z_CHANNEL_SHIFT) & REG_CHANNEL_MASK) +#define REG_W(reg) (((reg) >> W_CHANNEL_SHIFT) & REG_CHANNEL_MASK) + +enum i915_fs_channel { + X_CHANNEL_VAL = 0, + Y_CHANNEL_VAL, + Z_CHANNEL_VAL, + W_CHANNEL_VAL, + ZERO_CHANNEL_VAL, + ONE_CHANNEL_VAL, + + NEG_X_CHANNEL_VAL = X_CHANNEL_VAL | 0x8, + NEG_Y_CHANNEL_VAL = Y_CHANNEL_VAL | 0x8, + NEG_Z_CHANNEL_VAL = Z_CHANNEL_VAL | 0x8, + NEG_W_CHANNEL_VAL = W_CHANNEL_VAL | 0x8, + NEG_ONE_CHANNEL_VAL = ONE_CHANNEL_VAL | 0x8 }; -#define X_CHANNEL_VAL 1 -#define Y_CHANNEL_VAL 2 -#define Z_CHANNEL_VAL 3 -#define W_CHANNEL_VAL 4 -#define ZERO_CHANNEL_VAL 5 -#define ONE_CHANNEL_VAL 6 +#define i915_fs_operand(reg, x, y, z, w) \ + (reg) | \ +(x##_CHANNEL_VAL << X_CHANNEL_SHIFT) | \ +(y##_CHANNEL_VAL << Y_CHANNEL_SHIFT) | \ +(z##_CHANNEL_VAL << Z_CHANNEL_SHIFT) | \ +(w##_CHANNEL_VAL << W_CHANNEL_SHIFT) /** - * This structure represents the contents of an operand to an i915 fragment - * shader. - * - * It is not a hardware representation, though closely related. - */ -struct i915_fs_operand { - /**< REG_TYPE_* register type */ - int reg; - /**< *_CHANNEL_VAL swizzle value, with optional negation */ - int x; - /**< *_CHANNEL_VAL swizzle value, with optional negation */ - int y; - /**< *_CHANNEL_VAL swizzle value, with optional negation */ - int z; - /**< *_CHANNEL_VAL swizzle value, with optional negation */ - int w; -}; - -/** - * Construct an operand description for the fragment shader. - * - * \param regtype FS_* register used as the source value for X/Y/Z/W sources. - * \param x *_CHANNEL_VAL swizzle value prefix for operand X channel, with - * optional negation. - * \param y *_CHANNEL_VAL swizzle value prefix for operand Y channel, with - * optional negation. - * \param z *_CHANNEL_VAL swizzle value prefix for operand Z channel, with - * optional negation. - * \param w *_CHANNEL_VAL swizzle value prefix for operand W channel, with - * optional negation. - */ -#define i915_fs_operand(reg, x, y, z, w) \ - _i915_fs_operand(reg, \ - x##_CHANNEL_VAL, y##_CHANNEL_VAL, \ - z##_CHANNEL_VAL, w##_CHANNEL_VAL) - -/** - * Construct an oeprand description for using a register with no swizzling + * Construct an operand description for using a register with no swizzling */ #define i915_fs_operand_reg(reg) \ - i915_fs_operand(reg, X, Y, Z, W) - -static inline struct i915_fs_operand -_i915_fs_operand(int reg, int x, int y, int z, int w) -{ - struct i915_fs_operand operand; + i915_fs_operand(reg, X, Y, Z, W) - operand.reg = reg; - operand.x = x; - operand.y = y; - operand.z = z; - operand.w = w; - - return operand; -} +#define i915_fs_operand_reg_negate(reg) \ + i915_fs_operand(reg, NEG_X, NEG_Y, NEG_Z, NEG_W) /** * Returns an operand containing (0.0, 0.0, 0.0, 0.0). */ -static inline struct i915_fs_operand i915_fs_operand_zero(void) -{ - return i915_fs_operand(FS_R0, ZERO, ZERO, ZERO, ZERO); -} +#define i915_fs_operand_zero() i915_fs_operand(FS_R0, ZERO, ZERO, ZERO, ZERO) /** * Returns an unused operand @@ -171,246 +346,256 @@ static inline struct i915_fs_operand i915_fs_operand_zero(void) /** * Returns an operand containing (1.0, 1.0, 1.0, 1.0). */ -static inline struct i915_fs_operand i915_fs_operand_one(void) -{ - return i915_fs_operand(FS_R0, ONE, ONE, ONE, ONE); -} - -static inline int i915_get_hardware_channel_val(int channel_val) -{ - if (channel_val < 0) - channel_val = -channel_val; - - switch (channel_val) { - case X_CHANNEL_VAL: - return SRC_X; - case Y_CHANNEL_VAL: - return SRC_Y; - case Z_CHANNEL_VAL: - return SRC_Z; - case W_CHANNEL_VAL: - return SRC_W; - case ZERO_CHANNEL_VAL: - return SRC_ZERO; - case ONE_CHANNEL_VAL: - return SRC_ONE; - } - FatalError("Bad channel value %d\n", channel_val); -} +#define i915_fs_operand_one() i915_fs_operand(FS_R0, ONE, ONE, ONE, ONE) + +#define i915_get_hardware_channel_val(val, shift, negate) \ + (((val & 0x7) << shift) | ((val & 0x8) ? negate : 0)) /** * Outputs a fragment shader command to declare a sampler or texture register. */ #define i915_fs_dcl(reg) \ -do { \ - FS_OUT(_i915_fs_dcl(reg)); \ -} while (0) - -/** - * Constructs a fragment shader command to declare a sampler or texture - * register. - */ -static inline struct i915_fs_op _i915_fs_dcl(int reg) -{ - struct i915_fs_op op; + do { \ + OUT_BATCH(D0_DCL | \ + (REG_TYPE(reg) << D0_TYPE_SHIFT) | \ + (REG_NR(reg) << D0_NR_SHIFT) | \ + ((REG_TYPE(reg) != REG_TYPE_S) ? D0_CHANNEL_ALL : 0)); \ + OUT_BATCH(0); \ + OUT_BATCH(0); \ + } while (0) - op.ui[0] = D0_DCL | (REG_TYPE(reg) << D0_TYPE_SHIFT) | - (REG_NR(reg) << D0_NR_SHIFT); - op.ui[1] = 0; - op.ui[2] = 0; - if (REG_TYPE(reg) != REG_TYPE_S) - op.ui[0] |= D0_CHANNEL_ALL; - - return op; -} - -/** - * Constructs a fragment shader command to load from a texture sampler. - */ #define i915_fs_texld(dest_reg, sampler_reg, address_reg) \ -do { \ - FS_OUT(_i915_fs_texld(T0_TEXLD, dest_reg, sampler_reg, address_reg)); \ -} while (0) + do { \ + OUT_BATCH(T0_TEXLD | \ + (REG_TYPE(dest_reg) << T0_DEST_TYPE_SHIFT) | \ + (REG_NR(dest_reg) << T0_DEST_NR_SHIFT) | \ + (REG_NR(sampler_reg) << T0_SAMPLER_NR_SHIFT)); \ + OUT_BATCH((REG_TYPE(address_reg) << T1_ADDRESS_REG_TYPE_SHIFT) | \ + (REG_NR(address_reg) << T1_ADDRESS_REG_NR_SHIFT)); \ + OUT_BATCH(0); \ + } while (0) #define i915_fs_texldp(dest_reg, sampler_reg, address_reg) \ -do { \ - FS_OUT(_i915_fs_texld(T0_TEXLDP, dest_reg, sampler_reg, address_reg)); \ -} while (0) - -static inline struct i915_fs_op -_i915_fs_texld(int load_op, int dest_reg, int sampler_reg, int address_reg) -{ - struct i915_fs_op op; - - op.ui[0] = 0; - op.ui[1] = 0; - op.ui[2] = 0; - - if (REG_TYPE(sampler_reg) != REG_TYPE_S) - FatalError("Bad sampler reg type\n"); - - op.ui[0] |= load_op; - op.ui[0] |= REG_TYPE(dest_reg) << T0_DEST_TYPE_SHIFT; - op.ui[0] |= REG_NR(dest_reg) << T0_DEST_NR_SHIFT; - op.ui[0] |= REG_NR(sampler_reg) << T0_SAMPLER_NR_SHIFT; - op.ui[1] |= REG_TYPE(address_reg) << T1_ADDRESS_REG_TYPE_SHIFT; - op.ui[1] |= REG_NR(address_reg) << T1_ADDRESS_REG_NR_SHIFT; - - return op; -} + do { \ + OUT_BATCH(T0_TEXLDP | \ + (REG_TYPE(dest_reg) << T0_DEST_TYPE_SHIFT) | \ + (REG_NR(dest_reg) << T0_DEST_NR_SHIFT) | \ + (REG_NR(sampler_reg) << T0_SAMPLER_NR_SHIFT)); \ + OUT_BATCH((REG_TYPE(address_reg) << T1_ADDRESS_REG_TYPE_SHIFT) | \ + (REG_NR(address_reg) << T1_ADDRESS_REG_NR_SHIFT)); \ + OUT_BATCH(0); \ + } while (0) + +#define i915_fs_arith_masked(op, dest_reg, dest_mask, operand0, operand1, operand2) \ + _i915_fs_arith_masked(A0_##op, dest_reg, dest_mask, operand0, operand1, operand2) #define i915_fs_arith(op, dest_reg, operand0, operand1, operand2) \ - _i915_fs_arith(A0_##op, dest_reg, operand0, operand1, operand2) - -static inline struct i915_fs_op -_i915_fs_arith(int cmd, int dest_reg, - struct i915_fs_operand operand0, - struct i915_fs_operand operand1, struct i915_fs_operand operand2) -{ - struct i915_fs_op op; - - op.ui[0] = 0; - op.ui[1] = 0; - op.ui[2] = 0; - - /* Set up destination register and write mask */ - op.ui[0] |= cmd; - op.ui[0] |= REG_TYPE(dest_reg) << A0_DEST_TYPE_SHIFT; - op.ui[0] |= REG_NR(dest_reg) << A0_DEST_NR_SHIFT; - op.ui[0] |= A0_DEST_CHANNEL_ALL; - - /* Set up operand 0 */ - op.ui[0] |= REG_TYPE(operand0.reg) << A0_SRC0_TYPE_SHIFT; - op.ui[0] |= REG_NR(operand0.reg) << A0_SRC0_NR_SHIFT; - - op.ui[1] |= i915_get_hardware_channel_val(operand0.x) << - A1_SRC0_CHANNEL_X_SHIFT; - if (operand0.x < 0) - op.ui[1] |= A1_SRC0_CHANNEL_X_NEGATE; - - op.ui[1] |= i915_get_hardware_channel_val(operand0.y) << - A1_SRC0_CHANNEL_Y_SHIFT; - if (operand0.y < 0) - op.ui[1] |= A1_SRC0_CHANNEL_Y_NEGATE; - - op.ui[1] |= i915_get_hardware_channel_val(operand0.z) << - A1_SRC0_CHANNEL_Z_SHIFT; - if (operand0.z < 0) - op.ui[1] |= A1_SRC0_CHANNEL_Z_NEGATE; - - op.ui[1] |= i915_get_hardware_channel_val(operand0.w) << - A1_SRC0_CHANNEL_W_SHIFT; - if (operand0.w < 0) - op.ui[1] |= A1_SRC0_CHANNEL_W_NEGATE; - - /* Set up operand 1 */ - op.ui[1] |= REG_TYPE(operand1.reg) << A1_SRC1_TYPE_SHIFT; - op.ui[1] |= REG_NR(operand1.reg) << A1_SRC1_NR_SHIFT; - - op.ui[1] |= i915_get_hardware_channel_val(operand1.x) << - A1_SRC1_CHANNEL_X_SHIFT; - if (operand1.x < 0) - op.ui[1] |= A1_SRC1_CHANNEL_X_NEGATE; - - op.ui[1] |= i915_get_hardware_channel_val(operand1.y) << - A1_SRC1_CHANNEL_Y_SHIFT; - if (operand1.y < 0) - op.ui[1] |= A1_SRC1_CHANNEL_Y_NEGATE; - - op.ui[2] |= i915_get_hardware_channel_val(operand1.z) << - A2_SRC1_CHANNEL_Z_SHIFT; - if (operand1.z < 0) - op.ui[2] |= A2_SRC1_CHANNEL_Z_NEGATE; - - op.ui[2] |= i915_get_hardware_channel_val(operand1.w) << - A2_SRC1_CHANNEL_W_SHIFT; - if (operand1.w < 0) - op.ui[2] |= A2_SRC1_CHANNEL_W_NEGATE; - - /* Set up operand 2 */ - op.ui[2] |= REG_TYPE(operand2.reg) << A2_SRC2_TYPE_SHIFT; - op.ui[2] |= REG_NR(operand2.reg) << A2_SRC2_NR_SHIFT; - - op.ui[2] |= i915_get_hardware_channel_val(operand2.x) << - A2_SRC2_CHANNEL_X_SHIFT; - if (operand2.x < 0) - op.ui[2] |= A2_SRC2_CHANNEL_X_NEGATE; - - op.ui[2] |= i915_get_hardware_channel_val(operand2.y) << - A2_SRC2_CHANNEL_Y_SHIFT; - if (operand2.y < 0) - op.ui[2] |= A2_SRC2_CHANNEL_Y_NEGATE; - - op.ui[2] |= i915_get_hardware_channel_val(operand2.z) << - A2_SRC2_CHANNEL_Z_SHIFT; - if (operand2.z < 0) - op.ui[2] |= A2_SRC2_CHANNEL_Z_NEGATE; - - op.ui[2] |= i915_get_hardware_channel_val(operand2.w) << - A2_SRC2_CHANNEL_W_SHIFT; - if (operand2.w < 0) - op.ui[2] |= A2_SRC2_CHANNEL_W_NEGATE; - - return op; -} - -/** Move operand0 to dest_reg */ -#define i915_fs_mov(dest_reg, operand0) \ -do { \ - FS_OUT(i915_fs_arith(MOV, dest_reg, operand0, \ - i915_fs_operand_none(), \ - i915_fs_operand_none())); \ + _i915_fs_arith(A0_##op, dest_reg, operand0, operand1, operand2) + +#define _i915_fs_arith_masked(cmd, dest_reg, dest_mask, operand0, operand1, operand2) \ + do { \ + /* Set up destination register and write mask */ \ + OUT_BATCH(cmd | \ + (REG_TYPE(dest_reg) << A0_DEST_TYPE_SHIFT) | \ + (REG_NR(dest_reg) << A0_DEST_NR_SHIFT) | \ + (((dest_mask) & ~MASK_SATURATE) << A0_DEST_CHANNEL_SHIFT) | \ + (((dest_mask) & MASK_SATURATE) ? A0_DEST_SATURATE : 0) | \ + /* Set up operand 0 */ \ + (REG_TYPE(operand0) << A0_SRC0_TYPE_SHIFT) | \ + (REG_NR(operand0) << A0_SRC0_NR_SHIFT)); \ + OUT_BATCH(i915_get_hardware_channel_val(REG_X(operand0), \ + A1_SRC0_CHANNEL_X_SHIFT, \ + A1_SRC0_CHANNEL_X_NEGATE) | \ + i915_get_hardware_channel_val(REG_Y(operand0), \ + A1_SRC0_CHANNEL_Y_SHIFT, \ + A1_SRC0_CHANNEL_Y_NEGATE) | \ + i915_get_hardware_channel_val(REG_Z(operand0), \ + A1_SRC0_CHANNEL_Z_SHIFT, \ + A1_SRC0_CHANNEL_Z_NEGATE) | \ + i915_get_hardware_channel_val(REG_W(operand0), \ + A1_SRC0_CHANNEL_W_SHIFT, \ + A1_SRC0_CHANNEL_W_NEGATE) | \ + /* Set up operand 1 */ \ + (REG_TYPE(operand1) << A1_SRC1_TYPE_SHIFT) | \ + (REG_NR(operand1) << A1_SRC1_NR_SHIFT) | \ + i915_get_hardware_channel_val(REG_X(operand1), \ + A1_SRC1_CHANNEL_X_SHIFT, \ + A1_SRC1_CHANNEL_X_NEGATE) | \ + i915_get_hardware_channel_val(REG_Y(operand1), \ + A1_SRC1_CHANNEL_Y_SHIFT, \ + A1_SRC1_CHANNEL_Y_NEGATE)); \ + OUT_BATCH(i915_get_hardware_channel_val(REG_Z(operand1), \ + A2_SRC1_CHANNEL_Z_SHIFT, \ + A2_SRC1_CHANNEL_Z_NEGATE) | \ + i915_get_hardware_channel_val(REG_W(operand1), \ + A2_SRC1_CHANNEL_W_SHIFT, \ + A2_SRC1_CHANNEL_W_NEGATE) | \ + /* Set up operand 2 */ \ + (REG_TYPE(operand2) << A2_SRC2_TYPE_SHIFT) | \ + (REG_NR(operand2) << A2_SRC2_NR_SHIFT) | \ + i915_get_hardware_channel_val(REG_X(operand2), \ + A2_SRC2_CHANNEL_X_SHIFT, \ + A2_SRC2_CHANNEL_X_NEGATE) | \ + i915_get_hardware_channel_val(REG_Y(operand2), \ + A2_SRC2_CHANNEL_Y_SHIFT, \ + A2_SRC2_CHANNEL_Y_NEGATE) | \ + i915_get_hardware_channel_val(REG_Z(operand2), \ + A2_SRC2_CHANNEL_Z_SHIFT, \ + A2_SRC2_CHANNEL_Z_NEGATE) | \ + i915_get_hardware_channel_val(REG_W(operand2), \ + A2_SRC2_CHANNEL_W_SHIFT, \ + A2_SRC2_CHANNEL_W_NEGATE)); \ + } while (0) + +#define _i915_fs_arith(cmd, dest_reg, operand0, operand1, operand2) do {\ + /* Set up destination register and write mask */ \ + OUT_BATCH(cmd | \ + (REG_TYPE(dest_reg) << A0_DEST_TYPE_SHIFT) | \ + (REG_NR(dest_reg) << A0_DEST_NR_SHIFT) | \ + (A0_DEST_CHANNEL_ALL) | \ + /* Set up operand 0 */ \ + (REG_TYPE(operand0) << A0_SRC0_TYPE_SHIFT) | \ + (REG_NR(operand0) << A0_SRC0_NR_SHIFT)); \ + OUT_BATCH(i915_get_hardware_channel_val(REG_X(operand0), \ + A1_SRC0_CHANNEL_X_SHIFT, \ + A1_SRC0_CHANNEL_X_NEGATE) | \ + i915_get_hardware_channel_val(REG_Y(operand0), \ + A1_SRC0_CHANNEL_Y_SHIFT, \ + A1_SRC0_CHANNEL_Y_NEGATE) | \ + i915_get_hardware_channel_val(REG_Z(operand0), \ + A1_SRC0_CHANNEL_Z_SHIFT, \ + A1_SRC0_CHANNEL_Z_NEGATE) | \ + i915_get_hardware_channel_val(REG_W(operand0), \ + A1_SRC0_CHANNEL_W_SHIFT, \ + A1_SRC0_CHANNEL_W_NEGATE) | \ + /* Set up operand 1 */ \ + (REG_TYPE(operand1) << A1_SRC1_TYPE_SHIFT) | \ + (REG_NR(operand1) << A1_SRC1_NR_SHIFT) | \ + i915_get_hardware_channel_val(REG_X(operand1), \ + A1_SRC1_CHANNEL_X_SHIFT, \ + A1_SRC1_CHANNEL_X_NEGATE) | \ + i915_get_hardware_channel_val(REG_Y(operand1), \ + A1_SRC1_CHANNEL_Y_SHIFT, \ + A1_SRC1_CHANNEL_Y_NEGATE)); \ + OUT_BATCH(i915_get_hardware_channel_val(REG_Z(operand1), \ + A2_SRC1_CHANNEL_Z_SHIFT, \ + A2_SRC1_CHANNEL_Z_NEGATE) | \ + i915_get_hardware_channel_val(REG_W(operand1), \ + A2_SRC1_CHANNEL_W_SHIFT, \ + A2_SRC1_CHANNEL_W_NEGATE) | \ + /* Set up operand 2 */ \ + (REG_TYPE(operand2) << A2_SRC2_TYPE_SHIFT) | \ + (REG_NR(operand2) << A2_SRC2_NR_SHIFT) | \ + i915_get_hardware_channel_val(REG_X(operand2), \ + A2_SRC2_CHANNEL_X_SHIFT, \ + A2_SRC2_CHANNEL_X_NEGATE) | \ + i915_get_hardware_channel_val(REG_Y(operand2), \ + A2_SRC2_CHANNEL_Y_SHIFT, \ + A2_SRC2_CHANNEL_Y_NEGATE) | \ + i915_get_hardware_channel_val(REG_Z(operand2), \ + A2_SRC2_CHANNEL_Z_SHIFT, \ + A2_SRC2_CHANNEL_Z_NEGATE) | \ + i915_get_hardware_channel_val(REG_W(operand2), \ + A2_SRC2_CHANNEL_W_SHIFT, \ + A2_SRC2_CHANNEL_W_NEGATE)); \ } while (0) -/** - * Move the value in operand0 to the dest reg with the masking/saturation - * specified. - */ +#define i915_fs_mov(dest_reg, operand0) \ + i915_fs_arith(MOV, dest_reg, \ + operand0, \ + i915_fs_operand_none(), \ + i915_fs_operand_none()) + #define i915_fs_mov_masked(dest_reg, dest_mask, operand0) \ -do { \ - struct i915_fs_op op; \ - \ - op = i915_fs_arith(MOV, dest_reg, operand0, i915_fs_operand_none(), \ - i915_fs_operand_none()); \ - op.ui[0] &= ~A0_DEST_CHANNEL_ALL; \ - op.ui[0] |= ((dest_mask) & ~MASK_SATURATE) << A0_DEST_CHANNEL_SHIFT; \ - if ((dest_mask) & MASK_SATURATE) \ - op.ui[0] |= A0_DEST_SATURATE; \ - \ - FS_OUT(op); \ -} while (0) + i915_fs_arith_masked (MOV, dest_reg, dest_mask, \ + operand0, \ + i915_fs_operand_none(), \ + i915_fs_operand_none()) + + +#define i915_fs_frc(dest_reg, operand0) \ + i915_fs_arith (FRC, dest_reg, \ + operand0, \ + i915_fs_operand_none(), \ + i915_fs_operand_none()) /** Add operand0 and operand1 and put the result in dest_reg */ #define i915_fs_add(dest_reg, operand0, operand1) \ -do { \ - FS_OUT(i915_fs_arith(ADD, dest_reg, operand0, operand1, \ - i915_fs_operand_none())); \ -} while (0) + i915_fs_arith (ADD, dest_reg, \ + operand0, operand1, \ + i915_fs_operand_none()) -/** Add operand0 and operand1 and put the result in dest_reg */ +/** Multiply operand0 and operand1 and put the result in dest_reg */ #define i915_fs_mul(dest_reg, operand0, operand1) \ -do { \ - FS_OUT(i915_fs_arith(MUL, dest_reg, operand0, operand1, \ - i915_fs_operand_none())); \ -} while (0) + i915_fs_arith (MUL, dest_reg, \ + operand0, operand1, \ + i915_fs_operand_none()) + +/** Computes 1/sqrt(operand0.replicate_swizzle) puts the result in dest_reg */ +#define i915_fs_rsq(dest_reg, dest_mask, operand0) \ + do { \ + if (dest_mask) { \ + i915_fs_arith_masked (RSQ, dest_reg, dest_mask, \ + operand0, \ + i915_fs_operand_none (), \ + i915_fs_operand_none ()); \ + } else { \ + i915_fs_arith (RSQ, dest_reg, \ + operand0, \ + i915_fs_operand_none (), \ + i915_fs_operand_none ()); \ + } \ + } while (0) + +/** Puts the minimum of operand0 and operand1 in dest_reg */ +#define i915_fs_min(dest_reg, operand0, operand1) \ + i915_fs_arith (MIN, dest_reg, \ + operand0, operand1, \ + i915_fs_operand_none()) + +/** Puts the maximum of operand0 and operand1 in dest_reg */ +#define i915_fs_max(dest_reg, operand0, operand1) \ + i915_fs_arith (MAX, dest_reg, \ + operand0, operand1, \ + i915_fs_operand_none()) + +#define i915_fs_cmp(dest_reg, operand0, operand1, operand2) \ + i915_fs_arith (CMP, dest_reg, operand0, operand1, operand2) + +/** Perform operand0 * operand1 + operand2 and put the result in dest_reg */ +#define i915_fs_mad(dest_reg, dest_mask, op0, op1, op2) \ + do { \ + if (dest_mask) { \ + i915_fs_arith_masked (MAD, dest_reg, dest_mask, op0, op1, op2); \ + } else { \ + i915_fs_arith (MAD, dest_reg, op0, op1, op2); \ + } \ + } while (0) + +#define i915_fs_dp2add(dest_reg, dest_mask, op0, op1, op2) \ + do { \ + if (dest_mask) { \ + i915_fs_arith_masked (DP2ADD, dest_reg, dest_mask, op0, op1, op2); \ + } else { \ + i915_fs_arith (DP2ADD, dest_reg, op0, op1, op2); \ + } \ + } while (0) /** * Perform a 3-component dot-product of operand0 and operand1 and put the * resulting scalar in the channels of dest_reg specified by the dest_mask. */ -#define i915_fs_dp3_masked(dest_reg, dest_mask, operand0, operand1) \ -do { \ - struct i915_fs_op op; \ - \ - op = i915_fs_arith(DP3, dest_reg, operand0, operand1, \ - i915_fs_operand_none()); \ - op.ui[0] &= ~A0_DEST_CHANNEL_ALL; \ - op.ui[0] |= ((dest_mask) & ~MASK_SATURATE) << A0_DEST_CHANNEL_SHIFT; \ - if ((dest_mask) & MASK_SATURATE) \ - op.ui[0] |= A0_DEST_SATURATE; \ - \ - FS_OUT(op); \ -} while (0) +#define i915_fs_dp3(dest_reg, dest_mask, op0, op1) \ + do { \ + if (dest_mask) { \ + i915_fs_arith_masked (DP3, dest_reg, dest_mask, \ + op0, op1,\ + i915_fs_operand_none()); \ + } else { \ + i915_fs_arith (DP3, dest_reg, op0, op1,\ + i915_fs_operand_none()); \ + } \ + } while (0) /** * Sets up local state for accumulating a fragment shader buffer. @@ -418,36 +603,17 @@ do { \ * \param x maximum number of shader commands that may be used between * a FS_START and FS_END */ -#define FS_LOCALS(x) \ - uint32_t _shader_buf[(x) * 3]; \ - unsigned int _max_shader_commands = x; \ - unsigned int _cur_shader_commands +#define FS_LOCALS() \ + uint32_t _shader_offset #define FS_BEGIN() \ -do { \ - _cur_shader_commands = 0; \ -} while (0) - -#define FS_OUT(_shaderop) \ -do { \ - if (_cur_shader_commands >= _max_shader_commands) \ - FatalError("fragment shader command buffer exceeded (%d)\n", \ - _cur_shader_commands); \ - _shader_buf[_cur_shader_commands * 3 + 0] = _shaderop.ui[0]; \ - _shader_buf[_cur_shader_commands * 3 + 1] = _shaderop.ui[1]; \ - _shader_buf[_cur_shader_commands * 3 + 2] = _shaderop.ui[2]; \ - ++_cur_shader_commands; \ -} while (0) + do { \ + _shader_offset = intel->batch_used++; \ + } while (0) #define FS_END() \ -do { \ - int _i, _pad = (_cur_shader_commands & 0x1) ? 0 : 1; \ - ATOMIC_BATCH(_cur_shader_commands * 3 + 1 + _pad); \ - OUT_BATCH(_3DSTATE_PIXEL_SHADER_PROGRAM | \ - (_cur_shader_commands * 3 - 1)); \ - for (_i = 0; _i < _cur_shader_commands * 3; _i++) \ - OUT_BATCH(_shader_buf[_i]); \ - if (_pad != 0) \ - OUT_BATCH(MI_NOOP); \ - ADVANCE_BATCH(); \ -} while (0); + do { \ + intel->batch_ptr[_shader_offset] = \ + _3DSTATE_PIXEL_SHADER_PROGRAM | \ + (intel->batch_used - _shader_offset - 2); \ + } while (0); diff --git a/src/i915_reg.h b/src/i915_reg.h index a61bc401..746a4131 100644 --- a/src/i915_reg.h +++ b/src/i915_reg.h @@ -32,19 +32,20 @@ #define CMD_3D (0x3<<29) -#define PRIM3D_INLINE (CMD_3D | (0x1f<<24)) -#define PRIM3D_TRILIST (0x0<<18) -#define PRIM3D_TRISTRIP (0x1<<18) -#define PRIM3D_TRISTRIP_RVRSE (0x2<<18) -#define PRIM3D_TRIFAN (0x3<<18) -#define PRIM3D_POLY (0x4<<18) -#define PRIM3D_LINELIST (0x5<<18) -#define PRIM3D_LINESTRIP (0x6<<18) -#define PRIM3D_RECTLIST (0x7<<18) -#define PRIM3D_POINTLIST (0x8<<18) -#define PRIM3D_DIB (0x9<<18) -#define PRIM3D_CLEAR_RECT (0xa<<18) -#define PRIM3D_ZONE_INIT (0xd<<18) +#define PRIM3D (CMD_3D | (0x1f<<24)) +#define PRIM3D_INDIRECT_SEQUENTIAL ((1<<23) | (0<<17)) +#define PRIM3D_TRILIST (PRIM3D | (0x0<<18)) +#define PRIM3D_TRISTRIP (PRIM3D | (0x1<<18)) +#define PRIM3D_TRISTRIP_RVRSE (PRIM3D | (0x2<<18)) +#define PRIM3D_TRIFAN (PRIM3D | (0x3<<18)) +#define PRIM3D_POLY (PRIM3D | (0x4<<18)) +#define PRIM3D_LINELIST (PRIM3D | (0x5<<18)) +#define PRIM3D_LINESTRIP (PRIM3D | (0x6<<18)) +#define PRIM3D_RECTLIST (PRIM3D | (0x7<<18)) +#define PRIM3D_POINTLIST (PRIM3D | (0x8<<18)) +#define PRIM3D_DIB (PRIM3D | (0x9<<18)) +#define PRIM3D_CLEAR_RECT (PRIM3D | (0xa<<18)) +#define PRIM3D_ZONE_INIT (PRIM3D | (0xd<<18)) #define PRIM3D_MASK (0x1f<<18) /* p137 */ diff --git a/src/i915_render.c b/src/i915_render.c index 98b5b88a..53c99142 100644 --- a/src/i915_render.c +++ b/src/i915_render.c @@ -35,8 +35,6 @@ #include "i915_reg.h" #include "i915_3d.h" -#define PIXEL_CENTRE_SAMPLE 0 - struct formatinfo { int fmt; uint32_t card_fmt; @@ -133,8 +131,10 @@ static uint32_t i915_get_blend_cntl(int op, PicturePtr mask, } } - return (sblend << S6_CBUF_SRC_BLEND_FACT_SHIFT) | - (dblend << S6_CBUF_DST_BLEND_FACT_SHIFT); + return S6_CBUF_BLEND_ENABLE | S6_COLOR_WRITE_ENABLE | + (BLENDFUNC_ADD << S6_CBUF_BLEND_FUNC_SHIFT) | + (sblend << S6_CBUF_SRC_BLEND_FACT_SHIFT) | + (dblend << S6_CBUF_DST_BLEND_FACT_SHIFT); } #define DSTORG_HORT_BIAS(x) ((x)<<20) @@ -170,16 +170,72 @@ static Bool i915_get_dest_format(PicturePtr dest_picture, uint32_t * dst_format) (int)dest_picture->format); return FALSE; } -#if PIXEL_CENTRE_SAMPLE *dst_format |= DSTORG_HORT_BIAS(0x8) | DSTORG_VERT_BIAS(0x8); -#endif return TRUE; } -static Bool i915_check_composite_texture(ScrnInfoPtr scrn, PicturePtr picture, - int unit) +Bool +i915_check_composite(int op, + PicturePtr source_picture, + PicturePtr mask_picture, + PicturePtr dest_picture, + int width, int height) +{ + ScrnInfoPtr scrn = xf86Screens[dest_picture->pDrawable->pScreen->myNum]; + uint32_t tmp1; + + /* Check for unsupported compositing operations. */ + if (op >= sizeof(i915_blend_op) / sizeof(i915_blend_op[0])) { + intel_debug_fallback(scrn, "Unsupported Composite op 0x%x\n", + op); + return FALSE; + } + if (mask_picture != NULL && mask_picture->componentAlpha && + PICT_FORMAT_RGB(mask_picture->format)) { + /* Check if it's component alpha that relies on a source alpha + * and on the source value. We can only get one of those + * into the single source value that we get to blend with. + */ + if (i915_blend_op[op].src_alpha && + (i915_blend_op[op].src_blend != BLENDFACT_ZERO)) { + if (op != PictOpOver) { + intel_debug_fallback(scrn, + "Component alpha not supported " + "with source alpha and source " + "value blending.\n"); + return FALSE; + } + } + } + + if (!i915_get_dest_format(dest_picture, &tmp1)) { + intel_debug_fallback(scrn, "Get Color buffer format\n"); + return FALSE; + } + + if (width > 2048 || height > 2048) + return FALSE; + + return TRUE; +} + +Bool +i915_check_composite_target(PixmapPtr pixmap) +{ + if (pixmap->drawable.width > 2048 || pixmap->drawable.height > 2048) + return FALSE; + + if(!intel_check_pitch_3d(pixmap)) + return FALSE; + + return TRUE; +} + +Bool +i915_check_composite_texture(ScreenPtr screen, PicturePtr picture) { if (picture->repeatType > RepeatReflect) { + ScrnInfoPtr scrn = xf86Screens[screen->myNum]; intel_debug_fallback(scrn, "Unsupported picture repeat %d\n", picture->repeatType); return FALSE; @@ -187,17 +243,25 @@ static Bool i915_check_composite_texture(ScrnInfoPtr scrn, PicturePtr picture, if (picture->filter != PictFilterNearest && picture->filter != PictFilterBilinear) { + ScrnInfoPtr scrn = xf86Screens[screen->myNum]; intel_debug_fallback(scrn, "Unsupported filter 0x%x\n", picture->filter); return FALSE; } + if (picture->pSourcePict) { + SourcePict *source = picture->pSourcePict; + if (source->type == SourcePictTypeSolidFill) + return TRUE; + } + if (picture->pDrawable) { int w, h, i; w = picture->pDrawable->width; h = picture->pDrawable->height; if ((w > 2048) || (h > 2048)) { + ScrnInfoPtr scrn = xf86Screens[screen->myNum]; intel_debug_fallback(scrn, "Picture w/h too large (%dx%d)\n", w, h); @@ -212,61 +276,17 @@ static Bool i915_check_composite_texture(ScrnInfoPtr scrn, PicturePtr picture, } if (i == sizeof(i915_tex_formats) / sizeof(i915_tex_formats[0])) { + ScrnInfoPtr scrn = xf86Screens[screen->myNum]; intel_debug_fallback(scrn, "Unsupported picture format " "0x%x\n", (int)picture->format); return FALSE; } - } - - return TRUE; -} - -Bool -i915_check_composite(int op, PicturePtr source_picture, PicturePtr mask_picture, - PicturePtr dest_picture) -{ - ScrnInfoPtr scrn = xf86Screens[dest_picture->pDrawable->pScreen->myNum]; - uint32_t tmp1; - - /* Check for unsupported compositing operations. */ - if (op >= sizeof(i915_blend_op) / sizeof(i915_blend_op[0])) { - intel_debug_fallback(scrn, "Unsupported Composite op 0x%x\n", - op); - return FALSE; - } - if (mask_picture != NULL && mask_picture->componentAlpha && - PICT_FORMAT_RGB(mask_picture->format)) { - /* Check if it's component alpha that relies on a source alpha - * and on the source value. We can only get one of those - * into the single source value that we get to blend with. - */ - if (i915_blend_op[op].src_alpha && - (i915_blend_op[op].src_blend != BLENDFACT_ZERO)) { - intel_debug_fallback(scrn, - "Component alpha not supported " - "with source alpha and source " - "value blending.\n"); - return FALSE; - } - } - if (!i915_check_composite_texture(scrn, source_picture, 0)) { - intel_debug_fallback(scrn, "Check Src picture texture\n"); - return FALSE; - } - if (mask_picture != NULL - && !i915_check_composite_texture(scrn, mask_picture, 1)) { - intel_debug_fallback(scrn, "Check Mask picture texture\n"); - return FALSE; + return TRUE; } - if (!i915_get_dest_format(dest_picture, &tmp1)) { - intel_debug_fallback(scrn, "Get Color buffer format\n"); - return FALSE; - } - - return TRUE; + return FALSE; } static Bool i915_texture_setup(PicturePtr picture, PixmapPtr pixmap, int unit) @@ -280,8 +300,8 @@ static Bool i915_texture_setup(PicturePtr picture, PixmapPtr pixmap, int unit) pitch = intel_get_pixmap_pitch(pixmap); w = picture->pDrawable->width; h = picture->pDrawable->height; - intel->scale_units[unit][0] = pixmap->drawable.width; - intel->scale_units[unit][1] = pixmap->drawable.height; + intel->scale_units[unit][0] = 1. / pixmap->drawable.width; + intel->scale_units[unit][1] = 1. / pixmap->drawable.height; for (i = 0; i < sizeof(i915_tex_formats) / sizeof(i915_tex_formats[0]); i++) { @@ -360,352 +380,161 @@ static Bool i915_texture_setup(PicturePtr picture, PixmapPtr pixmap, int unit) return TRUE; } -Bool -i915_prepare_composite(int op, PicturePtr source_picture, - PicturePtr mask_picture, PicturePtr dest_picture, - PixmapPtr source, PixmapPtr mask, PixmapPtr dest) +static void +i915_emit_composite_primitive_constant(PixmapPtr dest, + int srcX, int srcY, + int maskX, int maskY, + int dstX, int dstY, + int w, int h) { - ScrnInfoPtr scrn = xf86Screens[source_picture->pDrawable->pScreen->myNum]; + ScrnInfoPtr scrn = xf86Screens[dest->drawable.pScreen->myNum]; intel_screen_private *intel = intel_get_screen_private(scrn); - drm_intel_bo *bo_table[] = { - NULL, /* batch_bo */ - i830_get_pixmap_bo(source), - mask ? i830_get_pixmap_bo(mask) : NULL, - i830_get_pixmap_bo(dest), - }; - int tex_unit = 0; - - intel->render_source_picture = source_picture; - intel->render_source = source; - intel->render_mask_picture = mask_picture; - intel->render_mask = mask; - intel->render_dest_picture = dest_picture; - intel->render_dest = dest; - intel->render_source_is_solid = - source_picture->pDrawable && - source_picture->pDrawable->width == 1 && - source_picture->pDrawable->height == 1 && - source_picture->repeat; + OUT_VERTEX(dstX + w); + OUT_VERTEX(dstY + h); - if (intel->render_source_is_solid) { - if (! uxa_get_color_for_pixmap (source, - source_picture->format, - PICT_a8r8g8b8, - &intel->render_source_solid)) - intel->render_source_is_solid = FALSE; - } - if (!intel->render_source_is_solid && !intel_check_pitch_3d(source)) - return FALSE; - - - intel->render_mask_is_solid = TRUE; /* mask == NULL => opaque */ - if (mask) { - intel->render_mask_is_solid = - mask_picture->pDrawable && - mask_picture->pDrawable->width == 1 && - mask_picture->pDrawable->height == 1 && - mask_picture->repeat; - if (intel->render_mask_is_solid) { - if (! uxa_get_color_for_pixmap (mask, - mask_picture->format, - PICT_a8r8g8b8, - &intel->render_mask_solid)) - intel->render_mask_is_solid = FALSE; - } - if (!intel->render_mask_is_solid && !intel_check_pitch_3d(mask)) - return FALSE; - } - - if (!intel_check_pitch_3d(dest)) - return FALSE; + OUT_VERTEX(dstX); + OUT_VERTEX(dstY + h); - if (!i915_get_dest_format(dest_picture, - &intel->i915_render_state.dst_format)) - return FALSE; - - if (!i830_get_aperture_space(scrn, bo_table, ARRAY_SIZE(bo_table))) - return FALSE; - intel->dst_coord_adjust = 0; - intel->src_coord_adjust = 0; - intel->mask_coord_adjust = 0; - - intel->transform[0] = NULL; - intel->scale_units[0][0] = -1; - intel->scale_units[0][1] = -1; - intel->transform[1] = NULL; - intel->scale_units[1][0] = -1; - intel->scale_units[1][1] = -1; - - if (! intel->render_source_is_solid) { - if (!i915_texture_setup(source_picture, source, tex_unit++)) { - intel_debug_fallback(scrn, "fail to setup src texture\n"); - return FALSE; - } - - if (source_picture->filter == PictFilterNearest) { -#if PIXEL_CENTRE_SAMPLE - intel->src_coord_adjust = 0.375; -#else - intel->dst_coord_adjust = -0.125; -#endif - } - } - - if (mask != NULL) { - if (! intel->render_mask_is_solid) { - if (!i915_texture_setup(mask_picture, mask, tex_unit++)) { - intel_debug_fallback(scrn, - "fail to setup mask texture\n"); - return FALSE; - } - - if (mask_picture->filter == PictFilterNearest) { -#if PIXEL_CENTRE_SAMPLE - intel->mask_coord_adjust = 0.375; -#else - intel->dst_coord_adjust = -0.125; -#endif - } - } - } - - intel->i915_render_state.op = op; - - if(i830_uxa_pixmap_is_dirty(source) || - (mask && i830_uxa_pixmap_is_dirty(mask))) - intel_batch_emit_flush(scrn); - - intel->needs_render_state_emit = TRUE; - - return TRUE; + OUT_VERTEX(dstX); + OUT_VERTEX(dstY); } -static void i915_emit_composite_setup(ScrnInfoPtr scrn) +static void +i915_emit_composite_primitive_identity_source(PixmapPtr dest, + int srcX, int srcY, + int maskX, int maskY, + int dstX, int dstY, + int w, int h) { + ScrnInfoPtr scrn = xf86Screens[dest->drawable.pScreen->myNum]; intel_screen_private *intel = intel_get_screen_private(scrn); - int op = intel->i915_render_state.op; - PicturePtr mask_picture = intel->render_mask_picture; - PicturePtr dest_picture = intel->render_dest_picture; - PixmapPtr mask = intel->render_mask; - PixmapPtr dest = intel->render_dest; - uint32_t dst_format = intel->i915_render_state.dst_format, dst_pitch; - uint32_t blendctl, tiling_bits; - Bool is_affine_src, is_affine_mask; - Bool is_solid_src, is_solid_mask; - int tex_count, t; - intel->needs_render_state_emit = FALSE; - - IntelEmitInvarientState(scrn); - intel->last_3d = LAST_3D_RENDER; + OUT_VERTEX(dstX + w); + OUT_VERTEX(dstY + h); + OUT_VERTEX((srcX + w) * intel->scale_units[0][0]); + OUT_VERTEX((srcY + h) * intel->scale_units[0][1]); - dst_pitch = intel_get_pixmap_pitch(dest); - - is_affine_src = i830_transform_is_affine(intel->transform[0]); - is_affine_mask = i830_transform_is_affine(intel->transform[1]); - - is_solid_src = intel->render_source_is_solid; - is_solid_mask = intel->render_mask_is_solid; - - tex_count = 0; - tex_count += ! is_solid_src; - tex_count += mask && ! is_solid_mask; + OUT_VERTEX(dstX); + OUT_VERTEX(dstY + h); + OUT_VERTEX(srcX * intel->scale_units[0][0]); + OUT_VERTEX((srcY + h) * intel->scale_units[0][1]); - t = 15; - if (tex_count) - t += 6 * tex_count + 4; - if (is_solid_src) - t += 2; - if (mask && is_solid_mask) - t += 2; - ATOMIC_BATCH (t); - - if (tex_count != 0) { - OUT_BATCH(_3DSTATE_MAP_STATE | (3 * tex_count)); - OUT_BATCH((1 << tex_count) - 1); - for (t = 0; t < tex_count; t++) { - OUT_RELOC_PIXMAP(intel->texture[t], I915_GEM_DOMAIN_SAMPLER, 0, 0); - OUT_BATCH(intel->mapstate[3*t + 1]); - OUT_BATCH(intel->mapstate[3*t + 2]); - } - - OUT_BATCH(_3DSTATE_SAMPLER_STATE | (3 * tex_count)); - OUT_BATCH((1 << tex_count) - 1); - for (t = 0; t < tex_count; t++) { - OUT_BATCH(intel->samplerstate[3*t + 0]); - OUT_BATCH(intel->samplerstate[3*t + 1]); - OUT_BATCH(intel->samplerstate[3*t + 2]); - } - } - - if (is_solid_src) { - OUT_BATCH (_3DSTATE_DFLT_DIFFUSE_CMD); - OUT_BATCH (intel->render_source_solid); - } - if (mask && is_solid_mask) { - OUT_BATCH (_3DSTATE_DFLT_SPEC_CMD); - OUT_BATCH (intel->render_mask_solid); - } - - if (i830_pixmap_tiled(dest)) { - tiling_bits = BUF_3D_TILED_SURFACE; - if (i830_get_pixmap_intel(dest)->tiling - == I915_TILING_Y) - tiling_bits |= BUF_3D_TILE_WALK_Y; - } else - tiling_bits = 0; - - OUT_BATCH(_3DSTATE_BUF_INFO_CMD); - OUT_BATCH(BUF_3D_ID_COLOR_BACK | tiling_bits | - BUF_3D_PITCH(dst_pitch)); - OUT_RELOC_PIXMAP(dest, I915_GEM_DOMAIN_RENDER, - I915_GEM_DOMAIN_RENDER, 0); - - OUT_BATCH(_3DSTATE_DST_BUF_VARS_CMD); - OUT_BATCH(dst_format); - - { - uint32_t ss2; - - OUT_BATCH(_3DSTATE_LOAD_STATE_IMMEDIATE_1 | I1_LOAD_S(2) | - I1_LOAD_S(4) | I1_LOAD_S(5) | I1_LOAD_S(6) | 3); - ss2 = ~0; - t = 0; - if (! is_solid_src) { - ss2 &= ~S2_TEXCOORD_FMT(t, TEXCOORDFMT_NOT_PRESENT); - ss2 |= S2_TEXCOORD_FMT(t, - is_affine_src ? TEXCOORDFMT_2D : - TEXCOORDFMT_4D); - t++; - } - if (mask && ! is_solid_mask) { - ss2 &= ~S2_TEXCOORD_FMT(t, TEXCOORDFMT_NOT_PRESENT); - ss2 |= S2_TEXCOORD_FMT(t, - is_affine_mask ? TEXCOORDFMT_2D : - TEXCOORDFMT_4D); - t++; - } - OUT_BATCH(ss2); - OUT_BATCH((1 << S4_POINT_WIDTH_SHIFT) | S4_LINE_WIDTH_ONE | - S4_CULLMODE_NONE | S4_VFMT_XY); - blendctl = - i915_get_blend_cntl(op, mask_picture, dest_picture->format); - OUT_BATCH(0x00000000); /* Disable stencil buffer */ - OUT_BATCH(S6_CBUF_BLEND_ENABLE | S6_COLOR_WRITE_ENABLE | - (BLENDFUNC_ADD << S6_CBUF_BLEND_FUNC_SHIFT) | - blendctl); - - /* draw rect is unconditional */ - OUT_BATCH(_3DSTATE_DRAW_RECT_CMD); - OUT_BATCH(0x00000000); - OUT_BATCH(0x00000000); /* ymin, xmin */ - OUT_BATCH(DRAW_YMAX(dest->drawable.height - 1) | - DRAW_XMAX(dest->drawable.width - 1)); - /* yorig, xorig (relate to color buffer?) */ - OUT_BATCH(0x00000000); - } - - ADVANCE_BATCH(); - - { - FS_LOCALS(20); - int src_reg, mask_reg, out_reg = FS_OC; - - FS_BEGIN(); + OUT_VERTEX(dstX); + OUT_VERTEX(dstY); + OUT_VERTEX(srcX * intel->scale_units[0][0]); + OUT_VERTEX(srcY * intel->scale_units[0][1]); +} - if (dst_format == COLR_BUF_8BIT) - out_reg = FS_U0; +static void +i915_emit_composite_primitive_affine_source(PixmapPtr dest, + int srcX, int srcY, + int maskX, int maskY, + int dstX, int dstY, + int w, int h) +{ + ScrnInfoPtr scrn = xf86Screens[dest->drawable.pScreen->myNum]; + intel_screen_private *intel = intel_get_screen_private(scrn); + float src_x[3], src_y[3]; + + if (!i830_get_transformed_coordinates(srcX, srcY, + intel->transform[0], + &src_x[0], + &src_y[0])) + return; + + if (!i830_get_transformed_coordinates(srcX, srcY + h, + intel->transform[0], + &src_x[1], + &src_y[1])) + return; + + if (!i830_get_transformed_coordinates(srcX + w, srcY + h, + intel->transform[0], + &src_x[2], + &src_y[2])) + return; + + OUT_VERTEX(dstX + w); + OUT_VERTEX(dstY + h); + OUT_VERTEX(src_x[2] * intel->scale_units[0][0]); + OUT_VERTEX(src_y[2] * intel->scale_units[0][1]); + + OUT_VERTEX(dstX); + OUT_VERTEX(dstY + h); + OUT_VERTEX(src_x[1] * intel->scale_units[0][0]); + OUT_VERTEX(src_y[1] * intel->scale_units[0][1]); + + OUT_VERTEX(dstX); + OUT_VERTEX(dstY); + OUT_VERTEX(src_x[0] * intel->scale_units[0][0]); + OUT_VERTEX(src_y[0] * intel->scale_units[0][1]); +} - /* Declare the registers necessary for our program. */ - t = 0; - if (is_solid_src) { - i915_fs_dcl(FS_T8); - src_reg = FS_T8; - } else { - i915_fs_dcl(FS_T0); - i915_fs_dcl(FS_S0); - t++; - } - if (mask) { - if (is_solid_mask) { - i915_fs_dcl(FS_T9); - mask_reg = FS_T9; - } else { - i915_fs_dcl(FS_T0 + t); - i915_fs_dcl(FS_S0 + t); - } - } +static void +i915_emit_composite_primitive_constant_identity_mask(PixmapPtr dest, + int srcX, int srcY, + int maskX, int maskY, + int dstX, int dstY, + int w, int h) +{ + ScrnInfoPtr scrn = xf86Screens[dest->drawable.pScreen->myNum]; + intel_screen_private *intel = intel_get_screen_private(scrn); - /* Load the source_picture texel */ - if (! is_solid_src) { - if (is_affine_src) { - i915_fs_texld(FS_R0, FS_S0, FS_T0); - } else { - i915_fs_texldp(FS_R0, FS_S0, FS_T0); - } + OUT_VERTEX(dstX + w); + OUT_VERTEX(dstY + h); + OUT_VERTEX((maskX + w) * intel->scale_units[0][0]); + OUT_VERTEX((maskY + h) * intel->scale_units[0][1]); - src_reg = FS_R0; - } + OUT_VERTEX(dstX); + OUT_VERTEX(dstY + h); + OUT_VERTEX(maskX * intel->scale_units[0][0]); + OUT_VERTEX((maskY + h) * intel->scale_units[0][1]); - if (!mask) { - /* No mask, so move to output color */ - i915_fs_mov(out_reg, i915_fs_operand_reg(src_reg)); - } else { - if (! is_solid_mask) { - /* Load the mask_picture texel */ - if (is_affine_mask) { - i915_fs_texld(FS_R1, FS_S0 + t, FS_T0 + t); - } else { - i915_fs_texldp(FS_R1, FS_S0 + t, FS_T0 + t); - } - - mask_reg = FS_R1; - } + OUT_VERTEX(dstX); + OUT_VERTEX(dstY); + OUT_VERTEX(maskX * intel->scale_units[0][0]); + OUT_VERTEX(maskY * intel->scale_units[0][1]); +} - /* If component alpha is active in the mask and the blend - * operation uses the source alpha, then we know we don't - * need the source value (otherwise we would have hit a - * fallback earlier), so we provide the source alpha (src.A * - * mask.X) as output color. - * Conversely, if CA is set and we don't need the source alpha, - * then we produce the source value (src.X * mask.X) and the - * source alpha is unused. Otherwise, we provide the non-CA - * source value (src.X * mask.A). - */ - if (mask_picture->componentAlpha && - PICT_FORMAT_RGB(mask_picture->format)) { - if (i915_blend_op[op].src_alpha) { - i915_fs_mul(out_reg, - i915_fs_operand(src_reg, W, W, W, W), - i915_fs_operand_reg(mask_reg)); - } else { - i915_fs_mul(out_reg, - i915_fs_operand_reg(src_reg), - i915_fs_operand_reg(mask_reg)); - } - } else { - i915_fs_mul(out_reg, - i915_fs_operand_reg(src_reg), - i915_fs_operand(mask_reg, W, W, W, W)); - } - } - if (dst_format == COLR_BUF_8BIT) - i915_fs_mov(FS_OC, i915_fs_operand(out_reg, W, W, W, W)); +static void +i915_emit_composite_primitive_identity_source_mask(PixmapPtr dest, + int srcX, int srcY, + int maskX, int maskY, + int dstX, int dstY, + int w, int h) +{ + ScrnInfoPtr scrn = xf86Screens[dest->drawable.pScreen->myNum]; + intel_screen_private *intel = intel_get_screen_private(scrn); - FS_END(); - } + OUT_VERTEX(dstX + w); + OUT_VERTEX(dstY + h); + OUT_VERTEX((srcX + w) * intel->scale_units[0][0]); + OUT_VERTEX((srcY + h) * intel->scale_units[0][1]); + OUT_VERTEX((maskX + w) * intel->scale_units[1][0]); + OUT_VERTEX((maskY + h) * intel->scale_units[1][1]); + + OUT_VERTEX(dstX); + OUT_VERTEX(dstY + h); + OUT_VERTEX(srcX * intel->scale_units[0][0]); + OUT_VERTEX((srcY + h) * intel->scale_units[0][1]); + OUT_VERTEX(maskX * intel->scale_units[1][0]); + OUT_VERTEX((maskY + h) * intel->scale_units[1][1]); + + OUT_VERTEX(dstX); + OUT_VERTEX(dstY); + OUT_VERTEX(srcX * intel->scale_units[0][0]); + OUT_VERTEX(srcY * intel->scale_units[0][1]); + OUT_VERTEX(maskX * intel->scale_units[1][0]); + OUT_VERTEX(maskY * intel->scale_units[1][1]); } -/* Emit the vertices for a single composite rectangle. - * - * This function is no longer shared between i830 and i915 generation code. - */ static void i915_emit_composite_primitive(PixmapPtr dest, int srcX, int srcY, int maskX, int maskY, - int dstX, int dstY, int w, int h) + int dstX, int dstY, + int w, int h) { ScrnInfoPtr scrn = xf86Screens[dest->drawable.pScreen->myNum]; intel_screen_private *intel = intel_get_screen_private(scrn); @@ -718,28 +547,25 @@ i915_emit_composite_primitive(PixmapPtr dest, per_vertex = 2; /* dest x/y */ if (! intel->render_source_is_solid) { - float x = srcX + intel->src_coord_adjust; - float y = srcY + intel->src_coord_adjust; - src_unit = tex_unit++; is_affine_src = i830_transform_is_affine(intel->transform[src_unit]); if (is_affine_src) { - if (!i830_get_transformed_coordinates(x, y, + if (!i830_get_transformed_coordinates(srcX, srcY, intel-> transform[src_unit], &src_x[0], &src_y[0])) return; - if (!i830_get_transformed_coordinates(x, y + h, + if (!i830_get_transformed_coordinates(srcX, srcY + h, intel-> transform[src_unit], &src_x[1], &src_y[1])) return; - if (!i830_get_transformed_coordinates(x + w, y + h, + if (!i830_get_transformed_coordinates(srcX + w, srcY + h, intel-> transform[src_unit], &src_x[2], @@ -748,7 +574,7 @@ i915_emit_composite_primitive(PixmapPtr dest, per_vertex += 2; /* src x/y */ } else { - if (!i830_get_transformed_coordinates_3d(x, y, + if (!i830_get_transformed_coordinates_3d(srcX, srcY, intel-> transform[src_unit], &src_x[0], @@ -756,7 +582,7 @@ i915_emit_composite_primitive(PixmapPtr dest, &src_w[0])) return; - if (!i830_get_transformed_coordinates_3d(x, y + h, + if (!i830_get_transformed_coordinates_3d(srcX, srcY + h, intel-> transform[src_unit], &src_x[1], @@ -764,7 +590,7 @@ i915_emit_composite_primitive(PixmapPtr dest, &src_w[1])) return; - if (!i830_get_transformed_coordinates_3d(x + w, y + h, + if (!i830_get_transformed_coordinates_3d(srcX + w, srcY + h, intel-> transform[src_unit], &src_x[2], @@ -777,28 +603,25 @@ i915_emit_composite_primitive(PixmapPtr dest, } if (intel->render_mask && ! intel->render_mask_is_solid) { - float x = maskX + intel->mask_coord_adjust; - float y = maskY + intel->mask_coord_adjust; - mask_unit = tex_unit++; is_affine_mask = i830_transform_is_affine(intel->transform[mask_unit]); if (is_affine_mask) { - if (!i830_get_transformed_coordinates(x, y, + if (!i830_get_transformed_coordinates(maskX, maskY, intel-> transform[mask_unit], &mask_x[0], &mask_y[0])) return; - if (!i830_get_transformed_coordinates(x, y + h, + if (!i830_get_transformed_coordinates(maskX, maskY + h, intel-> transform[mask_unit], &mask_x[1], &mask_y[1])) return; - if (!i830_get_transformed_coordinates(x + w, y + h, + if (!i830_get_transformed_coordinates(maskX + w, maskY + h, intel-> transform[mask_unit], &mask_x[2], @@ -807,7 +630,7 @@ i915_emit_composite_primitive(PixmapPtr dest, per_vertex += 2; /* mask x/y */ } else { - if (!i830_get_transformed_coordinates_3d(x, y, + if (!i830_get_transformed_coordinates_3d(maskX, maskY, intel-> transform[mask_unit], &mask_x[0], @@ -815,7 +638,7 @@ i915_emit_composite_primitive(PixmapPtr dest, &mask_w[0])) return; - if (!i830_get_transformed_coordinates_3d(x, y + h, + if (!i830_get_transformed_coordinates_3d(maskX, maskY + h, intel-> transform[mask_unit], &mask_x[1], @@ -823,7 +646,7 @@ i915_emit_composite_primitive(PixmapPtr dest, &mask_w[1])) return; - if (!i830_get_transformed_coordinates_3d(x + w, y + h, + if (!i830_get_transformed_coordinates_3d(maskX + w, maskY + h, intel-> transform[mask_unit], &mask_x[2], @@ -837,67 +660,444 @@ i915_emit_composite_primitive(PixmapPtr dest, num_floats = 3 * per_vertex; - ATOMIC_BATCH(1 + num_floats); - - OUT_BATCH(PRIM3D_INLINE | PRIM3D_RECTLIST | (num_floats - 1)); - OUT_BATCH_F(intel->dst_coord_adjust + dstX + w); - OUT_BATCH_F(intel->dst_coord_adjust + dstY + h); + OUT_VERTEX(dstX + w); + OUT_VERTEX(dstY + h); if (! intel->render_source_is_solid) { - OUT_BATCH_F(src_x[2] / intel->scale_units[src_unit][0]); - OUT_BATCH_F(src_y[2] / intel->scale_units[src_unit][1]); + OUT_VERTEX(src_x[2] * intel->scale_units[src_unit][0]); + OUT_VERTEX(src_y[2] * intel->scale_units[src_unit][1]); if (!is_affine_src) { - OUT_BATCH_F(0.0); - OUT_BATCH_F(src_w[2]); + OUT_VERTEX(0.0); + OUT_VERTEX(src_w[2]); } } if (intel->render_mask && ! intel->render_mask_is_solid) { - OUT_BATCH_F(mask_x[2] / intel->scale_units[mask_unit][0]); - OUT_BATCH_F(mask_y[2] / intel->scale_units[mask_unit][1]); + OUT_VERTEX(mask_x[2] * intel->scale_units[mask_unit][0]); + OUT_VERTEX(mask_y[2] * intel->scale_units[mask_unit][1]); if (!is_affine_mask) { - OUT_BATCH_F(0.0); - OUT_BATCH_F(mask_w[2]); + OUT_VERTEX(0.0); + OUT_VERTEX(mask_w[2]); } } - OUT_BATCH_F(intel->dst_coord_adjust + dstX); - OUT_BATCH_F(intel->dst_coord_adjust + dstY + h); + OUT_VERTEX(dstX); + OUT_VERTEX(dstY + h); if (! intel->render_source_is_solid) { - OUT_BATCH_F(src_x[1] / intel->scale_units[src_unit][0]); - OUT_BATCH_F(src_y[1] / intel->scale_units[src_unit][1]); + OUT_VERTEX(src_x[1] * intel->scale_units[src_unit][0]); + OUT_VERTEX(src_y[1] * intel->scale_units[src_unit][1]); if (!is_affine_src) { - OUT_BATCH_F(0.0); - OUT_BATCH_F(src_w[1]); + OUT_VERTEX(0.0); + OUT_VERTEX(src_w[1]); } } if (intel->render_mask && ! intel->render_mask_is_solid) { - OUT_BATCH_F(mask_x[1] / intel->scale_units[mask_unit][0]); - OUT_BATCH_F(mask_y[1] / intel->scale_units[mask_unit][1]); + OUT_VERTEX(mask_x[1] * intel->scale_units[mask_unit][0]); + OUT_VERTEX(mask_y[1] * intel->scale_units[mask_unit][1]); if (!is_affine_mask) { - OUT_BATCH_F(0.0); - OUT_BATCH_F(mask_w[1]); + OUT_VERTEX(0.0); + OUT_VERTEX(mask_w[1]); } } - OUT_BATCH_F(intel->dst_coord_adjust + dstX); - OUT_BATCH_F(intel->dst_coord_adjust + dstY); + OUT_VERTEX(dstX); + OUT_VERTEX(dstY); if (! intel->render_source_is_solid) { - OUT_BATCH_F(src_x[0] / intel->scale_units[src_unit][0]); - OUT_BATCH_F(src_y[0] / intel->scale_units[src_unit][1]); + OUT_VERTEX(src_x[0] * intel->scale_units[src_unit][0]); + OUT_VERTEX(src_y[0] * intel->scale_units[src_unit][1]); if (!is_affine_src) { - OUT_BATCH_F(0.0); - OUT_BATCH_F(src_w[0]); + OUT_VERTEX(0.0); + OUT_VERTEX(src_w[0]); } } if (intel->render_mask && ! intel->render_mask_is_solid) { - OUT_BATCH_F(mask_x[0] / intel->scale_units[mask_unit][0]); - OUT_BATCH_F(mask_y[0] / intel->scale_units[mask_unit][1]); + OUT_VERTEX(mask_x[0] * intel->scale_units[mask_unit][0]); + OUT_VERTEX(mask_y[0] * intel->scale_units[mask_unit][1]); if (!is_affine_mask) { - OUT_BATCH_F(0.0); - OUT_BATCH_F(mask_w[0]); + OUT_VERTEX(0.0); + OUT_VERTEX(mask_w[0]); + } + } +} + +Bool +i915_prepare_composite(int op, PicturePtr source_picture, + PicturePtr mask_picture, PicturePtr dest_picture, + PixmapPtr source, PixmapPtr mask, PixmapPtr dest) +{ + ScrnInfoPtr scrn = xf86Screens[dest_picture->pDrawable->pScreen->myNum]; + intel_screen_private *intel = intel_get_screen_private(scrn); + drm_intel_bo *bo_table[] = { + NULL, /* batch_bo */ + i830_get_pixmap_bo(dest), + source ? i830_get_pixmap_bo(source) : NULL, + mask ? i830_get_pixmap_bo(mask) : NULL, + }; + int tex_unit = 0; + int floats_per_vertex; + + intel->render_source_picture = source_picture; + intel->render_source = source; + intel->render_mask_picture = mask_picture; + intel->render_mask = mask; + intel->render_dest_picture = dest_picture; + intel->render_dest = dest; + + intel->render_source_is_solid = FALSE; + if (source_picture->pSourcePict) { + SourcePict *source = source_picture->pSourcePict; + if (source->type == SourcePictTypeSolidFill) { + intel->render_source_is_solid = TRUE; + intel->render_source_solid = source->solidFill.color; + } + } + if (!intel->render_source_is_solid && !intel_check_pitch_3d(source)) + return FALSE; + + intel->render_mask_is_solid = FALSE; + if (mask) { + if (mask_picture->pSourcePict) { + SourcePict *source = mask_picture->pSourcePict; + if (source->type == SourcePictTypeSolidFill) { + intel->render_mask_is_solid = TRUE; + intel->render_mask_solid = source->solidFill.color; + } + } + if (!intel->render_mask_is_solid && !intel_check_pitch_3d(mask)) + return FALSE; + } + + if (!intel_check_pitch_3d(dest)) + return FALSE; + + if (!i915_get_dest_format(dest_picture, + &intel->i915_render_state.dst_format)) + return FALSE; + + if (!i830_get_aperture_space(scrn, bo_table, ARRAY_SIZE(bo_table))) + return FALSE; + + intel->needs_render_ca_pass = FALSE; + if (mask_picture != NULL && mask_picture->componentAlpha && + PICT_FORMAT_RGB(mask_picture->format)) { + /* Check if it's component alpha that relies on a source alpha + * and on the source value. We can only get one of those + * into the single source value that we get to blend with. + */ + if (i915_blend_op[op].src_alpha && + (i915_blend_op[op].src_blend != BLENDFACT_ZERO)) { + if (op != PictOpOver) + return FALSE; + + intel->needs_render_ca_pass = TRUE; + } + } + + intel->transform[0] = NULL; + intel->scale_units[0][0] = -1; + intel->scale_units[0][1] = -1; + intel->transform[1] = NULL; + intel->scale_units[1][0] = -1; + intel->scale_units[1][1] = -1; + + floats_per_vertex = 2; /* dest x/y */ + if (! intel->render_source_is_solid) { + if (!i915_texture_setup(source_picture, source, tex_unit++)) { + intel_debug_fallback(scrn, "fail to setup src texture\n"); + return FALSE; + } + + if (i830_transform_is_affine(source_picture->transform)) + floats_per_vertex += 2; /* src x/y */ + else + floats_per_vertex += 4; /* src x/y/z/w */ + } + + if (mask != NULL) { + if (! intel->render_mask_is_solid) { + if (!i915_texture_setup(mask_picture, mask, tex_unit++)) { + intel_debug_fallback(scrn, + "fail to setup mask texture\n"); + return FALSE; + } + + if (i830_transform_is_affine(mask_picture->transform)) + floats_per_vertex += 2; /* mask x/y */ + else + floats_per_vertex += 4; /* mask x/y/z/w */ } } - ADVANCE_BATCH(); + intel->i915_render_state.op = op; + + /* BUF_INFO is an implicit flush */ + if (dest != intel->render_current_dest) + intel_batch_do_flush(scrn); + else if((source && i830_uxa_pixmap_is_dirty(source)) || + (mask && i830_uxa_pixmap_is_dirty(mask))) + intel_batch_emit_flush(scrn); + + intel->needs_render_state_emit = TRUE; + + intel->prim_emit = i915_emit_composite_primitive; + if (!mask) { + if (intel->render_source_is_solid) + intel->prim_emit = i915_emit_composite_primitive_constant; + else if (intel->transform[0] == NULL) + intel->prim_emit = i915_emit_composite_primitive_identity_source; + else if (i830_transform_is_affine(intel->transform[0])) + intel->prim_emit = i915_emit_composite_primitive_affine_source; + } else { + if (intel->transform[0] == NULL) { + if (intel->render_source_is_solid) + intel->prim_emit = i915_emit_composite_primitive_constant_identity_mask; + else if (intel->transform[1] == NULL) + intel->prim_emit = i915_emit_composite_primitive_identity_source_mask; + } + } + + if (floats_per_vertex != intel->floats_per_vertex) { + intel->floats_per_vertex = floats_per_vertex; + intel->needs_render_vertex_emit = TRUE; + } + + return TRUE; +} + +static void +i915_composite_emit_shader(intel_screen_private *intel, CARD8 op) +{ + PicturePtr mask_picture = intel->render_mask_picture; + PixmapPtr mask = intel->render_mask; + int src_reg, mask_reg; + Bool is_solid_src, is_solid_mask; + Bool dest_is_alpha = PIXMAN_FORMAT_RGB(intel->render_dest_picture->format) == 0; + int tex_unit, t; + FS_LOCALS(); + + is_solid_src = intel->render_source_is_solid; + is_solid_mask = intel->render_mask_is_solid; + + FS_BEGIN(); + + /* Declare the registers necessary for our program. */ + t = 0; + if (is_solid_src) { + i915_fs_dcl(FS_T8); + src_reg = FS_T8; + } else { + i915_fs_dcl(FS_T0); + i915_fs_dcl(FS_S0); + t++; + } + if (!mask) { + /* No mask, so load directly to output color */ + if (! is_solid_src) { + if (dest_is_alpha) + src_reg = FS_R0; + else + src_reg = FS_OC; + + if (i830_transform_is_affine(intel->transform[0])) + i915_fs_texld(src_reg, FS_S0, FS_T0); + else + i915_fs_texldp(src_reg, FS_S0, FS_T0); + } + + if (src_reg != FS_OC) { + if (dest_is_alpha) + i915_fs_mov(FS_OC, i915_fs_operand(src_reg, W, W, W, W)); + else + i915_fs_mov(FS_OC, i915_fs_operand_reg(src_reg)); + } + } else { + if (is_solid_mask) { + i915_fs_dcl(FS_T9); + mask_reg = FS_T9; + } else { + i915_fs_dcl(FS_T0 + t); + i915_fs_dcl(FS_S0 + t); + } + + tex_unit = 0; + if (! is_solid_src) { + /* Load the source_picture texel */ + if (i830_transform_is_affine(intel->transform[tex_unit])) + i915_fs_texld(FS_R0, FS_S0, FS_T0); + else + i915_fs_texldp(FS_R0, FS_S0, FS_T0); + + src_reg = FS_R0; + tex_unit++; + } + + if (! is_solid_mask) { + /* Load the mask_picture texel */ + if (i830_transform_is_affine(intel->transform[tex_unit])) + i915_fs_texld(FS_R1, FS_S0 + t, FS_T0 + t); + else + i915_fs_texldp(FS_R1, FS_S0 + t, FS_T0 + t); + + mask_reg = FS_R1; + } + + if (dest_is_alpha) { + i915_fs_mul(FS_OC, + i915_fs_operand(src_reg, W, W, W, W), + i915_fs_operand(mask_reg, W, W, W, W)); + } else { + /* If component alpha is active in the mask and the blend + * operation uses the source alpha, then we know we don't + * need the source value (otherwise we would have hit a + * fallback earlier), so we provide the source alpha (src.A * + * mask.X) as output color. + * Conversely, if CA is set and we don't need the source alpha, + * then we produce the source value (src.X * mask.X) and the + * source alpha is unused. Otherwise, we provide the non-CA + * source value (src.X * mask.A). + */ + if (mask_picture->componentAlpha && + PICT_FORMAT_RGB(mask_picture->format)) { + if (i915_blend_op[op].src_alpha) { + i915_fs_mul(FS_OC, + i915_fs_operand(src_reg, W, W, W, W), + i915_fs_operand_reg(mask_reg)); + } else { + i915_fs_mul(FS_OC, + i915_fs_operand_reg(src_reg), + i915_fs_operand_reg(mask_reg)); + } + } else { + i915_fs_mul(FS_OC, + i915_fs_operand_reg(src_reg), + i915_fs_operand(mask_reg, W, W, W, W)); + } + } + } + + FS_END(); +} + +static void i915_emit_composite_setup(ScrnInfoPtr scrn) +{ + intel_screen_private *intel = intel_get_screen_private(scrn); + int op = intel->i915_render_state.op; + PicturePtr mask_picture = intel->render_mask_picture; + PicturePtr dest_picture = intel->render_dest_picture; + PixmapPtr mask = intel->render_mask; + PixmapPtr dest = intel->render_dest; + Bool is_solid_src, is_solid_mask; + int tex_count, t; + + intel->needs_render_state_emit = FALSE; + + IntelEmitInvarientState(scrn); + intel->last_3d = LAST_3D_RENDER; + + is_solid_src = intel->render_source_is_solid; + is_solid_mask = intel->render_mask_is_solid; + + tex_count = 0; + tex_count += ! is_solid_src; + tex_count += mask && ! is_solid_mask; + + assert(intel->in_batch_atomic); + + if (tex_count != 0) { + OUT_BATCH(_3DSTATE_MAP_STATE | (3 * tex_count)); + OUT_BATCH((1 << tex_count) - 1); + for (t = 0; t < tex_count; t++) { + OUT_RELOC_PIXMAP(intel->texture[t], I915_GEM_DOMAIN_SAMPLER, 0, 0); + OUT_BATCH(intel->mapstate[3*t + 1]); + OUT_BATCH(intel->mapstate[3*t + 2]); + } + + OUT_BATCH(_3DSTATE_SAMPLER_STATE | (3 * tex_count)); + OUT_BATCH((1 << tex_count) - 1); + for (t = 0; t < tex_count; t++) { + OUT_BATCH(intel->samplerstate[3*t + 0]); + OUT_BATCH(intel->samplerstate[3*t + 1]); + OUT_BATCH(intel->samplerstate[3*t + 2]); + } + } + + if (is_solid_src) { + OUT_BATCH (_3DSTATE_DFLT_DIFFUSE_CMD); + OUT_BATCH (intel->render_source_solid); + } + if (mask && is_solid_mask) { + OUT_BATCH (_3DSTATE_DFLT_SPEC_CMD); + OUT_BATCH (intel->render_mask_solid); + } + + /* BUF_INFO is an implicit flush, so avoid if the target has not changed. + * XXX However for reasons unfathomed, correct rendering in KDE requires + * at least a MI_FLUSH | INHIBIT_RENDER_CACHE_FLUSH here. + */ + if (1 || dest != intel->render_current_dest) { + uint32_t tiling_bits; + + intel_batch_do_flush(scrn); + + if (i830_pixmap_tiled(dest)) { + tiling_bits = BUF_3D_TILED_SURFACE; + if (i830_get_pixmap_intel(dest)->tiling + == I915_TILING_Y) + tiling_bits |= BUF_3D_TILE_WALK_Y; + } else + tiling_bits = 0; + + OUT_BATCH(_3DSTATE_BUF_INFO_CMD); + OUT_BATCH(BUF_3D_ID_COLOR_BACK | tiling_bits | + BUF_3D_PITCH(intel_get_pixmap_pitch(dest))); + OUT_RELOC_PIXMAP(dest, I915_GEM_DOMAIN_RENDER, + I915_GEM_DOMAIN_RENDER, 0); + + OUT_BATCH(_3DSTATE_DST_BUF_VARS_CMD); + OUT_BATCH(intel->i915_render_state.dst_format); + + /* draw rect is unconditional */ + OUT_BATCH(_3DSTATE_DRAW_RECT_CMD); + OUT_BATCH(0x00000000); + OUT_BATCH(0x00000000); /* ymin, xmin */ + OUT_BATCH(DRAW_YMAX(dest->drawable.height - 1) | + DRAW_XMAX(dest->drawable.width - 1)); + /* yorig, xorig (relate to color buffer?) */ + OUT_BATCH(0x00000000); + + intel->render_current_dest = dest; + } + + { + uint32_t ss2; + + ss2 = ~0; + t = 0; + if (! is_solid_src) { + ss2 &= ~S2_TEXCOORD_FMT(t, TEXCOORDFMT_NOT_PRESENT); + ss2 |= S2_TEXCOORD_FMT(t, + i830_transform_is_affine(intel->transform[t]) ? + TEXCOORDFMT_2D : TEXCOORDFMT_4D); + t++; + } + if (mask && ! is_solid_mask) { + ss2 &= ~S2_TEXCOORD_FMT(t, TEXCOORDFMT_NOT_PRESENT); + ss2 |= S2_TEXCOORD_FMT(t, + i830_transform_is_affine(intel->transform[t]) ? + TEXCOORDFMT_2D : TEXCOORDFMT_4D); + t++; + } + + if (intel->needs_render_ca_pass) { + OUT_BATCH(_3DSTATE_LOAD_STATE_IMMEDIATE_1 | I1_LOAD_S(2) | 0); + OUT_BATCH(ss2); + } else { + OUT_BATCH(_3DSTATE_LOAD_STATE_IMMEDIATE_1 | I1_LOAD_S(2) | I1_LOAD_S(6) | 1); + OUT_BATCH(ss2); + OUT_BATCH(i915_get_blend_cntl(op, mask_picture, dest_picture->format)); + } + } + + if (! intel->needs_render_ca_pass) + i915_composite_emit_shader(intel, op); } void @@ -913,15 +1113,87 @@ i915_composite(PixmapPtr dest, int srcX, int srcY, int maskX, int maskY, if (intel->needs_render_state_emit) i915_emit_composite_setup(scrn); - i915_emit_composite_primitive(dest, srcX, srcY, maskX, maskY, dstX, - dstY, w, h); + if (intel->needs_render_vertex_emit || + intel_vertex_space(intel) < 3*4*intel->floats_per_vertex) { + i915_vertex_flush(intel); + + if (intel_vertex_space(intel) < 256) { + intel_next_vertex(intel); + + OUT_BATCH(_3DSTATE_LOAD_STATE_IMMEDIATE_1 | + I1_LOAD_S(0) | I1_LOAD_S(1) | 1); + OUT_RELOC(intel->vertex_bo, I915_GEM_DOMAIN_VERTEX, 0, 0); + OUT_BATCH((intel->floats_per_vertex << S1_VERTEX_WIDTH_SHIFT) | + (intel->floats_per_vertex << S1_VERTEX_PITCH_SHIFT)); + intel->vertex_index = 0; + } else if (intel->floats_per_vertex != intel->last_floats_per_vertex){ + OUT_BATCH(_3DSTATE_LOAD_STATE_IMMEDIATE_1 | + I1_LOAD_S(1) | 0); + OUT_BATCH((intel->floats_per_vertex << S1_VERTEX_WIDTH_SHIFT) | + (intel->floats_per_vertex << S1_VERTEX_PITCH_SHIFT)); + + intel->vertex_index = + (intel->vertex_used + intel->floats_per_vertex - 1) / intel->floats_per_vertex; + intel->vertex_used = intel->vertex_index * intel->floats_per_vertex; + } + + intel->last_floats_per_vertex = intel->floats_per_vertex; + intel->needs_render_vertex_emit = FALSE; + } + + if (intel->prim_offset == 0) { + if (intel->needs_render_ca_pass) { + OUT_BATCH(_3DSTATE_LOAD_STATE_IMMEDIATE_1 | I1_LOAD_S(6) | 0); + OUT_BATCH(i915_get_blend_cntl(PictOpOutReverse, + intel->render_mask_picture, + intel->render_dest_picture->format)); + i915_composite_emit_shader(intel, PictOpOutReverse); + } + + intel->prim_offset = intel->batch_used; + OUT_BATCH(PRIM3D_RECTLIST | PRIM3D_INDIRECT_SEQUENTIAL); + OUT_BATCH(intel->vertex_index); + } + intel->vertex_count += 3; + + intel->prim_emit(dest, + srcX, srcY, + maskX, maskY, + dstX, dstY, + w, h); intel_batch_end_atomic(scrn); } -void i915_batch_flush_notify(ScrnInfoPtr scrn) +void +i915_vertex_flush(intel_screen_private *intel) +{ + if (intel->prim_offset == 0) + return; + + intel->batch_ptr[intel->prim_offset] |= intel->vertex_count; + intel->prim_offset = 0; + + if (intel->needs_render_ca_pass) { + OUT_BATCH(_3DSTATE_LOAD_STATE_IMMEDIATE_1 | I1_LOAD_S(6) | 0); + OUT_BATCH(i915_get_blend_cntl(PictOpAdd, + intel->render_mask_picture, + intel->render_dest_picture->format)); + i915_composite_emit_shader(intel, PictOpAdd); + OUT_BATCH(PRIM3D_RECTLIST | PRIM3D_INDIRECT_SEQUENTIAL | intel->vertex_count); + OUT_BATCH(intel->vertex_index); + } + + intel->vertex_index += intel->vertex_count; + intel->vertex_count = 0; +} + +void +i915_batch_flush_notify(ScrnInfoPtr scrn) { intel_screen_private *intel = intel_get_screen_private(scrn); intel->needs_render_state_emit = TRUE; + intel->render_current_dest = NULL; + intel->last_floats_per_vertex = 0; } diff --git a/src/i915_video.c b/src/i915_video.c index 927047be..893855bd 100644 --- a/src/i915_video.c +++ b/src/i915_video.c @@ -49,17 +49,47 @@ I915DisplayVideoTextured(ScrnInfoPtr scrn, PixmapPtr pixmap) { intel_screen_private *intel = intel_get_screen_private(scrn); - uint32_t format, ms3, s5; + uint32_t format, ms3, s5, tiling; BoxPtr pbox = REGION_RECTS(dstRegion); int nbox_total = REGION_NUM_RECTS(dstRegion); int nbox_this_time; int dxo, dyo, pix_xoff, pix_yoff; + PixmapPtr target; #if 0 ErrorF("I915DisplayVideo: %dx%d (pitch %d)\n", width, height, video_pitch); #endif + dxo = dstRegion->extents.x1; + dyo = dstRegion->extents.y1; + + if (pixmap->drawable.width > 2048 || pixmap->drawable.height > 2048 || + !intel_check_pitch_3d(pixmap)) { + ScreenPtr screen = pixmap->drawable.pScreen; + + target = screen->CreatePixmap(screen, + drw_w, drw_h, + pixmap->drawable.depth, + CREATE_PIXMAP_USAGE_SCRATCH); + + pix_xoff = -dxo; + pix_yoff = -dyo; + } else { + target = pixmap; + + /* Set up the offset for translating from the given region + * (in screen coordinates) to the backing pixmap. + */ +#ifdef COMPOSITE + pix_xoff = -target->screen_x + target->drawable.x; + pix_yoff = -target->screen_y + target->drawable.y; +#else + pix_xoff = 0; + pix_yoff = 0; +#endif + } + #define BYTES_FOR_BOXES(n) ((200 + (n) * 20) * 4) #define BOXES_IN_BYTES(s) ((((s)/4) - 200) / 20) #define BATCH_BYTES(p) ((p)->batch_bo->size - 16) @@ -75,26 +105,18 @@ I915DisplayVideoTextured(ScrnInfoPtr scrn, IntelEmitInvarientState(scrn); intel->last_3d = LAST_3D_VIDEO; - ATOMIC_BATCH(20); - - /* flush map & render cache */ - OUT_BATCH(MI_FLUSH | MI_WRITE_DIRTY_STATE | - MI_INVALIDATE_MAP_CACHE); - OUT_BATCH(0x00000000); - /* draw rect -- just clipping */ OUT_BATCH(_3DSTATE_DRAW_RECT_CMD); OUT_BATCH(DRAW_DITHER_OFS_X(pixmap->drawable.x & 3) | DRAW_DITHER_OFS_Y(pixmap->drawable.y & 3)); OUT_BATCH(0x00000000); /* ymin, xmin */ /* ymax, xmax */ - OUT_BATCH((pixmap->drawable.width - 1) | - (pixmap->drawable.height - 1) << 16); + OUT_BATCH((target->drawable.width - 1) | + (target->drawable.height - 1) << 16); OUT_BATCH(0x00000000); /* yorigin, xorigin */ - OUT_BATCH(MI_NOOP); OUT_BATCH(_3DSTATE_LOAD_STATE_IMMEDIATE_1 | I1_LOAD_S(2) | - I1_LOAD_S(4) | I1_LOAD_S(5) | I1_LOAD_S(6) | 3); + I1_LOAD_S(5) | I1_LOAD_S(6) | 2); OUT_BATCH(S2_TEXCOORD_FMT(0, TEXCOORDFMT_2D) | S2_TEXCOORD_FMT(1, TEXCOORDFMT_NOT_PRESENT) | S2_TEXCOORD_FMT(2, TEXCOORDFMT_NOT_PRESENT) | @@ -103,8 +125,6 @@ I915DisplayVideoTextured(ScrnInfoPtr scrn, S2_TEXCOORD_FMT(5, TEXCOORDFMT_NOT_PRESENT) | S2_TEXCOORD_FMT(6, TEXCOORDFMT_NOT_PRESENT) | S2_TEXCOORD_FMT(7, TEXCOORDFMT_NOT_PRESENT)); - OUT_BATCH((1 << S4_POINT_WIDTH_SHIFT) | S4_LINE_WIDTH_ONE | - S4_CULLMODE_NONE | S4_VFMT_XY); s5 = 0x0; if (intel->cpp == 2) s5 |= S5_COLOR_DITHER_ENABLE; @@ -129,17 +149,21 @@ I915DisplayVideoTextured(ScrnInfoPtr scrn, DSTORG_VERT_BIAS(0x8) | format); /* front buffer, pitch, offset */ + if (i830_pixmap_tiled(target)) { + tiling = BUF_3D_TILED_SURFACE; + if (i830_get_pixmap_intel(target)->tiling == I915_TILING_Y) + tiling |= BUF_3D_TILE_WALK_Y; + } else + tiling = 0; OUT_BATCH(_3DSTATE_BUF_INFO_CMD); - OUT_BATCH(BUF_3D_ID_COLOR_BACK | BUF_3D_USE_FENCE | - BUF_3D_PITCH(intel_get_pixmap_pitch(pixmap))); - OUT_RELOC_PIXMAP(pixmap, I915_GEM_DOMAIN_RENDER, + OUT_BATCH(BUF_3D_ID_COLOR_BACK | tiling | + BUF_3D_PITCH(intel_get_pixmap_pitch(target))); + OUT_RELOC_PIXMAP(target, I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER, 0); - ADVANCE_BATCH(); if (!is_planar_fourcc(id)) { - FS_LOCALS(10); + FS_LOCALS(); - ATOMIC_BATCH(16); OUT_BATCH(_3DSTATE_PIXEL_SHADER_CONSTANTS | 4); OUT_BATCH(0x0000001); /* constant 0 */ /* constant 0: brightness/contrast */ @@ -170,7 +194,7 @@ I915DisplayVideoTextured(ScrnInfoPtr scrn, else OUT_BATCH(adaptor_priv->YBufOffset); - ms3 = MAPSURF_422 | MS3_USE_FENCE_REGS; + ms3 = MAPSURF_422; switch (id) { case FOURCC_YUY2: ms3 |= MT_422_YCRCB_NORMAL; @@ -184,8 +208,6 @@ I915DisplayVideoTextured(ScrnInfoPtr scrn, OUT_BATCH(ms3); OUT_BATCH(((video_pitch / 4) - 1) << MS4_PITCH_SHIFT); - ADVANCE_BATCH(); - FS_BEGIN(); i915_fs_dcl(FS_S0); i915_fs_dcl(FS_T0); @@ -198,9 +220,8 @@ I915DisplayVideoTextured(ScrnInfoPtr scrn, } FS_END(); } else { - FS_LOCALS(16); + FS_LOCALS(); - ATOMIC_BATCH(22 + 11 + 11); /* For the planar formats, we set up three samplers -- * one for each plane, in a Y8 format. Because I * couldn't get the special PLANAR_TO_PACKED @@ -292,7 +313,7 @@ I915DisplayVideoTextured(ScrnInfoPtr scrn, else OUT_BATCH(adaptor_priv->YBufOffset); - ms3 = MAPSURF_8BIT | MT_8BIT_I8 | MS3_USE_FENCE_REGS; + ms3 = MAPSURF_8BIT | MT_8BIT_I8; ms3 |= (height - 1) << MS3_HEIGHT_SHIFT; ms3 |= (width - 1) << MS3_WIDTH_SHIFT; OUT_BATCH(ms3); @@ -314,7 +335,7 @@ I915DisplayVideoTextured(ScrnInfoPtr scrn, else OUT_BATCH(adaptor_priv->UBufOffset); - ms3 = MAPSURF_8BIT | MT_8BIT_I8 | MS3_USE_FENCE_REGS; + ms3 = MAPSURF_8BIT | MT_8BIT_I8; ms3 |= (height / 2 - 1) << MS3_HEIGHT_SHIFT; ms3 |= (width / 2 - 1) << MS3_WIDTH_SHIFT; OUT_BATCH(ms3); @@ -327,12 +348,11 @@ I915DisplayVideoTextured(ScrnInfoPtr scrn, else OUT_BATCH(adaptor_priv->VBufOffset); - ms3 = MAPSURF_8BIT | MT_8BIT_I8 | MS3_USE_FENCE_REGS; + ms3 = MAPSURF_8BIT | MT_8BIT_I8; ms3 |= (height / 2 - 1) << MS3_HEIGHT_SHIFT; ms3 |= (width / 2 - 1) << MS3_WIDTH_SHIFT; OUT_BATCH(ms3); OUT_BATCH(((video_pitch / 4) - 1) << MS4_PITCH_SHIFT); - ADVANCE_BATCH(); FS_BEGIN(); /* Declare samplers */ @@ -365,15 +385,15 @@ I915DisplayVideoTextured(ScrnInfoPtr scrn, * color. The OC results are implicitly clamped * at the end of the program. */ - i915_fs_dp3_masked(FS_OC, MASK_X, - i915_fs_operand_reg(FS_R0), - i915_fs_operand_reg(FS_C1)); - i915_fs_dp3_masked(FS_OC, MASK_Y, - i915_fs_operand_reg(FS_R0), - i915_fs_operand_reg(FS_C2)); - i915_fs_dp3_masked(FS_OC, MASK_Z, - i915_fs_operand_reg(FS_R0), - i915_fs_operand_reg(FS_C3)); + i915_fs_dp3(FS_OC, MASK_X, + i915_fs_operand_reg(FS_R0), + i915_fs_operand_reg(FS_C1)); + i915_fs_dp3(FS_OC, MASK_Y, + i915_fs_operand_reg(FS_R0), + i915_fs_operand_reg(FS_C2)); + i915_fs_dp3(FS_OC, MASK_Z, + i915_fs_operand_reg(FS_R0), + i915_fs_operand_reg(FS_C3)); /* Set alpha of the output to 1.0, by wiring W to 1 * and not actually using the source. */ @@ -389,28 +409,7 @@ I915DisplayVideoTextured(ScrnInfoPtr scrn, FS_END(); } - { - ATOMIC_BATCH(2); - OUT_BATCH(MI_FLUSH | MI_WRITE_DIRTY_STATE | - MI_INVALIDATE_MAP_CACHE); - OUT_BATCH(0x00000000); - ADVANCE_BATCH(); - } - - /* Set up the offset for translating from the given region - * (in screen coordinates) to the backing pixmap. - */ -#ifdef COMPOSITE - pix_xoff = -pixmap->screen_x + pixmap->drawable.x; - pix_yoff = -pixmap->screen_y + pixmap->drawable.y; -#else - pix_xoff = 0; - pix_yoff = 0; -#endif - - dxo = dstRegion->extents.x1; - dyo = dstRegion->extents.y1; - + OUT_BATCH(PRIM3D_RECTLIST | (12 * nbox_this_time - 1)); while (nbox_this_time--) { int box_x1 = pbox->x1; int box_y1 = pbox->y1; @@ -423,19 +422,9 @@ I915DisplayVideoTextured(ScrnInfoPtr scrn, src_scale_x = ((float)src_w / width) / drw_w; src_scale_y = ((float)src_h / height) / drw_h; - ATOMIC_BATCH(8 + 12); - OUT_BATCH(MI_NOOP); - OUT_BATCH(MI_NOOP); - OUT_BATCH(MI_NOOP); - OUT_BATCH(MI_NOOP); - OUT_BATCH(MI_NOOP); - OUT_BATCH(MI_NOOP); - OUT_BATCH(MI_NOOP); - /* vertex data - rect list consists of bottom right, * bottom left, and top left vertices. */ - OUT_BATCH(PRIM3D_INLINE | PRIM3D_RECTLIST | (12 - 1)); /* bottom right */ OUT_BATCH_F(box_x2 + pix_xoff); @@ -454,12 +443,39 @@ I915DisplayVideoTextured(ScrnInfoPtr scrn, OUT_BATCH_F(box_y1 + pix_yoff); OUT_BATCH_F((box_x1 - dxo) * src_scale_x); OUT_BATCH_F((box_y1 - dyo) * src_scale_y); - - ADVANCE_BATCH(); } intel_batch_end_atomic(scrn); } + if (target != pixmap) { + GCPtr gc; + + gc = GetScratchGC(pixmap->drawable.depth, + pixmap->drawable.pScreen); + if (gc) { + RegionPtr tmp; + + ValidateGC(&pixmap->drawable, gc); + + if (REGION_NUM_RECTS(dstRegion) > 1) { + tmp = REGION_CREATE(pixmap->drawable.pScreen, NULL, 0); + if (tmp) { + REGION_COPY(pixmap->drawable.pScreen, tmp, dstRegion); + gc->funcs->ChangeClip(gc, CT_REGION, tmp, 0); + } + } + + gc->ops->CopyArea(&target->drawable, &pixmap->drawable, gc, + 0, 0, + target->drawable.width, + target->drawable.height, + -pix_xoff, -pix_yoff); + FreeScratchGC(gc); + } + + target->drawable.pScreen->DestroyPixmap(target); + } + i830_debug_flush(scrn); } diff --git a/src/i965_render.c b/src/i965_render.c index 7866dd75..75d63807 100644 --- a/src/i965_render.c +++ b/src/i965_render.c @@ -183,10 +183,52 @@ static Bool i965_get_dest_format(PicturePtr dest_picture, uint32_t * dst_format) return TRUE; } -static Bool i965_check_composite_texture(ScrnInfoPtr scrn, PicturePtr picture, - int unit) +Bool +i965_check_composite(int op, + PicturePtr source_picture, + PicturePtr mask_picture, + PicturePtr dest_picture, + int width, int height) +{ + ScrnInfoPtr scrn = xf86Screens[dest_picture->pDrawable->pScreen->myNum]; + uint32_t tmp1; + + /* Check for unsupported compositing operations. */ + if (op >= sizeof(i965_blend_op) / sizeof(i965_blend_op[0])) { + intel_debug_fallback(scrn, + "Unsupported Composite op 0x%x\n", op); + return FALSE; + } + + if (mask_picture && mask_picture->componentAlpha && + PICT_FORMAT_RGB(mask_picture->format)) { + /* Check if it's component alpha that relies on a source alpha and on + * the source value. We can only get one of those into the single + * source value that we get to blend with. + */ + if (i965_blend_op[op].src_alpha && + (i965_blend_op[op].src_blend != BRW_BLENDFACTOR_ZERO)) { + intel_debug_fallback(scrn, + "Component alpha not supported " + "with source alpha and source " + "value blending.\n"); + return FALSE; + } + } + + if (!i965_get_dest_format(dest_picture, &tmp1)) { + intel_debug_fallback(scrn, "Get Color buffer format\n"); + return FALSE; + } + + return TRUE; +} + +Bool +i965_check_composite_texture(ScreenPtr screen, PicturePtr picture) { if (picture->repeatType > RepeatReflect) { + ScrnInfoPtr scrn = xf86Screens[screen->myNum]; intel_debug_fallback(scrn, "extended repeat (%d) not supported\n", picture->repeatType); @@ -195,6 +237,7 @@ static Bool i965_check_composite_texture(ScrnInfoPtr scrn, PicturePtr picture, if (picture->filter != PictFilterNearest && picture->filter != PictFilterBilinear) { + ScrnInfoPtr scrn = xf86Screens[screen->myNum]; intel_debug_fallback(scrn, "Unsupported filter 0x%x\n", picture->filter); return FALSE; @@ -206,6 +249,7 @@ static Bool i965_check_composite_texture(ScrnInfoPtr scrn, PicturePtr picture, w = picture->pDrawable->width; h = picture->pDrawable->height; if ((w > 8192) || (h > 8192)) { + ScrnInfoPtr scrn = xf86Screens[screen->myNum]; intel_debug_fallback(scrn, "Picture w/h too large (%dx%d)\n", w, h); @@ -220,66 +264,21 @@ static Bool i965_check_composite_texture(ScrnInfoPtr scrn, PicturePtr picture, } if (i == sizeof(i965_tex_formats) / sizeof(i965_tex_formats[0])) { + ScrnInfoPtr scrn = xf86Screens[screen->myNum]; intel_debug_fallback(scrn, "Unsupported picture format " "0x%x\n", (int)picture->format); return FALSE; } - } - - return TRUE; -} - -Bool -i965_check_composite(int op, PicturePtr source_picture, PicturePtr mask_picture, - PicturePtr dest_picture) -{ - ScrnInfoPtr scrn = xf86Screens[dest_picture->pDrawable->pScreen->myNum]; - uint32_t tmp1; - - /* Check for unsupported compositing operations. */ - if (op >= sizeof(i965_blend_op) / sizeof(i965_blend_op[0])) { - intel_debug_fallback(scrn, - "Unsupported Composite op 0x%x\n", op); - return FALSE; - } - - if (mask_picture && mask_picture->componentAlpha && - PICT_FORMAT_RGB(mask_picture->format)) { - /* Check if it's component alpha that relies on a source alpha and on - * the source value. We can only get one of those into the single - * source value that we get to blend with. - */ - if (i965_blend_op[op].src_alpha && - (i965_blend_op[op].src_blend != BRW_BLENDFACTOR_ZERO)) { - intel_debug_fallback(scrn, - "Component alpha not supported " - "with source alpha and source " - "value blending.\n"); - return FALSE; - } - } - if (!i965_check_composite_texture(scrn, source_picture, 0)) { - intel_debug_fallback(scrn, "Check Src picture texture\n"); - return FALSE; - } - if (mask_picture != NULL - && !i965_check_composite_texture(scrn, mask_picture, 1)) { - intel_debug_fallback(scrn, "Check Mask picture texture\n"); - return FALSE; + return TRUE; } - if (!i965_get_dest_format(dest_picture, &tmp1)) { - intel_debug_fallback(scrn, "Get Color buffer format\n"); - return FALSE; - } - - return TRUE; - + return FALSE; } + #define BRW_GRF_BLOCKS(nreg) ((nreg + 15) / 16 - 1) /* Set up a default static partitioning of the URB, which is supposed to @@ -1143,6 +1142,12 @@ static void i965_emit_composite_state(ScrnInfoPtr scrn) IntelEmitInvarientState(scrn); intel->last_3d = LAST_3D_RENDER; + /* Mark the destination dirty within this batch */ + intel_batch_mark_pixmap_domains(intel, + i830_get_pixmap_intel(dest), + I915_GEM_DOMAIN_RENDER, + I915_GEM_DOMAIN_RENDER); + urb_vs_start = 0; urb_vs_size = URB_VS_ENTRIES * URB_VS_ENTRY_SIZE; urb_gs_start = urb_vs_start + urb_vs_size; @@ -1167,12 +1172,8 @@ static void i965_emit_composite_state(ScrnInfoPtr scrn) */ ALIGN_BATCH(64); + assert(intel->in_batch_atomic); { - if (IS_IGDNG(intel)) - ATOMIC_BATCH(14); - else - ATOMIC_BATCH(12); - /* Match Mesa driver setup */ OUT_BATCH(MI_FLUSH | MI_STATE_INSTRUCTION_CACHE_FLUSH | @@ -1215,12 +1216,17 @@ static void i965_emit_composite_state(ScrnInfoPtr scrn) OUT_BATCH(BRW_STATE_SIP | 0); OUT_RELOC(render_state->sip_kernel_bo, I915_GEM_DOMAIN_INSTRUCTION, 0, 0); - ADVANCE_BATCH(); + } + + if (IS_IGDNG(intel)) { + /* Ironlake errata workaround: Before disabling the clipper, + * you have to MI_FLUSH to get the pipeline idle. + */ + OUT_BATCH(MI_FLUSH); } { int pipe_ctrl; - ATOMIC_BATCH(26); /* Pipe control */ if (IS_IGDNG(intel)) @@ -1315,7 +1321,6 @@ static void i965_emit_composite_state(ScrnInfoPtr scrn) OUT_BATCH(BRW_CS_URB_STATE | 0); OUT_BATCH(((URB_CS_ENTRY_SIZE - 1) << 4) | (URB_CS_ENTRIES << 0)); - ADVANCE_BATCH(); } { /* @@ -1342,7 +1347,6 @@ static void i965_emit_composite_state(ScrnInfoPtr scrn) } if (IS_IGDNG(intel)) { - ATOMIC_BATCH(mask ? 9 : 7); /* * The reason to add this extra vertex element in the header is that * IGDNG has different vertex header definition and origin method to @@ -1372,7 +1376,6 @@ static void i965_emit_composite_state(ScrnInfoPtr scrn) (BRW_VFCOMPONENT_STORE_0 << VE1_VFCOMPONENT_3_SHIFT)); } else { - ATOMIC_BATCH(mask ? 7 : 5); /* Set up our vertex elements, sourced from the single vertex buffer. * that will be set up later. */ @@ -1434,8 +1437,6 @@ static void i965_emit_composite_state(ScrnInfoPtr scrn) else OUT_BATCH((BRW_VFCOMPONENT_STORE_SRC << VE1_VFCOMPONENT_0_SHIFT) | (BRW_VFCOMPONENT_STORE_SRC << VE1_VFCOMPONENT_1_SHIFT) | (w_component << VE1_VFCOMPONENT_2_SHIFT) | (BRW_VFCOMPONENT_STORE_1_FLT << VE1_VFCOMPONENT_3_SHIFT) | ((4 + 4 + 4) << VE1_DESTINATION_ELEMENT_OFFSET_SHIFT)); /* VUE offset in dwords */ } - - ADVANCE_BATCH(); } } @@ -1496,6 +1497,22 @@ i965_prepare_composite(int op, PicturePtr source_picture, } if (mask_picture) { + if (mask_picture->componentAlpha && + PICT_FORMAT_RGB(mask_picture->format)) { + /* Check if it's component alpha that relies on a source alpha and on + * the source value. We can only get one of those into the single + * source value that we get to blend with. + */ + if (i965_blend_op[op].src_alpha && + (i965_blend_op[op].src_blend != BRW_BLENDFACTOR_ZERO)) { + intel_debug_fallback(scrn, + "Component alpha not supported " + "with source alpha and source " + "value blending.\n"); + return FALSE; + } + } + composite_op->mask_filter = sampler_state_filter_from_picture(mask_picture->filter); if (composite_op->mask_filter < 0) { @@ -1515,6 +1532,12 @@ i965_prepare_composite(int op, PicturePtr source_picture, composite_op->mask_extend = SAMPLER_STATE_EXTEND_NONE; } + /* Flush any pending writes prior to relocating the textures. */ + if(i830_uxa_pixmap_is_dirty(source) || + (mask && i830_uxa_pixmap_is_dirty(mask))) + intel_batch_emit_flush(scrn); + + /* Set up the surface states. */ surface_state_bo = dri_bo_alloc(intel->bufmgr, "surface_state", 3 * sizeof(brw_surface_state_padded), @@ -1638,7 +1661,7 @@ i965_prepare_composite(int op, PicturePtr source_picture, } if (!i965_composite_check_aperture(scrn)) { - intel_batch_submit(scrn); + intel_batch_submit(scrn, FALSE); if (!i965_composite_check_aperture(scrn)) { intel_debug_fallback(scrn, "Couldn't fit render operation " @@ -1647,10 +1670,6 @@ i965_prepare_composite(int op, PicturePtr source_picture, } } - if(i830_uxa_pixmap_is_dirty(source) || - (mask && i830_uxa_pixmap_is_dirty(mask))) - intel_batch_emit_flush(scrn); - intel->needs_render_state_emit = TRUE; return TRUE; @@ -1815,13 +1834,12 @@ i965_composite(PixmapPtr dest, int srcX, int srcY, int maskX, int maskY, drm_intel_bo_subdata(vb_bo, render_state->vb_offset * 4, i * 4, vb); if (!i965_composite_check_aperture(scrn)) - intel_batch_submit(scrn); + intel_batch_submit(scrn, FALSE); intel_batch_start_atomic(scrn, 200); if (intel->needs_render_state_emit) i965_emit_composite_state(scrn); - ATOMIC_BATCH(12); OUT_BATCH(MI_FLUSH); /* Set up the pointer to our (single) vertex buffer */ OUT_BATCH(BRW_3DSTATE_VERTEX_BUFFERS | 3); @@ -1846,7 +1864,6 @@ i965_composite(PixmapPtr dest, int srcX, int srcY, int maskX, int maskY, OUT_BATCH(1); /* single instance */ OUT_BATCH(0); /* start instance location */ OUT_BATCH(0); /* index buffer offset, ignored */ - ADVANCE_BATCH(); render_state->vb_offset += i; drm_intel_bo_unreference(vb_bo); diff --git a/src/i965_video.c b/src/i965_video.c index c5378608..e25184b6 100644 --- a/src/i965_video.c +++ b/src/i965_video.c @@ -779,18 +779,12 @@ i965_emit_video_setup(ScrnInfoPtr scrn, drm_intel_bo * bind_bo, int n_src_surf) urb_cs_start = urb_sf_start + urb_sf_size; urb_cs_size = URB_CS_ENTRIES * URB_CS_ENTRY_SIZE; - ATOMIC_BATCH(2); OUT_BATCH(MI_FLUSH | MI_STATE_INSTRUCTION_CACHE_FLUSH | BRW_MI_GLOBAL_SNAPSHOT_RESET); OUT_BATCH(MI_NOOP); - ADVANCE_BATCH(); /* brw_debug (scrn, "before base address modify"); */ - if (IS_IGDNG(intel)) - ATOMIC_BATCH(14); - else - ATOMIC_BATCH(12); /* Match Mesa driver setup */ if (IS_G4X(intel) || IS_IGDNG(intel)) OUT_BATCH(NEW_PIPELINE_SELECT | PIPELINE_SELECT_3D); @@ -834,9 +828,6 @@ i965_emit_video_setup(ScrnInfoPtr scrn, drm_intel_bo * bind_bo, int n_src_surf) OUT_RELOC(intel->video.gen4_sip_kernel_bo, I915_GEM_DOMAIN_INSTRUCTION, 0, 0); - OUT_BATCH(MI_NOOP); - ADVANCE_BATCH(); - /* brw_debug (scrn, "after base address modify"); */ if (IS_IGDNG(intel)) @@ -844,10 +835,6 @@ i965_emit_video_setup(ScrnInfoPtr scrn, drm_intel_bo * bind_bo, int n_src_surf) else pipe_ctl = BRW_PIPE_CONTROL_NOWRITE | BRW_PIPE_CONTROL_IS_FLUSH; - ATOMIC_BATCH(38); - - OUT_BATCH(MI_NOOP); - /* Pipe control */ OUT_BATCH(BRW_PIPE_CONTROL | pipe_ctl | 2); OUT_BATCH(0); /* Destination address */ @@ -971,9 +958,6 @@ i965_emit_video_setup(ScrnInfoPtr scrn, drm_intel_bo * bind_bo, int n_src_surf) VE1_VFCOMPONENT_3_SHIFT) | (4 << VE1_DESTINATION_ELEMENT_OFFSET_SHIFT)); } - - OUT_BATCH(MI_NOOP); /* pad to quadword */ - ADVANCE_BATCH(); } void @@ -1213,14 +1197,13 @@ I965DisplayVideoTextured(ScrnInfoPtr scrn, if (drm_intel_bufmgr_check_aperture_space(bo_table, ARRAY_SIZE(bo_table)) < 0) { - intel_batch_submit(scrn); + intel_batch_submit(scrn, FALSE); } intel_batch_start_atomic(scrn, 100); i965_emit_video_setup(scrn, bind_bo, n_src_surf); - ATOMIC_BATCH(12); /* Set up the pointer to our vertex buffer */ OUT_BATCH(BRW_3DSTATE_VERTEX_BUFFERS | 3); /* four 32-bit floats per vertex */ @@ -1242,7 +1225,6 @@ I965DisplayVideoTextured(ScrnInfoPtr scrn, OUT_BATCH(0); /* start instance location */ OUT_BATCH(0); /* index buffer offset, ignored */ OUT_BATCH(MI_NOOP); - ADVANCE_BATCH(); intel_batch_end_atomic(scrn); diff --git a/src/xvmc/i965_xvmc.c b/src/xvmc/i965_xvmc.c index 1665f6d0..52b93e32 100644 --- a/src/xvmc/i965_xvmc.c +++ b/src/xvmc/i965_xvmc.c @@ -207,7 +207,7 @@ struct media_state { }; struct media_state media_state; -static int free_object(struct media_state *s) +static void free_object(struct media_state *s) { int i; #define FREE_ONE_BO(bo) drm_intel_bo_unreference(bo) diff --git a/src/xvmc/xvmc_vld.c b/src/xvmc/xvmc_vld.c index 5687593a..9ef840b3 100644 --- a/src/xvmc/xvmc_vld.c +++ b/src/xvmc/xvmc_vld.c @@ -354,7 +354,7 @@ static struct media_state { /* XvMCQMatrix * 2 + idct_table + 8 * kernel offset pointer */ #define CS_OBJECT_SIZE (32*20 + sizeof(unsigned int) * 8) -static int free_object(struct media_state *s) +static void free_object(struct media_state *s) { int i; #define FREE_ONE_BO(bo) \ diff --git a/uxa/uxa-accel.c b/uxa/uxa-accel.c index bede1f41..245738a6 100644 --- a/uxa/uxa-accel.c +++ b/uxa/uxa-accel.c @@ -34,33 +34,185 @@ #include <X11/fonts/fontstruct.h> #include "dixfontstr.h" #include "uxa.h" +#include "mipict.h" + +static CARD32 +format_for_depth(int depth) +{ + switch (depth) { + case 1: return PICT_a1; + case 4: return PICT_a4; + case 8: return PICT_a8; + case 15: return PICT_x1r5g5b5; + case 16: return PICT_r5g6b5; + default: + case 24: return PICT_x8r8g8b8; +#if 0 + case 30: return PICT_x2r10g10b10; +#endif + case 32: return PICT_a8r8g8b8; + } +} static void uxa_fill_spans(DrawablePtr pDrawable, GCPtr pGC, int n, DDXPointPtr ppt, int *pwidth, int fSorted) { - ScreenPtr pScreen = pDrawable->pScreen; - uxa_screen_t *uxa_screen = uxa_get_screen(pScreen); + ScreenPtr screen = pDrawable->pScreen; + uxa_screen_t *uxa_screen = uxa_get_screen(screen); RegionPtr pClip = fbGetCompositeClip(pGC); - PixmapPtr pPixmap = uxa_get_drawable_pixmap(pDrawable); + PixmapPtr dst_pixmap, src_pixmap = NULL; BoxPtr pextent, pbox; int nbox; int extentX1, extentX2, extentY1, extentY2; int fullX1, fullX2, fullY1; int partX1, partX2; int off_x, off_y; + xRenderColor color; + PictFormatPtr format; + PicturePtr dst, src; + int error; + + if (uxa_screen->swappedOut) + goto fallback; + + if (pGC->fillStyle != FillSolid) + goto fallback; + + dst_pixmap = uxa_get_offscreen_pixmap(pDrawable, &off_x, &off_y); + if (!dst_pixmap) + goto fallback; + + if (pGC->alu != GXcopy || pGC->planemask != FB_ALLONES) + goto solid; + + format = PictureMatchFormat(screen, + dst_pixmap->drawable.depth, + format_for_depth(dst_pixmap->drawable.depth)); + dst = CreatePicture(0, &dst_pixmap->drawable, format, 0, 0, serverClient, &error); + if (!dst) + goto solid; + + ValidatePicture(dst); + + uxa_get_rgba_from_pixel(pGC->fgPixel, + &color.red, + &color.green, + &color.blue, + &color.alpha, + format_for_depth(dst_pixmap->drawable.depth)); + src = CreateSolidPicture(0, &color, &error); + if (!src) { + FreePicture(dst, 0); + goto solid; + } + + if (!uxa_screen->info->check_composite(PictOpSrc, src, NULL, dst, 0, 0)) { + FreePicture(src, 0); + FreePicture(dst, 0); + goto solid; + } + + if (!uxa_screen->info->check_composite_texture || + !uxa_screen->info->check_composite_texture(screen, src)) { + PicturePtr solid; + int src_off_x, src_off_y; + + solid = uxa_acquire_solid(screen, src->pSourcePict); + FreePicture(src, 0); + + src = solid; + src_pixmap = uxa_get_offscreen_pixmap(src->pDrawable, + &src_off_x, &src_off_y); + if (!src_pixmap) { + FreePicture(src, 0); + FreePicture(dst, 0); + goto solid; + } + } - if (uxa_screen->swappedOut || pGC->fillStyle != FillSolid || - !(pPixmap = uxa_get_offscreen_pixmap(pDrawable, &off_x, &off_y)) || - !(*uxa_screen->info->prepare_solid) (pPixmap, + if (!uxa_screen->info->prepare_composite(PictOpSrc, src, NULL, dst, src_pixmap, NULL, dst_pixmap)) { + FreePicture(src, 0); + FreePicture(dst, 0); + goto solid; + } + + pextent = REGION_EXTENTS(pGC->screen, pClip); + extentX1 = pextent->x1; + extentY1 = pextent->y1; + extentX2 = pextent->x2; + extentY2 = pextent->y2; + while (n--) { + fullX1 = ppt->x; + fullY1 = ppt->y; + fullX2 = fullX1 + (int)*pwidth; + ppt++; + pwidth++; + + if (fullY1 < extentY1 || extentY2 <= fullY1) + continue; + + if (fullX1 < extentX1) + fullX1 = extentX1; + + if (fullX2 > extentX2) + fullX2 = extentX2; + + if (fullX1 >= fullX2) + continue; + + nbox = REGION_NUM_RECTS(pClip); + if (nbox == 1) { + uxa_screen->info->composite(dst_pixmap, + 0, 0, 0, 0, + fullX1 + off_x, + fullY1 + off_y, + fullX2 - fullX1, 1); + } else { + pbox = REGION_RECTS(pClip); + while (nbox--) { + if (pbox->y1 > fullY1) + break; + + if (pbox->y1 <= fullY1) { + partX1 = pbox->x1; + if (partX1 < fullX1) + partX1 = fullX1; + + partX2 = pbox->x2; + if (partX2 > fullX2) + partX2 = fullX2; + + if (partX2 > partX1) { + uxa_screen->info->composite(dst_pixmap, + 0, 0, 0, 0, + partX1 + off_x, + fullY1 + off_y, + partX2 - partX1, 1); + } + } + pbox++; + } + } + } + + uxa_screen->info->done_composite(dst_pixmap); + FreePicture(src, 0); + FreePicture(dst, 0); + return; + +solid: + if (uxa_screen->info->check_solid && + !uxa_screen->info->check_solid(pDrawable, pGC->alu, pGC->planemask)) + goto fallback; + + if (!(*uxa_screen->info->prepare_solid) (dst_pixmap, pGC->alu, pGC->planemask, - pGC->fgPixel)) { - uxa_check_fill_spans(pDrawable, pGC, n, ppt, pwidth, fSorted); - return; - } + pGC->fgPixel)) + goto fallback; - pextent = REGION_EXTENTS(pGC->pScreen, pClip); + pextent = REGION_EXTENTS(pGC->screen, pClip); extentX1 = pextent->x1; extentY1 = pextent->y1; extentX2 = pextent->x2; @@ -86,7 +238,7 @@ uxa_fill_spans(DrawablePtr pDrawable, GCPtr pGC, int n, nbox = REGION_NUM_RECTS(pClip); if (nbox == 1) { - (*uxa_screen->info->solid) (pPixmap, + (*uxa_screen->info->solid) (dst_pixmap, fullX1 + off_x, fullY1 + off_y, fullX2 + off_x, @@ -103,7 +255,7 @@ uxa_fill_spans(DrawablePtr pDrawable, GCPtr pGC, int n, partX2 = fullX2; if (partX2 > partX1) { (*uxa_screen->info-> - solid) (pPixmap, + solid) (dst_pixmap, partX1 + off_x, fullY1 + off_y, partX2 + off_x, @@ -114,7 +266,12 @@ uxa_fill_spans(DrawablePtr pDrawable, GCPtr pGC, int n, } } } - (*uxa_screen->info->done_solid) (pPixmap); + (*uxa_screen->info->done_solid) (dst_pixmap); + + return; + +fallback: + uxa_check_fill_spans(pDrawable, pGC, n, ppt, pwidth, fSorted); } static Bool @@ -204,92 +361,12 @@ uxa_do_put_image(DrawablePtr pDrawable, GCPtr pGC, int depth, int x, int y, return TRUE; } -#ifdef MITSHM - -#include "xorgVersion.h" - -static Bool -uxa_do_shm_put_image(DrawablePtr pDrawable, GCPtr pGC, int depth, - unsigned int format, int w, int h, int sx, int sy, int sw, - int sh, int dx, int dy, char *data) -{ - int src_stride = PixmapBytePad(w, depth); - - if (uxa_do_put_image - (pDrawable, pGC, depth, dx, dy, sw, sh, format, - data + sy * src_stride + sx * BitsPerPixel(depth) / 8, src_stride)) - return TRUE; - - if (format == ZPixmap) { - PixmapPtr pPixmap; - - pPixmap = - GetScratchPixmapHeader(pDrawable->pScreen, w, h, depth, - BitsPerPixel(depth), PixmapBytePad(w, - depth), - (pointer) data); - if (!pPixmap) - return FALSE; - - if (!uxa_prepare_access(pDrawable, UXA_ACCESS_RW)) { - FreeScratchPixmapHeader(pPixmap); - return FALSE; - } - - fbCopyArea((DrawablePtr) pPixmap, pDrawable, pGC, sx, sy, sw, - sh, dx, dy); - uxa_finish_access(pDrawable); - - FreeScratchPixmapHeader(pPixmap); - - return TRUE; - } - - return FALSE; -} - -#if XORG_VERSION_CURRENT < XORG_VERSION_NUMERIC(1,5,99,0,0) - -/* The actual ShmPutImage isn't wrapped by the damage layer, so we need to - * inform any interested parties of the damage incurred to the drawable. - * - * We also need to set the pending damage to ensure correct migration in all - * cases. - */ -void -uxa_shm_put_image(DrawablePtr pDrawable, GCPtr pGC, int depth, - unsigned int format, int w, int h, int sx, int sy, int sw, - int sh, int dx, int dy, char *data) -{ - if (!uxa_do_shm_put_image - (pDrawable, pGC, depth, format, w, h, sx, sy, sw, sh, dx, dy, - data)) { - if (!uxa_prepare_access(pDrawable, UXA_ACCESS_RW)) - return; - fbShmPutImage(pDrawable, pGC, depth, format, w, h, sx, sy, sw, - sh, dx, dy, data); - uxa_finish_access(pDrawable); - } -} -#else -#define uxa_shm_put_image NULL -#endif - -ShmFuncs uxa_shm_funcs = { NULL, uxa_shm_put_image }; - -#endif - static void uxa_put_image(DrawablePtr pDrawable, GCPtr pGC, int depth, int x, int y, int w, int h, int leftPad, int format, char *bits) { -#ifdef MITSHM - if (!uxa_do_shm_put_image - (pDrawable, pGC, depth, format, w, h, 0, 0, w, h, x, y, bits)) -#else if (!uxa_do_put_image(pDrawable, pGC, depth, x, y, w, h, format, bits, PixmapBytePad(w, pDrawable->depth))) -#endif uxa_check_put_image(pDrawable, pGC, depth, x, y, w, h, leftPad, format, bits); } @@ -435,6 +512,14 @@ uxa_copy_n_to_n(DrawablePtr pSrcDrawable, pSrcPixmap = uxa_get_drawable_pixmap(pSrcDrawable); pDstPixmap = uxa_get_drawable_pixmap(pDstDrawable); + if (!pSrcPixmap || !pDstPixmap) + goto fallback; + + if (uxa_screen->info->check_copy && + !uxa_screen->info->check_copy(pSrcPixmap, pDstPixmap, + pGC ? pGC->alu : GXcopy, + pGC ? pGC->planemask : FB_ALLONES)) + goto fallback; uxa_get_drawable_deltas(pSrcDrawable, pSrcPixmap, &src_off_x, &src_off_y); @@ -450,8 +535,45 @@ uxa_copy_n_to_n(DrawablePtr pSrcDrawable, goto fallback; } - if (!uxa_pixmap_is_offscreen(pDstPixmap)) - goto fallback; + if (!uxa_pixmap_is_offscreen(pDstPixmap)) { + int stride, bpp; + char *dst; + + if (!uxa_pixmap_is_offscreen(pSrcPixmap)) + goto fallback; + + if (!uxa_screen->info->get_image) + goto fallback; + + /* Don't bother with under 8bpp, XYPixmaps. */ + bpp = pSrcPixmap->drawable.bitsPerPixel; + if (bpp != pDstDrawable->bitsPerPixel || bpp < 8) + goto fallback; + + /* Only accelerate copies: no rop or planemask. */ + if (pGC && (!UXA_PM_IS_SOLID(pSrcDrawable, pGC->planemask) || pGC->alu != GXcopy)) + goto fallback; + + dst = pDstPixmap->devPrivate.ptr; + stride = pDstPixmap->devKind; + bpp /= 8; + while (nbox--) { + if (!uxa_screen->info->get_image(pSrcPixmap, + pbox->x1 + dx + src_off_x, + pbox->y1 + dy + src_off_y, + pbox->x2 - pbox->x1, + pbox->y2 - pbox->y1, + (char *) dst + + (pbox->y1 + dst_off_y) * stride + + (pbox->x1 + dst_off_x) * bpp, + stride)) + goto fallback; + + pbox++; + } + + return; + } if (uxa_pixmap_is_offscreen(pSrcPixmap)) { if (!(*uxa_screen->info->prepare_copy) (pSrcPixmap, pDstPixmap, @@ -558,7 +680,7 @@ uxa_poly_point(DrawablePtr pDrawable, GCPtr pGC, int mode, int npt, return; } - prect = xalloc(sizeof(xRectangle) * npt); + prect = malloc(sizeof(xRectangle) * npt); if (!prect) return; for (i = 0; i < npt; i++) { @@ -572,7 +694,7 @@ uxa_poly_point(DrawablePtr pDrawable, GCPtr pGC, int mode, int npt, prect[i].height = 1; } pGC->ops->PolyFillRect(pDrawable, pGC, npt, prect); - xfree(prect); + free(prect); } /** @@ -595,7 +717,7 @@ uxa_poly_lines(DrawablePtr pDrawable, GCPtr pGC, int mode, int npt, return; } - prect = xalloc(sizeof(xRectangle) * (npt - 1)); + prect = malloc(sizeof(xRectangle) * (npt - 1)); if (!prect) return; x1 = ppt[0].x; @@ -611,7 +733,7 @@ uxa_poly_lines(DrawablePtr pDrawable, GCPtr pGC, int mode, int npt, } if (x1 != x2 && y1 != y2) { - xfree(prect); + free(prect); uxa_check_poly_lines(pDrawable, pGC, mode, npt, ppt); return; } @@ -635,7 +757,7 @@ uxa_poly_lines(DrawablePtr pDrawable, GCPtr pGC, int mode, int npt, y1 = y2; } pGC->ops->PolyFillRect(pDrawable, pGC, npt - 1, prect); - xfree(prect); + free(prect); } /** @@ -664,7 +786,7 @@ uxa_poly_segment(DrawablePtr pDrawable, GCPtr pGC, int nseg, xSegment * pSeg) } } - prect = xalloc(sizeof(xRectangle) * nseg); + prect = malloc(sizeof(xRectangle) * nseg); if (!prect) return; for (i = 0; i < nseg; i++) { @@ -692,7 +814,7 @@ uxa_poly_segment(DrawablePtr pDrawable, GCPtr pGC, int nseg, xSegment * pSeg) } } pGC->ops->PolyFillRect(pDrawable, pGC, nseg, prect); - xfree(prect); + free(prect); } static Bool uxa_fill_region_solid(DrawablePtr pDrawable, RegionPtr pRegion, @@ -704,7 +826,7 @@ uxa_poly_fill_rect(DrawablePtr pDrawable, { uxa_screen_t *uxa_screen = uxa_get_screen(pDrawable->pScreen); RegionPtr pClip = fbGetCompositeClip(pGC); - PixmapPtr pPixmap = uxa_get_drawable_pixmap(pDrawable); + PixmapPtr pPixmap; register BoxPtr pbox; BoxPtr pextent; int extentX1, extentX2, extentY1, extentY2; @@ -722,11 +844,13 @@ uxa_poly_fill_rect(DrawablePtr pDrawable, if (!REGION_NUM_RECTS(pReg)) goto out; - uxa_get_drawable_deltas(pDrawable, pPixmap, &xoff, &yoff); - if (uxa_screen->swappedOut) goto fallback; + pPixmap = uxa_get_offscreen_pixmap (pDrawable, &xoff, &yoff); + if (!pPixmap) + goto fallback; + /* For ROPs where overlaps don't matter, convert rectangles to region * and call uxa_fill_region_{solid,tiled}. */ @@ -752,8 +876,12 @@ uxa_poly_fill_rect(DrawablePtr pDrawable, goto fallback; } - if (!uxa_pixmap_is_offscreen(pPixmap) || - !(*uxa_screen->info->prepare_solid) (pPixmap, + if (uxa_screen->info->check_solid && + !uxa_screen->info->check_solid(pDrawable, pGC->alu, pGC->planemask)) { + goto fallback; + } + + if (!(*uxa_screen->info->prepare_solid) (pPixmap, pGC->alu, pGC->planemask, pGC->fgPixel)) { @@ -896,35 +1024,121 @@ uxa_fill_region_solid(DrawablePtr pDrawable, RegionPtr pRegion, Pixel pixel, CARD32 planemask, CARD32 alu) { - uxa_screen_t *uxa_screen = uxa_get_screen(pDrawable->pScreen); - PixmapPtr pPixmap = uxa_get_drawable_pixmap(pDrawable); + ScreenPtr screen = pDrawable->pScreen; + uxa_screen_t *uxa_screen = uxa_get_screen(screen); + PixmapPtr pixmap; int xoff, yoff; + int nbox; + BoxPtr pBox, extents; Bool ret = FALSE; - uxa_get_drawable_deltas(pDrawable, pPixmap, &xoff, &yoff); - REGION_TRANSLATE(pScreen, pRegion, xoff, yoff); + pixmap = uxa_get_offscreen_pixmap(pDrawable, &xoff, &yoff); + if (!pixmap) + return FALSE; - if (uxa_pixmap_is_offscreen(pPixmap) && - (*uxa_screen->info->prepare_solid) (pPixmap, alu, planemask, pixel)) - { - int nbox; - BoxPtr pBox; + REGION_TRANSLATE(screen, pRegion, xoff, yoff); - nbox = REGION_NUM_RECTS(pRegion); - pBox = REGION_RECTS(pRegion); + nbox = REGION_NUM_RECTS(pRegion); + pBox = REGION_RECTS(pRegion); + extents = REGION_EXTENTS(screen, pRegion); + + /* Using GEM, the relocation costs outweigh the advantages of the blitter */ + if (nbox == 1 || (alu != GXcopy && alu != GXclear) || planemask != FB_ALLONES) { +try_solid: + if (uxa_screen->info->check_solid && + !uxa_screen->info->check_solid(&pixmap->drawable, alu, planemask)) + goto err; + + if (!uxa_screen->info->prepare_solid(pixmap, alu, planemask, pixel)) + goto err; while (nbox--) { - (*uxa_screen->info->solid) (pPixmap, pBox->x1, pBox->y1, - pBox->x2, pBox->y2); + uxa_screen->info->solid(pixmap, + pBox->x1, pBox->y1, + pBox->x2, pBox->y2); pBox++; } - (*uxa_screen->info->done_solid) (pPixmap); - ret = TRUE; + uxa_screen->info->done_solid(pixmap); + } else { + PicturePtr dst, src; + PixmapPtr src_pixmap = NULL; + xRenderColor color; + int error; + + dst = CreatePicture(0, &pixmap->drawable, + PictureMatchFormat(screen, + pixmap->drawable.depth, + format_for_depth(pixmap->drawable.depth)), + 0, 0, serverClient, &error); + if (!dst) + goto err; + + ValidatePicture(dst); + + uxa_get_rgba_from_pixel(pixel, + &color.red, + &color.green, + &color.blue, + &color.alpha, + format_for_depth(pixmap->drawable.depth)); + src = CreateSolidPicture(0, &color, &error); + if (!src) { + FreePicture(dst, 0); + goto err; + } + + if (!uxa_screen->info->check_composite(PictOpSrc, src, NULL, dst, + extents->x2 - extents->x1, + extents->y2 - extents->y1)) { + FreePicture(src, 0); + FreePicture(dst, 0); + goto try_solid; + } + + if (!uxa_screen->info->check_composite_texture || + !uxa_screen->info->check_composite_texture(screen, src)) { + PicturePtr solid; + int src_off_x, src_off_y; + + solid = uxa_acquire_solid(screen, src->pSourcePict); + FreePicture(src, 0); + + src = solid; + src_pixmap = uxa_get_offscreen_pixmap(src->pDrawable, + &src_off_x, &src_off_y); + if (!src_pixmap) { + FreePicture(src, 0); + FreePicture(dst, 0); + goto err; + } + } + + if (!uxa_screen->info->prepare_composite(PictOpSrc, src, NULL, dst, src_pixmap, NULL, pixmap)) { + FreePicture(src, 0); + FreePicture(dst, 0); + goto err; + } + + while (nbox--) { + uxa_screen->info->composite(pixmap, + 0, 0, 0, 0, + pBox->x1, + pBox->y1, + pBox->x2 - pBox->x1, + pBox->y2 - pBox->y1); + pBox++; + } + + uxa_screen->info->done_composite(pixmap); + FreePicture(src, 0); + FreePicture(dst, 0); } - REGION_TRANSLATE(pScreen, pRegion, -xoff, -yoff); + ret = TRUE; +err: + REGION_TRANSLATE(screen, pRegion, -xoff, -yoff); return ret; } @@ -956,15 +1170,16 @@ uxa_fill_region_tiled(DrawablePtr pDrawable, uxa_get_pixmap_first_pixel(pTile), planemask, alu); - pPixmap = uxa_get_drawable_pixmap(pDrawable); - uxa_get_drawable_deltas(pDrawable, pPixmap, &xoff, &yoff); - REGION_TRANSLATE(pScreen, pRegion, xoff, yoff); - pPixmap = uxa_get_offscreen_pixmap(pDrawable, &xoff, &yoff); - if (!pPixmap || !uxa_pixmap_is_offscreen(pTile)) goto out; + if (uxa_screen->info->check_copy && + !uxa_screen->info->check_copy(pTile, pPixmap, alu, planemask)) + return FALSE; + + REGION_TRANSLATE(pScreen, pRegion, xoff, yoff); + if ((*uxa_screen->info->prepare_copy) (pTile, pPixmap, 1, 1, alu, planemask)) { while (nbox--) { diff --git a/uxa/uxa-glyphs.c b/uxa/uxa-glyphs.c index 5c233216..823cf82f 100644 --- a/uxa/uxa-glyphs.c +++ b/uxa/uxa-glyphs.c @@ -1,11 +1,29 @@ /* - * Copyright © 2008 Red Hat, Inc. + * Copyright © 2010 Intel Corporation + * Partly based on code Copyright © 2008 Red Hat, Inc. * Partly based on code 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 Intel not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. Intel makes no representations about the + * suitability of this software for any purpose. It is provided "as is" + * without express or implied warranty. + * + * INTEL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL INTEL + * 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. + * + * 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 Red Hat not be used in advertising or * publicity pertaining to distribution of the software without specific, * written prior permission. Red Hat makes no representations about the @@ -16,7 +34,7 @@ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL Red Hat * 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 + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * * Permission to use, copy, modify, distribute, and sell this software and its @@ -33,11 +51,11 @@ * 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 + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * - * Author: Owen Taylor <otaylor@fishsoup.net> - * Based on code by: Keith Packard + * Author: Chris Wilson <chris@chris-wilson.co.uk> + * Based on code by: Keith Packard <keithp@keithp.com> and Owen Taylor <otaylor@fishsoup.net> */ #ifdef HAVE_DIX_CONFIG_H @@ -51,99 +69,63 @@ #include "mipict.h" -#if DEBUG_GLYPH_CACHE -#define DBG_GLYPH_CACHE(a) ErrorF a -#else -#define DBG_GLYPH_CACHE(a) -#endif - /* Width of the pixmaps we use for the caches; this should be less than * max texture size of the driver; this may need to actually come from * the driver. */ -#define CACHE_PICTURE_WIDTH 1024 - -/* Maximum number of glyphs we buffer on the stack before flushing - * rendering to the mask or destination surface. - */ -#define GLYPH_BUFFER_SIZE 256 - -typedef struct { - PicturePtr source; - uxa_composite_rect_t rects[GLYPH_BUFFER_SIZE]; - int count; -} uxa_glyph_buffer_t; - -typedef enum { - UXA_GLYPH_SUCCESS, /* Glyph added to render buffer */ - UXA_GLYPH_FAIL, /* out of memory, etc */ - UXA_GLYPH_NEED_FLUSH, /* would evict a glyph already in the buffer */ -} uxa_glyph_cache_result_t; +#define CACHE_PICTURE_SIZE 1024 +#define GLYPH_MIN_SIZE 8 +#define GLYPH_MAX_SIZE 64 +#define GLYPH_CACHE_SIZE (CACHE_PICTURE_SIZE * CACHE_PICTURE_SIZE / (GLYPH_MIN_SIZE * GLYPH_MIN_SIZE)) + +struct uxa_glyph { + uxa_glyph_cache_t *cache; + uint16_t x, y; + uint16_t size, pos; +}; + +#if HAS_DEVPRIVATEKEYREC +static DevPrivateKeyRec uxa_glyph_key; +#else +static int uxa_glyph_key; +#endif -void uxa_glyphs_init(ScreenPtr pScreen) +static inline struct uxa_glyph *uxa_glyph_get_private(GlyphPtr glyph) { - uxa_screen_t *uxa_screen = uxa_get_screen(pScreen); - int i = 0; - - memset(uxa_screen->glyphCaches, 0, sizeof(uxa_screen->glyphCaches)); +#if HAS_DEVPRIVATEKEYREC + return dixGetPrivate(&glyph->devPrivates, &uxa_glyph_key); +#else + return dixLookupPrivate(&glyph->devPrivates, &uxa_glyph_key); +#endif +} - uxa_screen->glyphCaches[i].format = PICT_a8; - uxa_screen->glyphCaches[i].glyphWidth = - uxa_screen->glyphCaches[i].glyphHeight = 16; - i++; - uxa_screen->glyphCaches[i].format = PICT_a8; - uxa_screen->glyphCaches[i].glyphWidth = - uxa_screen->glyphCaches[i].glyphHeight = 32; - i++; - uxa_screen->glyphCaches[i].format = PICT_a8r8g8b8; - uxa_screen->glyphCaches[i].glyphWidth = - uxa_screen->glyphCaches[i].glyphHeight = 16; - i++; - uxa_screen->glyphCaches[i].format = PICT_a8r8g8b8; - uxa_screen->glyphCaches[i].glyphWidth = - uxa_screen->glyphCaches[i].glyphHeight = 32; - i++; - - assert(i == UXA_NUM_GLYPH_CACHES); - - for (i = 0; i < UXA_NUM_GLYPH_CACHES; i++) { - uxa_screen->glyphCaches[i].columns = - CACHE_PICTURE_WIDTH / uxa_screen->glyphCaches[i].glyphWidth; - uxa_screen->glyphCaches[i].size = 256; - uxa_screen->glyphCaches[i].hashSize = 557; - } +static inline void uxa_glyph_set_private(GlyphPtr glyph, struct uxa_glyph *priv) +{ + dixSetPrivate(&glyph->devPrivates, &uxa_glyph_key, priv); } -static void uxa_unrealize_glyph_caches(ScreenPtr pScreen, unsigned int format) +#define NeedsComponent(f) (PICT_FORMAT_A(f) != 0 && PICT_FORMAT_RGB(f) != 0) + +static void uxa_unrealize_glyph_caches(ScreenPtr pScreen) { uxa_screen_t *uxa_screen = uxa_get_screen(pScreen); int i; - for (i = 0; i < UXA_NUM_GLYPH_CACHES; i++) { + for (i = 0; i < UXA_NUM_GLYPH_CACHE_FORMATS; i++) { uxa_glyph_cache_t *cache = &uxa_screen->glyphCaches[i]; - if (cache->format != format) - continue; - - if (cache->picture) { - FreePicture((pointer) cache->picture, (XID) 0); - cache->picture = NULL; - } - - if (cache->hashEntries) { - xfree(cache->hashEntries); - cache->hashEntries = NULL; - } + if (cache->picture) + FreePicture(cache->picture, 0); - if (cache->glyphs) { - xfree(cache->glyphs); - cache->glyphs = NULL; - } - cache->glyphCount = 0; + if (cache->glyphs) + free(cache->glyphs); } } -#define NeedsComponent(f) (PICT_FORMAT_A(f) != 0 && PICT_FORMAT_RGB(f) != 0) +void uxa_glyphs_fini(ScreenPtr pScreen) +{ + uxa_unrealize_glyph_caches(pScreen); +} /* All caches for a single format share a single pixmap for glyph storage, * allowing mixing glyphs of different sizes without paying a penalty @@ -154,460 +136,176 @@ static void uxa_unrealize_glyph_caches(ScreenPtr pScreen, unsigned int format) * This function allocates the storage pixmap, and then fills in the * rest of the allocated structures for all caches with the given format. */ -static Bool uxa_realize_glyph_caches(ScreenPtr pScreen, unsigned int format) +static Bool uxa_realize_glyph_caches(ScreenPtr pScreen) { uxa_screen_t *uxa_screen = uxa_get_screen(pScreen); - int depth = PIXMAN_FORMAT_DEPTH(format); - PictFormatPtr pPictFormat; - PixmapPtr pPixmap; - PicturePtr pPicture; - CARD32 component_alpha; - int height; + unsigned int formats[] = { + PIXMAN_a8, + PIXMAN_a8r8g8b8, + }; int i; - int error; - pPictFormat = PictureMatchFormat(pScreen, depth, format); - if (!pPictFormat) - return FALSE; - - /* Compute the total vertical size needed for the format */ + memset(uxa_screen->glyphCaches, 0, sizeof(uxa_screen->glyphCaches)); - height = 0; - for (i = 0; i < UXA_NUM_GLYPH_CACHES; i++) { + for (i = 0; i < sizeof(formats)/sizeof(formats[0]); i++) { uxa_glyph_cache_t *cache = &uxa_screen->glyphCaches[i]; - int rows; - - if (cache->format != format) - continue; - - cache->yOffset = height; - - rows = (cache->size + cache->columns - 1) / cache->columns; - height += rows * cache->glyphHeight; - } - - /* Now allocate the pixmap and picture */ - - pPixmap = (*pScreen->CreatePixmap) (pScreen, - CACHE_PICTURE_WIDTH, - height, depth, - INTEL_CREATE_PIXMAP_TILING_X); - if (!pPixmap) - return FALSE; - - component_alpha = NeedsComponent(pPictFormat->format); - pPicture = CreatePicture(0, &pPixmap->drawable, pPictFormat, - CPComponentAlpha, &component_alpha, - serverClient, &error); - - (*pScreen->DestroyPixmap) (pPixmap); /* picture holds a refcount */ + PixmapPtr pixmap; + PicturePtr picture; + CARD32 component_alpha; + int depth = PIXMAN_FORMAT_DEPTH(formats[i]); + int error; + PictFormatPtr pPictFormat = PictureMatchFormat(pScreen, depth, formats[i]); + if (!pPictFormat) + goto bail; - if (!pPicture) - return FALSE; + /* Now allocate the pixmap and picture */ + pixmap = pScreen->CreatePixmap(pScreen, + CACHE_PICTURE_SIZE, CACHE_PICTURE_SIZE, depth, + INTEL_CREATE_PIXMAP_TILING_X); + if (!pixmap) + goto bail; + assert (uxa_pixmap_is_offscreen(pixmap)); - /* And store the picture in all the caches for the format */ + component_alpha = NeedsComponent(pPictFormat->format); + picture = CreatePicture(0, &pixmap->drawable, pPictFormat, + CPComponentAlpha, &component_alpha, + serverClient, &error); - for (i = 0; i < UXA_NUM_GLYPH_CACHES; i++) { - uxa_glyph_cache_t *cache = &uxa_screen->glyphCaches[i]; - int j; + pScreen->DestroyPixmap(pixmap); - if (cache->format != format) - continue; + if (!picture) + goto bail; - cache->picture = pPicture; - cache->picture->refcnt++; - cache->hashEntries = xalloc(sizeof(int) * cache->hashSize); - cache->glyphs = - xalloc(sizeof(uxa_cached_glyph_t) * cache->size); - cache->glyphCount = 0; + ValidatePicture(picture); - if (!cache->hashEntries || !cache->glyphs) + cache->picture = picture; + cache->glyphs = calloc(sizeof(GlyphPtr), GLYPH_CACHE_SIZE); + if (!cache->glyphs) goto bail; - for (j = 0; j < cache->hashSize; j++) - cache->hashEntries[j] = -1; - - cache->evictionPosition = rand() % cache->size; + cache->evict = rand() % GLYPH_CACHE_SIZE; } + assert(i == UXA_NUM_GLYPH_CACHE_FORMATS); - /* Each cache references the picture individually */ - FreePicture((pointer) pPicture, (XID) 0); return TRUE; bail: - uxa_unrealize_glyph_caches(pScreen, format); + uxa_unrealize_glyph_caches(pScreen); return FALSE; } -void uxa_glyphs_fini(ScreenPtr pScreen) -{ - uxa_screen_t *uxa_screen = uxa_get_screen(pScreen); - int i; - - for (i = 0; i < UXA_NUM_GLYPH_CACHES; i++) { - uxa_glyph_cache_t *cache = &uxa_screen->glyphCaches[i]; - if (cache->picture) - uxa_unrealize_glyph_caches(pScreen, cache->format); - } -} - -static int -uxa_glyph_cache_hash_lookup(uxa_glyph_cache_t * cache, GlyphPtr pGlyph) +Bool uxa_glyphs_init(ScreenPtr pScreen) { - int slot; - - slot = (*(CARD32 *) pGlyph->sha1) % cache->hashSize; - - while (TRUE) { /* hash table can never be full */ - int entryPos = cache->hashEntries[slot]; - if (entryPos == -1) - return -1; - - if (memcmp - (pGlyph->sha1, cache->glyphs[entryPos].sha1, - sizeof(pGlyph->sha1)) == 0) { - return entryPos; - } - - slot--; - if (slot < 0) - slot = cache->hashSize - 1; - } -} - -static void -uxa_glyph_cache_hash_insert(uxa_glyph_cache_t * cache, GlyphPtr pGlyph, int pos) -{ - int slot; - - memcpy(cache->glyphs[pos].sha1, pGlyph->sha1, sizeof(pGlyph->sha1)); - - slot = (*(CARD32 *) pGlyph->sha1) % cache->hashSize; - - while (TRUE) { /* hash table can never be full */ - if (cache->hashEntries[slot] == -1) { - cache->hashEntries[slot] = pos; - return; - } - - slot--; - if (slot < 0) - slot = cache->hashSize - 1; - } -} - -static void uxa_glyph_cache_hash_remove(uxa_glyph_cache_t * cache, int pos) -{ - int slot; - int emptiedSlot = -1; - - slot = (*(CARD32 *) cache->glyphs[pos].sha1) % cache->hashSize; - - while (TRUE) { /* hash table can never be full */ - int entryPos = cache->hashEntries[slot]; + /* We are trying to initialise per screen resources prior to the + * complete initialisation of the screen. So ensure the components + * that we depend upon are initialsed prior to our use. + */ + if (!CreateScratchPixmapsForScreen(pScreen->myNum)) + return FALSE; - if (entryPos == -1) - return; +#if HAS_DIXREGISTERPRIVATEKEY + if (!dixRegisterPrivateKey(&uxa_glyph_key, PRIVATE_GLYPH, 0)) + return FALSE; +#else + if (!dixRequestPrivate(&uxa_glyph_key, 0)) + return FALSE; +#endif - if (entryPos == pos) { - cache->hashEntries[slot] = -1; - emptiedSlot = slot; - } else if (emptiedSlot != -1) { - /* See if we can move this entry into the emptied slot, - * we can't do that if if entry would have hashed - * between the current position and the emptied slot. - * (taking wrapping into account). Bad positions - * are: - * - * | XXXXXXXXXX | - * i j - * - * |XXX XXXX| - * j i - * - * i - slot, j - emptiedSlot - * - * (Knuth 6.4R) - */ - - int entrySlot = - (*(CARD32 *) cache->glyphs[entryPos].sha1) % - cache->hashSize; - - if (!((entrySlot >= slot && entrySlot < emptiedSlot) || - (emptiedSlot < slot - && (entrySlot < emptiedSlot - || entrySlot >= slot)))) { - cache->hashEntries[emptiedSlot] = entryPos; - cache->hashEntries[slot] = -1; - emptiedSlot = slot; - } - } + if (!uxa_realize_glyph_caches(pScreen)) + return FALSE; - slot--; - if (slot < 0) - slot = cache->hashSize - 1; - } + return TRUE; } -#define CACHE_X(pos) (((pos) % cache->columns) * cache->glyphWidth) -#define CACHE_Y(pos) (cache->yOffset + ((pos) / cache->columns) * cache->glyphHeight) - /* The most efficient thing to way to upload the glyph to the screen * is to use CopyArea; uxa pixmaps are always offscreen. */ -static Bool -uxa_glyph_cache_upload_glyph(ScreenPtr pScreen, +static void +uxa_glyph_cache_upload_glyph(ScreenPtr screen, uxa_glyph_cache_t * cache, - int pos, GlyphPtr pGlyph) + GlyphPtr glyph, + int x, int y) { - PicturePtr pGlyphPicture = GlyphPicture(pGlyph)[pScreen->myNum]; + PicturePtr pGlyphPicture = GlyphPicture(glyph)[screen->myNum]; PixmapPtr pGlyphPixmap = (PixmapPtr) pGlyphPicture->pDrawable; PixmapPtr pCachePixmap = (PixmapPtr) cache->picture->pDrawable; PixmapPtr scratch; - GCPtr pGC; + GCPtr gc; - /* UploadToScreen only works if bpp match */ - if (pGlyphPixmap->drawable.bitsPerPixel != - pCachePixmap->drawable.bitsPerPixel) - return FALSE; + gc = GetScratchGC(pCachePixmap->drawable.depth, screen); + if (!gc) + return; - pGC = GetScratchGC(pCachePixmap->drawable.depth, pScreen); - ValidateGC(&pCachePixmap->drawable, pGC); + ValidateGC(&pCachePixmap->drawable, gc); + scratch = pGlyphPixmap; /* Create a temporary bo to stream the updates to the cache */ - scratch = (*pScreen->CreatePixmap)(pScreen, - pGlyph->info.width, - pGlyph->info.height, - pGlyphPixmap->drawable.depth, - UXA_CREATE_PIXMAP_FOR_MAP); - if (scratch) { - (void)uxa_copy_area(&pGlyphPixmap->drawable, - &scratch->drawable, - pGC, - 0, 0, - pGlyph->info.width, pGlyph->info.height, - 0, 0); - } else { - scratch = pGlyphPixmap; - } - - (void)uxa_copy_area(&scratch->drawable, - &pCachePixmap->drawable, - pGC, - 0, 0, pGlyph->info.width, pGlyph->info.height, - CACHE_X(pos), CACHE_Y(pos)); - - if (scratch != pGlyphPixmap) - (*pScreen->DestroyPixmap)(scratch); - - FreeScratchGC(pGC); - - return TRUE; -} - -static uxa_glyph_cache_result_t -uxa_glyph_cache_buffer_glyph(ScreenPtr pScreen, - uxa_glyph_cache_t * cache, - uxa_glyph_buffer_t * buffer, - GlyphPtr pGlyph, int xGlyph, int yGlyph) -{ - uxa_composite_rect_t *rect; - int pos; - - if (buffer->source && buffer->source != cache->picture) - return UXA_GLYPH_NEED_FLUSH; - - if (!cache->picture) { - if (!uxa_realize_glyph_caches(pScreen, cache->format)) - return UXA_GLYPH_FAIL; - } - - DBG_GLYPH_CACHE(("(%d,%d,%s): buffering glyph %lx\n", - cache->glyphWidth, cache->glyphHeight, - cache->format == PICT_a8 ? "A" : "ARGB", - (long)*(CARD32 *) pGlyph->sha1)); - - pos = uxa_glyph_cache_hash_lookup(cache, pGlyph); - if (pos != -1) { - DBG_GLYPH_CACHE((" found existing glyph at %d\n", pos)); - } else { - if (cache->glyphCount < cache->size) { - /* Space remaining; we fill from the start */ - pos = cache->glyphCount; - cache->glyphCount++; - DBG_GLYPH_CACHE((" storing glyph in free space at %d\n", pos)); - - uxa_glyph_cache_hash_insert(cache, pGlyph, pos); - - } else { - /* Need to evict an entry. We have to see if any glyphs - * already in the output buffer were at this position in - * the cache - */ - - pos = cache->evictionPosition; - DBG_GLYPH_CACHE((" evicting glyph at %d\n", pos)); - if (buffer->count) { - int x, y; - int i; - - x = CACHE_X(pos); - y = CACHE_Y(pos); - - for (i = 0; i < buffer->count; i++) { - if (buffer->rects[i].xSrc == x - && buffer->rects[i].ySrc == y) { - DBG_GLYPH_CACHE((" must flush buffer\n")); - return UXA_GLYPH_NEED_FLUSH; - } + if (pGlyphPixmap->drawable.depth != pCachePixmap->drawable.depth || + !uxa_pixmap_is_offscreen(scratch)) { + scratch = screen->CreatePixmap(screen, + glyph->info.width, + glyph->info.height, + pCachePixmap->drawable.depth, + UXA_CREATE_PIXMAP_FOR_MAP); + if (scratch) { + if (pGlyphPixmap->drawable.depth != pCachePixmap->drawable.depth) { + PicturePtr picture; + int error; + + picture = CreatePicture(0, &scratch->drawable, + PictureMatchFormat(screen, + pCachePixmap->drawable.depth, + cache->picture->format), + 0, NULL, + serverClient, &error); + if (picture) { + ValidatePicture(picture); + uxa_composite(PictOpSrc, pGlyphPicture, NULL, picture, + 0, 0, + 0, 0, + 0, 0, + glyph->info.width, glyph->info.height); + FreePicture(picture, 0); } + } else { + uxa_copy_area(&pGlyphPixmap->drawable, + &scratch->drawable, + gc, + 0, 0, + glyph->info.width, glyph->info.height, + 0, 0); } - - /* OK, we're all set, swap in the new glyph */ - uxa_glyph_cache_hash_remove(cache, pos); - uxa_glyph_cache_hash_insert(cache, pGlyph, pos); - - /* And pick a new eviction position */ - cache->evictionPosition = rand() % cache->size; - } - - /* Now actually upload the glyph into the cache picture; if - * we can't do it with UploadToScreen (because the glyph is - * offscreen, etc), we fall back to CompositePicture. - */ - if (!uxa_glyph_cache_upload_glyph(pScreen, cache, pos, pGlyph)) { - CompositePicture(PictOpSrc, - GlyphPicture(pGlyph)[pScreen->myNum], - None, - cache->picture, - 0, 0, - 0, 0, - CACHE_X(pos), - CACHE_Y(pos), - pGlyph->info.width, - pGlyph->info.height); - } - - } - - buffer->source = cache->picture; - - rect = &buffer->rects[buffer->count]; - rect->xSrc = CACHE_X(pos); - rect->ySrc = CACHE_Y(pos); - rect->xDst = xGlyph - pGlyph->info.x; - rect->yDst = yGlyph - pGlyph->info.y; - rect->width = pGlyph->info.width; - rect->height = pGlyph->info.height; - - buffer->count++; - - return UXA_GLYPH_SUCCESS; -} - -#undef CACHE_X -#undef CACHE_Y - -static uxa_glyph_cache_result_t -uxa_buffer_glyph(ScreenPtr pScreen, - uxa_glyph_buffer_t * buffer, - GlyphPtr pGlyph, int xGlyph, int yGlyph) -{ - uxa_screen_t *uxa_screen = uxa_get_screen(pScreen); - unsigned int format = (GlyphPicture(pGlyph)[pScreen->myNum])->format; - int width = pGlyph->info.width; - int height = pGlyph->info.height; - uxa_composite_rect_t *rect; - PicturePtr source; - int i; - - if (buffer->count == GLYPH_BUFFER_SIZE) - return UXA_GLYPH_NEED_FLUSH; - - if (PICT_FORMAT_BPP(format) == 1) - format = PICT_a8; - - for (i = 0; i < UXA_NUM_GLYPH_CACHES; i++) { - uxa_glyph_cache_t *cache = &uxa_screen->glyphCaches[i]; - - if (format == cache->format && - width <= cache->glyphWidth && - height <= cache->glyphHeight) { - uxa_glyph_cache_result_t result = - uxa_glyph_cache_buffer_glyph(pScreen, - &uxa_screen-> - glyphCaches[i], - buffer, - pGlyph, xGlyph, - yGlyph); - switch (result) { - case UXA_GLYPH_FAIL: - break; - case UXA_GLYPH_SUCCESS: - case UXA_GLYPH_NEED_FLUSH: - return result; - } + } else { + scratch = pGlyphPixmap; } } - /* Couldn't find the glyph in the cache, use the glyph picture directly */ - - source = GlyphPicture(pGlyph)[pScreen->myNum]; - if (buffer->source && buffer->source != source) - return UXA_GLYPH_NEED_FLUSH; + uxa_copy_area(&scratch->drawable, &pCachePixmap->drawable, gc, + 0, 0, + glyph->info.width, glyph->info.height, + x, y); - buffer->source = source; - - rect = &buffer->rects[buffer->count]; - rect->xSrc = 0; - rect->ySrc = 0; - rect->xDst = xGlyph - pGlyph->info.x; - rect->yDst = yGlyph - pGlyph->info.y; - rect->width = pGlyph->info.width; - rect->height = pGlyph->info.height; - - buffer->count++; + if (scratch != pGlyphPixmap) + screen->DestroyPixmap(scratch); - return UXA_GLYPH_SUCCESS; + FreeScratchGC(gc); } -static void uxa_glyphs_to_mask(PicturePtr pMask, uxa_glyph_buffer_t * buffer) +void +uxa_glyph_unrealize(ScreenPtr pScreen, + GlyphPtr pGlyph) { - uxa_composite_rects(PictOpAdd, buffer->source, pMask, - buffer->count, buffer->rects); - - buffer->count = 0; - buffer->source = NULL; -} + struct uxa_glyph *priv; -static void -uxa_glyphs_to_dst(CARD8 op, - PicturePtr pSrc, - PicturePtr pDst, - uxa_glyph_buffer_t * buffer, - INT16 xSrc, INT16 ySrc, INT16 xDst, INT16 yDst) -{ - int i; + priv = uxa_glyph_get_private(pGlyph); + if (priv == NULL) + return; - for (i = 0; i < buffer->count; i++) { - uxa_composite_rect_t *rect = &buffer->rects[i]; - - CompositePicture(op, - pSrc, - buffer->source, - pDst, - xSrc + rect->xDst - xDst, - ySrc + rect->yDst - yDst, - rect->xSrc, - rect->ySrc, - rect->xDst, - rect->yDst, rect->width, rect->height); - } + priv->cache->glyphs[priv->pos] = NULL; - buffer->count = 0; - buffer->source = NULL; + uxa_glyph_set_private(pGlyph, NULL); + free(priv); } /* Cut and paste from render/glyph.c - probably should export it instead */ @@ -616,47 +314,43 @@ uxa_glyph_extents(int nlist, GlyphListPtr list, GlyphPtr * glyphs, BoxPtr extents) { int x1, x2, y1, y2; - int n; - GlyphPtr glyph; - int x, y; + int x, y, n; - x = 0; - y = 0; - extents->x1 = MAXSHORT; - extents->x2 = MINSHORT; - extents->y1 = MAXSHORT; - extents->y2 = MINSHORT; + x1 = y1 = MAXSHORT; + x2 = y2 = MINSHORT; + x = y = 0; while (nlist--) { x += list->xOff; y += list->yOff; n = list->len; list++; while (n--) { - glyph = *glyphs++; - x1 = x - glyph->info.x; - if (x1 < MINSHORT) - x1 = MINSHORT; - y1 = y - glyph->info.y; - if (y1 < MINSHORT) - y1 = MINSHORT; - x2 = x1 + glyph->info.width; - if (x2 > MAXSHORT) - x2 = MAXSHORT; - y2 = y1 + glyph->info.height; - if (y2 > MAXSHORT) - y2 = MAXSHORT; - if (x1 < extents->x1) - extents->x1 = x1; - if (x2 > extents->x2) - extents->x2 = x2; - if (y1 < extents->y1) - extents->y1 = y1; - if (y2 > extents->y2) - extents->y2 = y2; + GlyphPtr glyph = *glyphs++; + int v; + + v = x - glyph->info.x; + if (v < x1) + x1 = v; + v += glyph->info.width; + if (v > x2) + x2 = v; + + v = y - glyph->info.y; + if (v < y1) + y1 = v; + v += glyph->info.height; + if (v > y2) + y2 = v; + x += glyph->info.xOff; y += glyph->info.yOff; } } + + extents->x1 = x1 < MINSHORT ? MINSHORT : x1; + extents->x2 = x2 > MAXSHORT ? MAXSHORT : x2; + extents->y1 = y1 < MINSHORT ? MINSHORT : y1; + extents->y2 = y2 > MAXSHORT ? MAXSHORT : y2; } /** @@ -668,7 +362,6 @@ uxa_glyphs_intersect(int nlist, GlyphListPtr list, GlyphPtr * glyphs) { int x1, x2, y1, y2; int n; - GlyphPtr glyph; int x, y; BoxRec extents; Bool first = TRUE; @@ -685,7 +378,7 @@ uxa_glyphs_intersect(int nlist, GlyphListPtr list, GlyphPtr * glyphs) n = list->len; list++; while (n--) { - glyph = *glyphs++; + GlyphPtr glyph = *glyphs++; if (glyph->info.width == 0 || glyph->info.height == 0) { x += glyph->info.xOff; @@ -735,121 +428,98 @@ uxa_glyphs_intersect(int nlist, GlyphListPtr list, GlyphPtr * glyphs) return FALSE; } -void -uxa_glyphs(CARD8 op, - PicturePtr pSrc, - PicturePtr pDst, - PictFormatPtr maskFormat, - INT16 xSrc, - INT16 ySrc, int nlist, GlyphListPtr list, GlyphPtr * glyphs) +static void +uxa_check_glyphs(CARD8 op, + PicturePtr src, + PicturePtr dst, + PictFormatPtr maskFormat, + INT16 xSrc, + INT16 ySrc, int nlist, GlyphListPtr list, GlyphPtr * glyphs) { - PicturePtr pPicture; - PixmapPtr pMaskPixmap = 0; - PicturePtr pMask; - ScreenPtr pScreen = pDst->pDrawable->pScreen; + int screen = dst->pDrawable->pScreen->myNum; + pixman_image_t *image; + PixmapPtr scratch; + PicturePtr mask; int width = 0, height = 0; - int x, y; + int x, y, n; int xDst = list->xOff, yDst = list->yOff; - int n; - GlyphPtr glyph; - int error; BoxRec extents = { 0, 0, 0, 0 }; - CARD32 component_alpha; - uxa_glyph_buffer_t buffer; - - /* If we don't have a mask format but all the glyphs have the same format - * and don't intersect, use the glyph format as mask format for the full - * benefits of the glyph cache. - */ - if (!maskFormat) { - Bool sameFormat = TRUE; - int i; - - maskFormat = list[0].format; - - for (i = 0; i < nlist; i++) { - if (maskFormat->format != list[i].format->format) { - sameFormat = FALSE; - break; - } - } - - if (!sameFormat || (maskFormat->depth != 1 && - uxa_glyphs_intersect(nlist, list, - glyphs))) { - maskFormat = NULL; - } - } if (maskFormat) { - GCPtr pGC; - xRectangle rect; + pixman_format_code_t format; + CARD32 component_alpha; + int error; uxa_glyph_extents(nlist, list, glyphs, &extents); - if (extents.x2 <= extents.x1 || extents.y2 <= extents.y1) return; + width = extents.x2 - extents.x1; height = extents.y2 - extents.y1; - if (maskFormat->depth == 1) { - PictFormatPtr a8Format = - PictureMatchFormat(pScreen, 8, PICT_a8); + format = maskFormat->format | + (BitsPerPixel(maskFormat->depth) << 24); + image = + pixman_image_create_bits(format, width, height, NULL, 0); + if (!image) + return; - if (a8Format) - maskFormat = a8Format; - } + scratch = GetScratchPixmapHeader(dst->pDrawable->pScreen, width, height, + PIXMAN_FORMAT_DEPTH(format), + PIXMAN_FORMAT_BPP(format), + pixman_image_get_stride(image), + pixman_image_get_data(image)); - pMaskPixmap = (*pScreen->CreatePixmap) (pScreen, width, height, - maskFormat->depth, - CREATE_PIXMAP_USAGE_SCRATCH); - if (!pMaskPixmap) + if (!scratch) { + pixman_image_unref(image); return; + } + component_alpha = NeedsComponent(maskFormat->format); - pMask = CreatePicture(0, &pMaskPixmap->drawable, - maskFormat, CPComponentAlpha, - &component_alpha, serverClient, &error); - if (!pMask) { - (*pScreen->DestroyPixmap) (pMaskPixmap); + mask = CreatePicture(0, &scratch->drawable, + maskFormat, CPComponentAlpha, + &component_alpha, serverClient, &error); + if (!mask) { + FreeScratchPixmapHeader(scratch); + pixman_image_unref(image); return; } - pGC = GetScratchGC(pMaskPixmap->drawable.depth, pScreen); - ValidateGC(&pMaskPixmap->drawable, pGC); - rect.x = 0; - rect.y = 0; - rect.width = width; - rect.height = height; - (*pGC->ops->PolyFillRect) (&pMaskPixmap->drawable, pGC, 1, - &rect); - FreeScratchGC(pGC); + ValidatePicture(mask); + x = -extents.x1; y = -extents.y1; } else { - pMask = pDst; + mask = dst; x = 0; y = 0; } - buffer.count = 0; - buffer.source = NULL; + while (nlist--) { x += list->xOff; y += list->yOff; n = list->len; while (n--) { - glyph = *glyphs++; - pPicture = GlyphPicture(glyph)[pScreen->myNum]; - - if (glyph->info.width > 0 && glyph->info.height > 0 && - uxa_buffer_glyph(pScreen, &buffer, glyph, x, - y) == UXA_GLYPH_NEED_FLUSH) { - if (maskFormat) - uxa_glyphs_to_mask(pMask, &buffer); - else - uxa_glyphs_to_dst(op, pSrc, pDst, - &buffer, xSrc, ySrc, - xDst, yDst); - - uxa_buffer_glyph(pScreen, &buffer, glyph, x, y); + GlyphPtr glyph = *glyphs++; + PicturePtr g = GlyphPicture(glyph)[screen]; + if (g) { + if (maskFormat) { + CompositePicture(PictOpAdd, g, NULL, mask, + 0, 0, + 0, 0, + x - glyph->info.x, + y - glyph->info.y, + glyph->info.width, + glyph->info.height); + } else { + CompositePicture(op, src, g, dst, + xSrc + (x - glyph->info.x) - xDst, + ySrc + (y - glyph->info.y) - yDst, + 0, 0, + x - glyph->info.x, + y - glyph->info.y, + glyph->info.width, + glyph->info.height); + } } x += glyph->info.xOff; @@ -858,24 +528,659 @@ uxa_glyphs(CARD8 op, list++; } - if (buffer.count) { - if (maskFormat) - uxa_glyphs_to_mask(pMask, &buffer); - else - uxa_glyphs_to_dst(op, pSrc, pDst, &buffer, - xSrc, ySrc, xDst, yDst); - } - if (maskFormat) { x = extents.x1; y = extents.y1; - CompositePicture(op, - pSrc, - pMask, - pDst, + CompositePicture(op, src, mask, dst, xSrc + x - xDst, - ySrc + y - yDst, 0, 0, x, y, width, height); - FreePicture((pointer) pMask, (XID) 0); - (*pScreen->DestroyPixmap) (pMaskPixmap); + ySrc + y - yDst, + 0, 0, + x, y, + width, height); + FreePicture(mask, 0); + FreeScratchPixmapHeader(scratch); + pixman_image_unref(image); + } +} + +static inline unsigned int +uxa_glyph_size_to_count(int size) +{ + size /= GLYPH_MIN_SIZE; + return size * size; +} + +static inline unsigned int +uxa_glyph_count_to_mask(int count) +{ + return ~(count - 1); +} + +static inline unsigned int +uxa_glyph_size_to_mask(int size) +{ + return uxa_glyph_count_to_mask(uxa_glyph_size_to_count(size)); +} + +static PicturePtr +uxa_glyph_cache(ScreenPtr screen, GlyphPtr glyph, int *out_x, int *out_y) +{ + uxa_screen_t *uxa_screen = uxa_get_screen(screen); + PicturePtr glyph_picture = GlyphPicture(glyph)[screen->myNum]; + uxa_glyph_cache_t *cache = &uxa_screen->glyphCaches[PICT_FORMAT_RGB(glyph_picture->format) != 0]; + struct uxa_glyph *priv = NULL; + int size, mask, pos, s; + + if (glyph->info.width > GLYPH_MAX_SIZE || glyph->info.height > GLYPH_MAX_SIZE) + return NULL; + + for (size = GLYPH_MIN_SIZE; size <= GLYPH_MAX_SIZE; size *= 2) + if (glyph->info.width <= size && glyph->info.height <= size) + break; + + s = uxa_glyph_size_to_count(size); + mask = uxa_glyph_count_to_mask(s); + pos = (cache->count + s - 1) & mask; + if (pos < GLYPH_CACHE_SIZE) { + cache->count = pos + s; + } else { + for (s = size; s <= GLYPH_MAX_SIZE; s *= 2) { + int i = cache->evict & uxa_glyph_size_to_mask(s); + GlyphPtr evicted = cache->glyphs[i]; + if (evicted == NULL) + continue; + + priv = uxa_glyph_get_private(evicted); + if (priv->size >= s) { + cache->glyphs[i] = NULL; + uxa_glyph_set_private(evicted, NULL); + pos = cache->evict & uxa_glyph_size_to_mask(size); + } else + priv = NULL; + break; + } + if (priv == NULL) { + int count = uxa_glyph_size_to_count(size); + mask = uxa_glyph_count_to_mask(count); + pos = cache->evict & mask; + for (s = 0; s < count; s++) { + GlyphPtr evicted = cache->glyphs[pos + s]; + if (evicted != NULL) { + if (priv != NULL) + free(priv); + + priv = uxa_glyph_get_private(evicted); + uxa_glyph_set_private(evicted, NULL); + cache->glyphs[pos + s] = NULL; + } + } + } + + /* And pick a new eviction position */ + cache->evict = rand() % GLYPH_CACHE_SIZE; + } + + if (priv == NULL) { + priv = malloc(sizeof(struct uxa_glyph)); + if (priv == NULL) + return NULL; + } + + uxa_glyph_set_private(glyph, priv); + cache->glyphs[pos] = glyph; + + priv->cache = cache; + priv->size = size; + priv->pos = pos; + s = pos / ((GLYPH_MAX_SIZE / GLYPH_MIN_SIZE) * (GLYPH_MAX_SIZE / GLYPH_MIN_SIZE)); + priv->x = s % (CACHE_PICTURE_SIZE / GLYPH_MAX_SIZE) * GLYPH_MAX_SIZE; + priv->y = (s / (CACHE_PICTURE_SIZE / GLYPH_MAX_SIZE)) * GLYPH_MAX_SIZE; + for (s = GLYPH_MIN_SIZE; s < GLYPH_MAX_SIZE; s *= 2) { + if (pos & 1) + priv->x += s; + if (pos & 2) + priv->y += s; + pos >>= 2; + } + + uxa_glyph_cache_upload_glyph(screen, cache, glyph, priv->x, priv->y); + + *out_x = priv->x; + *out_y = priv->y; + return cache->picture; +} + +static int +uxa_glyphs_to_dst(CARD8 op, + PicturePtr pSrc, + PicturePtr pDst, + INT16 src_x, INT16 src_y, + INT16 xDst, INT16 yDst, + int nlist, GlyphListPtr list, GlyphPtr * glyphs, + BoxPtr extents) +{ + ScreenPtr screen = pDst->pDrawable->pScreen; + uxa_screen_t *uxa_screen = uxa_get_screen(screen); + PixmapPtr src_pixmap, dst_pixmap; + PicturePtr localSrc, glyph_atlas; + int x, y, n; + BoxRec box; + + if (uxa_screen->info->check_composite_texture && + uxa_screen->info->check_composite_texture(screen, pSrc)) { + if (pSrc->pDrawable) { + int src_off_x, src_off_y; + + src_pixmap = uxa_get_offscreen_pixmap(pSrc->pDrawable, &src_off_x, &src_off_y); + if (src_pixmap == NULL) + return -1; + + src_x += pSrc->pDrawable->x + src_off_x; + src_y += pSrc->pDrawable->y + src_off_y; + } else { + src_pixmap = NULL; + } + localSrc = pSrc; + } else { + int width, height; + + if (extents == NULL) { + uxa_glyph_extents(nlist, list, glyphs, &box); + extents = &box; + } + + width = extents->x2 - extents->x1; + height = extents->y2 - extents->y1; + if (width == 0 || height == 0) + return 0; + + if (pSrc->pDrawable) { + int src_off_x, src_off_y; + + src_off_x = extents->x1 - xDst; + src_off_y = extents->y1 - yDst; + localSrc = uxa_acquire_drawable(screen, pSrc, + src_x + src_off_x, src_y + src_off_y, + width, height, + &src_x, &src_y); + if (uxa_screen->info->check_composite_texture && + !uxa_screen->info->check_composite_texture(screen, localSrc)) { + if (localSrc != pSrc) + FreePicture(localSrc, 0); + return -1; + } + + src_pixmap = uxa_get_offscreen_pixmap(localSrc->pDrawable, &src_off_x, &src_off_y); + if (src_pixmap == NULL) { + if (localSrc != pSrc) + FreePicture(localSrc, 0); + return -1; + } + + src_x += localSrc->pDrawable->x + src_off_x; + src_y += localSrc->pDrawable->y + src_off_y; + } else { + localSrc = uxa_acquire_pattern(screen, pSrc, + PICT_a8r8g8b8, x, y, width, height); + if (!localSrc) + return 1; + + src_pixmap = uxa_get_drawable_pixmap(localSrc->pDrawable); + if (src_pixmap == NULL) { + FreePicture(localSrc, 0); + return -1; + } + + src_x = src_y = 0; + } + } + + dst_pixmap = uxa_get_offscreen_pixmap(pDst->pDrawable, &x, &y); + x += xDst + pDst->pDrawable->x - list->xOff; + y += yDst + pDst->pDrawable->y - list->yOff; + + glyph_atlas = NULL; + while (nlist--) { + x += list->xOff; + y += list->yOff; + n = list->len; + while (n--) { + GlyphPtr glyph = *glyphs++; + PicturePtr this_atlas; + int mask_x, mask_y, nrect; + struct uxa_glyph *priv; + BoxPtr rects; + + if (glyph->info.width == 0 || glyph->info.height == 0) + goto next_glyph; + + priv = uxa_glyph_get_private(glyph); + if (priv != NULL) { + mask_x = priv->x; + mask_y = priv->y; + this_atlas = priv->cache->picture; + } else { + if (glyph_atlas) { + uxa_screen->info->done_composite(dst_pixmap); + glyph_atlas = NULL; + } + this_atlas = uxa_glyph_cache(screen, glyph, &mask_x, &mask_y); + if (this_atlas == NULL) { + /* no cache for this glyph */ + this_atlas = GlyphPicture(glyph)[screen->myNum]; + mask_x = mask_y = 0; + } + } + + if (this_atlas != glyph_atlas) { + PixmapPtr mask_pixmap; + + if (glyph_atlas) + uxa_screen->info->done_composite(dst_pixmap); + + mask_pixmap = + uxa_get_drawable_pixmap(this_atlas->pDrawable); + assert (uxa_pixmap_is_offscreen(mask_pixmap)); + + if (!uxa_screen->info->prepare_composite(op, + localSrc, this_atlas, pDst, + src_pixmap, mask_pixmap, dst_pixmap)) + return -1; + + glyph_atlas = this_atlas; + } + + rects = REGION_RECTS(pDst->pCompositeClip); + nrect = REGION_NUM_RECTS(pDst->pCompositeClip); + while (nrect--) { + int x1 = x - glyph->info.x, dx = 0; + int y1 = y - glyph->info.y, dy = 0; + int x2 = x1 + glyph->info.width; + int y2 = y1 + glyph->info.height; + + if (rects->y1 >= y2) + break; + + if (x1 < rects->x1) + dx = rects->x1 - x1, x1 = rects->x1; + if (x2 > rects->x2) + x2 = rects->x2; + if (y1 < rects->y1) + dy = rects->y1 - y1, y1 = rects->y1; + if (y2 > rects->y2) + y2 = rects->y2; + + if (x1 < x2 && y1 < y2) { + uxa_screen->info->composite(dst_pixmap, + x1 + src_x, y1 + src_y, + dx + mask_x, dy + mask_y, + x1, y1, + x2 - x1, y2 - y1); + } + rects++; + } + +next_glyph: + x += glyph->info.xOff; + y += glyph->info.yOff; + } + list++; + } + if (glyph_atlas) + uxa_screen->info->done_composite(dst_pixmap); + + if (localSrc != pSrc) + FreePicture(localSrc, 0); + + return 0; +} + +static void +uxa_clear_pixmap(ScreenPtr screen, + uxa_screen_t *uxa_screen, + PixmapPtr pixmap) +{ + if (uxa_screen->info->check_solid && + !uxa_screen->info->check_solid(&pixmap->drawable, GXcopy, FB_ALLONES)) + goto fallback; + + if (!uxa_screen->info->prepare_solid(pixmap, GXcopy, FB_ALLONES, 0)) + goto fallback; + + uxa_screen->info->solid(pixmap, + 0, 0, + pixmap->drawable.width, + pixmap->drawable.height); + + uxa_screen->info->done_solid(pixmap); + return; + +fallback: + { + GCPtr gc; + + gc = GetScratchGC(pixmap->drawable.depth, screen); + if (gc) { + xRectangle rect; + + ValidateGC(&pixmap->drawable, gc); + + rect.x = 0; + rect.y = 0; + rect.width = pixmap->drawable.width; + rect.height = pixmap->drawable.height; + gc->ops->PolyFillRect(&pixmap->drawable, gc, 1, &rect); + + FreeScratchGC(gc); + } + } +} + +static int +uxa_glyphs_via_mask(CARD8 op, + PicturePtr pSrc, + PicturePtr pDst, + PictFormatPtr maskFormat, + INT16 xSrc, INT16 ySrc, + INT16 xDst, INT16 yDst, + int nlist, GlyphListPtr list, GlyphPtr * glyphs, + BoxPtr extents) +{ + ScreenPtr screen = pDst->pDrawable->pScreen; + uxa_screen_t *uxa_screen = uxa_get_screen(screen); + CARD32 component_alpha; + PixmapPtr pixmap; + PicturePtr glyph_atlas, mask; + int x, y, width, height; + int dst_off_x, dst_off_y; + int n, error; + BoxRec box; + + if (!extents) { + uxa_glyph_extents(nlist, list, glyphs, &box); + + if (box.x2 <= box.x1 || box.y2 <= box.y1) + return 0; + + extents = &box; + dst_off_x = box.x1; + dst_off_y = box.y1; + } else { + dst_off_x = dst_off_y = 0; + } + + width = extents->x2 - extents->x1; + height = extents->y2 - extents->y1; + x = -extents->x1; + y = -extents->y1; + + if (maskFormat->depth == 1) { + PictFormatPtr a8Format = + PictureMatchFormat(screen, 8, PICT_a8); + + if (!a8Format) + return -1; + + maskFormat = a8Format; + } + + pixmap = screen->CreatePixmap(screen, width, height, + maskFormat->depth, + CREATE_PIXMAP_USAGE_SCRATCH); + if (!pixmap) + return 1; + + uxa_clear_pixmap(screen, uxa_screen, pixmap); + + component_alpha = NeedsComponent(maskFormat->format); + mask = CreatePicture(0, &pixmap->drawable, + maskFormat, CPComponentAlpha, + &component_alpha, serverClient, &error); + screen->DestroyPixmap(pixmap); + + if (!mask) + return 1; + + ValidatePicture(mask); + + glyph_atlas = NULL; + while (nlist--) { + x += list->xOff; + y += list->yOff; + n = list->len; + while (n--) { + GlyphPtr glyph = *glyphs++; + PicturePtr this_atlas; + int src_x, src_y; + struct uxa_glyph *priv; + + if (glyph->info.width == 0 || glyph->info.height == 0) + goto next_glyph; + + priv = uxa_glyph_get_private(glyph); + if (priv != NULL) { + src_x = priv->x; + src_y = priv->y; + this_atlas = priv->cache->picture; + } else { + if (glyph_atlas) { + uxa_screen->info->done_composite(pixmap); + glyph_atlas = NULL; + } + this_atlas = uxa_glyph_cache(screen, glyph, &src_x, &src_y); + if (this_atlas == NULL) { + /* no cache for this glyph */ + this_atlas = GlyphPicture(glyph)[screen->myNum]; + src_x = src_y = 0; + } + } + + if (this_atlas != glyph_atlas) { + PixmapPtr src_pixmap; + + if (glyph_atlas) + uxa_screen->info->done_composite(pixmap); + + src_pixmap = + uxa_get_drawable_pixmap(this_atlas->pDrawable); + assert (uxa_pixmap_is_offscreen(src_pixmap)); + + if (!uxa_screen->info->prepare_composite(PictOpAdd, + this_atlas, NULL, mask, + src_pixmap, NULL, pixmap)) + return -1; + + glyph_atlas = this_atlas; + } + + uxa_screen->info->composite(pixmap, + src_x, src_y, + 0, 0, + x - glyph->info.x, + y - glyph->info.y, + glyph->info.width, + glyph->info.height); + +next_glyph: + x += glyph->info.xOff; + y += glyph->info.yOff; + } + list++; + } + if (glyph_atlas) + uxa_screen->info->done_composite(pixmap); + + uxa_composite(op, + pSrc, mask, pDst, + dst_off_x + xSrc - xDst, + dst_off_y + ySrc - yDst, + 0, 0, + dst_off_x, dst_off_y, + width, height); + + FreePicture(mask, 0); + return 0; +} + +void +uxa_glyphs(CARD8 op, + PicturePtr pSrc, + PicturePtr pDst, + PictFormatPtr maskFormat, + INT16 xSrc, INT16 ySrc, + int nlist, GlyphListPtr list, GlyphPtr * glyphs) +{ + ScreenPtr screen = pDst->pDrawable->pScreen; + uxa_screen_t *uxa_screen = uxa_get_screen(screen); + int xDst = list->xOff, yDst = list->yOff; + BoxRec extents = { 0, 0, 0, 0 }; + Bool have_extents = FALSE; + int width, height, ret; + PicturePtr localDst = pDst; + + if (!uxa_screen->info->prepare_composite || + uxa_screen->swappedOut || + !uxa_drawable_is_offscreen(pDst->pDrawable) || + pDst->alphaMap || pSrc->alphaMap) { +fallback: + uxa_check_glyphs(op, pSrc, pDst, maskFormat, xSrc, ySrc, nlist, list, glyphs); + return; + } + + /* basic sanity check */ + if (uxa_screen->info->check_composite && + !uxa_screen->info->check_composite(op, pSrc, NULL, pDst, 0, 0)) { + goto fallback; + } + + ValidatePicture(pSrc); + ValidatePicture(pDst); + + if (!maskFormat) { + /* If we don't have a mask format but all the glyphs have the same format, + * require ComponentAlpha and don't intersect, use the glyph format as mask + * format for the full benefits of the glyph cache. + */ + if (NeedsComponent(list[0].format->format)) { + Bool sameFormat = TRUE; + int i; + + maskFormat = list[0].format; + + for (i = 0; i < nlist; i++) { + if (maskFormat->format != list[i].format->format) { + sameFormat = FALSE; + break; + } + } + + if (!sameFormat || + uxa_glyphs_intersect(nlist, list, glyphs)) + maskFormat = NULL; + } + } + + if (!maskFormat && + uxa_screen->info->check_composite_target && + !uxa_screen->info->check_composite_target(uxa_get_drawable_pixmap(pDst->pDrawable))) { + int depth = pDst->pDrawable->depth; + PixmapPtr pixmap; + int x, y, error; + GCPtr gc; + + pixmap = uxa_get_drawable_pixmap(pDst->pDrawable); + if (uxa_screen->info->check_copy && + !uxa_screen->info->check_copy(pixmap, pixmap, GXcopy, FB_ALLONES)) + goto fallback; + + uxa_glyph_extents(nlist, list, glyphs, &extents); + + /* clip against dst bounds */ + if (extents.x1 < 0) + extents.x1 = 0; + if (extents.y1 < 0) + extents.y1 = 0; + if (extents.x2 > pDst->pDrawable->width) + extents.x2 = pDst->pDrawable->width; + if (extents.y2 > pDst->pDrawable->height) + extents.y2 = pDst->pDrawable->height; + + if (extents.x2 <= extents.x1 || extents.y2 <= extents.y1) + return; + width = extents.x2 - extents.x1; + height = extents.y2 - extents.y1; + x = -extents.x1; + y = -extents.y1; + have_extents = TRUE; + + xDst += x; + yDst += y; + + pixmap = screen->CreatePixmap(screen, + width, height, depth, + CREATE_PIXMAP_USAGE_SCRATCH); + if (!pixmap) + return; + + gc = GetScratchGC(depth, screen); + if (!gc) { + screen->DestroyPixmap(pixmap); + return; + } + + ValidateGC(&pixmap->drawable, gc); + gc->ops->CopyArea(pDst->pDrawable, &pixmap->drawable, gc, + extents.x1, extents.y1, + width, height, + 0, 0); + FreeScratchGC(gc); + + localDst = CreatePicture(0, &pixmap->drawable, + PictureMatchFormat(screen, depth, pDst->format), + 0, 0, serverClient, &error); + screen->DestroyPixmap(pixmap); + + if (!localDst) + return; + + ValidatePicture(localDst); + } + + if (maskFormat) { + ret = uxa_glyphs_via_mask(op, + pSrc, localDst, maskFormat, + xSrc, ySrc, + xDst, yDst, + nlist, list, glyphs, + have_extents ? &extents : NULL); + } else { + ret = uxa_glyphs_to_dst(op, + pSrc, localDst, + xSrc, ySrc, + xDst, yDst, + nlist, list, glyphs, + have_extents ? &extents : NULL); + } + if (ret) { + if (localDst != pDst) + FreePicture(localDst, 0); + + goto fallback; + } + + if (localDst != pDst) { + GCPtr gc; + + gc = GetScratchGC(pDst->pDrawable->depth, screen); + if (gc) { + ValidateGC(pDst->pDrawable, gc); + gc->ops->CopyArea(localDst->pDrawable, pDst->pDrawable, gc, + 0, 0, + width, height, + extents.x1, extents.y1); + FreeScratchGC(gc); + } + + FreePicture(localDst, 0); } } diff --git a/uxa/uxa-priv.h b/uxa/uxa-priv.h index c1f3688c..4b988f4e 100644 --- a/uxa/uxa-priv.h +++ b/uxa/uxa-priv.h @@ -41,14 +41,6 @@ #include <X11/X.h> #define NEED_EVENTS #include <X11/Xproto.h> -#ifdef MITSHM -#ifdef HAVE_XEXTPROTO_71 -#include <X11/extensions/shm.h> -#else -#define _XSHM_SERVER_ -#include <X11/extensions/shmstr.h> -#endif -#endif #include "scrnintstr.h" #include "pixmapstr.h" #include "windowstr.h" @@ -103,37 +95,13 @@ char uxa_drawable_location(DrawablePtr pDrawable); #endif typedef struct { - unsigned char sha1[20]; -} uxa_cached_glyph_t; - -typedef struct { - /* The identity of the cache, statically configured at initialization */ - unsigned int format; - int glyphWidth; - int glyphHeight; - - /* Size of cache; eventually this should be dynamically determined */ - int size; - - /* Hash table mapping from glyph sha1 to position in the glyph; we use - * open addressing with a hash table size determined based on size and large - * enough so that we always have a good amount of free space, so we can - * use linear probing. (Linear probing is preferrable to double hashing - * here because it allows us to easily remove entries.) - */ - int *hashEntries; - int hashSize; - - uxa_cached_glyph_t *glyphs; - int glyphCount; /* Current number of glyphs */ - PicturePtr picture; /* Where the glyphs of the cache are stored */ - int yOffset; /* y location within the picture where the cache starts */ - int columns; /* Number of columns the glyphs are layed out in */ - int evictionPosition; /* Next random position to evict a glyph */ + GlyphPtr *glyphs; + uint16_t count; + uint16_t evict; } uxa_glyph_cache_t; -#define UXA_NUM_GLYPH_CACHES 4 +#define UXA_NUM_GLYPH_CACHE_FORMATS 2 typedef struct { uint32_t color; @@ -156,10 +124,12 @@ typedef struct { BitmapToRegionProcPtr SavedBitmapToRegion; #ifdef RENDER CompositeProcPtr SavedComposite; + CompositeRectsProcPtr SavedCompositeRects; TrianglesProcPtr SavedTriangles; GlyphsProcPtr SavedGlyphs; TrapezoidsProcPtr SavedTrapezoids; AddTrapsProcPtr SavedAddTraps; + UnrealizeGlyphProcPtr SavedUnrealizeGlyph; #endif EnableDisableFBAccessProcPtr SavedEnableDisableFBAccess; @@ -168,7 +138,7 @@ typedef struct { unsigned disableFbCount; unsigned offScreenCounter; - uxa_glyph_cache_t glyphCaches[UXA_NUM_GLYPH_CACHES]; + uxa_glyph_cache_t glyphCaches[UXA_NUM_GLYPH_CACHE_FORMATS]; PicturePtr solid_clear, solid_black, solid_white; uxa_solid_cache_t solid_cache[UXA_NUM_SOLID_CACHE]; @@ -187,11 +157,19 @@ typedef struct { (PixmapWidthPaddingInfo[d].padRoundUp+1))) #endif +#if HAS_DEVPRIVATEKEYREC +extern DevPrivateKeyRec uxa_screen_index; +#else extern int uxa_screen_index; +#endif + static inline uxa_screen_t *uxa_get_screen(ScreenPtr screen) { - return (uxa_screen_t *) dixLookupPrivate(&screen->devPrivates, - &uxa_screen_index); +#if HAS_DEVPRIVATEKEYREC + return dixGetPrivate(&screen->devPrivates, &uxa_screen_index); +#else + return dixLookupPrivate(&screen->devPrivates, &uxa_screen_index); +#endif } /** Align an offset to an arbitrary alignment */ @@ -307,11 +285,6 @@ Bool uxa_fill_region_tiled(DrawablePtr pDrawable, RegionPtr pRegion, PixmapPtr pTile, DDXPointPtr pPatOrg, CARD32 planemask, CARD32 alu); -void -uxa_shm_put_image(DrawablePtr pDrawable, GCPtr pGC, int depth, - unsigned int format, int w, int h, int sx, int sy, int sw, - int sh, int dx, int dy, char *data); - void uxa_paint_window(WindowPtr pWin, RegionPtr pRegion, int what); void @@ -320,24 +293,6 @@ uxa_get_image(DrawablePtr pDrawable, int x, int y, int w, int h, extern const GCOps uxa_ops; -#ifdef MITSHM -/* XXX these come from shmint.h, which isn't exported by the server */ - -#ifdef HAVE_XEXTPROTO_71 -#include "shmint.h" -#else - -void ShmRegisterFuncs(ScreenPtr pScreen, ShmFuncsPtr funcs); - -void ShmSetPixmapFormat(ScreenPtr pScreen, int format); - -void fbShmPutImage(XSHM_PUT_IMAGE_ARGS); -#endif - -extern ShmFuncs uxa_shm_funcs; - -#endif - #ifdef RENDER /* XXX these are in fbpict.h, which is not installed */ @@ -417,6 +372,13 @@ uxa_composite_rects(CARD8 op, PicturePtr pDst, int nrect, uxa_composite_rect_t * rects); void +uxa_solid_rects (CARD8 op, + PicturePtr dst, + xRenderColor *color, + int num_rects, + xRectangle *rects); + +void uxa_trapezoids(CARD8 op, PicturePtr pSrc, PicturePtr pDst, PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc, int ntrap, xTrapezoid * traps); @@ -426,8 +388,33 @@ uxa_triangles(CARD8 op, PicturePtr pSrc, PicturePtr pDst, PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc, int ntri, xTriangle * tris); +PicturePtr +uxa_acquire_solid(ScreenPtr screen, SourcePict *source); + +PicturePtr +uxa_acquire_drawable(ScreenPtr pScreen, + PicturePtr pSrc, + INT16 x, INT16 y, + CARD16 width, CARD16 height, + INT16 * out_x, INT16 * out_y); + +PicturePtr +uxa_acquire_pattern(ScreenPtr pScreen, + PicturePtr pSrc, + pixman_format_code_t format, + INT16 x, INT16 y, + CARD16 width, CARD16 height); + +Bool +uxa_get_rgba_from_pixel(CARD32 pixel, + CARD16 * red, + CARD16 * green, + CARD16 * blue, + CARD16 * alpha, + CARD32 format); + /* uxa_glyph.c */ -void uxa_glyphs_init(ScreenPtr pScreen); +Bool uxa_glyphs_init(ScreenPtr pScreen); void uxa_glyphs_fini(ScreenPtr pScreen); @@ -439,4 +426,8 @@ uxa_glyphs(CARD8 op, INT16 xSrc, INT16 ySrc, int nlist, GlyphListPtr list, GlyphPtr * glyphs); +void +uxa_glyph_unrealize(ScreenPtr pScreen, + GlyphPtr pGlyph); + #endif /* UXAPRIV_H */ diff --git a/uxa/uxa-render.c b/uxa/uxa-render.c index 30934d0d..056b60a4 100644 --- a/uxa/uxa-render.c +++ b/uxa/uxa-render.c @@ -85,29 +85,88 @@ static void uxa_composite_fallback_pict_desc(PicturePtr pict, char *string, pict->alphaMap ? " with alpha map" :""); } +static const char * +op_to_string(CARD8 op) +{ + switch (op) { +#define C(x) case PictOp##x: return #x + C(Clear); + C(Src); + C(Dst); + C(Over); + C(OverReverse); + C(In); + C(InReverse); + C(Out); + C(OutReverse); + C(Atop); + C(AtopReverse); + C(Xor); + C(Add); + C(Saturate); + + /* + * Operators only available in version 0.2 + */ + C(DisjointClear); + C(DisjointSrc); + C(DisjointDst); + C(DisjointOver); + C(DisjointOverReverse); + C(DisjointIn); + C(DisjointInReverse); + C(DisjointOut); + C(DisjointOutReverse); + C(DisjointAtop); + C(DisjointAtopReverse); + C(DisjointXor); + + C(ConjointClear); + C(ConjointSrc); + C(ConjointDst); + C(ConjointOver); + C(ConjointOverReverse); + C(ConjointIn); + C(ConjointInReverse); + C(ConjointOut); + C(ConjointOutReverse); + C(ConjointAtop); + C(ConjointAtopReverse); + C(ConjointXor); + + /* + * Operators only available in version 0.11 + */ + C(Multiply); + C(Screen); + C(Overlay); + C(Darken); + C(Lighten); + C(ColorDodge); + C(ColorBurn); + C(HardLight); + C(SoftLight); + C(Difference); + C(Exclusion); + C(HSLHue); + C(HSLSaturation); + C(HSLColor); + C(HSLLuminosity); + default: return "garbage"; +#undef C + } +} + static void uxa_print_composite_fallback(const char *func, CARD8 op, PicturePtr pSrc, PicturePtr pMask, PicturePtr pDst) { uxa_screen_t *uxa_screen = uxa_get_screen(pDst->pDrawable->pScreen); - char sop[20]; char srcdesc[40], maskdesc[40], dstdesc[40]; if (! uxa_screen->fallback_debug) return; - switch (op) { - case PictOpSrc: - sprintf(sop, "Src"); - break; - case PictOpOver: - sprintf(sop, "Over"); - break; - default: - sprintf(sop, "0x%x", (int)op); - break; - } - uxa_composite_fallback_pict_desc(pSrc, srcdesc, 40); uxa_composite_fallback_pict_desc(pMask, maskdesc, 40); uxa_composite_fallback_pict_desc(pDst, dstdesc, 40); @@ -118,7 +177,7 @@ uxa_print_composite_fallback(const char *func, CARD8 op, " mask %s, \n" " dst %s, \n" " screen %s\n", - func, sop, srcdesc, maskdesc, dstdesc, + func, op_to_string (op), srcdesc, maskdesc, dstdesc, uxa_screen->swappedOut ? "swapped out" : "normal"); } @@ -182,7 +241,7 @@ uxa_get_pixel_from_rgba(CARD32 * pixel, return TRUE; } -static Bool +Bool uxa_get_rgba_from_pixel(CARD32 pixel, CARD16 * red, CARD16 * green, @@ -290,7 +349,12 @@ uxa_try_driver_solid_fill(PicturePtr pSrc, PixmapPtr pSrcPix = NULL, pDstPix; CARD32 pixel; - pDstPix = uxa_get_drawable_pixmap(pDst->pDrawable); + if (uxa_screen->info->check_solid && !uxa_screen->info->check_solid(pDst->pDrawable, GXcopy, FB_ALLONES)) + return -1; + + pDstPix = uxa_get_offscreen_pixmap(pDst->pDrawable, &dst_off_x, &dst_off_y); + if (!pDstPix) + return -1; xDst += pDst->pDrawable->x; yDst += pDst->pDrawable->y; @@ -306,16 +370,6 @@ uxa_try_driver_solid_fill(PicturePtr pSrc, width, height)) return 1; - uxa_get_drawable_deltas(pDst->pDrawable, pDstPix, &dst_off_x, - &dst_off_y); - - REGION_TRANSLATE(pScreen, ®ion, dst_off_x, dst_off_y); - - if (!uxa_pixmap_is_offscreen(pDstPix)) { - REGION_UNINIT(pDst->pDrawable->pScreen, ®ion); - return 0; - } - if (pSrcPix) { if (! uxa_get_color_for_pixmap (pSrcPix, pSrc->format, pDst->format, &pixel)) { REGION_UNINIT(pDst->pDrawable->pScreen, ®ion); @@ -334,11 +388,13 @@ uxa_try_driver_solid_fill(PicturePtr pSrc, } if (!(*uxa_screen->info->prepare_solid) - (pDstPix, GXcopy, 0xffffffff, pixel)) { + (pDstPix, GXcopy, FB_ALLONES, pixel)) { REGION_UNINIT(pDst->pDrawable->pScreen, ®ion); return -1; } + REGION_TRANSLATE(pScreen, ®ion, dst_off_x, dst_off_y); + nbox = REGION_NUM_RECTS(®ion); pbox = REGION_RECTS(®ion); @@ -391,74 +447,84 @@ uxa_picture_for_pixman_format(ScreenPtr pScreen, } static PicturePtr -uxa_picture_from_pixman_image(ScreenPtr pScreen, +uxa_picture_from_pixman_image(ScreenPtr screen, pixman_image_t * image, pixman_format_code_t format) { - PicturePtr pPicture; - PixmapPtr pPixmap; + uxa_screen_t *uxa_screen = uxa_get_screen(screen); + PicturePtr picture; + PixmapPtr pixmap; int width, height; width = pixman_image_get_width(image); height = pixman_image_get_height(image); - pPicture = uxa_picture_for_pixman_format(pScreen, format, - width, height); - if (!pPicture) + picture = uxa_picture_for_pixman_format(screen, format, + width, height); + if (!picture) return 0; - pPixmap = GetScratchPixmapHeader(pScreen, width, height, - PIXMAN_FORMAT_DEPTH(format), - PIXMAN_FORMAT_BPP(format), - pixman_image_get_stride(image), - pixman_image_get_data(image)); - if (!pPixmap) { - FreePicture(pPicture, 0); + if (uxa_screen->info->put_image && + ((picture->pDrawable->depth << 24) | picture->format) == format && + uxa_screen->info->put_image((PixmapPtr)picture->pDrawable, + 0, 0, + width, height, + (char *)pixman_image_get_data(image), + pixman_image_get_stride(image))) + return picture; + + pixmap = GetScratchPixmapHeader(screen, width, height, + PIXMAN_FORMAT_DEPTH(format), + PIXMAN_FORMAT_BPP(format), + pixman_image_get_stride(image), + pixman_image_get_data(image)); + if (!pixmap) { + FreePicture(picture, 0); return 0; } - if (((pPicture->pDrawable->depth << 24) | pPicture->format) == format) { - GCPtr pGC; + if (((picture->pDrawable->depth << 24) | picture->format) == format) { + GCPtr gc; - pGC = GetScratchGC(PIXMAN_FORMAT_DEPTH(format), pScreen); - if (!pGC) { - FreeScratchPixmapHeader(pPixmap); - FreePicture(pPicture, 0); - return 0; - } - ValidateGC(pPicture->pDrawable, pGC); + gc = GetScratchGC(PIXMAN_FORMAT_DEPTH(format), screen); + if (!gc) { + FreeScratchPixmapHeader(pixmap); + FreePicture(picture, 0); + return 0; + } + ValidateGC(picture->pDrawable, gc); - (*pGC->ops->CopyArea) (&pPixmap->drawable, pPicture->pDrawable, - pGC, 0, 0, width, height, 0, 0); + (*gc->ops->CopyArea) (&pixmap->drawable, picture->pDrawable, + gc, 0, 0, width, height, 0, 0); - FreeScratchGC(pGC); + FreeScratchGC(gc); } else { - PicturePtr pSrc; - int error; - - pSrc = CreatePicture(0, &pPixmap->drawable, - PictureMatchFormat(pScreen, - PIXMAN_FORMAT_DEPTH(format), - format), - 0, 0, serverClient, &error); - if (!pSrc) { - FreeScratchPixmapHeader(pPixmap); - FreePicture(pPicture, 0); - return 0; - } - ValidatePicture(pSrc); + PicturePtr src; + int error; + + src = CreatePicture(0, &pixmap->drawable, + PictureMatchFormat(screen, + PIXMAN_FORMAT_DEPTH(format), + format), + 0, 0, serverClient, &error); + if (!src) { + FreeScratchPixmapHeader(pixmap); + FreePicture(picture, 0); + return 0; + } + ValidatePicture(src); - if (uxa_prepare_access(pPicture->pDrawable, UXA_ACCESS_RW)) { - fbComposite(PictOpSrc, pSrc, NULL, pPicture, - 0, 0, 0, 0, 0, 0, width, height); - uxa_finish_access(pPicture->pDrawable); - } + if (uxa_prepare_access(picture->pDrawable, UXA_ACCESS_RW)) { + fbComposite(PictOpSrc, src, NULL, picture, + 0, 0, 0, 0, 0, 0, width, height); + uxa_finish_access(picture->pDrawable); + } - FreePicture(pSrc, 0); + FreePicture(src, 0); } - FreeScratchPixmapHeader(pPixmap); + FreeScratchPixmapHeader(pixmap); - return pPicture; + return picture; } static PicturePtr @@ -490,6 +556,21 @@ uxa_create_solid(ScreenPtr screen, uint32_t color) } static PicturePtr +uxa_solid_clear(ScreenPtr screen) +{ + uxa_screen_t *uxa_screen = uxa_get_screen(screen); + PicturePtr picture; + + if (!uxa_screen->solid_clear) { + uxa_screen->solid_clear = uxa_create_solid(screen, 0); + if (!uxa_screen->solid_clear) + return 0; + } + picture = uxa_screen->solid_clear; + return picture; +} + +PicturePtr uxa_acquire_solid(ScreenPtr screen, SourcePict *source) { uxa_screen_t *uxa_screen = uxa_get_screen(screen); @@ -498,12 +579,10 @@ uxa_acquire_solid(ScreenPtr screen, SourcePict *source) int i; if ((solid->color >> 24) == 0) { - if (!uxa_screen->solid_clear) { - uxa_screen->solid_clear = uxa_create_solid(screen, 0); - if (!uxa_screen->solid_clear) - return 0; - } - picture = uxa_screen->solid_clear; + picture = uxa_solid_clear(screen); + if (!picture) + return 0; + goto DONE; } else if (solid->color == 0xff000000) { if (!uxa_screen->solid_black) { @@ -548,7 +627,7 @@ DONE: return picture; } -static PicturePtr +PicturePtr uxa_acquire_pattern(ScreenPtr pScreen, PicturePtr pSrc, pixman_format_code_t format, @@ -577,158 +656,398 @@ uxa_acquire_pattern(ScreenPtr pScreen, } } -static PicturePtr -uxa_acquire_source(ScreenPtr pScreen, - PicturePtr pPict, - INT16 x, INT16 y, - CARD16 width, CARD16 height, INT16 * out_x, INT16 * out_y) +static Bool +transform_is_integer_translation(PictTransformPtr t, int *tx, int *ty) { - if (pPict->pDrawable) { - *out_x = x + pPict->pDrawable->x; - *out_y = y + pPict->pDrawable->y; - return pPict; + if (t == NULL) { + *tx = *ty = 0; + return TRUE; } - *out_x = 0; - *out_y = 0; - return uxa_acquire_pattern(pScreen, pPict, - PICT_a8r8g8b8, x, y, width, height); + if (t->matrix[0][0] != IntToxFixed(1) || + t->matrix[0][1] != 0 || + t->matrix[1][0] != 0 || + t->matrix[1][1] != IntToxFixed(1) || + t->matrix[2][0] != 0 || + t->matrix[2][1] != 0 || + t->matrix[2][2] != IntToxFixed(1)) + return FALSE; + + if (xFixedFrac(t->matrix[0][2]) != 0 || + xFixedFrac(t->matrix[1][2]) != 0) + return FALSE; + + *tx = xFixedToInt(t->matrix[0][2]); + *ty = xFixedToInt(t->matrix[1][2]); + return TRUE; } static PicturePtr -uxa_acquire_mask(ScreenPtr pScreen, - PicturePtr pPict, - INT16 x, INT16 y, - INT16 width, INT16 height, INT16 * out_x, INT16 * out_y) +uxa_render_picture(ScreenPtr screen, + PicturePtr src, + pixman_format_code_t format, + INT16 x, INT16 y, + CARD16 width, CARD16 height) { - if (pPict->pDrawable) { - *out_x = x + pPict->pDrawable->x; - *out_y = y + pPict->pDrawable->y; - return pPict; + PicturePtr picture; + int ret = 0; + + /* XXX we need a mechanism for the card to choose the fallback format */ + + /* force alpha channel in case source does not entirely cover the extents */ + if (PIXMAN_FORMAT_A(format) == 0) + format = PIXMAN_a8r8g8b8; /* available on all hardware */ + + picture = uxa_picture_for_pixman_format(screen, format, width, height); + if (!picture) + return 0; + + if (uxa_prepare_access(picture->pDrawable, UXA_ACCESS_RW)) { + if (uxa_prepare_access(src->pDrawable, UXA_ACCESS_RO)) { + ret = 1; + fbComposite(PictOpSrc, src, NULL, picture, + x, y, 0, 0, 0, 0, width, height); + uxa_finish_access(src->pDrawable); + } + uxa_finish_access(picture->pDrawable); } - *out_x = 0; - *out_y = 0; - return uxa_acquire_pattern(pScreen, pPict, - PICT_a8, x, y, width, height); + if (!ret) { + FreePicture(picture, 0); + return 0; + } + + return picture; } static int -uxa_try_driver_composite_rects(CARD8 op, - PicturePtr pSrc, - PicturePtr pDst, - int nrect, uxa_composite_rect_t * rects) +drawable_contains (DrawablePtr drawable, int x, int y, int w, int h) { - uxa_screen_t *uxa_screen = uxa_get_screen(pDst->pDrawable->pScreen); - int src_off_x, src_off_y, dst_off_x, dst_off_y; - PixmapPtr pSrcPix, pDstPix; + if (x < 0 || y < 0) + return FALSE; - if (!uxa_screen->info->prepare_composite || uxa_screen->swappedOut) - return -1; + if (x + w > drawable->width) + return FALSE; - if (uxa_screen->info->check_composite && - !(*uxa_screen->info->check_composite) (op, pSrc, NULL, pDst)) { - return -1; + if (y + h > drawable->height) + return FALSE; + + return TRUE; +} + +PicturePtr +uxa_acquire_drawable(ScreenPtr pScreen, + PicturePtr pSrc, + INT16 x, INT16 y, + CARD16 width, CARD16 height, + INT16 * out_x, INT16 * out_y) +{ + PixmapPtr pPixmap; + PicturePtr pDst; + int depth, error; + int tx, ty; + GCPtr pGC; + + depth = pSrc->pDrawable->depth; + if (!transform_is_integer_translation(pSrc->transform, &tx, &ty) || + !drawable_contains(pSrc->pDrawable, x + tx, y + ty, width, height) || + depth == 1 || + pSrc->filter == PictFilterConvolution) { + /* XXX extract the sample extents and do the transformation on the GPU */ + pDst = uxa_render_picture(pScreen, pSrc, + pSrc->format | (BitsPerPixel(pSrc->pDrawable->depth) << 24), + x, y, width, height); + + goto done; + } else { + if (width == pSrc->pDrawable->width && height == pSrc->pDrawable->height) { + *out_x = x + pSrc->pDrawable->x; + *out_y = y + pSrc->pDrawable->y; + return pSrc; + } } - pDstPix = - uxa_get_offscreen_pixmap(pDst->pDrawable, &dst_off_x, &dst_off_y); - if (!pDstPix) + pPixmap = pScreen->CreatePixmap(pScreen, + width, height, depth, + CREATE_PIXMAP_USAGE_SCRATCH); + if (!pPixmap) return 0; - pSrcPix = - uxa_get_offscreen_pixmap(pSrc->pDrawable, &src_off_x, &src_off_y); - if (!pSrcPix) + /* Skip the copy if the result remains in memory and not a bo */ + if (!uxa_pixmap_is_offscreen(pPixmap)) { + pScreen->DestroyPixmap(pPixmap); return 0; + } - if (!(*uxa_screen->info->prepare_composite) - (op, pSrc, NULL, pDst, pSrcPix, NULL, pDstPix)) - return -1; + pGC = GetScratchGC(depth, pScreen); + if (!pGC) { + pScreen->DestroyPixmap(pPixmap); + return 0; + } + + ValidateGC(&pPixmap->drawable, pGC); + pGC->ops->CopyArea(pSrc->pDrawable, &pPixmap->drawable, pGC, + x + tx, y + ty, width, height, 0, 0); + FreeScratchGC(pGC); + + pDst = CreatePicture(0, &pPixmap->drawable, + PictureMatchFormat(pScreen, depth, pSrc->format), + 0, 0, serverClient, &error); + pScreen->DestroyPixmap(pPixmap); + ValidatePicture(pDst); + +done: + pDst->componentAlpha = pSrc->componentAlpha; + *out_x = 0; + *out_y = 0; + return pDst; +} - while (nrect--) { - INT16 xDst = rects->xDst + pDst->pDrawable->x; - INT16 yDst = rects->yDst + pDst->pDrawable->y; - INT16 xSrc = rects->xSrc + pSrc->pDrawable->x; - INT16 ySrc = rects->ySrc + pSrc->pDrawable->y; - - RegionRec region; - BoxPtr pbox; - int nbox; - - if (!miComputeCompositeRegion(®ion, pSrc, NULL, pDst, - xSrc, ySrc, 0, 0, xDst, yDst, - rects->width, rects->height)) - goto next_rect; - - REGION_TRANSLATE(pScreen, ®ion, dst_off_x, dst_off_y); - - nbox = REGION_NUM_RECTS(®ion); - pbox = REGION_RECTS(®ion); - - xSrc = xSrc + src_off_x - xDst - dst_off_x; - ySrc = ySrc + src_off_y - yDst - dst_off_y; - - while (nbox--) { - (*uxa_screen->info->composite) (pDstPix, - pbox->x1 + xSrc, - pbox->y1 + ySrc, - 0, 0, - pbox->x1, - pbox->y1, - pbox->x2 - pbox->x1, - pbox->y2 - pbox->y1); - pbox++; +static PicturePtr +uxa_acquire_picture(ScreenPtr screen, + PicturePtr src, + pixman_format_code_t format, + INT16 x, INT16 y, + CARD16 width, CARD16 height, + INT16 * out_x, INT16 * out_y) +{ + uxa_screen_t *uxa_screen = uxa_get_screen(screen); + + if (uxa_screen->info->check_composite_texture && + uxa_screen->info->check_composite_texture(screen, src)) { + if (src->pDrawable) { + *out_x = x + src->pDrawable->x; + *out_y = y + src->pDrawable->y; + } else { + *out_x = x; + *out_y = y; } + return src; + } -next_rect: - REGION_UNINIT(pDst->pDrawable->pScreen, ®ion); + if (src->pDrawable) { + PicturePtr dst; - rects++; + dst = uxa_acquire_drawable(screen, src, + x, y, width, height, + out_x, out_y); + if (!dst) + return 0; + + if (uxa_screen->info->check_composite_texture && + !uxa_screen->info->check_composite_texture(screen, dst)) { + if (dst != src) + FreePicture(dst, 0); + return 0; + } + + return dst; } - (*uxa_screen->info->done_composite) (pDstPix); - return 1; + *out_x = 0; + *out_y = 0; + return uxa_acquire_pattern(screen, src, + format, x, y, width, height); +} + +static PicturePtr +uxa_acquire_source(ScreenPtr screen, + PicturePtr pict, + INT16 x, INT16 y, + CARD16 width, CARD16 height, + INT16 * out_x, INT16 * out_y) +{ + return uxa_acquire_picture (screen, pict, + PICT_a8r8g8b8, + x, y, + width, height, + out_x, out_y); +} + +static PicturePtr +uxa_acquire_mask(ScreenPtr screen, + PicturePtr pict, + INT16 x, INT16 y, + INT16 width, INT16 height, + INT16 * out_x, INT16 * out_y) +{ + return uxa_acquire_picture (screen, pict, + PICT_a8, + x, y, + width, height, + out_x, out_y); +} + +static Bool +_pixman_region_init_rectangles(pixman_region16_t *region, + int num_rects, + xRectangle *rects, + int tx, int ty) +{ + pixman_box16_t stack_boxes[64], *boxes = stack_boxes; + pixman_bool_t ret; + int i; + + if (num_rects > sizeof(stack_boxes) / sizeof(stack_boxes[0])) { + boxes = malloc(sizeof(pixman_box16_t) * num_rects); + if (boxes == NULL) + return FALSE; + } + + for (i = 0; i < num_rects; i++) { + boxes[i].x1 = rects[i].x + tx; + boxes[i].y1 = rects[i].y + ty; + boxes[i].x2 = rects[i].x + tx + rects[i].width; + boxes[i].y2 = rects[i].y + ty + rects[i].height; + } + + ret = pixman_region_init_rects(region, boxes, num_rects); + + if (boxes != stack_boxes) + free(boxes); + + return ret; } -/** - * Copy a number of rectangles from source to destination in a single - * operation. This is specialized for building a glyph mask: we don'y - * have a mask argument because we don't need it for that, and we - * don't have he special-case fallbacks found in uxa_composite() - if the - * driver can support it, we use the driver functionality, otherwise we - * fallback straight to software. - */ void -uxa_composite_rects(CARD8 op, - PicturePtr pSrc, - PicturePtr pDst, int nrect, uxa_composite_rect_t * rects) +uxa_solid_rects (CARD8 op, + PicturePtr dst, + xRenderColor *color, + int num_rects, + xRectangle *rects) { - int n; - uxa_composite_rect_t *r; + ScreenPtr screen = dst->pDrawable->pScreen; + uxa_screen_t *uxa_screen = uxa_get_screen(screen); + PixmapPtr dst_pixmap, src_pixmap = NULL; + pixman_region16_t region; + pixman_box16_t *boxes, *extents; + PicturePtr src; + int dst_x, dst_y; + int num_boxes; + + if (!pixman_region_not_empty(dst->pCompositeClip)) + return; - /************************************************************/ + if (dst->alphaMap) + goto fallback; - ValidatePicture(pSrc); - ValidatePicture(pDst); + dst_pixmap = uxa_get_offscreen_pixmap(dst->pDrawable, &dst_x, &dst_y); + if (!dst_pixmap) + goto fallback; + + if (!_pixman_region_init_rectangles(®ion, + num_rects, rects, + dst->pDrawable->x, dst->pDrawable->y)) + goto fallback; + + if (!pixman_region_intersect(®ion, ®ion, dst->pCompositeClip)) { + pixman_region_fini(®ion); + return; + } + + /* XXX xserver-1.8: CompositeRects is not tracked by Damage, so we must + * manually append the damaged regions ourselves. + */ + DamageRegionAppend(dst->pDrawable, ®ion); + + pixman_region_translate(®ion, dst_x, dst_y); + boxes = pixman_region_rectangles(®ion, &num_boxes); + extents = pixman_region_extents (®ion); + + if (op == PictOpClear) + color->red = color->green = color->blue = color->alpha = 0; + if (color->alpha >= 0xff00 && op == PictOpOver) { + color->alpha = 0xffff; + op = PictOpSrc; + } + + /* Using GEM, the relocation costs outweigh the advantages of the blitter */ + if (num_boxes == 1 && (op == PictOpSrc || op == PictOpClear)) { + CARD32 pixel; + +try_solid: + if (uxa_screen->info->check_solid && + !uxa_screen->info->check_solid(&dst_pixmap->drawable, GXcopy, FB_ALLONES)) + goto err_region; + + if (!uxa_get_pixel_from_rgba(&pixel, + color->red, + color->green, + color->blue, + color->alpha, + dst->format)) + goto err_region; + + if (!uxa_screen->info->prepare_solid(dst_pixmap, GXcopy, FB_ALLONES, pixel)) + goto err_region; + + while (num_boxes--) { + uxa_screen->info->solid(dst_pixmap, + boxes->x1, boxes->y1, + boxes->x2, boxes->y2); + boxes++; + } + + uxa_screen->info->done_solid(dst_pixmap); + } else { + int error; + + src = CreateSolidPicture(0, color, &error); + if (!src) + goto err_region; + + if (!uxa_screen->info->check_composite(op, src, NULL, dst, + extents->x2 - extents->x1, + extents->y2 - extents->y1)) { + if (op == PictOpSrc || op == PictOpClear) { + FreePicture(src, 0); + goto try_solid; + } + + goto err_src; + } - if (uxa_try_driver_composite_rects(op, pSrc, pDst, nrect, rects) != 1) { - uxa_print_composite_fallback("uxa_composite_rects", - op, pSrc, NULL, pDst); - - n = nrect; - r = rects; - while (n--) { - uxa_check_composite(op, pSrc, NULL, pDst, - r->xSrc, r->ySrc, - 0, 0, - r->xDst, r->yDst, - r->width, r->height); - r++; + if (!uxa_screen->info->check_composite_texture || + !uxa_screen->info->check_composite_texture(screen, src)) { + PicturePtr solid; + int src_off_x, src_off_y; + + solid = uxa_acquire_solid(screen, src->pSourcePict); + FreePicture(src, 0); + + src = solid; + src_pixmap = uxa_get_offscreen_pixmap(src->pDrawable, + &src_off_x, &src_off_y); + if (!src_pixmap) + goto err_src; } + + if (!uxa_screen->info->prepare_composite(op, src, NULL, dst, src_pixmap, NULL, dst_pixmap)) + goto err_src; + + while (num_boxes--) { + uxa_screen->info->composite(dst_pixmap, + 0, 0, 0, 0, + boxes->x1, + boxes->y1, + boxes->x2 - boxes->x1, + boxes->y2 - boxes->y1); + boxes++; + } + + uxa_screen->info->done_composite(dst_pixmap); + FreePicture(src, 0); } - /************************************************************/ + pixman_region_fini(®ion); + return; +err_src: + FreePicture(src, 0); +err_region: + pixman_region_fini(®ion); +fallback: + uxa_screen->SavedCompositeRects(op, dst, color, num_rects, rects); } static int @@ -736,130 +1055,217 @@ uxa_try_driver_composite(CARD8 op, PicturePtr pSrc, PicturePtr pMask, PicturePtr pDst, - INT16 xSrc, - INT16 ySrc, - INT16 xMask, - INT16 yMask, - INT16 xDst, INT16 yDst, CARD16 width, CARD16 height) + INT16 xSrc, INT16 ySrc, + INT16 xMask, INT16 yMask, + INT16 xDst, INT16 yDst, + CARD16 width, CARD16 height) { - uxa_screen_t *uxa_screen = uxa_get_screen(pDst->pDrawable->pScreen); + ScreenPtr screen = pDst->pDrawable->pScreen; + uxa_screen_t *uxa_screen = uxa_get_screen(screen); RegionRec region; BoxPtr pbox; int nbox; + int xDst_copy, yDst_copy; int src_off_x, src_off_y, mask_off_x, mask_off_y, dst_off_x, dst_off_y; PixmapPtr pSrcPix, pMaskPix = NULL, pDstPix; PicturePtr localSrc, localMask = NULL; + PicturePtr localDst = pDst; - xDst += pDst->pDrawable->x; - yDst += pDst->pDrawable->y; + if (uxa_screen->info->check_composite && + !(*uxa_screen->info->check_composite) (op, pSrc, pMask, pDst, width, height)) + return -1; + + if (uxa_screen->info->check_composite_target && + !uxa_screen->info->check_composite_target(uxa_get_drawable_pixmap(pDst->pDrawable))) { + int depth = pDst->pDrawable->depth; + PixmapPtr pixmap; + int error; + GCPtr gc; + + pixmap = uxa_get_drawable_pixmap(pDst->pDrawable); + if (uxa_screen->info->check_copy && + !uxa_screen->info->check_copy(pixmap, pixmap, GXcopy, FB_ALLONES)) + return -1; + + pixmap = screen->CreatePixmap(screen, + width, height, depth, + CREATE_PIXMAP_USAGE_SCRATCH); + if (!pixmap) + return 0; + + gc = GetScratchGC(depth, screen); + if (!gc) { + screen->DestroyPixmap(pixmap); + return 0; + } + + ValidateGC(&pixmap->drawable, gc); + gc->ops->CopyArea(pDst->pDrawable, &pixmap->drawable, gc, + xDst, yDst, width, height, 0, 0); + FreeScratchGC(gc); - localSrc = uxa_acquire_source(pDst->pDrawable->pScreen, - pSrc, xSrc, ySrc, width, height, + xDst_copy = xDst; xDst = 0; + yDst_copy = yDst; yDst = 0; + + localDst = CreatePicture(0, &pixmap->drawable, + PictureMatchFormat(screen, depth, pDst->format), + 0, 0, serverClient, &error); + screen->DestroyPixmap(pixmap); + + if (!localDst) + return 0; + + ValidatePicture(localDst); + } + + pDstPix = + uxa_get_offscreen_pixmap(localDst->pDrawable, &dst_off_x, &dst_off_y); + if (!pDstPix) { + if (localDst != pDst) + FreePicture(localDst, 0); + return -1; + } + + xDst += localDst->pDrawable->x; + yDst += localDst->pDrawable->y; + + localSrc = uxa_acquire_source(screen, pSrc, + xSrc, ySrc, + width, height, &xSrc, &ySrc); - if (!localSrc) + if (!localSrc) { + if (localDst != pDst) + FreePicture(localDst, 0); return 0; + } if (pMask) { - localMask = uxa_acquire_mask(pDst->pDrawable->pScreen, - pMask, xMask, yMask, width, height, + localMask = uxa_acquire_mask(screen, pMask, + xMask, yMask, + width, height, &xMask, &yMask); if (!localMask) { if (localSrc != pSrc) FreePicture(localSrc, 0); + if (localDst != pDst) + FreePicture(localDst, 0); return 0; } } - if (uxa_screen->info->check_composite && - !(*uxa_screen->info->check_composite) (op, localSrc, localMask, - pDst)) { - if (localSrc != pSrc) - FreePicture(localSrc, 0); - if (localMask && localMask != pMask) - FreePicture(localMask, 0); - - return -1; - } - - if (!miComputeCompositeRegion(®ion, localSrc, localMask, pDst, + if (!miComputeCompositeRegion(®ion, localSrc, localMask, localDst, xSrc, ySrc, xMask, yMask, xDst, yDst, width, height)) { if (localSrc != pSrc) FreePicture(localSrc, 0); if (localMask && localMask != pMask) FreePicture(localMask, 0); + if (localDst != pDst) + FreePicture(localDst, 0); return 1; } - pDstPix = - uxa_get_offscreen_pixmap(pDst->pDrawable, &dst_off_x, &dst_off_y); + if (localSrc->pDrawable) { + pSrcPix = uxa_get_offscreen_pixmap(localSrc->pDrawable, + &src_off_x, &src_off_y); + if (!pSrcPix) { + REGION_UNINIT(screen, ®ion); - pSrcPix = uxa_get_offscreen_pixmap(localSrc->pDrawable, - &src_off_x, &src_off_y); + if (localSrc != pSrc) + FreePicture(localSrc, 0); + if (localMask && localMask != pMask) + FreePicture(localMask, 0); + if (localDst != pDst) + FreePicture(localDst, 0); - if (localMask) - pMaskPix = uxa_get_offscreen_pixmap(localMask->pDrawable, - &mask_off_x, &mask_off_y); + return 0; + } + } else { + pSrcPix = NULL; + } - if (!pDstPix || !pSrcPix || (localMask && !pMaskPix)) { - REGION_UNINIT(pDst->pDrawable->pScreen, ®ion); + if (localMask) { + if (localMask->pDrawable) { + pMaskPix = uxa_get_offscreen_pixmap(localMask->pDrawable, + &mask_off_x, &mask_off_y); + if (!pMaskPix) { + REGION_UNINIT(screen, ®ion); - if (localSrc != pSrc) - FreePicture(localSrc, 0); - if (localMask && localMask != pMask) - FreePicture(localMask, 0); + if (localSrc != pSrc) + FreePicture(localSrc, 0); + if (localMask && localMask != pMask) + FreePicture(localMask, 0); + if (localDst != pDst) + FreePicture(localDst, 0); - return 0; + return 0; + } + } else { + pMaskPix = NULL; + } } - REGION_TRANSLATE(pScreen, ®ion, dst_off_x, dst_off_y); - if (!(*uxa_screen->info->prepare_composite) - (op, localSrc, localMask, pDst, pSrcPix, pMaskPix, pDstPix)) { - REGION_UNINIT(pDst->pDrawable->pScreen, ®ion); + (op, localSrc, localMask, localDst, pSrcPix, pMaskPix, pDstPix)) { + REGION_UNINIT(screen, ®ion); if (localSrc != pSrc) FreePicture(localSrc, 0); if (localMask && localMask != pMask) FreePicture(localMask, 0); + if (localDst != pDst) + FreePicture(localDst, 0); return -1; } - nbox = REGION_NUM_RECTS(®ion); - pbox = REGION_RECTS(®ion); - if (pMask) { - xMask = xMask + mask_off_x - xDst - dst_off_x; - yMask = yMask + mask_off_y - yDst - dst_off_y; + xMask = xMask + mask_off_x - xDst; + yMask = yMask + mask_off_y - yDst; } - xSrc = xSrc + src_off_x - xDst - dst_off_x; - ySrc = ySrc + src_off_y - yDst - dst_off_y; + xSrc = xSrc + src_off_x - xDst; + ySrc = ySrc + src_off_y - yDst; + nbox = REGION_NUM_RECTS(®ion); + pbox = REGION_RECTS(®ion); while (nbox--) { (*uxa_screen->info->composite) (pDstPix, pbox->x1 + xSrc, pbox->y1 + ySrc, pbox->x1 + xMask, pbox->y1 + yMask, - pbox->x1, - pbox->y1, + pbox->x1 + dst_off_x, + pbox->y1 + dst_off_y, pbox->x2 - pbox->x1, pbox->y2 - pbox->y1); pbox++; } (*uxa_screen->info->done_composite) (pDstPix); - REGION_UNINIT(pDst->pDrawable->pScreen, ®ion); + REGION_UNINIT(screen, ®ion); if (localSrc != pSrc) FreePicture(localSrc, 0); if (localMask && localMask != pMask) FreePicture(localMask, 0); + if (localDst != pDst) { + GCPtr gc; + + gc = GetScratchGC(pDst->pDrawable->depth, screen); + if (gc) { + ValidateGC(pDst->pDrawable, gc); + gc->ops->CopyArea(localDst->pDrawable, pDst->pDrawable, gc, + 0, 0, width, height, xDst_copy, yDst_copy); + FreeScratchGC(gc); + } + + FreePicture(localDst, 0); + } + return 1; } @@ -917,36 +1323,100 @@ uxa_try_magic_two_pass_composite_helper(CARD8 op, PicturePtr pSrc, PicturePtr pMask, PicturePtr pDst, - INT16 xSrc, - INT16 ySrc, - INT16 xMask, - INT16 yMask, - INT16 xDst, - INT16 yDst, CARD16 width, CARD16 height) + INT16 xSrc, INT16 ySrc, + INT16 xMask, INT16 yMask, + INT16 xDst, INT16 yDst, + CARD16 width, CARD16 height) { - uxa_screen_t *uxa_screen = uxa_get_screen(pDst->pDrawable->pScreen); + ScreenPtr screen = pDst->pDrawable->pScreen; + uxa_screen_t *uxa_screen = uxa_get_screen(screen); + PicturePtr localDst = pDst; + int xDst_copy, yDst_copy; assert(op == PictOpOver); if (uxa_screen->info->check_composite && (!(*uxa_screen->info->check_composite) (PictOpOutReverse, pSrc, - pMask, pDst) + pMask, pDst, width, height) || !(*uxa_screen->info->check_composite) (PictOpAdd, pSrc, pMask, - pDst))) { + pDst, width, height))) { return -1; } + if (uxa_screen->info->check_composite_target && + !uxa_screen->info->check_composite_target(uxa_get_drawable_pixmap(pDst->pDrawable))) { + int depth = pDst->pDrawable->depth; + PixmapPtr pixmap; + int error; + GCPtr gc; + + pixmap = uxa_get_drawable_pixmap(pDst->pDrawable); + if (uxa_screen->info->check_copy && + !uxa_screen->info->check_copy(pixmap, pixmap, GXcopy, FB_ALLONES)) + return -1; + + pixmap = screen->CreatePixmap(screen, + width, height, depth, + CREATE_PIXMAP_USAGE_SCRATCH); + if (!pixmap) + return 0; + + gc = GetScratchGC(depth, screen); + if (!gc) { + screen->DestroyPixmap(pixmap); + return 0; + } + + ValidateGC(&pixmap->drawable, gc); + gc->ops->CopyArea(pDst->pDrawable, &pixmap->drawable, gc, + xDst, yDst, width, height, 0, 0); + FreeScratchGC(gc); + + xDst_copy = xDst; xDst = 0; + yDst_copy = yDst; yDst = 0; + + localDst = CreatePicture(0, &pixmap->drawable, + PictureMatchFormat(screen, depth, pDst->format), + 0, 0, serverClient, &error); + screen->DestroyPixmap(pixmap); + + if (!localDst) + return 0; + + ValidatePicture(localDst); + } + /* Now, we think we should be able to accelerate this operation. First, * composite the destination to be the destination times the source alpha * factors. */ - uxa_composite(PictOpOutReverse, pSrc, pMask, pDst, xSrc, ySrc, xMask, - yMask, xDst, yDst, width, height); + uxa_composite(PictOpOutReverse, pSrc, pMask, localDst, + xSrc, ySrc, + xMask, yMask, + xDst, yDst, + width, height); /* Then, add in the source value times the destination alpha factors (1.0). */ - uxa_composite(PictOpAdd, pSrc, pMask, pDst, xSrc, ySrc, xMask, yMask, - xDst, yDst, width, height); + uxa_composite(PictOpAdd, pSrc, pMask, localDst, + xSrc, ySrc, + xMask, yMask, + xDst, yDst, + width, height); + + if (localDst != pDst) { + GCPtr gc; + + gc = GetScratchGC(pDst->pDrawable->depth, screen); + if (gc) { + ValidateGC(pDst->pDrawable, gc); + gc->ops->CopyArea(localDst->pDrawable, pDst->pDrawable, gc, + 0, 0, width, height, xDst_copy, yDst_copy); + FreeScratchGC(gc); + } + + FreePicture(localDst, 0); + } return 1; } @@ -958,99 +1428,113 @@ compatible_formats (CARD8 op, PicturePtr dst, PicturePtr src) if (src->format == dst->format) return 1; - if (src->format == PICT_a8r8g8b8 && dst->format == PICT_x8r8g8b8) + /* Is the destination an alpha-less version of source? */ + if (dst->format == PICT_FORMAT(PICT_FORMAT_BPP(src->format), + PICT_FORMAT_TYPE(src->format), + 0, + PICT_FORMAT_R(src->format), + PICT_FORMAT_G(src->format), + PICT_FORMAT_B(src->format))) return 1; - if (src->format == PICT_a8b8g8r8 && dst->format == PICT_x8b8g8r8) - return 1; - - /* xrgb is promoted to argb during image upload... */ + /* XXX xrgb is promoted to argb during image upload... */ +#if 0 if (dst->format == PICT_a8r8g8b8 && src->format == PICT_x8r8g8b8) return 1; +#endif } else if (op == PictOpOver) { - if (src->alphaMap || dst->alphaMap) - return 0; - - if (src->format != dst->format) + if (PICT_FORMAT_A(src->format)) return 0; - if (src->format == PICT_x8r8g8b8 || src->format == PICT_x8b8g8r8) - return 1; + return src->format == dst->format; } return 0; } -static int -drawable_contains (DrawablePtr drawable, int x1, int y1, int x2, int y2) -{ - if (x1 < 0 || y1 < 0) - return FALSE; - - if (x2 > drawable->width) - return FALSE; - - if (y2 > drawable->height) - return FALSE; - - return TRUE; -} - void uxa_composite(CARD8 op, PicturePtr pSrc, PicturePtr pMask, PicturePtr pDst, - INT16 xSrc, - INT16 ySrc, - INT16 xMask, - INT16 yMask, INT16 xDst, INT16 yDst, CARD16 width, CARD16 height) + INT16 xSrc, INT16 ySrc, + INT16 xMask, INT16 yMask, + INT16 xDst, INT16 yDst, + CARD16 width, CARD16 height) { uxa_screen_t *uxa_screen = uxa_get_screen(pDst->pDrawable->pScreen); int ret = -1; Bool saveSrcRepeat = pSrc->repeat; Bool saveMaskRepeat = pMask ? pMask->repeat : 0; RegionRec region; + int tx, ty; if (uxa_screen->swappedOut) goto fallback; + if (!uxa_drawable_is_offscreen(pDst->pDrawable)) + goto fallback; + + + if (pDst->alphaMap || pSrc->alphaMap || (pMask && pMask->alphaMap)) + goto fallback; + + /* Remove repeat in source if useless */ - if (pSrc->pDrawable && pSrc->repeat && !pSrc->transform && + if (pSrc->pDrawable && pSrc->repeat && pSrc->filter != PictFilterConvolution && + transform_is_integer_translation(pSrc->transform, &tx, &ty) && (pSrc->pDrawable->width > 1 || pSrc->pDrawable->height > 1) && - xSrc >= 0 && (xSrc + width) <= pSrc->pDrawable->width && - ySrc >= 0 && (ySrc + height) <= pSrc->pDrawable->height) + drawable_contains(pSrc->pDrawable, xSrc + tx, ySrc + ty, width, height)) pSrc->repeat = 0; if (!pMask) { + if (op == PictOpClear) { + PicturePtr clear = uxa_solid_clear(pDst->pDrawable->pScreen); + if (clear && + uxa_try_driver_solid_fill(clear, pDst, + xSrc, ySrc, + xDst, yDst, + width, height) == 1) + goto done; + } + if (pSrc->pDrawable == NULL) { if (pSrc->pSourcePict) { SourcePict *source = pSrc->pSourcePict; if (source->type == SourcePictTypeSolidFill) { - ret = uxa_try_driver_solid_fill(pSrc, pDst, - xSrc, ySrc, - xDst, yDst, - width, height); - if (ret == 1) - goto done; + if (op == PictOpSrc || + (op == PictOpOver && + (source->solidFill.color & 0xff000000) == 0xff000000)) { + ret = uxa_try_driver_solid_fill(pSrc, pDst, + xSrc, ySrc, + xDst, yDst, + width, height); + if (ret == 1) + goto done; + } } } - } else if (compatible_formats (op, pDst, pSrc)) { - if (pSrc->pDrawable->width == 1 && - pSrc->pDrawable->height == 1 && - pSrc->repeat) { - ret = uxa_try_driver_solid_fill(pSrc, pDst, - xSrc, ySrc, - xDst, yDst, - width, height); - if (ret == 1) - goto done; - } else if (!pSrc->repeat && !pSrc->transform && - drawable_contains(pSrc->pDrawable, xSrc, ySrc, xSrc + width, ySrc + height)) { + } else if (pSrc->pDrawable->width == 1 && + pSrc->pDrawable->height == 1 && + pSrc->repeat && + (op == PictOpSrc || (op == PictOpOver && !PICT_FORMAT_A(pSrc->format)))) { + ret = uxa_try_driver_solid_fill(pSrc, pDst, + xSrc, ySrc, + xDst, yDst, + width, height); + if (ret == 1) + goto done; + } else if (compatible_formats (op, pDst, pSrc) && + pSrc->filter != PictFilterConvolution && + transform_is_integer_translation(pSrc->transform, &tx, &ty)) { + if (!pSrc->repeat && + drawable_contains(pSrc->pDrawable, + xSrc + tx, ySrc + ty, + width, height)) { xDst += pDst->pDrawable->x; yDst += pDst->pDrawable->y; - xSrc += pSrc->pDrawable->x; - ySrc += pSrc->pDrawable->y; + xSrc += pSrc->pDrawable->x + tx; + ySrc += pSrc->pDrawable->y + ty; if (!miComputeCompositeRegion (®ion, pSrc, pMask, pDst, xSrc, ySrc, @@ -1066,16 +1550,14 @@ uxa_composite(CARD8 op, REGION_UNINIT(pDst->pDrawable->pScreen, ®ion); goto done; - } else if (pSrc->pDrawable->type == DRAWABLE_PIXMAP && - !pSrc->transform && - pSrc->repeatType == RepeatNormal) { + } else if (pSrc->repeat && pSrc->repeatType == RepeatNormal && + pSrc->pDrawable->type == DRAWABLE_PIXMAP) { DDXPointRec patOrg; /* Let's see if the driver can do the repeat * in one go */ - if (uxa_screen->info->prepare_composite - && !pSrc->alphaMap && !pDst->alphaMap) { + if (uxa_screen->info->prepare_composite) { ret = uxa_try_driver_composite(op, pSrc, pMask, pDst, xSrc, ySrc, @@ -1091,8 +1573,8 @@ uxa_composite(CARD8 op, */ xDst += pDst->pDrawable->x; yDst += pDst->pDrawable->y; - xSrc += pSrc->pDrawable->x; - ySrc += pSrc->pDrawable->y; + xSrc += pSrc->pDrawable->x + tx; + ySrc += pSrc->pDrawable->y + ty; if (!miComputeCompositeRegion (®ion, pSrc, pMask, pDst, xSrc, ySrc, @@ -1121,15 +1603,14 @@ uxa_composite(CARD8 op, } /* Remove repeat in mask if useless */ - if (pMask && pMask->repeat && !pMask->transform && pMask->pDrawable && + if (pMask && pMask->pDrawable && pMask->repeat && + pMask->filter != PictFilterConvolution && + transform_is_integer_translation(pMask->transform, &tx, &ty) && (pMask->pDrawable->width > 1 || pMask->pDrawable->height > 1) && - xMask >= 0 && (xMask + width) <= pMask->pDrawable->width && - yMask >= 0 && (yMask + height) <= pMask->pDrawable->height) + drawable_contains(pMask->pDrawable, xMask + tx, yMask + ty, width, height)) pMask->repeat = 0; - if (uxa_screen->info->prepare_composite && - !pSrc->alphaMap && (!pMask || !pMask->alphaMap) && !pDst->alphaMap) - { + if (uxa_screen->info->prepare_composite) { Bool isSrcSolid; ret = @@ -1142,9 +1623,15 @@ uxa_composite(CARD8 op, /* For generic masks and solid src pictures, mach64 can do * Over in two passes, similar to the component-alpha case. */ - isSrcSolid = pSrc->pDrawable && - pSrc->pDrawable->width == 1 && - pSrc->pDrawable->height == 1 && pSrc->repeat; + + isSrcSolid = + pSrc->pDrawable ? + pSrc->pDrawable->width == 1 && + pSrc->pDrawable->height == 1 && + pSrc->repeat : + pSrc->pSourcePict ? + pSrc->pSourcePict->type == SourcePictTypeSolidFill : + 0; /* If we couldn't do the Composite in a single pass, and it * was a component-alpha Over, see if we can do it in two @@ -1156,13 +1643,13 @@ uxa_composite(CARD8 op, uxa_try_magic_two_pass_composite_helper(op, pSrc, pMask, pDst, xSrc, ySrc, - xMask, - yMask, xDst, - yDst, width, - height); + xMask, yMask, + xDst, yDst, + width, height); if (ret == 1) goto done; } + } fallback: @@ -1232,15 +1719,15 @@ uxa_create_alpha_picture(ScreenPtr pScreen, * uxa_check_poly_fill_rect to initialize the contents. */ void -uxa_trapezoids(CARD8 op, PicturePtr pSrc, PicturePtr pDst, +uxa_trapezoids(CARD8 op, PicturePtr src, PicturePtr dst, PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc, int ntrap, xTrapezoid * traps) { - ScreenPtr pScreen = pDst->pDrawable->pScreen; - PictureScreenPtr ps = GetPictureScreen(pScreen); + ScreenPtr screen = dst->pDrawable->pScreen; BoxRec bounds; - Bool direct = op == PictOpAdd && miIsSolidAlpha(pSrc); + Bool direct; + direct = op == PictOpAdd && miIsSolidAlpha(src); if (maskFormat || direct) { miTrapezoidBounds(ntrap, traps, &bounds); @@ -1252,7 +1739,7 @@ uxa_trapezoids(CARD8 op, PicturePtr pSrc, PicturePtr pDst, * Check for solid alpha add */ if (direct) { - DrawablePtr pDraw = pDst->pDrawable; + DrawablePtr pDraw = dst->pDrawable; PixmapPtr pixmap = uxa_get_drawable_pixmap(pDraw); int xoff, yoff; @@ -1262,12 +1749,15 @@ uxa_trapezoids(CARD8 op, PicturePtr pSrc, PicturePtr pDst, yoff += pDraw->y; if (uxa_prepare_access(pDraw, UXA_ACCESS_RW)) { + PictureScreenPtr ps = GetPictureScreen(screen); + for (; ntrap; ntrap--, traps++) - (*ps->RasterizeTrapezoid) (pDst, traps, 0, 0); + (*ps->RasterizeTrapezoid) (dst, traps, 0, 0); uxa_finish_access(pDraw); } } else if (maskFormat) { - PicturePtr pPicture; + PixmapPtr scratch = NULL; + PicturePtr mask; INT16 xDst, yDst; INT16 xRel, yRel; int width, height; @@ -1291,28 +1781,48 @@ uxa_trapezoids(CARD8 op, PicturePtr pSrc, PicturePtr pDst, pixman_rasterize_trapezoid(image, (pixman_trapezoid_t *) traps, -bounds.x1, -bounds.y1); - - pPicture = - uxa_picture_from_pixman_image(pScreen, image, format); - pixman_image_unref(image); - if (!pPicture) + if (uxa_drawable_is_offscreen(dst->pDrawable)) { + mask = uxa_picture_from_pixman_image(screen, image, format); + } else { + int error; + + scratch = GetScratchPixmapHeader(screen, width, height, + PIXMAN_FORMAT_DEPTH(format), + PIXMAN_FORMAT_BPP(format), + pixman_image_get_stride(image), + pixman_image_get_data(image)); + mask = CreatePicture(0, &scratch->drawable, + PictureMatchFormat(screen, + PIXMAN_FORMAT_DEPTH(format), + format), + 0, 0, serverClient, &error); + } + if (!mask) { + if (scratch) + FreeScratchPixmapHeader(scratch); + pixman_image_unref(image); return; + } xRel = bounds.x1 + xSrc - xDst; yRel = bounds.y1 + ySrc - yDst; - CompositePicture(op, pSrc, pPicture, pDst, + CompositePicture(op, src, mask, dst, xRel, yRel, 0, 0, bounds.x1, bounds.y1, width, height); - FreePicture(pPicture, 0); + FreePicture(mask, 0); + + if (scratch) + FreeScratchPixmapHeader(scratch); + pixman_image_unref(image); } else { - if (pDst->polyEdge == PolyEdgeSharp) - maskFormat = PictureMatchFormat(pScreen, 1, PICT_a1); + if (dst->polyEdge == PolyEdgeSharp) + maskFormat = PictureMatchFormat(screen, 1, PICT_a1); else - maskFormat = PictureMatchFormat(pScreen, 8, PICT_a8); + maskFormat = PictureMatchFormat(screen, 8, PICT_a8); for (; ntrap; ntrap--, traps++) - uxa_trapezoids(op, pSrc, pDst, maskFormat, xSrc, ySrc, + uxa_trapezoids(op, src, dst, maskFormat, xSrc, ySrc, 1, traps); } } @@ -39,7 +39,11 @@ #include "dixfontstr.h" #include "uxa.h" +#if HAS_DEVPRIVATEKEYREC +DevPrivateKeyRec uxa_screen_index; +#else int uxa_screen_index; +#endif /** * uxa_get_drawable_pixmap() returns a backing pixmap for a given drawable. @@ -388,14 +392,17 @@ static Bool uxa_close_screen(int i, ScreenPtr pScreen) #ifdef RENDER if (ps) { ps->Composite = uxa_screen->SavedComposite; + ps->CompositeRects = uxa_screen->SavedCompositeRects; ps->Glyphs = uxa_screen->SavedGlyphs; ps->Trapezoids = uxa_screen->SavedTrapezoids; ps->AddTraps = uxa_screen->SavedAddTraps; ps->Triangles = uxa_screen->SavedTriangles; + + ps->UnrealizeGlyph = uxa_screen->SavedUnrealizeGlyph; } #endif - xfree(uxa_screen); + free(uxa_screen); return (*pScreen->CloseScreen) (i, pScreen); } @@ -406,13 +413,13 @@ static Bool uxa_close_screen(int i, ScreenPtr pScreen) * without breaking ABI between UXA and the drivers. The driver's * responsibility is to check beforehand that the UXA module has a matching * major number and sufficient minor. Drivers are responsible for freeing the - * driver structure using xfree(). + * driver structure using free(). * * @return a newly allocated, zero-filled driver structure */ uxa_driver_t *uxa_driver_alloc(void) { - return xcalloc(1, sizeof(uxa_driver_t)); + return calloc(1, sizeof(uxa_driver_t)); } /** @@ -429,9 +436,6 @@ Bool uxa_driver_init(ScreenPtr screen, uxa_driver_t * uxa_driver) { uxa_screen_t *uxa_screen; ScrnInfoPtr scrn = xf86Screens[screen->myNum]; -#ifdef RENDER - PictureScreenPtr ps; -#endif if (!uxa_driver) return FALSE; @@ -460,11 +464,11 @@ Bool uxa_driver_init(ScreenPtr screen, uxa_driver_t * uxa_driver) "non-NULL\n", screen->myNum); return FALSE; } -#ifdef RENDER - ps = GetPictureScreenIfSet(screen); +#if HAS_DIXREGISTERPRIVATEKEY + if (!dixRegisterPrivateKey(&uxa_screen_index, PRIVATE_SCREEN, 0)) + return FALSE; #endif - - uxa_screen = xcalloc(sizeof(uxa_screen_t), 1); + uxa_screen = calloc(sizeof(uxa_screen_t), 1); if (!uxa_screen) { LogMessage(X_WARNING, @@ -513,33 +517,32 @@ Bool uxa_driver_init(ScreenPtr screen, uxa_driver_t * uxa_driver) scrn->EnableDisableFBAccess = uxa_xorg_enable_disable_fb_access; #ifdef RENDER - if (ps) { - uxa_screen->SavedComposite = ps->Composite; - ps->Composite = uxa_composite; + { + PictureScreenPtr ps = GetPictureScreenIfSet(screen); + if (ps) { + uxa_screen->SavedComposite = ps->Composite; + ps->Composite = uxa_composite; - uxa_screen->SavedGlyphs = ps->Glyphs; - ps->Glyphs = uxa_glyphs; + uxa_screen->SavedCompositeRects = ps->CompositeRects; + ps->CompositeRects = uxa_solid_rects; - uxa_screen->SavedTriangles = ps->Triangles; - ps->Triangles = uxa_triangles; + uxa_screen->SavedGlyphs = ps->Glyphs; + ps->Glyphs = uxa_glyphs; - uxa_screen->SavedTrapezoids = ps->Trapezoids; - ps->Trapezoids = uxa_trapezoids; + uxa_screen->SavedUnrealizeGlyph = ps->UnrealizeGlyph; + ps->UnrealizeGlyph = uxa_glyph_unrealize; - uxa_screen->SavedAddTraps = ps->AddTraps; - ps->AddTraps = uxa_check_add_traps; - } -#endif + uxa_screen->SavedTriangles = ps->Triangles; + ps->Triangles = uxa_triangles; -#ifdef MITSHM - /* Re-register with the MI funcs, which don't allow shared pixmaps. - * Shared pixmaps are almost always a performance loss for us, but this - * still allows for SHM PutImage. - */ - ShmRegisterFuncs(screen, &uxa_shm_funcs); -#endif + uxa_screen->SavedTrapezoids = ps->Trapezoids; + ps->Trapezoids = uxa_trapezoids; - uxa_glyphs_init(screen); + uxa_screen->SavedAddTraps = ps->AddTraps; + ps->AddTraps = uxa_check_add_traps; + } + } +#endif LogMessage(X_INFO, "UXA(%d): Driver registered support for the following" @@ -561,6 +564,14 @@ Bool uxa_driver_init(ScreenPtr screen, uxa_driver_t * uxa_driver) return TRUE; } +Bool uxa_resources_init(ScreenPtr screen) +{ + if (!uxa_glyphs_init(screen)) + return FALSE; + + return TRUE; +} + /** * uxa_driver_fini tears down UXA on a given screen. * @@ -74,6 +74,17 @@ typedef struct _UxaDriver { * @{ */ /** + * check_solid() checks whether the driver can do a solid fill to this drawable. + * @param pDrawable Destination drawable + * @param alu raster operation + * @param planemask write mask for the fill + * + * The check_solid() call is recommended if prepare_solid() is + * implemented, but is not required. + */ + Bool(*check_solid) (DrawablePtr pDrawable, int alu, Pixel planemask); + + /** * prepare_solid() sets up the driver for doing a solid fill. * @param pPixmap Destination pixmap * @param alu raster operation @@ -138,6 +149,10 @@ typedef struct _UxaDriver { * @{ */ /** + * check_copy() checks whether the driver can blit between the two Pictures + */ + Bool(*check_copy) (PixmapPtr pSrc, PixmapPtr pDst, int alu, Pixel planemask); + /** * prepare_copy() sets up the driver for doing a copy within video * memory. - * @@ -232,6 +247,8 @@ typedef struct _UxaDriver { * @param pSrcPicture source Picture * @param pMaskPicture mask picture * @param pDstPicture destination Picture + * @param width The width of the composite operation + * @param height The height of the composite operation * * The check_composite() call checks if the driver could handle * acceleration of op with the given source, mask, and destination @@ -249,7 +266,32 @@ typedef struct _UxaDriver { Bool(*check_composite) (int op, PicturePtr pSrcPicture, PicturePtr pMaskPicture, - PicturePtr pDstPicture); + PicturePtr pDstPicture, + int width, int height); + + /** + * check_composite_target() checks to see if the destination of the composite + * operation can be used without midification. + * + * @param pixmap Destination Pixmap + * + * The check_composite_target() call is recommended if prepare_composite() is + * implemented, but is not required. + */ + Bool(*check_composite_target) (PixmapPtr pixmap); + + /** + * check_composite_texture() checks to see if a source to the composite + * operation can be used without midification. + * + * @param pScreen Screen + * @param pPicture Picture + * + * The check_composite_texture() call is recommended if prepare_composite() is + * implemented, but is not required. + */ + Bool(*check_composite_texture) (ScreenPtr pScreen, + PicturePtr pPicture); /** * prepare_composite() sets up the driver for doing a composite @@ -516,6 +558,7 @@ typedef struct _UxaDriver { uxa_driver_t *uxa_driver_alloc(void); Bool uxa_driver_init(ScreenPtr screen, uxa_driver_t * uxa_driver); +Bool uxa_resources_init(ScreenPtr screen); void uxa_driver_fini(ScreenPtr pScreen); |