724 lines
		
	
	
		
			17 KiB
		
	
	
	
		
			C
		
	
	
	
			
		
		
	
	
			724 lines
		
	
	
		
			17 KiB
		
	
	
	
		
			C
		
	
	
	
| /*
 | |
|  * 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 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
 | |
|  * 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@novell.com>
 | |
|  */
 | |
| 
 | |
| #include "xgl.h"
 | |
| #include <X11/fonts/fontstruct.h>
 | |
| #include "dixfontstr.h"
 | |
| 
 | |
| xglDataTypeInfoRec xglGeometryDataTypes[2] = {
 | |
|     { GLITZ_DATA_TYPE_SHORT, sizeof (glitz_short_t) },
 | |
|     { GLITZ_DATA_TYPE_FLOAT, sizeof (glitz_float_t) }
 | |
| };
 | |
| 
 | |
| glitz_buffer_hint_t usageTypes[] = {
 | |
|     GLITZ_BUFFER_HINT_STREAM_DRAW,
 | |
|     GLITZ_BUFFER_HINT_STATIC_DRAW,
 | |
|     GLITZ_BUFFER_HINT_DYNAMIC_DRAW
 | |
| };
 | |
| 
 | |
| void
 | |
| xglGeometryResize (ScreenPtr	  pScreen,
 | |
| 		   xglGeometryPtr pGeometry,
 | |
| 		   int		  size)
 | |
| {
 | |
|     XGL_SCREEN_PRIV (pScreen);
 | |
|     
 | |
|     if (size == pGeometry->size)
 | |
| 	return;
 | |
| 
 | |
|     if (pGeometry->broken)
 | |
| 	return;
 | |
| 
 | |
|     if (pGeometry->usage == GEOMETRY_USAGE_SYSMEM)
 | |
|     {
 | |
| 	pGeometry->data = xrealloc (pGeometry->data, size);
 | |
| 	
 | |
| 	if (pGeometry->buffer)
 | |
| 	    glitz_buffer_destroy (pGeometry->buffer);
 | |
| 	
 | |
| 	pGeometry->buffer = NULL;
 | |
| 	
 | |
| 	if (pGeometry->data)
 | |
| 	{
 | |
| 	    pGeometry->buffer = glitz_buffer_create_for_data (pGeometry->data);
 | |
| 	    if (!pGeometry->buffer)
 | |
| 	    {
 | |
| 		pGeometry->broken = TRUE;
 | |
| 		return;
 | |
| 	    }
 | |
| 	}
 | |
| 	else if (size)
 | |
| 	{
 | |
| 	    pGeometry->broken = TRUE;
 | |
| 	    return;
 | |
| 	}
 | |
|     }
 | |
|     else
 | |
|     {
 | |
| 	glitz_buffer_t *newBuffer;
 | |
| 	if (size)
 | |
| 	{
 | |
| 	    newBuffer =
 | |
| 		glitz_vertex_buffer_create (pScreenPriv->drawable, NULL, size,
 | |
| 					    usageTypes[pGeometry->usage]);
 | |
| 	    if (!newBuffer)
 | |
| 	    {
 | |
| 		pGeometry->broken = TRUE;
 | |
| 		return;
 | |
| 	    }
 | |
| 	} else
 | |
| 	    newBuffer = NULL;
 | |
| 	
 | |
| 	if (pGeometry->buffer && newBuffer)
 | |
| 	{
 | |
| 	    void *oldData, *newData;
 | |
| 	    
 | |
| 	    oldData = glitz_buffer_map (pGeometry->buffer,
 | |
| 					GLITZ_BUFFER_ACCESS_READ_ONLY);
 | |
| 	    newData = glitz_buffer_map (newBuffer,
 | |
| 					GLITZ_BUFFER_ACCESS_WRITE_ONLY);
 | |
| 	    
 | |
| 	    if (oldData && newData)
 | |
| 		memcpy (newData, oldData, MIN (size, pGeometry->size));
 | |
| 	    
 | |
| 	    glitz_buffer_unmap (pGeometry->buffer);
 | |
| 	    glitz_buffer_unmap (newBuffer);
 | |
| 	    
 | |
| 	    glitz_buffer_destroy (pGeometry->buffer);
 | |
| 	}
 | |
| 	pGeometry->buffer = newBuffer;
 | |
|     }
 | |
|     
 | |
|     pGeometry->size = size;
 | |
|     
 | |
|     if (pGeometry->endOffset > size)
 | |
| 	pGeometry->endOffset = size;
 | |
| }
 | |
