示例#1
0
SDL_GLContext
X11_GL_CreateContext(_THIS, SDL_Window * window)
{
    SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
    Display *display = data->videodata->display;
    int screen =
        ((SDL_DisplayData *) SDL_GetDisplayFromWindow(window)->
         driverdata)->screen;
    XWindowAttributes xattr;
    XVisualInfo v, *vinfo;
    int n;
    GLXContext context = NULL;

    /* We do this to create a clean separation between X and GLX errors. */
    XSync(display, False);
    XGetWindowAttributes(display, data->window, &xattr);
    v.screen = screen;
    v.visualid = XVisualIDFromVisual(xattr.visual);
    vinfo = XGetVisualInfo(display, VisualScreenMask | VisualIDMask, &v, &n);
    if (vinfo) {
        if (_this->gl_config.major_version < 3) {
            context =
                _this->gl_data->glXCreateContext(display, vinfo, NULL, True);
        } else {
            /* If we want a GL 3.0 context or later we need to get a temporary
               context to grab the new context creation function */
            GLXContext temp_context =
                _this->gl_data->glXCreateContext(display, vinfo, NULL, True);
            if (!temp_context) {
                SDL_SetError("Could not create GL context");
                return NULL;
            } else {
                int attribs[] = {
                    GLX_CONTEXT_MAJOR_VERSION_ARB,
                    _this->gl_config.major_version,
                    GLX_CONTEXT_MINOR_VERSION_ARB,
                    _this->gl_config.minor_version,
                    0
                };

                /* Get a pointer to the context creation function for GL 3.0 */
                PFNGLXCREATECONTEXTATTRIBSARBPROC glXCreateContextAttribs =
                    (PFNGLXCREATECONTEXTATTRIBSARBPROC) _this->gl_data->
                    glXGetProcAddress((GLubyte *)
                                      "glXCreateContextAttribsARB");
                if (!glXCreateContextAttribs) {
                    SDL_SetError("GL 3.x is not supported");
                    context = temp_context;
                } else {
                    /* Create a GL 3.x context */
                    GLXFBConfig *framebuffer_config = NULL;
                    int fbcount = 0;
                    GLXFBConfig *(*glXChooseFBConfig) (Display * disp,
                                                       int screen,
                                                       const int *attrib_list,
                                                       int *nelements);

                    glXChooseFBConfig =
                        (GLXFBConfig *
                         (*)(Display *, int, const int *,
                             int *)) _this->gl_data->
                        glXGetProcAddress((GLubyte *) "glXChooseFBConfig");

                    if (!glXChooseFBConfig
                        || !(framebuffer_config =
                             glXChooseFBConfig(display,
                                               DefaultScreen(display), NULL,
                                               &fbcount))) {
                        SDL_SetError
                            ("No good framebuffers found. GL 3.x disabled");
                        context = temp_context;
                    } else {
                        context =
                            glXCreateContextAttribs(display,
                                                    framebuffer_config[0],
                                                    NULL, True, attribs);
                        _this->gl_data->glXDestroyContext(display,
                                                          temp_context);
                    }
                }
            }
        }
        XFree(vinfo);
    }
    XSync(display, False);

    if (!context) {
        SDL_SetError("Could not create GL context");
        return NULL;
    }

    if (X11_GL_MakeCurrent(_this, window, context) < 0) {
        X11_GL_DeleteContext(_this, context);
        return NULL;
    }

    return context;
}
示例#2
0
/**
 * return prefered frame format (if this is 100% correct, I eat my shorts ;)
 */
static const char *_format()
{
        if(!_c.display)
                NFT_LOG_NULL(NULL);

        /* our result */
        char *res = "error";
        
        /* get XVisualInfo */
        XVisualInfo vi_proto = { .screen = _c.screen };
        XVisualInfo *vi;
        int nvi = 0;
        vi = XGetVisualInfo(_c.display, VisualScreenMask, &vi_proto, &nvi);
        if(!nvi)
        {
                NFT_LOG(L_ERROR, "No VisualInfo's returned?!");
                return NULL;
        }
        
        /* get default visual id */
        VisualID id;
        id = XVisualIDFromVisual(DefaultVisual(_c.display, _c.screen));

        /* get our VisualInfo */
        XVisualInfo *myvi = NULL;
        int i;
        for(i=0; i<nvi; i++)
        {
                if((vi[i].visualid) == id)
                {
                        myvi = &vi[i];
                        break;
                }
        }

        /* this may not happen */
        if(!myvi)
        {
                NFT_LOG(L_ERROR, "Didn't find our VisualID?!");
                goto _f_exit;
        }


        /* decide about bits-per-component */
        switch(myvi->bits_per_rgb)
        {
                case 8:
                {
                        res = "ARGB u8";
                        break;
                }

                case 16:
                {
                        res = "ARGB u16";
                        break;
                }

                case 32:
                {
                        res = "ARGB u32";
                        break;
                }
                        
                default:
                {
                        NFT_LOG(L_ERROR, "Invalid bits-per-component: %d", myvi->bits_per_rgb);
                        return NULL;
                }
                        
        }
        
        
_f_exit:
        NFT_LOG(L_VERBOSE, "Depth: %d Red-mask: 0x%lx Green-mask: "
                           "0x%lx Blue-mask: 0x%lx Bits per component: %d",
                               myvi->depth, 
                               myvi->red_mask, 
                               myvi->green_mask, 
                               myvi->blue_mask,
                               myvi->bits_per_rgb);
        XFree(vi);
        
        return (const char *) res;
}


/**
 * return whether capture mechanism delivers big-endian ordered data
 */
static bool _is_big_endian()
{
        if(XImageByteOrder(_c.display) == LSBFirst)
                return TRUE;
        else
                return FALSE;
}

