xserver

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

glxdricommon.c (13768B)


      1 /*
      2  * Copyright © 2008 Red Hat, Inc
      3  *
      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 the
      9  * copyright holders not be used in advertising or publicity
     10  * pertaining to distribution of the software without specific,
     11  * written prior permission.  The copyright holders make no
     12  * representations about the suitability of this software for any
     13  * purpose.  It is provided "as is" without express or implied
     14  * warranty.
     15  *
     16  * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
     17  * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
     18  * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
     19  * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
     20  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
     21  * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
     22  * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
     23  * SOFTWARE.
     24  */
     25 
     26 #ifdef HAVE_DIX_CONFIG_H
     27 #include <dix-config.h>
     28 #endif
     29 
     30 #include <ctype.h>
     31 #include <stdint.h>
     32 #include <errno.h>
     33 #include <dlfcn.h>
     34 #include <sys/time.h>
     35 #include <GL/gl.h>
     36 #include <GL/glxtokens.h>
     37 #include <GL/internal/dri_interface.h>
     38 #include <os.h>
     39 #include "extinit.h"
     40 #include "glxserver.h"
     41 #include "glxext.h"
     42 #include "glxcontext.h"
     43 #include "glxscreens.h"
     44 #include "glxdricommon.h"
     45 
     46 #define __ATTRIB(attrib, field) \
     47     { attrib, offsetof(__GLXconfig, field) }
     48 
     49 static const struct {
     50     unsigned int attrib, offset;
     51 } attribMap[] = {
     52 __ATTRIB(__DRI_ATTRIB_BUFFER_SIZE, rgbBits),
     53         __ATTRIB(__DRI_ATTRIB_LEVEL, level),
     54         __ATTRIB(__DRI_ATTRIB_RED_SIZE, redBits),
     55         __ATTRIB(__DRI_ATTRIB_GREEN_SIZE, greenBits),
     56         __ATTRIB(__DRI_ATTRIB_BLUE_SIZE, blueBits),
     57         __ATTRIB(__DRI_ATTRIB_ALPHA_SIZE, alphaBits),
     58         __ATTRIB(__DRI_ATTRIB_DEPTH_SIZE, depthBits),
     59         __ATTRIB(__DRI_ATTRIB_STENCIL_SIZE, stencilBits),
     60         __ATTRIB(__DRI_ATTRIB_ACCUM_RED_SIZE, accumRedBits),
     61         __ATTRIB(__DRI_ATTRIB_ACCUM_GREEN_SIZE, accumGreenBits),
     62         __ATTRIB(__DRI_ATTRIB_ACCUM_BLUE_SIZE, accumBlueBits),
     63         __ATTRIB(__DRI_ATTRIB_ACCUM_ALPHA_SIZE, accumAlphaBits),
     64         __ATTRIB(__DRI_ATTRIB_SAMPLE_BUFFERS, sampleBuffers),
     65         __ATTRIB(__DRI_ATTRIB_SAMPLES, samples),
     66         __ATTRIB(__DRI_ATTRIB_DOUBLE_BUFFER, doubleBufferMode),
     67         __ATTRIB(__DRI_ATTRIB_STEREO, stereoMode),
     68         __ATTRIB(__DRI_ATTRIB_AUX_BUFFERS, numAuxBuffers),
     69         __ATTRIB(__DRI_ATTRIB_TRANSPARENT_TYPE, transparentPixel),
     70         __ATTRIB(__DRI_ATTRIB_TRANSPARENT_INDEX_VALUE, transparentPixel),
     71         __ATTRIB(__DRI_ATTRIB_TRANSPARENT_RED_VALUE, transparentRed),
     72         __ATTRIB(__DRI_ATTRIB_TRANSPARENT_GREEN_VALUE, transparentGreen),
     73         __ATTRIB(__DRI_ATTRIB_TRANSPARENT_BLUE_VALUE, transparentBlue),
     74         __ATTRIB(__DRI_ATTRIB_TRANSPARENT_ALPHA_VALUE, transparentAlpha),
     75         __ATTRIB(__DRI_ATTRIB_RED_MASK, redMask),
     76         __ATTRIB(__DRI_ATTRIB_GREEN_MASK, greenMask),
     77         __ATTRIB(__DRI_ATTRIB_BLUE_MASK, blueMask),
     78         __ATTRIB(__DRI_ATTRIB_ALPHA_MASK, alphaMask),
     79         __ATTRIB(__DRI_ATTRIB_MAX_PBUFFER_WIDTH, maxPbufferWidth),
     80         __ATTRIB(__DRI_ATTRIB_MAX_PBUFFER_HEIGHT, maxPbufferHeight),
     81         __ATTRIB(__DRI_ATTRIB_MAX_PBUFFER_PIXELS, maxPbufferPixels),
     82         __ATTRIB(__DRI_ATTRIB_OPTIMAL_PBUFFER_WIDTH, optimalPbufferWidth),
     83         __ATTRIB(__DRI_ATTRIB_OPTIMAL_PBUFFER_HEIGHT, optimalPbufferHeight),
     84         __ATTRIB(__DRI_ATTRIB_SWAP_METHOD, swapMethod),
     85         __ATTRIB(__DRI_ATTRIB_BIND_TO_TEXTURE_RGB, bindToTextureRgb),
     86         __ATTRIB(__DRI_ATTRIB_BIND_TO_TEXTURE_RGBA, bindToTextureRgba),
     87         __ATTRIB(__DRI_ATTRIB_BIND_TO_MIPMAP_TEXTURE, bindToMipmapTexture),
     88         __ATTRIB(__DRI_ATTRIB_YINVERTED, yInverted),
     89         __ATTRIB(__DRI_ATTRIB_FRAMEBUFFER_SRGB_CAPABLE, sRGBCapable),
     90         };
     91 
     92 static void
     93 setScalar(__GLXconfig * config, unsigned int attrib, unsigned int value)
     94 {
     95     int i;
     96 
     97     for (i = 0; i < ARRAY_SIZE(attribMap); i++)
     98         if (attribMap[i].attrib == attrib) {
     99             *(unsigned int *) ((char *) config + attribMap[i].offset) = value;
    100             return;
    101         }
    102 }
    103 
    104 static Bool
    105 render_type_is_pbuffer_only(unsigned renderType)
    106 {
    107     /* The GL_ARB_color_buffer_float spec says:
    108      *
    109      *     "Note that floating point rendering is only supported for
    110      *     GLXPbuffer drawables.  The GLX_DRAWABLE_TYPE attribute of the
    111      *     GLXFBConfig must have the GLX_PBUFFER_BIT bit set and the
    112      *     GLX_RENDER_TYPE attribute must have the GLX_RGBA_FLOAT_BIT set."
    113      */
    114     return !!(renderType & (__DRI_ATTRIB_UNSIGNED_FLOAT_BIT
    115                             | __DRI_ATTRIB_FLOAT_BIT));
    116 }
    117 
    118 static int
    119 server_has_depth(int depth)
    120 {
    121     int i;
    122     for (i = 0; i < screenInfo.numPixmapFormats; i++)
    123         if (screenInfo.formats[i].depth == depth)
    124             return 1;
    125     return 0;
    126 }
    127 
    128 static __GLXconfig *
    129 createModeFromConfig(const __DRIcoreExtension * core,
    130                      const __DRIconfig * driConfig,
    131                      unsigned int visualType,
    132                      GLboolean duplicateForComp)
    133 {
    134     __GLXDRIconfig *config;
    135     GLint renderType = 0;
    136     unsigned int attrib, value, drawableType = GLX_PBUFFER_BIT;
    137     int i;
    138 
    139 
    140     config = calloc(1, sizeof *config);
    141 
    142     config->driConfig = driConfig;
    143 
    144     i = 0;
    145     while (core->indexConfigAttrib(driConfig, i++, &attrib, &value)) {
    146         switch (attrib) {
    147         case __DRI_ATTRIB_RENDER_TYPE:
    148             if (value & __DRI_ATTRIB_RGBA_BIT)
    149                 renderType |= GLX_RGBA_BIT;
    150             if (value & __DRI_ATTRIB_COLOR_INDEX_BIT)
    151                 renderType |= GLX_COLOR_INDEX_BIT;
    152             if (value & __DRI_ATTRIB_FLOAT_BIT)
    153                 renderType |= GLX_RGBA_FLOAT_BIT_ARB;
    154             if (value & __DRI_ATTRIB_UNSIGNED_FLOAT_BIT)
    155                 renderType |= GLX_RGBA_UNSIGNED_FLOAT_BIT_EXT;
    156             break;
    157         case __DRI_ATTRIB_CONFIG_CAVEAT:
    158             if (value & __DRI_ATTRIB_NON_CONFORMANT_CONFIG)
    159                 config->config.visualRating = GLX_NON_CONFORMANT_CONFIG;
    160             else if (value & __DRI_ATTRIB_SLOW_BIT)
    161                 config->config.visualRating = GLX_SLOW_CONFIG;
    162             else
    163                 config->config.visualRating = GLX_NONE;
    164             break;
    165         case __DRI_ATTRIB_BIND_TO_TEXTURE_TARGETS:
    166             config->config.bindToTextureTargets = 0;
    167             if (value & __DRI_ATTRIB_TEXTURE_1D_BIT)
    168                 config->config.bindToTextureTargets |= GLX_TEXTURE_1D_BIT_EXT;
    169             if (value & __DRI_ATTRIB_TEXTURE_2D_BIT)
    170                 config->config.bindToTextureTargets |= GLX_TEXTURE_2D_BIT_EXT;
    171             if (value & __DRI_ATTRIB_TEXTURE_RECTANGLE_BIT)
    172                 config->config.bindToTextureTargets |=
    173                     GLX_TEXTURE_RECTANGLE_BIT_EXT;
    174             break;
    175         case __DRI_ATTRIB_SWAP_METHOD:
    176             /* Workaround for broken dri drivers */
    177             if (value != GLX_SWAP_UNDEFINED_OML &&
    178                 value != GLX_SWAP_COPY_OML &&
    179                 value != GLX_SWAP_EXCHANGE_OML)
    180                 value = GLX_SWAP_UNDEFINED_OML;
    181             /* Fall through. */
    182         default:
    183             setScalar(&config->config, attrib, value);
    184             break;
    185         }
    186     }
    187 
    188     if (!render_type_is_pbuffer_only(renderType))
    189         drawableType |= GLX_WINDOW_BIT | GLX_PIXMAP_BIT;
    190 
    191     /* Make sure we don't advertise things the server isn't configured for */
    192     if ((drawableType & (GLX_PBUFFER_BIT | GLX_PIXMAP_BIT)) &&
    193         !server_has_depth(config->config.rgbBits)) {
    194         drawableType &= ~(GLX_PBUFFER_BIT | GLX_PIXMAP_BIT);
    195         if (!drawableType) {
    196             free(config);
    197             return NULL;
    198         }
    199     }
    200 
    201     config->config.next = NULL;
    202     config->config.visualType = visualType;
    203     config->config.renderType = renderType;
    204     config->config.drawableType = drawableType;
    205     config->config.yInverted = GL_TRUE;
    206 
    207 #ifdef COMPOSITE
    208     if (!noCompositeExtension) {
    209         /*
    210         * Here we decide what fbconfigs will be duplicated for compositing.
    211         * fgbconfigs marked with duplicatedForConf will be reserved for
    212         * compositing visuals.
    213         * It might look strange to do this decision this late when translation
    214         * from a __DRIConfig is already done, but using the __DRIConfig
    215         * accessor function becomes worse both with respect to code complexity
    216         * and CPU usage.
    217         */
    218         if (duplicateForComp &&
    219             (render_type_is_pbuffer_only(renderType) ||
    220             config->config.rgbBits != 32 ||
    221             config->config.redBits != 8 ||
    222             config->config.greenBits != 8 ||
    223             config->config.blueBits != 8 ||
    224             config->config.visualRating != GLX_NONE ||
    225             config->config.sampleBuffers != 0)) {
    226             free(config);
    227             return NULL;
    228         }
    229 
    230         config->config.duplicatedForComp = duplicateForComp;
    231     }
    232 #endif
    233 
    234     return &config->config;
    235 }
    236 
    237 __GLXconfig *
    238 glxConvertConfigs(const __DRIcoreExtension * core,
    239                   const __DRIconfig ** configs)
    240 {
    241     __GLXconfig head, *tail;
    242     int i;
    243 
    244     tail = &head;
    245     head.next = NULL;
    246 
    247     for (i = 0; configs[i]; i++) {
    248         tail->next = createModeFromConfig(core, configs[i], GLX_TRUE_COLOR,
    249                                           GL_FALSE);
    250         if (tail->next == NULL)
    251             break;
    252         tail = tail->next;
    253     }
    254 
    255     for (i = 0; configs[i]; i++) {
    256         tail->next = createModeFromConfig(core, configs[i], GLX_DIRECT_COLOR,
    257                                           GL_FALSE);
    258         if (tail->next == NULL)
    259             break;
    260 
    261         tail = tail->next;
    262     }
    263 
    264 #ifdef COMPOSITE
    265     if (!noCompositeExtension) {
    266         /* Duplicate fbconfigs for use with compositing visuals */
    267         for (i = 0; configs[i]; i++) {
    268             tail->next = createModeFromConfig(core, configs[i], GLX_TRUE_COLOR,
    269                                             GL_TRUE);
    270             if (tail->next == NULL)
    271                 continue;
    272 
    273             tail = tail->next;
    274         }
    275     }
    276 #endif
    277 
    278     return head.next;
    279 }
    280 
    281 static const char dri_driver_path[] = DRI_DRIVER_PATH;
    282 
    283 /* Temporary define to allow building without a dri_interface.h from
    284  * updated Mesa.  Some day when we don't care about Mesa that old any
    285  * more this can be removed.
    286  */
    287 #ifndef __DRI_DRIVER_GET_EXTENSIONS
    288 #define __DRI_DRIVER_GET_EXTENSIONS "__driDriverGetExtensions"
    289 #endif
    290 
    291 void *
    292 glxProbeDriver(const char *driverName,
    293                void **coreExt, const char *coreName, int coreVersion,
    294                void **renderExt, const char *renderName, int renderVersion)
    295 {
    296     int i;
    297     void *driver;
    298     char filename[PATH_MAX];
    299     char *get_extensions_name;
    300     const __DRIextension **extensions = NULL;
    301     const char *path = NULL;
    302 
    303     /* Search in LIBGL_DRIVERS_PATH if we're not setuid. */
    304     if (!PrivsElevated())
    305         path = getenv("LIBGL_DRIVERS_PATH");
    306 
    307     if (!path)
    308         path = dri_driver_path;
    309 
    310     do {
    311         const char *next;
    312         int path_len;
    313 
    314         next = strchr(path, ':');
    315         if (next) {
    316             path_len = next - path;
    317             next++;
    318         } else {
    319             path_len = strlen(path);
    320             next = NULL;
    321         }
    322 
    323         snprintf(filename, sizeof filename, "%.*s/%s_dri.so", path_len, path,
    324                  driverName);
    325 
    326         driver = dlopen(filename, RTLD_LAZY | RTLD_LOCAL);
    327         if (driver != NULL)
    328             break;
    329 
    330         LogMessage(X_ERROR, "AIGLX error: dlopen of %s failed (%s)\n",
    331                    filename, dlerror());
    332 
    333         path = next;
    334     } while (path);
    335 
    336     if (driver == NULL) {
    337         LogMessage(X_ERROR, "AIGLX error: unable to load driver %s\n",
    338                   driverName);
    339         goto cleanup_failure;
    340     }
    341 
    342     if (asprintf(&get_extensions_name, "%s_%s",
    343                  __DRI_DRIVER_GET_EXTENSIONS, driverName) != -1) {
    344         const __DRIextension **(*get_extensions)(void);
    345 
    346         for (i = 0; i < strlen(get_extensions_name); i++) {
    347             /* Replace all non-alphanumeric characters with underscore,
    348              * since they are not allowed in C symbol names. That fixes up
    349              * symbol name for drivers with '-drm' suffix
    350              */
    351             if (!isalnum(get_extensions_name[i]))
    352                 get_extensions_name[i] = '_';
    353         }
    354 
    355         get_extensions = dlsym(driver, get_extensions_name);
    356         if (get_extensions)
    357             extensions = get_extensions();
    358         free(get_extensions_name);
    359     }
    360 
    361     if (!extensions)
    362         extensions = dlsym(driver, __DRI_DRIVER_EXTENSIONS);
    363     if (extensions == NULL) {
    364         LogMessage(X_ERROR, "AIGLX error: %s exports no extensions (%s)\n",
    365                    driverName, dlerror());
    366         goto cleanup_failure;
    367     }
    368 
    369     for (i = 0; extensions[i]; i++) {
    370         if (strcmp(extensions[i]->name, coreName) == 0 &&
    371             extensions[i]->version >= coreVersion) {
    372             *coreExt = (void *) extensions[i];
    373         }
    374 
    375         if (strcmp(extensions[i]->name, renderName) == 0 &&
    376             extensions[i]->version >= renderVersion) {
    377             *renderExt = (void *) extensions[i];
    378         }
    379     }
    380 
    381     if (*coreExt == NULL || *renderExt == NULL) {
    382         LogMessage(X_ERROR,
    383                    "AIGLX error: %s does not export required DRI extension\n",
    384                    driverName);
    385         goto cleanup_failure;
    386     }
    387     return driver;
    388 
    389  cleanup_failure:
    390     if (driver)
    391         dlclose(driver);
    392     *coreExt = *renderExt = NULL;
    393     return NULL;
    394 }