Add patch that contain Mali fixes.
[deb_xorg-server.git] / Xext / xf86bigfont.c
1 /*
2 * BIGFONT extension for sharing font metrics between clients (if possible)
3 * and for transmitting font metrics to clients in a compressed form.
4 *
5 * Copyright (c) 1999-2000 Bruno Haible
6 * Copyright (c) 1999-2000 The XFree86 Project, Inc.
7 */
8
9 /* THIS IS NOT AN X CONSORTIUM STANDARD */
10
11 /*
12 * Big fonts suffer from the following: All clients that have opened a
13 * font can access the complete glyph metrics array (the XFontStruct member
14 * `per_char') directly, without going through a macro. Moreover these
15 * glyph metrics are ink metrics, i.e. are not redundant even for a
16 * fixed-width font. For a Unicode font, the size of this array is 768 KB.
17 *
18 * Problems: 1. It eats a lot of memory in each client. 2. All this glyph
19 * metrics data is piped through the socket when the font is opened.
20 *
21 * This extension addresses these two problems for local clients, by using
22 * shared memory. It also addresses the second problem for non-local clients,
23 * by compressing the data before transmit by a factor of nearly 6.
24 *
25 * If you use this extension, your OS ought to nicely support shared memory.
26 * This means: Shared memory should be swappable to the swap, and the limits
27 * should be high enough (SHMMNI at least 64, SHMMAX at least 768 KB,
28 * SHMALL at least 48 MB). It is a plus if your OS allows shmat() calls
29 * on segments that have already been marked "removed", because it permits
30 * these segments to be cleaned up by the OS if the X server is killed with
31 * signal SIGKILL.
32 *
33 * This extension is transparently exploited by Xlib (functions XQueryFont,
34 * XLoadQueryFont).
35 */
36
37 #ifdef HAVE_DIX_CONFIG_H
38 #include <dix-config.h>
39 #endif
40
41 #include <sys/types.h>
42 #ifdef HAS_SHM
43 #if defined(linux) && (!defined(__GNU_LIBRARY__) || __GNU_LIBRARY__ < 2)
44 /* libc4 does not define __GNU_LIBRARY__, libc5 defines __GNU_LIBRARY__ as 1 */
45 /* Linux libc4 and libc5 only (because glibc doesn't include kernel headers):
46 Linux 2.0.x and 2.2.x define SHMLBA as PAGE_SIZE, but forget to define
47 PAGE_SIZE. It is defined in <asm/page.h>. */
48 #include <asm/page.h>
49 #endif
50 #ifdef SVR4
51 #include <sys/sysmacros.h>
52 #endif
53 #if defined(__CYGWIN__)
54 #include <sys/param.h>
55 #include <sys/sysmacros.h>
56 #endif
57 #include <sys/ipc.h>
58 #include <sys/shm.h>
59 #include <sys/stat.h>
60 #include <stdlib.h>
61 #include <unistd.h>
62 #include <time.h>
63 #include <errno.h>
64 #endif
65
66 #include <X11/X.h>
67 #include <X11/Xproto.h>
68 #include "misc.h"
69 #include "os.h"
70 #include "dixstruct.h"
71 #include "gcstruct.h"
72 #include "dixfontstr.h"
73 #include "extnsionst.h"
74 #include "extinit.h"
75 #include "protocol-versions.h"
76
77 #include <X11/extensions/xf86bigfproto.h>
78 #include "xf86bigfontsrv.h"
79
80 static void XF86BigfontResetProc(ExtensionEntry * /* extEntry */
81 );
82
83 #ifdef HAS_SHM
84
85 /* A random signature, transmitted to the clients so they can verify that the
86 shared memory segment they are attaching to was really established by the
87 X server they are talking to. */
88 static CARD32 signature;
89
90 /* Index for additional information stored in a FontRec's devPrivates array. */
91 static int FontShmdescIndex;
92
93 static unsigned int pagesize;
94
95 static Bool badSysCall = FALSE;
96
97 #if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__CYGWIN__) || defined(__DragonFly__)
98
99 #include <sys/signal.h>
100
101 static void
102 SigSysHandler(int signo)
103 {
104 badSysCall = TRUE;
105 }
106
107 static Bool
108 CheckForShmSyscall(void)
109 {
110 void (*oldHandler) (int);
111 int shmid = -1;
112
113 /* If no SHM support in the kernel, the bad syscall will generate SIGSYS */
114 oldHandler = signal(SIGSYS, SigSysHandler);
115
116 badSysCall = FALSE;
117 shmid = shmget(IPC_PRIVATE, 4096, IPC_CREAT);
118 if (shmid != -1) {
119 /* Successful allocation - clean up */
120 shmctl(shmid, IPC_RMID, NULL);
121 }
122 else {
123 /* Allocation failed */
124 badSysCall = TRUE;
125 }
126 signal(SIGSYS, oldHandler);
127 return !badSysCall;
128 }
129
130 #define MUST_CHECK_FOR_SHM_SYSCALL
131
132 #endif
133
134 #endif
135
136 /* ========== Management of shared memory segments ========== */
137
138 #ifdef HAS_SHM
139
140 #ifdef __linux__
141 /* On Linux, shared memory marked as "removed" can still be attached.
142 Nice feature, because the kernel will automatically free the associated
143 storage when the server and all clients are gone. */
144 #define EARLY_REMOVE
145 #endif
146
147 typedef struct _ShmDesc {
148 struct _ShmDesc *next;
149 struct _ShmDesc **prev;
150 int shmid;
151 char *attach_addr;
152 } ShmDescRec, *ShmDescPtr;
153
154 static ShmDescPtr ShmList = (ShmDescPtr) NULL;
155
156 static ShmDescPtr
157 shmalloc(unsigned int size)
158 {
159 ShmDescPtr pDesc;
160 int shmid;
161 char *addr;
162
163 #ifdef MUST_CHECK_FOR_SHM_SYSCALL
164 if (pagesize == 0)
165 return (ShmDescPtr) NULL;
166 #endif
167
168 /* On some older Linux systems, the number of shared memory segments
169 system-wide is 127. In Linux 2.4, it is 4095.
170 Therefore there is a tradeoff to be made between allocating a
171 shared memory segment on one hand, and allocating memory and piping
172 the glyph metrics on the other hand. If the glyph metrics size is
173 small, we prefer the traditional way. */
174 if (size < 3500)
175 return (ShmDescPtr) NULL;
176
177 pDesc = malloc(sizeof(ShmDescRec));
178 if (!pDesc)
179 return (ShmDescPtr) NULL;
180
181 size = (size + pagesize - 1) & -pagesize;
182 shmid = shmget(IPC_PRIVATE, size, S_IWUSR | S_IRUSR | S_IRGRP | S_IROTH);
183 if (shmid == -1) {
184 ErrorF(XF86BIGFONTNAME " extension: shmget() failed, size = %u, %s\n",
185 size, strerror(errno));
186 free(pDesc);
187 return (ShmDescPtr) NULL;
188 }
189
190 if ((addr = shmat(shmid, 0, 0)) == (char *) -1) {
191 ErrorF(XF86BIGFONTNAME " extension: shmat() failed, size = %u, %s\n",
192 size, strerror(errno));
193 shmctl(shmid, IPC_RMID, (void *) 0);
194 free(pDesc);
195 return (ShmDescPtr) NULL;
196 }
197
198 #ifdef EARLY_REMOVE
199 shmctl(shmid, IPC_RMID, (void *) 0);
200 #endif
201
202 pDesc->shmid = shmid;
203 pDesc->attach_addr = addr;
204 if (ShmList)
205 ShmList->prev = &pDesc->next;
206 pDesc->next = ShmList;
207 pDesc->prev = &ShmList;
208 ShmList = pDesc;
209
210 return pDesc;
211 }
212
213 static void
214 shmdealloc(ShmDescPtr pDesc)
215 {
216 #ifndef EARLY_REMOVE
217 shmctl(pDesc->shmid, IPC_RMID, (void *) 0);
218 #endif
219 shmdt(pDesc->attach_addr);
220
221 if (pDesc->next)
222 pDesc->next->prev = pDesc->prev;
223 *pDesc->prev = pDesc->next;
224 free(pDesc);
225 }
226
227 #endif
228
229 /* Called when a font is closed. */
230 void
231 XF86BigfontFreeFontShm(FontPtr pFont)
232 {
233 #ifdef HAS_SHM
234 ShmDescPtr pDesc;
235
236 /* If during shutdown of the server, XF86BigfontCleanup() has already
237 * called shmdealloc() for all segments, we don't need to do it here.
238 */
239 if (!ShmList)
240 return;
241
242 pDesc = (ShmDescPtr) FontGetPrivate(pFont, FontShmdescIndex);
243 if (pDesc)
244 shmdealloc(pDesc);
245 #endif
246 }
247
248 /* Called upon fatal signal. */
249 void
250 XF86BigfontCleanup(void)
251 {
252 #ifdef HAS_SHM
253 while (ShmList)
254 shmdealloc(ShmList);
255 #endif
256 }
257
258 /* Called when a server generation dies. */
259 static void
260 XF86BigfontResetProc(ExtensionEntry * extEntry)
261 {
262 /* This function is normally called from CloseDownExtensions(), called
263 * from main(). It will be followed by a call to FreeAllResources(),
264 * which will call XF86BigfontFreeFontShm() for each font. Thus it
265 * appears that we do not need to do anything in this function. --
266 * But I prefer to write robust code, and not keep shared memory lying
267 * around when it's not needed any more. (Someone might close down the
268 * extension without calling FreeAllResources()...)
269 */
270 XF86BigfontCleanup();
271 }
272
273 /* ========== Handling of extension specific requests ========== */
274
275 static int
276 ProcXF86BigfontQueryVersion(ClientPtr client)
277 {
278 xXF86BigfontQueryVersionReply reply;
279
280 REQUEST_SIZE_MATCH(xXF86BigfontQueryVersionReq);
281 reply = (xXF86BigfontQueryVersionReply) {
282 .type = X_Reply,
283 .sequenceNumber = client->sequence,
284 .length = 0,
285 .majorVersion = SERVER_XF86BIGFONT_MAJOR_VERSION,
286 .minorVersion = SERVER_XF86BIGFONT_MINOR_VERSION,
287 .uid = geteuid(),
288 .gid = getegid(),
289 #ifdef HAS_SHM
290 .signature = signature,
291 .capabilities = (client->local && !client->swapped)
292 ? XF86Bigfont_CAP_LocalShm : 0
293 #else
294 .signature = 0,
295 .capabilities = 0
296 #endif
297 };
298 if (client->swapped) {
299 swaps(&reply.sequenceNumber);
300 swapl(&reply.length);
301 swaps(&reply.majorVersion);
302 swaps(&reply.minorVersion);
303 swapl(&reply.uid);
304 swapl(&reply.gid);
305 swapl(&reply.signature);
306 }
307 WriteToClient(client, sizeof(xXF86BigfontQueryVersionReply), &reply);
308 return Success;
309 }
310
311 static void
312 swapCharInfo(xCharInfo * pCI)
313 {
314 swaps(&pCI->leftSideBearing);
315 swaps(&pCI->rightSideBearing);
316 swaps(&pCI->characterWidth);
317 swaps(&pCI->ascent);
318 swaps(&pCI->descent);
319 swaps(&pCI->attributes);
320 }
321
322 /* static CARD32 hashCI (xCharInfo *p); */
323 #define hashCI(p) \
324 (CARD32)(((p->leftSideBearing << 27) + (p->leftSideBearing >> 5) + \
325 (p->rightSideBearing << 23) + (p->rightSideBearing >> 9) + \
326 (p->characterWidth << 16) + \
327 (p->ascent << 11) + (p->descent << 6)) ^ p->attributes)
328
329 static int
330 ProcXF86BigfontQueryFont(ClientPtr client)
331 {
332 FontPtr pFont;
333
334 REQUEST(xXF86BigfontQueryFontReq);
335 CARD32 stuff_flags;
336 xCharInfo *pmax;
337 xCharInfo *pmin;
338 int nCharInfos;
339 int shmid;
340
341 #ifdef HAS_SHM
342 ShmDescPtr pDesc = NULL;
343 #else
344 #define pDesc 0
345 #endif
346 xCharInfo *pCI;
347 CARD16 *pIndex2UniqIndex;
348 CARD16 *pUniqIndex2Index;
349 CARD32 nUniqCharInfos;
350
351 #if 0
352 REQUEST_SIZE_MATCH(xXF86BigfontQueryFontReq);
353 #else
354 switch (client->req_len) {
355 case 2: /* client with version 1.0 libX11 */
356 stuff_flags = (client->local &&
357 !client->swapped ? XF86Bigfont_FLAGS_Shm : 0);
358 break;
359 case 3: /* client with version 1.1 libX11 */
360 stuff_flags = stuff->flags;
361 break;
362 default:
363 return BadLength;
364 }
365 #endif
366 if (dixLookupFontable(&pFont, stuff->id, client, DixGetAttrAccess) !=
367 Success)
368 return BadFont; /* procotol spec says only error is BadFont */
369
370 pmax = FONTINKMAX(pFont);
371 pmin = FONTINKMIN(pFont);
372 nCharInfos =
373 (pmax->rightSideBearing == pmin->rightSideBearing
374 && pmax->leftSideBearing == pmin->leftSideBearing
375 && pmax->descent == pmin->descent
376 && pmax->ascent == pmin->ascent
377 && pmax->characterWidth == pmin->characterWidth)
378 ? 0 : N2dChars(pFont);
379 shmid = -1;
380 pCI = NULL;
381 pIndex2UniqIndex = NULL;
382 pUniqIndex2Index = NULL;
383 nUniqCharInfos = 0;
384
385 if (nCharInfos > 0) {
386 #ifdef HAS_SHM
387 if (!badSysCall)
388 pDesc = (ShmDescPtr) FontGetPrivate(pFont, FontShmdescIndex);
389 if (pDesc) {
390 pCI = (xCharInfo *) pDesc->attach_addr;
391 if (stuff_flags & XF86Bigfont_FLAGS_Shm)
392 shmid = pDesc->shmid;
393 }
394 else {
395 if (stuff_flags & XF86Bigfont_FLAGS_Shm && !badSysCall)
396 pDesc = shmalloc(nCharInfos * sizeof(xCharInfo)
397 + sizeof(CARD32));
398 if (pDesc) {
399 pCI = (xCharInfo *) pDesc->attach_addr;
400 shmid = pDesc->shmid;
401 }
402 else {
403 #endif
404 pCI = malloc(nCharInfos * sizeof(xCharInfo));
405 if (!pCI)
406 return BadAlloc;
407 #ifdef HAS_SHM
408 }
409 #endif
410 /* Fill nCharInfos starting at pCI. */
411 {
412 xCharInfo *prCI = pCI;
413 int ninfos = 0;
414 int ncols = pFont->info.lastCol - pFont->info.firstCol + 1;
415 int row;
416
417 for (row = pFont->info.firstRow;
418 row <= pFont->info.lastRow && ninfos < nCharInfos; row++) {
419 unsigned char chars[512];
420 xCharInfo *tmpCharInfos[256];
421 unsigned long count;
422 int col;
423 unsigned long i;
424
425 i = 0;
426 for (col = pFont->info.firstCol;
427 col <= pFont->info.lastCol; col++) {
428 chars[i++] = row;
429 chars[i++] = col;
430 }
431 (*pFont->get_metrics) (pFont, ncols, chars, TwoD16Bit,
432 &count, tmpCharInfos);
433 for (i = 0; i < count && ninfos < nCharInfos; i++) {
434 *prCI++ = *tmpCharInfos[i];
435 ninfos++;
436 }
437 }
438 }
439 #ifdef HAS_SHM
440 if (pDesc && !badSysCall) {
441 *(CARD32 *) (pCI + nCharInfos) = signature;
442 if (!FontSetPrivate(pFont, FontShmdescIndex, pDesc)) {
443 shmdealloc(pDesc);
444 return BadAlloc;
445 }
446 }
447 }
448 #endif
449 if (shmid == -1) {
450 /* Cannot use shared memory, so remove-duplicates the xCharInfos
451 using a temporary hash table. */
452 /* Note that CARD16 is suitable as index type, because
453 nCharInfos <= 0x10000. */
454 CARD32 hashModulus;
455 CARD16 *pHash2UniqIndex;
456 CARD16 *pUniqIndex2NextUniqIndex;
457 CARD32 NextIndex;
458 CARD32 NextUniqIndex;
459 CARD16 *tmp;
460 CARD32 i, j;
461
462 hashModulus = 67;
463 if (hashModulus > nCharInfos + 1)
464 hashModulus = nCharInfos + 1;
465
466 tmp = malloc((4 * nCharInfos + 1) * sizeof(CARD16));
467 if (!tmp) {
468 if (!pDesc)
469 free(pCI);
470 return BadAlloc;
471 }
472 pIndex2UniqIndex = tmp;
473 /* nCharInfos elements */
474 pUniqIndex2Index = tmp + nCharInfos;
475 /* max. nCharInfos elements */
476 pUniqIndex2NextUniqIndex = tmp + 2 * nCharInfos;
477 /* max. nCharInfos elements */
478 pHash2UniqIndex = tmp + 3 * nCharInfos;
479 /* hashModulus (<= nCharInfos+1) elements */
480
481 /* Note that we can use 0xffff as end-of-list indicator, because
482 even if nCharInfos = 0x10000, 0xffff can not occur as valid
483 entry before the last element has been inserted. And once the
484 last element has been inserted, we don't need the hash table
485 any more. */
486 for (j = 0; j < hashModulus; j++)
487 pHash2UniqIndex[j] = (CARD16) (-1);
488
489 NextUniqIndex = 0;
490 for (NextIndex = 0; NextIndex < nCharInfos; NextIndex++) {
491 xCharInfo *p = &pCI[NextIndex];
492 CARD32 hashCode = hashCI(p) % hashModulus;
493
494 for (i = pHash2UniqIndex[hashCode];
495 i != (CARD16) (-1); i = pUniqIndex2NextUniqIndex[i]) {
496 j = pUniqIndex2Index[i];
497 if (pCI[j].leftSideBearing == p->leftSideBearing
498 && pCI[j].rightSideBearing == p->rightSideBearing
499 && pCI[j].characterWidth == p->characterWidth
500 && pCI[j].ascent == p->ascent
501 && pCI[j].descent == p->descent
502 && pCI[j].attributes == p->attributes)
503 break;
504 }
505 if (i != (CARD16) (-1)) {
506 /* Found *p at Index j, UniqIndex i */
507 pIndex2UniqIndex[NextIndex] = i;
508 }
509 else {
510 /* Allocate a new entry in the Uniq table */
511 if (hashModulus <= 2 * NextUniqIndex
512 && hashModulus < nCharInfos + 1) {
513 /* Time to increate hash table size */
514 hashModulus = 2 * hashModulus + 1;
515 if (hashModulus > nCharInfos + 1)
516 hashModulus = nCharInfos + 1;
517 for (j = 0; j < hashModulus; j++)
518 pHash2UniqIndex[j] = (CARD16) (-1);
519 for (i = 0; i < NextUniqIndex; i++)
520 pUniqIndex2NextUniqIndex[i] = (CARD16) (-1);
521 for (i = 0; i < NextUniqIndex; i++) {
522 j = pUniqIndex2Index[i];
523 p = &pCI[j];
524 hashCode = hashCI(p) % hashModulus;
525 pUniqIndex2NextUniqIndex[i] =
526 pHash2UniqIndex[hashCode];
527 pHash2UniqIndex[hashCode] = i;
528 }
529 p = &pCI[NextIndex];
530 hashCode = hashCI(p) % hashModulus;
531 }
532 i = NextUniqIndex++;
533 pUniqIndex2NextUniqIndex[i] = pHash2UniqIndex[hashCode];
534 pHash2UniqIndex[hashCode] = i;
535 pUniqIndex2Index[i] = NextIndex;
536 pIndex2UniqIndex[NextIndex] = i;
537 }
538 }
539 nUniqCharInfos = NextUniqIndex;
540 /* fprintf(stderr, "font metrics: nCharInfos = %d, nUniqCharInfos = %d, hashModulus = %d\n", nCharInfos, nUniqCharInfos, hashModulus); */
541 }
542 }
543
544 {
545 int nfontprops = pFont->info.nprops;
546 int rlength = sizeof(xXF86BigfontQueryFontReply)
547 + nfontprops * sizeof(xFontProp)
548 + (nCharInfos > 0 && shmid == -1
549 ? nUniqCharInfos * sizeof(xCharInfo)
550 + (nCharInfos + 1) / 2 * 2 * sizeof(CARD16)
551 : 0);
552 xXF86BigfontQueryFontReply *reply = calloc(1, rlength);
553 char *p;
554
555 if (!reply) {
556 if (nCharInfos > 0) {
557 if (shmid == -1)
558 free(pIndex2UniqIndex);
559 if (!pDesc)
560 free(pCI);
561 }
562 return BadAlloc;
563 }
564 reply->type = X_Reply;
565 reply->length = bytes_to_int32(rlength - sizeof(xGenericReply));
566 reply->sequenceNumber = client->sequence;
567 reply->minBounds = pFont->info.ink_minbounds;
568 reply->maxBounds = pFont->info.ink_maxbounds;
569 reply->minCharOrByte2 = pFont->info.firstCol;
570 reply->maxCharOrByte2 = pFont->info.lastCol;
571 reply->defaultChar = pFont->info.defaultCh;
572 reply->nFontProps = pFont->info.nprops;
573 reply->drawDirection = pFont->info.drawDirection;
574 reply->minByte1 = pFont->info.firstRow;
575 reply->maxByte1 = pFont->info.lastRow;
576 reply->allCharsExist = pFont->info.allExist;
577 reply->fontAscent = pFont->info.fontAscent;
578 reply->fontDescent = pFont->info.fontDescent;
579 reply->nCharInfos = nCharInfos;
580 reply->nUniqCharInfos = nUniqCharInfos;
581 reply->shmid = shmid;
582 reply->shmsegoffset = 0;
583 if (client->swapped) {
584 swaps(&reply->sequenceNumber);
585 swapl(&reply->length);
586 swapCharInfo(&reply->minBounds);
587 swapCharInfo(&reply->maxBounds);
588 swaps(&reply->minCharOrByte2);
589 swaps(&reply->maxCharOrByte2);
590 swaps(&reply->defaultChar);
591 swaps(&reply->nFontProps);
592 swaps(&reply->fontAscent);
593 swaps(&reply->fontDescent);
594 swapl(&reply->nCharInfos);
595 swapl(&reply->nUniqCharInfos);
596 swapl(&reply->shmid);
597 swapl(&reply->shmsegoffset);
598 }
599 p = (char *) &reply[1];
600 {
601 FontPropPtr pFP;
602 xFontProp *prFP;
603 int i;
604
605 for (i = 0, pFP = pFont->info.props, prFP = (xFontProp *) p;
606 i < nfontprops; i++, pFP++, prFP++) {
607 prFP->name = pFP->name;
608 prFP->value = pFP->value;
609 if (client->swapped) {
610 swapl(&prFP->name);
611 swapl(&prFP->value);
612 }
613 }
614 p = (char *) prFP;
615 }
616 if (nCharInfos > 0 && shmid == -1) {
617 xCharInfo *pci;
618 CARD16 *ps;
619 int i, j;
620
621 pci = (xCharInfo *) p;
622 for (i = 0; i < nUniqCharInfos; i++, pci++) {
623 *pci = pCI[pUniqIndex2Index[i]];
624 if (client->swapped)
625 swapCharInfo(pci);
626 }
627 ps = (CARD16 *) pci;
628 for (j = 0; j < nCharInfos; j++, ps++) {
629 *ps = pIndex2UniqIndex[j];
630 if (client->swapped) {
631 swaps(ps);
632 }
633 }
634 }
635 WriteToClient(client, rlength, reply);
636 free(reply);
637 if (nCharInfos > 0) {
638 if (shmid == -1)
639 free(pIndex2UniqIndex);
640 if (!pDesc)
641 free(pCI);
642 }
643 return Success;
644 }
645 }
646
647 static int
648 ProcXF86BigfontDispatch(ClientPtr client)
649 {
650 REQUEST(xReq);
651
652 switch (stuff->data) {
653 case X_XF86BigfontQueryVersion:
654 return ProcXF86BigfontQueryVersion(client);
655 case X_XF86BigfontQueryFont:
656 return ProcXF86BigfontQueryFont(client);
657 default:
658 return BadRequest;
659 }
660 }
661
662 static int
663 SProcXF86BigfontQueryVersion(ClientPtr client)
664 {
665 REQUEST(xXF86BigfontQueryVersionReq);
666
667 swaps(&stuff->length);
668 return ProcXF86BigfontQueryVersion(client);
669 }
670
671 static int
672 SProcXF86BigfontQueryFont(ClientPtr client)
673 {
674 REQUEST(xXF86BigfontQueryFontReq);
675
676 swaps(&stuff->length);
677 REQUEST_SIZE_MATCH(xXF86BigfontQueryFontReq);
678 swapl(&stuff->id);
679 return ProcXF86BigfontQueryFont(client);
680 }
681
682 static int
683 SProcXF86BigfontDispatch(ClientPtr client)
684 {
685 REQUEST(xReq);
686
687 switch (stuff->data) {
688 case X_XF86BigfontQueryVersion:
689 return SProcXF86BigfontQueryVersion(client);
690 case X_XF86BigfontQueryFont:
691 return SProcXF86BigfontQueryFont(client);
692 default:
693 return BadRequest;
694 }
695 }
696
697 void
698 XFree86BigfontExtensionInit(void)
699 {
700 if (AddExtension(XF86BIGFONTNAME,
701 XF86BigfontNumberEvents,
702 XF86BigfontNumberErrors,
703 ProcXF86BigfontDispatch,
704 SProcXF86BigfontDispatch,
705 XF86BigfontResetProc, StandardMinorOpcode)) {
706 #ifdef HAS_SHM
707 #ifdef MUST_CHECK_FOR_SHM_SYSCALL
708 /*
709 * Note: Local-clients will not be optimized without shared memory
710 * support. Remote-client optimization does not depend on shared
711 * memory support. Thus, the extension is still registered even
712 * when shared memory support is not functional.
713 */
714 if (!CheckForShmSyscall()) {
715 ErrorF(XF86BIGFONTNAME
716 " extension local-client optimization disabled due to lack of shared memory support in the kernel\n");
717 return;
718 }
719 #endif
720
721 srand((unsigned int) time(NULL));
722 signature = ((unsigned int) (65536.0 / (RAND_MAX + 1.0) * rand()) << 16)
723 + (unsigned int) (65536.0 / (RAND_MAX + 1.0) * rand());
724 /* fprintf(stderr, "signature = 0x%08X\n", signature); */
725
726 FontShmdescIndex = AllocateFontPrivateIndex();
727
728 #if !defined(CSRG_BASED) && !defined(__CYGWIN__)
729 pagesize = SHMLBA;
730 #else
731 #ifdef _SC_PAGESIZE
732 pagesize = sysconf(_SC_PAGESIZE);
733 #else
734 pagesize = getpagesize();
735 #endif
736 #endif
737 #endif
738 }
739 }