/** descriptor of this mechanism */
CaptureMechanism XLIB =
{
        .name = "Xlib",
        .init = _init,
        .deinit = _deinit,
        .capture = _capture,
        .format = _format,
        .is_big_endian = _is_big_endian,
};
示例#3
0
XVisualInfo GlxContext::selectBestVisual(::Display* display, unsigned int bitsPerPixel, const ContextSettings& settings)
{
    // Retrieve all the visuals
    int count;
    XVisualInfo* visuals = XGetVisualInfo(display, 0, NULL, &count);
    if (visuals)
    {
        // Evaluate all the returned visuals, and pick the best one
        int bestScore = 0x7FFFFFFF;
        XVisualInfo bestVisual;
        for (int i = 0; i < count; ++i)
        {
            // Check mandatory attributes
            int doubleBuffer;
            glXGetConfig(display, &visuals[i], GLX_DOUBLEBUFFER, &doubleBuffer);
            if (!doubleBuffer)
                continue;

            // Extract the components of the current visual
            int red, green, blue, alpha, depth, stencil, multiSampling, samples;
            glXGetConfig(display, &visuals[i], GLX_RED_SIZE,     &red);
            glXGetConfig(display, &visuals[i], GLX_GREEN_SIZE,   &green);
            glXGetConfig(display, &visuals[i], GLX_BLUE_SIZE,    &blue);
            glXGetConfig(display, &visuals[i], GLX_ALPHA_SIZE,   &alpha);
            glXGetConfig(display, &visuals[i], GLX_DEPTH_SIZE,   &depth);
            glXGetConfig(display, &visuals[i], GLX_STENCIL_SIZE, &stencil);

            if (sfglx_ext_ARB_multisample == sfglx_LOAD_SUCCEEDED)
            {
                glXGetConfig(display, &visuals[i], GLX_SAMPLE_BUFFERS_ARB, &multiSampling);
                glXGetConfig(display, &visuals[i], GLX_SAMPLES_ARB,        &samples);
            }
            else
            {
                multiSampling = 0;
                samples = 0;
            }

            // TODO: Replace this with proper acceleration detection
            bool accelerated = true;

            // Evaluate the visual
            int color = red + green + blue + alpha;
            int score = evaluateFormat(bitsPerPixel, settings, color, depth, stencil, multiSampling ? samples : 0, accelerated);

            // If it's better than the current best, make it the new best
            if (score < bestScore)
            {
                bestScore = score;
                bestVisual = visuals[i];
            }
        }

        // Free the array of visuals
        XFree(visuals);

        return bestVisual;
    }
    else
    {
        // Should never happen...
        err() << "No GLX visual found. You should check your graphics driver" << std::endl;

        return XVisualInfo();
    }
}
示例#4
0
Visual *
createVisual(bool doubleBuffer, unsigned samples, Profile profile) {
    EGLint api_bits;
    if (profile.api == glprofile::API_GL) {
        api_bits = EGL_OPENGL_BIT;
        if (profile.core && !has_EGL_KHR_create_context) {
            return NULL;
        }
    } else if (profile.api == glprofile::API_GLES) {
        switch (profile.major) {
        case 1:
            api_bits = EGL_OPENGL_ES_BIT;
            break;
        case 3:
            if (has_EGL_KHR_create_context) {
                api_bits = EGL_OPENGL_ES3_BIT;
                break;
            }
            /* fall-through */
        case 2:
            api_bits = EGL_OPENGL_ES2_BIT;
            break;
        default:
            return NULL;
        }
    } else {
        assert(0);
        return NULL;
    }

    Attributes<EGLint> attribs;
    attribs.add(EGL_SURFACE_TYPE, EGL_WINDOW_BIT);
    attribs.add(EGL_RED_SIZE, 1);
    attribs.add(EGL_GREEN_SIZE, 1);
    attribs.add(EGL_BLUE_SIZE, 1);
    attribs.add(EGL_ALPHA_SIZE, 1);
    attribs.add(EGL_DEPTH_SIZE, 1);
    attribs.add(EGL_STENCIL_SIZE, 1);
    attribs.add(EGL_RENDERABLE_TYPE, api_bits);
    attribs.end(EGL_NONE);

    EGLint num_configs = 0;
    if (!eglGetConfigs(eglDisplay, NULL, 0, &num_configs) ||
        num_configs <= 0) {
        return NULL;
    }

    std::vector<EGLConfig> configs(num_configs);
    if (!eglChooseConfig(eglDisplay, attribs, &configs[0], num_configs,  &num_configs) ||
        num_configs <= 0) {
        return NULL;
    }

    // We can't tell what other APIs the trace will use afterwards, therefore
    // try to pick a config which supports the widest set of APIs.
    int bestScore = -1;
    EGLConfig config = configs[0];
    for (EGLint i = 0; i < num_configs; ++i) {
        EGLint renderable_type = EGL_NONE;
        eglGetConfigAttrib(eglDisplay, configs[i], EGL_RENDERABLE_TYPE, &renderable_type);
        int score = 0;
        assert(renderable_type & api_bits);
        renderable_type &= ~api_bits;
        if (renderable_type & EGL_OPENGL_ES2_BIT) {
            score += 1 << 4;
        }
        if (renderable_type & EGL_OPENGL_ES3_BIT) {
            score += 1 << 3;
        }
        if (renderable_type & EGL_OPENGL_ES_BIT) {
            score += 1 << 2;
        }
        if (renderable_type & EGL_OPENGL_BIT) {
            score += 1 << 1;
        }
        if (score > bestScore) {
            config = configs[i];
            bestScore = score;
        }
    }
    assert(bestScore >= 0);

    EGLint visual_id;
    if (!eglGetConfigAttrib(eglDisplay, config, EGL_NATIVE_VISUAL_ID, &visual_id)) {
        assert(0);
        return NULL;
    }

    EglVisual *visual = new EglVisual(profile);
    visual->config = config;

    XVisualInfo templ;
    int num_visuals = 0;
    templ.visualid = visual_id;
    visual->visinfo = XGetVisualInfo(display, VisualIDMask, &templ, &num_visuals);
    assert(visual->visinfo);

    return visual;
}
示例#5
0
static bool gfx_ctx_xegl_set_video_mode(void *data,
   unsigned width, unsigned height,
   bool fullscreen)
{
   EGLint egl_attribs[16];
   EGLint *attr;
   EGLint vid, num_visuals;
   bool windowed_full;
   bool true_full = false;
   int x_off = 0;
   int y_off = 0;
   struct sigaction sa = {{0}};
   XVisualInfo temp = {0};
   XSetWindowAttributes swa = {0};
   XVisualInfo *vi = NULL;
   driver_t *driver     = driver_get_ptr();
   settings_t *settings = config_get_ptr();

   int (*old_handler)(Display*, XErrorEvent*) = NULL;

   XEvent event;

   sa.sa_handler = egl_sighandler;
   sa.sa_flags   = SA_RESTART;
   sigemptyset(&sa.sa_mask);
   sigaction(SIGINT, &sa, NULL);
   sigaction(SIGTERM, &sa, NULL);

   windowed_full = settings->video.windowed_fullscreen;
   true_full = false;

   attr = egl_attribs;
   attr = xegl_fill_attribs(attr);

   if (!eglGetConfigAttrib(g_egl_dpy, g_egl_config, EGL_NATIVE_VISUAL_ID, &vid))
      goto error;

   temp.visualid = vid;

   vi = XGetVisualInfo(g_dpy, VisualIDMask, &temp, &num_visuals);
   if (!vi)
      goto error;

   swa.colormap = g_cmap = XCreateColormap(g_dpy, RootWindow(g_dpy, vi->screen),
         vi->visual, AllocNone);
   swa.event_mask = StructureNotifyMask | KeyPressMask | ButtonPressMask | ButtonReleaseMask | KeyReleaseMask;
   swa.override_redirect = fullscreen ? True : False;

   if (fullscreen && !windowed_full)
   {
      if (x11_enter_fullscreen(g_dpy, width, height, &g_desktop_mode))
      {
         g_should_reset_mode = true;
         true_full = true;
      }
      else
         RARCH_ERR("[X/EGL]: Entering true fullscreen failed. Will attempt windowed mode.\n");
   }

   if (settings->video.monitor_index)
      g_screen = settings->video.monitor_index - 1;

#ifdef HAVE_XINERAMA
   if (fullscreen || g_screen != 0)
   {
      unsigned new_width  = width;
      unsigned new_height = height;

      if (x11_get_xinerama_coord(g_dpy, g_screen, &x_off, &y_off, &new_width, &new_height))
         RARCH_LOG("[X/EGL]: Using Xinerama on screen #%u.\n", g_screen);
      else
         RARCH_LOG("[X/EGL]: Xinerama is not active on screen.\n");

      if (fullscreen)
      {
         width  = new_width;
         height = new_height;
      }
   }
#endif

   RARCH_LOG("[X/EGL]: X = %d, Y = %d, W = %u, H = %u.\n",
         x_off, y_off, width, height);

   g_win = XCreateWindow(g_dpy, RootWindow(g_dpy, vi->screen),
         x_off, y_off, width, height, 0,
         vi->depth, InputOutput, vi->visual, 
         CWBorderPixel | CWColormap | CWEventMask | (true_full ? CWOverrideRedirect : 0), &swa);
   XSetWindowBackground(g_dpy, g_win, 0);

   g_egl_ctx = eglCreateContext(g_egl_dpy, g_egl_config, EGL_NO_CONTEXT,
         attr != egl_attribs ? egl_attribs : NULL);

   RARCH_LOG("[X/EGL]: Created context: %p.\n", (void*)g_egl_ctx);

   if (g_egl_ctx == EGL_NO_CONTEXT)
      goto error;

   if (g_use_hw_ctx)
   {
      g_egl_hw_ctx = eglCreateContext(g_egl_dpy, g_egl_config, g_egl_ctx,
            attr != egl_attribs ? egl_attribs : NULL);
      RARCH_LOG("[X/EGL]: Created shared context: %p.\n", (void*)g_egl_hw_ctx);

      if (g_egl_hw_ctx == EGL_NO_CONTEXT)
         goto error;
   }

   g_egl_surf = eglCreateWindowSurface(g_egl_dpy, g_egl_config, (EGLNativeWindowType)g_win, NULL);
   if (!g_egl_surf)
      goto error;

   if (!eglMakeCurrent(g_egl_dpy, g_egl_surf, g_egl_surf, g_egl_ctx))
      goto error;

   RARCH_LOG("[X/EGL]: Current context: %p.\n", (void*)eglGetCurrentContext());

   x11_set_window_attr(g_dpy, g_win);

   if (fullscreen)
      x11_show_mouse(g_dpy, g_win, false);

   if (true_full)
   {
      RARCH_LOG("[X/EGL]: Using true fullscreen.\n");
      XMapRaised(g_dpy, g_win);
   }
   else if (fullscreen) 
   {
      /* We attempted true fullscreen, but failed.
       * Attempt using windowed fullscreen. */
      XMapRaised(g_dpy, g_win);
      RARCH_LOG("[X/EGL]: Using windowed fullscreen.\n");

      /* We have to move the window to the screen we 
       * want to go fullscreen on first.
       * x_off and y_off usually get ignored in XCreateWindow().
       */
      x11_move_window(g_dpy, g_win, x_off, y_off, width, height);
      x11_windowed_fullscreen(g_dpy, g_win);
   }
   else
   {
      XMapWindow(g_dpy, g_win);

      /* If we want to map the window on a different screen, 
       * we'll have to do it by force.
       *
       * Otherwise, we should try to let the window manager sort it out.
       * x_off and y_off usually get ignored in XCreateWindow().
       */
      if (g_screen)
         x11_move_window(g_dpy, g_win, x_off, y_off, width, height);
   }

   XIfEvent(g_dpy, &event, egl_wait_notify, NULL);

   g_quit_atom = XInternAtom(g_dpy, "WM_DELETE_WINDOW", False);
   if (g_quit_atom)
      XSetWMProtocols(g_dpy, g_win, &g_quit_atom, 1);

   gfx_ctx_xegl_swap_interval(data, g_interval);

   /* This can blow up on some drivers. It's not fatal, 
    * so override errors for this call.
    */
   old_handler = XSetErrorHandler(egl_nul_handler);
   XSetInputFocus(g_dpy, g_win, RevertToNone, CurrentTime);
   XSync(g_dpy, False);
   XSetErrorHandler(old_handler);

   XFree(vi);
   g_has_focus = true;
   g_inited    = true;

   if (!x11_create_input_context(g_dpy, g_win, &g_xim, &g_xic))
      goto error;

   driver->display_type  = RARCH_DISPLAY_X11;
   driver->video_display = (uintptr_t)g_dpy;
   driver->video_window  = (uintptr_t)g_win;
   g_true_full = true_full;

   return true;

error:
   if (vi)
      XFree(vi);

   gfx_ctx_xegl_destroy(data);
   return false;
}
示例#6
0
static bool gfx_ctx_xegl_set_video_mode(void *data,
   unsigned width, unsigned height,
   bool fullscreen)
{
   XEvent event;
   EGLint egl_attribs[16];
   EGLint *attr;
   EGLint vid, num_visuals;
   bool windowed_full;
   bool true_full = false;
   int x_off = 0;
   int y_off = 0;
   XVisualInfo temp = {0};
   XSetWindowAttributes swa = {0};
   XVisualInfo *vi = NULL;
   driver_t *driver     = driver_get_ptr();
   settings_t *settings = config_get_ptr();

   int (*old_handler)(Display*, XErrorEvent*) = NULL;

   x11_install_sighandlers();

   windowed_full = settings->video.windowed_fullscreen;

   attr = egl_attribs;
   attr = xegl_fill_attribs(attr);

   if (!eglGetConfigAttrib(g_egl_dpy, g_egl_config, EGL_NATIVE_VISUAL_ID, &vid))
      goto error;

   temp.visualid = vid;

   vi = XGetVisualInfo(g_x11_dpy, VisualIDMask, &temp, &num_visuals);
   if (!vi)
      goto error;

   swa.colormap = g_x11_cmap = XCreateColormap(g_x11_dpy, RootWindow(g_x11_dpy, vi->screen),
         vi->visual, AllocNone);
   swa.event_mask = StructureNotifyMask | KeyPressMask | ButtonPressMask | ButtonReleaseMask | KeyReleaseMask;
   swa.override_redirect = fullscreen ? True : False;

   if (fullscreen && !windowed_full)
   {
      if (x11_enter_fullscreen(g_x11_dpy, width, height, &g_desktop_mode))
      {
         g_should_reset_mode = true;
         true_full = true;
      }
      else
         RARCH_ERR("[X/EGL]: Entering true fullscreen failed. Will attempt windowed mode.\n");
   }

   if (settings->video.monitor_index)
      g_screen = settings->video.monitor_index - 1;

#ifdef HAVE_XINERAMA
   if (fullscreen || g_screen != 0)
   {
      unsigned new_width  = width;
      unsigned new_height = height;

      if (x11_get_xinerama_coord(g_x11_dpy, g_screen, &x_off, &y_off, &new_width, &new_height))
         RARCH_LOG("[X/EGL]: Using Xinerama on screen #%u.\n", g_screen);
      else
         RARCH_LOG("[X/EGL]: Xinerama is not active on screen.\n");

      if (fullscreen)
      {
         width  = new_width;
         height = new_height;
      }
   }
#endif

   RARCH_LOG("[X/EGL]: X = %d, Y = %d, W = %u, H = %u.\n",
         x_off, y_off, width, height);

   g_x11_win = XCreateWindow(g_x11_dpy, RootWindow(g_x11_dpy, vi->screen),
         x_off, y_off, width, height, 0,
         vi->depth, InputOutput, vi->visual, 
         CWBorderPixel | CWColormap | CWEventMask | (true_full ? CWOverrideRedirect : 0), &swa);
   XSetWindowBackground(g_x11_dpy, g_x11_win, 0);

   if (!egl_create_context((attr != egl_attribs) ? egl_attribs : NULL))
   {
      egl_report_error();
      goto error;
   }

   if (!egl_create_surface((EGLNativeWindowType)g_x11_win))
      goto error;

   x11_set_window_attr(g_x11_dpy, g_x11_win);

   if (fullscreen)
      x11_show_mouse(g_x11_dpy, g_x11_win, false);

   if (true_full)
   {
      RARCH_LOG("[X/EGL]: Using true fullscreen.\n");
      XMapRaised(g_x11_dpy, g_x11_win);
   }
   else if (fullscreen) 
   {
      /* We attempted true fullscreen, but failed.
       * Attempt using windowed fullscreen. */
      XMapRaised(g_x11_dpy, g_x11_win);
      RARCH_LOG("[X/EGL]: Using windowed fullscreen.\n");

      /* We have to move the window to the screen we 
       * want to go fullscreen on first.
       * x_off and y_off usually get ignored in XCreateWindow().
       */
      x11_move_window(g_x11_dpy, g_x11_win, x_off, y_off, width, height);
      x11_windowed_fullscreen(g_x11_dpy, g_x11_win);
   }
   else
   {
      XMapWindow(g_x11_dpy, g_x11_win);

      /* If we want to map the window on a different screen, 
       * we'll have to do it by force.
       *
       * Otherwise, we should try to let the window manager sort it out.
       * x_off and y_off usually get ignored in XCreateWindow().
       */
      if (g_screen)
         x11_move_window(g_x11_dpy, g_x11_win, x_off, y_off, width, height);
   }

   x11_event_queue_check(&event);
   x11_install_quit_atom();

   egl_set_swap_interval(data, g_interval);

   /* This can blow up on some drivers. It's not fatal, 
    * so override errors for this call.
    */
   old_handler = XSetErrorHandler(egl_nul_handler);
   XSetInputFocus(g_x11_dpy, g_x11_win, RevertToNone, CurrentTime);
   XSync(g_x11_dpy, False);
   XSetErrorHandler(old_handler);

   XFree(vi);
   g_egl_inited    = true;

   if (!x11_input_ctx_new(true_full))
      goto error;

   return true;

error:
   if (vi)
      XFree(vi);

   gfx_ctx_xegl_destroy(data);
   return false;
}
示例#7
0
文件: XEVI.c 项目: narenas/nx-libs
Status XeviGetVisualInfo(
    register Display *dpy,
    VisualID *visual,
    int n_visual,
    ExtendedVisualInfo **evi_return,
    int *n_info_return)
{
    XExtDisplayInfo *info = find_display (dpy);
    register xEVIGetVisualInfoReq *req;
    xEVIGetVisualInfoReply rep;
    int sz_info, sz_xInfo, sz_conflict, sz_xConflict;
    VisualID32 *temp_conflict, *temp_visual, *xConflictPtr;
    VisualID *conflict;
    xExtendedVisualInfo *temp_xInfo;
    XVisualInfo *vinfo;
    register ExtendedVisualInfo *infoPtr;
    register xExtendedVisualInfo *xInfoPtr;
    register int n_data, visualIndex, vinfoIndex;
    Bool isValid;
    XeviCheckExtension (dpy, info, 0);
    *n_info_return = 0;
    *evi_return = NULL;
    vinfo = XGetVisualInfo(dpy, 0, NULL, &sz_info);
    if (!vinfo) {
        return BadValue;
    }
    if (!n_visual || !visual) {		/* copy the all visual */
        temp_visual = (VisualID32 *)Xmalloc(sz_VisualID32 * sz_info);
        n_visual = 0;
        for (vinfoIndex = 0; vinfoIndex < sz_info; vinfoIndex++)
            if (notInList(temp_visual, n_visual, vinfo[vinfoIndex].visualid))
                temp_visual[n_visual++] = vinfo[vinfoIndex].visualid;
    }
    else {	/* check if the visual is valid */
        for (visualIndex = 0; visualIndex < n_visual; visualIndex++) {
            isValid = False;
            for (vinfoIndex = 0; vinfoIndex < sz_info; vinfoIndex++) {
                if (visual[visualIndex] == vinfo[vinfoIndex].visualid) {
                    isValid = True;
                    break;
                }
            }
            if (!isValid) {
                XFree(vinfo);
                return BadValue;
            }
        }
        temp_visual = (VisualID32 *)Xmalloc(sz_VisualID32 * n_visual);
        for (visualIndex = 0; visualIndex < n_visual; visualIndex++)
            temp_visual[visualIndex] = visual[visualIndex];
    }
    XFree(vinfo);
    LockDisplay(dpy);
    GetReq(EVIGetVisualInfo, req);
    req->reqType = info->codes->major_opcode;
    req->xeviReqType = X_EVIGetVisualInfo;
    req->n_visual = n_visual;
    SetReqLen(req, n_visual, 1);
    Data(dpy, (char *)temp_visual, n_visual * sz_VisualID32);
    if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
        UnlockDisplay(dpy);
        SyncHandle();
        Xfree(temp_visual);
        return BadAccess;
    }
    Xfree(temp_visual);
    sz_info = rep.n_info * sizeof(ExtendedVisualInfo);
    sz_xInfo = rep.n_info * sz_xExtendedVisualInfo;
    sz_conflict = rep.n_conflicts * sizeof(VisualID);
    sz_xConflict = rep.n_conflicts * sz_VisualID32;
    infoPtr = *evi_return = (ExtendedVisualInfo *)Xmalloc(sz_info + sz_conflict);
    xInfoPtr = temp_xInfo = (xExtendedVisualInfo *)Xmalloc(sz_xInfo);
    xConflictPtr = temp_conflict = (VisualID32 *)Xmalloc(sz_xConflict);
    if (!*evi_return || !temp_xInfo || !temp_conflict) {
        _XEatData(dpy, (sz_xInfo + sz_xConflict + 3) & ~3);
        UnlockDisplay(dpy);
        SyncHandle();
        if (evi_return)
            Xfree(evi_return);
        if (temp_xInfo)
            Xfree(temp_xInfo);
        if (temp_conflict)
            Xfree(temp_conflict);
        return BadAlloc;
    }
    _XRead(dpy, (char *)temp_xInfo, sz_xInfo);
    _XRead(dpy, (char *)temp_conflict, sz_xConflict);
    UnlockDisplay(dpy);
    SyncHandle();
    n_data = rep.n_info;
    conflict = (VisualID *)(infoPtr + n_data);
    while (n_data-- > 0) {
        infoPtr->core_visual_id		= xInfoPtr->core_visual_id;
        infoPtr->screen			= xInfoPtr->screen;
        infoPtr->level			= xInfoPtr->level;
        infoPtr->transparency_type	= xInfoPtr->transparency_type;
        infoPtr->transparency_value	= xInfoPtr->transparency_value;
        infoPtr->min_hw_colormaps	= xInfoPtr->min_hw_colormaps;
        infoPtr->max_hw_colormaps	= xInfoPtr->max_hw_colormaps;
        infoPtr->num_colormap_conflicts = xInfoPtr->num_colormap_conflicts;
        infoPtr->colormap_conflicts	= conflict;
        conflict += infoPtr->num_colormap_conflicts;
        infoPtr++;
        xInfoPtr++;
    }
    n_data = rep.n_conflicts;
    conflict = (VisualID *)(infoPtr);
    while (n_data-- > 0)
        *conflict++ = *xConflictPtr++;
    Xfree(temp_xInfo);
    Xfree(temp_conflict);
    *n_info_return = rep.n_info;
    return Success;
}
示例#8
0
static bool gfx_ctx_x_set_video_mode(void *data,
      unsigned width, unsigned height,
      bool fullscreen)
{
   XEvent event;
   bool true_full = false, windowed_full;
   int val, x_off = 0, y_off = 0;
   XVisualInfo *vi = NULL;
   XSetWindowAttributes swa = {0};
   int (*old_handler)(Display*, XErrorEvent*) = NULL;
   settings_t *settings    = config_get_ptr();
   gfx_ctx_x_data_t *x = (gfx_ctx_x_data_t*)data;

   x11_install_sighandlers();

   if (!x)
      return false;

   windowed_full = settings->video.windowed_fullscreen;
   true_full = false;

   switch (x_api)
   {
      case GFX_CTX_OPENGL_API:
      case GFX_CTX_OPENGL_ES_API:
#ifdef HAVE_OPENGL
         vi = glXGetVisualFromFBConfig(g_x11_dpy, x->g_fbc);
         if (!vi)
            goto error;
#endif
         break;

      case GFX_CTX_NONE:
      default:
      {
         XVisualInfo vi_template;
         /* For default case, just try to obtain a visual from template. */
         int nvisuals = 0;

         memset(&vi_template, 0, sizeof(vi_template));
         vi_template.screen = DefaultScreen(g_x11_dpy);
         vi = XGetVisualInfo(g_x11_dpy, VisualScreenMask, &vi_template, &nvisuals);
         if (!vi || nvisuals < 1)
            goto error;
      }
      break;
   }

   swa.colormap = g_x11_cmap = XCreateColormap(g_x11_dpy,
         RootWindow(g_x11_dpy, vi->screen), vi->visual, AllocNone);
   swa.event_mask = StructureNotifyMask | KeyPressMask | KeyReleaseMask |
      ButtonReleaseMask | ButtonPressMask;
   swa.override_redirect = fullscreen ? True : False;

   if (fullscreen && !windowed_full)
   {
      if (x11_enter_fullscreen(g_x11_dpy, width, height, &x->g_desktop_mode))
      {
         x->g_should_reset_mode = true;
         true_full = true;
      }
      else
         RARCH_ERR("[GLX]: Entering true fullscreen failed. Will attempt windowed mode.\n");
   }

   if (settings->video.monitor_index)
      g_x11_screen = settings->video.monitor_index - 1;

#ifdef HAVE_XINERAMA
   if (fullscreen || g_x11_screen != 0)
   {
      unsigned new_width  = width;
      unsigned new_height = height;

      if (x11_get_xinerama_coord(g_x11_dpy, g_x11_screen,
               &x_off, &y_off, &new_width, &new_height))
         RARCH_LOG("[GLX]: Using Xinerama on screen #%u.\n", g_x11_screen);
      else
         RARCH_LOG("[GLX]: Xinerama is not active on screen.\n");

      if (fullscreen)
      {
         width  = new_width;
         height = new_height;
      }
   }
#endif

   RARCH_LOG("[GLX]: X = %d, Y = %d, W = %u, H = %u.\n",
         x_off, y_off, width, height);

   g_x11_win = XCreateWindow(g_x11_dpy, RootWindow(g_x11_dpy, vi->screen),
         x_off, y_off, width, height, 0,
         vi->depth, InputOutput, vi->visual, 
         CWBorderPixel | CWColormap | CWEventMask | 
         (true_full ? CWOverrideRedirect : 0), &swa);
   XSetWindowBackground(g_x11_dpy, g_x11_win, 0);

   switch (x_api)
   {
      case GFX_CTX_OPENGL_API:
      case GFX_CTX_OPENGL_ES_API:
#ifdef HAVE_OPENGL
         x->g_glx_win = glXCreateWindow(g_x11_dpy, x->g_fbc, g_x11_win, 0);
#endif
         break;

      case GFX_CTX_NONE:
      default:
         break;
   }

   x11_set_window_attr(g_x11_dpy, g_x11_win);
   x11_update_window_title(NULL);

   if (fullscreen)
      x11_show_mouse(g_x11_dpy, g_x11_win, false);

   if (true_full)
   {
      RARCH_LOG("[GLX]: Using true fullscreen.\n");
      XMapRaised(g_x11_dpy, g_x11_win);
   }
   else if (fullscreen)
   {
      /* We attempted true fullscreen, but failed. 
       * Attempt using windowed fullscreen. */

      XMapRaised(g_x11_dpy, g_x11_win);
      RARCH_LOG("[GLX]: Using windowed fullscreen.\n");

      /* We have to move the window to the screen we want 
       * to go fullscreen on first.
       * x_off and y_off usually get ignored in XCreateWindow().
       */
      x11_move_window(g_x11_dpy, g_x11_win, x_off, y_off, width, height);
      x11_windowed_fullscreen(g_x11_dpy, g_x11_win);
   }
   else
   {
      XMapWindow(g_x11_dpy, g_x11_win);
      /* If we want to map the window on a different screen, 
       * we'll have to do it by force.
       * Otherwise, we should try to let the window manager sort it out.
       * x_off and y_off usually get ignored in XCreateWindow(). */
      if (g_x11_screen)
         x11_move_window(g_x11_dpy, g_x11_win, x_off, y_off, width, height);
   }

   x11_event_queue_check(&event);

   switch (x_api)
   {
      case GFX_CTX_OPENGL_API:
      case GFX_CTX_OPENGL_ES_API:
#ifdef HAVE_OPENGL
         if (!x->g_ctx)
         {
            if (x->g_core_es || x->g_debug)
            {
               int attribs[16];
               int *aptr = attribs;

               if (x->g_core_es)
               {
                  *aptr++ = GLX_CONTEXT_MAJOR_VERSION_ARB;
                  *aptr++ = g_major;
                  *aptr++ = GLX_CONTEXT_MINOR_VERSION_ARB;
                  *aptr++ = g_minor;

                  if (x->g_core_es_core)
                  {
                     /* Technically, we don't have core/compat until 3.2.
                      * Version 3.1 is either compat or not depending on 
                      * GL_ARB_compatibility.
                      */
                     *aptr++ = GLX_CONTEXT_PROFILE_MASK_ARB;
#ifdef HAVE_OPENGLES2
                     *aptr++ = GLX_CONTEXT_ES_PROFILE_BIT_EXT;
#else
                     *aptr++ = GLX_CONTEXT_CORE_PROFILE_BIT_ARB;
#endif
                  }
               }

               if (x->g_debug)
               {
                  *aptr++ = GLX_CONTEXT_FLAGS_ARB;
                  *aptr++ = GLX_CONTEXT_DEBUG_BIT_ARB;
               }

               *aptr = None;
               x->g_ctx = glx_create_context_attribs(g_x11_dpy,
                     x->g_fbc, NULL, True, attribs);

               if (x->g_use_hw_ctx)
               {
                  RARCH_LOG("[GLX]: Creating shared HW context.\n");
                  x->g_hw_ctx = glx_create_context_attribs(g_x11_dpy,
                        x->g_fbc, x->g_ctx, True, attribs);

                  if (!x->g_hw_ctx)
                     RARCH_ERR("[GLX]: Failed to create new shared context.\n");
               }
            }
            else
            {
               x->g_ctx = glXCreateNewContext(g_x11_dpy, x->g_fbc,
                     GLX_RGBA_TYPE, 0, True);
               if (x->g_use_hw_ctx)
               {
                  x->g_hw_ctx = glXCreateNewContext(g_x11_dpy, x->g_fbc,
                        GLX_RGBA_TYPE, x->g_ctx, True);
                  if (!x->g_hw_ctx)
                     RARCH_ERR("[GLX]: Failed to create new shared context.\n");
               }
            }

            if (!x->g_ctx)
            {
               RARCH_ERR("[GLX]: Failed to create new context.\n");
               goto error;
            }
         }
         else
         {
            video_driver_ctl(RARCH_DISPLAY_CTL_SET_VIDEO_CACHE_CONTEXT_ACK, NULL);
            RARCH_LOG("[GLX]: Using cached GL context.\n");
         }

         glXMakeContextCurrent(g_x11_dpy,
               x->g_glx_win, x->g_glx_win, x->g_ctx);
#endif
         break;

      case GFX_CTX_VULKAN_API:
#ifdef HAVE_VULKAN
         {
            bool quit, resize;
            unsigned width, height;
            x11_check_window(x, &quit, &resize, &width, &height, 0);

            /* Use XCB surface since it's the most supported WSI.
             * We can obtain the XCB connection directly from X11. */
            if (!vulkan_surface_create(&x->vk, VULKAN_WSI_XCB,
                     g_x11_dpy, &g_x11_win, 
                     width, height, x->g_interval))
               goto error;
         }
#endif
         break;

      case GFX_CTX_NONE:
      default:
         break;
   }

   XSync(g_x11_dpy, False);

   x11_install_quit_atom();

   switch (x_api)
   {
      case GFX_CTX_OPENGL_API:
      case GFX_CTX_OPENGL_ES_API:
#ifdef HAVE_OPENGL
         glXGetConfig(g_x11_dpy, vi, GLX_DOUBLEBUFFER, &val);
         x->g_is_double = val;

         if (x->g_is_double)
         {
            const char *swap_func = NULL;

            g_pglSwapIntervalEXT = (void (*)(Display*, GLXDrawable, int))
               glXGetProcAddress((const GLubyte*)"glXSwapIntervalEXT");
            g_pglSwapIntervalSGI = (int (*)(int))
               glXGetProcAddress((const GLubyte*)"glXSwapIntervalSGI");
            g_pglSwapInterval    = (int (*)(int))
               glXGetProcAddress((const GLubyte*)"glXSwapIntervalMESA");

            if (g_pglSwapIntervalEXT)
               swap_func = "glXSwapIntervalEXT";
            else if (g_pglSwapInterval)
               swap_func = "glXSwapIntervalMESA";
            else if (g_pglSwapIntervalSGI)
               swap_func = "glXSwapIntervalSGI";

            if (!g_pglSwapInterval && !g_pglSwapIntervalEXT && !g_pglSwapIntervalSGI)
               RARCH_WARN("[GLX]: Cannot find swap interval call.\n");
            else
               RARCH_LOG("[GLX]: Found swap function: %s.\n", swap_func);
         }
         else
            RARCH_WARN("[GLX]: Context is not double buffered!.\n");
#endif
         break;

      case GFX_CTX_NONE:
      default:
         break;
   }

   gfx_ctx_x_swap_interval(data, x->g_interval);

   /* This can blow up on some drivers. 
    * It's not fatal, so override errors for this call. */
   old_handler = XSetErrorHandler(x_nul_handler);
   XSetInputFocus(g_x11_dpy, g_x11_win, RevertToNone, CurrentTime);
   XSync(g_x11_dpy, False);
   XSetErrorHandler(old_handler);

   XFree(vi);
   vi = NULL;

   if (!x11_input_ctx_new(true_full))
      goto error;

   return true;

error:
   if (vi)
      XFree(vi);

   gfx_ctx_x_destroy_resources(x);

   if (x)
      free(x);
   g_x11_screen = 0;

   return false;
}
示例#9
0
Status
XmuLookupStandardColormap(Display *dpy, int screen, VisualID visualid,
			  unsigned int depth, Atom property,
			  Bool replace, Bool retain)
     /*
      * dpy		- specifies X server connection
      * screen 		- specifies screen of display
      * visualid	- specifies the visual type
      * depth		- specifies  the visual type
      * property	- a standard colormap property
      * replace		- specifies whether to replace
      * retain		- specifies whether to retain
      */
{
    Display		*odpy;		/* original display connection */
    XStandardColormap	*colormap;
    XVisualInfo		vinfo_template, *vinfo;	/* visual */
    long		vinfo_mask;
    unsigned long	r_max, g_max, b_max;	/* allocation */
    int			count;
    Colormap		cmap;			/* colormap ID */
    Status		status = 0;


    /* Match the requested visual */

    vinfo_template.visualid = visualid;
    vinfo_template.screen = screen;
    vinfo_template.depth = depth;
    vinfo_mask = VisualIDMask | VisualScreenMask | VisualDepthMask;
    if ((vinfo = XGetVisualInfo(dpy, vinfo_mask, &vinfo_template, &count)) ==
	NULL)
	return 0;

    /* Monochrome visuals have no standard maps */

    if (vinfo->colormap_size <= 2) {
	XFree((char *) vinfo);
	return 0;
    }

    /* If the requested property already exists on this screen, and,
     * if the replace flag has not been set to true, return success.
     * lookup() will remove a pre-existing map if replace is true.
     */

    if (lookup(dpy, screen, visualid, property, (XStandardColormap *) NULL,
	       replace) && !replace) {
	XFree((char *) vinfo);
	return 1;
    }

    /* Determine the best allocation for this property under the requested
     * visualid and depth, and determine whether or not to use the default
     * colormap of the screen.
     */

    if (!XmuGetColormapAllocation(vinfo, property, &r_max, &g_max, &b_max)) {
	XFree((char *) vinfo);
	return 0;
    }

    cmap = (property == XA_RGB_DEFAULT_MAP &&
	    visualid == XVisualIDFromVisual(DefaultVisual(dpy, screen)))
	? DefaultColormap(dpy, screen) : None;

    /* If retaining resources, open a new connection to the same server */

    if (retain) {
	odpy = dpy;
	if ((dpy = XOpenDisplay(XDisplayString(odpy))) == NULL) {
	    XFree((char *) vinfo);
	    return 0;
	}
    }

    /* Create the standard colormap */

    colormap = XmuStandardColormap(dpy, screen, visualid, depth, property,
				   cmap, r_max, g_max, b_max);

    /* Set the standard colormap property */

    if (colormap) {
	XGrabServer(dpy);

	if (lookup(dpy, screen, visualid, property, colormap, replace) &&
	    !replace) {
	    /* Someone has defined the property since we last looked.
	     * Since we will not replace it, release our own resources.
	     * If this is the default map, our allocations will be freed
	     * when this connection closes.
	     */
	    if (colormap->killid == ReleaseByFreeingColormap)
		XFreeColormap(dpy, colormap->colormap);
	}
	else if (retain) {
		XSetCloseDownMode(dpy, RetainPermanent);
	}
	XUngrabServer(dpy);
	XFree((char *) colormap);
	status = 1;
    }

    if (retain)
	XCloseDisplay(dpy);
    XFree((char *) vinfo);
    return status;
}
VisualID QXlibEglIntegration::getCompatibleVisualId(Display *display, EGLDisplay eglDisplay, EGLConfig config)
{
    VisualID    visualId = 0;
    EGLint      eglValue = 0;

    EGLint configRedSize = 0;
    eglGetConfigAttrib(eglDisplay, config, EGL_RED_SIZE, &configRedSize);

    EGLint configGreenSize = 0;
    eglGetConfigAttrib(eglDisplay, config, EGL_GREEN_SIZE, &configGreenSize);

    EGLint configBlueSize = 0;
    eglGetConfigAttrib(eglDisplay, config, EGL_BLUE_SIZE, &configBlueSize);

    EGLint configAlphaSize = 0;
    eglGetConfigAttrib(eglDisplay, config, EGL_ALPHA_SIZE, &configAlphaSize);

    eglGetConfigAttrib(eglDisplay, config, EGL_CONFIG_ID, &eglValue);
    int configId = eglValue;

    // See if EGL provided a valid VisualID:
    eglGetConfigAttrib(eglDisplay, config, EGL_NATIVE_VISUAL_ID, &eglValue);
    visualId = (VisualID)eglValue;
    if (visualId) {
        // EGL has suggested a visual id, so get the rest of the visual info for that id:
        XVisualInfo visualInfoTemplate;
        memset(&visualInfoTemplate, 0, sizeof(XVisualInfo));
        visualInfoTemplate.visualid = visualId;

        XVisualInfo *chosenVisualInfo;
        int matchingCount = 0;
        chosenVisualInfo = XGetVisualInfo(display, VisualIDMask, &visualInfoTemplate, &matchingCount);
        if (chosenVisualInfo) {
            // Skip size checks if implementation supports non-matching visual
            // and config (QTBUG-9444).
            if (q_hasEglExtension(eglDisplay,"EGL_NV_post_convert_rounding")) {
                XFree(chosenVisualInfo);
                return visualId;
            }

            int visualRedSize = qPopulationCount(chosenVisualInfo->red_mask);
            int visualGreenSize = qPopulationCount(chosenVisualInfo->green_mask);
            int visualBlueSize = qPopulationCount(chosenVisualInfo->blue_mask);
            int visualAlphaSize = chosenVisualInfo->depth == 32 ? 8 : 0;

            const bool visualMatchesConfig = visualRedSize == configRedSize
                && visualGreenSize == configGreenSize
                && visualBlueSize == configBlueSize
                && visualAlphaSize == configAlphaSize;

            // In some cases EGL tends to suggest a 24-bit visual for 8888
            // configs. In such a case we have to fall back to XGetVisualInfo.
            if (!visualMatchesConfig) {
                visualId = 0;
#ifdef QT_DEBUG_X11_VISUAL_SELECTION
                qWarning("Warning: EGL suggested using X Visual ID %d (%d %d %d depth %d) for EGL config %d (%d %d %d %d), but this is incompatible",
                         (int)visualId, visualRedSize, visualGreenSize, visualBlueSize, chosenVisualInfo->depth,
                         configId, configRedSize, configGreenSize, configBlueSize, configAlphaSize);
#endif
            }
        } else {
            qWarning("Warning: EGL suggested using X Visual ID %d for EGL config %d, but that isn't a valid ID",
                     (int)visualId, configId);
            visualId = 0;
        }
        XFree(chosenVisualInfo);
    }
#ifdef QT_DEBUG_X11_VISUAL_SELECTION
    else
        qDebug("EGL did not suggest a VisualID (EGL_NATIVE_VISUAL_ID was zero) for EGLConfig %d", configId);
#endif

    if (visualId) {
#ifdef QT_DEBUG_X11_VISUAL_SELECTION
        if (configAlphaSize > 0)
            qDebug("Using ARGB Visual ID %d provided by EGL for config %d", (int)visualId, configId);
        else
            qDebug("Using Opaque Visual ID %d provided by EGL for config %d", (int)visualId, configId);
#endif
        return visualId;
    }

    // Finally, try to use XGetVisualInfo and only use the bit depths to match on:
    if (!visualId) {
        XVisualInfo visualInfoTemplate;
        memset(&visualInfoTemplate, 0, sizeof(XVisualInfo));
        XVisualInfo *matchingVisuals;
        int matchingCount = 0;

        visualInfoTemplate.depth = configRedSize + configGreenSize + configBlueSize + configAlphaSize;
        matchingVisuals = XGetVisualInfo(display,
                                         VisualDepthMask,
                                         &visualInfoTemplate,
                                         &matchingCount);
        if (!matchingVisuals) {
            // Try again without taking the alpha channel into account:
            visualInfoTemplate.depth = configRedSize + configGreenSize + configBlueSize;
            matchingVisuals = XGetVisualInfo(display,
                                             VisualDepthMask,
                                             &visualInfoTemplate,
                                             &matchingCount);
        }

        if (matchingVisuals) {
            visualId = matchingVisuals[0].visualid;
            XFree(matchingVisuals);
        }
    }

    if (visualId) {
#ifdef QT_DEBUG_X11_VISUAL_SELECTION
        qDebug("Using Visual ID %d provided by XGetVisualInfo for EGL config %d", (int)visualId, configId);
#endif
        return visualId;
    }

    qWarning("Unable to find an X11 visual which matches EGL config %d", configId);
    return (VisualID)0;
}
示例#11
0
QXcbWindow::QXcbWindow(QWidget *tlw)
    : QPlatformWindow(tlw)
    , m_context(0)
{
    m_screen = static_cast<QXcbScreen *>(QPlatformScreen::platformScreenForWidget(tlw));

    setConnection(m_screen->connection());

    const quint32 mask = XCB_CW_BACK_PIXMAP | XCB_CW_EVENT_MASK;
    const quint32 values[] = {
        // XCB_CW_BACK_PIXMAP
        XCB_NONE,
        // XCB_CW_EVENT_MASK
        XCB_EVENT_MASK_EXPOSURE
        | XCB_EVENT_MASK_STRUCTURE_NOTIFY
        | XCB_EVENT_MASK_KEY_PRESS
        | XCB_EVENT_MASK_KEY_RELEASE
        | XCB_EVENT_MASK_BUTTON_PRESS
        | XCB_EVENT_MASK_BUTTON_RELEASE
        | XCB_EVENT_MASK_BUTTON_MOTION
        | XCB_EVENT_MASK_ENTER_WINDOW
        | XCB_EVENT_MASK_LEAVE_WINDOW
        | XCB_EVENT_MASK_PROPERTY_CHANGE
        | XCB_EVENT_MASK_FOCUS_CHANGE
    };

#if defined(XCB_USE_GLX) || defined(XCB_USE_EGL)
    if (tlw->platformWindowFormat().windowApi() == QPlatformWindowFormat::OpenGL
            && QApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::OpenGL)
            || tlw->platformWindowFormat().alpha())
    {
#if defined(XCB_USE_GLX)
        XVisualInfo *visualInfo = qglx_findVisualInfo(DISPLAY_FROM_XCB(m_screen),m_screen->screenNumber(), tlw->platformWindowFormat());
#elif defined(XCB_USE_EGL)
        EGLDisplay eglDisplay = connection()->egl_display();
        EGLConfig eglConfig = q_configFromQPlatformWindowFormat(eglDisplay,tlw->platformWindowFormat(),true);
        VisualID id = QXlibEglIntegration::getCompatibleVisualId(DISPLAY_FROM_XCB(this), eglDisplay, eglConfig);

        XVisualInfo visualInfoTemplate;
        memset(&visualInfoTemplate, 0, sizeof(XVisualInfo));
        visualInfoTemplate.visualid = id;

        XVisualInfo *visualInfo;
        int matchingCount = 0;
        visualInfo = XGetVisualInfo(DISPLAY_FROM_XCB(this), VisualIDMask, &visualInfoTemplate, &matchingCount);
#endif //XCB_USE_GLX
        if (visualInfo) {
            m_depth = visualInfo->depth;
            m_format = (m_depth == 32) ? QImage::Format_ARGB32_Premultiplied : QImage::Format_RGB32;
            Colormap cmap = XCreateColormap(DISPLAY_FROM_XCB(this), m_screen->root(), visualInfo->visual, AllocNone);

            XSetWindowAttributes a;
            a.background_pixel = WhitePixel(DISPLAY_FROM_XCB(this), m_screen->screenNumber());
            a.border_pixel = BlackPixel(DISPLAY_FROM_XCB(this), m_screen->screenNumber());
            a.colormap = cmap;
            m_window = XCreateWindow(DISPLAY_FROM_XCB(this), m_screen->root(), tlw->x(), tlw->y(), tlw->width(), tlw->height(),
                                     0, visualInfo->depth, InputOutput, visualInfo->visual,
                                     CWBackPixel|CWBorderPixel|CWColormap, &a);

            printf("created GL window: %d\n", m_window);
        } else {
            qFatal("no window!");
        }
    } else