| 
 | |
| #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))			   \
 | |
|     {									   \
 | |
| 	(pGeometry)->broken = TRUE;					   \
 | |
| 	return;								   \
 | |
|     }									   \
 | |
|     if (((offset) + (_size)) > (pGeometry)->endOffset)			   \
 | |
|     {									   \
 | |
| 	(pGeometry)->endOffset = (offset) + (_size);			   \
 | |
| 	(pGeometry)->count = (pGeometry)->endOffset /			   \
 | |
| 	    (2 * xglGeometryDataTypes[(pGeometry)->dataType].size);	   \
 | |
|     }
 | |
| 	
 | |
| /*
 | |
|  * Adds a number of boxes as GL_QUAD primitives
 | |
|  */
 | |
| void
 | |
| xglGeometryAddBox (ScreenPtr	  pScreen,
 | |
| 		   xglGeometryPtr pGeometry,
 | |
| 		   BoxPtr	  pBox,
 | |
| 		   int		  nBox,
 | |
| 		   int		  offset)
 | |
| {
 | |
|     int  size;
 | |
|     char *ptr;
 | |
| 
 | |
|     if (nBox < 1)
 | |
| 	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;
 | |
| 
 | |
| 	while (nBox--)
 | |
| 	{
 | |
| 	    *data++ = (glitz_short_t) pBox->x1;
 | |
| 	    *data++ = (glitz_short_t) pBox->y1;
 | |
| 	    *data++ = (glitz_short_t) pBox->x2;
 | |
| 	    *data++ = (glitz_short_t) pBox->y1;
 | |
| 	    *data++ = (glitz_short_t) pBox->x2;
 | |
| 	    *data++ = (glitz_short_t) pBox->y2;
 | |
| 	    *data++ = (glitz_short_t) pBox->x1;
 | |
| 	    *data++ = (glitz_short_t) pBox->y2;
 | |
| 
 | |
| 	    pBox++;
 | |
| 	}
 | |
|     } break;
 | |
|     case GEOMETRY_DATA_TYPE_FLOAT:
 | |
|     {
 | |
| 	glitz_float_t *data = (glitz_float_t *) ptr;
 | |
| 	
 | |
| 	while (nBox--)
 | |
| 	{
 | |
| 	    *data++ = (glitz_float_t) pBox->x1;
 | |
| 	    *data++ = (glitz_float_t) pBox->y1;
 | |
| 	    *data++ = (glitz_float_t) pBox->x2;
 | |
| 	    *data++ = (glitz_float_t) pBox->y1;
 | |
| 	    *data++ = (glitz_float_t) pBox->x2;
 | |
| 	    *data++ = (glitz_float_t) pBox->y2;
 | |
| 	    *data++ = (glitz_float_t) pBox->x1;
 | |
| 	    *data++ = (glitz_float_t) pBox->y2;
 | |
| 
 | |
| 	    pBox++;
 | |
| 	}
 | |
|     } break;
 | |
|     }
 | |
| 
 | |
|     UNMAP_GEOMETRY (pGeometry, offset, size);
 | |
| }
 | |
| 
 | |
| /*
 | |
|  * Adds a number of spans as GL_LINE primitives
 | |
|  */
 | |
| void
 | |
