private static X11GLXGraphicsConfiguration chooseGraphicsConfigurationXVisual(
      GLCapabilitiesImmutable capsChosen,
      GLCapabilitiesImmutable capsReq,
      GLCapabilitiesChooser chooser,
      X11GraphicsScreen x11Screen) {
    if (chooser == null) {
      chooser = new DefaultGLCapabilitiesChooser();
    }

    GLProfile glProfile = capsChosen.getGLProfile();
    final int winattrmask =
        GLGraphicsConfigurationUtil.getWinAttributeBits(
            capsChosen.isOnscreen(), false /* pbuffer */);
    ArrayList availableCaps = new ArrayList();
    int recommendedIndex = -1;

    AbstractGraphicsDevice absDevice = x11Screen.getDevice();
    long display = absDevice.getHandle();
    int screen = x11Screen.getIndex();

    final X11GLXDrawableFactory factory =
        (X11GLXDrawableFactory) GLDrawableFactory.getDesktopFactory();
    final boolean isMultisampleAvailable = factory.isGLXMultisampleAvailable(absDevice);
    int[] attribs =
        X11GLXGraphicsConfiguration.GLCapabilities2AttribList(
            capsChosen, false, isMultisampleAvailable, display, screen);

    // 1st choice: get GLCapabilities based on users GLCapabilities setting recommendedIndex as
    // preferred choice
    XVisualInfo recommendedVis = GLX.glXChooseVisual(display, screen, attribs, 0);
    if (DEBUG) {
      System.err.print("glXChooseVisual recommended ");
      if (recommendedVis == null) {
        System.err.println("null visual");
      } else {
        System.err.println("visual id " + toHexString(recommendedVis.getVisualid()));
      }
    }

    // 2nd choice: get all GLCapabilities available, preferred recommendedIndex might be available
    // if 1st choice was successful
    int[] count = new int[1];
    XVisualInfo template = XVisualInfo.create();
    template.setScreen(screen);
    XVisualInfo[] infos =
        X11Lib.XGetVisualInfo(display, X11Lib.VisualScreenMask, template, count, 0);
    if (infos == null || infos.length < 1) {
      throw new GLException("Error while enumerating available XVisualInfos");
    }

    for (int i = 0; i < infos.length; i++) {
      if (!X11GLXGraphicsConfiguration.XVisualInfo2GLCapabilities(
          availableCaps, glProfile, display, infos[i], winattrmask, isMultisampleAvailable)) {
        if (DEBUG) {
          System.err.println(
              "X11GLXGraphicsConfiguration.chooseGraphicsConfigurationXVisual: XVisual invalid: ("
                  + x11Screen
                  + "): fbcfg: "
                  + toHexString(infos[i].getVisualid()));
        }
      } else {
        // Attempt to find the visual chosenIndex by glXChooseVisual, if not translucent
        if (capsChosen.isBackgroundOpaque()
            && recommendedVis != null
            && recommendedVis.getVisualid() == infos[i].getVisualid()) {
          recommendedIndex = availableCaps.size() - 1;
        }
      }
    }

    int chosenIndex = chooseCapabilities(chooser, capsChosen, availableCaps, recommendedIndex);
    if (0 > chosenIndex) {
      if (DEBUG) {
        System.err.println(
            "X11GLXGraphicsConfiguration.chooseGraphicsConfigurationXVisual: failed, return null");
        Thread.dumpStack();
      }
      return null;
    }
    X11GLCapabilities chosenCaps = (X11GLCapabilities) availableCaps.get(chosenIndex);

    return new X11GLXGraphicsConfiguration(x11Screen, chosenCaps, capsReq, chooser);
  }
