glwin.c

来自「有限元学习研究用源代码(老外的),供科研人员参考」· C语言 代码 · 共 2,180 行 · 第 1/4 页

C
2,180
字号

void glwSetMouseMoveFunc(glWindow w,GLenum (*Func)(glWindow, void *,int, int, GLenum))
{
    if (w==NULL) { glwError("null window"); return;}

    w->MouseMoveFunc = Func;
}

/******************************************************************************/

void glwSetIdleFunc(glWindow w,void (*Func)(glWindow, void *))
{
  if (w==NULL) { glwError("null window"); return;}
  if (Func!=NULL)
    {
      w->RedrawFunc = Func;
      w->control_mode=GLW_APPLICATION_DRIVEN;
    }
  else
    w->control_mode=GLW_EVENT_DRIVEN;
}

/******************************************************************************/

void glwDestroy(glWindow w)
{
   glwTrace("destroy:");

   
   if (glwAttach(w)) 
       {   
	   glFlush();
	   glFinish();
       }


   if (GLW_HAS_OVERLAY(w->type)) 
       {
	   XDestroyWindow(w->xDisplay, w->wOverlay);
	   glXDestroyContext(w->xDisplay, w->cOverlay);
	   XFreeColormap(w->xDisplay, w->cMapOverlay);
	   XFree((char *)w->vInfoOverlay);
	   glwTrace("destroy overlay");
     
       }
   if (w->offscreen)
     {
       glXDestroyGLXPixmap(w->xDisplay, w->glx_pixmap);
       XFreePixmap(w->xDisplay, w->pixmap);
       glwTrace("destroy pixmap");
     }
  else
    {
      XDestroyWindow(w->xDisplay, w->wMain);
      glwTrace("destroy xwindow");
     }
   XFreeColormap(w->xDisplay, w->cMapMain);
   glXDestroyContext(w->xDisplay, w->cMain);
   XFree((char *)w->vInfoMain);
   XCloseDisplay(w->xDisplay);
   free(w->title);
   free(w->xtitle);
   if (w->state!=NULL) free(w->state);
   free(w);
   w=NULL;
   glwTrace("destroy window");
}


/******************************************************************************/
char *glwGetDefault(glWindow w,char *resource, char *dflt)
{
  char *data;
  data=XGetDefault(w->xDisplay,"gltools",resource);
  if (data==NULL) 
    return dflt;
  else 
    return data;
}

/******************************************************************************/
void glwGetWindowSize(glWindow w, int *width, int *height)
{
  *width=w->w;
  *height=w->h;
}
/******************************************************************************/
static glWindow wCreate=NULL;
static glWindow wEvent=NULL;

static void InitWindow(void)
{
  glWindow w;
  if (wCreate==NULL)
    {
      wCreate=(struct glWindowStruct *)calloc(sizeof(struct glWindowStruct),1);
      if (wCreate==NULL) 
	{
	  glwError("No space for window struct!");
	  return;
	}
    }
  else
    return;
  
  w=wCreate;
  w->xDisplay = XOpenDisplay(NULL);
  
  if (w->xDisplay==NULL) 
    {
      glwError("Unable to connect to display!");
      return;
    }
  
  w->x=atoi(glwGetDefault(w,"xOrigin","0"));
  w->y=atoi(glwGetDefault(w,"yOrigin","0"));;
  w->w=(atoi(glwGetDefault(w,"width","352"))/16)*16; /* GLW_MPEG1_PAL */
  w->h=(atoi(glwGetDefault(w,"height","288"))/16)*16; /* GLW_MPEG1_PAL */
  w->type=(GLenum)(GLW_RGB|GLW_DOUBLE|GLW_DIRECT|GLW_DEPTH);
  w->dmPolicy=(GLenum)GLW_MINIMUM_CRITERIA;
  w->title=(char*)malloc(GLW_NAMELEN);
  w->xtitle=(char*)malloc(GLW_NAMELEN);
  w->state=NULL;
  strcpy(w->title,glwGetDefault(w,"title","gltools"));
  w->control_mode=GLW_EVENT_DRIVEN;
  w->font_base[0]=0;
  w->keep_aspect=1;
  w->offscreen=0;
}

void glwInitDisplayMode(GLenum type)
{   
  InitWindow();
  wCreate->type = type;
}

