| /* |
| * (C) Copyright IBM Corporation 2003 |
| * All Rights Reserved. |
| * |
| * Permission is hereby granted, free of charge, to any person obtaining a |
| * copy of this software and associated documentation files (the "Software"), |
| * to deal in the Software without restriction, including without limitation |
| * on the rights to use, copy, modify, merge, publish, distribute, sub |
| * license, and/or sell copies of the Software, and to permit persons to whom |
| * the Software is furnished to do so, subject to the following conditions: |
| * |
| * The above copyright notice and this permission notice (including the next |
| * paragraph) shall be included in all copies or substantial portions of the |
| * Software. |
| * |
| * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
| * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
| * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL |
| * VA LINUX SYSTEM, IBM AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, |
| * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR |
| * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE |
| * USE OR OTHER DEALINGS IN THE SOFTWARE. |
| */ |
| |
| /** |
| * \file glcontextmodes.c |
| * Utility routines for working with \c __GLcontextModes structures. At |
| * some point most or all of these functions will be moved to the Mesa |
| * code base. |
| * |
| * \author Ian Romanick <idr@us.ibm.com> |
| */ |
| |
| #if defined(IN_MINI_GLX) |
| #include <GL/gl.h> |
| #else |
| #if defined(HAVE_DIX_CONFIG_H) |
| # include <dix-config.h> |
| #endif |
| #include <X11/X.h> |
| #include <GL/glx.h> |
| #include "GL/glxint.h" |
| #endif |
| |
| /* Memory macros */ |
| #if defined(IN_MINI_GLX) |
| # include <stdlib.h> |
| # include <string.h> |
| # define _mesa_malloc(b) malloc(b) |
| # define _mesa_free(m) free(m) |
| # define _mesa_memset memset |
| #else |
| # ifdef XFree86Server |
| # include <os.h> |
| # include <string.h> |
| # define _mesa_malloc(b) xalloc(b) |
| # define _mesa_free(m) xfree(m) |
| # define _mesa_memset memset |
| # else |
| # include <X11/Xlibint.h> |
| # define _mesa_memset memset |
| # define _mesa_malloc(b) Xmalloc(b) |
| # define _mesa_free(m) Xfree(m) |
| # endif /* XFree86Server */ |
| #endif /* !defined(IN_MINI_GLX) */ |
| |
| #include "glcontextmodes.h" |
| |
| #if !defined(IN_MINI_GLX) |
| #define NUM_VISUAL_TYPES 6 |
| |
| /** |
| * Convert an X visual type to a GLX visual type. |
| * |
| * \param visualType X visual type (i.e., \c TrueColor, \c StaticGray, etc.) |
| * to be converted. |
| * \return If \c visualType is a valid X visual type, a GLX visual type will |
| * be returned. Otherwise \c GLX_NONE will be returned. |
| */ |
| GLint |
| _gl_convert_from_x_visual_type(int visualType) |
| { |
| static const int glx_visual_types[NUM_VISUAL_TYPES] = { |
| GLX_STATIC_GRAY, GLX_GRAY_SCALE, |
| GLX_STATIC_COLOR, GLX_PSEUDO_COLOR, |
| GLX_TRUE_COLOR, GLX_DIRECT_COLOR |
| }; |
| |
| return ((unsigned) visualType < NUM_VISUAL_TYPES) |
| ? glx_visual_types[visualType] : GLX_NONE; |
| } |
| |
| |
| /** |
| * Convert a GLX visual type to an X visual type. |
| * |
| * \param visualType GLX visual type (i.e., \c GLX_TRUE_COLOR, |
| * \c GLX_STATIC_GRAY, etc.) to be converted. |
| * \return If \c visualType is a valid GLX visual type, an X visual type will |
| * be returned. Otherwise -1 will be returned. |
| */ |
| GLint |
| _gl_convert_to_x_visual_type(int visualType) |
| { |
| static const int x_visual_types[NUM_VISUAL_TYPES] = { |
| TrueColor, DirectColor, |
| PseudoColor, StaticColor, |
| GrayScale, StaticGray |
| }; |
| |
| return ((unsigned) (visualType - GLX_TRUE_COLOR) < NUM_VISUAL_TYPES) |
| ? x_visual_types[visualType - GLX_TRUE_COLOR] : -1; |
| } |
| |
| |
| /** |
| * Copy a GLX visual config structure to a GL context mode structure. All |
| * of the fields in \c config are copied to \c mode. Additional fields in |
| * \c mode that can be derrived from the fields of \c config (i.e., |
| * \c haveDepthBuffer) are also filled in. The remaining fields in \c mode |
| * that cannot be derived are set to default values. |
| * |
| * \param mode Destination GL context mode. |
| * \param config Source GLX visual config. |
| * |
| * \note |
| * The \c fbconfigID and \c visualID fields of the \c __GLcontextModes |
| * structure will be set to the \c vid of the \c __GLXvisualConfig structure. |
| */ |
| void |
| _gl_copy_visual_to_context_mode(__GLcontextModes * mode, |
| const __GLXvisualConfig * config) |
| { |
| __GLcontextModes *const next = mode->next; |
| |
| (void) _mesa_memset(mode, 0, sizeof(__GLcontextModes)); |
| mode->next = next; |
| |
| mode->visualID = config->vid; |
| mode->visualType = _gl_convert_from_x_visual_type(config->class); |
| mode->xRenderable = GL_TRUE; |
| mode->fbconfigID = config->vid; |
| mode->drawableType = GLX_WINDOW_BIT | GLX_PIXMAP_BIT; |
| |
| mode->rgbMode = (config->rgba != 0); |
| mode->renderType = (mode->rgbMode) ? GLX_RGBA_BIT : GLX_COLOR_INDEX_BIT; |
| |
| mode->colorIndexMode = !(mode->rgbMode); |
| mode->doubleBufferMode = (config->doubleBuffer != 0); |
| mode->stereoMode = (config->stereo != 0); |
| |
| mode->haveAccumBuffer = ((config->accumRedSize + |
| config->accumGreenSize + |
| config->accumBlueSize + |
| config->accumAlphaSize) > 0); |
| mode->haveDepthBuffer = (config->depthSize > 0); |
| mode->haveStencilBuffer = (config->stencilSize > 0); |
| |
| mode->redBits = config->redSize; |
| mode->greenBits = config->greenSize; |
| mode->blueBits = config->blueSize; |
| mode->alphaBits = config->alphaSize; |
| mode->redMask = config->redMask; |
| mode->greenMask = config->greenMask; |
| mode->blueMask = config->blueMask; |
| mode->alphaMask = config->alphaMask; |
| mode->rgbBits = mode->rgbMode ? config->bufferSize : 0; |
| mode->indexBits = mode->colorIndexMode ? config->bufferSize : 0; |
| |
| mode->accumRedBits = config->accumRedSize; |
| mode->accumGreenBits = config->accumGreenSize; |
| mode->accumBlueBits = config->accumBlueSize; |
| mode->accumAlphaBits = config->accumAlphaSize; |
| mode->depthBits = config->depthSize; |
| mode->stencilBits = config->stencilSize; |
| |
| mode->numAuxBuffers = config->auxBuffers; |
| mode->level = config->level; |
| |
| mode->visualRating = config->visualRating; |
| mode->transparentPixel = config->transparentPixel; |
| mode->transparentRed = config->transparentRed; |
| mode->transparentGreen = config->transparentGreen; |
| mode->transparentBlue = config->transparentBlue; |
| mode->transparentAlpha = config->transparentAlpha; |
| mode->transparentIndex = config->transparentIndex; |
| mode->samples = config->multiSampleSize; |
| mode->sampleBuffers = config->nMultiSampleBuffers; |
| /* mode->visualSelectGroup = config->visualSelectGroup; ? */ |
| |
| mode->swapMethod = GLX_SWAP_UNDEFINED_OML; |
| |
| mode->bindToTextureRgb = (mode->rgbMode) ? GL_TRUE : GL_FALSE; |
| mode->bindToTextureRgba = (mode->rgbMode && mode->alphaBits) ? |
| GL_TRUE : GL_FALSE; |
| mode->bindToMipmapTexture = mode->rgbMode ? GL_TRUE : GL_FALSE; |
| mode->bindToTextureTargets = mode->rgbMode ? |
| GLX_TEXTURE_1D_BIT_EXT | GLX_TEXTURE_2D_BIT_EXT | |
| GLX_TEXTURE_RECTANGLE_BIT_EXT : 0; |
| mode->yInverted = GL_FALSE; |
| } |
| |
| |
| /** |
| * Get data from a GL context mode. |
| * |
| * \param mode GL context mode whose data is to be returned. |
| * \param attribute Attribute of \c mode that is to be returned. |
| * \param value_return Location to store the data member of \c mode. |
| * \return If \c attribute is a valid attribute of \c mode, zero is |
| * returned. Otherwise \c GLX_BAD_ATTRIBUTE is returned. |
| */ |
| int |
| _gl_get_context_mode_data(const __GLcontextModes * mode, int attribute, |
| int *value_return) |
| { |
| switch (attribute) { |
| case GLX_USE_GL: |
| *value_return = GL_TRUE; |
| return 0; |
| case GLX_BUFFER_SIZE: |
| *value_return = mode->rgbBits; |
| return 0; |
| case GLX_RGBA: |
| *value_return = mode->rgbMode; |
| return 0; |
| case GLX_RED_SIZE: |
| *value_return = mode->redBits; |
| return 0; |
| case GLX_GREEN_SIZE: |
| *value_return = mode->greenBits; |
| return 0; |
| case GLX_BLUE_SIZE: |
| *value_return = mode->blueBits; |
| return 0; |
| case GLX_ALPHA_SIZE: |
| *value_return = mode->alphaBits; |
| return 0; |
| case GLX_DOUBLEBUFFER: |
| *value_return = mode->doubleBufferMode; |
| return 0; |
| case GLX_STEREO: |
| *value_return = mode->stereoMode; |
| return 0; |
| case GLX_AUX_BUFFERS: |
| *value_return = mode->numAuxBuffers; |
| return 0; |
| case GLX_DEPTH_SIZE: |
| *value_return = mode->depthBits; |
| return 0; |
| case GLX_STENCIL_SIZE: |
| *value_return = mode->stencilBits; |
| return 0; |
| case GLX_ACCUM_RED_SIZE: |
| *value_return = mode->accumRedBits; |
| return 0; |
| case GLX_ACCUM_GREEN_SIZE: |
| *value_return = mode->accumGreenBits; |
| return 0; |
| case GLX_ACCUM_BLUE_SIZE: |
| *value_return = mode->accumBlueBits; |
| return 0; |
| case GLX_ACCUM_ALPHA_SIZE: |
| *value_return = mode->accumAlphaBits; |
| return 0; |
| case GLX_LEVEL: |
| *value_return = mode->level; |
| return 0; |
| case GLX_TRANSPARENT_TYPE_EXT: |
| *value_return = mode->transparentPixel; |
| return 0; |
| case GLX_TRANSPARENT_RED_VALUE: |
| *value_return = mode->transparentRed; |
| return 0; |
| case GLX_TRANSPARENT_GREEN_VALUE: |
| *value_return = mode->transparentGreen; |
| return 0; |
| case GLX_TRANSPARENT_BLUE_VALUE: |
| *value_return = mode->transparentBlue; |
| return 0; |
| case GLX_TRANSPARENT_ALPHA_VALUE: |
| *value_return = mode->transparentAlpha; |
| return 0; |
| case GLX_TRANSPARENT_INDEX_VALUE: |
| *value_return = mode->transparentIndex; |
| return 0; |
| case GLX_X_VISUAL_TYPE: |
| *value_return = mode->visualType; |
| return 0; |
| case GLX_CONFIG_CAVEAT: |
| *value_return = mode->visualRating; |
| return 0; |
| case GLX_VISUAL_ID: |
| *value_return = mode->visualID; |
| return 0; |
| case GLX_DRAWABLE_TYPE: |
| *value_return = mode->drawableType; |
| return 0; |
| case GLX_RENDER_TYPE: |
| *value_return = mode->renderType; |
| return 0; |
| case GLX_X_RENDERABLE: |
| *value_return = mode->xRenderable; |
| return 0; |
| case GLX_FBCONFIG_ID: |
| *value_return = mode->fbconfigID; |
| return 0; |
| case GLX_MAX_PBUFFER_WIDTH: |
| *value_return = mode->maxPbufferWidth; |
| return 0; |
| case GLX_MAX_PBUFFER_HEIGHT: |
| *value_return = mode->maxPbufferHeight; |
| return 0; |
| case GLX_MAX_PBUFFER_PIXELS: |
| *value_return = mode->maxPbufferPixels; |
| return 0; |
| case GLX_OPTIMAL_PBUFFER_WIDTH_SGIX: |
| *value_return = mode->optimalPbufferWidth; |
| return 0; |
| case GLX_OPTIMAL_PBUFFER_HEIGHT_SGIX: |
| *value_return = mode->optimalPbufferHeight; |
| return 0; |
| case GLX_SWAP_METHOD_OML: |
| *value_return = mode->swapMethod; |
| return 0; |
| case GLX_SAMPLE_BUFFERS_SGIS: |
| *value_return = mode->sampleBuffers; |
| return 0; |
| case GLX_SAMPLES_SGIS: |
| *value_return = mode->samples; |
| return 0; |
| case GLX_BIND_TO_TEXTURE_RGB_EXT: |
| *value_return = mode->bindToTextureRgb; |
| return 0; |
| case GLX_BIND_TO_TEXTURE_RGBA_EXT: |
| *value_return = mode->bindToTextureRgba; |
| return 0; |
| case GLX_BIND_TO_MIPMAP_TEXTURE_EXT: |
| *value_return = mode->bindToMipmapTexture == GL_TRUE ? GL_TRUE : |
| GL_FALSE; |
| return 0; |
| case GLX_BIND_TO_TEXTURE_TARGETS_EXT: |
| *value_return = mode->bindToTextureTargets; |
| return 0; |
| case GLX_Y_INVERTED_EXT: |
| *value_return = mode->yInverted; |
| return 0; |
| |
| /* Applications are NOT allowed to query GLX_VISUAL_SELECT_GROUP_SGIX. |
| * It is ONLY for communication between the GLX client and the GLX |
| * server. |
| */ |
| case GLX_VISUAL_SELECT_GROUP_SGIX: |
| default: |
| return GLX_BAD_ATTRIBUTE; |
| } |
| } |
| #endif /* !defined(IN_MINI_GLX) */ |
| |
| |
| /** |
| * Allocate a linked list of \c __GLcontextModes structures. The fields of |
| * each structure will be initialized to "reasonable" default values. In |
| * most cases this is the default value defined by table 3.4 of the GLX |
| * 1.3 specification. This means that most values are either initialized to |
| * zero or \c GLX_DONT_CARE (which is -1). As support for additional |
| * extensions is added, the new values will be initialized to appropriate |
| * values from the extension specification. |
| * |
| * \param count Number of structures to allocate. |
| * \param minimum_size Minimum size of a structure to allocate. This allows |
| * for differences in the version of the |
| * \c __GLcontextModes stucture used in libGL and in a |
| * DRI-based driver. |
| * \returns A pointer to the first element in a linked list of \c count |
| * stuctures on success, or \c NULL on failure. |
| * |
| * \warning Use of \c minimum_size does \b not guarantee binary compatibility. |
| * The fundamental assumption is that if the \c minimum_size |
| * specified by the driver and the size of the \c __GLcontextModes |
| * structure in libGL is the same, then the meaning of each byte in |
| * the structure is the same in both places. \b Be \b careful! |
| * Basically this means that fields have to be added in libGL and |
| * then propagated to drivers. Drivers should \b never arbitrarilly |
| * extend the \c __GLcontextModes data-structure. |
| */ |
| __GLcontextModes * |
| _gl_context_modes_create(unsigned count, size_t minimum_size) |
| { |
| const size_t size = (minimum_size > sizeof(__GLcontextModes)) |
| ? minimum_size : sizeof(__GLcontextModes); |
| __GLcontextModes *base = NULL; |
| __GLcontextModes **next; |
| unsigned i; |
| |
| next = &base; |
| for (i = 0; i < count; i++) { |
| *next = (__GLcontextModes *) _mesa_malloc(size); |
| if (*next == NULL) { |
| _gl_context_modes_destroy(base); |
| base = NULL; |
| break; |
| } |
| |
| (void) _mesa_memset(*next, 0, size); |
| (*next)->visualID = GLX_DONT_CARE; |
| (*next)->visualType = GLX_DONT_CARE; |
| (*next)->visualRating = GLX_NONE; |
| (*next)->transparentPixel = GLX_NONE; |
| (*next)->transparentRed = GLX_DONT_CARE; |
| (*next)->transparentGreen = GLX_DONT_CARE; |
| (*next)->transparentBlue = GLX_DONT_CARE; |
| (*next)->transparentAlpha = GLX_DONT_CARE; |
| (*next)->transparentIndex = GLX_DONT_CARE; |
| (*next)->xRenderable = GLX_DONT_CARE; |
| (*next)->fbconfigID = GLX_DONT_CARE; |
| (*next)->swapMethod = GLX_SWAP_UNDEFINED_OML; |
| (*next)->bindToTextureRgb = GLX_DONT_CARE; |
| (*next)->bindToTextureRgba = GLX_DONT_CARE; |
| (*next)->bindToMipmapTexture = GLX_DONT_CARE; |
| (*next)->bindToTextureTargets = GLX_DONT_CARE; |
| (*next)->yInverted = GLX_DONT_CARE; |
| |
| next = &((*next)->next); |
| } |
| |
| return base; |
| } |
| |
| |
| /** |
| * Destroy a linked list of \c __GLcontextModes structures created by |
| * \c _gl_context_modes_create. |
| * |
| * \param modes Linked list of structures to be destroyed. All structres |
| * in the list will be freed. |
| */ |
| void |
| _gl_context_modes_destroy(__GLcontextModes * modes) |
| { |
| while (modes != NULL) { |
| __GLcontextModes *const next = modes->next; |
| |
| _mesa_free(modes); |
| modes = next; |
| } |
| } |
| |
| |
| /** |
| * Find a context mode matching a Visual ID. |
| * |
| * \param modes List list of context-mode structures to be searched. |
| * \param vid Visual ID to be found. |
| * \returns A pointer to a context-mode in \c modes if \c vid was found in |
| * the list, or \c NULL if it was not. |
| */ |
| |
| __GLcontextModes * |
| _gl_context_modes_find_visual(__GLcontextModes * modes, int vid) |
| { |
| __GLcontextModes *m; |
| |
| for (m = modes; m != NULL; m = m->next) |
| if (m->visualID == vid) |
| return m; |
| |
| return NULL; |
| } |
| |
| __GLcontextModes * |
| _gl_context_modes_find_fbconfig(__GLcontextModes * modes, int fbid) |
| { |
| __GLcontextModes *m; |
| |
| for (m = modes; m != NULL; m = m->next) |
| if (m->fbconfigID == fbid) |
| return m; |
| |
| return NULL; |
| } |
| |
| /** |
| * Determine if two context-modes are the same. This is intended to be used |
| * by libGL implementations to compare to sets of driver generated FBconfigs. |
| * |
| * \param a Context-mode to be compared. |
| * \param b Context-mode to be compared. |
| * \returns \c GL_TRUE if the two context-modes are the same. \c GL_FALSE is |
| * returned otherwise. |
| */ |
| GLboolean |
| _gl_context_modes_are_same(const __GLcontextModes * a, |
| const __GLcontextModes * b) |
| { |
| return ((a->rgbMode == b->rgbMode) && |
| (a->floatMode == b->floatMode) && |
| (a->colorIndexMode == b->colorIndexMode) && |
| (a->doubleBufferMode == b->doubleBufferMode) && |
| (a->stereoMode == b->stereoMode) && |
| (a->redBits == b->redBits) && |
| (a->greenBits == b->greenBits) && |
| (a->blueBits == b->blueBits) && (a->alphaBits == b->alphaBits) && |
| #if 0 /* For some reason these don't get set on the client-side in libGL. */ |
| (a->redMask == b->redMask) && |
| (a->greenMask == b->greenMask) && |
| (a->blueMask == b->blueMask) && (a->alphaMask == b->alphaMask) && |
| #endif |
| (a->rgbBits == b->rgbBits) && |
| (a->indexBits == b->indexBits) && |
| (a->accumRedBits == b->accumRedBits) && |
| (a->accumGreenBits == b->accumGreenBits) && |
| (a->accumBlueBits == b->accumBlueBits) && |
| (a->accumAlphaBits == b->accumAlphaBits) && |
| (a->depthBits == b->depthBits) && |
| (a->stencilBits == b->stencilBits) && |
| (a->numAuxBuffers == b->numAuxBuffers) && |
| (a->level == b->level) && |
| (a->pixmapMode == b->pixmapMode) && |
| (a->visualRating == b->visualRating) && |
| (a->transparentPixel == b->transparentPixel) && |
| ((a->transparentPixel != GLX_TRANSPARENT_RGB) || |
| ((a->transparentRed == b->transparentRed) && |
| (a->transparentGreen == b->transparentGreen) && |
| (a->transparentBlue == b->transparentBlue) && |
| (a->transparentAlpha == b->transparentAlpha))) && |
| ((a->transparentPixel != GLX_TRANSPARENT_INDEX) || |
| (a->transparentIndex == b->transparentIndex)) && |
| (a->sampleBuffers == b->sampleBuffers) && |
| (a->samples == b->samples) && |
| ((a->drawableType & b->drawableType) != 0) && |
| (a->renderType == b->renderType) && |
| (a->maxPbufferWidth == b->maxPbufferWidth) && |
| (a->maxPbufferHeight == b->maxPbufferHeight) && |
| (a->maxPbufferPixels == b->maxPbufferPixels) && |
| (a->optimalPbufferWidth == b->optimalPbufferWidth) && |
| (a->optimalPbufferHeight == b->optimalPbufferHeight) && |
| (a->swapMethod == b->swapMethod) && |
| (a->bindToTextureRgb == b->bindToTextureRgb) && |
| (a->bindToTextureRgba == b->bindToTextureRgba) && |
| (a->bindToMipmapTexture == b->bindToMipmapTexture) && |
| (a->bindToTextureTargets == b->bindToTextureTargets) && |
| (a->yInverted == b->yInverted)); |
| } |