glxcmds.c

来自「mesa-6.5-minigui源码」· C语言 代码 · 共 2,495 行 · 第 1/5 页

C
2,495
字号
/* $XFree86: xc/lib/GL/glx/glxcmds.c,v 1.30 2004/01/30 20:33:06 alanh Exp $ *//*** License Applicability. Except to the extent portions of this file are** made subject to an alternative license as permitted in the SGI Free** Software License B, Version 1.1 (the "License"), the contents of this** file are subject only to the provisions of the License. You may not use** this file except in compliance with the License. You may obtain a copy** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at:** ** http://oss.sgi.com/projects/FreeB** ** Note that, as provided in the License, the Software is distributed on an** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A** PARTICULAR PURPOSE, AND NON-INFRINGEMENT.** ** Original Code. The Original Code is: OpenGL Sample Implementation,** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics,** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc.** Copyright in any portions created by third parties is as indicated** elsewhere herein. All Rights Reserved.** ** Additional Notice Provisions: The application programming interfaces** established by SGI in conjunction with the Original Code are The** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X** Window System(R) (Version 1.3), released October 19, 1998. This software** was created using the OpenGL(R) version 1.2.1 Sample Implementation** published by SGI, but has not been independently verified as being** compliant with the OpenGL(R) version 1.2.1 Specification.***//** * \file glxcmds.c * Client-side GLX interface. */#include <inttypes.h>#include "glxclient.h"#include <X11/extensions/extutil.h>#include <X11/extensions/Xext.h>#include <assert.h>#include <string.h>#include "glapi.h"#ifdef GLX_DIRECT_RENDERING#include "indirect_init.h"#include <X11/extensions/xf86vmode.h>#include "xf86dri.h"#endif#include "glxextensions.h"#include "glcontextmodes.h"#include "glheader.h"#include <sys/time.h>static const char __glXGLXClientVendorName[] = "SGI";static const char __glXGLXClientVersion[] = "1.4";/****************************************************************************//** * Get the __DRIdrawable for the drawable associated with a GLXContext *  * \param dpy       The display associated with \c drawable. * \param drawable  GLXDrawable whose __DRIdrawable part is to be retrieved. * \returns  A pointer to the context's __DRIdrawable on success, or NULL if *           the drawable is not associated with a direct-rendering context. */#ifdef GLX_DIRECT_RENDERINGstatic __DRIdrawable *GetDRIDrawable( Display *dpy, GLXDrawable drawable, int * const scrn_num ){    __GLXdisplayPrivate * const priv = __glXInitialize(dpy);    if ( (priv != NULL) && (priv->driDisplay.private != NULL) ) {	const unsigned  screen_count = ScreenCount(dpy);	unsigned   i;	for ( i = 0 ; i < screen_count ; i++ ) {	    __DRIscreen * const psc = &priv->screenConfigs[i].driScreen;	    __DRIdrawable * const pdraw = (psc->private != NULL)	       ? (*psc->getDrawable)(dpy, drawable, psc->private) : NULL;	    if ( pdraw != NULL ) {		if ( scrn_num != NULL ) {		    *scrn_num = i;		}		return pdraw;	    }	}    }    return NULL;}#endif/** * Get the GLX per-screen data structure associated with a GLX context. *  * \param dpy   Display for which the GLX per-screen information is to be *              retrieved. * \param scrn  Screen on \c dpy for which the GLX per-screen information is *              to be retrieved. * \returns A pointer to the GLX per-screen data if \c dpy and \c scrn *          specify a valid GLX screen, or NULL otherwise. *  * \todo Should this function validate that \c scrn is within the screen *       number range for \c dpy? */static __GLXscreenConfigs *GetGLXScreenConfigs(Display *dpy, int scrn){    __GLXdisplayPrivate * const priv = __glXInitialize(dpy);    return (priv->screenConfigs != NULL) ? &priv->screenConfigs[scrn] : NULL;}static intGetGLXPrivScreenConfig( Display *dpy, int scrn, __GLXdisplayPrivate ** ppriv,			__GLXscreenConfigs ** ppsc ){    /* Initialize the extension, if needed .  This has the added value     * of initializing/allocating the display private      */        if ( dpy == NULL ) {	return GLX_NO_EXTENSION;    }    *ppriv = __glXInitialize(dpy);    if ( *ppriv == NULL ) {	return GLX_NO_EXTENSION;    }    /* Check screen number to see if its valid */    if ((scrn < 0) || (scrn >= ScreenCount(dpy))) {	return GLX_BAD_SCREEN;    }    /* Check to see if the GL is supported on this screen */    *ppsc = &((*ppriv)->screenConfigs[scrn]);    if ( (*ppsc)->configs == NULL ) {	/* No support for GL on this screen regardless of visual */	return GLX_BAD_VISUAL;    }    return Success;}/** * Determine if a \c GLXFBConfig supplied by the application is valid. * * \param dpy     Application supplied \c Display pointer. * \param config  Application supplied \c GLXFBConfig. * * \returns If the \c GLXFBConfig is valid, the a pointer to the matching *          \c __GLcontextModes structure is returned.  Otherwise, \c NULL *          is returned. */static __GLcontextModes *ValidateGLXFBConfig( Display * dpy, GLXFBConfig config ){    __GLXdisplayPrivate * const priv = __glXInitialize(dpy);    const unsigned num_screens = ScreenCount(dpy);    unsigned   i;    const __GLcontextModes * modes;    if ( priv != NULL ) {	for ( i = 0 ; i < num_screens ; i++ ) {	    for ( modes = priv->screenConfigs[i].configs		  ; modes != NULL		  ; modes = modes->next ) {		if ( modes == (__GLcontextModes *) config ) {		    return (__GLcontextModes *) config;		}	    }	}    }    return NULL;}/** * \todo It should be possible to move the allocate of \c client_state_private * later in the function for direct-rendering contexts.  Direct-rendering * contexts don't need to track client state, so they don't need that memory * at all. *  * \todo Eliminate \c __glXInitVertexArrayState.  Replace it with a new * function called \c __glXAllocateClientState that allocates the memory and * does all the initialization (including the pixel pack / unpack). */staticGLXContext AllocateGLXContext( Display *dpy ){     GLXContext gc;     int bufSize;     CARD8 opcode;    __GLXattribute *state;    if (!dpy)        return NULL;    opcode = __glXSetupForCommand(dpy);    if (!opcode) {	return NULL;    }    /* Allocate our context record */    gc = (GLXContext) Xmalloc(sizeof(struct __GLXcontextRec));    if (!gc) {	/* Out of memory */	return NULL;    }    memset(gc, 0, sizeof(struct __GLXcontextRec));    state = Xmalloc(sizeof(struct __GLXattributeRec));    if (state == NULL) {	/* Out of memory */	Xfree(gc);	return NULL;    }    gc->client_state_private = state;    memset(gc->client_state_private, 0, sizeof(struct __GLXattributeRec));    state->NoDrawArraysProtocol = (getenv("LIBGL_NO_DRAWARRAYS") != NULL);    /*    ** Create a temporary buffer to hold GLX rendering commands.  The size    ** of the buffer is selected so that the maximum number of GLX rendering    ** commands can fit in a single X packet and still have room in the X    ** packet for the GLXRenderReq header.    */    bufSize = (XMaxRequestSize(dpy) * 4) - sz_xGLXRenderReq;    gc->buf = (GLubyte *) Xmalloc(bufSize);    if (!gc->buf) {	Xfree(gc->client_state_private);	Xfree(gc);	return NULL;    }    gc->bufSize = bufSize;    /* Fill in the new context */    gc->renderMode = GL_RENDER;    state->storePack.alignment = 4;    state->storeUnpack.alignment = 4;    gc->attributes.stackPointer = &gc->attributes.stack[0];    /*    ** PERFORMANCE NOTE: A mode dependent fill image can speed things up.    ** Other code uses the fastImageUnpack bit, but it is never set    ** to GL_TRUE.    */    gc->fastImageUnpack = GL_FALSE;    gc->fillImage = __glFillImage;    gc->isDirect = GL_FALSE;    gc->pc = gc->buf;    gc->bufEnd = gc->buf + bufSize;    if (__glXDebug) {	/*	** Set limit register so that there will be one command per packet	*/	gc->limit = gc->buf;    } else {	gc->limit = gc->buf + bufSize - __GLX_BUFFER_LIMIT_SIZE;    }    gc->createDpy = dpy;    gc->majorOpcode = opcode;    /*    ** Constrain the maximum drawing command size allowed to be    ** transfered using the X_GLXRender protocol request.  First    ** constrain by a software limit, then constrain by the protocl    ** limit.    */    if (bufSize > __GLX_RENDER_CMD_SIZE_LIMIT) {        bufSize = __GLX_RENDER_CMD_SIZE_LIMIT;    }    if (bufSize > __GLX_MAX_RENDER_CMD_SIZE) {        bufSize = __GLX_MAX_RENDER_CMD_SIZE;    }    gc->maxSmallRenderCommandSize = bufSize;    return gc;}/** * Create a new context.  Exactly one of \c vis and \c fbconfig should be * non-NULL. *  * \param use_glx_1_3  For FBConfigs, should GLX 1.3 protocol or *                     SGIX_fbconfig protocol be used? * \param renderType   For FBConfigs, what is the rendering type? */static GLXContextCreateContext(Display *dpy, XVisualInfo *vis,	      const __GLcontextModes * const fbconfig,	      GLXContext shareList,	      Bool allowDirect, GLXContextID contextID,	      Bool use_glx_1_3, int renderType){    GLXContext gc;    if ( dpy == NULL )       return NULL;    gc = AllocateGLXContext(dpy);    if (!gc)	return NULL;    if (None == contextID) {	if ( (vis == NULL) && (fbconfig == NULL) )	    return NULL;#ifdef GLX_DIRECT_RENDERING	if (allowDirect) {	    int screen = (fbconfig == NULL) ? vis->screen : fbconfig->screen;	    __GLXscreenConfigs * const psc = GetGLXScreenConfigs(dpy, screen);	    const __GLcontextModes * mode;	    /* The value of fbconfig cannot change because it is tested	     * later in the function.	     */	    if ( fbconfig == NULL ) {		/* FIXME: Is it possible for the __GLcontextModes structure		 * FIXME: to not be found?		 */		mode = _gl_context_modes_find_visual( psc->configs,						      vis->visualid );		assert( mode != NULL );		assert( mode->screen == screen );	    }	    else {		mode = fbconfig;	    }	    if (psc && psc->driScreen.private) {		void * const shared = (shareList != NULL)		    ? shareList->driContext.private : NULL;		gc->driContext.private = 		  (*psc->driScreen.createNewContext)( dpy, mode, renderType,						      shared,						      &gc->driContext );		if (gc->driContext.private) {		    gc->isDirect = GL_TRUE;		    gc->screen = mode->screen;		    gc->vid = mode->visualID;		    gc->fbconfigID = mode->fbconfigID;		    gc->driContext.mode = mode;		}	    }	}#endif	LockDisplay(dpy);	if ( fbconfig == NULL ) {	    xGLXCreateContextReq *req;	    /* Send the glXCreateContext request */	    GetReq(GLXCreateContext,req);	    req->reqType = gc->majorOpcode;	    req->glxCode = X_GLXCreateContext;	    req->context = gc->xid = XAllocID(dpy);	    req->visual = vis->visualid;	    req->screen = vis->screen;	    req->shareList = shareList ? shareList->xid : None;	    req->isDirect = gc->isDirect;	}	else if ( use_glx_1_3 ) {	    xGLXCreateNewContextReq *req;	    /* Send the glXCreateNewContext request */	    GetReq(GLXCreateNewContext,req);	    req->reqType = gc->majorOpcode;	    req->glxCode = X_GLXCreateNewContext;	    req->context = gc->xid = XAllocID(dpy);	    req->fbconfig = fbconfig->fbconfigID;	    req->screen = fbconfig->screen;	    req->renderType = renderType;	    req->shareList = shareList ? shareList->xid : None;	    req->isDirect = gc->isDirect;	}	else {	    xGLXVendorPrivateWithReplyReq *vpreq;	    xGLXCreateContextWithConfigSGIXReq *req;	    /* Send the glXCreateNewContext request */	    GetReqExtra(GLXVendorPrivateWithReply,			sz_xGLXCreateContextWithConfigSGIXReq-sz_xGLXVendorPrivateWithReplyReq,vpreq);	    req = (xGLXCreateContextWithConfigSGIXReq *)vpreq;	    req->reqType = gc->majorOpcode;	    req->glxCode = X_GLXVendorPrivateWithReply;	    req->vendorCode = X_GLXvop_CreateContextWithConfigSGIX;	    req->context = gc->xid = XAllocID(dpy);	    req->fbconfig = fbconfig->fbconfigID;	    req->screen = fbconfig->screen;	    req->renderType = renderType;	    req->shareList = shareList ? shareList->xid : None;	    req->isDirect = gc->isDirect;	}	UnlockDisplay(dpy);	SyncHandle();	gc->imported = GL_FALSE;    }    else {	gc->xid = contextID;	gc->imported = GL_TRUE;    }    return gc;}PUBLIC GLXContext glXCreateContext(Display *dpy, XVisualInfo *vis,				   GLXContext shareList, Bool allowDirect){   return CreateContext(dpy, vis, NULL, shareList, allowDirect, None,			False, 0);}void __glXFreeContext(__GLXcontext *gc){    if (gc->vendor) XFree((char *) gc->vendor);    if (gc->renderer) XFree((char *) gc->renderer);    if (gc->version) XFree((char *) gc->version);    if (gc->extensions) XFree((char *) gc->extensions);    __glFreeAttributeState(gc);    XFree((char *) gc->buf);    Xfree((char *) gc->client_state_private);    XFree((char *) gc);    }/*** Destroy the named context*/static void DestroyContext(Display *dpy, GLXContext gc){    xGLXDestroyContextReq *req;    GLXContextID xid;    CARD8 opcode;    GLboolean imported;    opcode = __glXSetupForCommand(dpy);    if (!opcode || !gc) {	return;    }    __glXLock();    xid = gc->xid;    imported = gc->imported;    gc->xid = None;#ifdef GLX_DIRECT_RENDERING    /* Destroy the direct rendering context */    if (gc->isDirect) {	if (gc->driContext.private) {	    (*gc->driContext.destroyContext)(dpy, gc->screen,					     gc->driContext.private);	    gc->driContext.private = NULL;	}    }#endif    if (gc->currentDpy) {	/* Have to free later cuz it's in use now */	__glXUnlock();    } else {	/* Destroy the handle if not current to anybody */	__glXUnlock();	__glXFreeContext(gc);    }    if (!imported) {	/* 	** This dpy also created the server side part of the context.	** Send the glXDestroyContext request.	*/	LockDisplay(dpy);	GetReq(GLXDestroyContext,req);	req->reqType = opcode;	req->glxCode = X_GLXDestroyContext;	req->context = xid;	UnlockDisplay(dpy);	SyncHandle();

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?