| xglGeometryAddSpan (ScreenPtr	   pScreen,
 | |
| 		    xglGeometryPtr pGeometry,
 | |
| 		    DDXPointPtr	   ppt,
 | |
| 		    int		   *pwidth,
 | |
| 		    int		   n,
 | |
| 		    int		   offset)
 | |
| {
 | |
|     int  size;
 | |
|     char *ptr;
 | |
| 
 | |
|     if (n < 1)
 | |
| 	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;
 | |
| 
 | |
| 	while (n--)
 | |
| 	{
 | |
| 	    *data++ = (glitz_short_t) ppt->x;
 | |
| 	    *data++ = (glitz_short_t) ppt->y;
 | |
| 	    *data++ = (glitz_short_t) (ppt->x + *pwidth);
 | |
| 	    *data++ = (glitz_short_t) ppt->y;
 | |
| 	
 | |
| 	    ppt++;
 | |
| 	    pwidth++;
 | |
| 	}
 | |
|     } break;
 | |
|     case GEOMETRY_DATA_TYPE_FLOAT:
 | |
|     {
 | |
| 	glitz_float_t *data = (glitz_float_t *) ptr;
 | |
| 
 | |
| 	while (n--)
 | |
| 	{
 | |
| 	    *data++ = (glitz_float_t) ppt->x;
 | |
| 	    *data++ = (glitz_float_t) ppt->y;
 | |
| 	    *data++ = (glitz_float_t) (ppt->x + *pwidth);
 | |
| 	    *data++ = (glitz_float_t) ppt->y;
 | |
| 	
 | |
| 	    ppt++;
 | |
| 	    pwidth++;
 | |
| 	}
 | |
|     } break;
 | |
|     }
 | |
|     
 | |
|     UNMAP_GEOMETRY (pGeometry, offset, size);
 | |
| }
 | |
| 
 | |
| /*
 | |
|  * This macro is needed for end pixels to be rasterized correctly using
 | |
|  * OpenGL as OpenGL line segments are half-opened.
 | |
|  */
 | |
| #define ADJUST_END_POINT(start, end, isPoint) \
 | |
|     (((end) > (start)) ? (end) + 1:	      \
 | |
|      ((end) < (start)) ? (end) - 1:	      \
 | |
|      (isPoint)	       ? (end) + 1:	      \
 | |
|      (end))
 | |
| 
 | |
| /*
 | |
|  * Adds a number of connected lines as GL_LINE_STRIP primitives
 | |
|  */
 | |
| void
 | |
| xglGeometryAddLine (ScreenPtr	   pScreen,
 | |
| 		    xglGeometryPtr pGeometry,
 | |
| 		    int		   loop,
 | |
| 		    int		   mode,
 | |
| 		    int		   npt,
 | |
| 		    DDXPointPtr    ppt,
 | |
| 		    int		   offset)
 | |
