2
* Copyright Ā© 2004 David Reveman
4
* Permission to use, copy, modify, distribute, and sell this software
5
* and its documentation for any purpose is hereby granted without
6
* fee, provided that the above copyright notice appear in all copies
7
* and that both that copyright notice and this permission notice
8
* appear in supporting documentation, and that the name of
9
* David Reveman not be used in advertising or publicity pertaining to
10
* distribution of the software without specific, written prior permission.
11
* David Reveman makes no representations about the suitability of this
12
* software for any purpose. It is provided "as is" without express or
15
* DAVID REVEMAN DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
16
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
17
* NO EVENT SHALL DAVID REVEMAN BE LIABLE FOR ANY SPECIAL, INDIRECT OR
18
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
19
* OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
20
* NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
21
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
23
* Author: David Reveman <davidr@novell.com>
27
#include <X11/fonts/fontstruct.h>
28
#include "dixfontstr.h"
30
xglDataTypeInfoRec xglGeometryDataTypes[2] = {
31
{ GLITZ_DATA_TYPE_SHORT, sizeof (glitz_short_t) },
32
{ GLITZ_DATA_TYPE_FLOAT, sizeof (glitz_float_t) }
35
glitz_buffer_hint_t usageTypes[] = {
36
GLITZ_BUFFER_HINT_STREAM_DRAW,
37
GLITZ_BUFFER_HINT_STATIC_DRAW,
38
GLITZ_BUFFER_HINT_DYNAMIC_DRAW
42
xglGeometryResize (ScreenPtr pScreen,
43
xglGeometryPtr pGeometry,
46
XGL_SCREEN_PRIV (pScreen);
48
if (size == pGeometry->size)
51
if (pGeometry->broken)
54
if (pGeometry->usage == GEOMETRY_USAGE_SYSMEM)
56
pGeometry->data = xrealloc (pGeometry->data, size);
58
if (pGeometry->buffer)
59
glitz_buffer_destroy (pGeometry->buffer);
61
pGeometry->buffer = NULL;
65
pGeometry->buffer = glitz_buffer_create_for_data (pGeometry->data);
66
if (!pGeometry->buffer)
68
pGeometry->broken = TRUE;
74
pGeometry->broken = TRUE;
80
glitz_buffer_t *newBuffer;
85
glitz_vertex_buffer_create (pScreenPriv->drawable, NULL, size,
86
usageTypes[pGeometry->usage]);
89
pGeometry->broken = TRUE;
95
if (pGeometry->buffer && newBuffer)
97
void *oldData, *newData;
99
oldData = glitz_buffer_map (pGeometry->buffer,
100
GLITZ_BUFFER_ACCESS_READ_ONLY);
101
newData = glitz_buffer_map (newBuffer,
102
GLITZ_BUFFER_ACCESS_WRITE_ONLY);
104
if (oldData && newData)
105
memcpy (newData, oldData, MIN (size, pGeometry->size));
107
glitz_buffer_unmap (pGeometry->buffer);
108
glitz_buffer_unmap (newBuffer);
110
glitz_buffer_destroy (pGeometry->buffer);
112
pGeometry->buffer = newBuffer;
115
pGeometry->size = size;
117
if (pGeometry->endOffset > size)
118
pGeometry->endOffset = size;
121
#define MAP_GEOMETRY(pScreen, pGeometry, offset, units, ptr, _size) \
122
if ((pGeometry)->broken) \
124
(_size) = (units) * xglGeometryDataTypes[(pGeometry)->dataType].size; \
125
if (((pGeometry)->size - (offset)) < (_size)) \
127
xglGeometryResize (pScreen, pGeometry, \
128
(pGeometry)->endOffset + (_size) + 500); \
129
if ((pGeometry)->broken) \
132
(ptr) = glitz_buffer_map ((pGeometry)->buffer, \
133
GLITZ_BUFFER_ACCESS_WRITE_ONLY); \
136
(pGeometry)->broken = TRUE; \
141
#define UNMAP_GEOMETRY(pGeometry, offset, _size) \
142
if (glitz_buffer_unmap ((pGeometry)->buffer)) \
144
(pGeometry)->broken = TRUE; \
147
if (((offset) + (_size)) > (pGeometry)->endOffset) \
149
(pGeometry)->endOffset = (offset) + (_size); \
150
(pGeometry)->count = (pGeometry)->endOffset / \
151
(2 * xglGeometryDataTypes[(pGeometry)->dataType].size); \
155
* Adds a number of boxes as GL_QUAD primitives
158
xglGeometryAddBox (ScreenPtr pScreen,
159
xglGeometryPtr pGeometry,
170
MAP_GEOMETRY (pScreen, pGeometry, offset, nBox * 8, ptr, size);
172
switch (pGeometry->dataType) {
173
case GEOMETRY_DATA_TYPE_SHORT:
175
glitz_short_t *data = (glitz_short_t *) ptr;
179
*data++ = (glitz_short_t) pBox->x1;
180
*data++ = (glitz_short_t) pBox->y1;
181
*data++ = (glitz_short_t) pBox->x2;
182
*data++ = (glitz_short_t) pBox->y1;
183
*data++ = (glitz_short_t) pBox->x2;
184
*data++ = (glitz_short_t) pBox->y2;
185
*data++ = (glitz_short_t) pBox->x1;
186
*data++ = (glitz_short_t) pBox->y2;
191
case GEOMETRY_DATA_TYPE_FLOAT:
193
glitz_float_t *data = (glitz_float_t *) ptr;
197
*data++ = (glitz_float_t) pBox->x1;
198
*data++ = (glitz_float_t) pBox->y1;
199
*data++ = (glitz_float_t) pBox->x2;
200
*data++ = (glitz_float_t) pBox->y1;
201
*data++ = (glitz_float_t) pBox->x2;
202
*data++ = (glitz_float_t) pBox->y2;
203
*data++ = (glitz_float_t) pBox->x1;
204
*data++ = (glitz_float_t) pBox->y2;
211
UNMAP_GEOMETRY (pGeometry, offset, size);
215
* Adds a number of spans as GL_LINE primitives
218
xglGeometryAddSpan (ScreenPtr pScreen,
219
xglGeometryPtr pGeometry,
231
MAP_GEOMETRY (pScreen, pGeometry, offset, n * 4, ptr, size);
233
switch (pGeometry->dataType) {
234
case GEOMETRY_DATA_TYPE_SHORT:
236
glitz_short_t *data = (glitz_short_t *) ptr;
240
*data++ = (glitz_short_t) ppt->x;
241
*data++ = (glitz_short_t) ppt->y;
242
*data++ = (glitz_short_t) (ppt->x + *pwidth);
243
*data++ = (glitz_short_t) ppt->y;
249
case GEOMETRY_DATA_TYPE_FLOAT:
251
glitz_float_t *data = (glitz_float_t *) ptr;
255
*data++ = (glitz_float_t) ppt->x;
256
*data++ = (glitz_float_t) ppt->y;
257
*data++ = (glitz_float_t) (ppt->x + *pwidth);
258
*data++ = (glitz_float_t) ppt->y;
266
UNMAP_GEOMETRY (pGeometry, offset, size);
270
* This macro is needed for end pixels to be rasterized correctly using
271
* OpenGL as OpenGL line segments are half-opened.
273
#define ADJUST_END_POINT(start, end, isPoint) \
274
(((end) > (start)) ? (end) + 1: \
275
((end) < (start)) ? (end) - 1: \
276
(isPoint) ? (end) + 1: \
280
* Adds a number of connected lines as GL_LINE_STRIP primitives
283
xglGeometryAddLine (ScreenPtr pScreen,
284
xglGeometryPtr pGeometry,
298
MAP_GEOMETRY (pScreen, pGeometry, offset, npt * 2, ptr, size);
303
switch (pGeometry->dataType) {
304
case GEOMETRY_DATA_TYPE_SHORT:
306
glitz_short_t *data = (glitz_short_t *) ptr;
310
if (mode == CoordModePrevious)
323
*data++ = (glitz_short_t) pt.x;
324
*data++ = (glitz_short_t) pt.y;
329
*data++ = (glitz_short_t)
330
ADJUST_END_POINT (ppt->x, pt.x, ppt->y == pt.y);
331
*data++ = (glitz_short_t) ADJUST_END_POINT (ppt->y, pt.y, 0);
337
case GEOMETRY_DATA_TYPE_FLOAT:
339
glitz_float_t *data = (glitz_float_t *) ptr;
343
if (mode == CoordModePrevious)
356
*data++ = (glitz_float_t) pt.x;
357
*data++ = (glitz_float_t) pt.y;
362
*data++ = (glitz_float_t)
363
ADJUST_END_POINT (ppt->x, pt.x, ppt->y == pt.y);
364
*data++ = (glitz_float_t) ADJUST_END_POINT (ppt->y, pt.y, 0);
372
UNMAP_GEOMETRY (pGeometry, offset, size);
376
* Adds a number of line segments as GL_LINE primitives
379
xglGeometryAddSegment (ScreenPtr pScreen,
380
xglGeometryPtr pGeometry,
391
MAP_GEOMETRY (pScreen, pGeometry, offset, nsegInit * 4, ptr, size);
393
switch (pGeometry->dataType) {
394
case GEOMETRY_DATA_TYPE_SHORT:
396
glitz_short_t *data = (glitz_short_t *) ptr;
400
*data++ = (glitz_short_t) pSegInit->x1;
401
*data++ = (glitz_short_t) pSegInit->y1;
402
*data++ = (glitz_short_t)
403
ADJUST_END_POINT (pSegInit->x1, pSegInit->x2,
404
pSegInit->y1 == pSegInit->y2);
405
*data++ = (glitz_short_t)
406
ADJUST_END_POINT (pSegInit->y1, pSegInit->y2, 0);
411
case GEOMETRY_DATA_TYPE_FLOAT:
413
glitz_float_t *data = (glitz_float_t *) ptr;
417
*data++ = (glitz_float_t) pSegInit->x1;
418
*data++ = (glitz_float_t) pSegInit->y1;
419
*data++ = (glitz_float_t)
420
ADJUST_END_POINT (pSegInit->x1, pSegInit->x2,
421
pSegInit->y1 == pSegInit->y2);
422
*data++ = (glitz_float_t)
423
ADJUST_END_POINT (pSegInit->y1, pSegInit->y2, 0);
430
UNMAP_GEOMETRY (pGeometry, offset, size);
434
xglGeometryForGlyph (ScreenPtr pScreen,
435
xglGeometryPtr pGeometry,
437
CharInfoPtr *ppciInit,
442
unsigned char *glyphbase = (pointer) ~0;
443
unsigned char *pglyph;
447
int n, lastX = 0, lastY = 0;
448
glitz_multi_array_t *array;
449
glitz_buffer_t *buffer;
456
pglyph = FONTGLYPHBITS (pglyphBase, *ppci++);
457
if (pglyph < glyphbase)
461
buffer = glitz_buffer_create_for_data (glyphbase);
464
pGeometry->broken = TRUE;
468
GEOMETRY_SET_BUFFER (pGeometry, buffer);
470
array = glitz_multi_array_create (nGlyph);
473
pGeometry->broken = TRUE;
477
GEOMETRY_SET_MULTI_ARRAY (pGeometry, array);
483
pglyph = FONTGLYPHBITS (pglyphBase, pci);
484
gWidth = GLYPHWIDTHPIXELS (pci);
485
gHeight = GLYPHHEIGHTPIXELS (pci);
487
if (gWidth && gHeight)
489
gx = x + pci->metrics.leftSideBearing;
490
gy = -pci->metrics.ascent;
492
glitz_multi_array_add (array,
493
(pglyph - glyphbase) * 8,
495
(gx - lastX) << 16, (gy - lastY) << 16);
499
x += pci->metrics.characterWidth;
502
glitz_buffer_destroy (buffer);
503
glitz_multi_array_destroy (array);
506
#define FIXED_LINE_X_TO_FLOAT(line, v) \
508
((line).p1.x + (xFixed_16_16) \
509
(((xFixed_32_32) ((v) - (line).p1.y) * \
510
((line).p2.x - (line).p1.x)) / \
511
((line).p2.y - (line).p1.y)))) / 65536)
513
#define FIXED_LINE_X_CEIL_TO_FLOAT(line, v) \
515
((line).p1.x + (xFixed_16_16) \
516
(((((line).p2.y - (line).p1.y) - 1) + \
517
((xFixed_32_32) ((v) - (line).p1.y) * \
518
((line).p2.x - (line).p1.x))) / \
519
((line).p2.y - (line).p1.y)))) / 65536)
522
* Adds a number of trapezoids as GL_QUAD primitives
525
xglGeometryAddTrapezoid (ScreenPtr pScreen,
526
xglGeometryPtr pGeometry,
537
MAP_GEOMETRY (pScreen, pGeometry, offset, nTrap * 8, ptr, size);
539
switch (pGeometry->dataType) {
540
case GEOMETRY_DATA_TYPE_SHORT:
542
pGeometry->broken = TRUE;
544
case GEOMETRY_DATA_TYPE_FLOAT:
546
glitz_float_t *data = (glitz_float_t *) ptr;
547
glitz_float_t top, bottom;
551
top = FIXED_TO_FLOAT (pTrap->top);
552
bottom = FIXED_TO_FLOAT (pTrap->bottom);
554
*data++ = FIXED_LINE_X_TO_FLOAT (pTrap->left, pTrap->top);
556
*data++ = FIXED_LINE_X_CEIL_TO_FLOAT (pTrap->right, pTrap->top);
558
*data++ = FIXED_LINE_X_CEIL_TO_FLOAT (pTrap->right, pTrap->bottom);
560
*data++ = FIXED_LINE_X_TO_FLOAT (pTrap->left, pTrap->bottom);
568
UNMAP_GEOMETRY (pGeometry, offset, size);
572
* Adds a number of traps as GL_QUAD primitives
575
xglGeometryAddTrap (ScreenPtr pScreen,
576
xglGeometryPtr pGeometry,
587
MAP_GEOMETRY (pScreen, pGeometry, offset, nTrap * 8, ptr, size);
589
switch (pGeometry->dataType) {
590
case GEOMETRY_DATA_TYPE_SHORT:
592
pGeometry->broken = TRUE;
594
case GEOMETRY_DATA_TYPE_FLOAT:
596
glitz_float_t *data = (glitz_float_t *) ptr;
597
glitz_float_t top, bottom;
601
top = FIXED_TO_FLOAT (pTrap->top.y);
602
bottom = FIXED_TO_FLOAT (pTrap->bot.y);
604
*data++ = FIXED_TO_FLOAT (pTrap->top.l);
606
*data++ = FIXED_TO_FLOAT (pTrap->top.r);
608
*data++ = FIXED_TO_FLOAT (pTrap->bot.r);
610
*data++ = FIXED_TO_FLOAT (pTrap->bot.l);
618
UNMAP_GEOMETRY (pGeometry, offset, size);
621
/* XXX: scratch geometry size never shrinks, it just gets larger when
622
required. this is not acceptable. */
624
xglGetScratchGeometryWithSize (ScreenPtr pScreen,
627
xglGeometryPtr pGeometry;
629
XGL_SCREEN_PRIV (pScreen);
631
pGeometry = &pScreenPriv->scratchGeometry;
633
if (pGeometry->broken || pGeometry->size < size)
635
GEOMETRY_UNINIT (pGeometry);
636
GEOMETRY_INIT (pScreen, pGeometry, pGeometry->type,
637
pScreenPriv->geometryUsage, size);
641
if (pGeometry->array)
643
glitz_multi_array_destroy (pGeometry->array);
644
pGeometry->array = NULL;
646
pGeometry->endOffset = 0;
649
pGeometry->first = 0;
650
pGeometry->count = 0;
651
pGeometry->width = 2;
658
xglGetScratchVertexGeometryWithType (ScreenPtr pScreen,
662
xglGeometryPtr pGeometry;
665
stride = 2 * xglGeometryDataTypes[type].size;
667
pGeometry = xglGetScratchGeometryWithSize (pScreen, count * stride);
669
pGeometry->type = GLITZ_GEOMETRY_TYPE_VERTEX;
670
pGeometry->dataType = type;
672
pGeometry->f.vertex.primitive = GLITZ_PRIMITIVE_QUADS;
673
pGeometry->f.vertex.type = xglGeometryDataTypes[type].type;
674
pGeometry->f.vertex.bytes_per_vertex = stride;
675
pGeometry->f.vertex.attributes = 0;
681
xglGetScratchVertexGeometry (ScreenPtr pScreen,
684
xglGeometryPtr pGeometry;
687
XGL_SCREEN_PRIV (pScreen);
689
type = pScreenPriv->geometryDataType;
690
stride = 2 * xglGeometryDataTypes[type].size;
692
pGeometry = xglGetScratchGeometryWithSize (pScreen, count * stride);
694
pGeometry->type = GLITZ_GEOMETRY_TYPE_VERTEX;
695
pGeometry->dataType = type;
697
pGeometry->f.vertex.primitive = GLITZ_PRIMITIVE_QUADS;
698
pGeometry->f.vertex.type = xglGeometryDataTypes[type].type;
699
pGeometry->f.vertex.bytes_per_vertex = stride;
700
pGeometry->f.vertex.attributes = 0;
706
xglSetGeometry (xglGeometryPtr pGeometry,
707
glitz_surface_t *surface)
709
if (pGeometry->broken)
712
glitz_set_geometry (surface, pGeometry->type, &pGeometry->f,
715
if (pGeometry->array)
716
glitz_set_multi_array (surface, pGeometry->array,
717
pGeometry->xOff, pGeometry->yOff);
719
glitz_set_array (surface,
720
pGeometry->first, pGeometry->width, pGeometry->count,
721
pGeometry->xOff, pGeometry->yOff);