Beispiel #1
0
Datei: glx.c Projekt: zwizwa/pdp
void zl_glx_vsync(zl_glx *x, bool sync) {
#ifdef TARGET_WIN32
    if (sync) {
        if (GLEE_WGL_EXT_swap_control) wglSwapIntervalEXT (1);
    } else {
        if (GLEE_WGL_EXT_swap_control) wglSwapIntervalEXT (0);
    }
#endif
#ifdef TARGET_OSX
    long sync = sync ? 1 : 0;
    CGLSetParameter (CGLGetCurrentContext(), kCGLCPSwapInterval, &sync);
#endif
#ifdef TARGET_LINUX
    int interval = sync ? 2 : 0;
    glXSwapIntervalSGIFunc glXSwapIntervalSGI = 0;
    glXSwapIntervalMESAFunc glXSwapIntervalMESA = 0;

    if (GLXExtensionSupported(x->xdpy->dpy, "GLX_MESA_swap_control")) {
        glXSwapIntervalMESA = (glXSwapIntervalMESAFunc)
            glXGetProcAddressARB((const GLubyte *)"glXSwapIntervalMESA");
        if (glXSwapIntervalMESA) {
            ZL_LOG("glXSwapIntervalMESA(%d)", interval);
            glXSwapIntervalMESA (interval);
        }
        else {
            ZL_LOG("Could not get glXSwapIntervalMESA()\n");
        }
    }
    else if (GLXExtensionSupported(x->xdpy->dpy, "GLX_SGI_swap_control")) {
        glXSwapIntervalSGI = (glXSwapIntervalSGIFunc)
            glXGetProcAddressARB((const GLubyte *)"glXSwapIntervalSGI");
        if (glXSwapIntervalSGI) {
            ZL_LOG("glXSwapIntervalSGI(%d)", interval, glXSwapIntervalSGI);
            glXSwapIntervalSGI (interval);
        }
        else {
            ZL_LOG("Could not get glXSwapIntervalSGI()\n");
        }
    }
    else {
        ZL_LOG("can't change vblank settings");
    }
#endif
}
Beispiel #2
0
int main(int argc, char *argv[])
{
	Display *disp;
	XVisualInfo *pvi;
	XSetWindowAttributes swa;
	int attrib[14];
	GLint last_val = -1, count = 0;
	Window winGL;
	GLXContext context;
	int dummy;
	Atom wmDelete;
	enum sync_type waitforsync = none;
	int width = 500, height = 500, verbose = 0,
		countonly = 0;
	int c, i = 1;

	opterr = 0;
	while ((c = getopt(argc, argv, optstr)) != -1) {
		switch (c) {
		case 'w':
			width = atoi(optarg);
			break;
		case 'h':
			height = atoi(optarg);
			break;
		case 's':
			switch (optarg[0]) {
			case 'n':
				waitforsync = none;
				break;
			case 's':
				waitforsync = sgi_video_sync;
				break;
			case 'b':
				waitforsync = buffer_swap;
				break;
			default:
				usage(argv[0]);
				break;
			}
			break;
		case 'v':
			verbose = 1;
			break;
		default:
			usage(argv[0]);
			break;
		}
	}

	disp = XOpenDisplay(NULL);
	if (!disp) {
		fprintf(stderr, "failed to open display\n");
		return -1;
	}

	if (!glXQueryExtension(disp, &dummy, &dummy)) {
		fprintf(stderr, "glXQueryExtension failed\n");
		return -1;
	}

	if (!GLXExtensionSupported(disp, "GLX_SGI_video_sync")) {
		fprintf(stderr, "GLX_SGI_video_sync not supported, exiting\n");
		return -1;
	}

	attrib[0] = GLX_RGBA;
	attrib[1] = 1;
	attrib[2] = GLX_RED_SIZE;
	attrib[3] = 1;
	attrib[4] = GLX_GREEN_SIZE;
	attrib[5] = 1;
	attrib[6] = GLX_BLUE_SIZE;
	attrib[7] = 1;
	if (waitforsync != buffer_swap)
		attrib[8] = None;
	else {
		attrib[8] = GLX_DOUBLEBUFFER;
		attrib[9] = 1;
		attrib[10] = None;
	}

	pvi = glXChooseVisual(disp, DefaultScreen(disp), attrib);
	if (!pvi) {
		fprintf(stderr, "failed to choose visual, exiting\n");
		return -1;
	}

	context = glXCreateContext(disp, pvi, None, GL_TRUE);
	if (!context) {
		fprintf(stderr, "failed to create glx context\n");
		return -1;
	}

	pvi->screen = DefaultScreen(disp);

	swa.colormap = XCreateColormap(disp, RootWindow(disp, pvi->screen),
				       pvi->visual, AllocNone);
	swa.border_pixel = 0;
	swa.event_mask = ExposureMask | KeyPressMask | ButtonPressMask |
		StructureNotifyMask;
	winGL = XCreateWindow(disp, RootWindow(disp, pvi->screen),
			      0, 0,
			      width, height,
			      0, pvi->depth, InputOutput, pvi->visual,
			      CWBorderPixel | CWColormap | CWEventMask, &swa);
	if (!winGL) {
		fprintf(stderr, "window creation failed\n");
		return -1;
	}
        wmDelete = XInternAtom(disp, "WM_DELETE_WINDOW", True);
        XSetWMProtocols(disp, winGL, &wmDelete, 1);

	XSetStandardProperties(disp, winGL, "glsync test", "glsync text",
			       None, NULL, 0, NULL);

	XMapRaised(disp, winGL);

	glXMakeCurrent(disp, winGL, context);

	video_sync_get = glXGetProcAddress((unsigned char *)"glXGetVideoSyncSGI");
	video_sync = glXGetProcAddress((unsigned char *)"glXWaitVideoSyncSGI");

	if (!video_sync_get || !video_sync) {
		fprintf(stderr, "failed to get sync functions\n");
		return -1;
	}

	video_sync_get(&count);
	count++;
	while (i++) {
		/* Wait for vsync */
		if (waitforsync == sgi_video_sync) {
			if (verbose)
				fprintf(stderr, "waiting on count %d\n", count);
			video_sync(2, (count + 1) % 2, &count);
			if (count < last_val)
				fprintf(stderr, "error:  vblank count went backwards: %d -> %d\n", last_val, count);
			if (count == last_val)
				fprintf(stderr, "error:  count didn't change: %d\n", count);
			last_val = count;
		} else if (waitforsync == buffer_swap) {
			glXSwapBuffers(disp, winGL);
		}

		if (countonly) {
			video_sync(2, 1, &count);
			fprintf(stderr, "current count: %d\n", count);
			sleep(1);
			continue;
		}

		/* Alternate colors to make tearing obvious */
		if (i & 1)
			glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
		else
			glClearColor(1.0f, 0.0f, 0.0f, 0.0f);
		glClear(GL_COLOR_BUFFER_BIT);
		glFlush();
	}

	XDestroyWindow(disp, winGL);
	glXDestroyContext(disp, context);
	XCloseDisplay(disp);

	return 0;
}
Beispiel #3
0
static int
glw_x11_init(glw_x11_t *gx11)
{
  int attribs[10];
  int na = 0;
  
  XInitThreads();

  int use_locales = XSupportsLocale() && XSetLocaleModifiers("") != NULL;

  if((gx11->display = XOpenDisplay(gx11->displayname_real)) == NULL) {
    TRACE(TRACE_ERROR, "GLW", "Unable to open X display \"%s\"\n",
	    gx11->displayname_real);
    return 1;
  }

  if(!glXQueryExtension(gx11->display, NULL, NULL)) {
    TRACE(TRACE_ERROR, "GLW", 
	  "OpenGL GLX extension not supported by display \"%s\"\n",
	    gx11->displayname_real);
    return 1;
  }


  gx11->screen        = DefaultScreen(gx11->display);
  gx11->screen_width  = DisplayWidth(gx11->display, gx11->screen);
  gx11->screen_height = DisplayHeight(gx11->display, gx11->screen);
  gx11->root          = RootWindow(gx11->display, gx11->screen);
 
  attribs[na++] = GLX_RGBA;
  attribs[na++] = GLX_RED_SIZE;
  attribs[na++] = 1;
  attribs[na++] = GLX_GREEN_SIZE;
  attribs[na++] = 1;
  attribs[na++] = GLX_BLUE_SIZE; 
  attribs[na++] = 1;
  attribs[na++] = GLX_DOUBLEBUFFER;
  attribs[na++] = None;
  
  gx11->xvi = glXChooseVisual(gx11->display, gx11->screen, attribs);

  if(gx11->xvi == NULL) {
    TRACE(TRACE_ERROR, "GLW", "Unable to find an adequate Visual on \"%s\"\n",
	    gx11->displayname_real);
    return 1;
  }
  
  if(GLXExtensionSupported(gx11->display, "GLX_SGI_swap_control")) {
    TRACE(TRACE_DEBUG, "GLW", "GLX_SGI_swap_control extension is present");
    gx11->glXSwapIntervalSGI = (PFNGLXSWAPINTERVALSGIPROC)
      glXGetProcAddress((const GLubyte*)"glXSwapIntervalSGI");
  }

  build_blank_cursor(gx11);

  if(use_locales)
    gx11->im = XOpenIM(gx11->display, NULL, NULL, NULL);


  gx11->atom_deletewindow = 
    XInternAtom(gx11->display, "WM_DELETE_WINDOW", 0);

#if ENABLE_VDPAU
  if(GLXExtensionSupported(gx11->display, "GLX_EXT_texture_from_pixmap")) {

    gx11->gr.gr_be.gbr_bind_tex_image = (PFNGLXBINDTEXIMAGEEXTPROC)
      glXGetProcAddress((const GLubyte*)"glXBindTexImageEXT");

    gx11->gr.gr_be.gbr_release_tex_image = (PFNGLXRELEASETEXIMAGEEXTPROC)
      glXGetProcAddress((const GLubyte*)"glXReleaseTexImageEXT");

    gx11->gr.gr_be.gbr_vdpau_dev = vdpau_init_x11(gx11->display, gx11->screen,
						  vdpau_preempted, gx11);

  } else {
    TRACE(TRACE_DEBUG, "VDPAU", 
	  "GLX_EXT_texture_from_pixmap extension not present, disabling VDPAU");
  }
#endif

  probe_wm(gx11);


  gx11->is_fullscreen = gx11->want_fullscreen;

  int fs = 0;
  if(gx11->wm_flags == 0) {
    fs = 1; // No window manager, open in fullscreen mode
  } else {
    /* If window manager cannot do fullscreen, ask window to open 
       in fullscreen mode */
    fs = gx11->want_fullscreen && !(gx11->wm_flags & GX11_WM_CAN_FULLSCREEN);
  }

  if(window_open(gx11, fs))
    return -1;

  // Fullscreen via window manager
  if(gx11->want_fullscreen && !fs)
    wm_set_fullscreen(gx11, 1);

  return 0;
}
Beispiel #4
0
static int
glw_x11_init(glw_x11_t *gx11)
{
  int attribs[10];
  int na = 0;
  
  int use_locales = XSupportsLocale() && XSetLocaleModifiers("@im=none") != NULL;

  if((gx11->display = XOpenDisplay(gx11->displayname_real)) == NULL) {
    TRACE(TRACE_ERROR, "GLW", "Unable to open X display \"%s\"\n",
          gx11->displayname_real);
    return 1;
  }

  if(!glXQueryExtension(gx11->display, NULL, NULL)) {
    TRACE(TRACE_ERROR, "GLW", 
	  "OpenGL GLX extension not supported by display \"%s\"\n",
          gx11->displayname_real);
    return 1;
  }


  gx11->screen        = DefaultScreen(gx11->display);
  gx11->screen_width  = DisplayWidth(gx11->display, gx11->screen);
  gx11->screen_height = DisplayHeight(gx11->display, gx11->screen);
  gx11->root          = RootWindow(gx11->display, gx11->screen);
 
  attribs[na++] = GLX_RGBA;
  attribs[na++] = GLX_RED_SIZE;
  attribs[na++] = 1;
  attribs[na++] = GLX_GREEN_SIZE;
  attribs[na++] = 1;
  attribs[na++] = GLX_BLUE_SIZE; 
  attribs[na++] = 1;
  attribs[na++] = GLX_DOUBLEBUFFER;
  attribs[na++] = None;
  
  gx11->xvi = glXChooseVisual(gx11->display, gx11->screen, attribs);

  if(gx11->xvi == NULL) {
    TRACE(TRACE_ERROR, "GLW", "Unable to find an adequate Visual on \"%s\"\n",
          gx11->displayname_real);
    return 1;
  }
  
  if(GLXExtensionSupported(gx11->display, "GLX_SGI_swap_control")) {
    TRACE(TRACE_DEBUG, "GLW", "GLX_SGI_swap_control extension is present");
    gx11->glXSwapIntervalSGI = (PFNGLXSWAPINTERVALSGIPROC)
      glXGetProcAddress((const GLubyte*)"glXSwapIntervalSGI");
  }

  build_blank_cursor(gx11);

  if(use_locales)
    gx11->im = XOpenIM(gx11->display, NULL, NULL, NULL);


  gx11->atom_deletewindow = 
    XInternAtom(gx11->display, "WM_DELETE_WINDOW", 0);

#if ENABLE_VDPAU

  gx11->gr.gr_be.gbr_glVDPAUInitNV =
    (PFNGLVDPAUINITNVPROC)
    glXGetProcAddress((const GLubyte*)"glVDPAUInitNV");

  if(gx11->gr.gr_be.gbr_glVDPAUInitNV != NULL) {

    vdpau_dev_t *vd;
    vd = vdpau_init_x11(gx11->display, gx11->screen, vdpau_preempted, gx11);
    gx11->gr.gr_be.gbr_vdpau_dev = vd;

    gx11->gr.gr_be.gbr_glVDPAUUnregisterSurfaceNV =
      (PFNGLVDPAUUNREGISTERSURFACENVPROC)
      glXGetProcAddress((const GLubyte*)"glVDPAUUnregisterSurfaceNV");

    gx11->gr.gr_be.gbr_glVDPAUUnmapSurfacesNV =
      (PFNGLVDPAUUNMAPSURFACESNVPROC)
      glXGetProcAddress((const GLubyte*)"glVDPAUUnmapSurfacesNV");

    gx11->gr.gr_be.gbr_glVDPAURegisterOutputSurfaceNV =
      (PFNGLVDPAUREGISTEROUTPUTSURFACENVPROC)
      glXGetProcAddress((const GLubyte*)"glVDPAURegisterOutputSurfaceNV");

    gx11->gr.gr_be.gbr_glVDPAUMapSurfacesNV =
      (PFNGLVDPAUMAPSURFACESNVPROC)
      glXGetProcAddress((const GLubyte*)"glVDPAUMapSurfacesNV");
  }
#endif

  probe_wm(gx11);


  gx11->is_fullscreen = gx11->want_fullscreen;

  int fs = 0;
  if(gx11->wm_flags == 0) {
    fs = 1; // No window manager, open in fullscreen mode
  } else {
    /* If window manager cannot do fullscreen, ask window to open 
       in fullscreen mode */
    fs = gx11->want_fullscreen && !(gx11->wm_flags & GX11_WM_CAN_FULLSCREEN);
  }

  if(window_open(gx11, fs))
    return -1;

  // Fullscreen via window manager
  if(gx11->want_fullscreen && !fs)
    wm_set_fullscreen(gx11, 1);

  return 0;
}
Beispiel #5
0
static void *gfx_ctx_x_init(video_frame_info_t *video_info, void *data)
{
   int nelements           = 0;
   int major               = 0;
   int minor               = 0;
#ifdef HAVE_OPENGL
   static const int visual_attribs[] = {
      GLX_X_RENDERABLE     , True,
      GLX_DRAWABLE_TYPE    , GLX_WINDOW_BIT,
      GLX_RENDER_TYPE      , GLX_RGBA_BIT,
      GLX_DOUBLEBUFFER     , True,
      GLX_RED_SIZE         , 8,
      GLX_GREEN_SIZE       , 8,
      GLX_BLUE_SIZE        , 8,
      GLX_ALPHA_SIZE       , 8,
      GLX_DEPTH_SIZE       , 0,
      GLX_STENCIL_SIZE     , 0,
      GLX_SAMPLE_BUFFERS   , 0,
      GLX_SAMPLES          , 0,
      None
   };
   GLXFBConfig *fbcs       = NULL;
#endif
   gfx_ctx_x_data_t *x = (gfx_ctx_x_data_t*)
      calloc(1, sizeof(gfx_ctx_x_data_t));
#ifndef GL_DEBUG
   struct retro_hw_render_callback *hwr =
      video_driver_get_hw_context();
#endif

   if (!x)
      return NULL;

   current_context_data = x;

   XInitThreads();

   if (!x11_connect())
      goto error;


   switch (x_api)
   {
      case GFX_CTX_OPENGL_API:
      case GFX_CTX_OPENGL_ES_API:
#if defined(HAVE_OPENGL) || defined(HAVE_OPENGLES)
         glXQueryVersion(g_x11_dpy, &major, &minor);

         /* GLX 1.3+ minimum required. */
         if ((major * 1000 + minor) < 1003)
            goto error;

         glx_create_context_attribs = (PFNGLXCREATECONTEXTATTRIBSARBPROC)
            glXGetProcAddress((const GLubyte*)"glXCreateContextAttribsARB");

#ifdef GL_DEBUG
         x->g_debug = true;
#else
         x->g_debug = hwr->debug_context;
#endif

         /* Have to use ContextAttribs */
#ifdef HAVE_OPENGLES2
         x->g_core_es      = true;
         x->g_core_es_core = true;
#else
         x->g_core_es      = (g_major * 1000 + g_minor) >= 3001;
         x->g_core_es_core = (g_major * 1000 + g_minor) >= 3002;
#endif

         if ((x->g_core_es || x->g_debug) && !glx_create_context_attribs)
            goto error;

         fbcs = glXChooseFBConfig(g_x11_dpy, DefaultScreen(g_x11_dpy),
               visual_attribs, &nelements);

         if (!fbcs)
            goto error;

         if (!nelements)
         {
            XFree(fbcs);
            goto error;
         }

         x->g_fbc = fbcs[0];
         XFree(fbcs);
#endif
         break;
      case GFX_CTX_VULKAN_API:
#ifdef HAVE_VULKAN
         /* Use XCB WSI since it's the most supported WSI over legacy Xlib. */
         if (!vulkan_context_init(&x->vk, VULKAN_WSI_XCB))
            goto error;
#endif
         break;

      case GFX_CTX_NONE:
      default:
         break;
   }

   switch (x_api)
   {
      case GFX_CTX_OPENGL_API:
#ifdef HAVE_OPENGL
	 if (GLXExtensionSupported(g_x11_dpy, "GLX_EXT_swap_control_tear"))
	 {
            RARCH_LOG("[GLX]: GLX_EXT_swap_control_tear supported.\n");
	    x_adaptive_vsync = true;
	 }
         if (GLXExtensionSupported(g_x11_dpy, "GLX_OML_sync_control") &&
             GLXExtensionSupported(g_x11_dpy, "GLX_MESA_swap_control")
            )
         {
            RARCH_LOG("[GLX]: GLX_OML_sync_control and GLX_MESA_swap_control supported, using better swap control method...\n");

            x->swap_mode         = 1;

            glXGetSyncValuesOML  = (GLXGETSYNCVALUESOMLPROC)glXGetProcAddress((unsigned char *)"glXGetSyncValuesOML");
            glXGetMscRateOML     = (GLXGETMSCRATEOMLPROC)glXGetProcAddress((unsigned char *)"glXGetMscRateOML");
            glXSwapBuffersMscOML = (GLXSWAPBUFFERSMSCOMLPROC)glXGetProcAddress((unsigned char *)"glXSwapBuffersMscOML");
            glXWaitForMscOML     = (GLXWAITFORMSCOMLPROC)glXGetProcAddress((unsigned char *)"glXWaitForMscOML");
            glXWaitForSbcOML     = (GLXWAITFORSBCOMLPROC)glXGetProcAddress((unsigned char *)"glXWaitForSbcOML");

            glXGetSyncValuesOML(g_x11_dpy, g_x11_win, &x->ust, &x->msc, &x->sbc);

#if 0
            RARCH_LOG("[GLX]: UST: %d, MSC: %d, SBC: %d\n", x->ust, x->msc, x->sbc);
#endif
         }
#endif
         break;
      default:
         break;
   }

   return x;

error:
   if (x)
   {
      gfx_ctx_x_destroy_resources(x);
      free(x);
   }
   g_x11_screen = 0;

   return NULL;
}