void glwInitOffscreen(void)
{   
  InitWindow();
  wCreate->offscreen=1;
  wCreate->control_mode=GLW_APPLICATION_DRIVEN;
}

void glwInitDisplayModePolicy(GLenum type)
{
  InitWindow();
  wCreate->dmPolicy = type;
}

/******************************************************************************/

void glwInitPosition(int x, int y, int width, int height)
{
  
  InitWindow();
  wCreate->x = x;
  wCreate->y = y;
  wCreate->w = (width/16)*16;
  wCreate->h = (height/16)*16;
}

void glwInitPos(int x, int y)
{
  
  InitWindow();
  wCreate->x = x;
  wCreate->y = y;
}


void glwInitTitle(char *title)
{
  
  InitWindow();
  strcpy(wCreate->title,title);
}


void glwInitAspectKeeping(int yesno)
{
  wCreate->keep_aspect=yesno;
}

static int ErrorHandler(Display *xDisplay, XErrorEvent *event)
{
  char buf[80];
  
  glwError("Received X error!");
  printf(" Error code   : %d\n", event->error_code);
  printf(" Request code : %d\n", event->request_code);
  printf(" Minor code   : %d\n", event->minor_code);
  XGetErrorText(xDisplay, event->error_code, buf, 80);
  printf(" Error text   : %s\n", buf);
  return 0;
}

static XVisualInfo *FindBestMainVisual(glWindow w,GLenum type)
{
    int list[32], i;

    i = 0;

    list[i++] = GLX_LEVEL;
    list[i++] = 0;

    if (GLW_IS_DOUBLE(type)) {
	list[i++] = GLX_DOUBLEBUFFER;
    }

    if (GLW_IS_RGB(type)) {
	list[i++] = GLX_RGBA;
	list[i++] = GLX_RED_SIZE;
	list[i++] = 1;
	list[i++] = GLX_GREEN_SIZE;
	list[i++] = 1;
	list[i++] = GLX_BLUE_SIZE;
	list[i++] = 1;
	if (GLW_HAS_ALPHA(type)) {
	    list[i++] = GLX_ALPHA_SIZE;
	    list[i++] = 1;
	}
	if (GLW_HAS_ACCUM(type)) {
	    list[i++] = GLX_ACCUM_RED_SIZE;
	    list[i++] = 1;
	    list[i++] = GLX_ACCUM_GREEN_SIZE;
	    list[i++] = 1;
	    list[i++] = GLX_ACCUM_BLUE_SIZE;
	    list[i++] = 1;
	    if (GLW_HAS_ALPHA(type)) {
		list[i++] = GLX_ACCUM_ALPHA_SIZE;
		list[i++] = 1;
	    }
	}
    } else if (GLW_IS_INDEX(type)) {
	list[i++] = GLX_BUFFER_SIZE;
	list[i++] = 1;
    }

    if (GLW_HAS_DEPTH(type)) {
	list[i++] = GLX_DEPTH_SIZE;
	list[i++] = 1;
    }

    if (GLW_HAS_STENCIL(type)) {
	list[i++] = GLX_STENCIL_SIZE;
	list[i++] = 1;
    }

    list[i] = (int)None;

    return glXChooseVisual(w->xDisplay, w->xScreen, list);
}