Esempio n. 2
0
  /**
   * Create a GLCanvas widget using the attributes described in the GLData object provided.
   *
   * @param parent a composite widget
   * @param style the bitwise OR'ing of widget styles
   * @param data the requested attributes of the GLCanvas
   * @exception IllegalArgumentException
   *     <ul>
   *       <li>ERROR_NULL_ARGUMENT when the data is null
   *       <li>ERROR_UNSUPPORTED_DEPTH when the requested attributes cannot be provided
   *     </ul>
   *     </ul>
   */
  public GLCanvas(Composite parent, int style, GLData data) {
    super(parent, style);
    if (data == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
    int glxAttrib[] = new int[MAX_ATTRIBUTES];
    int pos = 0;
    glxAttrib[pos++] = GLX.GLX_RGBA;
    if (data.doubleBuffer) glxAttrib[pos++] = GLX.GLX_DOUBLEBUFFER;
    if (data.stereo) glxAttrib[pos++] = GLX.GLX_STEREO;
    if (data.redSize > 0) {
      glxAttrib[pos++] = GLX.GLX_RED_SIZE;
      glxAttrib[pos++] = data.redSize;
    }
    if (data.greenSize > 0) {
      glxAttrib[pos++] = GLX.GLX_GREEN_SIZE;
      glxAttrib[pos++] = data.greenSize;
    }
    if (data.blueSize > 0) {
      glxAttrib[pos++] = GLX.GLX_BLUE_SIZE;
      glxAttrib[pos++] = data.blueSize;
    }
    if (data.alphaSize > 0) {
      glxAttrib[pos++] = GLX.GLX_ALPHA_SIZE;
      glxAttrib[pos++] = data.alphaSize;
    }
    if (data.depthSize > 0) {
      glxAttrib[pos++] = GLX.GLX_DEPTH_SIZE;
      glxAttrib[pos++] = data.depthSize;
    }
    if (data.stencilSize > 0) {
      glxAttrib[pos++] = GLX.GLX_STENCIL_SIZE;
      glxAttrib[pos++] = data.stencilSize;
    }
    if (data.accumRedSize > 0) {
      glxAttrib[pos++] = GLX.GLX_ACCUM_RED_SIZE;
      glxAttrib[pos++] = data.accumRedSize;
    }
    if (data.accumGreenSize > 0) {
      glxAttrib[pos++] = GLX.GLX_ACCUM_GREEN_SIZE;
      glxAttrib[pos++] = data.accumGreenSize;
    }
    if (data.accumBlueSize > 0) {
      glxAttrib[pos++] = GLX.GLX_ACCUM_BLUE_SIZE;
      glxAttrib[pos++] = data.accumBlueSize;
    }
    if (data.accumAlphaSize > 0) {
      glxAttrib[pos++] = GLX.GLX_ACCUM_ALPHA_SIZE;
      glxAttrib[pos++] = data.accumAlphaSize;
    }
    if (data.sampleBuffers > 0) {
      glxAttrib[pos++] = GLX.GLX_SAMPLE_BUFFERS;
      glxAttrib[pos++] = data.sampleBuffers;
    }
    if (data.samples > 0) {
      glxAttrib[pos++] = GLX.GLX_SAMPLES;
      glxAttrib[pos++] = data.samples;
    }
    glxAttrib[pos++] = 0;
    OS.gtk_widget_realize(handle);
    int /*long*/ window = OS.GTK_WIDGET_WINDOW(handle);
    int /*long*/ xDisplay = OS.gdk_x11_drawable_get_xdisplay(window);
    int /*long*/ infoPtr = GLX.glXChooseVisual(xDisplay, OS.XDefaultScreen(xDisplay), glxAttrib);
    if (infoPtr == 0) {
      dispose();
      SWT.error(SWT.ERROR_UNSUPPORTED_DEPTH);
    }
    vinfo = new XVisualInfo();
    GLX.memmove(vinfo, infoPtr, XVisualInfo.sizeof);
    OS.XFree(infoPtr);
    int /*long*/ screen = OS.gdk_screen_get_default();
    int /*long*/ gdkvisual = OS.gdk_x11_screen_lookup_visual(screen, vinfo.visualid);
    // FIXME- share lists
    // context = GLX.glXCreateContext (xDisplay, info, share == null ? 0 : share.context, true);
    context = GLX.glXCreateContext(xDisplay, vinfo, 0, true);
    if (context == 0) SWT.error(SWT.ERROR_NO_HANDLES);
    GdkWindowAttr attrs = new GdkWindowAttr();
    attrs.width = 1;
    attrs.height = 1;
    attrs.event_mask =
        OS.GDK_KEY_PRESS_MASK
            | OS.GDK_KEY_RELEASE_MASK
            | OS.GDK_FOCUS_CHANGE_MASK
            | OS.GDK_POINTER_MOTION_MASK
            | OS.GDK_BUTTON_PRESS_MASK
            | OS.GDK_BUTTON_RELEASE_MASK
            | OS.GDK_ENTER_NOTIFY_MASK
            | OS.GDK_LEAVE_NOTIFY_MASK
            | OS.GDK_EXPOSURE_MASK
            | OS.GDK_VISIBILITY_NOTIFY_MASK
            | OS.GDK_POINTER_MOTION_HINT_MASK;
    attrs.window_type = OS.GDK_WINDOW_CHILD;
    attrs.visual = gdkvisual;
    glWindow = OS.gdk_window_new(window, attrs, OS.GDK_WA_VISUAL);
    OS.gdk_window_set_user_data(glWindow, handle);
    if ((style & SWT.NO_BACKGROUND) != 0) OS.gdk_window_set_back_pixmap(window, 0, false);
    xWindow = OS.gdk_x11_drawable_get_xid(glWindow);
    OS.gdk_window_show(glWindow);

    Listener listener =
        new Listener() {
          public void handleEvent(Event event) {
            switch (event.type) {
              case SWT.Paint:
                /**
                 * Bug in MESA. MESA does some nasty sort of polling to try and ensure that their
                 * buffer sizes match the current X state. This state can be updated using
                 * glViewport(). FIXME: There has to be a better way of doing this.
                 */
                int[] viewport = new int[4];
                GLX.glGetIntegerv(GLX.GL_VIEWPORT, viewport);
                GLX.glViewport(viewport[0], viewport[1], viewport[2], viewport[3]);
                break;
              case SWT.Resize:
                Rectangle clientArea = getClientArea();
                OS.gdk_window_move(glWindow, clientArea.x, clientArea.y);
                OS.gdk_window_resize(glWindow, clientArea.width, clientArea.height);
                break;
              case SWT.Dispose:
                int /*long*/ window = OS.GTK_WIDGET_WINDOW(handle);
                int /*long*/ xDisplay = OS.gdk_x11_drawable_get_xdisplay(window);
                if (context != 0) {
                  if (GLX.glXGetCurrentContext() == context) {
                    GLX.glXMakeCurrent(xDisplay, 0, 0);
                  }
                  GLX.glXDestroyContext(xDisplay, context);
                  context = 0;
                }
                if (glWindow != 0) {
                  OS.gdk_window_destroy(glWindow);
                  glWindow = 0;
                }
                break;
            }
          }
        };
    addListener(SWT.Resize, listener);
    addListener(SWT.Paint, listener);
    addListener(SWT.Dispose, listener);
  }