#endif //defined(XCB_USE_GLX) || defined(XCB_USE_EGL)
    {
        m_window = xcb_generate_id(xcb_connection());
        m_depth = m_screen->screen()->root_depth;
        m_format = (m_depth == 32) ? QImage::Format_ARGB32_Premultiplied : QImage::Format_RGB32;

        Q_XCB_CALL(xcb_create_window(xcb_connection(),
                                     XCB_COPY_FROM_PARENT,            // depth -- same as root
                                     m_window,                        // window id
                                     m_screen->root(),                // parent window id
                                     tlw->x(),
                                     tlw->y(),
                                     tlw->width(),
                                     tlw->height(),
                                     0,                               // border width
                                     XCB_WINDOW_CLASS_INPUT_OUTPUT,   // window class
                                     m_screen->screen()->root_visual, // visual
                                     0,                               // value mask
                                     0));                             // value list

        printf("created regular window: %d\n", m_window);
    }

    Q_XCB_CALL(xcb_change_window_attributes(xcb_connection(), m_window, mask, values));

    xcb_atom_t properties[4];
    int propertyCount = 0;
    properties[propertyCount++] = atom(QXcbAtom::WM_DELETE_WINDOW);
    properties[propertyCount++] = atom(QXcbAtom::WM_TAKE_FOCUS);
    properties[propertyCount++] = atom(QXcbAtom::_NET_WM_PING);

    if (m_screen->syncRequestSupported())
        properties[propertyCount++] = atom(QXcbAtom::_NET_WM_SYNC_REQUEST);

    if (tlw->windowFlags() & Qt::WindowContextHelpButtonHint)
        properties[propertyCount++] = atom(QXcbAtom::_NET_WM_CONTEXT_HELP);

    Q_XCB_CALL(xcb_change_property(xcb_connection(),
                                   XCB_PROP_MODE_REPLACE,
                                   m_window,
                                   atom(QXcbAtom::WM_PROTOCOLS),
                                   XCB_ATOM_ATOM,
                                   32,
                                   propertyCount,
                                   properties));
    m_syncValue.hi = 0;
    m_syncValue.lo = 0;

    if (m_screen->syncRequestSupported()) {
        m_syncCounter = xcb_generate_id(xcb_connection());
        Q_XCB_CALL(xcb_sync_create_counter(xcb_connection(), m_syncCounter, m_syncValue));

        Q_XCB_CALL(xcb_change_property(xcb_connection(),
                                       XCB_PROP_MODE_REPLACE,
                                       m_window,
                                       atom(QXcbAtom::_NET_WM_SYNC_REQUEST_COUNTER),
                                       XCB_ATOM_CARDINAL,
                                       32,
                                       1,
                                       &m_syncCounter));
    }

    if (isTransient(tlw) && tlw->parentWidget()) {
        // ICCCM 4.1.2.6
        QWidget *p = tlw->parentWidget()->window();
        xcb_window_t parentWindow = p->winId();
        Q_XCB_CALL(xcb_change_property(xcb_connection(), XCB_PROP_MODE_REPLACE, m_window,
                                       XCB_ATOM_WM_TRANSIENT_FOR, XCB_ATOM_WINDOW, 32,
                                       1, &parentWindow));

    }

    // set the PID to let the WM kill the application if unresponsive
    long pid = getpid();
    Q_XCB_CALL(xcb_change_property(xcb_connection(), XCB_PROP_MODE_REPLACE, m_window,
                                   atom(QXcbAtom::_NET_WM_PID), XCB_ATOM_CARDINAL, 32,
                                   1, &pid));
}
示例#12
0
bool QGLContext::chooseContext( const QGLContext* shareContext )
{
    Display* disp = paintDevice->x11Display();
    vi = chooseVisual();
    if ( !vi )
	return FALSE;

    if ( deviceIsPixmap() && 
	 ((XVisualInfo*)vi)->depth != paintDevice->x11Depth() ) {
	XFree( vi );
	XVisualInfo appVisInfo;
	memset( &appVisInfo, 0, sizeof(XVisualInfo) );
	appVisInfo.visualid = XVisualIDFromVisual( (Visual*)paintDevice->x11Visual() );
	int nvis;
	vi = XGetVisualInfo( disp, VisualIDMask, &appVisInfo, &nvis );
	if ( !vi )
	    return FALSE;
	
	int useGL;
	glXGetConfig( disp, (XVisualInfo*)vi, GLX_USE_GL, &useGL );
	if ( !useGL )
	    return FALSE;	//# Chickening out already...
    }
    int res;
    glXGetConfig( disp, (XVisualInfo*)vi, GLX_LEVEL, &res );
    glFormat.setPlane( res );
    glXGetConfig( disp, (XVisualInfo*)vi, GLX_DOUBLEBUFFER, &res );
    glFormat.setDoubleBuffer( res );
    glXGetConfig( disp, (XVisualInfo*)vi, GLX_DEPTH_SIZE, &res );
    glFormat.setDepth( res );
    glXGetConfig( disp, (XVisualInfo*)vi, GLX_RGBA, &res );
    glFormat.setRgba( res );
    glXGetConfig( disp, (XVisualInfo*)vi, GLX_ALPHA_SIZE, &res );
    glFormat.setAlpha( res );
    glXGetConfig( disp, (XVisualInfo*)vi, GLX_ACCUM_RED_SIZE, &res );
    glFormat.setAccum( res );
    glXGetConfig( disp, (XVisualInfo*)vi, GLX_STENCIL_SIZE, &res );
    glFormat.setStencil( res );
    glXGetConfig( disp, (XVisualInfo*)vi, GLX_STEREO, &res );
    glFormat.setStereo( res );

    Bool direct = format().directRendering() ? True : False;
    
    if ( shareContext && 
	 ( !shareContext->isValid() || !shareContext->cx ) ) {
#if defined(CHECK_NULL)
	    qWarning("QGLContext::chooseContext(): Cannot share with invalid context");
#endif
	    shareContext = 0;
    }

    // sharing between rgba and color-index will give wrong colors
    if ( shareContext && ( format().rgba() != shareContext->format().rgba() ) )
	shareContext = 0;

    cx = 0;
    if ( shareContext ) {
	cx = glXCreateContext( disp, (XVisualInfo *)vi,
			       (GLXContext)shareContext->cx, direct );
	if ( cx )
	    sharing = TRUE;
    }
    if ( !cx )
	cx = glXCreateContext( disp, (XVisualInfo *)vi, None, direct );
    if ( !cx )
	return FALSE;
    glFormat.setDirectRendering( glXIsDirect( disp, (GLXContext)cx ) );
    if ( deviceIsPixmap() ) {
#if defined(GLX_MESA_pixmap_colormap) && defined(QGL_USE_MESA_EXT)
	gpm = glXCreateGLXPixmapMESA( disp, (XVisualInfo *)vi,
				      paintDevice->handle(),
				      choose_cmap( disp, (XVisualInfo *)vi ) );
#else
	gpm = (Q_UINT32)glXCreateGLXPixmap( disp, (XVisualInfo *)vi,
					    paintDevice->handle() );
#endif
	if ( !gpm )
	    return FALSE;
    }
    return TRUE;
}
示例#13
0
文件: GlxContext.cpp 项目: CPB9/SFML
void GlxContext::createContext(GlxContext* shared, unsigned int bitsPerPixel, const ContextSettings& settings)
{
    // Save the creation settings
    m_settings = settings;

    // Retrieve the attributes of the target window
    XWindowAttributes windowAttributes;
    if (XGetWindowAttributes(m_display, m_window, &windowAttributes) == 0)
    {
        err() << "Failed to get the window attributes" << std::endl;
        return;
    }

    // Get its visuals
    XVisualInfo tpl;
    tpl.screen   = DefaultScreen(m_display);
    tpl.visualid = XVisualIDFromVisual(windowAttributes.visual);
    int nbVisuals = 0;
    XVisualInfo* visualInfo = XGetVisualInfo(m_display, VisualIDMask | VisualScreenMask, &tpl, &nbVisuals);

    // Get the context to share display lists with
    GLXContext toShare = shared ? shared->m_context : NULL;

    // There are no GLX versions prior to 1.0
    int major = 0;
    int minor = 0;

    if (!glXQueryVersion(m_display, &major, &minor))
        err() << "Failed to query GLX version, limited to legacy context creation" << std::endl;

    // Make sure that extensions are initialized if this is not the shared context
    // The shared context is the context used to initialize the extensions
    if (shared)
        ensureExtensionsInit(m_display, DefaultScreen(m_display));

    // Check if glXCreateContextAttribsARB is available (requires GLX 1.3 or greater)
    bool hasCreateContextArb = (sfglx_ext_ARB_create_context == sfglx_LOAD_SUCCEEDED) && ((major > 1) || (minor >= 3));

    // Check if we need to use glXCreateContextAttribsARB
    bool needCreateContextArb = false;

    if (m_settings.attributeFlags)
        needCreateContextArb = true;
    else if (m_settings.majorVersion >= 3)
        needCreateContextArb = true;

    // Create the OpenGL context -- first try using glXCreateContextAttribsARB if we need to
    if (hasCreateContextArb && needCreateContextArb)
    {
        // Get a GLXFBConfig that matches the the window's visual, for glXCreateContextAttribsARB
        GLXFBConfig* config = NULL;

        // We don't supply attributes to match against, since
        // the visual we are matching against was already
        // deemed suitable in selectBestVisual()
        int nbConfigs = 0;
        GLXFBConfig* configs = glXChooseFBConfig(m_display, DefaultScreen(m_display), NULL, &nbConfigs);

        for (int i = 0; configs && (i < nbConfigs); ++i)
        {
            XVisualInfo* visual = glXGetVisualFromFBConfig(m_display, configs[i]);

            if (!visual)
                continue;

            if (visual->visualid == visualInfo->visualid)
            {
                config = &configs[i];
                break;
            }
        }

        if (!config)
            err() << "Failed to get GLXFBConfig which corresponds to the window's visual" << std::endl;

        while (config && !m_context && m_settings.majorVersion)
        {
            // Check if setting the profile is supported
            if (sfglx_ext_ARB_create_context_profile == sfglx_LOAD_SUCCEEDED)
            {
                int profile = (m_settings.attributeFlags & ContextSettings::Core) ? GLX_CONTEXT_CORE_PROFILE_BIT_ARB : GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB;
                int debug = (m_settings.attributeFlags & ContextSettings::Debug) ? GLX_CONTEXT_DEBUG_BIT_ARB : 0;

                // Create the context
                int attributes[] =
                {
                    GLX_CONTEXT_MAJOR_VERSION_ARB, static_cast<int>(m_settings.majorVersion),
                    GLX_CONTEXT_MINOR_VERSION_ARB, static_cast<int>(m_settings.minorVersion),
                    GLX_CONTEXT_PROFILE_MASK_ARB,  profile,
                    GLX_CONTEXT_FLAGS_ARB,         debug,
                    0,                             0
                };

                // RAII GLX error handler (we simply ignore errors here)
                // On an error, glXCreateContextAttribsARB will return 0 anyway
                GlxErrorHandler handler(m_display);

                m_context = glXCreateContextAttribsARB(m_display, *config, toShare, true, attributes);
            }
            else
            {
                if ((m_settings.attributeFlags & ContextSettings::Core) || (m_settings.attributeFlags & ContextSettings::Debug))
                    err() << "Selecting a profile during context creation is not supported,"
                          << "disabling comptibility and debug" << std::endl;

                m_settings.attributeFlags = ContextSettings::Default;

                // Create the context
                int attributes[] =
                {
                    GLX_CONTEXT_MAJOR_VERSION_ARB, static_cast<int>(m_settings.majorVersion),
                    GLX_CONTEXT_MINOR_VERSION_ARB, static_cast<int>(m_settings.minorVersion),
                    0,                             0
                };

                // RAII GLX error handler (we simply ignore errors here)
                // On an error, glXCreateContextAttribsARB will return 0 anyway
                GlxErrorHandler handler(m_display);

                m_context = glXCreateContextAttribsARB(m_display, *config, toShare, true, attributes);
            }

            if (!m_context)
            {
                // If we couldn't create the context, first try disabling flags,
                // then lower the version number and try again -- stop at 0.0
                // Invalid version numbers will be generated by this algorithm (like 3.9), but we really don't care
                if (m_settings.attributeFlags != ContextSettings::Default)
                {
                    m_settings.attributeFlags = ContextSettings::Default;
                }
                else if (m_settings.minorVersion > 0)
                {
                    // If the minor version is not 0, we decrease it and try again
                    m_settings.minorVersion--;

                    m_settings.attributeFlags = settings.attributeFlags;
                }
                else
                {
                    // If the minor version is 0, we decrease the major version
                    m_settings.majorVersion--;
                    m_settings.minorVersion = 9;

                    m_settings.attributeFlags = settings.attributeFlags;
                }
            }
        }

        if (configs)
            XFree(configs);
    }

    // If glXCreateContextAttribsARB failed, use glXCreateContext
    if (!m_context)
    {
        // set the context version to 2.1 (arbitrary) and disable flags
        m_settings.majorVersion = 2;
        m_settings.minorVersion = 1;
        m_settings.attributeFlags = ContextSettings::Default;

#if defined(GLX_DEBUGGING)
    GlxErrorHandler handler(m_display);
#endif

        // Create the context, using the target window's visual
        m_context = glXCreateContext(m_display, visualInfo, toShare, true);

#if defined(GLX_DEBUGGING)
    if (glxErrorOccurred)
        err() << "GLX error in GlxContext::createContext()" << std::endl;
#endif
    }

    if (!m_context)
    {
        err() << "Failed to create an OpenGL context for this window" << std::endl;
    }
    else
    {
        // Update the creation settings from the chosen format
        int depth, stencil, multiSampling, samples;
        glXGetConfig(m_display, visualInfo, GLX_DEPTH_SIZE,         &depth);
        glXGetConfig(m_display, visualInfo, GLX_STENCIL_SIZE,       &stencil);

        if (sfglx_ext_ARB_multisample == sfglx_LOAD_SUCCEEDED)
        {
            glXGetConfig(m_display, visualInfo, GLX_SAMPLE_BUFFERS_ARB, &multiSampling);
            glXGetConfig(m_display, visualInfo, GLX_SAMPLES_ARB,        &samples);
        }
        else
        {
            multiSampling = 0;
            samples = 0;
        }

        m_settings.depthBits         = static_cast<unsigned int>(depth);
        m_settings.stencilBits       = static_cast<unsigned int>(stencil);
        m_settings.antialiasingLevel = multiSampling ? samples : 0;
    }

    // Free the visual info
    XFree(visualInfo);
}
示例#14
0
/*
 * Create an RGB, double-buffered X window.
 * Return the window and context handles.
 */