static XVisualInfo *FindExactMainVisual(glWindow w, GLenum type)
{
  int i, nvis, val, rval, gval, bval, aval;
  XVisualInfo *vis_list, *this_vis, *best_vis, sampleVis;
  int this_score, best_score;
  
  /* Get list of visuals for this screen */
  sampleVis.screen = w->xScreen;
  vis_list = XGetVisualInfo(w->xDisplay, VisualScreenMask, &sampleVis, &nvis);
  
  /* 
   * Loop through the visuals; find first one that matches the attr 
   * specified in type
   */
  best_score = -1; best_vis = NULL;
  for ( i = 0; i < nvis; i++ ) 
    {
      this_vis = &vis_list[i];
      if (debug) 
	fprintf(stderr,"glwin: testing visual id 0x%x: ", (unsigned)this_vis->visualid);
      /* Visual must be supported by GLX */
      if ( glXGetConfig(w->xDisplay, this_vis, GLX_USE_GL, &val) ) continue;
      if ( !val ) 
	{  
	  if (debug) fprintf(stderr,"no GLX support.\n");
	  continue;
	}
      /* Visual must be in main planes which is level 0 */
      glXGetConfig(w->xDisplay, this_vis, GLX_LEVEL, &val);
      if ( val != 0 ) 
	{  
	  if (debug) fprintf(stderr,"no level 0 visual.\n");
	  continue;
	}
      
      /* Color Index or RGBA? It must match the requested value */
      glXGetConfig(w->xDisplay, this_vis, GLX_RGBA, &val);
      if ( GLW_IS_RGB(type) && !val ) 
	{  
	  if (debug) fprintf(stderr,"no RGB support.\n");
	  continue;
	}
      
      if ( GLW_IS_INDEX(type) && val )
	{  
	  if (debug) fprintf(stderr,"no color index support.\n");
	  continue;
	}
      
      
      /* Double buffered or Single buffered? */
      glXGetConfig(w->xDisplay, this_vis, GLX_DOUBLEBUFFER, &val);
      if ( GLW_IS_DOUBLE(type) && !val )
	{  
	  if (debug) fprintf(stderr,"no double buffer support.\n");
	  continue;
	}
      if ( GLW_IS_SINGLE(type) && val ) 
	{  
	  if (debug) fprintf(stderr,"no single buffer support.\n");
	  continue;
	}

      
      /* If accum requested then accum rgb size must be > 0 */
      /* If alpha requested then alpha size must be > 0 */
      /* if accum & alpha requested then accum alpha size must be > 0 */
      if ( GLW_IS_RGB(type) ) 
	{
	  glXGetConfig(w->xDisplay, this_vis, GLX_ACCUM_RED_SIZE, &rval);
	  glXGetConfig(w->xDisplay, this_vis, GLX_ACCUM_GREEN_SIZE, &gval);
	  glXGetConfig(w->xDisplay, this_vis, GLX_ACCUM_BLUE_SIZE, &bval);
	 
	  glXGetConfig(w->xDisplay, this_vis, GLX_ACCUM_ALPHA_SIZE, &aval);
	  if ( GLW_HAS_ACCUM(type) ) 
	    {
	      if ( rval <= 0 || gval <= 0 || bval <= 0 ) 
		{  
		  if (debug) fprintf(stderr,"accum RGB size <0.\n");
		  continue;
		}
	    } 
	  else 
	    {
	      if ( rval > 0 || gval > 0 || bval > 0 || aval > 0 )
		{  
		  if (debug) fprintf(stderr,"accum support not demanded.\n");
		  continue;
		}
	    }
	
	  glXGetConfig(w->xDisplay, this_vis, GLX_ALPHA_SIZE, &val);
	  if ( GLW_HAS_ALPHA(type) ) 
	    {
	      if ( val <= 0 )
		{  
		  if (debug) fprintf(stderr,"alpha size < 0.\n");
		  continue;
		}

	    if ( GLW_HAS_ACCUM(type) && aval <= 0 ) 
	      {
		if (debug) fprintf(stderr,"alpha accum size < 0.\n");
		continue;
	      }
	    }
	  else
	    {
	      if ( val > 0 ) 
	      {
		if (debug) fprintf(stderr,"alpha support not demanded.\n");
		continue;
	      }
	    }
	
	}
      
      /* Check depth buffer */
      glXGetConfig(w->xDisplay, this_vis, GLX_DEPTH_SIZE, &val);
      if ( GLW_HAS_DEPTH(type) ) 
	{
	  if ( val <= 0 )
	    {
	      if (debug) fprintf(stderr,"no depth buffer support.\n");
	      continue;
	    }
	} 
      else
	{
	  if ( val > 0 )
	    {
	      if (debug) fprintf(stderr,"depth buffer support not demanded.\n");
	      continue;
	    }
	}
      
      /* Check stencil buffer */
      glXGetConfig(w->xDisplay, this_vis, GLX_STENCIL_SIZE, &val);
      if ( GLW_HAS_STENCIL(type) )
	{
	  if ( val <= 0 )
	    {
	      if (debug) fprintf(stderr,"no stencil buffer support.\n");
	      continue;
	    }
	} 
      else
	{
	  if ( val > 0 )
	    {
	      if (debug) fprintf(stderr,"stencil buffer support not demanded.\n");
	      continue;
	    }
	}
      
      glXGetConfig(w->xDisplay, this_vis, GLX_BUFFER_SIZE, &this_score);
      
      if (debug) fprintf(stderr,"ok, buffer size=%d.\n",this_score);
      if (this_score > best_score ) 
	{
	  best_score = this_score;
	  best_vis = this_vis;
	}
      
    }
  
  if ( best_vis ) 
    {
      sampleVis.visualid = best_vis->visualid;
      sampleVis.screen = w->xScreen;
      if ( nvis > 0 ) XFree(vis_list);
      return XGetVisualInfo(w->xDisplay, VisualIDMask|VisualScreenMask, 
			    &sampleVis, &nvis);
    } 
  else 
    {
      if ( nvis > 0 ) XFree(vis_list);
      return None;
    }
  
}

