diff options
-rw-r--r-- | hw/xgl/Makefile.am | 6 | ||||
-rw-r--r-- | hw/xgl/glx/xglx.c | 28 | ||||
-rw-r--r-- | hw/xgl/xgl.h | 672 | ||||
-rw-r--r-- | hw/xgl/xglarea.c | 318 | ||||
-rw-r--r-- | hw/xgl/xglbstore.c | 10 | ||||
-rw-r--r-- | hw/xgl/xglcmap.c | 34 | ||||
-rw-r--r-- | hw/xgl/xglcomp.c | 271 | ||||
-rw-r--r-- | hw/xgl/xglcopy.c | 163 | ||||
-rw-r--r-- | hw/xgl/xglfill.c | 312 | ||||
-rw-r--r-- | hw/xgl/xglgc.c | 198 | ||||
-rw-r--r-- | hw/xgl/xglgeometry.c | 616 | ||||
-rw-r--r-- | hw/xgl/xglget.c | 18 | ||||
-rw-r--r-- | hw/xgl/xglglyph.c | 1080 | ||||
-rw-r--r-- | hw/xgl/xglinput.c | 4 | ||||
-rw-r--r-- | hw/xgl/xgloffscreen.c | 428 | ||||
-rw-r--r-- | hw/xgl/xgloutput.c | 4 | ||||
-rw-r--r-- | hw/xgl/xglparse.c | 35 | ||||
-rw-r--r-- | hw/xgl/xglpict.c | 282 | ||||
-rw-r--r-- | hw/xgl/xglpixel.c | 149 | ||||
-rw-r--r-- | hw/xgl/xglpixmap.c | 102 | ||||
-rw-r--r-- | hw/xgl/xglscreen.c | 202 | ||||
-rw-r--r-- | hw/xgl/xglsolid.c | 122 | ||||
-rw-r--r-- | hw/xgl/xglsync.c | 129 | ||||
-rw-r--r-- | hw/xgl/xgltile.c | 336 | ||||
-rw-r--r-- | hw/xgl/xgltrap.c | 520 | ||||
-rw-r--r-- | hw/xgl/xglwindow.c | 193 |
26 files changed, 4594 insertions, 1638 deletions
diff --git a/hw/xgl/Makefile.am b/hw/xgl/Makefile.am index 2471758a8..8ae1a47fd 100644 --- a/hw/xgl/Makefile.am +++ b/hw/xgl/Makefile.am @@ -13,13 +13,13 @@ libxgl_a_SOURCES = \ xglcmap.c \ xglparse.c \ xglscreen.c \ + xglarea.c \ xgloffscreen.c \ xglgeometry.c \ xglpixmap.c \ xglsync.c \ xglsolid.c \ xgltile.c \ - xglpixel.c \ xglcopy.c \ xglfill.c \ xglwindow.c \ @@ -27,4 +27,6 @@ libxgl_a_SOURCES = \ xglget.c \ xglgc.c \ xglcomp.c \ - xglpict.c + xglpict.c \ + xglglyph.c \ + xgltrap.c diff --git a/hw/xgl/glx/xglx.c b/hw/xgl/glx/xglx.c index c013317e3..cda3e96bc 100644 --- a/hw/xgl/glx/xglx.c +++ b/hw/xgl/glx/xglx.c @@ -5,7 +5,7 @@ * 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 names of + * appear in supporting documentation, and that the name of * David Reveman not be used in advertising or publicity pertaining to * distribution of the software without specific, written prior permission. * David Reveman makes no representations about the suitability of this @@ -20,7 +20,7 @@ * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * - * Author: David Reveman <davidr@freedesktop.org> + * Author: David Reveman <davidr@novell.com> */ #include <X11/Xlib.h> @@ -64,7 +64,11 @@ int xscreen; glitz_format_t *xglxCurrentFormat; CARD32 lastEventTime = 0; ScreenPtr currentScreen = NULL; -xglScreenInfoRec xglScreenInfo = { 0, 0, 0, 0, FALSE }; +xglScreenInfoRec xglScreenInfo = { + NULL, 0, 0, 0, 0, FALSE, + DEFAULT_GEOMETRY_DATA_TYPE, + DEFAULT_GEOMETRY_USAGE +}; static Bool xglxAllocatePrivates (ScreenPtr pScreen) @@ -386,9 +390,15 @@ xglxBlockHandler (pointer blockData, OSTimePtr pTimeout, pointer pReadMask) { - glitz_surface_flush (XGL_GET_SCREEN_PRIV (currentScreen)->surface); - glitz_drawable_flush (XGL_GET_SCREEN_PRIV (currentScreen)->drawable); - XFlush (xdisplay); + XGL_SCREEN_PRIV (currentScreen); + + if (!xglSyncSurface (&pScreenPriv->pScreenPixmap->drawable)) + FatalError (XGL_SW_FAILURE_STRING); + + glitz_surface_flush (pScreenPriv->surface); + glitz_drawable_finish (pScreenPriv->drawable); + + XSync (xdisplay, FALSE); } static void @@ -397,8 +407,8 @@ xglxWakeupHandler (pointer blockData, pointer pReadMask) { ScreenPtr pScreen = currentScreen; - XEvent X; - xEvent x; + XEvent X; + xEvent x; while (XPending (xdisplay)) { XNextEvent (xdisplay, &X); @@ -578,7 +588,7 @@ InitInput (int argc, char **argv) void ddxUseMsg (void) { - ErrorF ("\nXglx Usage:\n"); + ErrorF ("\nXglx usage:\n"); ErrorF ("-display string display name of the real server\n"); xglUseMsg (); diff --git a/hw/xgl/xgl.h b/hw/xgl/xgl.h index 3f1616af5..930f3d038 100644 --- a/hw/xgl/xgl.h +++ b/hw/xgl/xgl.h @@ -5,7 +5,7 @@ * 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 names of + * appear in supporting documentation, and that the name of * David Reveman not be used in advertising or publicity pertaining to * distribution of the software without specific, written prior permission. * David Reveman makes no representations about the suitability of this @@ -20,7 +20,7 @@ * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * - * Author: David Reveman <davidr@freedesktop.org> + * Author: David Reveman <davidr@novell.com> */ #ifndef _XGL_H_ @@ -61,6 +61,8 @@ typedef struct _xglScreenInfo { unsigned int widthMm; unsigned int heightMm; Bool fullscreen; + int geometryDataType; + int geometryUsage; } xglScreenInfoRec, *xglScreenInfoPtr; typedef struct _xglPixelFormat { @@ -85,29 +87,123 @@ extern int nxglVisuals; extern xglVisualPtr xglPbufferVisuals; extern int nxglPbufferVisuals; -#define xglOffscreenAreaAvailable 0 -#define xglOffscreenAreaDivided 1 -#define xglOffscreenAreaOccupied 2 +#define xglAreaAvailable 0 +#define xglAreaDivided 1 +#define xglAreaOccupied 2 + +typedef struct _xglRootArea *xglRootAreaPtr; + +typedef struct _xglArea { + int state; + int level; + int x, y; + int width, height; + struct _xglArea *pArea[4]; + xglRootAreaPtr pRoot; + pointer closure; + DevUnion devPrivate; +} xglAreaRec, *xglAreaPtr; + +typedef struct _xglAreaFuncs { + Bool (*Create) (xglAreaPtr pArea); + + Bool (*MoveIn) (xglAreaPtr pArea, + pointer closure); + + void (*MoveOut) (xglAreaPtr pArea, + pointer closure); + + int (*CompareScore) (xglAreaPtr pArea, + pointer closure1, + pointer closure2); + +} xglAreaFuncsRec, *xglAreaFuncsPtr; + +typedef struct _xglRootArea { + int maxLevel; + int width, height; + xglAreaPtr pArea; + xglAreaFuncsPtr funcs; + int devPrivateSize; + pointer closure; +} xglRootAreaRec; + +typedef struct xglGeometry { + glitz_buffer_t *buffer; + pointer *data; + Bool broken; + glitz_fixed16_16_t xOff, yOff; + int dataType; + int usage; + int size, endOffset; + glitz_geometry_type_t type; + glitz_geometry_format_t f; + int first, width, count; + glitz_multi_array_t *array; +} xglGeometryRec, *xglGeometryPtr; -typedef struct _xglOffscreen *xglOffscreenPtr; -typedef struct _xglPixmap *xglPixmapPtr; +#ifdef RENDER +typedef struct _xglFBox { + glitz_float_t x1, y1, x2, y2; +} xglFBoxRec; + +typedef union _xglBox { + BoxRec sBox; + xglFBoxRec fBox; +} xglBoxRec, *xglBoxPtr; + +typedef struct _xglRange { + int first; + unsigned int count; +} xglRangeRec, *xglRangePtr; + +typedef struct _xglGlyphTexture { + glitz_surface_t *mask; + glitz_pixel_format_t pixel; + glitz_geometry_format_t format; + int geometryDataType; +} xglGlyphTextureRec, *xglGlyphTexturePtr; + +typedef struct _xglGlyphArea { + unsigned long serial; + union { + xglBoxRec box; + xglRangeRec range; + } u; +} xglGlyphAreaRec, *xglGlyphAreaPtr; + +typedef struct _xglGlyphCache { + ScreenPtr pScreen; + int depth; + xglRootAreaRec rootArea; + union { + xglGlyphTextureRec texture; + xglGeometryRec geometry; + } u; +} xglGlyphCacheRec, *xglGlyphCachePtr; + +typedef struct _xglGlyph { + xglAreaPtr pArea; +} xglGlyphRec, *xglGlyphPtr; + +extern int xglGlyphPrivateIndex; + +#define XGL_GET_GLYPH_PRIV(pScreen, pGlyph) ((xglGlyphPtr) \ + (GetGlyphPrivatesForScreen (pGlyph, pScreen))[xglGlyphPrivateIndex].ptr) + +#define XGL_GLYPH_PRIV(pScreen, pGlyph) \ + xglGlyphPtr pGlyphPriv = XGL_GET_GLYPH_PRIV (pScreen, pGlyph) + +#endif -typedef struct _xglOffscreenArea { - int level; - int state; - int x, y; - xglPixmapPtr pPixmapPriv; - struct _xglOffscreenArea *pArea[4]; - xglOffscreenPtr pOffscreen; -} xglOffscreenAreaRec, *xglOffscreenAreaPtr; +#define XGL_MAX_OFFSCREEN_AREAS 8 typedef struct _xglOffscreen { + xglRootAreaRec rootArea; glitz_drawable_t *drawable; glitz_drawable_format_t *format; glitz_drawable_buffer_t buffer; - int width, height; - xglOffscreenAreaPtr pArea; -} xglOffscreenRec; +} xglOffscreenRec, *xglOffscreenPtr; typedef struct _xglScreen { xglVisualPtr pVisual; @@ -117,12 +213,26 @@ typedef struct _xglScreen { glitz_surface_t *solid; PixmapPtr pScreenPixmap; unsigned long features; - xglOffscreenPtr pOffscreen; + xglOffscreenRec pOffscreen[XGL_MAX_OFFSCREEN_AREAS]; int nOffscreen; + int geometryUsage; + int geometryDataType; + xglGeometryRec scratchGeometry; + +#ifdef RENDER + xglGlyphCacheRec glyphCache[33]; + PicturePtr pSolidAlpha; + struct _trapInfo { + PicturePtr pMask; + glitz_surface_t *mask; + glitz_geometry_format_t format; + } trapInfo; +#endif GetImageProcPtr GetImage; GetSpansProcPtr GetSpans; CreateWindowProcPtr CreateWindow; + ChangeWindowAttributesProcPtr ChangeWindowAttributes; PaintWindowBackgroundProcPtr PaintWindowBackground; PaintWindowBorderProcPtr PaintWindowBorder; CopyWindowProcPtr CopyWindow; @@ -133,11 +243,16 @@ typedef struct _xglScreen { #ifdef RENDER CompositeProcPtr Composite; - RasterizeTrapezoidProcPtr RasterizeTrapezoid; GlyphsProcPtr Glyphs; + TrapezoidsProcPtr Trapezoids; + AddTrapsProcPtr AddTraps; + AddTrianglesProcPtr AddTriangles; ChangePictureProcPtr ChangePicture; ChangePictureTransformProcPtr ChangePictureTransform; ChangePictureFilterProcPtr ChangePictureFilter; + + RealizeGlyphProcPtr RealizeGlyph; + UnrealizeGlyphProcPtr UnrealizeGlyph; #endif BSFuncRec BackingStoreFuncs; @@ -213,22 +328,23 @@ extern int xglGCPrivateIndex; #define xglPixmapTargetIn 2 typedef struct _xglPixmap { - xglPixelFormatPtr pPixel; - glitz_format_t *format; - glitz_surface_t *surface; - glitz_buffer_t *buffer; - int target; - xglOffscreenAreaPtr pArea; - int score; - Bool acceleratedTile; - pointer bits; - unsigned int stride; - DamagePtr pDamage; - BoxRec damageBox; - BoxRec bitBox; - Bool allBits; - unsigned long pictureMask; -} xglPixmapRec; + xglPixelFormatPtr pPixel; + glitz_format_t *format; + glitz_surface_t *surface; + glitz_buffer_t *buffer; + int target; + xglAreaPtr pArea; + int score; + Bool acceleratedTile; + pointer bits; + unsigned int stride; + DamagePtr pDamage; + BoxRec damageBox; + BoxRec bitBox; + Bool allBits; + unsigned long pictureMask; + xglGeometryPtr pGeometry; +} xglPixmapRec, *xglPixmapPtr; extern int xglPixmapPrivateIndex; @@ -271,19 +387,6 @@ extern int xglWinPrivateIndex; #define XGL_DRAWABLE_PIXMAP_PRIV(pDrawable) \ xglPixmapPtr pPixmapPriv = XGL_GET_DRAWABLE_PIXMAP_PRIV (pDrawable) - -typedef struct xglGeometry { - glitz_buffer_t *buffer; - pointer *data; - glitz_geometry_primitive_t primitive; - Bool broken; - glitz_fixed16_16_t xOff, yOff; - int dataType; - int usage; - int size, endOffset; -} xglGeometryRec, *xglGeometryPtr; - - #ifdef COMPOSITE #define __XGL_OFF_X_WIN(pPix) (-(pPix)->screen_x) #define __XGL_OFF_Y_WIN(pPix) (-(pPix)->screen_y) @@ -308,11 +411,6 @@ typedef struct xglGeometry { #define XGL_DEFAULT_DPI 96 -#define XGL_INTERNAL_SCANLINE_ORDER GLITZ_PIXEL_SCANLINE_ORDER_TOP_DOWN - -#define XGL_INTERNAL_SCANLINE_ORDER_UPSIDE_DOWN \ - (XGL_INTERNAL_SCANLINE_ORDER == GLITZ_PIXEL_SCANLINE_ORDER_BOTTOM_UP) - #define XGL_SW_FAILURE_STRING "software fall-back failure" #define MIN(a,b) ((a) < (b) ? (a) : (b)) @@ -322,32 +420,13 @@ typedef struct xglGeometry { #define MOD(a,b) ((a) < 0 ? ((b) - ((-(a) - 1) % (b))) - 1 : (a) % (b)) +#define FIXED_TO_FLOAT(f) (((glitz_float_t) (f)) / 65536) +#define FLOAT_TO_FIXED(f) ((int) ((f) * 65536)) + #define BOX_NOTEMPTY(pBox) \ (((pBox)->x2 - (pBox)->x1) > 0 && \ ((pBox)->y2 - (pBox)->y1) > 0) -#define BOX_EXTENTS(pBox, nBox, pExt) \ - { \ - int i; \ - (pExt)->x1 = (pExt)->y1 = 32767; \ - (pExt)->x2 = (pExt)->y2 = -32767; \ - for (i = 0; i < (nBox); i++) \ - { \ - if ((pBox)[i].x1 < (pExt)->x1) \ - (pExt)->x1 = (pBox)[i].x1; \ - if ((pBox)[i].y1 < (pExt)->y1) \ - (pExt)->y1 = (pBox)[i].y1; \ - if ((pBox)[i].x2 > (pExt)->x2) \ - (pExt)->x2 = (pBox)[i].x2; \ - if ((pBox)[i].y2 > (pExt)->y2) \ - (pExt)->y2 = (pBox)[i].y2; \ - } \ - if (((pExt)->x2 - (pExt)->x1) < 0) \ - (pExt)->x1 = (pExt)->x2 = 0; \ - if (((pExt)->y2 - (pExt)->y1) < 0) \ - (pExt)->y1 = (pExt)->y2 = 0; \ - } - #define XGL_MAX_PIXMAP_SCORE 32768 #define XGL_MIN_PIXMAP_SCORE -32768 @@ -453,6 +532,37 @@ Bool xglCloseScreen (int index, ScreenPtr pScreen); +void +xglCreateSolidAlphaPicture (ScreenPtr pScreen); + + +/* xglarea.c */ + +Bool +xglRootAreaInit (xglRootAreaPtr pRoot, + int maxLevel, + int width, + int height, + int devPrivateSize, + xglAreaFuncsPtr funcs, + pointer closure); + +void +xglRootAreaFini (xglRootAreaPtr pRoot); + +void +xglLeaveArea (xglAreaPtr pArea); + +void +xglWithdrawArea (xglAreaPtr pArea); + +Bool +xglFindArea (xglAreaPtr pArea, + int width, + int height, + Bool kickOut, + pointer closure); + /* xgloffscreen.c */ @@ -468,7 +578,7 @@ xglFindOffscreenArea (ScreenPtr pScreen, PixmapPtr pPixmap); void -xglWithdrawOffscreenArea (xglOffscreenAreaPtr pArea); +xglLeaveOffscreenArea (PixmapPtr pPixmap); /* xglgeometry.c */ @@ -476,40 +586,101 @@ xglWithdrawOffscreenArea (xglOffscreenAreaPtr pArea); #define GEOMETRY_DATA_TYPE_SHORT 0 #define GEOMETRY_DATA_TYPE_FLOAT 1 +typedef struct _xglDataTypeInfo { + glitz_data_type_t type; + int size; +} xglDataTypeInfoRec, *xglDataTypeInfoPtr; + +extern xglDataTypeInfoRec xglGeometryDataTypes[2]; + +#define DEFAULT_GEOMETRY_DATA_TYPE GEOMETRY_DATA_TYPE_FLOAT + #define GEOMETRY_USAGE_STREAM 0 #define GEOMETRY_USAGE_STATIC 1 #define GEOMETRY_USAGE_DYNAMIC 2 -#define GEOMETRY_USAGE_USERMEM 3 - -#define GEOMETRY_INIT(pScreen, pGeometry, _size) \ - { \ - (pGeometry)->dataType = GEOMETRY_DATA_TYPE_FLOAT; \ - (pGeometry)->usage = GEOMETRY_USAGE_USERMEM; \ - (pGeometry)->primitive = GLITZ_GEOMETRY_PRIMITIVE_QUADS; \ - (pGeometry)->size = 0; \ - (pGeometry)->endOffset = 0; \ - (pGeometry)->data = (pointer) 0; \ - (pGeometry)->buffer = NULL; \ - (pGeometry)->broken = FALSE; \ - (pGeometry)->xOff = 0; \ - (pGeometry)->yOff = 0; \ - xglGeometryResize (pScreen, pGeometry, _size); \ +#define GEOMETRY_USAGE_SYSMEM 3 + +#define DEFAULT_GEOMETRY_USAGE GEOMETRY_USAGE_SYSMEM + +#define GEOMETRY_INIT(pScreen, pGeometry, _type, _usage, _size) \ + { \ + (pGeometry)->type = _type; \ + (pGeometry)->usage = _usage; \ + (pGeometry)->dataType = DEFAULT_GEOMETRY_DATA_TYPE; \ + (pGeometry)->usage = _usage; \ + (pGeometry)->size = 0; \ + (pGeometry)->endOffset = 0; \ + (pGeometry)->data = (pointer) 0; \ + (pGeometry)->buffer = NULL; \ + (pGeometry)->broken = FALSE; \ + (pGeometry)->xOff = 0; \ + (pGeometry)->yOff = 0; \ + (pGeometry)->array = NULL; \ + (pGeometry)->first = 0; \ + (pGeometry)->count = 0; \ + if (_type == GLITZ_GEOMETRY_TYPE_VERTEX) \ + { \ + (pGeometry)->width = 2; \ + (pGeometry)->f.vertex.type = \ + xglGeometryDataTypes[(pGeometry)->dataType].type; \ + (pGeometry)->f.vertex.bytes_per_vertex = (pGeometry)->width * \ + xglGeometryDataTypes[(pGeometry)->dataType].size; \ + (pGeometry)->f.vertex.primitive = GLITZ_PRIMITIVE_QUADS; \ + (pGeometry)->f.vertex.attributes = 0; \ + (pGeometry)->f.vertex.src.type = GLITZ_DATA_TYPE_FLOAT; \ + (pGeometry)->f.vertex.src.size = GLITZ_COORDINATE_SIZE_X; \ + (pGeometry)->f.vertex.src.offset = 0; \ + (pGeometry)->f.vertex.mask.type = GLITZ_DATA_TYPE_FLOAT; \ + (pGeometry)->f.vertex.mask.size = GLITZ_COORDINATE_SIZE_X; \ + (pGeometry)->f.vertex.mask.offset = 0; \ + } \ + else \ + { \ + (pGeometry)->width = 0; \ + (pGeometry)->f.bitmap.scanline_order = \ + GLITZ_PIXEL_SCANLINE_ORDER_TOP_DOWN; \ + (pGeometry)->f.bitmap.bytes_per_line = 0; \ + (pGeometry)->f.bitmap.pad = GLYPHPADBYTES; \ + } \ + if (_size) \ + xglGeometryResize (pScreen, pGeometry, _size); \ } -#define GEOMETRY_UNINIT(pGeometry) \ +#define GEOMETRY_UNINIT(pGeometry) \ + { \ + if ((pGeometry)->array) \ + glitz_multi_array_destroy ((pGeometry)->array); \ + if ((pGeometry)->buffer) \ + glitz_buffer_destroy ((pGeometry)->buffer); \ + if ((pGeometry)->data) \ + xfree ((pGeometry)->data); \ + } + +#define GEOMETRY_SET_BUFFER(pGeometry, _buffer) \ { \ + glitz_buffer_reference (_buffer); \ if ((pGeometry)->buffer) \ glitz_buffer_destroy ((pGeometry)->buffer); \ - if ((pGeometry)->data) \ - xfree ((pGeometry)->data); \ + (pGeometry)->buffer = _buffer; \ } -#define GEOMETRY_SET_PRIMITIVE(pScreen, pGeometry, _primitive) \ - (pGeometry)->primitive = _primitive +#define GEOMETRY_SET_MULTI_ARRAY(pGeometry, _array) \ + { \ + glitz_multi_array_reference (_array); \ + if ((pGeometry)->array) \ + glitz_multi_array_destroy ((pGeometry)->array); \ + (pGeometry)->array = _array; \ + } #define GEOMETRY_RESIZE(pScreen, pGeometry, size) \ xglGeometryResize (pScreen, pGeometry, size) +#define GEOMETRY_SET_TRANSLATE(pGeometry, _x, _y) \ + { \ + (pGeometry)->xOff = (_x) << 16; \ + (pGeometry)->yOff = (_y) << 16; \ + } + #define GEOMETRY_TRANSLATE(pGeometry, tx, ty) \ { \ (pGeometry)->xOff += (tx) << 16; \ @@ -522,34 +693,64 @@ xglWithdrawOffscreenArea (xglOffscreenAreaPtr pArea); (pGeometry)->yOff += (fty); \ } -#define GEOMETRY_ADD_RECT(pScreen, pGeometry, pRect, nRect) \ - xglGeometryAddRect (pScreen, pGeometry, pRect, nRect) +#define GEOMETRY_SET_VERTEX_PRIMITIVE(pGeometry, _primitive) \ + (pGeometry)->f.vertex.primitive = _primitive + +#define GEOMETRY_SET_VERTEX_DATA_TYPE(pGeometry, _type) \ + { \ + (pGeometry)->dataType = _type; \ + (pGeometry)->f.vertex.type = xglGeometryDataTypes[_type].type; \ + (pGeometry)->f.vertex.bytes_per_vertex = (pGeometry)->width * \ + xglGeometryDataTypes[_type].size; \ + } #define GEOMETRY_ADD_BOX(pScreen, pGeometry, pBox, nBox) \ - xglGeometryAddBox (pScreen, pGeometry, pBox, nBox) + xglGeometryAddBox (pScreen, pGeometry, pBox, nBox, \ + (pGeometry)->endOffset) + +#define GEOMETRY_ADD_REGION_AT(pScreen, pGeometry, pRegion, offset) \ + xglGeometryAddBox (pScreen, pGeometry, \ + REGION_RECTS (pRegion), \ + REGION_NUM_RECTS (pRegion), \ + offset) #define GEOMETRY_ADD_REGION(pScreen, pGeometry, pRegion) \ xglGeometryAddBox (pScreen, pGeometry, \ REGION_RECTS (pRegion), \ - REGION_NUM_RECTS (pRegion)) + REGION_NUM_RECTS (pRegion), \ + (pGeometry)->endOffset) #define GEOMETRY_ADD_SPAN(pScreen, pGeometry, ppt, pwidth, n) \ - xglGeometryAddSpan (pScreen, pGeometry, ppt, pwidth, n) + xglGeometryAddSpan (pScreen, pGeometry, ppt, pwidth, n, \ + (pGeometry)->endOffset) #define GEOMETRY_ADD_LINE(pScreen, pGeometry, loop, mode, npt, ppt) \ - xglGeometryAddLine (pScreen, pGeometry, loop, mode, npt, ppt) + xglGeometryAddLine (pScreen, pGeometry, loop, mode, npt, ppt, \ + (pGeometry)->endOffset) #define GEOMETRY_ADD_SEGMENT(pScreen, pGeometry, nsegInit, pSegInit) \ - xglGeometryAddSegment (pScreen, pGeometry, nsegInit, pSegInit) + xglGeometryAddSegment (pScreen, pGeometry, nsegInit, pSegInit, \ + (pGeometry)->endOffset) -#define GEOMETRY_ENABLE(pGeometry, surface, first, count) \ - xglSetGeometry (pGeometry, surface, first, count); +#define GEOMETRY_FOR_GLYPH(pScreen, pGeometry, nGlyph, ppciInit, pglyphBase) \ + xglGeometryForGlyph (pScreen, pGeometry, nGlyph, ppciInit, pglyphBase); -#define GEOMETRY_ENABLE_ALL_VERTICES(pGeometry, surface) \ - xglSetGeometry (pGeometry, surface, 0, (pGeometry)->endOffset / 2) +#define GEOMETRY_ADD_TRAPEZOID(pScreen, pGeometry, pTrap, nTrap) \ + xglGeometryAddTrapezoid (pScreen, pGeometry, pTrap, nTrap, \ + (pGeometry)->endOffset) -#define GEOMETRY_DISABLE(surface) \ - glitz_set_geometry (surface, 0, 0, NULL, NULL) +#define GEOMETRY_ADD_TRAP(pScreen, pGeometry, pTrap, nTrap) \ + xglGeometryAddTrap (pScreen, pGeometry, pTrap, nTrap, \ + (pGeometry)->endOffset) + +#define GEOMETRY_GET_FORMAT(pGeometry, format) \ + xglGeometryGetFormat (pGeometry, format) + +#define GEOMETRY_ENABLE(pGeometry, surface) \ + xglSetGeometry (pGeometry, surface) + +#define GEOMETRY_DISABLE(surface) \ + glitz_set_geometry (surface, GLITZ_GEOMETRY_TYPE_NONE, NULL, NULL) void xglGeometryResize (ScreenPtr pScreen, @@ -557,23 +758,19 @@ xglGeometryResize (ScreenPtr pScreen, int size); void -xglGeometryAddRect (ScreenPtr pScreen, - xglGeometryPtr pGeometry, - xRectangle *pRect, - int nRect); - -void xglGeometryAddBox (ScreenPtr pScreen, xglGeometryPtr pGeometry, BoxPtr pBox, - int nBox); + int nBox, + int offset); void xglGeometryAddSpan (ScreenPtr pScreen, xglGeometryPtr pGeometry, DDXPointPtr ppt, int *pwidth, - int n); + int n, + int offset); void xglGeometryAddLine (ScreenPtr pScreen, @@ -581,19 +778,53 @@ xglGeometryAddLine (ScreenPtr pScreen, int loop, int mode, int npt, - DDXPointPtr ppt); + DDXPointPtr ppt, + int offset); void xglGeometryAddSegment (ScreenPtr pScreen, xglGeometryPtr pGeometry, int nsegInit, - xSegment *pSegInit); + xSegment *pSegInit, + int offset); + +void +xglGeometryForGlyph (ScreenPtr pScreen, + xglGeometryPtr pGeometry, + unsigned int nGlyph, + CharInfoPtr *ppciInit, + pointer pglyphBase); + +void +xglGeometryAddTrapezoid (ScreenPtr pScreen, + xglGeometryPtr pGeometry, + xTrapezoid *pTrap, + int nTrap, + int offset); + +void +xglGeometryAddTrap (ScreenPtr pScreen, + xglGeometryPtr pGeometry, + xTrap *pTrap, + int nTrap, + int offset); + +xglGeometryPtr +xglGetScratchGeometryWithSize (ScreenPtr pScreen, + int size); + +xglGeometryPtr +xglGetScratchVertexGeometryWithType (ScreenPtr pScreen, + int type, + int count); + +xglGeometryPtr +xglGetScratchVertexGeometry (ScreenPtr pScreen, + int count); Bool xglSetGeometry (xglGeometryPtr pGeometry, - glitz_surface_t *surface, - int first, - int count); + glitz_surface_t *surface); /* xglpixmap.c */ @@ -619,6 +850,11 @@ xglModifyPixmapHeader (PixmapPtr pPixmap, RegionPtr xglPixmapToRegion (PixmapPtr pPixmap); +xglGeometryPtr +xglPixmapToGeometry (PixmapPtr pPixmap, + int xOff, + int yOff); + Bool xglCreatePixmapSurface (PixmapPtr pPixmap); @@ -648,10 +884,14 @@ Bool xglPrepareTarget (DrawablePtr pDrawable); void -xglAddSurfaceDamage (DrawablePtr pDrawable); +xglAddSurfaceDamage (DrawablePtr pDrawable, + RegionPtr pRegion); + +void +xglAddCurrentSurfaceDamage (DrawablePtr pDrawable); void -xglAddBitDamage (DrawablePtr pDrawable); +xglAddCurrentBitDamage (DrawablePtr pDrawable); /* xglsolid.c */ @@ -661,12 +901,32 @@ xglSolid (DrawablePtr pDrawable, glitz_operator_t op, glitz_color_t *color, xglGeometryPtr pGeometry, + int x, + int y, + int width, + int height, BoxPtr pBox, int nBox); +Bool +xglSolidGlyph (DrawablePtr pDrawable, + GCPtr pGC, + int x, + int y, + unsigned int nGlyph, + CharInfoPtr *ppci, + pointer pglyphBase); + /* xgltile.c */ +xglGeometryPtr +xglTiledBoxGeometry (PixmapPtr pTile, + int tileX, + int tileY, + BoxPtr pBox, + int nBox); + Bool xglTile (DrawablePtr pDrawable, glitz_operator_t op, @@ -674,41 +934,13 @@ xglTile (DrawablePtr pDrawable, int tileX, int tileY, xglGeometryPtr pGeometry, + int x, + int y, + int width, + int height, BoxPtr pBox, int nBox); -#define TILE_SOURCE 0 -#define TILE_MASK 1 - -void -xglSwTile (glitz_operator_t op, - glitz_surface_t *srcSurface, - glitz_surface_t *maskSurface, - glitz_surface_t *dstSurface, - int xSrc, - int ySrc, - int xMask, - int yMask, - int what, - BoxPtr pBox, - int nBox, - int xOff, - int yOff); - - -/* xglpixel.c */ - -Bool -xglSetPixels (DrawablePtr pDrawable, - char *src, - int stride, - int x, - int y, - int width, - int height, - BoxPtr pBox, - int nBox); - /* xglcopy.c */ @@ -737,9 +969,15 @@ xglCopyProc (DrawablePtr pSrc, /* xglfill.c */ Bool -xglFill (DrawablePtr pDrawable, - GCPtr pGC, - xglGeometryPtr pGeometry); +xglFill (DrawablePtr pDrawable, + GCPtr pGC, + xglGeometryPtr pGeometry, + int x, + int y, + int width, + int height, + BoxPtr pBox, + int nBox); Bool xglFillSpan (DrawablePtr pDrawable, @@ -748,7 +986,7 @@ xglFillSpan (DrawablePtr pDrawable, DDXPointPtr ppt, int *pwidth); -Bool +void xglFillRect (DrawablePtr pDrawable, GCPtr pGC, int nrect, @@ -767,12 +1005,25 @@ xglFillSegment (DrawablePtr pDrawable, int nsegInit, xSegment *pSegInit); +Bool +xglFillGlyph (DrawablePtr pDrawable, + GCPtr pGC, + int x, + int y, + unsigned int nglyph, + CharInfoPtr *ppciInit, + pointer pglyphBase); + /* xglwindow.c */ Bool xglCreateWindow (WindowPtr pWin); +Bool +xglChangeWindowAttributes (WindowPtr pWin, + unsigned long mask); + void xglCopyWindow (WindowPtr pWin, DDXPointRec ptOldOrg, @@ -959,18 +1210,20 @@ xglPushPixels (GCPtr pGC, /* xglcomp.c */ Bool -xglComp (CARD8 op, - PicturePtr pSrc, - PicturePtr pMask, - PicturePtr pDst, - INT16 xSrc, - INT16 ySrc, - INT16 xMask, - INT16 yMask, - INT16 xDst, - INT16 yDst, - CARD16 width, - CARD16 height); +xglComp (CARD8 op, + PicturePtr pSrc, + PicturePtr pMask, + PicturePtr pDst, + INT16 xSrc, + INT16 ySrc, + INT16 xMask, + INT16 yMask, + INT16 xDst, + INT16 yDst, + CARD16 width, + CARD16 height, + xglGeometryPtr pGeometry, + glitz_surface_t *mask); /* xglpict.c */ @@ -990,21 +1243,11 @@ xglComposite (CARD8 op, CARD16 height); void -xglGlyphs (CARD8 op, - PicturePtr pSrc, - PicturePtr pDst, - PictFormatPtr maskFormat, - INT16 xSrc, - INT16 ySrc, - int nlist, - GlyphListPtr list, - GlyphPtr *glyphs); - -void -xglRasterizeTrapezoid (PicturePtr pDst, - xTrapezoid *trap, - int xOff, - int yOff); +xglAddTriangles (PicturePtr pDst, + INT16 xOff, + INT16 yOff, + int ntri, + xTriangle *tris); void xglChangePicture (PicturePtr pPicture, @@ -1023,6 +1266,59 @@ xglChangePictureFilter (PicturePtr pPicture, void xglUpdatePicture (PicturePtr pPicture); +Bool +xglPictureInit (ScreenPtr pScreen); + + +/* xglglyph.c */ + +Bool +xglRealizeGlyph (ScreenPtr pScreen, + GlyphPtr pGlyph); + +void +xglUnrealizeGlyph (ScreenPtr pScreen, + GlyphPtr pGlyph); + +Bool +xglInitGlyphCache (xglGlyphCachePtr pCache, + ScreenPtr pScreen, + PictFormatPtr format); + +void +xglFiniGlyphCache (xglGlyphCachePtr pCache); + +void +xglGlyphs (CARD8 op, + PicturePtr pSrc, + PicturePtr pDst, + PictFormatPtr maskFormat, + INT16 xSrc, + INT16 ySrc, + int nlist, + GlyphListPtr list, + GlyphPtr *glyphs); + + +/* xgltrap.c */ + +void +xglTrapezoids (CARD8 op, + PicturePtr pSrc, + PicturePtr pDst, + PictFormatPtr maskFormat, + INT16 xSrc, + INT16 ySrc, + int nTrap, + xTrapezoid *traps); + +void +xglAddTraps (PicturePtr pDst, + INT16 xOff, + INT16 yOff, + int nTrap, + xTrap *traps); + #endif #endif /* _XGL_H_ */ diff --git a/hw/xgl/xglarea.c b/hw/xgl/xglarea.c new file mode 100644 index 000000000..b09e454ba --- /dev/null +++ b/hw/xgl/xglarea.c @@ -0,0 +1,318 @@ +/* + * Copyright © 2005 Novell, 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 + * Novell, Inc. not be used in advertising or publicity pertaining to + * distribution of the software without specific, written prior permission. + * Novell, Inc. makes no representations about the suitability of this + * software for any purpose. It is provided "as is" without express or + * implied warranty. + * + * NOVELL, INC. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN + * NO EVENT SHALL NOVELL, INC. BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS + * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, + * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION + * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Author: David Reveman <davidr@novell.com> + */ + +#include "xgl.h" + +static Bool +xglAreaMoveIn (xglAreaPtr pArea, + pointer closure) +{ + pArea->closure = closure; + pArea->state = xglAreaOccupied; + + return (*pArea->pRoot->funcs->MoveIn) (pArea, closure); +} + +static void +xglAreaMoveOut (xglAreaPtr pArea) +{ + (*pArea->pRoot->funcs->MoveOut) (pArea, pArea->closure); + + pArea->state = xglAreaAvailable; +} + +static xglAreaPtr +xglAreaCreate (xglRootAreaPtr pRoot, + int level, + int x, + int y, + int width, + int height) +{ + xglAreaPtr pArea; + int n = 4; + + pArea = xalloc (sizeof (xglAreaRec) + pRoot->devPrivateSize); + if (!pArea) + return NULL; + + pArea->level = level; + pArea->x = x; + pArea->y = y; + pArea->width = width; + pArea->height = height; + pArea->pRoot = pRoot; + pArea->closure = (pointer) 0; + pArea->state = xglAreaAvailable; + + while (n--) + pArea->pArea[n] = NULL; + + if (pRoot->devPrivateSize) + pArea->devPrivate.ptr = pArea + 1; + else + pArea->devPrivate.ptr = (pointer) 0; + + if (!(*pArea->pRoot->funcs->Create) (pArea)) + { + free (pArea); + return NULL; + } + + return pArea; +} + +static void +xglAreaDestroy (xglAreaPtr pArea) +{ + if (!pArea) + return; + + if (pArea->state == xglAreaOccupied) + { + xglAreaMoveOut (pArea); + } + else + { + int n = 4; + + while (n--) + xglAreaDestroy (pArea->pArea[n]); + } + + xfree (pArea); +} + +static xglAreaPtr +xglAreaGetTopScoredSubArea (xglAreaPtr pArea) +{ + switch (pArea->state) { + case xglAreaOccupied: + return pArea; + case xglAreaAvailable: + break; + case xglAreaDivided: + { + xglAreaPtr tmp, top = NULL; + int i; + + for (i = 0; i < 4; i++) + { + if (pArea->pArea[i]) + { + tmp = xglAreaGetTopScoredSubArea (pArea->pArea[i]); + if (!tmp) + break; + + if ((!top) || + (*pArea->pRoot->funcs->CompareScore) (tmp, + tmp->closure, + top->closure) > 0) + top = tmp; + } + } + return top; + } + } + return NULL; +} + +static Bool +xglAreaFind (xglAreaPtr pArea, + int width, + int height, + Bool kickOut, + pointer closure) +{ + if (pArea->width < width || pArea->height < height) + return FALSE; + + switch (pArea->state) { + case xglAreaOccupied: + if (kickOut) + { + if ((*pArea->pRoot->funcs->CompareScore) (pArea, + pArea->closure, + closure) >= 0) + return FALSE; + + xglAreaMoveOut (pArea); + } else + return FALSE; + + /* fall-through */ + case xglAreaAvailable: + { + if (pArea->level == pArea->pRoot->maxLevel || + (pArea->width == width && pArea->height == height)) + { + if (xglAreaMoveIn (pArea, closure)) + return TRUE; + } + else + { + int dx[4], dy[4], w[4], h[4], i; + + dx[0] = dx[2] = dy[0] = dy[1] = 0; + + w[0] = w[2] = dx[1] = dx[3] = width; + h[0] = h[1] = dy[2] = dy[3] = height; + + w[1] = w[3] = pArea->width - width; + h[2] = h[3] = pArea->height - height; + + for (i = 0; i < 2; i++) + { + if (w[i]) + pArea->pArea[i] = + xglAreaCreate (pArea->pRoot, + pArea->level + 1, + pArea->x + dx[i], + pArea->y + dy[i], + w[i], h[i]); + } + + for (; i < 4; i++) + { + if (w[i] && h[i]) + pArea->pArea[i] = + xglAreaCreate (pArea->pRoot, + pArea->level + 1, + pArea->x + dx[i], + pArea->y + dy[i], + w[i], h[i]); + } + + pArea->state = xglAreaDivided; + + if (xglAreaFind (pArea->pArea[0], width, height, kickOut, closure)) + return TRUE; + } + } break; + case xglAreaDivided: + { + xglAreaPtr topArea; + int i, rejected = FALSE; + + for (i = 0; i < 4; i++) + { + if (pArea->pArea[i]) + { + if (pArea->pArea[i]->width >= width && + pArea->pArea[i]->height >= height) + { + if (xglFindArea (pArea->pArea[i], width, height, kickOut, + closure)) + return TRUE; + + rejected = TRUE; + } + } + } + + if (rejected) + return FALSE; + + topArea = xglAreaGetTopScoredSubArea (pArea); + if (topArea) + { + if (kickOut) + { + if ((*pArea->pRoot->funcs->CompareScore) (topArea, + topArea->closure, + closure) >= 0) + return FALSE; + } else + return FALSE; + } + + for (i = 0; i < 4; i++) + { + xglAreaDestroy (pArea->pArea[i]); + pArea->pArea[i] = NULL; + } + + pArea->state = xglAreaAvailable; + if (xglFindArea (pArea, width, height, TRUE, closure)) + return TRUE; + + } break; + } + + return FALSE; +} + +Bool +xglRootAreaInit (xglRootAreaPtr pRoot, + int maxLevel, + int width, + int height, + int devPrivateSize, + xglAreaFuncsPtr funcs, + pointer closure) +{ + pRoot->maxLevel = maxLevel; + pRoot->funcs = funcs; + pRoot->devPrivateSize = devPrivateSize; + pRoot->closure = closure; + + pRoot->pArea = xglAreaCreate (pRoot, 0, 0, 0, width, height); + if (!pRoot->pArea) + return FALSE; + + return TRUE; +} + +void +xglRootAreaFini (xglRootAreaPtr pRoot) +{ + xglAreaDestroy (pRoot->pArea); +} + +void +xglLeaveArea (xglAreaPtr pArea) +{ + xglAreaMoveOut (pArea); +} + +void +xglWithdrawArea (xglAreaPtr pArea) +{ + pArea->closure = NULL; + pArea->state = xglAreaAvailable; +} + +Bool +xglFindArea (xglAreaPtr pArea, + int width, + int height, + Bool kickOut, + pointer closure) +{ + if (width < 1 || height < 0) + return FALSE; + + return xglAreaFind (pArea, width, height, kickOut, closure); +} diff --git a/hw/xgl/xglbstore.c b/hw/xgl/xglbstore.c index 8760efaec..65b4bbf5c 100644 --- a/hw/xgl/xglbstore.c +++ b/hw/xgl/xglbstore.c @@ -5,7 +5,7 @@ * 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 names of + * appear in supporting documentation, and that the name of * David Reveman not be used in advertising or publicity pertaining to * distribution of the software without specific, written prior permission. * David Reveman makes no representations about the suitability of this @@ -20,7 +20,7 @@ * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * - * Author: David Reveman <davidr@freedesktop.org> + * Author: David Reveman <davidr@novell.com> */ #include "xgl.h" @@ -31,7 +31,7 @@ #define XGL_BSTORE_FALLBACK_EPILOGUE(pDrawable, func, xglfunc) \ XGL_SCREEN_WRAP (func, xglfunc); \ - xglAddSurfaceDamage (pDrawable) + xglAddCurrentSurfaceDamage (pDrawable) /* * The follwong functions are not yet tested so we can assume that they @@ -61,7 +61,7 @@ xglSaveAreas (PixmapPtr pPixmap, REGION_RECTS (prgnSave), REGION_NUM_RECTS (prgnSave))) { - xglAddBitDamage (&pPixmap->drawable); + xglAddCurrentBitDamage (&pPixmap->drawable); return; } @@ -101,7 +101,7 @@ xglRestoreAreas (PixmapPtr pPixmap, REGION_RECTS (prgnRestore), REGION_NUM_RECTS (prgnRestore))) { - xglAddBitDamage (&pPixmap->drawable); + xglAddCurrentBitDamage (&pPixmap->drawable); return; } diff --git a/hw/xgl/xglcmap.c b/hw/xgl/xglcmap.c index be383a103..3c7a9747c 100644 --- a/hw/xgl/xglcmap.c +++ b/hw/xgl/xglcmap.c @@ -5,7 +5,7 @@ * 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 names of + * appear in supporting documentation, and that the name of * David Reveman not be used in advertising or publicity pertaining to * distribution of the software without specific, written prior permission. * David Reveman makes no representations about the suitability of this @@ -20,7 +20,7 @@ * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * - * Author: David Reveman <davidr@freedesktop.org> + * Author: David Reveman <davidr@novell.com> */ #include "xgl.h" @@ -257,7 +257,7 @@ xglClearVisualTypes (void) void xglInitPixmapFormats (ScreenPtr pScreen) { - glitz_format_t *format; + glitz_format_t *format, **best; int i, j; XGL_SCREEN_PRIV (pScreen); @@ -275,6 +275,7 @@ xglInitPixmapFormats (ScreenPtr pScreen) pScreenPriv->pixmapFormats[i].pPixel = &xglPixelFormats[j]; pScreenPriv->pixmapFormats[i].format = NULL; + best = &pScreenPriv->pixmapFormats[i].format; rs = Ones (xglPixelFormats[j].masks.red_mask); gs = Ones (xglPixelFormats[j].masks.green_mask); @@ -287,13 +288,28 @@ xglInitPixmapFormats (ScreenPtr pScreen) 0, NULL, k++); if (format && format->type == GLITZ_FORMAT_TYPE_COLOR) { - if (rs == format->color.red_size && - gs == format->color.green_size && - bs == format->color.blue_size && - as == format->color.alpha_size) + /* formats must have an alpha channel, otherwise + filtering wont match the render spec. */ + if (!format->color.alpha_size) + continue; + + /* find best matching sufficient format */ + if (format->color.red_size >= rs && + format->color.green_size >= gs && + format->color.blue_size >= bs && + format->color.alpha_size >= as) { - pScreenPriv->pixmapFormats[i].format = format; - break; + if (*best) + { + if (((format->color.red_size - rs) + + (format->color.green_size - gs) + + (format->color.blue_size - bs)) < + (((*best)->color.red_size - rs) + + ((*best)->color.green_size - gs) + + ((*best)->color.blue_size - bs))) + *best = format; + } else + *best = format; } } } while (format); diff --git a/hw/xgl/xglcomp.c b/hw/xgl/xglcomp.c index edae5d3ad..320221c8a 100644 --- a/hw/xgl/xglcomp.c +++ b/hw/xgl/xglcomp.c @@ -5,7 +5,7 @@ * 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 names of + * appear in supporting documentation, and that the name of * David Reveman not be used in advertising or publicity pertaining to * distribution of the software without specific, written prior permission. * David Reveman makes no representations about the suitability of this @@ -20,7 +20,7 @@ * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * - * Author: David Reveman <davidr@freedesktop.org> + * Author: David Reveman <davidr@novell.com> */ #include "xgl.h" @@ -49,22 +49,24 @@ static glitz_operator_t xglOperators[] = { #define XGL_OPERATOR(op) (xglOperators[op]) Bool -xglComp (CARD8 op, - PicturePtr pSrc, - PicturePtr pMask, - PicturePtr pDst, - INT16 xSrc, - INT16 ySrc, - INT16 xMask, - INT16 yMask, - INT16 xDst, - INT16 yDst, - CARD16 width, - CARD16 height) +xglComp (CARD8 op, + PicturePtr pSrc, + PicturePtr pMask, + PicturePtr pDst, + INT16 xSrc, + INT16 ySrc, + INT16 xMask, + INT16 yMask, + INT16 xDst, + INT16 yDst, + CARD16 width, + CARD16 height, + xglGeometryPtr pGeometry, + glitz_surface_t *mask) { ScreenPtr pScreen = pDst->pDrawable->pScreen; - xglPixmapPtr pSrcPriv, pMaskPriv; - glitz_surface_t *dst; + xglPixmapPtr pSrcPriv; + glitz_surface_t *src, *dst; int dstXoff, dstYoff; RegionRec region; BoxPtr pBox; @@ -78,24 +80,21 @@ xglComp (CARD8 op, if (op >= NUM_XGL_OPERATORS) return FALSE; - + if (pSrc->pDrawable->type != DRAWABLE_PIXMAP) return FALSE; + if (pSrc->pDrawable->bitsPerPixel == 1) + return FALSE; + if (pMask) { if (pMask->pDrawable->type != DRAWABLE_PIXMAP) return FALSE; - /* - * Why? - */ - if (pSrc->pDrawable == pMask->pDrawable) + if (pSrc->pDrawable == pMask->pDrawable && pSrc != pMask) return FALSE; } - - xDst += pDst->pDrawable->x; - yDst += pDst->pDrawable->y; if (!miComputeCompositeRegion (®ion, pSrc, pMask, pDst, xSrc, ySrc, xMask, yMask, @@ -105,29 +104,6 @@ xglComp (CARD8 op, pBox = REGION_RECTS (®ion); nBox = REGION_NUM_RECTS (®ion); - /* - * Simple copy - */ - if (op == PictOpSrc && !pMask && - !pSrc->transform && !pSrc->repeat && pSrc->filter <= 1) - { - if (xglCopy (pSrc->pDrawable, - pDst->pDrawable, - xSrc - xDst, - ySrc - yDst, - pBox, - nBox)) - { - REGION_UNINIT (pScreen, ®ion); - xglAddBitDamage (pDst->pDrawable); - - return TRUE; - } - - REGION_UNINIT (pScreen, ®ion); - return FALSE; - } - if (!xglPrepareTarget (pDst->pDrawable)) { REGION_UNINIT (pScreen, ®ion); @@ -135,116 +111,159 @@ xglComp (CARD8 op, } XGL_GET_DRAWABLE (pDst->pDrawable, dst, dstXoff, dstYoff); - + if (!xglSyncSurface (pSrc->pDrawable)) { REGION_UNINIT (pScreen, ®ion); return FALSE; } - + pSrcPriv = XGL_GET_PIXMAP_PRIV ((PixmapPtr) pSrc->pDrawable); if (XGL_PICTURE_CHANGES (pSrcPriv->pictureMask)) xglUpdatePicture (pSrc); + src = pSrcPriv->surface; + if (pMask) { - if (!xglSyncSurface (pMask->pDrawable)) + xglPixmapPtr pMaskPriv; + + /* bitmap as mask */ + if (pMask->pDrawable->bitsPerPixel == 1) { - REGION_UNINIT (pScreen, ®ion); - return FALSE; + if (pGeometry) + { + REGION_UNINIT (pScreen, ®ion); + return FALSE; + } + + pGeometry = + xglPixmapToGeometry ((PixmapPtr) pMask->pDrawable, + xDst - xMask, + yDst - yMask); + if (!pGeometry) + { + REGION_UNINIT (pScreen, ®ion); + return FALSE; + } } + else + { + if (!xglSyncSurface (pMask->pDrawable)) + { + REGION_UNINIT (pScreen, ®ion); + return FALSE; + } + + pMaskPriv = XGL_GET_PIXMAP_PRIV ((PixmapPtr) pMask->pDrawable); + if (XGL_PICTURE_CHANGES (pMaskPriv->pictureMask)) + xglUpdatePicture (pMask); + + mask = pMaskPriv->surface; + } + } - pMaskPriv = XGL_GET_PIXMAP_PRIV ((PixmapPtr) pMask->pDrawable); - if (XGL_PICTURE_CHANGES (pMaskPriv->pictureMask)) - xglUpdatePicture (pMask); - } else - pMaskPriv = NULL; - - if (nBox > 1) + if (!pGeometry) { - xglGeometryRec geometry; - - GEOMETRY_INIT (pScreen, &geometry, REGION_NUM_RECTS (®ion) << 3); - GEOMETRY_ADD_BOX (pScreen, &geometry, pBox, nBox); - GEOMETRY_TRANSLATE (&geometry, dstXoff, dstYoff); - - if (!GEOMETRY_ENABLE_ALL_VERTICES (&geometry, dst)) + if (!pSrc->transform && pSrc->filter != PictFilterConvolution) { - GEOMETRY_UNINIT (&geometry); - return FALSE; + if (pSrc->repeat) + { + /* tile */ + if (!pSrcPriv->acceleratedTile && + (pSrc->pDrawable->width > 1 || + pSrc->pDrawable->height > 1)) + { + pGeometry = + xglTiledBoxGeometry ((PixmapPtr) pSrc->pDrawable, + xSrc - xDst, ySrc - yDst, + pBox, nBox); + if (!pGeometry) + { + REGION_UNINIT (pScreen, ®ion); + return FALSE; + } + + pBox = REGION_EXTENTS (pScreen, ®ion); + nBox = 1; + } + } + else + { + /* copy */ + if (op == PictOpSrc && !mask) + { + if (xglCopy (pSrc->pDrawable, + pDst->pDrawable, + xSrc - xDst, + ySrc - yDst, + pBox, + nBox)) + { + REGION_UNINIT (pScreen, ®ion); + return TRUE; + } + } + } } - pBox = REGION_EXTENTS (pScreen, ®ion); - } else - GEOMETRY_DISABLE (dst); + if (nBox > 1) + { + pGeometry = xglGetScratchVertexGeometry (pScreen, 4 * nBox); + + GEOMETRY_ADD_BOX (pScreen, pGeometry, pBox, nBox); + + pBox = REGION_EXTENTS (pScreen, ®ion); + } - xSrc += pBox->x1 - xDst; - ySrc += pBox->y1 - yDst; + xSrc += pBox->x1 - xDst; + ySrc += pBox->y1 - yDst; - if (pMask) - { - xMask += pBox->x1 - xDst; - yMask += pBox->y1 - yDst; - } + if (pMask) + { + xMask += pBox->x1 - xDst; + yMask += pBox->y1 - yDst; + } - xDst = pBox->x1; - yDst = pBox->y1; + xDst = pBox->x1; + yDst = pBox->y1; - width = pBox->x2 - pBox->x1; - height = pBox->y2 - pBox->y1; - - REGION_UNINIT (pScreen, ®ion); + width = pBox->x2 - pBox->x1; + height = pBox->y2 - pBox->y1; + } + else + { + glitz_surface_set_clip_region (dst, + dstXoff, dstYoff, + (glitz_box_t *) pBox, nBox); + } - /* - * Do software tile instead if hardware can't do it. - */ - if (pSrc->repeat && !pSrcPriv->acceleratedTile) + if (pGeometry) { - BoxRec box; + GEOMETRY_TRANSLATE (pGeometry, dstXoff, dstYoff); - if (pSrc->transform || pSrc->filter > 1) - return FALSE; - - /* - * Don't allow software tile with really small pixmaps. - */ - if (pSrc->pDrawable->width < 8 && pSrc->pDrawable->height < 8) + if (!GEOMETRY_ENABLE (pGeometry, dst)) + { + REGION_UNINIT (pScreen, ®ion); return FALSE; + } + } else + GEOMETRY_DISABLE (dst); - box.x1 = xDst + dstXoff; - box.y1 = yDst + dstYoff; - box.x2 = box.x1 + width; - box.y2 = box.y1 + height; - - glitz_surface_set_fill (pSrcPriv->surface, GLITZ_FILL_TRANSPARENT); - - xglSwTile (XGL_OPERATOR (op), - pSrcPriv->surface, - (pMaskPriv)? pMaskPriv->surface: NULL, - dst, - xSrc - box.x1, ySrc - box.y1, - xMask - box.x1, yMask - box.y1, - TILE_SOURCE, - &box, 1, - 0, 0); - } - else - { - glitz_composite (XGL_OPERATOR (op), - pSrcPriv->surface, - (pMaskPriv)? pMaskPriv->surface: NULL, - dst, - xSrc, ySrc, - xMask, yMask, - xDst + dstXoff, yDst + dstYoff, - width, height); - } + glitz_composite (XGL_OPERATOR (op), + src, mask, dst, + xSrc, ySrc, + xMask, yMask, + xDst + dstXoff, yDst + dstYoff, + width, height); + + glitz_surface_set_clip_region (dst, 0, 0, NULL, 0); + + REGION_UNINIT (pScreen, ®ion); if (glitz_surface_get_status (dst)) return FALSE; - xglAddBitDamage (pDst->pDrawable); - return TRUE; } diff --git a/hw/xgl/xglcopy.c b/hw/xgl/xglcopy.c index aca4ea418..c34459b5a 100644 --- a/hw/xgl/xglcopy.c +++ b/hw/xgl/xglcopy.c @@ -5,7 +5,7 @@ * 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 names of + * appear in supporting documentation, and that the name of * David Reveman not be used in advertising or publicity pertaining to * distribution of the software without specific, written prior permission. * David Reveman makes no representations about the suitability of this @@ -20,10 +20,11 @@ * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * - * Author: David Reveman <davidr@freedesktop.org> + * Author: David Reveman <davidr@novell.com> */ #include "xgl.h" +#include "fb.h" Bool xglCopy (DrawablePtr pSrc, @@ -33,101 +34,59 @@ xglCopy (DrawablePtr pSrc, BoxPtr pBox, int nBox) { - glitz_surface_t *srcSurface; - glitz_surface_t *dstSurface; + glitz_surface_t *src, *dst; int srcXoff, srcYoff; int dstXoff, dstYoff; + if (!nBox) + return TRUE; + if (xglPrepareTarget (pDst)) { - glitz_drawable_t *srcDrawable; - glitz_drawable_t *dstDrawable; - XGL_SCREEN_PRIV (pDst->pScreen); - XGL_DRAWABLE_PIXMAP_PRIV (pSrc); - + if (!xglSyncSurface (pSrc)) return FALSE; - XGL_GET_DRAWABLE (pSrc, srcSurface, srcXoff, srcYoff); - XGL_GET_DRAWABLE (pDst, dstSurface, dstXoff, dstYoff); - - /* - * Blit to screen. - */ - if (dstSurface == pScreenPriv->surface) - XGL_INCREMENT_PIXMAP_SCORE (pPixmapPriv, 5000); + XGL_GET_DRAWABLE (pDst, dst, dstXoff, dstYoff); - srcDrawable = glitz_surface_get_attached_drawable (srcSurface); - dstDrawable = glitz_surface_get_attached_drawable (dstSurface); - - if (srcDrawable != dstDrawable && nBox > 1) + /* blit to screen */ + if (dst == pScreenPriv->surface) { - xglGeometryRec geometry; - BoxRec extents; - - BOX_EXTENTS (pBox, nBox, &extents); - - GEOMETRY_INIT (pDst->pScreen, &geometry, nBox << 3); - GEOMETRY_ADD_BOX (pDst->pScreen, &geometry, pBox, nBox); - GEOMETRY_TRANSLATE (&geometry, dstXoff, dstYoff); - - if (!GEOMETRY_ENABLE_ALL_VERTICES (&geometry, dstSurface)) - return FALSE; + XGL_DRAWABLE_PIXMAP_PRIV (pSrc); - pPixmapPriv->pictureMask |= - xglPCFillMask | xglPCFilterMask | xglPCTransformMask; - - glitz_surface_set_fill (srcSurface, GLITZ_FILL_TRANSPARENT); - glitz_surface_set_filter (srcSurface, GLITZ_FILTER_NEAREST, - NULL, 0); - glitz_surface_set_transform (srcSurface, NULL); - - glitz_composite (GLITZ_OPERATOR_SRC, - srcSurface, NULL, dstSurface, - extents.x1 + dx + srcXoff, - extents.y1 + dy + srcYoff, - 0, 0, - extents.x1 + dstXoff, - extents.y1 + dstYoff, - extents.x2 - extents.x1, - extents.y2 - extents.y1); - - GEOMETRY_UNINIT (&geometry); - - if (glitz_surface_get_status (dstSurface)) - return FALSE; - - return TRUE; + XGL_INCREMENT_PIXMAP_SCORE (pPixmapPriv, 5000); } } else { if (!xglPrepareTarget (pSrc)) return FALSE; - + if (!xglSyncSurface (pDst)) return FALSE; - - XGL_GET_DRAWABLE (pSrc, srcSurface, srcXoff, srcYoff); - XGL_GET_DRAWABLE (pDst, dstSurface, dstXoff, dstYoff); + + XGL_GET_DRAWABLE (pDst, dst, dstXoff, dstYoff); } - while (nBox--) - { - glitz_copy_area (srcSurface, - dstSurface, - pBox->x1 + dx + srcXoff, - pBox->y1 + dy + srcYoff, - pBox->x2 - pBox->x1, - pBox->y2 - pBox->y1, - pBox->x1 + dstXoff, - pBox->y1 + dstYoff); + XGL_GET_DRAWABLE (pSrc, src, srcXoff, srcYoff); - pBox++; - } + glitz_surface_set_clip_region (dst, + dstXoff, dstYoff, + (glitz_box_t *) pBox, nBox); + + glitz_copy_area (src, + dst, + pDst->x + srcXoff + dx, + pDst->y + srcYoff + dy, + pDst->width, + pDst->height, + pDst->x + dstXoff, + pDst->y + dstYoff); - if (glitz_surface_get_status (dstSurface)) + glitz_surface_set_clip_region (dst, 0, 0, NULL, 0); + + if (glitz_surface_get_status (dst)) return FALSE; return TRUE; @@ -146,7 +105,59 @@ xglCopyProc (DrawablePtr pSrc, Pixel bitplane, void *closure) { - Bool *pRet = (Bool *) closure; - - *pRet = xglCopy (pSrc, pDst, dx, dy, pBox, nBox); + BoxPtr pSrcBox = (BoxPtr) closure; + + if (!xglCopy (pSrc, pDst, dx, dy, pBox, nBox)) + { + RegionPtr pDamageRegion; + glitz_surface_t *dst; + int dstXoff, dstYoff; + RegionRec region; + BoxRec box; + + XGL_DRAWABLE_PIXMAP (pDst); + XGL_PIXMAP_PRIV (pPixmap); + + XGL_GET_DRAWABLE (pDst, dst, dstXoff, dstYoff); + + pDamageRegion = DamageRegion (pPixmapPriv->pDamage); + + if (!xglMapPixmapBits (pPixmap)) + FatalError (XGL_SW_FAILURE_STRING); + + if (!xglSyncBits (pSrc, pSrcBox)) + FatalError (XGL_SW_FAILURE_STRING); + + fbCopyNtoN (pSrc, pDst, pGC, + pBox, nBox, + dx, dy, + reverse, upsidedown, bitplane, + (void *) 0); + + pPixmapPriv->damageBox = miEmptyBox; + if (!pPixmapPriv->format) + return; + + while (nBox--) + { + box.x1 = pBox->x1 + dstXoff; + box.y1 = pBox->y1 + dstYoff; + box.x2 = pBox->x2 + dstXoff; + box.y2 = pBox->y2 + dstYoff; + + REGION_INIT (pDst->pScreen, ®ion, &box, 1); + REGION_UNION (pDst->pScreen, + pDamageRegion, pDamageRegion, ®ion); + REGION_UNINIT (pDst->pScreen, ®ion); + + pBox++; + } + + if (pPixmapPriv->target == xglPixmapTargetIn) + { + if (!xglSyncSurface (pDst)) + FatalError (XGL_SW_FAILURE_STRING); + } + } else + xglAddCurrentBitDamage (pDst); } diff --git a/hw/xgl/xglfill.c b/hw/xgl/xglfill.c index 7bb2c8d4d..7832df27e 100644 --- a/hw/xgl/xglfill.c +++ b/hw/xgl/xglfill.c @@ -5,7 +5,7 @@ * 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 names of + * appear in supporting documentation, and that the name of * David Reveman not be used in advertising or publicity pertaining to * distribution of the software without specific, written prior permission. * David Reveman makes no representations about the suitability of this @@ -20,36 +20,48 @@ * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * - * Author: David Reveman <davidr@freedesktop.org> + * Author: David Reveman <davidr@novell.com> */ #include "xgl.h" #include "gcstruct.h" +#include "fb.h" Bool xglFill (DrawablePtr pDrawable, GCPtr pGC, - xglGeometryPtr pGeometry) + xglGeometryPtr pGeometry, + int x, + int y, + int width, + int height, + BoxPtr pBox, + int nBox) { XGL_GC_PRIV (pGC); switch (pGC->fillStyle) { case FillSolid: - if (xglSolid (pDrawable, pGCPriv->op, &pGCPriv->fg, + if (xglSolid (pDrawable, + pGCPriv->op, &pGCPriv->fg, pGeometry, - REGION_RECTS (pGC->pCompositeClip), - REGION_NUM_RECTS (pGC->pCompositeClip))) + x, y, + width, height, + pBox, nBox)) return TRUE; break; case FillStippled: case FillOpaqueStippled: break; case FillTiled: - if (xglTile (pDrawable, pGCPriv->op, pGC->tile.pixmap, - -pGC->patOrg.x, -pGC->patOrg.y, + if (xglTile (pDrawable, + pGCPriv->op, pGC->tile.pixmap, + -(pGC->patOrg.x + pDrawable->x), + -(pGC->patOrg.y + pDrawable->y), pGeometry, - REGION_RECTS (pGC->pCompositeClip), - REGION_NUM_RECTS (pGC->pCompositeClip))) + x, y, + width, height, + pBox, nBox)) return TRUE; break; } @@ -57,26 +69,163 @@ xglFill (DrawablePtr pDrawable, return FALSE; } -Bool +#define N_STACK_BOX 1024 + +static BoxPtr +xglMoreBoxes (BoxPtr stackBox, + BoxPtr heapBox, + int nBoxes) +{ + Bool stack = !heapBox; + + heapBox = xrealloc (heapBox, sizeof (BoxRec) * nBoxes); + if (!heapBox) + return NULL; + + if (stack) + memcpy (heapBox, stackBox, sizeof (BoxRec) * N_STACK_BOX); + + return heapBox; +} + +#define ADD_BOX(pBox, nBox, stackBox, heapBox, size, box) \ + { \ + if ((nBox) == (size)) \ + { \ + (size) *= 2; \ + (heapBox) = xglMoreBoxes (stackBox, heapBox, size); \ + if (!(heapBox)) \ + return; \ + (pBox) = (heapBox) + (nBox); \ + } \ + *(pBox)++ = (box); \ + (nBox)++; \ + } + +void xglFillRect (DrawablePtr pDrawable, GCPtr pGC, int nrect, xRectangle *prect) { - xglGeometryRec geometry; + RegionPtr pClip = pGC->pCompositeClip; + BoxPtr pClipBox; + BoxPtr pExtent = REGION_EXTENTS (pGC->pScreen, pClip); + BoxRec full, part; + BoxPtr heapBox = NULL; + BoxRec stackBox[N_STACK_BOX]; + int size = N_STACK_BOX; + BoxPtr pBox = stackBox; + int n, nBox = 0; - GEOMETRY_INIT (pGC->pScreen, &geometry, nrect << 3); - GEOMETRY_ADD_RECT (pGC->pScreen, &geometry, prect, nrect); - GEOMETRY_TRANSLATE (&geometry, pDrawable->x, pDrawable->y); - - if (xglFill (pDrawable, pGC, &geometry)) + while (nrect--) { - GEOMETRY_UNINIT (&geometry); - return TRUE; - } + full.x1 = prect->x + pDrawable->x; + full.y1 = prect->y + pDrawable->y; + full.x2 = full.x1 + (int) prect->width; + full.y2 = full.y1 + (int) prect->height; + + prect++; + + if (full.x1 < pExtent->x1) + full.x1 = pExtent->x1; + + if (full.y1 < pExtent->y1) + full.y1 = pExtent->y1; + + if (full.x2 > pExtent->x2) + full.x2 = pExtent->x2; + + if (full.y2 > pExtent->y2) + full.y2 = pExtent->y2; + + if (full.x1 >= full.x2 || full.y1 >= full.y2) + continue; + + n = REGION_NUM_RECTS (pClip); + + if (n == 1) + { + ADD_BOX (pBox, nBox, stackBox, heapBox, size, full); + } + else + { + pClipBox = REGION_RECTS (pClip); + + while (n--) + { + part.x1 = pClipBox->x1; + if (part.x1 < full.x1) + part.x1 = full.x1; + + part.y1 = pClipBox->y1; + if (part.y1 < full.y1) + part.y1 = full.y1; + + part.x2 = pClipBox->x2; + if (part.x2 > full.x2) + part.x2 = full.x2; + + part.y2 = pClipBox->y2; + if (part.y2 > full.y2) + part.y2 = full.y2; - GEOMETRY_UNINIT (&geometry); - return FALSE; + pClipBox++; + + if (part.x1 < part.x2 && part.y1 < part.y2) + ADD_BOX (pBox, nBox, stackBox, heapBox, size, part); + } + } + } + + pBox = (heapBox) ? heapBox : stackBox; + + if (!xglFill (pDrawable, pGC, NULL, + pExtent->x1, pExtent->y1, + pExtent->x2 - pExtent->x1, pExtent->y2 - pExtent->y1, + pBox, nBox)) + { + RegionRec region; + Bool overlap; + + XGL_DRAWABLE_PIXMAP (pDrawable); + + if (!xglMapPixmapBits (pPixmap)) + FatalError (XGL_SW_FAILURE_STRING); + + switch (pGC->fillStyle) { + case FillSolid: + break; + case FillStippled: + case FillOpaqueStippled: + if (!xglSyncBits (&pGC->stipple->drawable, NullBox)) + FatalError (XGL_SW_FAILURE_STRING); + break; + case FillTiled: + if (!xglSyncBits (&pGC->tile.pixmap->drawable, NullBox)) + FatalError (XGL_SW_FAILURE_STRING); + break; + } + + REGION_INIT (pGC->pScreen, ®ion, pBox, nBox); + + while (nBox--) + { + fbFill (pDrawable, pGC, + pBox->x1, pBox->y1, + pBox->x2 - pBox->x1, pBox->y2 - pBox->y1); + pBox++; + } + + /* hmm, overlap can't be good, don't know what to do about that */ + REGION_VALIDATE (pGC->pScreen, ®ion, &overlap); + xglAddSurfaceDamage (pDrawable, ®ion); + REGION_UNINIT (pGC->pScreen, ®ion); + } else + xglAddCurrentBitDamage (pDrawable); + + if (heapBox) + xfree (heapBox); } Bool @@ -86,23 +235,26 @@ xglFillSpan (DrawablePtr pDrawable, DDXPointPtr ppt, int *pwidth) { - xglGeometryRec geometry; + BoxPtr pExtent; + xglGeometryPtr pGeometry; - GEOMETRY_INIT (pGC->pScreen, &geometry, n << 2); - GEOMETRY_ADD_SPAN (pGC->pScreen, &geometry, ppt, pwidth, n); + pExtent = REGION_EXTENTS (pDrawable->pScreen, pGC->pCompositeClip); + + pGeometry = xglGetScratchVertexGeometry (pGC->pScreen, 2 * n); + + GEOMETRY_ADD_SPAN (pGC->pScreen, pGeometry, ppt, pwidth, n); /* Spans are treated as lines so they need a 0.5 translate */ - GEOMETRY_TRANSLATE_FIXED (&geometry, 1 << 15, 1 << 15); - GEOMETRY_SET_PRIMITIVE (pGC->pScreen, &geometry, - GLITZ_GEOMETRY_PRIMITIVE_LINES); + GEOMETRY_TRANSLATE_FIXED (pGeometry, 1 << 15, 1 << 15); + GEOMETRY_SET_VERTEX_PRIMITIVE (pGeometry, GLITZ_PRIMITIVE_LINES); - if (xglFill (pDrawable, pGC, &geometry)) - { - GEOMETRY_UNINIT (&geometry); + if (xglFill (pDrawable, pGC, pGeometry, + pExtent->x1, pExtent->y1, + pExtent->x2 - pExtent->x1, pExtent->y2 - pExtent->y1, + REGION_RECTS (pGC->pCompositeClip), + REGION_NUM_RECTS (pGC->pCompositeClip))) return TRUE; - } - GEOMETRY_UNINIT (&geometry); return FALSE; } @@ -113,9 +265,12 @@ xglFillLine (DrawablePtr pDrawable, int npt, DDXPointPtr ppt) { - xglGeometryRec geometry; + BoxPtr pExtent; + xglGeometryPtr pGeometry; Bool coincident_endpoints; + pExtent = REGION_EXTENTS (pDrawable->pScreen, pGC->pCompositeClip); + coincident_endpoints = FALSE; if (mode == CoordModePrevious) { @@ -148,29 +303,30 @@ xglFillLine (DrawablePtr pDrawable, if (coincident_endpoints) npt--; - GEOMETRY_INIT (pGC->pScreen, &geometry, npt << 1); - GEOMETRY_ADD_LINE (pGC->pScreen, &geometry, + pGeometry = xglGetScratchVertexGeometry (pGC->pScreen, npt); + + GEOMETRY_ADD_LINE (pGC->pScreen, pGeometry, coincident_endpoints, mode, npt, ppt); if (coincident_endpoints) - GEOMETRY_SET_PRIMITIVE (pGC->pScreen, &geometry, - GLITZ_GEOMETRY_PRIMITIVE_LINE_LOOP); + GEOMETRY_SET_VERTEX_PRIMITIVE (pGeometry, GLITZ_PRIMITIVE_LINE_LOOP); else - GEOMETRY_SET_PRIMITIVE (pGC->pScreen, &geometry, - GLITZ_GEOMETRY_PRIMITIVE_LINE_STRIP); + GEOMETRY_SET_VERTEX_PRIMITIVE (pGeometry, GLITZ_PRIMITIVE_LINE_STRIP); /* Lines need a 0.5 translate */ - GEOMETRY_TRANSLATE_FIXED (&geometry, 1 << 15, 1 << 15); + GEOMETRY_TRANSLATE_FIXED (pGeometry, 1 << 15, 1 << 15); - GEOMETRY_TRANSLATE (&geometry, pDrawable->x, pDrawable->y); + GEOMETRY_TRANSLATE (pGeometry, pDrawable->x, pDrawable->y); + + pExtent = REGION_EXTENTS (pDrawable->pScreen, pGC->pCompositeClip); - if (xglFill (pDrawable, pGC, &geometry)) - { - GEOMETRY_UNINIT (&geometry); + if (xglFill (pDrawable, pGC, pGeometry, + pExtent->x1, pExtent->y1, + pExtent->x2 - pExtent->x1, pExtent->y2 - pExtent->y1, + REGION_RECTS (pGC->pCompositeClip), + REGION_NUM_RECTS (pGC->pCompositeClip))) return TRUE; - } - GEOMETRY_UNINIT (&geometry); return FALSE; } @@ -180,19 +336,65 @@ xglFillSegment (DrawablePtr pDrawable, int nsegInit, xSegment *pSegInit) { - xglGeometryRec geometry; + BoxPtr pExtent; + xglGeometryPtr pGeometry; - GEOMETRY_INIT (pGC->pScreen, &geometry, nsegInit << 2); - GEOMETRY_ADD_SEGMENT (pGC->pScreen, &geometry, nsegInit, pSegInit); + pExtent = REGION_EXTENTS (pDrawable->pScreen, pGC->pCompositeClip); + + pGeometry = xglGetScratchVertexGeometry (pGC->pScreen, 2 * nsegInit); + + GEOMETRY_ADD_SEGMENT (pGC->pScreen, pGeometry, nsegInit, pSegInit); /* Line segments need 0.5 translate */ - GEOMETRY_TRANSLATE_FIXED (&geometry, 1 << 15, 1 << 15); - GEOMETRY_SET_PRIMITIVE (pGC->pScreen, &geometry, - GLITZ_GEOMETRY_PRIMITIVE_LINES); + GEOMETRY_TRANSLATE_FIXED (pGeometry, 1 << 15, 1 << 15); + GEOMETRY_SET_VERTEX_PRIMITIVE (pGeometry, GLITZ_PRIMITIVE_LINES); - GEOMETRY_TRANSLATE (&geometry, pDrawable->x, pDrawable->y); + GEOMETRY_TRANSLATE (pGeometry, pDrawable->x, pDrawable->y); - if (xglFill (pDrawable, pGC, &geometry)) + if (xglFill (pDrawable, pGC, pGeometry, + pExtent->x1, pExtent->y1, + pExtent->x2 - pExtent->x1, pExtent->y2 - pExtent->y1, + REGION_RECTS (pGC->pCompositeClip), + REGION_NUM_RECTS (pGC->pCompositeClip))) + return TRUE; + + return FALSE; +} + +Bool +xglFillGlyph (DrawablePtr pDrawable, + GCPtr pGC, + int x, + int y, + unsigned int nGlyph, + CharInfoPtr *ppci, + pointer pglyphBase) +{ + BoxPtr pExtent; + xglGeometryRec geometry; + + pExtent = REGION_EXTENTS (pDrawable->pScreen, pGC->pCompositeClip); + + x += pDrawable->x; + y += pDrawable->y; + + GEOMETRY_INIT (pDrawable->pScreen, &geometry, + GLITZ_GEOMETRY_TYPE_BITMAP, + GEOMETRY_USAGE_SYSMEM, 0); + + GEOMETRY_FOR_GLYPH (pDrawable->pScreen, + &geometry, + nGlyph, + ppci, + pglyphBase); + + GEOMETRY_TRANSLATE (&geometry, x, y); + + if (xglFill (pDrawable, pGC, &geometry, + pExtent->x1, pExtent->y1, + pExtent->x2 - pExtent->x1, pExtent->y2 - pExtent->y1, + REGION_RECTS (pGC->pCompositeClip), + REGION_NUM_RECTS (pGC->pCompositeClip))) { GEOMETRY_UNINIT (&geometry); return TRUE; diff --git a/hw/xgl/xglgc.c b/hw/xgl/xglgc.c index 971edb43b..bfe6cdaa2 100644 --- a/hw/xgl/xglgc.c +++ b/hw/xgl/xglgc.c @@ -5,7 +5,7 @@ * 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 names of + * appear in supporting documentation, and that the name of * David Reveman not be used in advertising or publicity pertaining to * distribution of the software without specific, written prior permission. * David Reveman makes no representations about the suitability of this @@ -20,7 +20,7 @@ * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * - * Author: David Reveman <davidr@freedesktop.org> + * Author: David Reveman <davidr@novell.com> */ #include "xgl.h" @@ -36,7 +36,7 @@ #define XGL_GC_OP_FALLBACK_EPILOGUE(pDrawable) \ XGL_GC_WRAP (funcs, (GCFuncs *) &xglGCFuncs); \ XGL_GC_WRAP (ops, (GCOps *) &xglGCOps); \ - xglAddSurfaceDamage (pDrawable) + xglAddCurrentSurfaceDamage (pDrawable) #define XGL_GC_FILL_OP_FALLBACK_PROLOGUE(pDrawable) \ switch (pGC->fillStyle) { \ @@ -104,7 +104,7 @@ xglFillSpans (DrawablePtr pDrawable, { if (xglFillSpan (pDrawable, pGC, nspans, ppt, pwidth)) { - xglAddBitDamage (pDrawable); + xglAddCurrentBitDamage (pDrawable); return; } } @@ -144,38 +144,45 @@ xglPutImage (DrawablePtr pDrawable, { XGL_GC_PRIV (pGC); - switch (format) { - case XYBitmap: - break; - case XYPixmap: - case ZPixmap: - if (!pGCPriv->flags) - { - XGL_DRAWABLE_PIXMAP_PRIV (pDrawable); + if (pGC->alu != GXcopy || (pGCPriv->flags & xglGCPlaneMaskFlag)) + { + XGL_GC_OP_FALLBACK_PROLOGUE (pDrawable); + (*pGC->ops->PutImage) (pDrawable, pGC, depth, + x, y, w, h, leftPad, format, bits); + XGL_GC_OP_FALLBACK_EPILOGUE (pDrawable); + } + else + { + RegionPtr pClip = pGC->pCompositeClip; + RegionRec region; + BoxRec box; - if (!pPixmapPriv->allBits && - pPixmapPriv->target == xglPixmapTargetIn) - { - if (xglSetPixels (pDrawable, - bits, - PixmapBytePad (w, pDrawable->depth), - x + pDrawable->x, y + pDrawable->y, - w, h, - REGION_RECTS (pGC->pCompositeClip), - REGION_NUM_RECTS (pGC->pCompositeClip))) - { - xglAddBitDamage (pDrawable); - return; - } - } - } - break; + XGL_DRAWABLE_PIXMAP (pDrawable); + + if (!xglMapPixmapBits (pPixmap)) + FatalError (XGL_SW_FAILURE_STRING); + + XGL_GC_UNWRAP (funcs); + XGL_GC_UNWRAP (ops); + + (*pGC->ops->PutImage) (pDrawable, pGC, depth, + x, y, w, h, leftPad, format, bits); + + XGL_GC_WRAP (funcs, (GCFuncs *) &xglGCFuncs); + XGL_GC_WRAP (ops, (GCOps *) &xglGCOps); + + box.x1 = pDrawable->x + x; + box.y1 = pDrawable->y + y; + box.x2 = box.x1 + w; + box.y2 = box.y1 + h; + + REGION_INIT (pDrawable->pScreen, ®ion, &box, 1); + REGION_INTERSECT (pDrawable->pScreen, ®ion, pClip, ®ion); + + xglAddSurfaceDamage (pDrawable, ®ion); + + REGION_UNINIT (pDrawable->pScreen, ®ion); } - - XGL_GC_OP_FALLBACK_PROLOGUE (pDrawable); - (*pGC->ops->PutImage) (pDrawable, pGC, depth, - x, y, w, h, leftPad, format, bits); - XGL_GC_OP_FALLBACK_EPILOGUE (pDrawable); } RegionPtr @@ -195,45 +202,37 @@ xglCopyArea (DrawablePtr pSrc, XGL_GC_PRIV (pGC); + box.x1 = pSrc->x + srcX; + box.y1 = pSrc->y + srcY; + box.x2 = box.x1 + w; + box.y2 = box.y1 + h; + flags = pGCPriv->flags; if (XGL_GET_DRAWABLE_PIXMAP_PRIV (pSrc)->target == xglPixmapTargetIn) flags &= ~xglGCReadOnlyDrawableFlag; - - if (!flags) + + if (flags) { - Bool ret; - - ret = TRUE; + if (!xglSyncBits (pSrc, &box)) + FatalError (XGL_SW_FAILURE_STRING); + + XGL_GC_OP_FALLBACK_PROLOGUE (pDst); + pRegion = (*pGC->ops->CopyArea) (pSrc, pDst, pGC, + srcX, srcY, w, h, dstX, dstY); + XGL_GC_OP_FALLBACK_EPILOGUE (pDst); + } + else + { + /* xglCopyProc handles fall-back */ pRegion = fbDoCopy (pSrc, pDst, pGC, srcX, srcY, w, h, dstX, dstY, xglCopyProc, 0, - (void *) &ret); - if (ret) - { - xglAddBitDamage (pDst); - return pRegion; - } - - if (pRegion) - REGION_DESTROY (pDst->pScreen, pRegion); + (void *) &box); } - box.x1 = pSrc->x + srcX; - box.y1 = pSrc->y + srcY; - box.x2 = box.x1 + w; - box.y2 = box.y1 + h; - - if (!xglSyncBits (pSrc, &box)) - FatalError (XGL_SW_FAILURE_STRING); - - XGL_GC_OP_FALLBACK_PROLOGUE (pDst); - pRegion = (*pGC->ops->CopyArea) (pSrc, pDst, pGC, - srcX, srcY, w, h, dstX, dstY); - XGL_GC_OP_FALLBACK_EPILOGUE (pDst); - return pRegion; } @@ -302,13 +301,13 @@ xglPolylines (DrawablePtr pDrawable, { if (xglFillLine (pDrawable, pGC, mode, npt, ppt)) { - xglAddBitDamage (pDrawable); + xglAddCurrentBitDamage (pDrawable); return; } } } - XGL_GC_OP_FALLBACK_PROLOGUE (pDrawable); + XGL_GC_FILL_OP_FALLBACK_PROLOGUE (pDrawable); (*pGC->ops->Polylines) (pDrawable, pGC, mode, npt, ppt); XGL_GC_OP_FALLBACK_EPILOGUE (pDrawable); } @@ -337,13 +336,13 @@ xglPolySegment (DrawablePtr pDrawable, { if (xglFillSegment (pDrawable, pGC, nsegInit, pSegInit)) { - xglAddBitDamage (pDrawable); + xglAddCurrentBitDamage (pDrawable); return; } } } - XGL_GC_OP_FALLBACK_PROLOGUE (pDrawable); + XGL_GC_FILL_OP_FALLBACK_PROLOGUE (pDrawable); (*pGC->ops->PolySegment) (pDrawable, pGC, nsegInit, pSegInit); XGL_GC_OP_FALLBACK_EPILOGUE (pDrawable); } else @@ -360,7 +359,7 @@ xglPolyArc (DrawablePtr pDrawable, { XGL_GC_PRIV (pGC); - XGL_GC_OP_FALLBACK_PROLOGUE (pDrawable); + XGL_GC_FILL_OP_FALLBACK_PROLOGUE (pDrawable); (*pGC->ops->PolyArc) (pDrawable, pGC, narcs, pArcs); XGL_GC_OP_FALLBACK_EPILOGUE (pDrawable); } else @@ -375,18 +374,17 @@ xglPolyFillRect (DrawablePtr pDrawable, { XGL_GC_PRIV (pGC); - if (!pGCPriv->flags) + if (pGCPriv->flags || pGC->fillStyle == FillStippled) { - if (xglFillRect (pDrawable, pGC, nrect, prect)) - { - xglAddBitDamage (pDrawable); - return; - } + XGL_GC_FILL_OP_FALLBACK_PROLOGUE (pDrawable); + (*pGC->ops->PolyFillRect) (pDrawable, pGC, nrect, prect); + XGL_GC_OP_FALLBACK_EPILOGUE (pDrawable); + } + else + { + /* xglFillRect handles fall-back */ + xglFillRect (pDrawable, pGC, nrect, prect); } - - XGL_GC_FILL_OP_FALLBACK_PROLOGUE (pDrawable); - (*pGC->ops->PolyFillRect) (pDrawable, pGC, nrect, prect); - XGL_GC_OP_FALLBACK_EPILOGUE (pDrawable); } void @@ -412,7 +410,22 @@ xglImageGlyphBlt (DrawablePtr pDrawable, pointer pglyphBase) { XGL_GC_PRIV (pGC); - + + if (!(pGCPriv->flags & ~xglGCBadFunctionFlag)) + { + if (xglSolidGlyph (pDrawable, + pGC, + x, + y, + nglyph, + ppci, + pglyphBase)) + { + xglAddCurrentBitDamage (pDrawable); + return; + } + } + XGL_GC_OP_FALLBACK_PROLOGUE (pDrawable); (*pGC->ops->ImageGlyphBlt) (pDrawable, pGC, x, y, nglyph, ppci, pglyphBase); @@ -429,8 +442,23 @@ xglPolyGlyphBlt (DrawablePtr pDrawable, pointer pglyphBase) { XGL_GC_PRIV (pGC); + + if (!pGCPriv->flags) + { + if (xglFillGlyph (pDrawable, + pGC, + x, + y, + nglyph, + ppci, + pglyphBase)) + { + xglAddCurrentBitDamage (pDrawable); + return; + } + } - XGL_GC_OP_FALLBACK_PROLOGUE (pDrawable); + XGL_GC_FILL_OP_FALLBACK_PROLOGUE (pDrawable); (*pGC->ops->PolyGlyphBlt) (pDrawable, pGC, x, y, nglyph, ppci, pglyphBase); XGL_GC_OP_FALLBACK_EPILOGUE (pDrawable); } @@ -486,6 +514,20 @@ xglValidateGC (GCPtr pGC, { XGL_GC_PRIV (pGC); + if (changes & GCTile) + { + if (!pGC->tileIsPixel && + FbEvenTile (pGC->tile.pixmap->drawable.width * + pDrawable->bitsPerPixel)) + xglSyncBits (&pGC->tile.pixmap->drawable, NULL); + } + + if (changes & GCStipple) + { + if (pGC->stipple) + xglSyncBits (&pGC->stipple->drawable, NULL); + } + XGL_GC_UNWRAP (funcs); XGL_GC_UNWRAP (ops); (*pGC->funcs->ValidateGC) (pGC, changes, pDrawable); diff --git a/hw/xgl/xglgeometry.c b/hw/xgl/xglgeometry.c index 6b2ebd3a7..7c46e31ca 100644 --- a/hw/xgl/xglgeometry.c +++ b/hw/xgl/xglgeometry.c @@ -5,7 +5,7 @@ * 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 names of + * appear in supporting documentation, and that the name of * David Reveman not be used in advertising or publicity pertaining to * distribution of the software without specific, written prior permission. * David Reveman makes no representations about the suitability of this @@ -20,15 +20,14 @@ * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * - * Author: David Reveman <davidr@freedesktop.org> + * Author: David Reveman <davidr@novell.com> */ #include "xgl.h" +#include "fontstruct.h" +#include "dixfontstr.h" -struct xglDataTypeInfo { - glitz_data_type_t type; - int size; -} dataTypes[] = { +xglDataTypeInfoRec xglGeometryDataTypes[2] = { { GLITZ_DATA_TYPE_SHORT, sizeof (glitz_short_t) }, { GLITZ_DATA_TYPE_FLOAT, sizeof (glitz_float_t) } }; @@ -45,19 +44,17 @@ xglGeometryResize (ScreenPtr pScreen, int size) { XGL_SCREEN_PRIV (pScreen); - - if (pGeometry->broken) - return; if (size == pGeometry->size) return; - if (pGeometry->usage == GEOMETRY_USAGE_USERMEM) - { - pGeometry->data = - xrealloc (pGeometry->data, - size * dataTypes[pGeometry->dataType].size); + if (pGeometry->broken) + return; + if (pGeometry->usage == GEOMETRY_USAGE_SYSMEM) + { + pGeometry->data = xrealloc (pGeometry->data, size); + if (pGeometry->buffer) glitz_buffer_destroy (pGeometry->buffer); @@ -81,16 +78,11 @@ xglGeometryResize (ScreenPtr pScreen, else { glitz_buffer_t *newBuffer; - int dataTypeSize; - - dataTypeSize = dataTypes[pGeometry->dataType].size; - if (size) { newBuffer = - glitz_geometry_buffer_create (pScreenPriv->drawable, NULL, - size * dataTypeSize, - usageTypes[pGeometry->usage]); + glitz_vertex_buffer_create (pScreenPriv->drawable, NULL, size, + usageTypes[pGeometry->usage]); if (!newBuffer) { pGeometry->broken = TRUE; @@ -109,8 +101,7 @@ xglGeometryResize (ScreenPtr pScreen, GLITZ_BUFFER_ACCESS_WRITE_ONLY); if (oldData && newData) - memcpy (newData, oldData, - MIN (size, pGeometry->size) * dataTypeSize); + memcpy (newData, oldData, MIN (size, pGeometry->size)); glitz_buffer_unmap (pGeometry->buffer); glitz_buffer_unmap (newBuffer); @@ -126,103 +117,39 @@ xglGeometryResize (ScreenPtr pScreen, pGeometry->endOffset = size; } -/* - * Storage for 100 extra vertices are always allocated if - * buffer size is to small. Geometry should be initialized - * to desired size prior to calling this function when size - * is known. - */ -#define RESIZE_GEOMETRY_FOR_VERTICES(pScreen, pGeometry, nvertices) \ - if (((pGeometry)->size - (pGeometry)->endOffset) < ((nvertices) << 1)) \ +#define MAP_GEOMETRY(pScreen, pGeometry, offset, units, ptr, _size) \ + if ((pGeometry)->broken) \ + return; \ + (_size) = (units) * xglGeometryDataTypes[(pGeometry)->dataType].size; \ + if (((pGeometry)->size - (offset)) < (_size)) \ + { \ + xglGeometryResize (pScreen, pGeometry, \ + (pGeometry)->endOffset + (_size) + 500); \ + if ((pGeometry)->broken) \ + return; \ + } \ + (ptr) = glitz_buffer_map ((pGeometry)->buffer, \ + GLITZ_BUFFER_ACCESS_WRITE_ONLY); \ + if (!(ptr)) \ + { \ + (pGeometry)->broken = TRUE; \ + return; \ + } \ + (ptr) += (offset) + +#define UNMAP_GEOMETRY(pGeometry, offset, _size) \ + if (glitz_buffer_unmap ((pGeometry)->buffer)) \ { \ - xglGeometryResize (pScreen, pGeometry, \ - (pGeometry)->endOffset + \ - ((nvertices) << 1) + 200); \ - if ((pGeometry)->broken) \ - return; \ - } - -/* - * Adds a number of rectangles as GL_QUAD primitives - */ -void -xglGeometryAddRect (ScreenPtr pScreen, - xglGeometryPtr pGeometry, - xRectangle *pRect, - int nRect) -{ - int nvertices; - void *ptr; - - if (pGeometry->broken) - return; - - if (nRect < 1) - return; - - nvertices = nRect << 2; - - RESIZE_GEOMETRY_FOR_VERTICES (pScreen, pGeometry, nvertices); - - ptr = glitz_buffer_map (pGeometry->buffer, GLITZ_BUFFER_ACCESS_WRITE_ONLY); - if (!ptr) - { - pGeometry->broken = TRUE; - return; - } - - switch (pGeometry->dataType) { - case GEOMETRY_DATA_TYPE_SHORT: - { - glitz_short_t *data = (glitz_short_t *) ptr; - - data += pGeometry->endOffset; - - while (nRect--) - { - *data++ = pRect->x; - *data++ = pRect->y; - *data++ = pRect->x + pRect->width; - *data++ = pRect->y; - *data++ = pRect->x + pRect->width; - *data++ = pRect->y + pRect->height; - *data++ = pRect->x; - *data++ = pRect->y + pRect->height; - - pRect++; - } - } break; - case GEOMETRY_DATA_TYPE_FLOAT: - { - glitz_float_t *data = (glitz_float_t *) ptr; - - data += pGeometry->endOffset; - - while (nRect--) - { - *data++ = (glitz_float_t) pRect->x; - *data++ = (glitz_float_t) pRect->y; - *data++ = (glitz_float_t) pRect->x + pRect->width; - *data++ = (glitz_float_t) pRect->y; - *data++ = (glitz_float_t) pRect->x + pRect->width; - *data++ = (glitz_float_t) pRect->y + pRect->height; - *data++ = (glitz_float_t) pRect->x; - *data++ = (glitz_float_t) pRect->y + pRect->height; - - pRect++; - } - } break; + (pGeometry)->broken = TRUE; \ + return; \ + } \ + if (((offset) + (_size)) > (pGeometry)->endOffset) \ + { \ + (pGeometry)->endOffset = (offset) + (_size); \ + (pGeometry)->count = (pGeometry)->endOffset / \ + (2 * xglGeometryDataTypes[(pGeometry)->dataType].size); \ } - if (glitz_buffer_unmap (pGeometry->buffer)) - { - pGeometry->broken = TRUE; - return; - } - - pGeometry->endOffset += (nvertices << 1); -} - /* * Adds a number of boxes as GL_QUAD primitives */ @@ -230,35 +157,22 @@ void xglGeometryAddBox (ScreenPtr pScreen, xglGeometryPtr pGeometry, BoxPtr pBox, - int nBox) + int nBox, + int offset) { - int nvertices; - void *ptr; - - if (pGeometry->broken) - return; + int size; + char *ptr; if (nBox < 1) return; - nvertices = nBox << 2; - - RESIZE_GEOMETRY_FOR_VERTICES (pScreen, pGeometry, nvertices); - - ptr = glitz_buffer_map (pGeometry->buffer, GLITZ_BUFFER_ACCESS_WRITE_ONLY); - if (!ptr) - { - pGeometry->broken = TRUE; - return; - } - + MAP_GEOMETRY (pScreen, pGeometry, offset, nBox * 8, ptr, size); + switch (pGeometry->dataType) { case GEOMETRY_DATA_TYPE_SHORT: { glitz_short_t *data = (glitz_short_t *) ptr; - data += pGeometry->endOffset; - while (nBox--) { *data++ = (glitz_short_t) pBox->x1; @@ -277,8 +191,6 @@ xglGeometryAddBox (ScreenPtr pScreen, { glitz_float_t *data = (glitz_float_t *) ptr; - data += pGeometry->endOffset; - while (nBox--) { *data++ = (glitz_float_t) pBox->x1; @@ -295,59 +207,38 @@ xglGeometryAddBox (ScreenPtr pScreen, } break; } - if (glitz_buffer_unmap (pGeometry->buffer)) - { - pGeometry->broken = TRUE; - return; - } - - pGeometry->endOffset += (nvertices << 1); + UNMAP_GEOMETRY (pGeometry, offset, size); } /* * Adds a number of spans as GL_LINE primitives - * - * An extra 1 is added to *pwidth as OpenGL line segments are half-opened. */ void xglGeometryAddSpan (ScreenPtr pScreen, xglGeometryPtr pGeometry, DDXPointPtr ppt, int *pwidth, - int n) + int n, + int offset) { - int nvertices; - void *ptr; - - if (pGeometry->broken) - return; + int size; + char *ptr; if (n < 1) return; - nvertices = n << 1; - - RESIZE_GEOMETRY_FOR_VERTICES (pScreen, pGeometry, nvertices); - - ptr = glitz_buffer_map (pGeometry->buffer, GLITZ_BUFFER_ACCESS_WRITE_ONLY); - if (!ptr) - { - pGeometry->broken = TRUE; - return; - } + MAP_GEOMETRY (pScreen, pGeometry, offset, n * 4, ptr, size); switch (pGeometry->dataType) { case GEOMETRY_DATA_TYPE_SHORT: { glitz_short_t *data = (glitz_short_t *) ptr; - data += pGeometry->endOffset; - while (n--) { *data++ = (glitz_short_t) ppt->x; *data++ = (glitz_short_t) ppt->y; - *data++ = (glitz_short_t) (ppt->x + *pwidth + 1); + *data++ = (glitz_short_t) (ppt->x + *pwidth); *data++ = (glitz_short_t) ppt->y; ppt++; @@ -358,13 +249,11 @@ xglGeometryAddSpan (ScreenPtr pScreen, { glitz_float_t *data = (glitz_float_t *) ptr; - data += pGeometry->endOffset; - while (n--) { *data++ = (glitz_float_t) ppt->x; *data++ = (glitz_float_t) ppt->y; - *data++ = (glitz_float_t) (ppt->x + *pwidth + 1); + *data++ = (glitz_float_t) (ppt->x + *pwidth); *data++ = (glitz_float_t) ppt->y; ppt++; @@ -372,14 +261,8 @@ xglGeometryAddSpan (ScreenPtr pScreen, } } break; } - - if (glitz_buffer_unmap (pGeometry->buffer)) - { - pGeometry->broken = TRUE; - return; - } - - pGeometry->endOffset += (nvertices << 1); + + UNMAP_GEOMETRY (pGeometry, offset, size); } /* @@ -401,28 +284,17 @@ xglGeometryAddLine (ScreenPtr pScreen, int loop, int mode, int npt, - DDXPointPtr ppt) + DDXPointPtr ppt, + int offset) { DDXPointRec pt; - int nvertices; - void *ptr; - - if (pGeometry->broken) - return; + int size; + char *ptr; if (npt < 2) return; - nvertices = npt; - - RESIZE_GEOMETRY_FOR_VERTICES (pScreen, pGeometry, nvertices); - - ptr = glitz_buffer_map (pGeometry->buffer, GLITZ_BUFFER_ACCESS_WRITE_ONLY); - if (!ptr) - { - pGeometry->broken = TRUE; - return; - } + MAP_GEOMETRY (pScreen, pGeometry, offset, npt * 2, ptr, size); pt.x = 0; pt.y = 0; @@ -432,8 +304,6 @@ xglGeometryAddLine (ScreenPtr pScreen, { glitz_short_t *data = (glitz_short_t *) ptr; - data += pGeometry->endOffset; - while (npt--) { if (mode == CoordModePrevious) @@ -447,19 +317,17 @@ xglGeometryAddLine (ScreenPtr pScreen, pt.y = ppt->y; } - *data++ = pt.x; - *data++ = pt.y; - if (npt || loop) { - *data++ = pt.x; - *data++ = pt.y; + *data++ = (glitz_short_t) pt.x; + *data++ = (glitz_short_t) pt.y; } else { ppt--; - *data++ = ADJUST_END_POINT (ppt->x, pt.x, ppt->y == pt.y); - *data++ = ADJUST_END_POINT (ppt->y, pt.y, 0); + *data++ = (glitz_short_t) + ADJUST_END_POINT (ppt->x, pt.x, ppt->y == pt.y); + *data++ = (glitz_short_t) ADJUST_END_POINT (ppt->y, pt.y, 0); } ppt++; @@ -469,8 +337,6 @@ xglGeometryAddLine (ScreenPtr pScreen, { glitz_float_t *data = (glitz_float_t *) ptr; - data += pGeometry->endOffset; - while (npt--) { if (mode == CoordModePrevious) @@ -501,14 +367,8 @@ xglGeometryAddLine (ScreenPtr pScreen, } } break; } - - if (glitz_buffer_unmap (pGeometry->buffer)) - { - pGeometry->broken = TRUE; - return; - } - pGeometry->endOffset += (nvertices << 1); + UNMAP_GEOMETRY (pGeometry, offset, size); } /* @@ -518,42 +378,31 @@ void xglGeometryAddSegment (ScreenPtr pScreen, xglGeometryPtr pGeometry, int nsegInit, - xSegment *pSegInit) + xSegment *pSegInit, + int offset) { - int nvertices; - void *ptr; - - if (pGeometry->broken) - return; + int size; + char *ptr; if (nsegInit < 1) return; - nvertices = nsegInit << 1; - - RESIZE_GEOMETRY_FOR_VERTICES (pScreen, pGeometry, nvertices); - - ptr = glitz_buffer_map (pGeometry->buffer, GLITZ_BUFFER_ACCESS_WRITE_ONLY); - if (!ptr) - { - pGeometry->broken = TRUE; - return; - } + MAP_GEOMETRY (pScreen, pGeometry, offset, nsegInit * 4, ptr, size); switch (pGeometry->dataType) { case GEOMETRY_DATA_TYPE_SHORT: { glitz_short_t *data = (glitz_short_t *) ptr; - data += pGeometry->endOffset; - while (nsegInit--) { - *data++ = pSegInit->x1; - *data++ = pSegInit->y1; - *data++ = ADJUST_END_POINT (pSegInit->x1, pSegInit->x2, - pSegInit->y1 == pSegInit->y2); - *data++ = ADJUST_END_POINT (pSegInit->y1, pSegInit->y2, 0); + *data++ = (glitz_short_t) pSegInit->x1; + *data++ = (glitz_short_t) pSegInit->y1; + *data++ = (glitz_short_t) + ADJUST_END_POINT (pSegInit->x1, pSegInit->x2, + pSegInit->y1 == pSegInit->y2); + *data++ = (glitz_short_t) + ADJUST_END_POINT (pSegInit->y1, pSegInit->y2, 0); pSegInit++; } @@ -562,8 +411,6 @@ xglGeometryAddSegment (ScreenPtr pScreen, { glitz_float_t *data = (glitz_float_t *) ptr; - data += pGeometry->endOffset; - while (nsegInit--) { *data++ = (glitz_float_t) pSegInit->x1; @@ -578,38 +425,299 @@ xglGeometryAddSegment (ScreenPtr pScreen, } } break; } - - if (glitz_buffer_unmap (pGeometry->buffer)) + + UNMAP_GEOMETRY (pGeometry, offset, size); +} + +void +xglGeometryForGlyph (ScreenPtr pScreen, + xglGeometryPtr pGeometry, + unsigned int nGlyph, + CharInfoPtr *ppciInit, + pointer pglyphBase) +{ + CharInfoPtr *ppci; + CharInfoPtr pci; + unsigned char *glyphbase = (pointer) ~0; + unsigned char *pglyph; + int x = 0; + int gx, gy; + int gWidth, gHeight; + int n, lastX = 0, lastY = 0; + glitz_multi_array_t *array; + glitz_buffer_t *buffer; + + ppci = ppciInit; + n = nGlyph; + + while (n--) + { + pglyph = FONTGLYPHBITS (pglyphBase, *ppci++); + if (pglyph < glyphbase) + glyphbase = pglyph; + } + + buffer = glitz_buffer_create_for_data (glyphbase); + if (!buffer) + { + pGeometry->broken = TRUE; + return; + } + + GEOMETRY_SET_BUFFER (pGeometry, buffer); + + array = glitz_multi_array_create (nGlyph); + if (!array) + { + pGeometry->broken = TRUE; + return; + } + + GEOMETRY_SET_MULTI_ARRAY (pGeometry, array); + + ppci = ppciInit; + while (nGlyph--) { + pci = *ppci++; + pglyph = FONTGLYPHBITS (pglyphBase, pci); + gWidth = GLYPHWIDTHPIXELS (pci); + gHeight = GLYPHHEIGHTPIXELS (pci); + + if (gWidth && gHeight) + { + gx = x + pci->metrics.leftSideBearing; + gy = -pci->metrics.ascent; + + glitz_multi_array_add (array, + (pglyph - glyphbase) * 8, + gWidth, gHeight, + (gx - lastX) << 16, (gy - lastY) << 16); + lastX = gx; + lastY = gy; + } + x += pci->metrics.characterWidth; + } + + glitz_buffer_destroy (buffer); + glitz_multi_array_destroy (array); +} + +#define FIXED_LINE_X_TO_FLOAT(line, v) \ + (((glitz_float_t) \ + ((line).p1.x + (xFixed_16_16) \ + (((xFixed_32_32) ((v) - (line).p1.y) * \ + ((line).p2.x - (line).p1.x)) / \ + ((line).p2.y - (line).p1.y)))) / 65536) + +#define FIXED_LINE_X_CEIL_TO_FLOAT(line, v) \ + (((glitz_float_t) \ + ((line).p1.x + (xFixed_16_16) \ + (((((line).p2.y - (line).p1.y) - 1) + \ + ((xFixed_32_32) ((v) - (line).p1.y) * \ + ((line).p2.x - (line).p1.x))) / \ + ((line).p2.y - (line).p1.y)))) / 65536) + +/* + * Adds a number of trapezoids as GL_QUAD primitives + */ +void +xglGeometryAddTrapezoid (ScreenPtr pScreen, + xglGeometryPtr pGeometry, + xTrapezoid *pTrap, + int nTrap, + int offset) +{ + int size; + char *ptr; + + if (nTrap < 1) + return; + + MAP_GEOMETRY (pScreen, pGeometry, offset, nTrap * 8, ptr, size); + + switch (pGeometry->dataType) { + case GEOMETRY_DATA_TYPE_SHORT: + /* not supported */ pGeometry->broken = TRUE; + break; + case GEOMETRY_DATA_TYPE_FLOAT: + { + glitz_float_t *data = (glitz_float_t *) ptr; + glitz_float_t top, bottom; + + while (nTrap--) + { + top = FIXED_TO_FLOAT (pTrap->top); + bottom = FIXED_TO_FLOAT (pTrap->bottom); + + *data++ = FIXED_LINE_X_TO_FLOAT (pTrap->left, pTrap->top); + *data++ = top; + *data++ = FIXED_LINE_X_CEIL_TO_FLOAT (pTrap->right, pTrap->top); + *data++ = top; + *data++ = FIXED_LINE_X_CEIL_TO_FLOAT (pTrap->right, pTrap->bottom); + *data++ = bottom; + *data++ = FIXED_LINE_X_TO_FLOAT (pTrap->left, pTrap->bottom); + *data++ = bottom; + + pTrap++; + } + } break; + } + + UNMAP_GEOMETRY (pGeometry, offset, size); +} + +/* + * Adds a number of traps as GL_QUAD primitives + */ +void +xglGeometryAddTrap (ScreenPtr pScreen, + xglGeometryPtr pGeometry, + xTrap *pTrap, + int nTrap, + int offset) +{ + int size; + char *ptr; + + if (nTrap < 1) return; + + MAP_GEOMETRY (pScreen, pGeometry, offset, nTrap * 8, ptr, size); + + switch (pGeometry->dataType) { + case GEOMETRY_DATA_TYPE_SHORT: + /* not supported */ + pGeometry->broken = TRUE; + break; + case GEOMETRY_DATA_TYPE_FLOAT: + { + glitz_float_t *data = (glitz_float_t *) ptr; + glitz_float_t top, bottom; + + while (nTrap--) + { + top = FIXED_TO_FLOAT (pTrap->top.y); + bottom = FIXED_TO_FLOAT (pTrap->bot.y); + + *data++ = FIXED_TO_FLOAT (pTrap->top.l); + *data++ = top; + *data++ = FIXED_TO_FLOAT (pTrap->top.r); + *data++ = top; + *data++ = FIXED_TO_FLOAT (pTrap->bot.r); + *data++ = bottom; + *data++ = FIXED_TO_FLOAT (pTrap->bot.l); + *data++ = bottom; + + pTrap++; + } + } break; + } + + UNMAP_GEOMETRY (pGeometry, offset, size); +} + +/* XXX: scratch geometry size never shrinks, it just gets larger when + required. this is not acceptable. */ +xglGeometryPtr +xglGetScratchGeometryWithSize (ScreenPtr pScreen, + int size) +{ + xglGeometryPtr pGeometry; + + XGL_SCREEN_PRIV (pScreen); + + pGeometry = &pScreenPriv->scratchGeometry; + + if (pGeometry->broken || pGeometry->size < size) + { + GEOMETRY_UNINIT (pGeometry); + GEOMETRY_INIT (pScreen, pGeometry, pGeometry->type, + pScreenPriv->geometryUsage, size); + } + else + { + if (pGeometry->array) + { + glitz_multi_array_destroy (pGeometry->array); + pGeometry->array = NULL; + } + pGeometry->endOffset = 0; + pGeometry->xOff = 0; + pGeometry->yOff = 0; + pGeometry->first = 0; + pGeometry->count = 0; + pGeometry->width = 2; } + + return pGeometry; +} + +xglGeometryPtr +xglGetScratchVertexGeometryWithType (ScreenPtr pScreen, + int type, + int count) +{ + xglGeometryPtr pGeometry; + int stride; - pGeometry->endOffset += (nvertices << 1); + stride = 2 * xglGeometryDataTypes[type].size; + + pGeometry = xglGetScratchGeometryWithSize (pScreen, count * stride); + + pGeometry->type = GLITZ_GEOMETRY_TYPE_VERTEX; + pGeometry->dataType = type; + + pGeometry->f.vertex.primitive = GLITZ_PRIMITIVE_QUADS; + pGeometry->f.vertex.type = xglGeometryDataTypes[type].type; + pGeometry->f.vertex.bytes_per_vertex = stride; + pGeometry->f.vertex.attributes = 0; + + return pGeometry; +} + +xglGeometryPtr +xglGetScratchVertexGeometry (ScreenPtr pScreen, + int count) +{ + xglGeometryPtr pGeometry; + int type, stride; + + XGL_SCREEN_PRIV (pScreen); + + type = pScreenPriv->geometryDataType; + stride = 2 * xglGeometryDataTypes[type].size; + + pGeometry = xglGetScratchGeometryWithSize (pScreen, count * stride); + + pGeometry->type = GLITZ_GEOMETRY_TYPE_VERTEX; + pGeometry->dataType = type; + + pGeometry->f.vertex.primitive = GLITZ_PRIMITIVE_QUADS; + pGeometry->f.vertex.type = xglGeometryDataTypes[type].type; + pGeometry->f.vertex.bytes_per_vertex = stride; + pGeometry->f.vertex.attributes = 0; + + return pGeometry; } Bool xglSetGeometry (xglGeometryPtr pGeometry, - glitz_surface_t *surface, - int first, - int count) + glitz_surface_t *surface) { - glitz_geometry_format_t format; - if (pGeometry->broken) return FALSE; - format.first = first; - format.count = count; - format.primitive = pGeometry->primitive; - format.type = dataTypes[pGeometry->dataType].type; - format.mode = GLITZ_GEOMETRY_MODE_DIRECT; - format.edge_hint = GLITZ_GEOMETRY_EDGE_HINT_SHARP; - - glitz_set_geometry (surface, - pGeometry->xOff, pGeometry->yOff, - &format, + glitz_set_geometry (surface, pGeometry->type, &pGeometry->f, pGeometry->buffer); + if (pGeometry->array) + glitz_set_multi_array (surface, pGeometry->array, + pGeometry->xOff, pGeometry->yOff); + else + glitz_set_array (surface, + pGeometry->first, pGeometry->width, pGeometry->count, + pGeometry->xOff, pGeometry->yOff); + return TRUE; } diff --git a/hw/xgl/xglget.c b/hw/xgl/xglget.c index c13be9f30..70f29e2e5 100644 --- a/hw/xgl/xglget.c +++ b/hw/xgl/xglget.c @@ -5,7 +5,7 @@ * 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 names of + * appear in supporting documentation, and that the name of * David Reveman not be used in advertising or publicity pertaining to * distribution of the software without specific, written prior permission. * David Reveman makes no representations about the suitability of this @@ -20,7 +20,7 @@ * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * - * Author: David Reveman <davidr@freedesktop.org> + * Author: David Reveman <davidr@novell.com> */ #include "xgl.h" @@ -35,8 +35,10 @@ xglGetImage (DrawablePtr pDrawable, unsigned long planeMask, char *d) { - ScreenPtr pScreen = pDrawable->pScreen; - BoxRec box; + ScreenPtr pScreen = pDrawable->pScreen; + glitz_surface_t *surface; + int xOff, yOff; + BoxRec box; XGL_SCREEN_PRIV (pScreen); @@ -44,11 +46,13 @@ xglGetImage (DrawablePtr pDrawable, if (pDrawable->type == DRAWABLE_WINDOW) { glitz_surface_flush (pScreenPriv->surface); - glitz_drawable_flush (pScreenPriv->drawable); + glitz_drawable_finish (pScreenPriv->drawable); } - box.x1 = x + pDrawable->x; - box.y1 = y + pDrawable->y; + XGL_GET_DRAWABLE (pDrawable, surface, xOff, yOff); + + box.x1 = pDrawable->x + xOff + x; + box.y1 = pDrawable->y + yOff + y; box.x2 = box.x1 + w; box.y2 = box.y1 + h; diff --git a/hw/xgl/xglglyph.c b/hw/xgl/xglglyph.c new file mode 100644 index 000000000..157dfb6af --- /dev/null +++ b/hw/xgl/xglglyph.c @@ -0,0 +1,1080 @@ +/* + * Copyright © 2005 Novell, 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 + * Novell, Inc. not be used in advertising or publicity pertaining to + * distribution of the software without specific, written prior permission. + * Novell, Inc. makes no representations about the suitability of this + * software for any purpose. It is provided "as is" without express or + * implied warranty. + * + * NOVELL, INC. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN + * NO EVENT SHALL NOVELL, INC. BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS + * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, + * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION + * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Author: David Reveman <davidr@novell.com> + */ + +#include "xgl.h" + +#ifdef RENDER +#include "gcstruct.h" +#include "picturestr.h" + +#define BITMAP_CACHE_SIZE 256000 +#define BITMAP_CACHE_MAX_LEVEL ~0 +#define BITMAP_CACHE_MAX_SIZE 512 + +#define TEXTURE_CACHE_SIZE 512 +#define TEXTURE_CACHE_MAX_LEVEL 64 +#define TEXTURE_CACHE_MAX_HEIGHT 72 +#define TEXTURE_CACHE_MAX_WIDTH 72 + +#define NEXT_GLYPH_SERIAL_NUMBER ((++glyphSerialNumber) > MAX_SERIAL_NUM ? \ + (glyphSerialNumber = 1): glyphSerialNumber) + +#define GLYPH_GET_AREA_PRIV(pArea) \ + ((xglGlyphAreaPtr) (pArea)->devPrivate.ptr) + +#define GLYPH_AREA_PRIV(pArea) \ + xglGlyphAreaPtr pAreaPriv = GLYPH_GET_AREA_PRIV (pArea) + +#define NEEDS_COMPONENT(f) (PICT_FORMAT_A (f) != 0 && PICT_FORMAT_RGB (f) != 0) + +#define WRITE_VEC2(ptr, _x, _y) \ + *(ptr)++ = (_x); \ + *(ptr)++ = (_y) + +#define WRITE_BOX(ptr, _vx1, _vy1, _vx2, _vy2, box) \ + WRITE_VEC2 (ptr, _vx1, _vy1); \ + WRITE_VEC2 (ptr, (box).x1, (box).y2); \ + WRITE_VEC2 (ptr, _vx2, _vy1); \ + WRITE_VEC2 (ptr, (box).x2, (box).y2); \ + WRITE_VEC2 (ptr, _vx2, _vy2); \ + WRITE_VEC2 (ptr, (box).x2, (box).y1); \ + WRITE_VEC2 (ptr, _vx1, _vy2); \ + WRITE_VEC2 (ptr, (box).x1, (box).y1) + +typedef union _xglGlyphList { + glitz_short_t *s; + glitz_float_t *f; +} xglGlyphListRec, *xglGlyphListPtr; + +typedef struct _xglGlyphArray { + int lastX, lastY; +} xglGlyphArrayRec, *xglGlyphArrayPtr; + +typedef union _xglGlyphVertexData { + xglGlyphArrayRec array; + xglGlyphListRec list; +} xglGlyphVertexDataRec, *xglGlyphVertexDataPtr; + +typedef struct _xglGlyphOp { + GlyphListPtr pLists; + int listLen; + GlyphPtr *ppGlyphs; + int nGlyphs; + int xOff; + int yOff; + Bool noCache; +} xglGlyphOpRec, *xglGlyphOpPtr; + +unsigned long glyphSerialNumber = 0; + +xglAreaRec zeroSizeArea = { + 0, 0, + 0, 0, + 0, 0, + { NULL, NULL, NULL, NULL }, NULL, + (pointer) 0, + { 0 } +}; + +static Bool +xglGlyphCreate (xglAreaPtr pArea) +{ + return TRUE; +} + +static Bool +xglGlyphMoveIn (xglAreaPtr pArea, + pointer closure) +{ + xglGlyphCachePtr pCache = (xglGlyphCachePtr) pArea->pRoot->closure; + GlyphPtr pGlyph = (GlyphPtr) closure; + + XGL_GLYPH_PRIV (pCache->pScreen, pGlyph); + + pGlyphPriv->pArea = pArea; + + return TRUE; +} + +static void +xglGlyphMoveOut (xglAreaPtr pArea, + pointer closure) +{ + xglGlyphCachePtr pCache = (xglGlyphCachePtr) pArea->pRoot->closure; + GlyphPtr pGlyph = (GlyphPtr) closure; + + XGL_GLYPH_PRIV (pCache->pScreen, pGlyph); + + pGlyphPriv->pArea = NULL; +} + +static int +xglGlyphCompareScore (xglAreaPtr pArea, + pointer closure1, + pointer closure2) +{ + xglGlyphCachePtr pCache = (xglGlyphCachePtr) pArea->pRoot->closure; + GlyphPtr pGlyph = (GlyphPtr) closure2; + + XGL_GLYPH_PRIV (pCache->pScreen, pGlyph); + GLYPH_AREA_PRIV (pGlyphPriv->pArea); + + if (pAreaPriv->serial != glyphSerialNumber) + return 1; + + return -1; +} + +static const xglAreaFuncsRec xglGlyphAreaFuncs = { + xglGlyphCreate, + xglGlyphMoveIn, + xglGlyphMoveOut, + xglGlyphCompareScore +}; + +Bool +xglRealizeGlyph (ScreenPtr pScreen, + GlyphPtr pGlyph) +{ + PictureScreenPtr pPictureScreen = GetPictureScreen (pScreen); + Bool ret; + + XGL_SCREEN_PRIV (pScreen); + XGL_GLYPH_PRIV (pScreen, pGlyph); + + XGL_PICTURE_SCREEN_UNWRAP (RealizeGlyph); + ret = (*pPictureScreen->RealizeGlyph) (pScreen, pGlyph); + XGL_PICTURE_SCREEN_WRAP (RealizeGlyph, xglRealizeGlyph); + + pGlyphPriv->pArea = NULL; + + return ret; +} + +void +xglUnrealizeGlyph (ScreenPtr pScreen, + GlyphPtr pGlyph) +{ + PictureScreenPtr pPictureScreen = GetPictureScreen (pScreen); + + XGL_SCREEN_PRIV (pScreen); + XGL_GLYPH_PRIV (pScreen, pGlyph); + + XGL_PICTURE_SCREEN_UNWRAP (UnrealizeGlyph); + (*pPictureScreen->UnrealizeGlyph) (pScreen, pGlyph); + XGL_PICTURE_SCREEN_WRAP (UnrealizeGlyph, xglUnrealizeGlyph); + + if (pGlyphPriv->pArea && pGlyphPriv->pArea->width) + xglWithdrawArea (pGlyphPriv->pArea); +} + +Bool +xglInitGlyphCache (xglGlyphCachePtr pCache, + ScreenPtr pScreen, + PictFormatPtr format) +{ + XGL_SCREEN_PRIV (pScreen); + + pCache->depth = format->depth; + + if (!pScreenPriv->pSolidAlpha) + { + xglCreateSolidAlphaPicture (pScreen); + if (!pScreenPriv->pSolidAlpha) + return FALSE; + } + + if (pCache->depth == 1) + { + int stride; + + GEOMETRY_INIT (pScreen, &pCache->u.geometry, + GLITZ_GEOMETRY_TYPE_VERTEX, + GEOMETRY_USAGE_STATIC, BITMAP_CACHE_SIZE); + GEOMETRY_SET_VERTEX_DATA_TYPE (&pCache->u.geometry, + pScreenPriv->geometryDataType); + + stride = pCache->u.geometry.f.vertex.bytes_per_vertex; + if (!xglRootAreaInit (&pCache->rootArea, + BITMAP_CACHE_MAX_LEVEL, + BITMAP_CACHE_SIZE / (stride * 4), + 0, sizeof (xglGlyphAreaRec), + (xglAreaFuncsPtr) &xglGlyphAreaFuncs, + (pointer) pCache)) + { + GEOMETRY_UNINIT (&pCache->u.geometry); + return FALSE; + } + } + else + { + + xglGlyphTexturePtr pTexture = &pCache->u.texture; + glitz_surface_attributes_t attr; + xglPixmapFormatPtr pFormat; + glitz_vertex_format_t *vertex; + + if (!xglRootAreaInit (&pCache->rootArea, + TEXTURE_CACHE_MAX_LEVEL, + TEXTURE_CACHE_SIZE, TEXTURE_CACHE_SIZE, + sizeof (xglGlyphAreaRec), + (xglAreaFuncsPtr) &xglGlyphAreaFuncs, + (pointer) pCache)) + return FALSE; + + pFormat = &pScreenPriv->pixmapFormats[format->depth]; + + if (pScreenPriv->geometryDataType == GEOMETRY_DATA_TYPE_SHORT) + { + attr.unnormalized = 1; + pTexture->mask = + glitz_surface_create (pScreenPriv->drawable, pFormat->format, + TEXTURE_CACHE_SIZE, TEXTURE_CACHE_SIZE, + GLITZ_SURFACE_UNNORMALIZED_MASK, &attr); + } else + pTexture->mask = NULL; + + if (!pTexture->mask) + { + pTexture->mask = + glitz_surface_create (pScreenPriv->drawable, pFormat->format, + TEXTURE_CACHE_SIZE, TEXTURE_CACHE_SIZE, + 0, NULL); + if (!pTexture->mask) + return FALSE; + + pTexture->geometryDataType = GEOMETRY_DATA_TYPE_FLOAT; + } else + pTexture->geometryDataType = GEOMETRY_DATA_TYPE_SHORT; + + if (NEEDS_COMPONENT (format->format)) + glitz_surface_set_component_alpha (pTexture->mask, 1); + + vertex = &pCache->u.texture.format.vertex; + vertex->primitive = GLITZ_PRIMITIVE_QUADS; + vertex->mask.size = GLITZ_COORDINATE_SIZE_XY; + vertex->attributes = GLITZ_VERTEX_ATTRIBUTE_MASK_COORD_MASK; + + if (pTexture->geometryDataType == GEOMETRY_DATA_TYPE_FLOAT) + { + vertex->type = GLITZ_DATA_TYPE_FLOAT; + vertex->bytes_per_vertex = sizeof (glitz_float_t) * 4; + vertex->mask.offset = sizeof (glitz_float_t) * 2; + vertex->mask.type = GLITZ_DATA_TYPE_FLOAT; + } + else + { + vertex->type = GLITZ_DATA_TYPE_SHORT; + vertex->bytes_per_vertex = sizeof (glitz_short_t) * 4; + vertex->mask.offset = sizeof (glitz_short_t) * 2; + vertex->mask.type = GLITZ_DATA_TYPE_SHORT; + } + + pTexture->pixel.masks = pFormat->pPixel->masks; + pTexture->pixel.scanline_order = GLITZ_PIXEL_SCANLINE_ORDER_BOTTOM_UP; + pTexture->pixel.bytes_per_line = 0; + pTexture->pixel.xoffset = 0; + pTexture->pixel.skip_lines = 0; + } + + pCache->pScreen = pScreen; + + return TRUE; +} + +void +xglFiniGlyphCache (xglGlyphCachePtr pCache) +{ + if (pCache->pScreen) + { + xglRootAreaFini (&pCache->rootArea); + + if (pCache->depth == 1) + { + GEOMETRY_UNINIT (&pCache->u.geometry); + } + else + { + if (pCache->u.texture.mask) + glitz_surface_destroy (pCache->u.texture.mask); + } + + pCache->pScreen = NULL; + } +} + +static xglAreaPtr +xglCacheGlyph (xglGlyphCachePtr pCache, + GlyphPtr pGlyph) +{ + ScreenPtr pScreen = pCache->pScreen; + + XGL_GLYPH_PRIV (pScreen, pGlyph); + + if (pCache->depth == 1) + { + PixmapPtr pPixmap; + RegionPtr pRegion; + int nBox; + + pPixmap = GetScratchPixmapHeader (pScreen, + pGlyph->info.width, + pGlyph->info.height, + pCache->depth, pCache->depth, 0, + (pointer) (pGlyph + 1)); + if (!pPixmap) + return NULL; + + (*pScreen->ModifyPixmapHeader) (pPixmap, + pGlyph->info.width, + pGlyph->info.height, + 0, 0, -1, (pointer) (pGlyph + 1)); + + pRegion = (*pScreen->BitmapToRegion) (pPixmap); + FreeScratchPixmapHeader (pPixmap); + + if (!pRegion) + return NULL; + + nBox = REGION_NUM_RECTS (pRegion); + if (nBox > BITMAP_CACHE_MAX_SIZE) + { + REGION_DESTROY (pScreen, pRegion); + return NULL; + } + + if (nBox > 0) + { + /* Find available area */ + if (!xglFindArea (pCache->rootArea.pArea, nBox, 0, + FALSE, (pointer) pGlyph)) + { + /* Kicking out area with lower score */ + xglFindArea (pCache->rootArea.pArea, nBox, 0, + TRUE, (pointer) pGlyph); + } + + if (pGlyphPriv->pArea) + { + int stride; + + GLYPH_AREA_PRIV (pGlyphPriv->pArea); + + pAreaPriv->u.range.first = pGlyphPriv->pArea->x * 4; + pAreaPriv->u.range.count = nBox * 4; + + stride = pCache->u.geometry.f.vertex.bytes_per_vertex; + GEOMETRY_ADD_REGION_AT (pScreen, &pCache->u.geometry, pRegion, + pGlyphPriv->pArea->x * stride * 4); + } + } else + pGlyphPriv->pArea = &zeroSizeArea; + + REGION_DESTROY (pScreen, pRegion); + } + else + { + xglGlyphTexturePtr pTexture = &pCache->u.texture; + + if (pGlyph->info.width > TEXTURE_CACHE_MAX_WIDTH || + pGlyph->info.height > TEXTURE_CACHE_MAX_HEIGHT) + return NULL; + + if (pGlyph->info.width > 0 && pGlyph->info.height > 0) + { + glitz_buffer_t *buffer; + + buffer = glitz_buffer_create_for_data (pGlyph + 1); + if (!buffer) + return NULL; + + /* Find available area */ + if (!xglFindArea (pCache->rootArea.pArea, + pGlyph->info.width, pGlyph->info.height, + FALSE, (pointer) pGlyph)) + { + /* Kicking out area with lower score */ + xglFindArea (pCache->rootArea.pArea, + pGlyph->info.width, pGlyph->info.height, + TRUE, (pointer) pGlyph); + } + + if (pGlyphPriv->pArea) + { + glitz_point_fixed_t p1, p2; + glitz_pixel_format_t pixel; + + GLYPH_AREA_PRIV (pGlyphPriv->pArea); + + pixel = pTexture->pixel; + pixel.bytes_per_line = + PixmapBytePad (pGlyph->info.width, pCache->depth); + + glitz_set_pixels (pTexture->mask, + pGlyphPriv->pArea->x, + pGlyphPriv->pArea->y, + pGlyph->info.width, + pGlyph->info.height, + &pixel, + buffer); + + p1.x = pGlyphPriv->pArea->x << 16; + p1.y = pGlyphPriv->pArea->y << 16; + p2.x = (pGlyphPriv->pArea->x + pGlyph->info.width) << 16; + p2.y = (pGlyphPriv->pArea->y + pGlyph->info.height) << 16; + + glitz_surface_translate_point (pTexture->mask, &p1, &p1); + glitz_surface_translate_point (pTexture->mask, &p2, &p2); + + if (pTexture->geometryDataType) + { + pAreaPriv->u.box.fBox.x1 = FIXED_TO_FLOAT (p1.x); + pAreaPriv->u.box.fBox.y1 = FIXED_TO_FLOAT (p1.y); + pAreaPriv->u.box.fBox.x2 = FIXED_TO_FLOAT (p2.x); + pAreaPriv->u.box.fBox.y2 = FIXED_TO_FLOAT (p2.y); + } + else + { + pAreaPriv->u.box.sBox.x1 = p1.x >> 16; + pAreaPriv->u.box.sBox.y1 = p1.y >> 16; + pAreaPriv->u.box.sBox.x2 = p2.x >> 16; + pAreaPriv->u.box.sBox.y2 = p2.y >> 16; + } + } + glitz_buffer_destroy (buffer); + } else + pGlyphPriv->pArea = &zeroSizeArea; + } + + return pGlyphPriv->pArea; +} + +static void +xglUncachedGlyphs (CARD8 op, + PicturePtr pSrc, + PicturePtr pDst, + INT16 xSrc, + INT16 ySrc, + xglGlyphOpPtr pOp) +{ + ScreenPtr pScreen = pDst->pDrawable->pScreen; + PicturePtr pPicture = NULL; + PixmapPtr pPixmap = NULL; + xglGlyphCachePtr pCache; + int depth = pOp->pLists->format->depth; + GlyphPtr glyph; + INT16 xOff, yOff; + xglGlyphPtr pGlyphPriv; + xglAreaPtr pArea; + Bool usingCache = !pOp->noCache; + + XGL_SCREEN_PRIV (pScreen); + + pCache = &pScreenPriv->glyphCache[depth]; + + while (pOp->nGlyphs) + { + glyph = *pOp->ppGlyphs; + + if (!pOp->listLen) + { + pOp->pLists++; + pOp->listLen = pOp->pLists->len; + pOp->xOff += pOp->pLists->xOff; + pOp->yOff += pOp->pLists->yOff; + } + + xOff = pOp->xOff; + yOff = pOp->yOff; + + if (usingCache) + { + pGlyphPriv = XGL_GET_GLYPH_PRIV (pScreen, glyph); + if (pSrc) + { + pArea = pGlyphPriv->pArea; + if (pArea) + break; + + if (pCache->pScreen || + xglInitGlyphCache (pCache, pScreen, pOp->pLists->format)) + { + if (xglCacheGlyph (pCache, glyph)) + break; + } + } + else + { + pArea = pGlyphPriv->pArea; + } + } else + pArea = NULL; + + pOp->listLen--; + pOp->nGlyphs--; + pOp->ppGlyphs++; + + pOp->xOff += glyph->info.xOff; + pOp->yOff += glyph->info.yOff; + + if (pArea) + continue; + + if (!pPicture) + { + CARD32 componentAlpha; + int error; + + pPixmap = GetScratchPixmapHeader (pScreen, + glyph->info.width, + glyph->info.height, + pOp->pLists->format->depth, + pOp->pLists->format->depth, + 0, (pointer) (glyph + 1)); + if (!pPixmap) + return; + + componentAlpha = NEEDS_COMPONENT (pOp->pLists->format->format); + pPicture = CreatePicture (0, &pPixmap->drawable, + pOp->pLists->format, + CPComponentAlpha, &componentAlpha, + serverClient, &error); + if (!pPicture) + { + FreeScratchPixmapHeader (pPixmap); + return; + } + } + + (*pScreen->ModifyPixmapHeader) (pPixmap, + glyph->info.width, glyph->info.height, + 0, 0, -1, (pointer) (glyph + 1)); + pPixmap->drawable.serialNumber = NEXT_SERIAL_NUMBER; + + if (pSrc) + CompositePicture (op, + pSrc, + pPicture, + pDst, + xSrc + (xOff - glyph->info.x), + ySrc + (yOff - glyph->info.y), + 0, 0, + xOff - glyph->info.x, + yOff - glyph->info.y, + glyph->info.width, + glyph->info.height); + else + CompositePicture (PictOpAdd, + pPicture, + NULL, + pDst, + 0, 0, + 0, 0, + xOff - glyph->info.x, + yOff - glyph->info.y, + glyph->info.width, + glyph->info.height); + } + + if (pPicture) + { + FreeScratchPixmapHeader (pPixmap); + FreePicture ((pointer) pPicture, 0); + } +} + +static Bool +xglCachedGlyphs (CARD8 op, + PicturePtr pSrc, + PicturePtr pDst, + INT16 xSrc, + INT16 ySrc, + xglGlyphOpPtr pOp) +{ + ScreenPtr pScreen = pDst->pDrawable->pScreen; + xglGlyphOpRec opSave = *pOp; + xglGlyphCachePtr pCache; + xglGlyphVertexDataRec vData; + xglGeometryPtr pGeometry; + GlyphPtr glyph; + xglGlyphPtr pGlyphPriv; + xglAreaPtr pArea; + xglGlyphAreaPtr pGlyphArea; + BoxRec extents; + INT16 xOff, yOff, x1, x2, y1, y2; + int depth = pOp->pLists->format->depth; + int n, count = 0, remaining = pOp->nGlyphs; + glitz_surface_t *mask = NULL; + + XGL_SCREEN_PRIV (pScreen); + + pCache = &pScreenPriv->glyphCache[depth]; + if (!pCache->pScreen) + { + if (!xglInitGlyphCache (pCache, pScreen, pOp->pLists->format)) + return 1; + } + + if (depth == 1) + { + glitz_multi_array_t *multiArray; + + pGeometry = &pCache->u.geometry; + pGeometry->xOff = pGeometry->yOff = 0; + + multiArray = glitz_multi_array_create (pOp->nGlyphs); + if (!multiArray) + return 1; + + GEOMETRY_SET_MULTI_ARRAY (pGeometry, multiArray); + glitz_multi_array_destroy (multiArray); + + vData.array.lastX = 0; + vData.array.lastY = 0; + } + else + { + n = pCache->u.texture.format.vertex.bytes_per_vertex; + pGeometry = xglGetScratchGeometryWithSize (pScreen, 4 * n * remaining); + + pGeometry->f = pCache->u.texture.format; + pGeometry->type = GLITZ_GEOMETRY_TYPE_VERTEX; + mask = pCache->u.texture.mask; + + vData.list.s = glitz_buffer_map (pGeometry->buffer, + GLITZ_BUFFER_ACCESS_WRITE_ONLY); + } + + NEXT_GLYPH_SERIAL_NUMBER; + + while (pOp->nGlyphs) + { + glyph = *pOp->ppGlyphs; + + if (!pOp->listLen) + { + pOp->pLists++; + pOp->listLen = pOp->pLists->len; + pOp->xOff += pOp->pLists->xOff; + pOp->yOff += pOp->pLists->yOff; + } + + xOff = pOp->xOff; + yOff = pOp->yOff; + + pGlyphPriv = XGL_GET_GLYPH_PRIV (pScreen, glyph); + pArea = pGlyphPriv->pArea; + if (!pArea) + { + n = pOp->nGlyphs; + while (n--) + { + pGlyphPriv = XGL_GET_GLYPH_PRIV (pScreen, pOp->ppGlyphs[n]); + pArea = pGlyphPriv->pArea; + if (pArea && pArea->width) + GLYPH_GET_AREA_PRIV (pArea)->serial = glyphSerialNumber; + } + + pArea = xglCacheGlyph (pCache, glyph); + if (!pArea && pSrc) + break; + } + + pOp->listLen--; + pOp->nGlyphs--; + pOp->ppGlyphs++; + + pOp->xOff += glyph->info.xOff; + pOp->yOff += glyph->info.yOff; + + if (!pArea) + continue; + + x1 = xOff - glyph->info.x; + x2 = x1 + glyph->info.width; + if (x1 < extents.x1) + extents.x1 = x1; + if (x2 > extents.x2) + extents.x2 = x2; + + y1 = yOff - glyph->info.y; + y2 = y1 + glyph->info.height; + if (y1 < extents.y1) + extents.y1 = y1; + if (y2 > extents.y2) + extents.y2 = y2; + + if (pArea->width) + { + pGlyphArea = GLYPH_GET_AREA_PRIV (pArea); + if (depth == 1) + { + glitz_multi_array_add (pGeometry->array, + pGlyphArea->u.range.first, 2, + pGlyphArea->u.range.count, + (x1 - vData.array.lastX) << 16, + (y1 - vData.array.lastY) << 16); + vData.array.lastX = x1; + vData.array.lastY = y1; + } + else + { + if (pCache->u.texture.geometryDataType) + { + WRITE_BOX (vData.list.f, x1, y1, x2, y2, + pGlyphArea->u.box.fBox); + } + else + { + WRITE_BOX (vData.list.s, x1, y1, x2, y2, + pGlyphArea->u.box.sBox); + } + } + count++; + } + remaining--; + } + + if (depth != 1) + { + glitz_buffer_unmap (pGeometry->buffer); + pGeometry->count = count * 4; + } + + if (count) + { + xSrc += extents.x1; + ySrc += extents.y1; + + if (!pSrc) + { + op = PictOpAdd; + pSrc = pScreenPriv->pSolidAlpha; + + if (remaining) + *pOp = opSave; + } + + GEOMETRY_TRANSLATE (pGeometry, + pDst->pDrawable->x, + pDst->pDrawable->y); + + if (xglComp (op, + pSrc, + NULL, + pDst, + xSrc, ySrc, + 0, 0, + pDst->pDrawable->x + extents.x1, + pDst->pDrawable->y + extents.y1, + extents.x2 - extents.x1, + extents.y2 - extents.y1, + pGeometry, + mask)) + { + xglAddCurrentBitDamage (pDst->pDrawable); + return remaining; + } + + remaining = ~0; + pOp->noCache = TRUE; + *pOp = opSave; + } + else + { + if (remaining) + { + pOp->noCache = TRUE; + *pOp = opSave; + } + } + + return remaining; +} + +static Bool +xglGlyphExtents (int nlist, + GlyphListPtr list, + GlyphPtr *glyphs, + BoxPtr extents) +{ + GlyphPtr glyph; + int x1, x2, y1, y2; + int n; + int x; + int y; + Bool x_overlap, overlap = FALSE; + + x = 0; + y = 0; + + while (!list->len) + { + if (--nlist) + { + x += list->xOff; + y += list->yOff; + list++; + } + else + { + extents->x1 = MAXSHORT; + extents->x2 = MINSHORT; + extents->y1 = MAXSHORT; + extents->y2 = MINSHORT; + + return FALSE; + } + } + + glyph = *glyphs; + x1 = (x + list->xOff) - glyph->info.x; + if (x1 < MINSHORT) + x1 = MINSHORT; + y1 = (y + list->yOff) - glyph->info.y; + if (y1 < MINSHORT) + y1 = MINSHORT; + + extents->x1 = x1; + extents->x2 = x1; + extents->y1 = y1; + extents->y2 = y1; + + 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; + + x_overlap = FALSE; + if (x1 >= extents->x2) + extents->x2 = x2; + else if (x2 <= extents->x1) + extents->x1 = x1; + else + { + x_overlap = TRUE; + if (x1 < extents->x1) + extents->x1 = x1; + if (x2 > extents->x2) + extents->x2 = x2; + } + + if (y1 >= extents->y2) + extents->y2 = y2; + else if (y2 <= extents->y1) + extents->y1 = y1; + else + { + if (y1 < extents->y1) + extents->y1 = y1; + if (y2 > extents->y2) + extents->y2 = y2; + + if (x_overlap) + overlap = TRUE; + } + + x += glyph->info.xOff; + y += glyph->info.yOff; + } + } + + return overlap; +} + +/* returns 0 if all glyph lists don't have the same format */ +static CARD32 +xglGlyphListFormatId (GlyphListPtr list, + int nlist) +{ + CARD32 id = list->format->id; + + nlist--; + list++; + + while (nlist--) + { + if (list->format->id != id) + return 0; + + list++; + } + + return id; +} + +void +xglGlyphs (CARD8 op, + PicturePtr pSrc, + PicturePtr pDst, + PictFormatPtr maskFormat, + INT16 xSrc, + INT16 ySrc, + int nlist, + GlyphListPtr list, + GlyphPtr *glyphs) +{ + ScreenPtr pScreen = pDst->pDrawable->pScreen; + PicturePtr pMask = NULL, pSrcPicture, pDstPicture; + BoxRec extents; + xglGlyphOpRec glyphOp; + int xDst = list->xOff, yDst = list->yOff; + + if (op != PictOpAdd && maskFormat && + (xglGlyphExtents (nlist, list, glyphs, &extents) || op != PictOpOver || + xglGlyphListFormatId (list, nlist) != maskFormat->id)) + { + PixmapPtr pPixmap; + xglPixmapPtr pPixmapPriv; + CARD32 componentAlpha; + GCPtr pGC; + xRectangle rect; + int error; + + if (extents.x2 <= extents.x1 || extents.y2 <= extents.y1) + return; + + rect.x = 0; + rect.y = 0; + rect.width = extents.x2 - extents.x1; + rect.height = extents.y2 - extents.y1; + + pPixmap = (*pScreen->CreatePixmap) (pScreen, + rect.width, rect.height, + maskFormat->depth); + if (!pPixmap) + return; + + componentAlpha = NEEDS_COMPONENT (maskFormat->format); + pMask = CreatePicture (0, &pPixmap->drawable, + maskFormat, CPComponentAlpha, &componentAlpha, + serverClient, &error); + if (!pMask) + return; + + ValidatePicture (pMask); + pGC = GetScratchGC (pPixmap->drawable.depth, pScreen); + ValidateGC (&pPixmap->drawable, pGC); + (*pGC->ops->PolyFillRect) (&pPixmap->drawable, pGC, 1, &rect); + FreeScratchGC (pGC); + + /* all will be damaged */ + pPixmapPriv = XGL_GET_PIXMAP_PRIV (pPixmap); + pPixmapPriv->damageBox.x1 = 0; + pPixmapPriv->damageBox.y1 = 0; + pPixmapPriv->damageBox.x2 = pMask->pDrawable->width; + pPixmapPriv->damageBox.y2 = pMask->pDrawable->height; + + (*pScreen->DestroyPixmap) (pPixmap); + + glyphOp.xOff = -extents.x1; + glyphOp.yOff = -extents.y1; + pSrcPicture = NULL; + pDstPicture = pMask; + } + else + { + glyphOp.xOff = 0; + glyphOp.yOff = 0; + pSrcPicture = pSrc; + pDstPicture = pDst; + } + + glyphOp.ppGlyphs = glyphs; + + if (xglPrepareTarget (pDstPicture->pDrawable)) + glyphOp.noCache = FALSE; + else + glyphOp.noCache = TRUE; + + while (nlist--) + { + glyphOp.xOff += list->xOff; + glyphOp.yOff += list->yOff; + glyphOp.listLen = list->len; + glyphOp.nGlyphs = list->len; + glyphOp.pLists = list++; + + for (; nlist; nlist--, list++) + { + if (list->format->id != glyphOp.pLists->format->id) + break; + + glyphOp.nGlyphs += list->len; + } + + while (glyphOp.nGlyphs) + { + if (glyphOp.noCache || xglCachedGlyphs (op, + pSrcPicture, + pDstPicture, + xSrc - xDst, ySrc - yDst, + &glyphOp)) + xglUncachedGlyphs (op, + pSrcPicture, + pDstPicture, + xSrc - xDst, ySrc - yDst, + &glyphOp); + } + } + + if (pMask) + { + xglLeaveOffscreenArea ((PixmapPtr) pMask->pDrawable); + + CompositePicture (op, + pSrc, + pMask, + pDst, + xSrc + extents.x1 - xDst, + ySrc + extents.y1 - yDst, + 0, 0, + extents.x1, extents.y1, + extents.x2 - extents.x1, + extents.y2 - extents.y1); + + FreePicture ((pointer) pMask, (XID) 0); + } +} + +#endif diff --git a/hw/xgl/xglinput.c b/hw/xgl/xglinput.c index 6790d4bf2..91becc3c1 100644 --- a/hw/xgl/xglinput.c +++ b/hw/xgl/xglinput.c @@ -5,7 +5,7 @@ * 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 names of + * appear in supporting documentation, and that the name of * David Reveman not be used in advertising or publicity pertaining to * distribution of the software without specific, written prior permission. * David Reveman makes no representations about the suitability of this @@ -20,7 +20,7 @@ * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * - * Author: David Reveman <davidr@freedesktop.org> + * Author: David Reveman <davidr@novell.com> */ #include "xgl.h" diff --git a/hw/xgl/xgloffscreen.c b/hw/xgl/xgloffscreen.c index 7018c054a..b19c3ce21 100644 --- a/hw/xgl/xgloffscreen.c +++ b/hw/xgl/xgloffscreen.c @@ -5,7 +5,7 @@ * 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 names of + * appear in supporting documentation, and that the name of * David Reveman not be used in advertising or publicity pertaining to * distribution of the software without specific, written prior permission. * David Reveman makes no representations about the suitability of this @@ -20,278 +20,98 @@ * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * - * Author: David Reveman <davidr@freedesktop.org> + * Author: David Reveman <davidr@novell.com> */ #include "xgl.h" -/* - * This offscreen memory manager is horrible and needs some serious work. - * - * It's a recursive memory manager. It's quite fast but wastes huge - * amounts of memory. A simple scoring mechanism is used and pixmaps - * that blit to screen get high scores which makes a compositing - * manager run fast. - * - * NOTE: With GL_ARB_uber_buffer or GL_EXT_render_target we probably - * wont need this offscreen management at all. - */ - static glitz_drawable_buffer_t _buffers[] = { GLITZ_DRAWABLE_BUFFER_BACK_COLOR, GLITZ_DRAWABLE_BUFFER_FRONT_COLOR }; -#define MAX_LEVEL 6 +#define MAX_OFFSCREEN_LEVEL 8 + +static Bool +xglOffscreenCreate (xglAreaPtr pArea) +{ + return TRUE; +} static Bool -xglOffscreenMoveIn (xglOffscreenAreaPtr pArea, - PixmapPtr pPixmap) +xglOffscreenMoveIn (xglAreaPtr pArea, + pointer closure) { + xglOffscreenPtr pOffscreen = (xglOffscreenPtr) pArea->pRoot->closure; + PixmapPtr pPixmap = (PixmapPtr) closure; + XGL_PIXMAP_PRIV (pPixmap); if (!xglSyncSurface (&pPixmap->drawable)) FatalError (XGL_SW_FAILURE_STRING); - pArea->pPixmapPriv = pPixmapPriv; - pArea->state = xglOffscreenAreaOccupied; - pPixmapPriv->pArea = pArea; pPixmapPriv->target = xglPixmapTargetIn; glitz_surface_attach (pPixmapPriv->surface, - pArea->pOffscreen->drawable, - pArea->pOffscreen->buffer, + pOffscreen->drawable, pOffscreen->buffer, pArea->x, pArea->y); - XGL_INCREMENT_PIXMAP_SCORE (pPixmapPriv, 500); + XGL_INCREMENT_PIXMAP_SCORE (pPixmapPriv, 100); return TRUE; } static void -xglOffscreenMoveOut (xglOffscreenAreaPtr pArea) +xglOffscreenMoveOut (xglAreaPtr pArea, + pointer closure) { - glitz_surface_detach (pArea->pPixmapPriv->surface); - - pArea->pPixmapPriv->pArea = NULL; - pArea->pPixmapPriv->target = xglPixmapTargetOut; - pArea->pPixmapPriv = NULL; - pArea->state = xglOffscreenAreaAvailable; -} + PixmapPtr pPixmap = (PixmapPtr) closure; -static xglOffscreenAreaPtr -xglCreateOffscreenArea (xglOffscreenPtr pOffscreen, - int level, - int x, - int y) -{ - xglOffscreenAreaPtr pArea; - int i; - - pArea = xalloc (sizeof (xglOffscreenAreaRec)); - if (!pArea) - return NULL; - - pArea->level = level; - pArea->x = x; - pArea->y = y; - pArea->pOffscreen = pOffscreen; - pArea->pPixmapPriv = NULL; - pArea->state = xglOffscreenAreaAvailable; - - for (i = 0; i < 4; i++) - pArea->pArea[i] = NULL; - - return pArea; -} - -static void -xglDestroyOffscreenArea (xglOffscreenAreaPtr pArea) -{ - if (!pArea) - return; - - if (pArea->pPixmapPriv) - { - xglOffscreenMoveOut (pArea); - } - else - { - int i; + XGL_PIXMAP_PRIV (pPixmap); - for (i = 0; i < 4; i++) - xglDestroyOffscreenArea (pArea->pArea[i]); - } + glitz_surface_detach (pPixmapPriv->surface); - xfree (pArea); + pPixmapPriv->pArea = NULL; + pPixmapPriv->target = xglPixmapTargetOut; } -static Bool -xglOffscreenInit (xglOffscreenPtr pOffscreen, - glitz_drawable_t *drawable, - glitz_drawable_buffer_t buffer, - unsigned int width, - unsigned int height) +static int +xglOffscreenCompareScore (xglAreaPtr pArea, + pointer closure1, + pointer closure2) { - pOffscreen->pArea = xglCreateOffscreenArea (NULL, 0, 0, 0); - if (!pOffscreen->pArea) - return FALSE; - - glitz_drawable_reference (drawable); - - pOffscreen->drawable = drawable; - pOffscreen->format = glitz_drawable_get_format (drawable); - pOffscreen->buffer = buffer; - pOffscreen->width = width; - pOffscreen->height = height; + int s1, s2; - return TRUE; -} + XGL_PIXMAP_PRIV ((PixmapPtr) closure1); -static void -xglOffscreenFini (xglOffscreenPtr pOffscreen) -{ - xglDestroyOffscreenArea (pOffscreen->pArea); - glitz_drawable_destroy (pOffscreen->drawable); -} - -static int -xglOffscreenAreaGetTopScore (xglOffscreenAreaPtr pArea) -{ - int topScore; + s1 = pPixmapPriv->score; + s2 = XGL_GET_PIXMAP_PRIV ((PixmapPtr) closure2)->score; - if (pArea->pPixmapPriv) - { - topScore = pArea->pPixmapPriv->score; - XGL_DECREMENT_PIXMAP_SCORE (pArea->pPixmapPriv, 5); - - return topScore; - } - else - { - int topScore, score, i; - - topScore = 0; - for (i = 0; i < 4; i++) - { - if (pArea->pArea[i]) - { - score = xglOffscreenAreaGetTopScore (pArea->pArea[i]); - if (score > topScore) - topScore = score; - } - } - return topScore; - } + if (s1 > s2) + XGL_DECREMENT_PIXMAP_SCORE (pPixmapPriv, 10); + + return s1 - s2; } - -static Bool -xglOffscreenFindArea (xglOffscreenAreaPtr pArea, - PixmapPtr pPixmap, - int level) -{ - if (pArea->level > level) - return FALSE; - - switch (pArea->state) { - case xglOffscreenAreaOccupied: - { - XGL_PIXMAP_PRIV (pPixmap); - - if (pPixmapPriv->score < pArea->pPixmapPriv->score) - { - XGL_DECREMENT_PIXMAP_SCORE (pArea->pPixmapPriv, 10); - - return FALSE; - } - - xglOffscreenMoveOut (pArea); - } - /* fall-through */ - case xglOffscreenAreaAvailable: - { - if (pArea->level == level || pArea->level == MAX_LEVEL) - { - if (xglOffscreenMoveIn (pArea, pPixmap)) - return TRUE; - } - else - { - int dx[4], dy[4], i; - - dx[0] = dx[2] = dy[0] = dy[1] = 0; - dx[1] = dx[3] = pArea->pOffscreen->width >> (pArea->level + 1); - dy[2] = dy[3] = pArea->pOffscreen->height >> (pArea->level + 1); - - for (i = 0; i < 4; i++) - { - pArea->pArea[i] = - xglCreateOffscreenArea (pArea->pOffscreen, - pArea->level + 1, - pArea->x + dx[i], - pArea->y + dy[i]); - } - - pArea->state = xglOffscreenAreaDivided; - - if (xglOffscreenFindArea (pArea->pArea[0], pPixmap, level)) - return TRUE; - } - } break; - case xglOffscreenAreaDivided: - { - int i; - - if (pArea->level == level) - { - int topScore; - - XGL_PIXMAP_PRIV (pPixmap); - - topScore = xglOffscreenAreaGetTopScore (pArea); - - if (pPixmapPriv->score >= topScore) - { - /* - * Kick out old pixmaps - */ - for (i = 0; i < 4; i++) - { - xglDestroyOffscreenArea (pArea->pArea[i]); - pArea->pArea[i] = NULL; - } - - if (xglOffscreenMoveIn (pArea, pPixmap)) - return TRUE; - } - } - else - { - for (i = 0; i < 4; i++) - { - if (xglOffscreenFindArea (pArea->pArea[i], pPixmap, level)) - return TRUE; - } - } - } break; - } - - return FALSE; -} +static const xglAreaFuncsRec xglOffscreenAreaFuncs = { + xglOffscreenCreate, + xglOffscreenMoveIn, + xglOffscreenMoveOut, + xglOffscreenCompareScore +}; Bool xglInitOffscreen (ScreenPtr pScreen, xglScreenInfoPtr pScreenInfo) { xglOffscreenPtr pOffscreen; - int nOffscreen; glitz_drawable_format_t *format; XGL_SCREEN_PRIV (pScreen); - pScreenPriv->pOffscreen = NULL; + pOffscreen = pScreenPriv->pOffscreen; + pScreenPriv->nOffscreen = 0; format = glitz_drawable_get_format (pScreenPriv->drawable); @@ -301,33 +121,32 @@ xglInitOffscreen (ScreenPtr pScreen, */ if (format->doublebuffer) { - pScreenPriv->pOffscreen = - xrealloc (pScreenPriv->pOffscreen, - sizeof (xglOffscreenRec) * - (pScreenPriv->nOffscreen + 1)); - if (pScreenPriv->pOffscreen) + pOffscreen->drawable = pScreenPriv->drawable; + pOffscreen->format = format; + pOffscreen->buffer = GLITZ_DRAWABLE_BUFFER_BACK_COLOR; + + if (xglRootAreaInit (&pOffscreen->rootArea, + MAX_OFFSCREEN_LEVEL, + pScreenInfo->width, + pScreenInfo->height, 0, + (xglAreaFuncsPtr) &xglOffscreenAreaFuncs, + (pointer) pOffscreen)) { - pOffscreen = &pScreenPriv->pOffscreen[pScreenPriv->nOffscreen]; + glitz_drawable_reference (pOffscreen->drawable); - if (xglOffscreenInit (pOffscreen, - pScreenPriv->drawable, - GLITZ_DRAWABLE_BUFFER_BACK_COLOR, - pScreenInfo->width, pScreenInfo->height)) - { - pScreenPriv->nOffscreen++; - ErrorF ("Initialized %dx%d back buffer offscreen area\n", - pScreenInfo->width, pScreenInfo->height); - } + pScreenPriv->nOffscreen++; + pOffscreen++; + ErrorF ("Initialized %dx%d back buffer offscreen area\n", + pScreenInfo->width, pScreenInfo->height); } } if (nxglPbufferVisuals) { - glitz_pbuffer_attributes_t attributes; - unsigned long mask; - glitz_drawable_t *pbuffer; - int i; - + glitz_drawable_t *pbuffer; + unsigned int width, height; + int i; + for (i = 0; i < nxglPbufferVisuals; i++) { /* @@ -338,26 +157,25 @@ xglInitOffscreen (ScreenPtr pScreen, * supports accelerated pbuffers but offscreen drawing is really * slow, try decrementing these values. */ - attributes.width = 2048; - attributes.height = 2048; - - mask = GLITZ_PBUFFER_WIDTH_MASK | GLITZ_PBUFFER_HEIGHT_MASK; - - pbuffer = - glitz_create_pbuffer_drawable (pScreenPriv->drawable, - xglPbufferVisuals[i].format, - &attributes, mask); + width = 2048; + height = 2048; + + do { + pbuffer = + glitz_create_pbuffer_drawable (pScreenPriv->drawable, + xglPbufferVisuals[i].format, + width, height); + width >>= 1; + height >>= 1; + } while (!pbuffer && width); if (pbuffer) { - unsigned long width, height; - int j; + int j = 0; width = glitz_drawable_get_width (pbuffer); height = glitz_drawable_get_height (pbuffer); - j = 0; - /* * No back buffer? only add front buffer. */ @@ -366,23 +184,23 @@ xglInitOffscreen (ScreenPtr pScreen, while (j < 2) { - pScreenPriv->pOffscreen = - xrealloc (pScreenPriv->pOffscreen, - sizeof (xglOffscreenRec) * - (pScreenPriv->nOffscreen + 1)); - if (pScreenPriv->pOffscreen) + pOffscreen->drawable = pbuffer; + pOffscreen->format = xglPbufferVisuals[i].format; + pOffscreen->buffer = _buffers[j]; + + if (xglRootAreaInit (&pOffscreen->rootArea, + MAX_OFFSCREEN_LEVEL, + width, height, 0, + (xglAreaFuncsPtr) + &xglOffscreenAreaFuncs, + (pointer) pOffscreen)) { - pOffscreen = - &pScreenPriv->pOffscreen[pScreenPriv->nOffscreen]; - - if (xglOffscreenInit (pOffscreen, - pbuffer, _buffers[j], - width, height)) - { - pScreenPriv->nOffscreen++; - ErrorF ("Initialized %dx%d pbuffer offscreen " - "area\n", width, height); - } + glitz_drawable_reference (pbuffer); + + pScreenPriv->nOffscreen++; + pOffscreen++; + ErrorF ("Initialized %dx%d pbuffer offscreen area\n", + width, height); } j++; } @@ -390,18 +208,6 @@ xglInitOffscreen (ScreenPtr pScreen, } } } - - pOffscreen = pScreenPriv->pOffscreen; - nOffscreen = pScreenPriv->nOffscreen; - - /* - * Update offscreen pointers in root offscreen areas - */ - while (nOffscreen--) - { - pOffscreen->pArea->pOffscreen = pOffscreen; - pOffscreen++; - } return TRUE; } @@ -409,13 +215,18 @@ xglInitOffscreen (ScreenPtr pScreen, void xglFiniOffscreen (ScreenPtr pScreen) { - XGL_SCREEN_PRIV (pScreen); - - while (pScreenPriv->nOffscreen--) - xglOffscreenFini (&pScreenPriv->pOffscreen[pScreenPriv->nOffscreen]); + int n; - if (pScreenPriv->pOffscreen) - xfree (pScreenPriv->pOffscreen); + XGL_SCREEN_PRIV (pScreen); + + n = pScreenPriv->nOffscreen; + while (n--) + { + xglRootAreaFini (&pScreenPriv->pOffscreen[n].rootArea); + glitz_drawable_destroy (pScreenPriv->pOffscreen[n].drawable); + } + + pScreenPriv->nOffscreen = 0; } Bool @@ -439,34 +250,41 @@ xglFindOffscreenArea (ScreenPtr pScreen, while (nOffscreen--) { - int level; - if (pOffscreen->format->color.red_size >= pColor->red_size && pOffscreen->format->color.green_size >= pColor->green_size && pOffscreen->format->color.blue_size >= pColor->blue_size && pOffscreen->format->color.alpha_size >= pColor->alpha_size) { + /* Find available area */ + if (xglFindArea (pOffscreen->rootArea.pArea, + pPixmap->drawable.width, + pPixmap->drawable.height, + FALSE, + (pointer) pPixmap)) + return TRUE; - level = 0; - while ((pOffscreen->width >> level) >= pPixmap->drawable.width && - (pOffscreen->height >> level) >= pPixmap->drawable.height) - level++; - - if (!level) - continue; - - if (xglOffscreenFindArea (pOffscreen->pArea, pPixmap, level - 1)) + /* Kicking out area with lower score */ + if (xglFindArea (pOffscreen->rootArea.pArea, + pPixmap->drawable.width, + pPixmap->drawable.height, + TRUE, + (pointer) pPixmap)) return TRUE; } + pOffscreen++; } - + return FALSE; } void -xglWithdrawOffscreenArea (xglOffscreenAreaPtr pArea) +xglLeaveOffscreenArea (PixmapPtr pPixmap) { - pArea->pPixmapPriv = NULL; - pArea->state = xglOffscreenAreaAvailable; + XGL_PIXMAP_PRIV (pPixmap); + + if (pPixmapPriv->pArea) + xglLeaveArea (pPixmapPriv->pArea); + + pPixmapPriv->pArea = NULL; } diff --git a/hw/xgl/xgloutput.c b/hw/xgl/xgloutput.c index 09a09c77f..788dafb43 100644 --- a/hw/xgl/xgloutput.c +++ b/hw/xgl/xgloutput.c @@ -5,7 +5,7 @@ * 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 names of + * appear in supporting documentation, and that the name of * David Reveman not be used in advertising or publicity pertaining to * distribution of the software without specific, written prior permission. * David Reveman makes no representations about the suitability of this @@ -20,7 +20,7 @@ * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * - * Author: David Reveman <davidr@freedesktop.org> + * Author: David Reveman <davidr@novell.com> */ #include "xgl.h" diff --git a/hw/xgl/xglparse.c b/hw/xgl/xglparse.c index 185a842a2..ed95680d1 100644 --- a/hw/xgl/xglparse.c +++ b/hw/xgl/xglparse.c @@ -5,7 +5,7 @@ * 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 names of + * appear in supporting documentation, and that the name of * David Reveman not be used in advertising or publicity pertaining to * distribution of the software without specific, written prior permission. * David Reveman makes no representations about the suitability of this @@ -20,7 +20,7 @@ * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * - * Author: David Reveman <davidr@freedesktop.org> + * Author: David Reveman <davidr@novell.com> */ #include "xgl.h" @@ -100,8 +100,11 @@ void xglUseMsg (void) { ErrorF ("-screen WIDTH[/WIDTHMM]xHEIGHT[/HEIGHTMM] " - "Specify screen characteristics\n"); - ErrorF ("-fullscreen Run fullscreen\n"); + "specify screen characteristics\n"); + ErrorF ("-fullscreen run fullscreen\n"); + ErrorF ("-vertextype [short|float] set vertex data type\n"); + ErrorF ("-vbostream " + "use vertex buffer objects for streaming of vertex data\n"); } int @@ -121,12 +124,30 @@ xglProcessArgument (xglScreenInfoPtr pScreenInfo, return 2; } - - if (!strcmp (argv[i], "-fullscreen")) + else if (!strcmp (argv[i], "-fullscreen")) { pScreenInfo->fullscreen = TRUE; return 1; } - + else if (!strcmp (argv[i], "-vertextype")) + { + if ((i + 1) < argc) + { + if (!strcasecmp (argv[i + 1], "short")) + pScreenInfo->geometryDataType = GEOMETRY_DATA_TYPE_SHORT; + else if (!strcasecmp (argv[i + 1], "float")) + pScreenInfo->geometryDataType = GEOMETRY_DATA_TYPE_FLOAT; + } + else + return 1; + + return 2; + } + else if (!strcmp (argv[i], "-vbostream")) + { + pScreenInfo->geometryUsage = GEOMETRY_USAGE_STREAM; + return 1; + } + return 0; } diff --git a/hw/xgl/xglpict.c b/hw/xgl/xglpict.c index 7bfbcd398..90f1c900e 100644 --- a/hw/xgl/xglpict.c +++ b/hw/xgl/xglpict.c @@ -5,7 +5,7 @@ * 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 names of + * appear in supporting documentation, and that the name of * David Reveman not be used in advertising or publicity pertaining to * distribution of the software without specific, written prior permission. * David Reveman makes no representations about the suitability of this @@ -20,10 +20,11 @@ * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * - * Author: David Reveman <davidr@freedesktop.org> + * Author: David Reveman <davidr@novell.com> */ #include "xgl.h" +#include "fb.h" #ifdef RENDER @@ -33,7 +34,7 @@ #define XGL_PICTURE_FALLBACK_EPILOGUE(pPicture, func, xglfunc) \ XGL_PICTURE_SCREEN_WRAP (func, xglfunc); \ - xglAddSurfaceDamage (pPicture->pDrawable) + xglAddCurrentSurfaceDamage (pPicture->pDrawable) void xglComposite (CARD8 op, @@ -49,7 +50,7 @@ xglComposite (CARD8 op, CARD16 width, CARD16 height) { - PictureScreenPtr pPictureScreen; + PictureScreenPtr pPictureScreen; ScreenPtr pScreen = pDst->pDrawable->pScreen; XGL_SCREEN_PRIV (pScreen); @@ -58,9 +59,13 @@ xglComposite (CARD8 op, pSrc, pMask, pDst, xSrc, ySrc, xMask, yMask, - xDst, yDst, - width, height)) + xDst + pDst->pDrawable->x, yDst + pDst->pDrawable->y, + width, height, + NULL, NULL)) + { + xglAddCurrentBitDamage (pDst->pDrawable); return; + } pPictureScreen = GetPictureScreen (pScreen); @@ -73,46 +78,74 @@ xglComposite (CARD8 op, FatalError (XGL_SW_FAILURE_STRING); } - XGL_PICTURE_FALLBACK_PROLOGUE (pDst, Composite); + if (op == PictOpSrc) + { + XGL_DRAWABLE_PIXMAP (pDst->pDrawable); + + if (!xglMapPixmapBits (pPixmap)) + FatalError (XGL_SW_FAILURE_STRING); + } else + xglSyncDamageBoxBits (pDst->pDrawable); + + XGL_PICTURE_SCREEN_UNWRAP (Composite); (*pPictureScreen->Composite) (op, pSrc, pMask, pDst, xSrc, ySrc, xMask, yMask, xDst, yDst, width, height); - XGL_PICTURE_FALLBACK_EPILOGUE (pDst, Composite, xglComposite); -} + XGL_PICTURE_SCREEN_WRAP (Composite, xglComposite); -void -xglGlyphs (CARD8 op, - PicturePtr pSrc, - PicturePtr pDst, - PictFormatPtr maskFormat, - INT16 xSrc, - INT16 ySrc, - int nlist, - GlyphListPtr list, - GlyphPtr *glyphs) -{ - miGlyphs (op, pSrc, pDst, maskFormat, xSrc, ySrc, nlist, list, glyphs); + if (op == PictOpSrc) + { + RegionRec region; + + xDst += pDst->pDrawable->x; + yDst += pDst->pDrawable->y; + + xSrc += pSrc->pDrawable->x; + ySrc += pSrc->pDrawable->y; + + if (pMask) + { + xMask += pMask->pDrawable->x; + yMask += pMask->pDrawable->y; + } + + if (!miComputeCompositeRegion (®ion, pSrc, pMask, pDst, + xSrc, ySrc, xMask, yMask, xDst, yDst, + width, height)) + return; + + xglAddSurfaceDamage (pDst->pDrawable, ®ion); + REGION_UNINIT (pDst->pDrawable->pScreen, ®ion); + } else + xglAddCurrentSurfaceDamage (pDst->pDrawable); } void -xglRasterizeTrapezoid (PicturePtr pDst, - xTrapezoid *trap, - int xOff, - int yOff) +xglAddTriangles (PicturePtr pDst, + INT16 xOff, + INT16 yOff, + int ntri, + xTriangle *tris) { PictureScreenPtr pPictureScreen; ScreenPtr pScreen = pDst->pDrawable->pScreen; XGL_SCREEN_PRIV (pScreen); + XGL_DRAWABLE_PIXMAP_PRIV (pDst->pDrawable); pPictureScreen = GetPictureScreen (pScreen); - XGL_PICTURE_FALLBACK_PROLOGUE (pDst, RasterizeTrapezoid); - (*pPictureScreen->RasterizeTrapezoid) (pDst, trap, xOff, yOff); - XGL_PICTURE_FALLBACK_EPILOGUE (pDst, RasterizeTrapezoid, - xglRasterizeTrapezoid); + pPixmapPriv->damageBox.x1 = 0; + pPixmapPriv->damageBox.y1 = 0; + pPixmapPriv->damageBox.x2 = pDst->pDrawable->width; + pPixmapPriv->damageBox.y2 = pDst->pDrawable->height; + + XGL_PICTURE_FALLBACK_PROLOGUE (pDst, AddTriangles); + (*pPictureScreen->AddTriangles) (pDst, xOff, yOff, ntri, tris); + XGL_PICTURE_FALLBACK_EPILOGUE (pDst, AddTriangles, xglAddTriangles); } + void xglChangePicture (PicturePtr pPicture, Mask mask) @@ -207,16 +240,18 @@ xglUpdatePicture (PicturePtr pPicture) case PictFilterNearest: case PictFilterFast: glitz_surface_set_filter (surface, GLITZ_FILTER_NEAREST, NULL, 0); - pPixmapPriv->pictureMask &= ~xglPFFilterMask; break; case PictFilterGood: case PictFilterBest: case PictFilterBilinear: glitz_surface_set_filter (surface, GLITZ_FILTER_BILINEAR, NULL, 0); - pPixmapPriv->pictureMask &= ~xglPFFilterMask; break; - default: - pPixmapPriv->pictureMask |= xglPFFilterMask; + case PictFilterConvolution: + glitz_surface_set_filter (surface, GLITZ_FILTER_CONVOLUTION, + (glitz_fixed16_16_t *) + pPicture->filter_params, + pPicture->filter_nparams); + break; } } @@ -237,4 +272,185 @@ xglUpdatePicture (PicturePtr pPicture) pPixmapPriv->pictureMask &= ~XGL_PICTURE_CHANGES (~0); } +static int +xglVisualDepth (ScreenPtr pScreen, VisualPtr pVisual) +{ + DepthPtr pDepth; + int d, v; + + for (d = 0; d < pScreen->numDepths; d++) + { + pDepth = &pScreen->allowedDepths[d]; + for (v = 0; v < pDepth->numVids; v++) + if (pDepth->vids[v] == pVisual->vid) + return pDepth->depth; + } + + return 0; +} + +typedef struct _xglformatInit { + CARD32 format; + CARD8 depth; +} xglFormatInitRec, *xglFormatInitPtr; + +static int +xglAddFormat (xglFormatInitPtr formats, + int nformat, + CARD32 format, + CARD8 depth) +{ + int n; + + for (n = 0; n < nformat; n++) + if (formats[n].format == format && formats[n].depth == depth) + return nformat; + + formats[nformat].format = format; + formats[nformat].depth = depth; + + return ++nformat; +} + +#define Mask(n) ((n) == 32 ? 0xffffffff : ((1 << (n)) - 1)) + +Bool +xglPictureInit (ScreenPtr pScreen) +{ + int f, nformats = 0; + PictFormatPtr pFormats; + xglFormatInitRec formats[64]; + CARD32 format; + CARD8 depth; + VisualPtr pVisual; + int v; + int bpp; + int r, g, b; + int d; + DepthPtr pDepth; + + /* formats required by protocol */ + formats[nformats].format = PICT_a1; + formats[nformats].depth = 1; + nformats++; + formats[nformats].format = PICT_a4; + formats[nformats].depth = 4; + nformats++; + formats[nformats].format = PICT_a8; + formats[nformats].depth = 8; + nformats++; + formats[nformats].format = PICT_a8r8g8b8; + formats[nformats].depth = 32; + nformats++; + + /* now look through the depths and visuals adding other formats */ + for (v = 0; v < pScreen->numVisuals; v++) + { + pVisual = &pScreen->visuals[v]; + depth = xglVisualDepth (pScreen, pVisual); + if (!depth) + continue; + + bpp = BitsPerPixel (depth); + switch (pVisual->class) { + case DirectColor: + case TrueColor: + r = Ones (pVisual->redMask); + g = Ones (pVisual->greenMask); + b = Ones (pVisual->blueMask); + if (pVisual->offsetBlue == 0 && + pVisual->offsetGreen == b && + pVisual->offsetRed == b + g) + { + format = PICT_FORMAT (bpp, PICT_TYPE_ARGB, 0, r, g, b); + nformats = xglAddFormat (formats, nformats, format, depth); + } + break; + case StaticColor: + case PseudoColor: + case StaticGray: + case GrayScale: + break; + } + } + + /* walk supported depths and add missing Direct formats */ + for (d = 0; d < pScreen->numDepths; d++) + { + pDepth = &pScreen->allowedDepths[d]; + bpp = BitsPerPixel (pDepth->depth); + format = 0; + switch (bpp) { + case 16: + if (pDepth->depth == 15) + nformats = xglAddFormat (formats, nformats, + PICT_x1r5g5b5, pDepth->depth); + if (pDepth->depth == 16) + nformats = xglAddFormat (formats, nformats, + PICT_r5g6b5, pDepth->depth); + break; + case 24: + if (pDepth->depth == 24) + nformats = xglAddFormat (formats, nformats, + PICT_r8g8b8, pDepth->depth); + break; + case 32: + if (pDepth->depth == 24) + nformats = xglAddFormat (formats, nformats, + PICT_x8r8g8b8, pDepth->depth); + break; + } + } + + pFormats = (PictFormatPtr) xalloc (nformats * sizeof (PictFormatRec)); + if (!pFormats) + return 0; + + memset (pFormats, '\0', nformats * sizeof (PictFormatRec)); + for (f = 0; f < nformats; f++) + { + pFormats[f].id = FakeClientID (0); + pFormats[f].depth = formats[f].depth; + format = formats[f].format; + pFormats[f].format = format; + pFormats[f].type = PictTypeDirect; + switch (PICT_FORMAT_TYPE (format)) { + case PICT_TYPE_ARGB: + pFormats[f].direct.alphaMask = Mask (PICT_FORMAT_A (format)); + if (pFormats[f].direct.alphaMask) + pFormats[f].direct.alpha = (PICT_FORMAT_R (format) + + PICT_FORMAT_G (format) + + PICT_FORMAT_B (format)); + + pFormats[f].direct.redMask = Mask (PICT_FORMAT_R (format)); + pFormats[f].direct.red = (PICT_FORMAT_G (format) + + PICT_FORMAT_B (format)); + + pFormats[f].direct.greenMask = Mask (PICT_FORMAT_G (format)); + pFormats[f].direct.green = PICT_FORMAT_B (format); + + pFormats[f].direct.blueMask = Mask (PICT_FORMAT_B (format)); + pFormats[f].direct.blue = 0; + break; + case PICT_TYPE_A: + pFormats[f].direct.alpha = 0; + pFormats[f].direct.alphaMask = Mask (PICT_FORMAT_A (format)); + break; + case PICT_TYPE_COLOR: + case PICT_TYPE_GRAY: + break; + } + } + + if (!fbPictureInit (pScreen, pFormats, nformats)) + return FALSE; + + if (PictureAddFilter (pScreen, + FilterConvolution, + miFilterValidateParams) < 0) + return FALSE; + + return TRUE; +} + #endif diff --git a/hw/xgl/xglpixel.c b/hw/xgl/xglpixel.c deleted file mode 100644 index f6ecf0a41..000000000 --- a/hw/xgl/xglpixel.c +++ /dev/null @@ -1,149 +0,0 @@ -/* - * Copyright © 2004 David Reveman - * - * 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 names of - * David Reveman not be used in advertising or publicity pertaining to - * distribution of the software without specific, written prior permission. - * David Reveman makes no representations about the suitability of this - * software for any purpose. It is provided "as is" without express or - * implied warranty. - * - * DAVID REVEMAN DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, - * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN - * NO EVENT SHALL DAVID REVEMAN BE LIABLE FOR ANY SPECIAL, INDIRECT OR - * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS - * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, - * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION - * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - * Author: David Reveman <davidr@freedesktop.org> - */ - -#include "xgl.h" -#include "fb.h" - -Bool -xglSetPixels (DrawablePtr pDrawable, - char *src, - int stride, - int x, - int y, - int width, - int height, - BoxPtr pBox, - int nBox) -{ - glitz_pixel_format_t format; - glitz_surface_t *surface; - FbBits *srcBits, *dstBits; - FbStride srcStride, dstStride; - BoxPtr pDstBox; - int nDstBox; - int dstXoff, dstYoff, dstBpp; - int x1, y1, x2, y2; - - XGL_DRAWABLE_PIXMAP (pDrawable); - XGL_PIXMAP_PRIV (pPixmap); - - if (!nBox) - return TRUE; - - if (!xglSyncSurface (pDrawable)) - return FALSE; - - XGL_GET_DRAWABLE (pDrawable, surface, dstXoff, dstYoff); - - if (!xglMapPixmapBits (pPixmap)) - return FALSE; - - dstBpp = pDrawable->bitsPerPixel; - - srcBits = (FbBits *) src; - dstBits = (FbBits *) pPixmap->devPrivate.ptr; - - srcStride = stride / sizeof (FbBits); - dstStride = pPixmapPriv->stride / sizeof (FbBits); - - pDstBox = xalloc (nBox); - if (!pDstBox) - return FALSE; - - nDstBox = 0; - - while (nBox--) - { - x1 = x; - y1 = y; - x2 = x + width; - y2 = y + height; - - if (x1 < pBox->x1) - x1 = pBox->x1; - if (y1 < pBox->y1) - y1 = pBox->y1; - if (x2 > pBox->x2) - x2 = pBox->x2; - if (y2 > pBox->y2) - y2 = pBox->y2; - - if (x1 < x2 && y1 < y2) - { - fbBlt (srcBits + (y1 - y) * srcStride, - srcStride, - (x1 - x) * dstBpp, - - dstBits + (y1 + dstYoff) * dstStride, - dstStride, - (x1 + dstXoff) * dstBpp, - - (x2 - x1) * dstBpp, - y2 - y1, - - GXcopy, - FB_ALLONES, - dstBpp, - FALSE, - FALSE); - - pDstBox[nDstBox].x1 = x1; - pDstBox[nDstBox].y1 = y1; - pDstBox[nDstBox].x2 = x2; - pDstBox[nDstBox].y2 = y2; - - nDstBox++; - } - pBox++; - } - - xglUnmapPixmapBits (pPixmap); - - format.masks = pPixmapPriv->pPixel->masks; - format.bytes_per_line = pPixmapPriv->stride; - format.scanline_order = XGL_INTERNAL_SCANLINE_ORDER; - - pBox = pDstBox; - - while (nDstBox--) - { - format.xoffset = pBox->x1 + dstXoff; - format.skip_lines = pBox->y1 + dstYoff; - - glitz_set_pixels (surface, - pBox->x1 + dstXoff, - pBox->y1 + dstYoff, - pBox->x2 - pBox->x1, - pBox->y2 - pBox->y1, - &format, - pPixmapPriv->buffer); - - pBox++; - } - - xfree (pDstBox); - - return TRUE; -} diff --git a/hw/xgl/xglpixmap.c b/hw/xgl/xglpixmap.c index 099ded652..52ae1ead1 100644 --- a/hw/xgl/xglpixmap.c +++ b/hw/xgl/xglpixmap.c @@ -5,7 +5,7 @@ * 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 names of + * appear in supporting documentation, and that the name of * David Reveman not be used in advertising or publicity pertaining to * distribution of the software without specific, written prior permission. * David Reveman makes no representations about the suitability of this @@ -20,7 +20,7 @@ * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * - * Author: David Reveman <davidr@freedesktop.org> + * Author: David Reveman <davidr@novell.com> */ #include "xgl.h" @@ -32,7 +32,7 @@ xglPixmapDamageReport (DamagePtr pDamage, void *closure) { PixmapPtr pPixmap = (PixmapPtr) closure; - BoxPtr pExt; + BoxPtr pExt; XGL_PIXMAP_PRIV (pPixmap); @@ -104,10 +104,9 @@ xglPixmapSurfaceInit (PixmapPtr pPixmap, pPixmapPriv->target = xglPixmapTargetOut; /* - * Don't allow depth 8 pixmaps into offscreen drawables as - * no trapezoid acceleration is hooked up yet. + * Do not allow accelerated drawing to bitmaps. */ - if (pPixmap->drawable.depth <= 8) + if (pPixmap->drawable.depth == 1) pPixmapPriv->target = xglPixmapTargetNo; /* @@ -165,10 +164,11 @@ xglCreatePixmap (ScreenPtr pScreen, if (!xglPixmapSurfaceInit (pPixmap, pScreenPriv->features, width, height)) return NullPixmap; - + pPixmapPriv->buffer = NULL; pPixmapPriv->bits = (pointer) 0; pPixmapPriv->stride = 0; + pPixmapPriv->pGeometry = NULL; pPixmapPriv->allBits = TRUE; pPixmapPriv->bitBox.x1 = 0; @@ -189,7 +189,7 @@ xglDestroyPixmap (PixmapPtr pPixmap) return TRUE; if (pPixmapPriv->pArea) - xglWithdrawOffscreenArea (pPixmapPriv->pArea); + xglWithdrawArea (pPixmapPriv->pArea); if (pPixmap->devPrivate.ptr) { @@ -197,6 +197,9 @@ xglDestroyPixmap (PixmapPtr pPixmap) glitz_buffer_unmap (pPixmapPriv->buffer); } + if (pPixmapPriv->pGeometry) + GEOMETRY_UNINIT (pPixmapPriv->pGeometry); + if (pPixmapPriv->buffer) glitz_buffer_destroy (pPixmapPriv->buffer); @@ -265,7 +268,6 @@ xglModifyPixmapHeader (PixmapPtr pPixmap, else if ((bitsPerPixel < 0) && (depth > 0)) pPixmap->drawable.bitsPerPixel = BitsPerPixel (depth); - if (devKind > 0) pPixmapPriv->stride = devKind; else if ((devKind < 0) && ((width > 0) || (depth > 0))) @@ -283,7 +285,7 @@ xglModifyPixmapHeader (PixmapPtr pPixmap, pPixmap->drawable.height != oldHeight) { if (pPixmapPriv->pArea) - xglWithdrawOffscreenArea (pPixmapPriv->pArea); + xglWithdrawArea (pPixmapPriv->pArea); if (pPixmapPriv->surface) glitz_surface_destroy (pPixmapPriv->surface); @@ -304,6 +306,12 @@ xglModifyPixmapHeader (PixmapPtr pPixmap, pPixmap->devPrivate.ptr = 0; } + + if (pPixmapPriv->pGeometry) + { + GEOMETRY_UNINIT (pPixmapPriv->pGeometry); + pPixmapPriv->pGeometry = NULL; + } if (pPixmapPriv->buffer) glitz_buffer_destroy (pPixmapPriv->buffer); @@ -374,6 +382,63 @@ xglPixmapToRegion (PixmapPtr pPixmap) return pRegion; } +xglGeometryPtr +xglPixmapToGeometry (PixmapPtr pPixmap, + int xOff, + int yOff) +{ + XGL_PIXMAP_PRIV (pPixmap); + + if (pPixmap->devPrivate.ptr) + xglUnmapPixmapBits (pPixmap); + + if (!pPixmapPriv->pGeometry) + { + xglGeometryPtr pGeometry; + + if (!pPixmapPriv->buffer) + { + if (!xglAllocatePixmapBits (pPixmap)) + return NULL; + } + + pGeometry = xalloc (sizeof (xglGeometryRec)); + if (!pGeometry) + return NULL; + + GEOMETRY_INIT (pPixmap->drawable.pScreen, pGeometry, + GLITZ_GEOMETRY_TYPE_BITMAP, + GEOMETRY_USAGE_DYNAMIC, 0); + + GEOMETRY_SET_BUFFER (pGeometry, pPixmapPriv->buffer); + + if (pPixmapPriv->stride < 0) + { + pGeometry->f.bitmap.bytes_per_line = -pPixmapPriv->stride; + pGeometry->f.bitmap.scanline_order = + GLITZ_PIXEL_SCANLINE_ORDER_BOTTOM_UP; + } + else + { + pGeometry->f.bitmap.bytes_per_line = pPixmapPriv->stride; + pGeometry->f.bitmap.scanline_order = + GLITZ_PIXEL_SCANLINE_ORDER_TOP_DOWN; + } + + pGeometry->f.bitmap.pad = ((1 + FB_MASK) >> FB_SHIFT) * + sizeof (FbBits); + pGeometry->width = pPixmap->drawable.width; + pGeometry->count = pPixmap->drawable.height; + + pPixmapPriv->pGeometry = pGeometry; + } + + pPixmapPriv->pGeometry->xOff = xOff << 16; + pPixmapPriv->pGeometry->yOff = yOff << 16; + + return pPixmapPriv->pGeometry; +} + Bool xglCreatePixmapSurface (PixmapPtr pPixmap) { @@ -390,7 +455,8 @@ xglCreatePixmapSurface (PixmapPtr pPixmap) glitz_surface_create (pScreenPriv->drawable, pPixmapPriv->format, pPixmap->drawable.width, - pPixmap->drawable.height); + pPixmap->drawable.height, + 0, NULL); if (!pPixmapPriv->surface) { pPixmapPriv->format = NULL; @@ -415,8 +481,6 @@ xglAllocatePixmapBits (PixmapPtr pPixmap) stride = ((width * bpp + FB_MASK) >> FB_SHIFT) * sizeof (FbBits); - pPixmapPriv->stride = stride; - if (stride) { pPixmapPriv->bits = xalloc (height * stride); @@ -432,6 +496,9 @@ xglAllocatePixmapBits (PixmapPtr pPixmap) return FALSE; } } + + /* XXX: pPixmapPriv->stride = -stride */ + pPixmapPriv->stride = stride; return TRUE; } @@ -454,15 +521,14 @@ xglMapPixmapBits (PixmapPtr pPixmap) if (!bits) return FALSE; - if (XGL_INTERNAL_SCANLINE_ORDER_UPSIDE_DOWN && pPixmapPriv->format) + pPixmap->devKind = pPixmapPriv->stride; + if (pPixmapPriv->stride < 0) { - pPixmap->devKind = -pPixmapPriv->stride; - pPixmap->devPrivate.ptr = - bits + (pPixmap->drawable.height - 1) * pPixmapPriv->stride; + pPixmap->devPrivate.ptr = bits + + (pPixmap->drawable.height - 1) * -pPixmapPriv->stride; } else { - pPixmap->devKind = pPixmapPriv->stride; pPixmap->devPrivate.ptr = bits; } } diff --git a/hw/xgl/xglscreen.c b/hw/xgl/xglscreen.c index b2e1e1f48..7ce02c1b1 100644 --- a/hw/xgl/xglscreen.c +++ b/hw/xgl/xglscreen.c @@ -5,7 +5,7 @@ * 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 names of + * appear in supporting documentation, and that the name of * David Reveman not be used in advertising or publicity pertaining to * distribution of the software without specific, written prior permission. * David Reveman makes no representations about the suitability of this @@ -20,7 +20,7 @@ * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * - * Author: David Reveman <davidr@freedesktop.org> + * Author: David Reveman <davidr@novell.com> */ #include "xgl.h" @@ -28,6 +28,12 @@ #include "mipointer.h" #include "damage.h" #include "fb.h" +#ifdef MITSHM +#include "shmint.h" +#endif +#ifdef RENDER +#include "glyphstr.h" +#endif int xglScreenGeneration = -1; int xglScreenPrivateIndex; @@ -35,12 +41,13 @@ int xglGCPrivateIndex; int xglPixmapPrivateIndex; int xglWinPrivateIndex; +#ifdef RENDER +int xglGlyphPrivateIndex; +#endif + #define xglQueryBestSize (void *) NoopDDA #define xglSaveScreen (void *) NoopDDA -#define xglRealizeFont (void *) NoopDDA -#define xglUnrealizeFont (void *) NoopDDA - #define xglConstrainCursor (void *) NoopDDA #define xglCursorLimits (void *) NoopDDA #define xglDisplayCursor (void *) NoopDDA @@ -49,14 +56,6 @@ int xglWinPrivateIndex; #define xglRecolorCursor (void *) NoopDDA #define xglSetCursorPosition (void *) NoopDDA -#define xglCreateColormap (void *) NoopDDA -#define xglDestroyColormap (void *) NoopDDA -#define xglInstallColormap (void *) NoopDDA -#define xglUninstallColormap (void *) NoopDDA -#define xglListInstalledColormaps (void *) NoopDDA -#define xglStoreColors (void *) NoopDDA -#define xglResolveColor (void *) NoopDDA - static PixmapPtr xglGetWindowPixmap (WindowPtr pWin) { @@ -100,7 +99,13 @@ xglAllocatePrivates (ScreenPtr pScreen) xglWinPrivateIndex = AllocateWindowPrivateIndex (); if (xglWinPrivateIndex < 0) return FALSE; - + +#ifdef RENDER + xglGlyphPrivateIndex = AllocateGlyphPrivateIndex (); + if (xglGlyphPrivateIndex < 0) + return FALSE; +#endif + xglScreenGeneration = serverGeneration; } @@ -114,7 +119,7 @@ xglAllocatePrivates (ScreenPtr pScreen) if (!AllocateWindowPrivate (pScreen, xglWinPrivateIndex, sizeof (xglWinRec))) return FALSE; - + pScreenPriv = xalloc (sizeof (xglScreenRec)); if (!pScreenPriv) return FALSE; @@ -128,7 +133,7 @@ Bool xglScreenInit (ScreenPtr pScreen, xglScreenInfoPtr pScreenInfo) { - xglScreenPtr pScreenPriv; + xglScreenPtr pScreenPriv; #ifdef RENDER PictureScreenPtr pPictureScreen; @@ -152,11 +157,19 @@ xglScreenInit (ScreenPtr pScreen, xglInitPixmapFormats (pScreen); if (!pScreenPriv->pixmapFormats[32].format) return FALSE; + + pScreenPriv->geometryDataType = pScreenInfo->geometryDataType; + pScreenPriv->geometryUsage = pScreenInfo->geometryUsage; + GEOMETRY_INIT (pScreen, &pScreenPriv->scratchGeometry, + GLITZ_GEOMETRY_TYPE_VERTEX, + pScreenPriv->geometryUsage, 0); + pScreenPriv->surface = glitz_surface_create (pScreenPriv->drawable, pScreenPriv->pixmapFormats[32].format, - pScreenInfo->width, pScreenInfo->height); + pScreenInfo->width, pScreenInfo->height, + 0, NULL); if (!pScreenPriv->surface) return FALSE; @@ -167,7 +180,7 @@ xglScreenInit (ScreenPtr pScreen, if (monitorResolution == 0) monitorResolution = XGL_DEFAULT_DPI; - + if (!fbSetupScreen (pScreen, NULL, pScreenInfo->width, pScreenInfo->height, monitorResolution, monitorResolution, @@ -187,8 +200,12 @@ xglScreenInit (ScreenPtr pScreen, pScreenPriv->pVisual->pPixel->masks.bpp)) return FALSE; +#ifdef MITSHM + ShmRegisterFuncs (pScreen, NULL); +#endif + #ifdef RENDER - if (!fbPictureInit (pScreen, 0, 0)) + if (!xglPictureInit (pScreen)) return FALSE; #endif @@ -197,14 +214,10 @@ xglScreenInit (ScreenPtr pScreen, XGL_SCREEN_WRAP (CopyWindow, xglCopyWindow); XGL_SCREEN_WRAP (CreateWindow, xglCreateWindow); + XGL_SCREEN_WRAP (ChangeWindowAttributes, xglChangeWindowAttributes); XGL_SCREEN_WRAP (PaintWindowBackground, xglPaintWindowBackground); XGL_SCREEN_WRAP (PaintWindowBorder, xglPaintWindowBorder); - /* - pScreen->RealizeFont = xglRealizeFont; - pScreen->UnrealizeFont = xglUnrealizeFont; - */ - XGL_SCREEN_WRAP (CreateGC, xglCreateGC); pScreen->ConstrainCursor = xglConstrainCursor; @@ -215,16 +228,6 @@ xglScreenInit (ScreenPtr pScreen, pScreen->RecolorCursor = xglRecolorCursor; pScreen->SetCursorPosition = xglSetCursorPosition; - /* - pScreen->CreateColormap = miInitializeColormap; - pScreen->DestroyColormap = xglDestroyColormap; - pScreen->InstallColormap = miInstallColormap; - pScreen->UninstallColormap = miUninstallColormap; - pScreen->ListInstalledColormaps = miListInstalledColormaps; - pScreen->StoreColors = xglStoreColors; - pScreen->ResolveColor = miResolveColor; - */ - pScreen->ModifyPixmapHeader = xglModifyPixmapHeader; XGL_SCREEN_WRAP (BitmapToRegion, xglPixmapToRegion); @@ -235,10 +238,19 @@ xglScreenInit (ScreenPtr pScreen, #ifdef RENDER pPictureScreen = GetPictureScreenIfSet (pScreen); - if (pPictureScreen) { + if (pPictureScreen) + { + if (!AllocateGlyphPrivate (pScreen, xglGlyphPrivateIndex, + sizeof (xglGlyphRec))) + return FALSE; + + XGL_PICTURE_SCREEN_WRAP (RealizeGlyph, xglRealizeGlyph); + XGL_PICTURE_SCREEN_WRAP (UnrealizeGlyph, xglUnrealizeGlyph); XGL_PICTURE_SCREEN_WRAP (Composite, xglComposite); XGL_PICTURE_SCREEN_WRAP (Glyphs, xglGlyphs); - XGL_PICTURE_SCREEN_WRAP (RasterizeTrapezoid, xglRasterizeTrapezoid); + XGL_PICTURE_SCREEN_WRAP (Trapezoids, xglTrapezoids); + XGL_PICTURE_SCREEN_WRAP (AddTraps, xglAddTraps); + XGL_PICTURE_SCREEN_WRAP (AddTriangles, xglAddTriangles); XGL_PICTURE_SCREEN_WRAP (ChangePicture, xglChangePicture); XGL_PICTURE_SCREEN_WRAP (ChangePictureTransform, xglChangePictureTransform); @@ -260,6 +272,14 @@ xglScreenInit (ScreenPtr pScreen, Bool xglFinishScreenInit (ScreenPtr pScreen) { + +#ifdef RENDER + glitz_vertex_format_t *format; + static glitz_color_t clearBlack = { 0x0, 0x0, 0x0, 0x0 }; + static glitz_color_t solidWhite = { 0xffff, 0xffff, 0xffff, 0xffff }; + int i; +#endif + XGL_SCREEN_PRIV (pScreen); miInitializeBackingStore (pScreen); @@ -270,11 +290,54 @@ xglFinishScreenInit (ScreenPtr pScreen) pScreenPriv->solid = glitz_surface_create (pScreenPriv->drawable, pScreenPriv->pixmapFormats[32].format, - 1, 1); + 1, 1, 0, NULL); if (!pScreenPriv->solid) return FALSE; glitz_surface_set_fill (pScreenPriv->solid, GLITZ_FILL_REPEAT); + +#ifdef RENDER + for (i = 0; i < 33; i++) + pScreenPriv->glyphCache[i].pScreen = NULL; + + pScreenPriv->pSolidAlpha = NULL; + + pScreenPriv->trapInfo.mask = + glitz_surface_create (pScreenPriv->drawable, + pScreenPriv->pixmapFormats[8].format, + 2, 1, 0, NULL); + if (!pScreenPriv->trapInfo.mask) + return FALSE; + + glitz_set_rectangle (pScreenPriv->trapInfo.mask, &clearBlack, 0, 0, 1, 1); + glitz_set_rectangle (pScreenPriv->trapInfo.mask, &solidWhite, 1, 0, 1, 1); + + glitz_surface_set_fill (pScreenPriv->trapInfo.mask, GLITZ_FILL_NEAREST); + glitz_surface_set_filter (pScreenPriv->trapInfo.mask, + GLITZ_FILTER_BILINEAR, + NULL, 0); + + format = &pScreenPriv->trapInfo.format.vertex; + format->primitive = GLITZ_PRIMITIVE_QUADS; + format->attributes = GLITZ_VERTEX_ATTRIBUTE_MASK_COORD_MASK; + + format->mask.type = GLITZ_DATA_TYPE_FLOAT; + format->mask.size = GLITZ_COORDINATE_SIZE_X; + format->bytes_per_vertex = sizeof (glitz_float_t); + + if (pScreenPriv->geometryDataType) + { + format->type = GLITZ_DATA_TYPE_FLOAT; + format->bytes_per_vertex += 2 * sizeof (glitz_float_t); + format->mask.offset = 2 * sizeof (glitz_float_t); + } + else + { + format->type = GLITZ_DATA_TYPE_SHORT; + format->bytes_per_vertex += 2 * sizeof (glitz_short_t); + format->mask.offset = 2 * sizeof (glitz_short_t); + } +#endif return TRUE; } @@ -285,6 +348,19 @@ xglCloseScreen (int index, { XGL_SCREEN_PRIV (pScreen); +#ifdef RENDER + int i; + + for (i = 0; i < 33; i++) + xglFiniGlyphCache (&pScreenPriv->glyphCache[i]); + + if (pScreenPriv->pSolidAlpha) + FreePicture ((pointer) pScreenPriv->pSolidAlpha, 0); + + if (pScreenPriv->trapInfo.mask) + glitz_surface_destroy (pScreenPriv->trapInfo.mask); +#endif + if (pScreenPriv->solid) glitz_surface_destroy (pScreenPriv->solid); @@ -292,9 +368,59 @@ xglCloseScreen (int index, glitz_surface_destroy (pScreenPriv->surface); xglFiniOffscreen (pScreen); - + + GEOMETRY_UNINIT (&pScreenPriv->scratchGeometry); + XGL_SCREEN_UNWRAP (CloseScreen); xfree (pScreenPriv); return (*pScreen->CloseScreen) (index, pScreen); } + +#ifdef RENDER +void +xglCreateSolidAlphaPicture (ScreenPtr pScreen) +{ + static xRenderColor solidWhite = { 0xffff, 0xffff, 0xffff, 0xffff }; + static xRectangle one = { 0, 0, 1, 1 }; + PixmapPtr pPixmap; + PictFormatPtr pFormat; + int error; + Pixel pixel; + GCPtr pGC; + CARD32 tmpval[2]; + + XGL_SCREEN_PRIV (pScreen); + + pFormat = PictureMatchFormat (pScreen, 32, PICT_a8r8g8b8); + if (!pFormat) + return; + + pGC = GetScratchGC (pFormat->depth, pScreen); + if (!pGC) + return; + + pPixmap = (*pScreen->CreatePixmap) (pScreen, 1, 1, pFormat->depth); + if (!pPixmap) + return; + + miRenderColorToPixel (pFormat, &solidWhite, &pixel); + + tmpval[0] = GXcopy; + tmpval[1] = pixel; + + ChangeGC (pGC, GCFunction | GCForeground, tmpval); + ValidateGC (&pPixmap->drawable, pGC); + (*pGC->ops->PolyFillRect) (&pPixmap->drawable, pGC, 1, &one); + FreeScratchGC (pGC); + + tmpval[0] = xTrue; + pScreenPriv->pSolidAlpha = + CreatePicture (0, &pPixmap->drawable, pFormat, + CPRepeat, tmpval, 0, &error); + (*pScreen->DestroyPixmap) (pPixmap); + + if (pScreenPriv->pSolidAlpha) + ValidatePicture (pScreenPriv->pSolidAlpha); +} +#endif diff --git a/hw/xgl/xglsolid.c b/hw/xgl/xglsolid.c index 2892978e5..789c9dd12 100644 --- a/hw/xgl/xglsolid.c +++ b/hw/xgl/xglsolid.c @@ -5,7 +5,7 @@ * 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 names of + * appear in supporting documentation, and that the name of * David Reveman not be used in advertising or publicity pertaining to * distribution of the software without specific, written prior permission. * David Reveman makes no representations about the suitability of this @@ -20,16 +20,23 @@ * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * - * Author: David Reveman <davidr@freedesktop.org> + * Author: David Reveman <davidr@novell.com> */ #include "xgl.h" +#include "gcstruct.h" +#include "fontstruct.h" +#include "dixfontstr.h" Bool xglSolid (DrawablePtr pDrawable, glitz_operator_t op, glitz_color_t *color, xglGeometryPtr pGeometry, + int x, + int y, + int width, + int height, BoxPtr pBox, int nBox) { @@ -38,6 +45,9 @@ xglSolid (DrawablePtr pDrawable, XGL_SCREEN_PRIV (pDrawable->pScreen); + if (nBox < 1) + return TRUE; + if (!xglPrepareTarget (pDrawable)) return FALSE; @@ -45,26 +55,108 @@ xglSolid (DrawablePtr pDrawable, glitz_set_rectangle (pScreenPriv->solid, color, 0, 0, 1, 1); + if (pGeometry) + { + glitz_surface_set_clip_region (surface, xOff, yOff, + (glitz_box_t *) pBox, nBox); + } + else + { + pGeometry = xglGetScratchVertexGeometry (pDrawable->pScreen, 4 * nBox); + GEOMETRY_ADD_BOX (pDrawable->pScreen, pGeometry, pBox, nBox); + } + GEOMETRY_TRANSLATE (pGeometry, xOff, yOff); - if (!GEOMETRY_ENABLE_ALL_VERTICES (pGeometry, surface)) + if (!GEOMETRY_ENABLE (pGeometry, surface)) return FALSE; - - while (nBox--) - { - glitz_composite (op, - pScreenPriv->solid, NULL, surface, - 0, 0, - 0, 0, - pBox->x1 + xOff, - pBox->y1 + yOff, - pBox->x2 - pBox->x1, pBox->y2 - pBox->y1); - pBox++; - } + glitz_composite (op, + pScreenPriv->solid, NULL, surface, + 0, 0, + 0, 0, + x + xOff, + y + yOff, + width, height); + glitz_surface_set_clip_region (surface, 0, 0, NULL, 0); + if (glitz_surface_get_status (surface)) return FALSE; return TRUE; } + +Bool +xglSolidGlyph (DrawablePtr pDrawable, + GCPtr pGC, + int x, + int y, + unsigned int nGlyph, + CharInfoPtr *ppci, + pointer pglyphBase) +{ + xglGeometryRec geometry; + int xBack, widthBack; + int yBack, heightBack; + + XGL_GC_PRIV (pGC); + + x += pDrawable->x; + y += pDrawable->y; + + GEOMETRY_INIT (pDrawable->pScreen, &geometry, + GLITZ_GEOMETRY_TYPE_BITMAP, + GEOMETRY_USAGE_SYSMEM, 0); + + GEOMETRY_FOR_GLYPH (pDrawable->pScreen, + &geometry, + nGlyph, + ppci, + pglyphBase); + + GEOMETRY_TRANSLATE (&geometry, x, y); + + widthBack = 0; + while (nGlyph--) + widthBack += (*ppci++)->metrics.characterWidth; + + xBack = x; + if (widthBack < 0) + { + xBack += widthBack; + widthBack = -widthBack; + } + yBack = y - FONTASCENT (pGC->font); + heightBack = FONTASCENT (pGC->font) + FONTDESCENT (pGC->font); + + if (xglSolid (pDrawable, + pGCPriv->op, + &pGCPriv->bg, + NULL, + xBack, + yBack, + widthBack, + heightBack, + REGION_RECTS (pGC->pCompositeClip), + REGION_NUM_RECTS (pGC->pCompositeClip))) + { + if (xglSolid (pDrawable, + pGCPriv->op, + &pGCPriv->fg, + &geometry, + xBack, + yBack, + widthBack, + heightBack, + REGION_RECTS (pGC->pCompositeClip), + REGION_NUM_RECTS (pGC->pCompositeClip))) + { + GEOMETRY_UNINIT (&geometry); + return TRUE; + } + } + + GEOMETRY_UNINIT (&geometry); + return FALSE; +} diff --git a/hw/xgl/xglsync.c b/hw/xgl/xglsync.c index 2837a86a9..15d328aeb 100644 --- a/hw/xgl/xglsync.c +++ b/hw/xgl/xglsync.c @@ -5,7 +5,7 @@ * 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 names of + * appear in supporting documentation, and that the name of * David Reveman not be used in advertising or publicity pertaining to * distribution of the software without specific, written prior permission. * David Reveman makes no representations about the suitability of this @@ -20,7 +20,7 @@ * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * - * Author: David Reveman <davidr@freedesktop.org> + * Author: David Reveman <davidr@novell.com> */ #include "xgl.h" @@ -152,39 +152,56 @@ xglSyncBits (DrawablePtr pDrawable, if (!pPixmapPriv->buffer) if (!xglAllocatePixmapBits (pPixmap)) return FALSE; + + if (pPixmapPriv->pDamage) + { + RegionPtr pRegion; + + pRegion = DamageRegion (pPixmapPriv->pDamage); + REGION_SUBTRACT (pDrawable->pScreen, ®ion, ®ion, pRegion); + } - if (REGION_NOTEMPTY (pDrawable->pScreen, ®ion)) + if (REGION_NOTEMPTY (pDrawable->pScreen, ®ion) && pPixmapPriv->surface) { - if (pPixmapPriv->surface) - { - glitz_pixel_format_t format; - BoxPtr pBox; - int nBox; + glitz_pixel_format_t format; + BoxPtr pBox; + int nBox; + + if (!xglSyncSurface (pDrawable)) + FatalError (XGL_SW_FAILURE_STRING); - xglUnmapPixmapBits (pPixmap); + xglUnmapPixmapBits (pPixmap); - pBox = REGION_RECTS (®ion); - nBox = REGION_NUM_RECTS (®ion); + pBox = REGION_RECTS (®ion); + nBox = REGION_NUM_RECTS (®ion); - format.masks = pPixmapPriv->pPixel->masks; + format.masks = pPixmapPriv->pPixel->masks; + + if (pPixmapPriv->stride < 0) + { + format.bytes_per_line = -pPixmapPriv->stride; + format.scanline_order = GLITZ_PIXEL_SCANLINE_ORDER_BOTTOM_UP; + } + else + { format.bytes_per_line = pPixmapPriv->stride; - format.scanline_order = XGL_INTERNAL_SCANLINE_ORDER; - - while (nBox--) - { - format.xoffset = pBox->x1; - format.skip_lines = pBox->y1; - - glitz_get_pixels (pPixmapPriv->surface, - pBox->x1, - pBox->y1, - pBox->x2 - pBox->x1, - pBox->y2 - pBox->y1, - &format, - pPixmapPriv->buffer); - - pBox++; - } + format.scanline_order = GLITZ_PIXEL_SCANLINE_ORDER_TOP_DOWN; + } + + while (nBox--) + { + format.xoffset = pBox->x1; + format.skip_lines = pBox->y1; + + glitz_get_pixels (pPixmapPriv->surface, + pBox->x1, + pBox->y1, + pBox->x2 - pBox->x1, + pBox->y2 - pBox->y1, + &format, + pPixmapPriv->buffer); + + pBox++; } } @@ -234,16 +251,25 @@ xglSyncSurface (DrawablePtr pDrawable) nBox = REGION_NUM_RECTS (pRegion); pBox = REGION_RECTS (pRegion); + + format.masks = pPixmapPriv->pPixel->masks; - format.masks = pPixmapPriv->pPixel->masks; - format.bytes_per_line = pPixmapPriv->stride; - format.scanline_order = XGL_INTERNAL_SCANLINE_ORDER; + if (pPixmapPriv->stride < 0) + { + format.bytes_per_line = -pPixmapPriv->stride; + format.scanline_order = GLITZ_PIXEL_SCANLINE_ORDER_BOTTOM_UP; + } + else + { + format.bytes_per_line = pPixmapPriv->stride; + format.scanline_order = GLITZ_PIXEL_SCANLINE_ORDER_TOP_DOWN; + } while (nBox--) { format.xoffset = pBox->x1; format.skip_lines = pBox->y1; - + glitz_set_pixels (pPixmapPriv->surface, pBox->x1, pBox->y1, @@ -288,7 +314,34 @@ xglPrepareTarget (DrawablePtr pDrawable) } void -xglAddSurfaceDamage (DrawablePtr pDrawable) +xglAddSurfaceDamage (DrawablePtr pDrawable, + RegionPtr pRegion) +{ + RegionPtr pDamageRegion; + glitz_surface_t *surface; + int xOff, yOff; + + XGL_DRAWABLE_PIXMAP_PRIV (pDrawable); + + pPixmapPriv->damageBox = miEmptyBox; + if (!pPixmapPriv->format) + return; + + XGL_GET_DRAWABLE (pDrawable, surface, xOff, yOff); + + if (xOff || yOff) + REGION_TRANSLATE (pDrawable->pScreen, pRegion, xOff, yOff); + + pDamageRegion = DamageRegion (pPixmapPriv->pDamage); + + REGION_UNION (pDrawable->pScreen, pDamageRegion, pDamageRegion, pRegion); + + if (xOff || yOff) + REGION_TRANSLATE (pDrawable->pScreen, pRegion, -xOff, -yOff); +} + +void +xglAddCurrentSurfaceDamage (DrawablePtr pDrawable) { XGL_DRAWABLE_PIXMAP_PRIV (pDrawable); @@ -310,18 +363,12 @@ xglAddSurfaceDamage (DrawablePtr pDrawable) pDamageRegion, pDamageRegion, ®ion); REGION_UNINIT (pDrawable->pScreen, ®ion); - if (pPixmapPriv->target == xglPixmapTargetIn) - { - if (!xglSyncSurface (pDrawable)) - FatalError (XGL_SW_FAILURE_STRING); - } - pPixmapPriv->damageBox = miEmptyBox; } } void -xglAddBitDamage (DrawablePtr pDrawable) +xglAddCurrentBitDamage (DrawablePtr pDrawable) { XGL_DRAWABLE_PIXMAP_PRIV (pDrawable); diff --git a/hw/xgl/xgltile.c b/hw/xgl/xgltile.c index 60840ae66..d2a440f92 100644 --- a/hw/xgl/xgltile.c +++ b/hw/xgl/xgltile.c @@ -5,7 +5,7 @@ * 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 names of + * appear in supporting documentation, and that the name of * David Reveman not be used in advertising or publicity pertaining to * distribution of the software without specific, written prior permission. * David Reveman makes no representations about the suitability of this @@ -20,11 +20,146 @@ * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * - * Author: David Reveman <davidr@freedesktop.org> + * Author: David Reveman <davidr@novell.com> */ #include "xgl.h" +static glitz_geometry_format_t tileGeometryFormat = { + { + GLITZ_PRIMITIVE_QUADS, + GLITZ_DATA_TYPE_FLOAT, + sizeof (glitz_float_t) * 4, + GLITZ_VERTEX_ATTRIBUTE_SRC_COORD_MASK, { + GLITZ_DATA_TYPE_FLOAT, + GLITZ_COORDINATE_SIZE_XY, + sizeof (glitz_float_t) * 2, + }, { + 0, 0, 0 + } + } +}; + +xglGeometryPtr +xglTiledBoxGeometry (PixmapPtr pTile, + int tileX, + int tileY, + BoxPtr pBox, + int nBox) +{ + ScreenPtr pScreen = pTile->drawable.pScreen; + glitz_point_fixed_t p1, p2; + xglGeometryPtr pGeometry; + glitz_float_t x1, x2, y1, y2; + int x, y, width, height, i; + int xTile, yTile; + int widthTile, heightTile; + int widthTmp, xTmp, yTmp, xTileTmp; + int tileWidth, tileHeight; + int size = 0; + glitz_float_t *data; + + XGL_PIXMAP_PRIV (pTile); + + tileWidth = pTile->drawable.width; + tileHeight = pTile->drawable.height; + + for (i = 0; i < nBox; i++) + size += + (((pBox[i].x2 - pBox[i].x1) / tileWidth) + 2) * + (((pBox[i].y2 - pBox[i].y1) / tileHeight) + 2); + + pGeometry = xglGetScratchVertexGeometryWithType (pScreen, + GEOMETRY_DATA_TYPE_FLOAT, + 8 * size); + + data = glitz_buffer_map (pGeometry->buffer, + GLITZ_BUFFER_ACCESS_WRITE_ONLY); + + while (nBox--) + { + x = pBox->x1; + y = pBox->y1; + width = pBox->x2 - pBox->x1; + height = pBox->y2 - pBox->y1; + + xTile = MOD (tileX + x, tileWidth); + yTile = MOD (tileY + y, tileHeight); + + yTmp = y; + + while (height) + { + heightTile = MIN (tileHeight - yTile, height); + + xTileTmp = xTile; + widthTmp = width; + xTmp = x; + + while (widthTmp) + { + widthTile = MIN (tileWidth - xTileTmp, widthTmp); + + p1.x = xTileTmp << 16; + p1.y = yTile << 16; + p2.x = (xTileTmp + widthTile) << 16; + p2.y = (yTile + heightTile) << 16; + + glitz_surface_translate_point (pPixmapPriv->surface, &p1, &p1); + glitz_surface_translate_point (pPixmapPriv->surface, &p2, &p2); + + x1 = FIXED_TO_FLOAT (p1.x); + y1 = FIXED_TO_FLOAT (p1.y); + x2 = FIXED_TO_FLOAT (p2.x); + y2 = FIXED_TO_FLOAT (p2.y); + + *data++ = (glitz_float_t) xTmp; + *data++ = (glitz_float_t) yTmp; + *data++ = x1; + *data++ = y1; + + *data++ = (glitz_float_t) (xTmp + widthTile); + *data++ = (glitz_float_t) yTmp; + *data++ = x2; + *data++ = y1; + + *data++ = (glitz_float_t) (xTmp + widthTile); + *data++ = (glitz_float_t) (yTmp + heightTile); + *data++ = x2; + *data++ = y2; + + *data++ = (glitz_float_t) xTmp; + *data++ = (glitz_float_t) (yTmp + heightTile); + *data++ = x1; + *data++ = y2; + + pGeometry->endOffset += sizeof (glitz_float_t) * 16; + + xTileTmp = 0; + xTmp += widthTile; + widthTmp -= widthTile; + } + + yTile = 0; + yTmp += heightTile; + height -= heightTile; + } + + pBox++; + } + + if (glitz_buffer_unmap (pGeometry->buffer)) + return NULL; + + pGeometry->f = tileGeometryFormat; + pGeometry->count = + pGeometry->endOffset / tileGeometryFormat.vertex.bytes_per_vertex; + + pPixmapPriv->pictureMask |= xglPCFillMask; + glitz_surface_set_fill (pPixmapPriv->surface, GLITZ_FILL_TRANSPARENT); + + return pGeometry; +} Bool xglTile (DrawablePtr pDrawable, @@ -33,6 +168,10 @@ xglTile (DrawablePtr pDrawable, int tileX, int tileY, xglGeometryPtr pGeometry, + int x, + int y, + int width, + int height, BoxPtr pBox, int nBox) { @@ -40,161 +179,90 @@ xglTile (DrawablePtr pDrawable, glitz_surface_t *surface; int xOff, yOff; - if (!xglSyncSurface (&pTile->drawable)) - return FALSE; + if (nBox < 1) + return TRUE; if (!xglPrepareTarget (pDrawable)) return FALSE; - - XGL_GET_DRAWABLE (pDrawable, surface, xOff, yOff); - GEOMETRY_TRANSLATE (pGeometry, xOff, yOff); - - if (!GEOMETRY_ENABLE_ALL_VERTICES (pGeometry, surface)) + if (!xglSyncSurface (&pTile->drawable)) return FALSE; + XGL_GET_DRAWABLE (pDrawable, surface, xOff, yOff); + pTilePriv = XGL_GET_PIXMAP_PRIV (pTile); - pTilePriv->pictureMask |= - xglPCFillMask | xglPCFilterMask | xglPCTransformMask; - - glitz_surface_set_filter (pTilePriv->surface, GLITZ_FILTER_NEAREST, + pTilePriv->pictureMask |= xglPCFilterMask | xglPCTransformMask; + glitz_surface_set_filter (pTilePriv->surface, + GLITZ_FILTER_NEAREST, NULL, 0); glitz_surface_set_transform (pTilePriv->surface, NULL); if (pTilePriv->acceleratedTile) { - glitz_surface_set_fill (pTilePriv->surface, GLITZ_FILL_REPEAT); - - while (nBox--) + if (pGeometry) { - glitz_composite (op, - pTilePriv->surface, NULL, surface, - pBox->x1 + tileX, - pBox->y1 + tileY, - 0, 0, - pBox->x1 + xOff, - pBox->y1 + yOff, - pBox->x2 - pBox->x1, pBox->y2 - pBox->y1); - - pBox++; + glitz_surface_set_clip_region (surface, xOff, yOff, + (glitz_box_t *) pBox, nBox); + nBox = 0; + } + else + { + pGeometry = xglGetScratchVertexGeometry (pDrawable->pScreen, + 4 * nBox); + GEOMETRY_ADD_BOX (pDrawable->pScreen, pGeometry, pBox, nBox); } - if (!glitz_surface_get_status (surface)) - return TRUE; - } + GEOMETRY_TRANSLATE (pGeometry, xOff, yOff); - glitz_surface_set_fill (pTilePriv->surface, GLITZ_FILL_TRANSPARENT); + if (!GEOMETRY_ENABLE (pGeometry, surface)) + return FALSE; - /* - * Don't allow software tile with really small pixmaps. - */ - if (pTile->drawable.width < 8 && pTile->drawable.height < 8) - return FALSE; - - xglSwTile (op, - pTilePriv->surface, NULL, surface, - tileX - xOff, tileY - yOff, - 0, 0, - TILE_SOURCE, - pBox, nBox, - xOff, yOff); + pTilePriv->pictureMask |= xglPCFillMask; + glitz_surface_set_fill (pTilePriv->surface, GLITZ_FILL_REPEAT); - if (glitz_surface_get_status (surface)) - return FALSE; + glitz_composite (op, + pTilePriv->surface, NULL, surface, + x + tileX, + y + tileY, + 0, 0, + x + xOff, + y + yOff, + width, height); - return TRUE; -} + glitz_surface_set_clip_region (surface, 0, 0, NULL, 0); + + if (!glitz_surface_get_status (surface)) + return TRUE; -void -xglSwTile (glitz_operator_t op, - glitz_surface_t *srcSurface, - glitz_surface_t *maskSurface, - glitz_surface_t *dstSurface, - int xSrc, - int ySrc, - int xMask, - int yMask, - int what, - BoxPtr pBox, - int nBox, - int xOff, - int yOff) -{ - int tileX, tileY; - int tileWidth, tileHeight; - - if (what == TILE_MASK) { - tileX = xMask; - tileY = yMask; - tileWidth = glitz_surface_get_width (maskSurface); - tileHeight = glitz_surface_get_height (maskSurface); - } else { - tileX = xSrc; - tileY = ySrc; - tileWidth = glitz_surface_get_width (srcSurface); - tileHeight = glitz_surface_get_height (srcSurface); + if (!nBox) + return FALSE; } - - while (nBox--) + else { - int x, y, width, height; - int xTile, yTile; - int widthTile, heightTile; - int widthTmp, xTmp, yTmp, xTileTmp; - - x = pBox->x1 + xOff; - y = pBox->y1 + yOff; - width = pBox->x2 - pBox->x1; - height = pBox->y2 - pBox->y1; - - xTile = MOD (tileX + x, tileWidth); - yTile = MOD (tileY + y, tileHeight); - - yTmp = y; - - while (height) - { - heightTile = MIN (tileHeight - yTile, height); - - xTileTmp = xTile; - widthTmp = width; - xTmp = x; - - while (widthTmp) - { - widthTile = MIN (tileWidth - xTileTmp, widthTmp); + if (pGeometry) + return FALSE; + } - if (what == TILE_MASK) - { - glitz_composite (op, - srcSurface, maskSurface, dstSurface, - xSrc + xTmp, ySrc + yTmp, - xTileTmp, yTile, - xTmp, yTmp, - widthTile, heightTile); - } - else - { - glitz_composite (op, - srcSurface, maskSurface, dstSurface, - xTileTmp, yTile, - xMask + xTmp, yMask + yTmp, - xTmp, yTmp, - widthTile, heightTile); - } - - xTileTmp = 0; - xTmp += widthTile; - widthTmp -= widthTile; - - } + pGeometry = xglTiledBoxGeometry (pTile, tileX, tileY, pBox, nBox); + if (!pGeometry) + return FALSE; - yTile = 0; - yTmp += heightTile; - height -= heightTile; - } - - pBox++; - } + GEOMETRY_TRANSLATE (pGeometry, xOff, yOff); + + if (!GEOMETRY_ENABLE (pGeometry, surface)) + return FALSE; + + glitz_composite (op, + pTilePriv->surface, NULL, surface, + 0, 0, + 0, 0, + x + xOff, + y + yOff, + width, height); + + if (glitz_surface_get_status (surface)) + return FALSE; + + return TRUE; } diff --git a/hw/xgl/xgltrap.c b/hw/xgl/xgltrap.c new file mode 100644 index 000000000..723a43225 --- /dev/null +++ b/hw/xgl/xgltrap.c @@ -0,0 +1,520 @@ +/* + * Copyright © 2005 Novell, 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 + * Novell, Inc. not be used in advertising or publicity pertaining to + * distribution of the software without specific, written prior permission. + * Novell, Inc. makes no representations about the suitability of this + * software for any purpose. It is provided "as is" without express or + * implied warranty. + * + * NOVELL, INC. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN + * NO EVENT SHALL NOVELL, INC. BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS + * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, + * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION + * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Author: David Reveman <davidr@novell.com> + */ + +#include "xgl.h" +#include "gcstruct.h" +#include "damage.h" + +#ifdef RENDER + +#define XGL_TRAP_FALLBACK_PROLOGUE(pPicture, func) \ + xglSyncDamageBoxBits (pPicture->pDrawable); \ + XGL_PICTURE_SCREEN_UNWRAP (func) + +#define XGL_TRAP_FALLBACK_EPILOGUE(pPicture, func, xglfunc) \ + XGL_PICTURE_SCREEN_WRAP (func, xglfunc); \ + xglAddCurrentSurfaceDamage (pPicture->pDrawable) + +/* just a guess */ +#define SMOOTH_TRAPS_ESTIMATE_RECTS(nTrap) (30 * nTrap) + +static PicturePtr +xglCreateMaskPicture (ScreenPtr pScreen, + PicturePtr pDst, + PictFormatPtr pPictFormat, + CARD16 width, + CARD16 height, + Bool accelerate) +{ + PixmapPtr pPixmap; + PicturePtr pPicture; + GCPtr pGC; + int error; + xRectangle rect; + + if (width > 32767 || height > 32767) + return 0; + + pPixmap = (*pScreen->CreatePixmap) (pScreen, width, height, + pPictFormat->depth); + if (!pPixmap) + return 0; + + if (!accelerate) + { + XGL_PIXMAP_PRIV (pPixmap); + + if (!xglAllocatePixmapBits (pPixmap)) + { + (*pScreen->DestroyPixmap) (pPixmap); + return 0; + } + + pPixmapPriv->target = xglPixmapTargetNo; + + /* force negative stride + if (pPixmapPriv->stride > 0) + pPixmapPriv->stride = -pPixmapPriv->stride; + */ + } + + pGC = GetScratchGC (pPixmap->drawable.depth, pScreen); + if (!pGC) + { + (*pScreen->DestroyPixmap) (pPixmap); + return 0; + } + + rect.x = 0; + rect.y = 0; + rect.width = width; + rect.height = height; + + ValidateGC (&pPixmap->drawable, pGC); + (*pGC->ops->PolyFillRect) (&pPixmap->drawable, pGC, 1, &rect); + FreeScratchGC (pGC); + + pPicture = CreatePicture (0, &pPixmap->drawable, pPictFormat, + 0, 0, serverClient, &error); + (*pScreen->DestroyPixmap) (pPixmap); + + return pPicture; +} + +#define LINE_FIXED_X(l, _y, v) \ + dx = (l)->p2.x - (l)->p1.x; \ + ex = (xFixed_32_32) ((_y) - (l)->p1.y) * dx; \ + dy = (l)->p2.y - (l)->p1.y; \ + (v) = (l)->p1.x + (xFixed) (ex / dy) + +#define LINE_FIXED_X_CEIL(l, _y, v) \ + dx = (l)->p2.x - (l)->p1.x; \ + ex = (xFixed_32_32) ((_y) - (l)->p1.y) * dx; \ + dy = (l)->p2.y - (l)->p1.y; \ + (v) = (l)->p1.x + (xFixed) ((ex + (dy - 1)) / dy) + +static Bool +xglTrapezoidBounds (int ntrap, + xTrapezoid *traps, + BoxPtr box) +{ + Bool x_overlap, overlap = FALSE; + xFixed dx, dy, top, bottom; + xFixed_32_32 ex; + + if (!ntrap) + { + box->x1 = MAXSHORT; + box->x2 = MINSHORT; + box->y1 = MAXSHORT; + box->y2 = MINSHORT; + + return FALSE; + } + + box->y1 = xFixedToInt (traps->top); + box->y2 = xFixedToInt (xFixedCeil (traps->bottom)); + + LINE_FIXED_X (&traps->left, traps->top, top); + LINE_FIXED_X (&traps->left, traps->bottom, bottom); + box->x1 = xFixedToInt (MIN (top, bottom)); + + LINE_FIXED_X_CEIL (&traps->right, traps->top, top); + LINE_FIXED_X_CEIL (&traps->right, traps->bottom, bottom); + box->x2 = xFixedToInt (xFixedCeil (MAX (top, bottom))); + + ntrap--; + traps++; + + for (; ntrap; ntrap--, traps++) + { + INT16 x1, y1, x2, y2; + + if (!xTrapezoidValid (traps)) + continue; + + y1 = xFixedToInt (traps->top); + y2 = xFixedToInt (xFixedCeil (traps->bottom)); + + LINE_FIXED_X (&traps->left, traps->top, top); + LINE_FIXED_X (&traps->left, traps->bottom, bottom); + x1 = xFixedToInt (MIN (top, bottom)); + + LINE_FIXED_X_CEIL (&traps->right, traps->top, top); + LINE_FIXED_X_CEIL (&traps->right, traps->bottom, bottom); + x2 = xFixedToInt (xFixedCeil (MAX (top, bottom))); + + x_overlap = FALSE; + if (x1 >= box->x2) + box->x2 = x2; + else if (x2 <= box->x1) + box->x1 = x1; + else + { + x_overlap = TRUE; + if (x1 < box->x1) + box->x1 = x1; + if (x2 > box->x2) + box->x2 = x2; + } + + if (y1 >= box->y2) + box->y2 = y2; + else if (y2 <= box->y1) + box->y1 = y1; + else + { + if (y1 < box->y1) + box->y1 = y1; + if (y2 > box->y2) + box->y2 = y2; + + if (x_overlap) + overlap = TRUE; + } + } + + return overlap; +} + +void +xglTrapezoids (CARD8 op, + PicturePtr pSrc, + PicturePtr pDst, + PictFormatPtr maskFormat, + INT16 xSrc, + INT16 ySrc, + int nTrap, + xTrapezoid *traps) +{ + ScreenPtr pScreen = pDst->pDrawable->pScreen; + PicturePtr pMask = NULL, pSrcPicture, pDstPicture; + xglGeometryPtr pGeometry = NULL; + glitz_surface_t *mask = NULL; + unsigned int polyEdge = pDst->polyEdge; + INT16 xDst, yDst; + INT16 xOff, yOff; + BoxRec bounds; + Bool overlap; + + XGL_SCREEN_PRIV (pScreen); + + xDst = traps[0].left.p1.x >> 16; + yDst = traps[0].left.p1.y >> 16; + + overlap = xglTrapezoidBounds (nTrap, traps, &bounds); + if (bounds.y1 >= bounds.y2 || bounds.x1 >= bounds.x2) + return; + + if (nTrap > 1 && op != PictOpAdd && maskFormat && + (overlap || op != PictOpOver)) + { + xglPixmapPtr pPixmapPriv; + int width, height; + Bool accelerate; + + if (!pScreenPriv->pSolidAlpha) + { + xglCreateSolidAlphaPicture (pScreen); + if (!pScreenPriv->pSolidAlpha) + return; + } + + accelerate = TRUE; + width = bounds.x2 - bounds.x1; + height = bounds.y2 - bounds.y1; + if (maskFormat->depth > 1) + { + /* Avoid acceleration if the estimated amount of vertex data + is likely to exceed the size of the mask. */ + if ((SMOOTH_TRAPS_ESTIMATE_RECTS (nTrap) * 4) > (width * height)) + accelerate = FALSE; + + accelerate = FALSE; + } + + pMask = xglCreateMaskPicture (pScreen, pDst, maskFormat, + width, height, accelerate); + if (!pMask) + return; + + ValidatePicture (pMask); + + /* all will be damaged */ + pPixmapPriv = XGL_GET_DRAWABLE_PIXMAP_PRIV (pMask->pDrawable); + pPixmapPriv->damageBox.x1 = 0; + pPixmapPriv->damageBox.y1 = 0; + pPixmapPriv->damageBox.x2 = pMask->pDrawable->width; + pPixmapPriv->damageBox.y2 = pMask->pDrawable->height; + + xOff = -bounds.x1; + yOff = -bounds.y1; + pSrcPicture = pScreenPriv->pSolidAlpha; + pDstPicture = pMask; + } + else + { + if (maskFormat) + { + if (maskFormat->depth == 1) + polyEdge = PolyEdgeSharp; + else + polyEdge = PolyEdgeSmooth; + } + + xOff = 0; + yOff = 0; + pSrcPicture = pSrc; + pDstPicture = pDst; + } + + if (xglPrepareTarget (pDstPicture->pDrawable)) + { + if (maskFormat || polyEdge == PolyEdgeSmooth) + { + glitz_vertex_format_t *format; + xTrapezoid *pTrap = traps; + int nAddedTrap, n = nTrap; + int offset = 0; + int size = SMOOTH_TRAPS_ESTIMATE_RECTS (n); + + mask = pScreenPriv->trapInfo.mask; + format = &pScreenPriv->trapInfo.format.vertex; + + size *= format->bytes_per_vertex; + pGeometry = xglGetScratchGeometryWithSize (pScreen, size); + + while (n) + { + if (pGeometry->size < size) + GEOMETRY_RESIZE (pScreen, pGeometry, size); + + if (!pGeometry->buffer) + { + if (pMask) + FreePicture (pMask, 0); + + return; + } + + offset += + glitz_add_trapezoids (pGeometry->buffer, + offset, size - offset, format->type, + mask, (glitz_trapezoid_t *) pTrap, n, + &nAddedTrap); + + n -= nAddedTrap; + pTrap += nAddedTrap; + size *= 2; + } + + pGeometry->f = pScreenPriv->trapInfo.format; + pGeometry->count = offset / format->bytes_per_vertex; + } + else + { + pGeometry = + xglGetScratchVertexGeometryWithType (pScreen, + GEOMETRY_DATA_TYPE_FLOAT, + 4 * nTrap); + if (!pGeometry->buffer) + { + if (pMask) + FreePicture (pMask, 0); + + return; + } + + GEOMETRY_ADD_TRAPEZOID (pScreen, pGeometry, traps, nTrap); + } + + GEOMETRY_TRANSLATE (pGeometry, + pDstPicture->pDrawable->x + xOff, + pDstPicture->pDrawable->y + yOff); + } + + if (pGeometry && + xglComp (pMask ? PictOpAdd : op, + pSrcPicture, + NULL, + pDstPicture, + bounds.x1 + xOff + xSrc - xDst, + bounds.y1 + yOff + ySrc - yDst, + 0, 0, + pDstPicture->pDrawable->x + bounds.x1 + xOff, + pDstPicture->pDrawable->y + bounds.y1 + yOff, + bounds.x2 - bounds.x1, + bounds.y2 - bounds.y1, + pGeometry, + mask)) + { + /* no intermediate mask? we need to register damage from here as + CompositePicture will never be called. */ + if (!pMask) + { + RegionRec region; + + REGION_INIT (pScreen, ®ion, &bounds, 1); + REGION_TRANSLATE (pScreen, ®ion, + pDst->pDrawable->x, pDst->pDrawable->y); + + DamageDamageRegion (pDst->pDrawable, ®ion); + + REGION_UNINIT (pScreen, ®ion); + } + + xglAddCurrentBitDamage (pDstPicture->pDrawable); + } + else + { + XGL_DRAWABLE_PIXMAP_PRIV (pDstPicture->pDrawable); + + pPixmapPriv->damageBox.x1 = bounds.x1 + xOff; + pPixmapPriv->damageBox.y1 = bounds.y1 + yOff; + pPixmapPriv->damageBox.x2 = bounds.x2 + xOff; + pPixmapPriv->damageBox.y2 = bounds.y2 + yOff; + + xglSyncDamageBoxBits (pDstPicture->pDrawable); + + if (pMask || (polyEdge == PolyEdgeSmooth && + op == PictOpAdd && miIsSolidAlpha (pSrc))) + { + PictureScreenPtr ps = GetPictureScreen (pScreen); + + for (; nTrap; nTrap--, traps++) + (*ps->RasterizeTrapezoid) (pDstPicture, traps, xOff, yOff); + + xglAddCurrentSurfaceDamage (pDstPicture->pDrawable); + } else + miTrapezoids (op, pSrc, pDstPicture, NULL, + xSrc, ySrc, nTrap, traps); + } + + if (pMask) + { + xglLeaveOffscreenArea ((PixmapPtr) pMask->pDrawable); + + CompositePicture (op, pSrc, pMask, pDst, + bounds.x1 + xSrc - xDst, + bounds.y1 + ySrc - yDst, + 0, 0, + bounds.x1, bounds.y1, + bounds.x2 - bounds.x1, + bounds.y2 - bounds.y1); + + FreePicture (pMask, 0); + } +} + +void +xglAddTraps (PicturePtr pDst, + INT16 xOff, + INT16 yOff, + int nTrap, + xTrap *traps) +{ + PictureScreenPtr pPictureScreen; + ScreenPtr pScreen = pDst->pDrawable->pScreen; + + XGL_SCREEN_PRIV (pScreen); + XGL_DRAWABLE_PIXMAP_PRIV (pDst->pDrawable); + + if (!pScreenPriv->pSolidAlpha) + { + xglCreateSolidAlphaPicture (pScreen); + if (!pScreenPriv->pSolidAlpha) + return; + } + + pPixmapPriv->damageBox.x1 = 0; + pPixmapPriv->damageBox.y1 = 0; + pPixmapPriv->damageBox.x2 = pDst->pDrawable->width; + pPixmapPriv->damageBox.y2 = pDst->pDrawable->height; + + if (xglPrepareTarget (pDst->pDrawable)) + { + glitz_vertex_format_t *format; + xglGeometryPtr pGeometry; + xTrap *pTrap = traps; + int nAddedTrap, n = nTrap; + int offset = 0; + int size = SMOOTH_TRAPS_ESTIMATE_RECTS (n); + + format = &pScreenPriv->trapInfo.format.vertex; + + size *= format->bytes_per_vertex; + pGeometry = xglGetScratchGeometryWithSize (pScreen, size); + + while (n) + { + if (pGeometry->size < size) + GEOMETRY_RESIZE (pScreen, pGeometry, size); + + if (!pGeometry->buffer) + return; + + offset += + glitz_add_traps (pGeometry->buffer, + offset, size - offset, format->type, + pScreenPriv->trapInfo.mask, + (glitz_trap_t *) pTrap, n, + &nAddedTrap); + + n -= nAddedTrap; + pTrap += nAddedTrap; + size *= 2; + } + + pGeometry->f = pScreenPriv->trapInfo.format; + pGeometry->count = offset / format->bytes_per_vertex; + + GEOMETRY_TRANSLATE (pGeometry, + pDst->pDrawable->x + xOff, + pDst->pDrawable->y + yOff); + + if (xglComp (PictOpAdd, + pScreenPriv->pSolidAlpha, + NULL, + pDst, + 0, 0, + 0, 0, + pDst->pDrawable->x, pDst->pDrawable->y, + pDst->pDrawable->width, pDst->pDrawable->height, + pGeometry, + pScreenPriv->trapInfo.mask)) + { + xglAddCurrentBitDamage (pDst->pDrawable); + return; + } + } + + pPictureScreen = GetPictureScreen (pScreen); + + XGL_TRAP_FALLBACK_PROLOGUE (pDst, AddTraps); + (*pPictureScreen->AddTraps) (pDst, xOff, yOff, nTrap, traps); + XGL_TRAP_FALLBACK_EPILOGUE (pDst, AddTraps, xglAddTraps); +} + +#endif diff --git a/hw/xgl/xglwindow.c b/hw/xgl/xglwindow.c index 361a204f5..2a4bb9ae1 100644 --- a/hw/xgl/xglwindow.c +++ b/hw/xgl/xglwindow.c @@ -5,7 +5,7 @@ * 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 names of + * appear in supporting documentation, and that the name of * David Reveman not be used in advertising or publicity pertaining to * distribution of the software without specific, written prior permission. * David Reveman makes no representations about the suitability of this @@ -20,19 +20,20 @@ * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * - * Author: David Reveman <davidr@freedesktop.org> + * Author: David Reveman <davidr@novell.com> */ #include "xgl.h" #include "fb.h" -#define XGL_WINDOW_FALLBACK_PROLOGUE(pWin, func) \ - xglSyncDamageBoxBits (&pWin->drawable); \ +#define XGL_WINDOW_FALLBACK_PROLOGUE(pWin, func) \ + if (!xglMapPixmapBits (XGL_GET_DRAWABLE_PIXMAP (&pWin->drawable))) \ + FatalError (XGL_SW_FAILURE_STRING); \ XGL_SCREEN_UNWRAP (func) -#define XGL_WINDOW_FALLBACK_EPILOGUE(pWin, func, xglfunc) \ - XGL_SCREEN_WRAP (func, xglfunc); \ - xglAddSurfaceDamage (&pWin->drawable) +#define XGL_WINDOW_FALLBACK_EPILOGUE(pWin, pRegion, func, xglfunc) \ + XGL_SCREEN_WRAP (func, xglfunc); \ + xglAddSurfaceDamage (&pWin->drawable, pRegion) Bool xglCreateWindow (WindowPtr pWin) @@ -52,96 +53,119 @@ xglCreateWindow (WindowPtr pWin) return ret; } -void -xglCopyWindow (WindowPtr pWin, - DDXPointRec ptOldOrg, - RegionPtr prgnSrc) +Bool +xglChangeWindowAttributes (WindowPtr pWin, + unsigned long mask) { ScreenPtr pScreen = pWin->drawable.pScreen; - + PixmapPtr pPixmap; + Bool ret; + XGL_SCREEN_PRIV (pScreen); - - if (XGL_GET_DRAWABLE_PIXMAP_PRIV (&pWin->drawable)->target) + + if (mask & CWBackPixmap) { - PixmapPtr pPixmap; - RegionRec rgnDst; - int dx, dy; - Bool ret; + if (pWin->backgroundState == BackgroundPixmap) + { + pPixmap = pWin->background.pixmap; - pPixmap = XGL_GET_WINDOW_PIXMAP (pWin); - - dx = ptOldOrg.x - pWin->drawable.x; - dy = ptOldOrg.y - pWin->drawable.y; + if (FbEvenTile (pPixmap->drawable.width * + pPixmap->drawable.bitsPerPixel)) + xglSyncBits (&pPixmap->drawable, NULL); + } + } - REGION_TRANSLATE (pScreen, prgnSrc, -dx, -dy); - REGION_INIT (pScreen, &rgnDst, NullBox, 0); - REGION_INTERSECT (pScreen, &rgnDst, &pWin->borderClip, prgnSrc); - -#ifdef COMPOSITE - if (pPixmap->screen_x || pPixmap->screen_y) - REGION_TRANSLATE (pWin->drawable.pScreen, &rgnDst, - -pPixmap->screen_x, -pPixmap->screen_y); -#endif - - ret = TRUE; - fbCopyRegion (&pWin->drawable, &pWin->drawable, - 0, &rgnDst, dx, dy, xglCopyProc, 0, (void *) &ret); - - REGION_UNINIT (pScreen, &rgnDst); - - if (ret) + if (mask & CWBorderPixmap) + { + if (pWin->borderIsPixel == FALSE) { - xglAddBitDamage (&pWin->drawable); - return; + pPixmap = pWin->border.pixmap; + + if (FbEvenTile (pPixmap->drawable.width * + pPixmap->drawable.bitsPerPixel)) + xglSyncBits (&pPixmap->drawable, NULL); } + } -#ifdef COMPOSITE - if (pPixmap->screen_x || pPixmap->screen_y) - REGION_TRANSLATE (pWin->drawable.pScreen, &rgnDst, - pPixmap->screen_x, pPixmap->screen_y); -#endif + XGL_SCREEN_UNWRAP (ChangeWindowAttributes); + ret = (*pScreen->ChangeWindowAttributes) (pWin, mask); + XGL_SCREEN_WRAP (ChangeWindowAttributes, xglChangeWindowAttributes); + + return ret; +} + +void +xglCopyWindow (WindowPtr pWin, + DDXPointRec ptOldOrg, + RegionPtr prgnSrc) +{ + PixmapPtr pPixmap; + RegionRec rgnDst; + int dx, dy; + BoxPtr pExtent = REGION_EXTENTS (pWin->drawable.pScreen, prgnSrc); + BoxRec box; + + pPixmap = XGL_GET_WINDOW_PIXMAP (pWin); + + box.x1 = pWin->drawable.x + pExtent->x1; + box.y1 = pWin->drawable.y + pExtent->y1; + box.x2 = pWin->drawable.x + pExtent->x2; + box.y2 = pWin->drawable.y + pExtent->y2; - REGION_TRANSLATE (pScreen, prgnSrc, dx, dy); - } + dx = ptOldOrg.x - pWin->drawable.x; + dy = ptOldOrg.y - pWin->drawable.y; + + REGION_TRANSLATE (pWin->drawable.pScreen, prgnSrc, -dx, -dy); + REGION_INIT (pWin->drawable.pScreen, &rgnDst, NullBox, 0); + REGION_INTERSECT (pWin->drawable.pScreen, + &rgnDst, &pWin->borderClip, prgnSrc); - if (!xglSyncBits (&pWin->drawable, NullBox)) - FatalError (XGL_SW_FAILURE_STRING); +#ifdef COMPOSITE + if (pPixmap->screen_x || pPixmap->screen_y) + { + REGION_TRANSLATE (pWin->drawable.pScreen, &rgnDst, + -pPixmap->screen_x, -pPixmap->screen_y); - XGL_WINDOW_FALLBACK_PROLOGUE (pWin, CopyWindow); - (*pScreen->CopyWindow) (pWin, ptOldOrg, prgnSrc); - XGL_WINDOW_FALLBACK_EPILOGUE (pWin, CopyWindow, xglCopyWindow); + box.x1 -= pPixmap->screen_x; + box.y1 -= pPixmap->screen_y; + box.x2 -= pPixmap->screen_x; + box.y2 -= pPixmap->screen_y; + } +#endif + + fbCopyRegion (&pWin->drawable, &pWin->drawable, + 0, &rgnDst, dx, dy, xglCopyProc, 0, (void *) &box); + + REGION_UNINIT (pWin->drawable.pScreen, &rgnDst); } static Bool -xglFillRegionSolid (DrawablePtr pDrawable, - RegionPtr pRegion, - Pixel pixel) +xglFillRegionSolid (DrawablePtr pDrawable, + RegionPtr pRegion, + Pixel pixel) { - ScreenPtr pScreen = pDrawable->pScreen; - xglGeometryRec geometry; - glitz_color_t color; + glitz_color_t color; + BoxPtr pExtent; XGL_DRAWABLE_PIXMAP_PRIV (pDrawable); if (!pPixmapPriv->target) return FALSE; - xglPixelToColor (pPixmapPriv->pPixel, pixel, &color); + pExtent = REGION_EXTENTS (pDrawable->pScreen, pRegion); - GEOMETRY_INIT (pScreen, &geometry, REGION_NUM_RECTS (pRegion) << 3); - GEOMETRY_ADD_REGION (pScreen, &geometry, pRegion); + xglPixelToColor (pPixmapPriv->pPixel, pixel, &color); if (xglSolid (pDrawable, GLITZ_OPERATOR_SRC, &color, - &geometry, - REGION_EXTENTS (pScreen, pRegion), 1)) - { - GEOMETRY_UNINIT (&geometry); + NULL, + pExtent->x1, pExtent->y1, + pExtent->x2 - pExtent->x1, pExtent->y2 - pExtent->y1, + REGION_RECTS (pRegion), + REGION_NUM_RECTS (pRegion))) return TRUE; - } - GEOMETRY_UNINIT (&geometry); return FALSE; } @@ -152,27 +176,26 @@ xglFillRegionTiled (DrawablePtr pDrawable, int tileX, int tileY) { - ScreenPtr pScreen = pDrawable->pScreen; - xglGeometryRec geometry; + BoxPtr pExtent; + + XGL_DRAWABLE_PIXMAP_PRIV (pDrawable); - if (!XGL_GET_DRAWABLE_PIXMAP_PRIV (pDrawable)->target) + if (!pPixmapPriv->target) return FALSE; - GEOMETRY_INIT (pScreen, &geometry, REGION_NUM_RECTS (pRegion) << 3); - GEOMETRY_ADD_REGION (pScreen, &geometry, pRegion); + pExtent = REGION_EXTENTS (pDrawable->pScreen, pRegion); if (xglTile (pDrawable, GLITZ_OPERATOR_SRC, pTile, tileX, tileY, - &geometry, - REGION_EXTENTS (pScreen, pRegion), 1)) - { - GEOMETRY_UNINIT (&geometry); + NULL, + pExtent->x1, pExtent->y1, + pExtent->x2 - pExtent->x1, pExtent->y2 - pExtent->y1, + REGION_RECTS (pRegion), + REGION_NUM_RECTS (pRegion))) return TRUE; - } - GEOMETRY_UNINIT (&geometry); return FALSE; } @@ -202,7 +225,7 @@ xglPaintWindowBackground (WindowPtr pWin, -pWin->drawable.x, -pWin->drawable.y)) { - xglAddBitDamage (&pWin->drawable); + xglAddCurrentBitDamage (&pWin->drawable); return; } @@ -214,7 +237,7 @@ xglPaintWindowBackground (WindowPtr pWin, pRegion, pWin->background.pixel)) { - xglAddBitDamage (&pWin->drawable); + xglAddCurrentBitDamage (&pWin->drawable); return; } break; @@ -222,7 +245,7 @@ xglPaintWindowBackground (WindowPtr pWin, XGL_WINDOW_FALLBACK_PROLOGUE (pWin, PaintWindowBackground); (*pScreen->PaintWindowBackground) (pWin, pRegion, what); - XGL_WINDOW_FALLBACK_EPILOGUE (pWin, PaintWindowBackground, + XGL_WINDOW_FALLBACK_EPILOGUE (pWin, pRegion, PaintWindowBackground, xglPaintWindowBackground); } @@ -241,7 +264,7 @@ xglPaintWindowBorder (WindowPtr pWin, pRegion, pWin->border.pixel)) { - xglAddBitDamage (&pWin->drawable); + xglAddCurrentBitDamage (&pWin->drawable); return; } } @@ -258,7 +281,7 @@ xglPaintWindowBorder (WindowPtr pWin, -pBgWin->drawable.x, -pBgWin->drawable.y)) { - xglAddBitDamage (&pWin->drawable); + xglAddCurrentBitDamage (&pWin->drawable); return; } @@ -268,6 +291,6 @@ xglPaintWindowBorder (WindowPtr pWin, XGL_WINDOW_FALLBACK_PROLOGUE (pWin, PaintWindowBorder); (*pScreen->PaintWindowBorder) (pWin, pRegion, what); - XGL_WINDOW_FALLBACK_EPILOGUE (pWin, PaintWindowBorder, + XGL_WINDOW_FALLBACK_EPILOGUE (pWin, pRegion, PaintWindowBorder, xglPaintWindowBorder); } |