static void
make_x_window(Display *x_dpy, EGLDisplay egl_dpy,
              const char *name,
              int x, int y, int width, int height, int es_ver,
              Window *winRet,
              EGLContext *ctxRet,
              EGLSurface *surfRet)
{
   EGLint attribs[] = {
      EGL_RENDERABLE_TYPE, 0x0,
      EGL_RED_SIZE, 1,
      EGL_GREEN_SIZE, 1,
      EGL_BLUE_SIZE, 1,
      EGL_NONE
   };
   EGLint ctx_attribs[] = {
      EGL_CONTEXT_CLIENT_VERSION, 0,
      EGL_NONE
   };

   int scrnum;
   XSetWindowAttributes attr;
   unsigned long mask;
   Window root;
   Window win;
   XVisualInfo *visInfo, visTemplate;
   int num_visuals;
   EGLContext ctx;
   EGLConfig config;
   EGLint num_configs;
   EGLint vid;

   scrnum = DefaultScreen( x_dpy );
   root = RootWindow( x_dpy, scrnum );

   if (es_ver == 1)
      attribs[1] = EGL_OPENGL_ES_BIT;
   else
      attribs[1] = EGL_OPENGL_ES2_BIT;
   ctx_attribs[1] = es_ver;

   if (!eglChooseConfig( egl_dpy, attribs, &config, 1, &num_configs)) {
      printf("Error: couldn't get an EGL visual config\n");
      exit(1);
   }

   assert(config);
   assert(num_configs > 0);

   if (!eglGetConfigAttrib(egl_dpy, config, EGL_NATIVE_VISUAL_ID, &vid)) {
      printf("Error: eglGetConfigAttrib() failed\n");
      exit(1);
   }

   /* The X window visual must match the EGL config */
   visTemplate.visualid = vid;
   visInfo = XGetVisualInfo(x_dpy, VisualIDMask, &visTemplate, &num_visuals);
   if (!visInfo) {
      printf("Error: couldn't get X visual\n");
      exit(1);
   }

   /* window attributes */
   attr.background_pixel = 0;
   attr.border_pixel = 0;
   attr.colormap = XCreateColormap( x_dpy, root, visInfo->visual, AllocNone);
   attr.event_mask = StructureNotifyMask | ExposureMask | KeyPressMask;
   mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask;

   win = XCreateWindow( x_dpy, root, 0, 0, width, height,
		        0, visInfo->depth, InputOutput,
		        visInfo->visual, mask, &attr );

   /* set hints and properties */
   {
      XSizeHints sizehints;
      sizehints.x = x;
      sizehints.y = y;
      sizehints.width  = width;
      sizehints.height = height;
      sizehints.flags = USSize | USPosition;
      XSetNormalHints(x_dpy, win, &sizehints);
      XSetStandardProperties(x_dpy, win, name, name,
                              None, (char **)NULL, 0, &sizehints);
   }

   eglBindAPI(EGL_OPENGL_ES_API);

   ctx = eglCreateContext(egl_dpy, config, EGL_NO_CONTEXT, ctx_attribs );
   if (!ctx) {
      printf("Error: eglCreateContext failed\n");
      exit(1);
   }

   *surfRet = eglCreateWindowSurface(egl_dpy, config, win, NULL);

   if (!*surfRet) {
      printf("Error: eglCreateWindowSurface failed\n");
      exit(1);
   }

   XFree(visInfo);

   *winRet = win;
   *ctxRet = ctx;
}
示例#15
0
            break;
        sleep(1);
    }
    if (server.num_desktops == 0) {
        server.num_desktops = 1;
        fprintf(stderr, "warning : WM doesn't respect NETWM specs. tint2 default to 1 desktop.\n");
    }
}