/*
old code 

static XVisualInfo *FindMainVisual(glWindow w,GLenum type)
{
  int list[32], i;
  i = 0;
  
  list[i++] = GLX_LEVEL;
  list[i++] = 0;
  
  if (GLW_IS_DOUBLE(type)) 
    {
      list[i++] = GLX_DOUBLEBUFFER;
    }

  if (GLW_IS_RGB(type)) 
    {
      list[i++] = GLX_RGBA;
      list[i++] = GLX_RED_SIZE;
      list[i++] = 1;
      list[i++] = GLX_GREEN_SIZE;
      list[i++] = 1;
      list[i++] = GLX_BLUE_SIZE;
      list[i++] = 1;

      if (GLW_HAS_ALPHA(type)) 
	{
	  list[i++] = GLX_ALPHA_SIZE;
	  list[i++] = 1;
	}
      
      if (GLW_HAS_ACCUM(type)) 
	{
	  list[i++] = GLX_ACCUM_RED_SIZE;
	  list[i++] = 1;
	  list[i++] = GLX_ACCUM_GREEN_SIZE;
	  list[i++] = 1;
	  list[i++] = GLX_ACCUM_BLUE_SIZE;
	  list[i++] = 1;
	  if (GLW_HAS_ALPHA(type)) {
	    list[i++] = GLX_ACCUM_ALPHA_SIZE;
	    list[i++] = 1;
	  }
	}
    }
  else if (GLW_IS_INDEX(type)) 
    {
      list[i++] = GLX_BUFFER_SIZE;
      list[i++] = 1;
    }
  
  if (GLW_HAS_DEPTH(type)) 
    {
      list[i++] = GLX_DEPTH_SIZE;
      list[i++] = 1;
    }
  
  if (GLW_HAS_STENCIL(type)) 
    {
      list[i++] = GLX_STENCIL_SIZE;
      list[i++] = 1;
    }
  
  list[i] = (int)None;
  return glXChooseVisual(w->xDisplay, w->xScreen, list);
}
*/

static XVisualInfo *FindOverlayVisual(glWindow w)
{
    int list[3];

    list[0] = GLX_LEVEL;
    list[1] = 1;
    list[2] = (int)None;
    return glXChooseVisual(w->xDisplay, w->xScreen, list);
}

static GLenum GetMainWindowType(glWindow w,XVisualInfo *vi)
{
    GLenum mask;
    int x, y, z;

    mask = (GLenum)0;

    glXGetConfig(w->xDisplay, vi, GLX_DOUBLEBUFFER, &x);
    if (x) {
	mask |= GLW_DOUBLE;
    } else {
	mask |= GLW_SINGLE;
    }

    glXGetConfig(w->xDisplay, vi, GLX_RGBA, &x);
    if (x) {
	mask |= GLW_RGB;
	glXGetConfig(w->xDisplay, vi, GLX_ALPHA_SIZE, &x);
	if (x > 0) {
	    mask |= GLW_ALPHA;
	}
	glXGetConfig(w->xDisplay, vi, GLX_ACCUM_RED_SIZE, &x);
	glXGetConfig(w->xDisplay, vi, GLX_ACCUM_GREEN_SIZE, &y);
	glXGetConfig(w->xDisplay, vi, GLX_ACCUM_BLUE_SIZE, &z);
	if (x > 0 && y > 0 && z > 0) {
	    mask |= GLW_ACCUM;
	}
    } else {
	mask |= GLW_INDEX;
    }

⌨️ 快捷键说明

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