xserver

xserver with xephyr scale patch
git clone https://git.neptards.moe/u3shit/xserver.git
Log | Files | Refs | README | LICENSE

single2.c (11164B)


      1 /*
      2  * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
      3  * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
      4  *
      5  * Permission is hereby granted, free of charge, to any person obtaining a
      6  * copy of this software and associated documentation files (the "Software"),
      7  * to deal in the Software without restriction, including without limitation
      8  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      9  * and/or sell copies of the Software, and to permit persons to whom the
     10  * Software is furnished to do so, subject to the following conditions:
     11  *
     12  * The above copyright notice including the dates of first publication and
     13  * either this permission notice or a reference to
     14  * http://oss.sgi.com/projects/FreeB/
     15  * shall be included in all copies or substantial portions of the Software.
     16  *
     17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
     18  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     19  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
     20  * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
     21  * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
     22  * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
     23  * SOFTWARE.
     24  *
     25  * Except as contained in this notice, the name of Silicon Graphics, Inc.
     26  * shall not be used in advertising or otherwise to promote the sale, use or
     27  * other dealings in this Software without prior written authorization from
     28  * Silicon Graphics, Inc.
     29  */
     30 
     31 #ifdef HAVE_DIX_CONFIG_H
     32 #include <dix-config.h>
     33 #endif
     34 
     35 #include <string.h>
     36 #include <stdio.h>
     37 #include <stdlib.h>
     38 
     39 #include "glxserver.h"
     40 #include "glxutil.h"
     41 #include "glxext.h"
     42 #include "indirect_dispatch.h"
     43 #include "unpack.h"
     44 
     45 int
     46 __glXDisp_FeedbackBuffer(__GLXclientState * cl, GLbyte * pc)
     47 {
     48     ClientPtr client = cl->client;
     49     GLsizei size;
     50     GLenum type;
     51     __GLXcontext *cx;
     52     int error;
     53 
     54     REQUEST_FIXED_SIZE(xGLXSingleReq, 8);
     55 
     56     cx = __glXForceCurrent(cl, __GLX_GET_SINGLE_CONTEXT_TAG(pc), &error);
     57     if (!cx) {
     58         return error;
     59     }
     60 
     61     pc += __GLX_SINGLE_HDR_SIZE;
     62     size = *(GLsizei *) (pc + 0);
     63     type = *(GLenum *) (pc + 4);
     64     if (cx->feedbackBufSize < size) {
     65         cx->feedbackBuf = reallocarray(cx->feedbackBuf,
     66                                        (size_t) size, __GLX_SIZE_FLOAT32);
     67         if (!cx->feedbackBuf) {
     68             cl->client->errorValue = size;
     69             return BadAlloc;
     70         }
     71         cx->feedbackBufSize = size;
     72     }
     73     glFeedbackBuffer(size, type, cx->feedbackBuf);
     74     return Success;
     75 }
     76 
     77 int
     78 __glXDisp_SelectBuffer(__GLXclientState * cl, GLbyte * pc)
     79 {
     80     ClientPtr client = cl->client;
     81     __GLXcontext *cx;
     82     GLsizei size;
     83     int error;
     84 
     85     REQUEST_FIXED_SIZE(xGLXSingleReq, 4);
     86 
     87     cx = __glXForceCurrent(cl, __GLX_GET_SINGLE_CONTEXT_TAG(pc), &error);
     88     if (!cx) {
     89         return error;
     90     }
     91 
     92     pc += __GLX_SINGLE_HDR_SIZE;
     93     size = *(GLsizei *) (pc + 0);
     94     if (cx->selectBufSize < size) {
     95         cx->selectBuf = reallocarray(cx->selectBuf,
     96                                      (size_t) size, __GLX_SIZE_CARD32);
     97         if (!cx->selectBuf) {
     98             cl->client->errorValue = size;
     99             return BadAlloc;
    100         }
    101         cx->selectBufSize = size;
    102     }
    103     glSelectBuffer(size, cx->selectBuf);
    104     return Success;
    105 }
    106 
    107 int
    108 __glXDisp_RenderMode(__GLXclientState * cl, GLbyte * pc)
    109 {
    110     ClientPtr client = cl->client;
    111     xGLXRenderModeReply reply;
    112     __GLXcontext *cx;
    113     GLint nitems = 0, retBytes = 0, retval, newModeCheck;
    114     GLubyte *retBuffer = NULL;
    115     GLenum newMode;
    116     int error;
    117 
    118     REQUEST_FIXED_SIZE(xGLXSingleReq, 4);
    119 
    120     cx = __glXForceCurrent(cl, __GLX_GET_SINGLE_CONTEXT_TAG(pc), &error);
    121     if (!cx) {
    122         return error;
    123     }
    124 
    125     pc += __GLX_SINGLE_HDR_SIZE;
    126     newMode = *(GLenum *) pc;
    127     retval = glRenderMode(newMode);
    128 
    129     /* Check that render mode worked */
    130     glGetIntegerv(GL_RENDER_MODE, &newModeCheck);
    131     if (newModeCheck != newMode) {
    132         /* Render mode change failed.  Bail */
    133         newMode = newModeCheck;
    134         goto noChangeAllowed;
    135     }
    136 
    137     /*
    138      ** Render mode might have still failed if we get here.  But in this
    139      ** case we can't really tell, nor does it matter.  If it did fail, it
    140      ** will return 0, and thus we won't send any data across the wire.
    141      */
    142 
    143     switch (cx->renderMode) {
    144     case GL_RENDER:
    145         cx->renderMode = newMode;
    146         break;
    147     case GL_FEEDBACK:
    148         if (retval < 0) {
    149             /* Overflow happened. Copy the entire buffer */
    150             nitems = cx->feedbackBufSize;
    151         }
    152         else {
    153             nitems = retval;
    154         }
    155         retBytes = nitems * __GLX_SIZE_FLOAT32;
    156         retBuffer = (GLubyte *) cx->feedbackBuf;
    157         cx->renderMode = newMode;
    158         break;
    159     case GL_SELECT:
    160         if (retval < 0) {
    161             /* Overflow happened.  Copy the entire buffer */
    162             nitems = cx->selectBufSize;
    163         }
    164         else {
    165             GLuint *bp = cx->selectBuf;
    166             GLint i;
    167 
    168             /*
    169              ** Figure out how many bytes of data need to be sent.  Parse
    170              ** the selection buffer to determine this fact as the
    171              ** return value is the number of hits, not the number of
    172              ** items in the buffer.
    173              */
    174             nitems = 0;
    175             i = retval;
    176             while (--i >= 0) {
    177                 GLuint n;
    178 
    179                 /* Parse select data for this hit */
    180                 n = *bp;
    181                 bp += 3 + n;
    182             }
    183             nitems = bp - cx->selectBuf;
    184         }
    185         retBytes = nitems * __GLX_SIZE_CARD32;
    186         retBuffer = (GLubyte *) cx->selectBuf;
    187         cx->renderMode = newMode;
    188         break;
    189     }
    190 
    191     /*
    192      ** First reply is the number of elements returned in the feedback or
    193      ** selection array, as per the API for glRenderMode itself.
    194      */
    195  noChangeAllowed:;
    196     reply = (xGLXRenderModeReply) {
    197         .type = X_Reply,
    198         .sequenceNumber = client->sequence,
    199         .length = nitems,
    200         .retval = retval,
    201         .size = nitems,
    202         .newMode = newMode
    203     };
    204     WriteToClient(client, sz_xGLXRenderModeReply, &reply);
    205     if (retBytes) {
    206         WriteToClient(client, retBytes, retBuffer);
    207     }
    208     return Success;
    209 }
    210 
    211 int
    212 __glXDisp_Flush(__GLXclientState * cl, GLbyte * pc)
    213 {
    214     ClientPtr client = cl->client;
    215     __GLXcontext *cx;
    216     int error;
    217 
    218     REQUEST_SIZE_MATCH(xGLXSingleReq);
    219 
    220     cx = __glXForceCurrent(cl, __GLX_GET_SINGLE_CONTEXT_TAG(pc), &error);
    221     if (!cx) {
    222         return error;
    223     }
    224 
    225     glFlush();
    226     return Success;
    227 }
    228 
    229 int
    230 __glXDisp_Finish(__GLXclientState * cl, GLbyte * pc)
    231 {
    232     ClientPtr client = cl->client;
    233     __GLXcontext *cx;
    234     int error;
    235     xGLXSingleReply reply = { 0, };
    236 
    237     REQUEST_SIZE_MATCH(xGLXSingleReq);
    238 
    239     cx = __glXForceCurrent(cl, __GLX_GET_SINGLE_CONTEXT_TAG(pc), &error);
    240     if (!cx) {
    241         return error;
    242     }
    243 
    244     /* Do a local glFinish */
    245     glFinish();
    246 
    247     /* Send empty reply packet to indicate finish is finished */
    248     client = cl->client;
    249     __GLX_BEGIN_REPLY(0);
    250     __GLX_SEND_HEADER();
    251     return Success;
    252 }
    253 
    254 #define SEPARATOR " "
    255 
    256 static char *
    257 __glXcombine_strings(const char *cext_string, const char *sext_string)
    258 {
    259     size_t clen, slen;
    260     char *combo_string, *token, *s1;
    261     const char *s2, *end;
    262 
    263     /* safeguard to prevent potentially fatal errors in the string functions */
    264     if (!cext_string)
    265         cext_string = "";
    266     if (!sext_string)
    267         sext_string = "";
    268 
    269     /*
    270      ** String can't be longer than min(cstring, sstring)
    271      ** pull tokens out of shortest string
    272      ** include space in combo_string for final separator and null terminator
    273      */
    274     clen = strlen(cext_string);
    275     slen = strlen(sext_string);
    276     if (clen > slen) {
    277         combo_string = (char *) malloc(slen + 2);
    278         s1 = (char *) malloc(slen + 2);
    279         if (s1)
    280             strcpy(s1, sext_string);
    281         s2 = cext_string;
    282     }
    283     else {
    284         combo_string = (char *) malloc(clen + 2);
    285         s1 = (char *) malloc(clen + 2);
    286         if (s1)
    287             strcpy(s1, cext_string);
    288         s2 = sext_string;
    289     }
    290     if (!combo_string || !s1) {
    291         free(combo_string);
    292         free(s1);
    293         return NULL;
    294     }
    295     combo_string[0] = '\0';
    296 
    297     /* Get first extension token */
    298     token = strtok(s1, SEPARATOR);
    299     while (token != NULL) {
    300 
    301         /*
    302          ** if token in second string then save it
    303          ** beware of extension names which are prefixes of other extension names
    304          */
    305         const char *p = s2;
    306 
    307         end = p + strlen(p);
    308         while (p < end) {
    309             size_t n = strcspn(p, SEPARATOR);
    310 
    311             if ((strlen(token) == n) && (strncmp(token, p, n) == 0)) {
    312                 combo_string = strcat(combo_string, token);
    313                 combo_string = strcat(combo_string, SEPARATOR);
    314             }
    315             p += (n + 1);
    316         }
    317 
    318         /* Get next extension token */
    319         token = strtok(NULL, SEPARATOR);
    320     }
    321     free(s1);
    322     return combo_string;
    323 }
    324 
    325 int
    326 DoGetString(__GLXclientState * cl, GLbyte * pc, GLboolean need_swap)
    327 {
    328     ClientPtr client = cl->client;
    329     __GLXcontext *cx;
    330     GLenum name;
    331     const char *string;
    332     xGLXSingleReply reply = { 0, };
    333 
    334     __GLX_DECLARE_SWAP_VARIABLES;
    335     int error;
    336     char *buf = NULL, *buf1 = NULL;
    337     GLint length = 0;
    338 
    339     REQUEST_FIXED_SIZE(xGLXSingleReq, 4);
    340 
    341     /* If the client has the opposite byte order, swap the contextTag and
    342      * the name.
    343      */
    344     if (need_swap) {
    345         __GLX_SWAP_INT(pc + 4);
    346         __GLX_SWAP_INT(pc + __GLX_SINGLE_HDR_SIZE);
    347     }
    348 
    349     cx = __glXForceCurrent(cl, __GLX_GET_SINGLE_CONTEXT_TAG(pc), &error);
    350     if (!cx) {
    351         return error;
    352     }
    353 
    354     pc += __GLX_SINGLE_HDR_SIZE;
    355     name = *(GLenum *) (pc + 0);
    356     string = (const char *) glGetString(name);
    357 
    358     if (string == NULL)
    359         string = "";
    360 
    361     /*
    362      ** Restrict extensions to those that are supported by both the
    363      ** implementation and the connection.  That is, return the
    364      ** intersection of client, server, and core extension strings.
    365      */
    366     if (name == GL_EXTENSIONS) {
    367         buf1 = __glXcombine_strings(string, cl->GLClientextensions);
    368         buf = __glXcombine_strings(buf1, cx->pGlxScreen->GLextensions);
    369         free(buf1);
    370         string = buf;
    371     }
    372     else if (name == GL_VERSION) {
    373         if (atof(string) > atof(GLServerVersion)) {
    374             if (asprintf(&buf, "%s (%s)", GLServerVersion, string) == -1) {
    375                 string = GLServerVersion;
    376             }
    377             else {
    378                 string = buf;
    379             }
    380         }
    381     }
    382     if (string) {
    383         length = strlen((const char *) string) + 1;
    384     }
    385 
    386     __GLX_BEGIN_REPLY(length);
    387     __GLX_PUT_SIZE(length);
    388 
    389     if (need_swap) {
    390         __GLX_SWAP_REPLY_SIZE();
    391         __GLX_SWAP_REPLY_HEADER();
    392     }
    393 
    394     __GLX_SEND_HEADER();
    395     WriteToClient(client, length, string);
    396     free(buf);
    397 
    398     return Success;
    399 }
    400 
    401 int
    402 __glXDisp_GetString(__GLXclientState * cl, GLbyte * pc)
    403 {
    404     return DoGetString(cl, pc, GL_FALSE);
    405 }