void server_init_visual()
{
    // inspired by freedesktops fdclock ;)
    XVisualInfo templ = {.screen = server.screen, .depth = 32, .class = TrueColor};
    int nvi;
    XVisualInfo *xvi =
        XGetVisualInfo(server.display, VisualScreenMask | VisualDepthMask | VisualClassMask, &templ, &nvi);

    Visual *visual = NULL;
    if (xvi) {
        XRenderPictFormat *format;
        for (int i = 0; i < nvi; i++) {
            format = XRenderFindVisualFormat(server.display, xvi[i].visual);
            if (format->type == PictTypeDirect && format->direct.alphaMask) {
                visual = xvi[i].visual;
                break;
            }
        }
    }
    XFree(xvi);

    // check composite manager
示例#16
0
Visual *XAbstractGui::GetBestVisual(Display *dpy, int *vClass, int *depth)
{
    int default_depth;
    XVisualInfo vTemplate;
    XVisualInfo *visualList = nullptr;
    Visual *visual = nullptr;
    int nrOfVisuals;

    vTemplate.screen = DefaultScreen(dpy);
    default_depth = DefaultDepth(dpy, vTemplate.screen);

    switch (default_depth)
    {
        case 8:
            *vClass = vTemplate.c_class  = PseudoColor;
            visualList = XGetVisualInfo(dpy,
                                        VisualScreenMask | VisualClassMask,
                                        &vTemplate, &nrOfVisuals);

            if (nrOfVisuals > 0)
            {
                *depth = visualList[0].depth;
                visual = visualList[0].visual;
            }
            else
            {
                *vClass = vTemplate.c_class = TrueColor;
                visualList = XGetVisualInfo(dpy,
                                            VisualScreenMask | VisualClassMask,
                                            &vTemplate, &nrOfVisuals);

                if (nrOfVisuals > 0)
                {
                    *depth = visualList[0].depth;
                    visual = visualList[0].visual;
                }
                else
                {
                    *vClass = vTemplate.c_class  = GrayScale;
                    visualList = XGetVisualInfo(dpy, VisualScreenMask |
                                                VisualClassMask, &vTemplate,
                                                &nrOfVisuals);

                    if (nrOfVisuals > 0)
                    {
                        *depth = visualList[0].depth;
                        visual = visualList[0].visual;
                    }
                }
            }

            break;

        case 16:
        case 24:
        case 32:
            *vClass = vTemplate.c_class  = TrueColor;
            visualList = XGetVisualInfo(dpy,
                                        VisualScreenMask | VisualClassMask,
                                        &vTemplate, &nrOfVisuals);

            if (nrOfVisuals > 0)
            {
                *depth = visualList[0].depth;
                visual = visualList[0].visual;
            }

            break;
    }

    XFree(visualList);
    return visual;
}
示例#17
0
WindowEGL::WindowEGL(const Window::Properties & properties) :
		WindowX11(properties), eglData(new WindowEGLData) {
			
	eglData->shareContext = properties.shareContext;
	eglData->display = eglGetDisplay(x11Data->display);
	if (eglData->display == EGL_NO_DISPLAY) {
		throw std::runtime_error("Failed to open display.");
	}

	EGLint versionMajor;
	EGLint versionMinor;
	if (eglInitialize(eglData->display, &versionMajor, &versionMinor) == EGL_FALSE) {
		throw std::runtime_error("Failed to initialize display.");
	}

	// EGL version 1.3 is needed for EGL_CONTEXT_CLIENT_VERSION
	if ((versionMajor < 1) || ((versionMajor == 1) && (versionMinor < 3))) {
		throw std::runtime_error("EGL version less than 1.3 detected.");
	}

	EGLenum api;
	EGLint glesVersion = 0;
	switch(properties.renderingAPI) {
		case Properties::RenderingAPI::GL_ES_1:
			api = EGL_OPENGL_ES_API;
			glesVersion = 1;
			break;
		case Properties::RenderingAPI::GL_ES_2:
			api = EGL_OPENGL_ES_API;
			glesVersion = 2;
			break;
		case Properties::RenderingAPI::GL_ES_3:
			api = EGL_OPENGL_ES_API;
			glesVersion = 3;
			break;
		case Properties::RenderingAPI::GL:
			api = EGL_OPENGL_API;
			break;
		default:
			throw std::runtime_error("Unsupported rendering API.");
	}
	if (EGL_TRUE != eglBindAPI(api)) {
		throw std::runtime_error("Cannot bind API.");
	}

	// Define attributes of desired framebuffer configurations
	EGLint fbAttribs[] = { EGL_COLOR_BUFFER_TYPE, EGL_RGB_BUFFER, EGL_BUFFER_SIZE, 24, EGL_RED_SIZE, 8, EGL_GREEN_SIZE, 8, EGL_BLUE_SIZE, 8, EGL_DEPTH_SIZE, 8,
							EGL_NATIVE_RENDERABLE, EGL_TRUE, EGL_SURFACE_TYPE, EGL_WINDOW_BIT, EGL_NONE };
	// Request a single framebuffer configuration
	EGLConfig fbConfig;
	EGLint fbCount;
	if (eglChooseConfig(eglData->display, fbAttribs, &fbConfig, 1, &fbCount) == EGL_FALSE) {
		throw std::runtime_error("Failed to retrieve a matching framebuffer configuration.");
	}

	if (fbCount == 0) {
		// FIXME: Workaround: Use eglGetConfigs instead of eglChooseConfig, because sometimes eglChooseConfig does not find matching configurations.
		EGLConfig fbConfigs[200];
		eglGetConfigs(eglData->display, fbConfigs, 200, &fbCount);
		for (EGLint i = 0; i < fbCount; ++i) {
			EGLint value;
			// We want to render into a window
			eglGetConfigAttrib(eglData->display, fbConfigs[i], EGL_SURFACE_TYPE, &value);
			if (!(value & EGL_WINDOW_BIT)) {
				continue;
			}
			// We want a configuration with a depth buffer
			eglGetConfigAttrib(eglData->display, fbConfigs[i], EGL_DEPTH_SIZE, &value);
			if (value == 0) {
				continue;
			}
			fbConfig = fbConfigs[i];
		}
	}

	if (fbCount == 0) {
		throw std::runtime_error("No matching framebuffer configurations found.");
	}

	EGLint visualID;
	eglGetConfigAttrib(eglData->display, fbConfig, EGL_NATIVE_VISUAL_ID, &visualID);

	EGLint contextAttribs[] = { EGL_CONTEXT_CLIENT_VERSION, glesVersion, EGL_NONE };
	if (0 == glesVersion) {
		contextAttribs[0] = EGL_NONE;
		contextAttribs[1] = EGL_NONE;
	}
	// Check for existing GL context
	if(properties.shareContext) {
		eglData->context = eglGetCurrentContext();
	}
	if (eglData->context == EGL_NO_CONTEXT) {
		eglData->context = eglCreateContext(eglData->display, fbConfig, EGL_NO_CONTEXT, contextAttribs);
	}
	if (eglData->context == EGL_NO_CONTEXT) {
		throw std::runtime_error("Failed to create context: " +
								 eglErrorToString(eglGetError()));
	}

	// Create X11 window
	XVisualInfo templateInfo;
	templateInfo.visualid = visualID;
	int visualCount;
	XVisualInfo * visualsInfo = XGetVisualInfo(x11Data->display, VisualIDMask, &templateInfo, &visualCount);
	if (visualsInfo == nullptr) {
		throw std::runtime_error("Failed to find a matching visual.");
	} else if (visualCount != 1) {
		XFree(visualsInfo);
		throw std::runtime_error("More than one visual found.");
	}

	x11Data->colorMap = XCreateColormap(x11Data->display, RootWindow(x11Data->display, visualsInfo[0].screen), visualsInfo[0].visual, AllocNone);
	x11Data->freeColorMap = true;

	XSetWindowAttributes windowAttribs;
	windowAttribs.colormap = x11Data->colorMap;
	windowAttribs.background_pixmap = None;
	windowAttribs.border_pixel = 0;
	windowAttribs.event_mask = StructureNotifyMask | KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask | PointerMotionMask;

	x11Data->window = XCreateWindow(x11Data->display, RootWindow(x11Data->display, visualsInfo[0].screen), 
								 0, 0, properties.clientAreaWidth, properties.clientAreaHeight, 
								 0, visualsInfo[0].depth,
								 InputOutput, visualsInfo[0].visual, CWBorderPixel | CWColormap | CWEventMask, &windowAttribs);

	XFree(visualsInfo);

	if (!x11Data->window) {
		throw std::runtime_error("Failed to create window.");
	} else {
		x11Data->freeWindow = true;
	}

	if (properties.borderless) {
		x11Data->removeWindowBorder();
	}
	if (!properties.resizable) {
		x11Data->fixWindowSize(static_cast<int>(properties.clientAreaWidth), 
							   static_cast<int>(properties.clientAreaHeight));
	}

	x11Data->inputMethod = XOpenIM(x11Data->display, nullptr, nullptr, nullptr);
	if (x11Data->inputMethod == nullptr) {
		throw std::runtime_error("Failed to create input method.");
	}

	x11Data->inputContext = XCreateIC(x11Data->inputMethod,
								   XNInputStyle, XIMPreeditNone | XIMStatusNone,
								   XNClientWindow, x11Data->window,
								   XNFocusWindow, x11Data->window,
								   nullptr);
	if (x11Data->inputContext == nullptr) {
		throw std::runtime_error("Failed to create input context.");
	}

	XStoreName(x11Data->display, x11Data->window, properties.title.c_str());

	XMapWindow(x11Data->display, x11Data->window);
	if (properties.positioned) {
		XMoveWindow(x11Data->display, x11Data->window, properties.posX, properties.posY);
	}

	eglData->surface = eglCreateWindowSurface(eglData->display, fbConfig, x11Data->window, nullptr);
	if (eglData->surface == EGL_NO_SURFACE) {
		throw std::runtime_error("Failed to create window surface.");
	}

	eglMakeCurrent(eglData->display, eglData->surface, eglData->surface, eglData->context);
}
示例#18
0
文件: xeglgears.c 项目: aosm/X11apps
static EGLBoolean
egl_manager_create_window(struct egl_manager *eman, const char *name,
                          EGLint w, EGLint h, EGLBoolean need_surface,
                          EGLBoolean fullscreen, const EGLint *attrib_list)
{
   XVisualInfo vinfo_template, *vinfo = NULL;
   EGLint val, num_vinfo;
   Window root;
   XSetWindowAttributes attrs;
   unsigned long mask;
   EGLint x = 0, y = 0;

   if (!eglGetConfigAttrib(eman->dpy, eman->conf,
                           EGL_NATIVE_VISUAL_ID, &val)) {
      printf("eglGetConfigAttrib() failed\n");
      return EGL_FALSE;
   }
   if (val) {
      vinfo_template.visualid = (VisualID) val;
      vinfo = XGetVisualInfo(eman->xdpy, VisualIDMask, &vinfo_template, &num_vinfo);
   }
   /* try harder if window surface is not needed */
   if (!vinfo && !need_surface &&
       eglGetConfigAttrib(eman->dpy, eman->conf, EGL_BUFFER_SIZE, &val)) {
      if (val == 32)
         val = 24;
      vinfo_template.depth = val;
      vinfo = XGetVisualInfo(eman->xdpy, VisualDepthMask, &vinfo_template, &num_vinfo);
   }

   if (!vinfo) {
      printf("XGetVisualInfo() failed\n");
      return EGL_FALSE;
   }

   root = DefaultRootWindow(eman->xdpy);
   if (fullscreen) {
      x = y = 0;
      w = DisplayWidth(eman->xdpy, DefaultScreen(eman->xdpy));
      h = DisplayHeight(eman->xdpy, DefaultScreen(eman->xdpy));
   }

   /* window attributes */
   attrs.background_pixel = 0;
   attrs.border_pixel = 0;
   attrs.colormap = XCreateColormap(eman->xdpy, root, vinfo->visual, AllocNone);
   attrs.event_mask = StructureNotifyMask | ExposureMask | KeyPressMask;
   attrs.override_redirect = fullscreen;
   mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask | CWOverrideRedirect;

   eman->xwin = XCreateWindow(eman->xdpy, root, x, y, w, h,
                              0, vinfo->depth, InputOutput,
                              vinfo->visual, mask, &attrs);
   XFree(vinfo);

   /* set hints and properties */
   {
      XSizeHints sizehints;
      sizehints.x = x;
      sizehints.y = y;
      sizehints.width  = w;
      sizehints.height = h;
      sizehints.flags = USSize | USPosition;
      XSetNormalHints(eman->xdpy, eman->xwin, &sizehints);
      XSetStandardProperties(eman->xdpy, eman->xwin, name, name,
                             None, (char **)NULL, 0, &sizehints);
   }

   if (need_surface) {
      eman->win = eglCreateWindowSurface(eman->dpy, eman->conf,
                                         eman->xwin, attrib_list);
      if (eman->win == EGL_NO_SURFACE) {
         printf("eglCreateWindowSurface() failed\n");
         XDestroyWindow(eman->xdpy, eman->xwin);
         eman->xwin = None;
         return EGL_FALSE;
      }
   }

   eman->gc = XCreateGC(eman->xdpy, eman->xwin, 0, NULL);

   XMapWindow(eman->xdpy, eman->xwin);

   return EGL_TRUE;
}
bool
NativeStateX11::create_window(WindowProperties const& properties)
{
    static const char *win_name("glmark2 "GLMARK_VERSION);

    if (!xdpy_) {
        Log::error("Error: X11 Display has not been initialized!\n");
        return false;
    }

    /* Recreate an existing window only if it has actually been resized */
    if (xwin_) {
        if (properties_.fullscreen != properties.fullscreen ||
            (properties.fullscreen == false &&
             (properties_.width != properties.width ||
              properties_.height != properties.height)))
        {
            XDestroyWindow(xdpy_, xwin_);
            xwin_ = 0;
        }
        else
        {
            return true;
        }
    }

    /* Set desired attributes */
    properties_.fullscreen = properties.fullscreen;
    properties_.visual_id = properties.visual_id;

    if (properties_.fullscreen) {
        /* Get the screen (root window) size */
        XWindowAttributes window_attr;
        XGetWindowAttributes(xdpy_, RootWindow(xdpy_, DefaultScreen(xdpy_)), 
                             &window_attr);
        properties_.width = window_attr.width;
        properties_.height = window_attr.height;
    }
    else {
        properties_.width = properties.width;
        properties_.height = properties.height;
    }

    XVisualInfo vis_tmpl;
    XVisualInfo *vis_info = 0;
    int num_visuals;

    /* The X window visual must match the supplied visual id */
    vis_tmpl.visualid = properties_.visual_id;
    vis_info = XGetVisualInfo(xdpy_, VisualIDMask, &vis_tmpl,
                             &num_visuals);
    if (!vis_info) {
        Log::error("Error: Could not get a valid XVisualInfo!\n");
        return false;
    }

    Log::debug("Creating XWindow W: %d H: %d VisualID: 0x%x\n",
               properties_.width, properties_.height, vis_info->visualid);

    /* window attributes */
    XSetWindowAttributes attr;
    unsigned long mask;
    Window root = RootWindow(xdpy_, DefaultScreen(xdpy_));

    attr.background_pixel = 0;
    attr.border_pixel = 0;
    attr.colormap = XCreateColormap(xdpy_, root, vis_info->visual, AllocNone);
    attr.event_mask = KeyPressMask;
    mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask;

    xwin_ = XCreateWindow(xdpy_, root, 0, 0, properties_.width, properties_.height,
                          0, vis_info->depth, InputOutput,
                          vis_info->visual, mask, &attr);

    XFree(vis_info);

    if (!xwin_) {
        Log::error("Error: XCreateWindow() failed!\n");
        return false;
    }

    /* set hints and properties */
    Atom fs_atom = None;
    if (properties_.fullscreen) {
        fs_atom = XInternAtom(xdpy_, "_NET_WM_STATE_FULLSCREEN", True);
        if (fs_atom == None)
            Log::debug("Warning: Could not set EWMH Fullscreen hint.\n");
    }
    if (fs_atom != None) {
        XChangeProperty(xdpy_, xwin_,
                        XInternAtom(xdpy_, "_NET_WM_STATE", True),
                        XA_ATOM, 32, PropModeReplace,
                        reinterpret_cast<unsigned char*>(&fs_atom),  1);
    }
    else {
        XSizeHints sizehints;
        sizehints.min_width  = properties_.width;
        sizehints.min_height = properties_.height;
        sizehints.max_width  = properties_.width;
        sizehints.max_height = properties_.height;
        sizehints.flags = PMaxSize | PMinSize;

        XSetWMProperties(xdpy_, xwin_, NULL, NULL,
                         NULL, 0, &sizehints, NULL, NULL);
    }

    /* Set the window name */
    XStoreName(xdpy_ , xwin_,  win_name);

    /* Gracefully handle Window Delete event from window manager */
    Atom wmDelete = XInternAtom(xdpy_, "WM_DELETE_WINDOW", True);
    XSetWMProtocols(xdpy_, xwin_, &wmDelete, 1);

    return true;
}
示例#20
0
void
initSpace(Window window)
{
	Display    *display = dsp;
	XWindowAttributes xwa;


	(void) XGetWindowAttributes(dsp, window, &xwa);
	int         n;
	XVisualInfo *wantVis, vTemplate;
	int  VisualClassWanted=-1;

	vTemplate.screen = screen;
	vTemplate.depth = xwa.depth;

	if (VisualClassWanted == -1) {
	  vTemplate.c_class = DefaultVisual(display, screen)->c_class;
	} else {
	  vTemplate.c_class = VisualClassWanted;
	}

	wantVis = XGetVisualInfo(display,
				 VisualScreenMask | VisualDepthMask | VisualClassMask,
				 &vTemplate, &n);

	if (VisualClassWanted != -1 && n == 0) {
	  /* Wanted visual not found so use default */

	  vTemplate.c_class = DefaultVisual(display, screen)->c_class;

	  wantVis = XGetVisualInfo(display,
				   VisualScreenMask | VisualDepthMask | VisualClassMask,
				   &vTemplate, &n);
	}
	/* if User asked for color, try that first, then try mono */
	/* if User asked for mono.  Might fail on 16/24 bit displays,
	   so fall back on color, but keep the mono "look & feel". */

	if (!getVisual(wantVis, n)) {
	  if (!getVisual(wantVis, n)) {
	    kdError() << i18n("GL can not render with root visual\n") << endl;
	    return;
	  }
	}

	/* PURIFY 3.0a on SunOS4 reports a 104 byte memory leak on the next line each
	 * time that morph3d mode is run in random mode. */

	glx_context = glXCreateContext(display, wantVis, 0, True);

	XFree((char *) wantVis);


	glXMakeCurrent(display, window, glx_context);
	glDrawBuffer(GL_FRONT);

	if (mono) {
	  glIndexi(WhitePixel(display, screen));
	  glClearIndex(BlackPixel(display, screen));
	}

	retqshape(xwa.width, xwa.height);
	Init();
}
示例#21
0
QT_BEGIN_NAMESPACE

QXlibWindow::QXlibWindow(QWidget *window)
    : QPlatformWindow(window)
    , mGLContext(0)
    , mScreen(QXlibScreen::testLiteScreenForWidget(window))
{
    int x = window->x();
    int y = window->y();
    int w = window->width();
    int h = window->height();

#if !defined(QT_NO_OPENGL)
    if(window->platformWindowFormat().windowApi() == QPlatformWindowFormat::OpenGL
            && QApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::OpenGL)
            || window->platformWindowFormat().alpha()) {
#if !defined(QT_OPENGL_ES_2)
        XVisualInfo *visualInfo = qglx_findVisualInfo(mScreen->display()->nativeDisplay(),mScreen->xScreenNumber(),window->platformWindowFormat());
#else
        QPlatformWindowFormat windowFormat = correctColorBuffers(window->platformWindowFormat());

        EGLDisplay eglDisplay = mScreen->eglDisplay();
        EGLConfig eglConfig = q_configFromQPlatformWindowFormat(eglDisplay,windowFormat);
        VisualID id = QXlibEglIntegration::getCompatibleVisualId(mScreen->display()->nativeDisplay(), eglDisplay, eglConfig);

        XVisualInfo visualInfoTemplate;
        memset(&visualInfoTemplate, 0, sizeof(XVisualInfo));
        visualInfoTemplate.visualid = id;

        XVisualInfo *visualInfo;
        int matchingCount = 0;
        visualInfo = XGetVisualInfo(mScreen->display()->nativeDisplay(), VisualIDMask, &visualInfoTemplate, &matchingCount);
#endif //!defined(QT_OPENGL_ES_2)
        if (visualInfo) {
            mDepth = visualInfo->depth;
            mFormat = (mDepth == 32) ? QImage::Format_ARGB32_Premultiplied : QImage::Format_RGB32;
            mVisual = visualInfo->visual;
            Colormap cmap = XCreateColormap(mScreen->display()->nativeDisplay(), mScreen->rootWindow(), visualInfo->visual, AllocNone);

            XSetWindowAttributes a;
            a.background_pixel = WhitePixel(mScreen->display()->nativeDisplay(), mScreen->xScreenNumber());
            a.border_pixel = BlackPixel(mScreen->display()->nativeDisplay(), mScreen->xScreenNumber());
            a.colormap = cmap;
            x_window = XCreateWindow(mScreen->display()->nativeDisplay(), mScreen->rootWindow(),x, y, w, h,
                                     0, visualInfo->depth, InputOutput, visualInfo->visual,
                                     CWBackPixel|CWBorderPixel|CWColormap, &a);
        } else {
            qFatal("no window!");
        }
    } else
#endif //!defined(QT_NO_OPENGL)
    {
        mDepth = mScreen->depth();
        mFormat = (mDepth == 32) ? QImage::Format_ARGB32_Premultiplied : QImage::Format_RGB32;
        mVisual = mScreen->defaultVisual();

        x_window = XCreateSimpleWindow(mScreen->display()->nativeDisplay(), mScreen->rootWindow(),
                                       x, y, w, h, 0 /*border_width*/,
                                       mScreen->blackPixel(), mScreen->whitePixel());
    }

#ifdef MYX11_DEBUG
    qDebug() << "QTestLiteWindow::QTestLiteWindow creating" << hex << x_window << window;
#endif

    XSetWindowBackgroundPixmap(mScreen->display()->nativeDisplay(), x_window, XNone);

    XSelectInput(mScreen->display()->nativeDisplay(), x_window,
                 ExposureMask | KeyPressMask | KeyReleaseMask |
                 EnterWindowMask | LeaveWindowMask | FocusChangeMask |
                 PointerMotionMask | ButtonPressMask |  ButtonReleaseMask |
                 ButtonMotionMask | PropertyChangeMask |
                 StructureNotifyMask);

    gc = createGC();

    Atom protocols[5];
    int n = 0;
    protocols[n++] = QXlibStatic::atom(QXlibStatic::WM_DELETE_WINDOW);        // support del window protocol
    protocols[n++] = QXlibStatic::atom(QXlibStatic::WM_TAKE_FOCUS);                // support take focus window protocol
//    protocols[n++] = QXlibStatic::atom(QXlibStatic::_NET_WM_PING);                // support _NET_WM_PING protocol
#ifndef QT_NO_XSYNC
    protocols[n++] = QXlibStatic::atom(QXlibStatic::_NET_WM_SYNC_REQUEST);        // support _NET_WM_SYNC_REQUEST protocol
#endif // QT_NO_XSYNC
    if (window->windowFlags() & Qt::WindowContextHelpButtonHint)
        protocols[n++] = QXlibStatic::atom(QXlibStatic::_NET_WM_CONTEXT_HELP);
    XSetWMProtocols(mScreen->display()->nativeDisplay(), x_window, protocols, n);
}
示例#22
0
VisualID QEgl::getCompatibleVisualId(EGLConfig config)
{
    VisualID    visualId = 0;
    EGLint      eglValue = 0;

    EGLint configRedSize = 0;
    eglGetConfigAttrib(display(), config, EGL_RED_SIZE, &configRedSize);

    EGLint configGreenSize = 0;
    eglGetConfigAttrib(display(), config, EGL_GREEN_SIZE, &configGreenSize);

    EGLint configBlueSize = 0;
    eglGetConfigAttrib(display(), config, EGL_BLUE_SIZE, &configBlueSize);

    EGLint configAlphaSize = 0;
    eglGetConfigAttrib(display(), config, EGL_ALPHA_SIZE, &configAlphaSize);

    eglGetConfigAttrib(display(), config, EGL_CONFIG_ID, &eglValue);
    int configId = eglValue;

    // See if EGL provided a valid VisualID:
    eglGetConfigAttrib(display(), config, EGL_NATIVE_VISUAL_ID, &eglValue);
    visualId = (VisualID)eglValue;
    if (visualId) {
        // EGL has suggested a visual id, so get the rest of the visual info for that id:
        XVisualInfo visualInfoTemplate;
        memset(&visualInfoTemplate, 0, sizeof(XVisualInfo));
        visualInfoTemplate.visualid = visualId;

        XVisualInfo *chosenVisualInfo;
        int matchingCount = 0;
        chosenVisualInfo = XGetVisualInfo(X11->display, VisualIDMask, &visualInfoTemplate, &matchingCount);
        if (chosenVisualInfo) {
            // Skip size checks if implementation supports non-matching visual
            // and config (http://bugreports.qt-project.org/browse/QTBUG-9444).
            if (QEgl::hasExtension("EGL_NV_post_convert_rounding")) {
                XFree(chosenVisualInfo);
                return visualId;
            }

            int visualRedSize = countBits(chosenVisualInfo->red_mask);
            int visualGreenSize = countBits(chosenVisualInfo->green_mask);
            int visualBlueSize = countBits(chosenVisualInfo->blue_mask);
            int visualAlphaSize = -1; // Need XRender to tell us the alpha channel size

#if !defined(QT_NO_XRENDER)
            if (X11->use_xrender) {
                // If we have XRender, actually check the visual supplied by EGL is ARGB
                XRenderPictFormat *format;
                format = XRenderFindVisualFormat(X11->display, chosenVisualInfo->visual);
                if (format && (format->type == PictTypeDirect))
                    visualAlphaSize = countBits(format->direct.alphaMask);
            }
#endif

            bool visualMatchesConfig = false;
            if ( visualRedSize == configRedSize &&
                 visualGreenSize == configGreenSize &&
                 visualBlueSize == configBlueSize )
            {
                // We need XRender to check the alpha channel size of the visual. If we don't have
                // the alpha size, we don't check it against the EGL config's alpha size.
                if (visualAlphaSize >= 0)
                    visualMatchesConfig = visualAlphaSize == configAlphaSize;
                else
                    visualMatchesConfig = true;
            }

            if (!visualMatchesConfig) {
                if (visualAlphaSize >= 0) {
                    qWarning("Warning: EGL suggested using X Visual ID %d (ARGB%d%d%d%d) for EGL config %d (ARGB%d%d%d%d), but this is incompatable",
                             (int)visualId, visualAlphaSize, visualRedSize, visualGreenSize, visualBlueSize,
                             configId, configAlphaSize, configRedSize, configGreenSize, configBlueSize);
                } else {
                    qWarning("Warning: EGL suggested using X Visual ID %d (RGB%d%d%d) for EGL config %d (RGB%d%d%d), but this is incompatable",
                             (int)visualId, visualRedSize, visualGreenSize, visualBlueSize,
                             configId, configRedSize, configGreenSize, configBlueSize);
                }
                visualId = 0;
            }
        } else {
            qWarning("Warning: EGL suggested using X Visual ID %d for EGL config %d, but that isn't a valid ID",
                     (int)visualId, configId);
            visualId = 0;
        }
        XFree(chosenVisualInfo);
    }
#ifdef QT_DEBUG_X11_VISUAL_SELECTION
    else
        qDebug("EGL did not suggest a VisualID (EGL_NATIVE_VISUAL_ID was zero) for EGLConfig %d", configId);
#endif

    if (visualId) {
#ifdef QT_DEBUG_X11_VISUAL_SELECTION
        if (configAlphaSize > 0)
            qDebug("Using ARGB Visual ID %d provided by EGL for config %d", (int)visualId, configId);
        else
            qDebug("Using Opaque Visual ID %d provided by EGL for config %d", (int)visualId, configId);
#endif
        return visualId;
    }


    // If EGL didn't give us a valid visual ID, try XRender
#if !defined(QT_NO_XRENDER)
    if (!visualId && X11->use_xrender) {
        XVisualInfo visualInfoTemplate;
        memset(&visualInfoTemplate, 0, sizeof(XVisualInfo));

        visualInfoTemplate.c_class = TrueColor;

        XVisualInfo *matchingVisuals;
        int matchingCount = 0;
        matchingVisuals = XGetVisualInfo(X11->display,
                                         VisualClassMask,
                                         &visualInfoTemplate,
                                         &matchingCount);

        for (int i = 0; i < matchingCount; ++i) {
            XRenderPictFormat *format;
            format = XRenderFindVisualFormat(X11->display, matchingVisuals[i].visual);

            // Check the format for the visual matches the EGL config
            if ( (countBits(format->direct.redMask) == configRedSize) &&
                 (countBits(format->direct.greenMask) == configGreenSize) &&
                 (countBits(format->direct.blueMask) == configBlueSize) &&
                 (countBits(format->direct.alphaMask) == configAlphaSize) )
            {
                visualId = matchingVisuals[i].visualid;
                break;
            }
        }
        if (matchingVisuals)
            XFree(matchingVisuals);

    }
    if (visualId) {
# ifdef QT_DEBUG_X11_VISUAL_SELECTION
        if (configAlphaSize > 0)
            qDebug("Using ARGB Visual ID %d provided by XRender for EGL config %d", (int)visualId, configId);
        else
            qDebug("Using Opaque Visual ID %d provided by XRender for EGL config %d", (int)visualId, configId);
# endif // QT_DEBUG_X11_VISUAL_SELECTION
        return visualId;
    }
# ifdef QT_DEBUG_X11_VISUAL_SELECTION
    else
        qDebug("Failed to find an XVisual which matches EGL config %d using XRender", configId);
# endif // QT_DEBUG_X11_VISUAL_SELECTION

#endif //!defined(QT_NO_XRENDER)


    // Finally, if XRender also failed to find a visual (or isn't present), try to
    // use XGetVisualInfo and only use the bit depths to match on:
    if (!visualId) {
        XVisualInfo visualInfoTemplate;
        memset(&visualInfoTemplate, 0, sizeof(XVisualInfo));
        XVisualInfo *matchingVisuals;
        int matchingCount = 0;

        visualInfoTemplate.depth = configRedSize + configGreenSize + configBlueSize + configAlphaSize;
        matchingVisuals = XGetVisualInfo(X11->display,
                                         VisualDepthMask,
                                         &visualInfoTemplate,
                                         &matchingCount);
        if (!matchingVisuals) {
            // Try again without taking the alpha channel into account:
            visualInfoTemplate.depth = configRedSize + configGreenSize + configBlueSize;
            matchingVisuals = XGetVisualInfo(X11->display,
                                             VisualDepthMask,
                                             &visualInfoTemplate,
                                             &matchingCount);
        }

        if (matchingVisuals) {
            visualId = matchingVisuals[0].visualid;
            XFree(matchingVisuals);
        }
    }

    if (visualId) {
#ifdef QT_DEBUG_X11_VISUAL_SELECTION
        qDebug("Using Visual ID %d provided by XGetVisualInfo for EGL config %d", (int)visualId, configId);
#endif
        return visualId;
    }

    qWarning("Unable to find an X11 visual which matches EGL config %d", configId);
    return (VisualID)0;
}
示例#23
0
ibool   MGLAPI XWINDC_initDriver(void *data,MGLDC *dc,int driverId,int modeId,ulong hwnd,
                                 int virtualX,int virtualY,int numBuffers,ibool stereo,int refreshRate)
