2004-11-05 00:19:13 +01:00
|
|
|
/*
|
2004-11-05 14:26:07 +01:00
|
|
|
* Copyright © 2004 David Reveman
|
2004-11-05 00:19:13 +01:00
|
|
|
*
|
|
|
|
* 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
|
2005-01-26 11:58:52 +01:00
|
|
|
* appear in supporting documentation, and that the name of
|
2004-11-05 00:19:13 +01:00
|
|
|
* 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.
|
|
|
|
*
|
2005-01-26 11:58:52 +01:00
|
|
|
* Author: David Reveman <davidr@novell.com>
|
2004-11-05 00:19:13 +01:00
|
|
|
*/
|
|
|
|
|
|
|
|
#include "xgl.h"
|
2005-01-26 11:58:52 +01:00
|
|
|
#include "fontstruct.h"
|
|
|
|
#include "dixfontstr.h"
|
2004-11-05 00:19:13 +01:00
|
|
|
|
2005-01-26 11:58:52 +01:00
|
|
|
xglDataTypeInfoRec xglGeometryDataTypes[2] = {
|
2004-11-05 00:19:13 +01:00
|
|
|
{ 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;
|
|
|
|
|
2005-01-26 11:58:52 +01:00
|
|
|
if (pGeometry->broken)
|
|
|
|
return;
|
2004-11-05 00:19:13 +01:00
|
|
|
|
2005-01-26 11:58:52 +01:00
|
|
|
if (pGeometry->usage == GEOMETRY_USAGE_SYSMEM)
|
|
|
|
{
|
|
|
|
pGeometry->data = xrealloc (pGeometry->data, size);
|
|
|
|
|
2004-11-05 00:19:13 +01:00
|
|
|
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 =
|
2005-01-26 11:58:52 +01:00
|
|
|
glitz_vertex_buffer_create (pScreenPriv->drawable, NULL, size,
|
|
|
|
usageTypes[pGeometry->usage]);
|
2004-11-05 00:19:13 +01:00
|
|
|
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)
|
2005-01-26 11:58:52 +01:00
|
|
|
memcpy (newData, oldData, MIN (size, pGeometry->size));
|
2004-11-05 00:19:13 +01:00
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2005-01-26 11:58:52 +01:00
|
|
|
#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)) \
|
2004-11-05 00:19:13 +01:00
|
|
|
{ \
|
2005-01-26 11:58:52 +01:00
|
|
|
(pGeometry)->broken = TRUE; \
|
|
|
|
return; \
|
|
|
|
} \
|
|
|
|
if (((offset) + (_size)) > (pGeometry)->endOffset) \
|
|
|
|
{ \
|
|
|
|
(pGeometry)->endOffset = (offset) + (_size); \
|
|
|
|
(pGeometry)->count = (pGeometry)->endOffset / \
|
|
|
|
(2 * xglGeometryDataTypes[(pGeometry)->dataType].size); \
|
2004-11-05 00:19:13 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Adds a number of boxes as GL_QUAD primitives
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
xglGeometryAddBox (ScreenPtr pScreen,
|
|
|
|
xglGeometryPtr pGeometry,
|
|
|
|
BoxPtr pBox,
|
2005-01-26 11:58:52 +01:00
|
|
|
int nBox,
|
|
|
|
int offset)
|
2004-11-05 00:19:13 +01:00
|
|
|
{
|
2005-01-26 11:58:52 +01:00
|
|
|
int size;
|
|
|
|
char *ptr;
|
2004-11-05 00:19:13 +01:00
|
|
|
|
|
|
|
if (nBox < 1)
|
|
|
|
return;
|
|
|
|
|
2005-01-26 11:58:52 +01:00
|
|
|
MAP_GEOMETRY (pScreen, pGeometry, offset, nBox * 8, ptr, size);
|
|
|
|
|
2004-11-05 00:19:13 +01:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2005-01-26 11:58:52 +01:00
|
|
|
UNMAP_GEOMETRY (pGeometry, offset, size);
|
2004-11-05 00:19:13 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Adds a number of spans as GL_LINE primitives
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
xglGeometryAddSpan (ScreenPtr pScreen,
|
|
|
|
xglGeometryPtr pGeometry,
|
|
|
|
DDXPointPtr ppt,
|
|
|
|
int *pwidth,
|
2005-01-26 11:58:52 +01:00
|
|
|
int n,
|
|
|
|
int offset)
|
2004-11-05 00:19:13 +01:00
|
|
|
{
|
2005-01-26 11:58:52 +01:00
|
|
|
int size;
|
|
|
|
char *ptr;
|
2004-11-05 00:19:13 +01:00
|
|
|
|
|
|
|
if (n < 1)
|
|
|
|
return;
|
|
|
|
|
2005-01-26 11:58:52 +01:00
|
|
|
MAP_GEOMETRY (pScreen, pGeometry, offset, n * 4, ptr, size);
|
2004-11-05 00:19:13 +01:00
|
|
|
|
|
|
|
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;
|
2005-01-26 11:58:52 +01:00
|
|
|
*data++ = (glitz_short_t) (ppt->x + *pwidth);
|
2004-11-05 00:19:13 +01:00
|
|
|
*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;
|
2005-01-26 11:58:52 +01:00
|
|
|
*data++ = (glitz_float_t) (ppt->x + *pwidth);
|
2004-11-05 00:19:13 +01:00
|
|
|
*data++ = (glitz_float_t) ppt->y;
|
|
|
|
|
|
|
|
ppt++;
|
|
|
|
pwidth++;
|
|
|
|
}
|
|
|
|
} break;
|
|
|
|
}
|
2005-01-26 11:58:52 +01:00
|
|
|
|
|
|
|
UNMAP_GEOMETRY (pGeometry, offset, size);
|
2004-11-05 00:19:13 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* 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,
|
2005-01-26 11:58:52 +01:00
|
|
|
DDXPointPtr ppt,
|
|
|
|
int offset)
|
2004-11-05 00:19:13 +01:00
|
|
|
{
|
|
|
|
DDXPointRec pt;
|
2005-01-26 11:58:52 +01:00
|
|
|
int size;
|
|
|
|
char *ptr;
|
2004-11-05 00:19:13 +01:00
|
|
|
|
|
|
|
if (npt < 2)
|
|
|
|
return;
|
|
|
|
|
2005-01-26 11:58:52 +01:00
|
|
|
MAP_GEOMETRY (pScreen, pGeometry, offset, npt * 2, ptr, size);
|
2004-11-05 00:19:13 +01:00
|
|
|
|
|
|
|
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)
|
|
|
|
{
|
2005-01-26 11:58:52 +01:00
|
|
|
*data++ = (glitz_short_t) pt.x;
|
|
|
|
*data++ = (glitz_short_t) pt.y;
|
2004-11-05 00:19:13 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
ppt--;
|
2005-01-26 11:58:52 +01:00
|
|
|
*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);
|
2004-11-05 00:19:13 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2005-01-26 11:58:52 +01:00
|
|
|
UNMAP_GEOMETRY (pGeometry, offset, size);
|
2004-11-05 00:19:13 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Adds a number of line segments as GL_LINE primitives
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
xglGeometryAddSegment (ScreenPtr pScreen,
|
|
|
|
xglGeometryPtr pGeometry,
|
|
|
|
int nsegInit,
|
2005-01-26 11:58:52 +01:00
|
|
|
xSegment *pSegInit,
|
|
|
|
int offset)
|
2004-11-05 00:19:13 +01:00
|
|
|
{
|
2005-01-26 11:58:52 +01:00
|
|
|
int size;
|
|
|
|
char *ptr;
|
2004-11-05 00:19:13 +01:00
|
|
|
|
|
|
|
if (nsegInit < 1)
|
|
|
|
return;
|
|
|
|
|
2005-01-26 11:58:52 +01:00
|
|
|
MAP_GEOMETRY (pScreen, pGeometry, offset, nsegInit * 4, ptr, size);
|
2004-11-05 00:19:13 +01:00
|
|
|
|
|
|
|
switch (pGeometry->dataType) {
|
|
|
|
case GEOMETRY_DATA_TYPE_SHORT:
|
|
|
|
{
|
|
|
|
glitz_short_t *data = (glitz_short_t *) ptr;
|
|
|
|
|
|
|
|
while (nsegInit--)
|
|
|
|
{
|
2005-01-26 11:58:52 +01:00
|
|
|
*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);
|
2004-11-05 00:19:13 +01:00
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
2005-01-26 11:58:52 +01:00
|
|
|
|
|
|
|
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--)
|
2004-11-05 00:19:13 +01:00
|
|
|
{
|
2005-01-26 11:58:52 +01:00
|
|
|
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 */
|
2004-11-05 00:19:13 +01:00
|
|
|
pGeometry->broken = TRUE;
|
2005-01-26 11:58:52 +01:00
|
|
|
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)
|
2004-11-05 00:19:13 +01:00
|
|
|
return;
|
2005-01-26 11:58:52 +01:00
|
|
|
|
|
|
|
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;
|
2004-11-05 00:19:13 +01:00
|
|
|
}
|
2005-01-26 11:58:52 +01:00
|
|
|
|
|
|
|
return pGeometry;
|
|
|
|
}
|
|
|
|
|
|
|
|
xglGeometryPtr
|
|
|
|
xglGetScratchVertexGeometryWithType (ScreenPtr pScreen,
|
|
|
|
int type,
|
|
|
|
int count)
|
|
|
|
{
|
|
|
|
xglGeometryPtr pGeometry;
|
|
|
|
int stride;
|
2004-11-05 00:19:13 +01:00
|
|
|
|
2005-01-26 11:58:52 +01:00
|
|
|
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;
|
2004-11-05 00:19:13 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
Bool
|
|
|
|
xglSetGeometry (xglGeometryPtr pGeometry,
|
2005-01-26 11:58:52 +01:00
|
|
|
glitz_surface_t *surface)
|
2004-11-05 00:19:13 +01:00
|
|
|
{
|
|
|
|
if (pGeometry->broken)
|
|
|
|
return FALSE;
|
|
|
|
|
2005-01-26 11:58:52 +01:00
|
|
|
glitz_set_geometry (surface, pGeometry->type, &pGeometry->f,
|
2004-11-05 00:19:13 +01:00
|
|
|
pGeometry->buffer);
|
|
|
|
|
2005-01-26 11:58:52 +01:00
|
|
|
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);
|
|
|
|
|
2004-11-05 00:19:13 +01:00
|
|
|
return TRUE;
|
|
|
|
}
|