| {
 | |
|     DDXPointRec pt;
 | |
|     int		size;
 | |
|     char	*ptr;
 | |
| 
 | |
|     if (npt < 2)
 | |
| 	return;
 | |
| 
 | |
|     MAP_GEOMETRY (pScreen, pGeometry, offset, npt * 2, ptr, size);
 | |
| 
 | |
|     pt.x = 0;
 | |
|     pt.y = 0;
 | |
|     
 | |
|     switch (pGeometry->dataType) {
 | |
|     case GEOMETRY_DATA_TYPE_SHORT:
 | |
|     {
 | |
| 	glitz_short_t *data = (glitz_short_t *) ptr;
 | |
| 
 | |
| 	while (npt--)
 | |
| 	{
 | |
| 	    if (mode == CoordModePrevious)
 | |
| 	    {
 | |
| 		pt.x += ppt->x;
 | |
| 		pt.y += ppt->y;
 | |
| 	    }
 | |
| 	    else
 | |
| 	    {
 | |
| 		pt.x = ppt->x;
 | |
| 		pt.y = ppt->y;
 | |
| 	    }
 | |
| 
 | |
| 	    if (npt || loop)
 | |
| 	    {
 | |
| 		*data++ = (glitz_short_t) pt.x;
 | |
| 		*data++ = (glitz_short_t) pt.y;
 | |
| 	    }
 | |
| 	    else
 | |
| 	    {
 | |
| 		ppt--;
 | |
| 		*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++;
 | |
| 	}
 | |
|     } break;
 | |
|     case GEOMETRY_DATA_TYPE_FLOAT:
 | |
|     {
 | |
| 	glitz_float_t *data = (glitz_float_t *) ptr;
 | |
| 
 | |
| 	while (npt--)
 | |
| 	{
 | |
| 	    if (mode == CoordModePrevious)
 | |
| 	    {
 | |
| 		pt.x += ppt->x;
 | |
| 		pt.y += ppt->y;
 | |
| 	    }
 | |
| 	    else
 | |
| 	    {
 | |
| 		pt.x = ppt->x;
 | |
| 		pt.y = ppt->y;
 | |
| 	    }
 | |
| 
 | |
| 	    if (npt || loop)
 | |
| 	    {
 | |
| 		*data++ = (glitz_float_t) pt.x;
 | |
| 		*data++ = (glitz_float_t) pt.y;
 | |
| 	    }
 | |
| 	    else
 | |
| 	    {
 | |
| 		ppt--;
 | |
| 		*data++ = (glitz_float_t)
 | |
| 		    ADJUST_END_POINT (ppt->x, pt.x, ppt->y == pt.y);
 | |
| 		*data++ = (glitz_float_t) ADJUST_END_POINT (ppt->y, pt.y, 0);
 | |
| 	    }
 | |
| 	    
 | |
| 	    ppt++;
 | |
| 	}
 | |
|     } break;
 | |
|     }
 | |
| 
 | |
|     UNMAP_GEOMETRY (pGeometry, offset, size);
 | |
| }
 | |
| 
 | |
| /*
 | |
|  * Adds a number of line segments as GL_LINE primitives
 | |
|  */
 | |
| void
 | |
| xglGeometryAddSegment (ScreenPtr      pScreen,
 | |
| 		       xglGeometryPtr pGeometry,
 | |
| 		       int	      nsegInit,
 | |
| 		       xSegment       *pSegInit,
 | |
| 		       int	      offset)
 | |
| {
 | |
|     int  size;
 | |
|     char *ptr;
 | |
| 
 | |
|     if (nsegInit < 1)
 | |
| 	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;
 | |
| 
 | |
| 	while (nsegInit--)
 | |
| 	{
 | |
| 	    *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++;
 | |
| 	}
 | |
|     } break;
 | |
|     case GEOMETRY_DATA_TYPE_FLOAT:
 | |
|     {
 | |
| 	glitz_float_t *data = (glitz_float_t *) ptr;
 | |
| 
 | |
| 	while (nsegInit--)
 | |
| 	{
 | |
| 	    *data++ = (glitz_float_t) pSegInit->x1;
 | |
| 	    *data++ = (glitz_float_t) pSegInit->y1;
 | |
| 	    *data++ = (glitz_float_t)
 | |
| 		ADJUST_END_POINT (pSegInit->x1, pSegInit->x2,
 | |
| 				  pSegInit->y1 == pSegInit->y2);
 | |
| 	    *data++ = (glitz_float_t)
 | |
| 		ADJUST_END_POINT (pSegInit->y1, pSegInit->y2, 0);
 | |
| 	    
 | |
| 	    pSegInit++;
 | |
| 	}
 | |
|     } break;
 | |
|     }
 | |
|     
 | |
|     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;
 | |
| 
 | |
|     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)
 | |
| {
 | |
|     if (pGeometry->broken)
 | |
| 	return FALSE;
 | |
|     
 | |
|     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;
 | |
| }
 |