/****************************************************************************
*
* Function:     XWINDC_initDriver
* Parameters:   dc  - Device context.
* Returns:      True if the device was correctly initialised.
*
* Description:  Initialises the device driver, and starts the specified
*               graphics mode. This is also where we fill in all of the
*               vectors in the device context to initialise our device
*               context properly.
*
****************************************************************************/
{
    Screen *scr;
    XSetWindowAttributes xswa;
    Display *dpy = dc->wm.xwindc.dpy;
    XVisualInfo *visinfo, vis;
    int nvis, npfv;
    Window root;
    int x,y;
    unsigned int w,h, bw, d;
    XPixmapFormatValues *pfv;

    _MGL_initInternal();
    dc->deviceType = MGL_WINDOWED_DEVICE;
    dc->xInch = dc->yInch = 0;

    g_state.d.hardwareCursor = false;

    dc->v = &g_state;
    dc->v->m.refCount++;
    dc->wm.xwindc.scr = scr = DefaultScreenOfDisplay(dpy);
    dc->wm.xwindc.gc  = DefaultGCOfScreen(scr);

    xswa.background_pixel = BlackPixel(dpy,XScreenNumberOfScreen(scr));
    xswa.backing_store = Always;

    dc->wm.xwindc.wnd = hwnd;
    XGetGeometry(dpy, hwnd, &root, &x, &y, &w, &h, &bw, &d);

    dc->mi.xRes = w;
    dc->mi.yRes = h;
    dc->mi.maxPage = 0;
    dc->mi.bytesPerLine = 0;
    dc->mi.pageSize = 0;
    dc->surface = NULL;
    dc->mi.bitsPerPixel = dc->wm.xwindc.depth = d;

    vis.visualid = XVisualIDFromVisual(DefaultVisual(dpy, XScreenNumberOfScreen(scr)));
    visinfo = XGetVisualInfo(dpy, VisualIDMask, &vis, &nvis);

    pfv = XListPixmapFormats(dpy, &npfv);
    switch (d) {
        case 8: dc->mi.maxColor = 0xFFUL;       break;
        case 15:    dc->mi.maxColor = 0x7FFFUL;     dc->pf= _MGL_pixelFormats[pfRGB555]; break;
        case 16:    dc->mi.maxColor = 0xFFFFUL;     dc->pf= _MGL_pixelFormats[visinfo->green_mask==0x7e0 ? pfRGB565 : pfRGB555]; break;
        case 24: {
            int i;
            dc->mi.maxColor = 0xFFFFFFUL;
            for(i=0; i<npfv; i++)
                if(pfv[i].depth == 24) break;
            if(pfv[i].bits_per_pixel==32){
                dc->mi.bitsPerPixel = 32;
                dc->pf= _MGL_pixelFormats[pfARGB32];
            }else
                dc->pf= _MGL_pixelFormats[pfRGB24];
            break;
            }
        case 32:    dc->mi.maxColor = 0xFFFFFFFFUL; dc->pf= _MGL_pixelFormats[pfARGB32]; break;
        }

    XFree(visinfo);

    if(d == 8){
        // Set up the private colormap if necesary
        dc->wm.xwindc.hpal = xswa.colormap = XCreateColormap(dpy, hwnd, DefaultVisualOfScreen(scr), AllocAll);
        XChangeWindowAttributes(dpy, hwnd, CWColormap, &xswa);
        }

    XMapRaised(dpy, hwnd);
    XClearWindow(dpy, hwnd);

    XWIN_initInternal(dc);
    dc->v->w.destroy = destroyDC;
    dc->r.realizePalette = XWIN_realizePalette;
    dc->r.getDefaultPalette = XWIN_getDefaultPalette;
    dc->r.putImage = XWIN_putImage;
    return true;
}
示例#24
0
// NOTE: The X11 version of createSurface will re-create the native drawable if it's visual doesn't
// match the one for the passed in EGLConfig
EGLSurface QEgl::createSurface(QPaintDevice *device, EGLConfig config, const QEglProperties *properties)
{
    int devType = device->devType();

    if (devType == QInternal::Pbuffer) {
        // TODO
        return EGL_NO_SURFACE;
    }

    QX11PixmapData *x11PixmapData = 0;
    if (devType == QInternal::Pixmap) {
        QPixmapData *pmd = static_cast<QPixmap*>(device)->data_ptr().data();
        if (pmd->classId() == QPixmapData::X11Class)
            x11PixmapData = static_cast<QX11PixmapData*>(pmd);
        else {
            // TODO: Replace the pixmap's data with a new QX11PixmapData
            qWarning("WARNING: Creating an EGL surface on a QPixmap is only supported for QX11PixmapData");
            return EGL_NO_SURFACE;
        }
    } else if ((devType != QInternal::Widget) && (devType != QInternal::Pbuffer)) {
        qWarning("WARNING: Creating an EGLSurface for device type %d isn't supported", devType);
        return EGL_NO_SURFACE;
    }

    VisualID visualId = QEgl::getCompatibleVisualId(config);
    EGLint alphaSize;
    eglGetConfigAttrib(QEgl::display(), config, EGL_ALPHA_SIZE, &alphaSize);

    if (devType == QInternal::Widget) {
        QWidget *widget = static_cast<QWidget*>(device);

        VisualID currentVisualId = 0;
        if (widget->testAttribute(Qt::WA_WState_Created))
            currentVisualId = XVisualIDFromVisual((Visual*)widget->x11Info().visual());

        if (currentVisualId != visualId) {
            // The window is either not created or has the wrong visual. Either way, we need
            // to create a window with the correct visual and call create() on the widget:

            bool visible = widget->isVisible();
            if (visible)
                widget->hide();

            XVisualInfo visualInfo;
            visualInfo.visualid = visualId;
            {
                XVisualInfo *visualInfoPtr;
                int matchingCount = 0;
                visualInfoPtr = XGetVisualInfo(widget->x11Info().display(), VisualIDMask,
                                               &visualInfo, &matchingCount);
                Q_ASSERT(visualInfoPtr); // visualId really should be valid!
                visualInfo = *visualInfoPtr;
                XFree(visualInfoPtr);
            }

            Window parentWindow = RootWindow(widget->x11Info().display(), widget->x11Info().screen());
            if (widget->parentWidget())
                parentWindow = widget->parentWidget()->winId();

            XSetWindowAttributes windowAttribs;
            QColormap colmap = QColormap::instance(widget->x11Info().screen());
            windowAttribs.background_pixel = colmap.pixel(widget->palette().color(widget->backgroundRole()));
            windowAttribs.border_pixel = colmap.pixel(Qt::black);

            unsigned int valueMask = CWBackPixel|CWBorderPixel;
            if (alphaSize > 0) {
                windowAttribs.colormap = XCreateColormap(widget->x11Info().display(), parentWindow,
                                                         visualInfo.visual, AllocNone);
                valueMask |= CWColormap;
            }

            Window window = XCreateWindow(widget->x11Info().display(), parentWindow,
                                          widget->x(), widget->y(), widget->width(), widget->height(),
                                          0, visualInfo.depth, InputOutput, visualInfo.visual,
                                          valueMask, &windowAttribs);

            // This is a nasty hack to get round the fact that we can't be a friend of QWidget:
            qt_set_winid_on_widget(widget, window);

            if (visible)
                widget->show();
        }

        // At this point, the widget's window should be created and have the correct visual. Now we
        // just need to create the EGL surface for it:
        const int *props;
        if (properties)
            props = properties->properties();
        else
            props = 0;
        EGLSurface surf = eglCreateWindowSurface(QEgl::display(), config, (EGLNativeWindowType)widget->winId(), props);
        if (surf == EGL_NO_SURFACE)
            qWarning("QEglContext::createSurface(): Unable to create EGL surface, error = 0x%x", eglGetError());
        return surf;
    }

    if (x11PixmapData) {
        // X11 Pixmaps are only created with a depth, so that's all we need to check
        EGLint configDepth;
        eglGetConfigAttrib(QEgl::display(), config, EGL_BUFFER_SIZE , &configDepth);
        if (x11PixmapData->depth() != configDepth) {
            // The bit depths are wrong which means the EGLConfig isn't compatable with
            // this pixmap. So we need to replace the pixmap's existing data with a new
            // one which is created with the correct depth:

#ifndef QT_NO_XRENDER
            if (configDepth == 32) {
                qWarning("Warning: EGLConfig's depth (32) != pixmap's depth (%d), converting to ARGB32",
                         x11PixmapData->depth());
                x11PixmapData->convertToARGB32(true);
            } else
#endif
            {
                qWarning("Warning: EGLConfig's depth (%d) != pixmap's depth (%d)",
                         configDepth, x11PixmapData->depth());
            }
        }

        QEglProperties surfaceAttribs;

        // If the pixmap can't be bound to a texture, it's pretty useless
        surfaceAttribs.setValue(EGL_TEXTURE_TARGET, EGL_TEXTURE_2D);
        if (alphaSize > 0)
            surfaceAttribs.setValue(EGL_TEXTURE_FORMAT, EGL_TEXTURE_RGBA);
        else
            surfaceAttribs.setValue(EGL_TEXTURE_FORMAT, EGL_TEXTURE_RGB);

        EGLSurface surf = eglCreatePixmapSurface(QEgl::display(), config,
                                                 (EGLNativePixmapType) x11PixmapData->handle(),
                                                 surfaceAttribs.properties());
        x11PixmapData->gl_surface = (void*)surf;
        QImagePixmapCleanupHooks::enableCleanupHooks(x11PixmapData);
        return surf;
    }

    return EGL_NO_SURFACE;
}
示例#25
0
文件: mikey1.1.c 项目: 10crimes/code
  int main (void)
  {
    int i;
  
    int allocateOK;
  
    ximg = NULL;
  
  	
    d = XOpenDisplay (NULL);
  
    if (!d)
      fputs ("Couldn't open display\n", stderr), exit (1);
  
    screen = DefaultScreen (d);
    gc = DefaultGC (d, screen);
  
    /* Find a visual */
  
    vis.screen = screen;
    vlist = XGetVisualInfo (d, VisualScreenMask, &vis, &match);
  
    if (!vlist)
      fputs ("No matched visuals\n", stderr), exit (1);
  
    vis = vlist[0];
    XFree (vlist);
		
  	// That's not a fair comparison colormap_size is depth in bits!
    // if (vis.colormap_size < COLORS)
      // printf("Colormap is too small: %i.\n",vis.colormap_size); // , exit (1);
		printf("Colour depth: %i\n",vis.colormap_size);
  
    win = XCreateSimpleWindow (d, DefaultRootWindow (d),
			       0, 0, WIN_W, WIN_H, 0,
			       WhitePixel (d, screen), BlackPixel (d, screen));
  
	  int xclass=get_xvisinfo_class(vis);
		// printf("class = %i\n",xclass);
	  stylee = ( vis.depth > 8 ? styleeTrueColor : styleePrivate );
	  // printf("stylee=%i\n",stylee);
  
    if ( get_xvisinfo_class(vis) % 2 == 1) {	/* The odd numbers can redefine colors */
  
			  // printf("%i\n",get_xvisinfo_class(vis));
	  	
      colormap = DefaultColormap (d, screen);
		  Visual *defaultVisual=DefaultVisual(d,screen);
	  	
      /* Allocate cells */
      allocateOK = (XAllocColorCells (d, colormap, 1,
							      NULL, 0, color, COLORS) != 0);

			// printf("Allocated OK? %i\n",allocateOK);
			
      if (allocateOK) {
  
			  // printf("Allocated OK\n");
        // This doesn't work for installed colormap!
  
        /* Modify the colorcells */
        for (i = 0; i < COLORS; i++)
				  xrgb[i].pixel = color[i];
  
        XStoreColors (d, colormap, xrgb, COLORS);
  
		  } else {

			  colormap = XCreateColormap(d,win,defaultVisual,AllocNone);
		  	
    	  // redocolors();
					  	
      }
  
		  // black = XBlackPixel(d,screen);
		  // white = XWhitePixel(d,screen);
  
    } else if ( get_xvisinfo_class(vis) == TrueColor) {
      colormap = DefaultColormap (d, screen);
					  // printf("TrueColor %i = %i\n",xclass,TrueColor);
      /* This will lookup the color and sets the xrgb[i].pixel value */
      // for (i = 0; i < COLORS; i++)
        // XAllocColor (d, colormap, &xrgb[i]);
    } else
      fprintf (stderr, "Not content with visual class %d.\n",
	       get_xvisinfo_class(vis) ), exit (1);
  
    /* Find out if MITSHM is supported and useable */
    printf ("MITSHM: ");
  
    if (XShmQueryVersion (d, &mitshm_major_code,
			  &mitshm_minor_code, &shared_pixmaps)) {
      int (*handler) (Display *, XErrorEvent *);
      ximg = XShmCreateImage (d, vis.visual,
			     vis.depth, XShmPixmapFormat (d),
			     NULL, &shminfo, WIN_W, WIN_H);
      shminfo.shmid = shmget (IPC_PRIVATE,
			      ximg->bytes_per_line * ximg->height,
			      IPC_CREAT | 0777);
      shminfo.shmaddr = (char *)shmat (shminfo.shmid, 0, 0);
		  ximg->data = (char *)shminfo.shmaddr;
  
      handler = XSetErrorHandler (mitshm_handler);
      XShmAttach (d, &shminfo);	/* Tell the server to attach */
      XSync (d, 0);
      XSetErrorHandler (handler);
  
      shmctl (shminfo.shmid, IPC_RMID, 0);
      /* Mark this shm segment for deletion at once. The segment will
       * automatically become released when both the server and this
       * client have detached from it.
       * (Process termination automagically detach shm segments) */
  
      if (!can_use_mitshm) {
        shmdt (shminfo.shmaddr);
        ximg = NULL;
      }
    }
  
    if (ximg == NULL) {
      can_use_mitshm = 0;
      /* XInitImage(ximg); */
      ximg = XCreateImage (d, vis.visual, vis.depth, ZPixmap,
			  0, (char *)malloc (WIN_W * WIN_H), WIN_W, WIN_H, 8, 0);
    }
  
    if (can_use_mitshm)
      printf ("YES!\n");
    else
      printf ("NO, using fallback instead.\n");
  
    // DrawFractal (ximg,xrgb);
  
    XSelectInput (d, win, ButtonPressMask | ExposureMask);
    XMapWindow (d, win);
  
  
  
  
    real_main();


  
      // XNextEvent (d, &ev);
      // switch (ev.type) {
      // case ButtonPress:
        // should_quit = 1;
        // break;
      // case Expose:
        // if (can_use_mitshm)
				  // XShmPutImage (d, win, gc, img, 0, 0, 0, 0, WIN_W, WIN_H, True);
        // else
				  // XPutImage (d, win, gc, img, 0, 0, 0, 0, WIN_W, WIN_H);
        // break;
      // default:
			  // break;
      // }
  
  
  
    if (get_xvisinfo_class(vis) % 2 == 1 || get_xvisinfo_class(vis) == TrueColor) {
      unsigned long color[COLORS];
  
      if (allocateOK) {
        for (i = 0; i < COLORS; i++)
				  color[i] = xrgb[i].pixel;
        XFreeColors (d, colormap, color, COLORS, 0);
      }				/* Allocated colors freed */
    } else {
      XUninstallColormap (d, colormap);
    }
  
    if (can_use_mitshm) {
      XShmDetach (d, &shminfo);	/* Server detached */
      XDestroyImage (ximg);	/* Image struct freed */
      shmdt (shminfo.shmaddr);	/* We're detached */
    } else
      XDestroyImage (ximg);	/* Image struct freed */
  
    XDestroyWindow (d, win);	/* Window removed */
    XCloseDisplay (d);		/* Display disconnected */
  
    /* So you can see how your computer compares to your friend's */
    getrusage (RUSAGE_SELF, &resource_utilization);
		float seconds=(float)resource_utilization.ru_utime.tv_sec
						     +(float)resource_utilization.ru_utime.tv_usec*0.000000001;
		printf("CPU seconds per frame: %f\n",seconds/(float)frameno);
    // printf ("CPU seconds consumed: %ds and %dµs\n",
	    // (int) resource_utilization.ru_utime.tv_sec,
	    // (int) resource_utilization.ru_utime.tv_usec);
  
    return 0;
  }
示例#26
0
static bool gfx_ctx_xegl_set_video_mode(void *data,
      video_frame_info_t *video_info,
      unsigned width, unsigned height,
      bool fullscreen)
{
   XEvent event;
   EGLint egl_attribs[16];
   EGLint vid, num_visuals;
   EGLint *attr             = NULL;
   bool true_full           = false;
   int x_off                = 0;
   int y_off                = 0;
   XVisualInfo temp         = {0};
   XSetWindowAttributes swa = {0};
   XVisualInfo *vi          = NULL;
   char *wm_name            = NULL;
   xegl_ctx_data_t *xegl    = (xegl_ctx_data_t*)data;
   settings_t *settings     = config_get_ptr();

   int (*old_handler)(Display*, XErrorEvent*) = NULL;

   frontend_driver_install_signal_handler();

   attr = egl_attribs;
   attr = xegl_fill_attribs(xegl, attr);

#ifdef HAVE_EGL
   if (!egl_get_native_visual_id(&xegl->egl, &vid))
      goto error;
#endif

   temp.visualid = vid;

   vi = XGetVisualInfo(g_x11_dpy, VisualIDMask, &temp, &num_visuals);
   if (!vi)
      goto error;

   swa.colormap = g_x11_cmap = XCreateColormap(
         g_x11_dpy, RootWindow(g_x11_dpy, vi->screen),
         vi->visual, AllocNone);
   swa.event_mask = StructureNotifyMask | KeyPressMask |
      ButtonPressMask | ButtonReleaseMask | KeyReleaseMask;
   swa.override_redirect = False;

   if (fullscreen && !video_info->windowed_fullscreen)
   {
      if (x11_enter_fullscreen(video_info, g_x11_dpy, width, height))
      {
         xegl->should_reset_mode = true;
         true_full = true;
      }
      else
         RARCH_ERR("[X/EGL]: Entering true fullscreen failed. Will attempt windowed mode.\n");
   }

   wm_name = x11_get_wm_name(g_x11_dpy);
   if (wm_name)
   {
      RARCH_LOG("[X/EGL]: Window manager is %s.\n", wm_name);

      if (true_full && strcasestr(wm_name, "xfwm"))
      {
         RARCH_LOG("[X/EGL]: Using override-redirect workaround.\n");
         swa.override_redirect = True;
      }
      free(wm_name);
   }
   if (!x11_has_net_wm_fullscreen(g_x11_dpy) && true_full)
      swa.override_redirect = True;

   if (video_info->monitor_index)
      g_x11_screen = video_info->monitor_index - 1;

#ifdef HAVE_XINERAMA
   if (fullscreen || g_x11_screen != 0)
   {
      unsigned new_width  = width;
      unsigned new_height = height;

      if (xinerama_get_coord(g_x11_dpy, g_x11_screen,
               &x_off, &y_off, &new_width, &new_height))
         RARCH_LOG("[X/EGL]: Using Xinerama on screen #%u.\n", g_x11_screen);
      else
         RARCH_LOG("[X/EGL]: Xinerama is not active on screen.\n");

      if (fullscreen)
      {
         width  = new_width;
         height = new_height;
      }
   }
#endif

   RARCH_LOG("[X/EGL]: X = %d, Y = %d, W = %u, H = %u.\n",
         x_off, y_off, width, height);

   g_x11_win = XCreateWindow(g_x11_dpy, RootWindow(g_x11_dpy, vi->screen),
         x_off, y_off, width, height, 0,
         vi->depth, InputOutput, vi->visual,
         CWBorderPixel | CWColormap | CWEventMask | CWOverrideRedirect,
         &swa);
   XSetWindowBackground(g_x11_dpy, g_x11_win, 0);

   if (fullscreen && settings && settings->bools.video_disable_composition)
   {
      uint32_t value                = 1;
      Atom cardinal                 = XInternAtom(g_x11_dpy, "CARDINAL", False);
      Atom net_wm_bypass_compositor = XInternAtom(g_x11_dpy, "_NET_WM_BYPASS_COMPOSITOR", False);

      RARCH_LOG("[X/EGL]: Requesting compositor bypass.\n");
      XChangeProperty(g_x11_dpy, g_x11_win, net_wm_bypass_compositor, cardinal, 32, PropModeReplace, (const unsigned char*)&value, 1);
   }

   if (!egl_create_context(&xegl->egl, (attr != egl_attribs) ? egl_attribs : NULL))
   {
      egl_report_error();
      goto error;
   }

   if (!egl_create_surface(&xegl->egl, (void*)g_x11_win))
      goto error;

   x11_set_window_attr(g_x11_dpy, g_x11_win);
   x11_update_title(NULL, video_info);

   if (fullscreen)
      x11_show_mouse(g_x11_dpy, g_x11_win, false);

   if (true_full)
   {
      RARCH_LOG("[X/EGL]: Using true fullscreen.\n");
      XMapRaised(g_x11_dpy, g_x11_win);
      x11_set_net_wm_fullscreen(g_x11_dpy, g_x11_win);
   }
   else if (fullscreen)
   {
      /* We attempted true fullscreen, but failed.
       * Attempt using windowed fullscreen. */
      XMapRaised(g_x11_dpy, g_x11_win);
      RARCH_LOG("[X/EGL]: Using windowed fullscreen.\n");

      /* We have to move the window to the screen we
       * want to go fullscreen on first.
       * x_off and y_off usually get ignored in XCreateWindow().
       */
      x11_move_window(g_x11_dpy, g_x11_win, x_off, y_off, width, height);
      x11_set_net_wm_fullscreen(g_x11_dpy, g_x11_win);
   }
   else
   {
      XMapWindow(g_x11_dpy, g_x11_win);

      /* If we want to map the window on a different screen,
       * we'll have to do it by force.
       *
       * Otherwise, we should try to let the window manager sort it out.
       * x_off and y_off usually get ignored in XCreateWindow().
       */
      if (g_x11_screen)
         x11_move_window(g_x11_dpy, g_x11_win, x_off, y_off, width, height);
   }

   x11_event_queue_check(&event);
   x11_install_quit_atom();

#ifdef HAVE_EGL
   gfx_ctx_xegl_set_swap_interval(&xegl->egl, xegl->egl.interval);
#endif

   /* This can blow up on some drivers. It's not fatal,
    * so override errors for this call.
    */
   old_handler = XSetErrorHandler(x_nul_handler);
   XSetInputFocus(g_x11_dpy, g_x11_win, RevertToNone, CurrentTime);
   XSync(g_x11_dpy, False);
   XSetErrorHandler(old_handler);

   XFree(vi);
   g_egl_inited = true;

   if (!x11_input_ctx_new(true_full))
      goto error;

   return true;

error:
   if (vi)
      XFree(vi);

   gfx_ctx_xegl_destroy(data);
   return false;
}
示例#27
0
static Bool
make_x_window(struct app_data *data, const char *name,
              int x, int y, int width, int height)
{
   static const EGLint attribs[] = {
      EGL_RED_SIZE, 1,
      EGL_GREEN_SIZE, 1,
      EGL_BLUE_SIZE, 1,
      EGL_DEPTH_SIZE, 1,
      EGL_RENDERABLE_TYPE, EGL_OPENGL_ES_BIT,
      EGL_NONE
   };
   static const EGLint ctx_attribs[] = {
      EGL_CONTEXT_CLIENT_VERSION, 1,
      EGL_NONE
   };
   int scrnum;
   XSetWindowAttributes attr;
   unsigned long mask;
   Window root;
   Window win;
   XVisualInfo *visInfo, visTemplate;
   int num_visuals;
   EGLConfig config;
   EGLint num_configs;
   EGLint vid;

   scrnum = DefaultScreen( data->xdpy );
   root = RootWindow( data->xdpy, scrnum );

   if (!eglChooseConfig( data->dpy, attribs, &config, 1, &num_configs)) {
      printf("Error: couldn't get an EGL visual config\n");
      exit(1);
   }

   assert(config);
   assert(num_configs > 0);

   if (!eglGetConfigAttrib(data->dpy, config, EGL_NATIVE_VISUAL_ID, &vid)) {
      printf("Error: eglGetConfigAttrib() failed\n");
      exit(1);
   }

   /* The X window visual must match the EGL config */
   visTemplate.visualid = vid;
   visInfo = XGetVisualInfo(data->xdpy, VisualIDMask, &visTemplate, &num_visuals);
   if (!visInfo) {
      printf("Error: couldn't get X visual\n");
      exit(1);
   }

   /* window attributes */
   attr.background_pixel = 0;
   attr.border_pixel = 0;
   attr.colormap = XCreateColormap( data->xdpy, root, visInfo->visual, AllocNone);
   attr.event_mask = StructureNotifyMask | ExposureMask |
                     KeyPressMask | ButtonPressMask | ButtonMotionMask;
   mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask;

   win = XCreateWindow( data->xdpy, root, 0, 0, width * 2, height,
		        0, visInfo->depth, InputOutput,
		        visInfo->visual, mask, &attr );

   /* set hints and properties */
   {
      XSizeHints sizehints;
      sizehints.x = x;
      sizehints.y = y;
      sizehints.width  = width;
      sizehints.height = height;
      sizehints.flags = USSize | USPosition;
      XSetNormalHints(data->xdpy, win, &sizehints);
      XSetStandardProperties(data->xdpy, win, name, name,
                              None, (char **)NULL, 0, &sizehints);
   }

   data->canvas = win;

   attr.event_mask = 0x0;
   win = XCreateWindow( data->xdpy, win, width, 0, width, height,
		        0, visInfo->depth, InputOutput,
		        visInfo->visual, mask, &attr );
   data->cube = win;

   eglBindAPI(EGL_OPENGL_ES_API);

   data->ctx = eglCreateContext(data->dpy, config, EGL_NO_CONTEXT, ctx_attribs );
   if (!data->ctx) {
      printf("Error: eglCreateContext failed\n");
      exit(1);
   }

   data->surf = eglCreateWindowSurface(data->dpy, config, data->cube, NULL);
   if (!data->surf) {
      printf("Error: eglCreateWindowSurface failed\n");
      exit(1);
   }

   XFree(visInfo);

   return (data->canvas && data->cube && data->ctx && data->surf);
}
示例#28
0
static XVisualInfo*
getVisual(PuglView* view)
{
	PuglInternals* const impl = view->impl;
	XVisualInfo*         vi   = NULL;

#ifdef PUGL_HAVE_GL
	if (view->ctx_type == PUGL_GL) {
		/**
		  Attributes for single-buffered RGBA with at least
		  4 bits per color and a 16 bit depth buffer.
		*/
		int attrListSgl[] = {
			GLX_RGBA,
			GLX_RED_SIZE,        4,
			GLX_GREEN_SIZE,      4,
			GLX_BLUE_SIZE,       4,
			GLX_DEPTH_SIZE,      16,
			GLX_ARB_multisample, 1,
			None
		};

		/**
		  Attributes for double-buffered RGBA with at least
		  4 bits per color and a 16 bit depth buffer.
		*/
		int attrListDbl[] = {
			GLX_RGBA,
			GLX_DOUBLEBUFFER,
			GLX_RED_SIZE,        4,
			GLX_GREEN_SIZE,      4,
			GLX_BLUE_SIZE,       4,
			GLX_DEPTH_SIZE,      16,
			GLX_ARB_multisample, 1,
			None
		};

		/**
		  Attributes for double-buffered RGBA with multi-sampling
		  (antialiasing)
		*/
		int attrListDblMS[] = {
			GLX_RGBA,
			GLX_DOUBLEBUFFER,
			GLX_RED_SIZE,       4,
			GLX_GREEN_SIZE,     4,
			GLX_BLUE_SIZE,      4,
			GLX_ALPHA_SIZE,     4,
			GLX_DEPTH_SIZE,     16,
			GLX_SAMPLE_BUFFERS, 1,
			GLX_SAMPLES,        4,
			None
		};

		impl->doubleBuffered = True;

		vi = glXChooseVisual(impl->display, impl->screen, attrListDblMS);

		if (vi == NULL) {
			vi = glXChooseVisual(impl->display, impl->screen, attrListDbl);
			PUGL_LOG("multisampling (antialiasing) is not available\n");
		}

		if (vi == NULL) {
			vi = glXChooseVisual(impl->display, impl->screen, attrListSgl);
			impl->doubleBuffered = False;
			PUGL_LOG("singlebuffered rendering will be used, no doublebuffering available\n");
		}
	}
#endif
#ifdef PUGL_HAVE_CAIRO
	if (view->ctx_type == PUGL_CAIRO) {
		XVisualInfo pat;
		int         n;
		pat.screen = impl->screen;
		vi         = XGetVisualInfo(impl->display, VisualScreenMask, &pat, &n);
	}
#endif

	return vi;
}
示例#29
0
void GlxContext::createContext(GlxContext* shared)
{
    // Get a working copy of the context settings
    ContextSettings settings = m_settings;

    XVisualInfo* visualInfo = NULL;

    if (m_pbuffer)
    {
        unsigned int fbConfigId = 0;

        glXQueryDrawable(m_display, m_pbuffer, GLX_FBCONFIG_ID, &fbConfigId);

        int attributes[] =
        {
            GLX_FBCONFIG_ID, static_cast<int>(fbConfigId),
            0,               0
        };

        int count = 0;
        GLXFBConfig* fbconfig = glXChooseFBConfig(m_display, DefaultScreen(m_display), attributes, &count);

        if (count == 1)
            visualInfo = glXGetVisualFromFBConfig(m_display, *fbconfig);

        if (fbconfig)
            XFree(fbconfig);
    }
    else
    {
        // Retrieve the attributes of the target window
        XWindowAttributes windowAttributes;
        if (XGetWindowAttributes(m_display, m_window, &windowAttributes) == 0)
        {
            err() << "Failed to get the window attributes" << std::endl;
            return;
        }

        // Get its visuals
        XVisualInfo tpl;
        tpl.screen   = DefaultScreen(m_display);
        tpl.visualid = XVisualIDFromVisual(windowAttributes.visual);
        int nbVisuals = 0;
        visualInfo = XGetVisualInfo(m_display, VisualIDMask | VisualScreenMask, &tpl, &nbVisuals);
    }

    if (!visualInfo)
    {
        err() << "Failed to get visual info" << std::endl;
        return;
    }

    // Get the context to share display lists with
    GLXContext toShare = shared ? shared->m_context : NULL;

    // There are no GLX versions prior to 1.0
    int major = 0;
    int minor = 0;

    if (!glXQueryVersion(m_display, &major, &minor))
        err() << "Failed to query GLX version, limited to legacy context creation" << std::endl;

    // Check if glXCreateContextAttribsARB is available (requires GLX 1.3 or greater)
    bool hasCreateContextArb = (sfglx_ext_ARB_create_context == sfglx_LOAD_SUCCEEDED) && ((major > 1) || (minor >= 3));

    // Create the OpenGL context -- first try using glXCreateContextAttribsARB
    if (hasCreateContextArb)
    {
        // Get a GLXFBConfig that matches the window's visual, for glXCreateContextAttribsARB
        GLXFBConfig* config = NULL;

        // We don't supply attributes to match against, since
        // the visual we are matching against was already
        // deemed suitable in selectBestVisual()
        int nbConfigs = 0;
        GLXFBConfig* configs = glXChooseFBConfig(m_display, DefaultScreen(m_display), NULL, &nbConfigs);

        for (int i = 0; configs && (i < nbConfigs); ++i)
        {
            XVisualInfo* visual = glXGetVisualFromFBConfig(m_display, configs[i]);

            if (!visual)
                continue;

            if (visual->visualid == visualInfo->visualid)
            {
                config = &configs[i];
                break;
            }
        }

        if (!config)
            err() << "Failed to get GLXFBConfig which corresponds to the window's visual" << std::endl;

        while (config && !m_context && m_settings.majorVersion)
        {
            std::vector<int> attributes;

            // Check if the user requested a specific context version (anything > 1.1)
            if ((m_settings.majorVersion > 1) || ((m_settings.majorVersion == 1) && (m_settings.minorVersion > 1)))
            {
                attributes.push_back(GLX_CONTEXT_MAJOR_VERSION_ARB);
                attributes.push_back(m_settings.majorVersion);
                attributes.push_back(GLX_CONTEXT_MINOR_VERSION_ARB);
                attributes.push_back(m_settings.minorVersion);
            }

            // Check if setting the profile is supported
            if (sfglx_ext_ARB_create_context_profile == sfglx_LOAD_SUCCEEDED)
            {
                int profile = (m_settings.attributeFlags & ContextSettings::Core) ? GLX_CONTEXT_CORE_PROFILE_BIT_ARB : GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB;
                int debug = (m_settings.attributeFlags & ContextSettings::Debug) ? GLX_CONTEXT_DEBUG_BIT_ARB : 0;

                attributes.push_back(GLX_CONTEXT_PROFILE_MASK_ARB);
                attributes.push_back(profile);
                attributes.push_back(GLX_CONTEXT_FLAGS_ARB);
                attributes.push_back(debug);
            }
            else
            {
                if ((m_settings.attributeFlags & ContextSettings::Core) || (m_settings.attributeFlags & ContextSettings::Debug))
                    err() << "Selecting a profile during context creation is not supported,"
                          << "disabling comptibility and debug" << std::endl;

                m_settings.attributeFlags = ContextSettings::Default;
            }

            // Append the terminating 0
            attributes.push_back(0);
            attributes.push_back(0);

            // RAII GLX error handler (we simply ignore errors here)
            // On an error, glXCreateContextAttribsARB will return 0 anyway
            GlxErrorHandler handler(m_display);

            // Create the context
            m_context = glXCreateContextAttribsARB(m_display, *config, toShare, true, &attributes[0]);

            if (!m_context)
            {
                // If we couldn't create the context, first try disabling flags,
                // then lower the version number and try again -- stop at 0.0
                // Invalid version numbers will be generated by this algorithm (like 3.9), but we really don't care
                if (m_settings.attributeFlags != ContextSettings::Default)
                {
                    m_settings.attributeFlags = ContextSettings::Default;
                }
                else if (m_settings.minorVersion > 0)
                {
                    // If the minor version is not 0, we decrease it and try again
                    m_settings.minorVersion--;

                    m_settings.attributeFlags = settings.attributeFlags;
                }
                else
                {
                    // If the minor version is 0, we decrease the major version
                    m_settings.majorVersion--;
                    m_settings.minorVersion = 9;

                    m_settings.attributeFlags = settings.attributeFlags;
                }
            }
        }

        if (configs)
            XFree(configs);
    }

    // If glXCreateContextAttribsARB failed, use glXCreateContext
    if (!m_context)
    {
        // set the context version to 2.1 (arbitrary) and disable flags
        m_settings.majorVersion = 2;
        m_settings.minorVersion = 1;
        m_settings.attributeFlags = ContextSettings::Default;

#if defined(GLX_DEBUGGING)
    GlxErrorHandler handler(m_display);
#endif

        // Create the context, using the target window's visual
        m_context = glXCreateContext(m_display, visualInfo, toShare, true);

#if defined(GLX_DEBUGGING)
    if (glxErrorOccurred)
        err() << "GLX error in GlxContext::createContext()" << std::endl;
#endif
    }

    if (!m_context)
        err() << "Failed to create an OpenGL context for this window" << std::endl;

    // Free the visual info
    XFree(visualInfo);
}
示例#30
0
gboolean gst_imx_egl_viv_sink_egl_platform_init_window(GstImxEglVivSinkEGLPlatform *platform, guintptr window_handle, gboolean event_handling, GstVideoInfo *video_info, gboolean fullscreen, gint x_coord, gint y_coord, guint width, guint height, gboolean borderless)
{
	EGLint num_configs;
	EGLConfig config;
	Window x11_window;

	Display *x11_display = (Display *)(platform->native_display);

	static EGLint const eglconfig_attribs[] =
	{
		EGL_RED_SIZE, 1,
		EGL_GREEN_SIZE, 1,
		EGL_BLUE_SIZE, 1,
		EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
		EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
		EGL_NONE
	};

	static EGLint const ctx_attribs[] =
	{
		EGL_CONTEXT_CLIENT_VERSION, 2,
		EGL_NONE
	};

	if (!eglChooseConfig(platform->egl_display, eglconfig_attribs, &config, 1, &num_configs))
	{
		GST_ERROR("eglChooseConfig failed: %s", gst_imx_egl_viv_sink_egl_platform_get_last_error_string());
		return FALSE;
	}

	EGL_PLATFORM_LOCK(platform);

	{
		EGLint native_visual_id;
		XVisualInfo visual_info_template;
		XVisualInfo *visual_info;
		int num_matching_visuals;
		XSetWindowAttributes attr;
		int screen_num;
		Window root_window;
		Atom net_wm_state_atom, net_wm_state_fullscreen_atom;
		guint chosen_width, chosen_height;

		GST_INFO("Creating new X11 window with EGL context (parent window: %" G_GUINTPTR_FORMAT ")", window_handle);

		if (!eglGetConfigAttrib(platform->egl_display, config, EGL_NATIVE_VISUAL_ID, &native_visual_id))
		{
			GST_ERROR("eglGetConfigAttrib failed: %s", gst_imx_egl_viv_sink_egl_platform_get_last_error_string());
			EGL_PLATFORM_UNLOCK(platform);
			return FALSE;
		}

		screen_num = DefaultScreen(x11_display);
		root_window = RootWindow(x11_display, screen_num);

		memset(&visual_info_template, 0, sizeof(visual_info_template));
		visual_info_template.visualid = native_visual_id;

		visual_info = XGetVisualInfo(x11_display, VisualIDMask, &visual_info_template, &num_matching_visuals);
		if (visual_info == NULL)
		{
			GST_ERROR("Could not get visual info for native visual ID %d", native_visual_id);
			EGL_PLATFORM_UNLOCK(platform);
			return FALSE;
		}

		memset(&attr, 0, sizeof(attr));
		attr.background_pixmap = None;
		attr.background_pixel  = BlackPixel(x11_display, screen_num);
		attr.border_pixmap     = CopyFromParent;
		attr.border_pixel      = BlackPixel(x11_display, screen_num);
		attr.backing_store     = NotUseful;
		attr.override_redirect = borderless ? True : False;
		attr.cursor            = None;

		if (window_handle != 0)
		{
			platform->parent_window = (Window)window_handle;
			/* Out of the parent window events, only the structure
			 * notifications are of interest here */
			XSelectInput(x11_display, platform->parent_window, StructureNotifyMask);
		}

		// TODO: xlib error handler

		platform->fixed_window_width = width;
		platform->fixed_window_height = height;

		platform->video_width = GST_VIDEO_INFO_WIDTH(video_info);
		platform->video_height = GST_VIDEO_INFO_HEIGHT(video_info);

		platform->fullscreen = fullscreen;

		/* If either no fixed size is set, or fullscreen is requested, use the video frame size
		 * In the fullscreen case, the size is actually irrelevant, since it will be overwritten
		 * with the screen size. But passing zero for the width/height values is invalid, the
		 * video frame size is used. */
		chosen_width = ((width == 0) || fullscreen) ? platform->video_width : width;
		chosen_height = ((height == 0) || fullscreen) ? platform->video_height : height;

		/* This video output window can be embedded into other windows, for example inside
		 * media player user interfaces. This is done by making the specified window as
		 * the parent of the video playback window. */
		x11_window = XCreateWindow(
			x11_display, (window_handle != 0) ? platform->parent_window : root_window,
			x_coord,
			y_coord,
			chosen_width,
			chosen_height,
			0, visual_info->depth, InputOutput, visual_info->visual,
			CWBackPixel | CWColormap  | CWBorderPixel | CWBackingStore | CWOverrideRedirect,
			&attr
		);

		platform->native_window = (EGLNativeWindowType)x11_window;

		net_wm_state_atom = XInternAtom(x11_display, "_NET_WM_STATE", True);
		net_wm_state_fullscreen_atom = XInternAtom(x11_display, "_NET_WM_STATE_FULLSCREEN", True);

		platform->wm_delete_atom = XInternAtom(x11_display, "WM_DELETE_WINDOW", True);
		XSetWMProtocols(x11_display, x11_window, &(platform->wm_delete_atom), 1);

		XStoreName(x11_display, x11_window, "eglvivsink window");
		gst_imx_egl_viv_sink_egl_platform_set_event_handling_nolock(platform, event_handling);

		XSizeHints sizehints;
		sizehints.x = 0;
		sizehints.y = 0;
		sizehints.width  = chosen_width;
		sizehints.height = chosen_height;
		sizehints.flags = PPosition | PSize;
		XSetNormalHints(x11_display, x11_window, &sizehints);

		if (fullscreen)
		{
			XChangeProperty(
				x11_display, x11_window,
				net_wm_state_atom,
				XA_ATOM, 32, PropModeReplace,
				(unsigned char*)&net_wm_state_fullscreen_atom, 1
			);
		}

		XClearWindow(x11_display, x11_window);
		XMapRaised(x11_display, x11_window);

		if (fullscreen)
		{
			XEvent event;
			event.type = ClientMessage;
			event.xclient.window = x11_window;
			event.xclient.message_type = net_wm_state_atom;
			event.xclient.format = 32;
			event.xclient.data.l[0] = 1;
			event.xclient.data.l[1] = net_wm_state_fullscreen_atom;
			event.xclient.data.l[3] = 0l;

			XSendEvent(
				x11_display,
				root_window,
				0,
				SubstructureNotifyMask,
				&event
			);
		}

		XSync(x11_display, False);
	}

	eglBindAPI(EGL_OPENGL_ES_API);

	platform->egl_context = eglCreateContext(platform->egl_display, config, EGL_NO_CONTEXT, ctx_attribs);
	if (platform->egl_context == EGL_NO_CONTEXT)
	{
		GST_ERROR("eglCreateContext failed: %s", gst_imx_egl_viv_sink_egl_platform_get_last_error_string());
		EGL_PLATFORM_UNLOCK(platform);
		return FALSE;
	}

	platform->egl_surface = eglCreateWindowSurface(platform->egl_display, config, platform->native_window, NULL);
	if (platform->egl_surface == EGL_NO_SURFACE)
	{
		GST_ERROR("eglCreateWindowSurface failed: %s", gst_imx_egl_viv_sink_egl_platform_get_last_error_string());
		EGL_PLATFORM_UNLOCK(platform);
		return FALSE;
	}

	if (!eglMakeCurrent(platform->egl_display, platform->egl_surface, platform->egl_surface, platform->egl_context))
	{
		GST_ERROR("eglMakeCurrent failed: %s", gst_imx_egl_viv_sink_egl_platform_get_last_error_string());
		EGL_PLATFORM_UNLOCK(platform);
		return FALSE;
	}

	{
		XWindowAttributes window_attr;
		XGetWindowAttributes(x11_display, x11_window, &window_attr);

		if (fullscreen || (platform->fixed_window_width != 0) || (platform->fixed_window_height != 0))
		{
			platform->fixed_window_width = window_attr.width;
			platform->fixed_window_height = window_attr.height;
		}

		if (platform->window_resized_event_cb != NULL)
			platform->window_resized_event_cb(platform, window_attr.width, window_attr.height, platform->user_context);
		else
			glViewport(0, 0, window_attr.width, window_attr.height);
	}

	EGL_PLATFORM_UNLOCK(platform);

	return TRUE;
}