获得无效的抽奖'

时间:2014-05-30 23:56:53

标签: java macos opengl jna

我正在尝试在Mac OSX上使用JNA直接从Java中使用OpenGL(我已经在Windows和Linux上成功完成了)。我通过JOGL源浏览,但他们使用的CALayers我还不明白。我想尽可能简单地使用NSOpenGLView并将其置于AWT Canvas的顶部。我发现NSWindow使用JNA并添加我创建的NSOpenGLView,它似乎工作,除非我调用[nsOpenGLContext setView]或[nsOpenGLView lockFocus]我得到'无效的drawable'错误。我从Rococoa那里学到了如何使用Java中的ObjectiveC。

以下是一些示例代码:

  private static boolean createMac(GL gl, Component c) {
    NSAutoreleasePool pool = new NSAutoreleasePool();
    pool.alloc();
    pool.init();
    gl.nsopenglview = new NSOpenGLView();
    gl.nsopenglview.alloc();
    Pointer ptr = Native.getWindowPointer(findWindow(c));
    NSObject nsComponent = new NSObject();
    nsComponent.obj = ptr;
    Pointer cClass = nsComponent._class();
    NSView view = new NSView();
    view.alloc();
    boolean isView = view.isKindOfClass(cClass);
//    JFLog.log("test=" + isView);
    if (isView) {
      view.dealloc();
      view.obj = ptr;  //do NOT dealloc this (usually NSWindowViewAWT)
      gl.nswindow = view.window();
    } else {
      view.dealloc();
      gl.nswindow = new NSWindow();
      gl.nswindow.obj = ptr;
    }
    NSOpenGLPixelFormat fmt = new NSOpenGLPixelFormat();
    fmt.alloc();
    fmt.initWithAttributes(new int[] {
      NSOpenGLPFAWindow,
//      NSOpenGLPFAAccelerated,  //is not available on my test system
      NSOpenGLPFADoubleBuffer,
      NSOpenGLPFAColorSize,24,
      NSOpenGLPFADepthSize,16,
        0  //zero terminate list
      }
    );
    if (fmt.obj == null) {
      JFLog.log("NSOpenGLPixelFormat initWithAttributes failed");
      return false;
    }
    if (gl.nsopenglview != null) {
      gl.nsopenglview.initWithFrame(new NSRect(c.getBounds()), fmt);
    }

    NSView content = gl.nswindow.contentView();
    JFLog.log("content view=" + content.obj);
    content.addSubview(gl.nsopenglview);
    JFLog.log("layered=" + content.wantsLayer());

    //use created context
    gl.nsopenglcontext = gl.nsopenglview.openGLContext();

    //create some resize/move listeners
    final GL _gl = gl;
    final Component _c = c;
    c.addComponentListener(new ComponentListener() {
      public void componentResized(ComponentEvent e) {
        _gl.nsopenglview.setFrame(new NSRect(_c.getBounds()));
      }
      public void componentMoved(ComponentEvent e) {
        _gl.nsopenglview.setFrame(new NSRect(_c.getBounds()));
      }
      public void componentShown(ComponentEvent e) {}
      public void componentHidden(ComponentEvent e) {}
    });
    if (api == null) {
      api = new GLFuncs();
      gl.glLibrary = NativeLibrary.getInstance("OpenGL");
      try {
        Field fields[] = api.getClass().getFields();
        for(int a=0;a<fields.length;a++) {
          String name = fields[a].getName();
          try {
            fields[a].set(api, gl.glLibrary.getFunction(name));
          } catch (Throwable t) {
            JFLog.log("OpenGL:Warning:Function not found:" + name);
          }
        }
      } catch (Exception e) {
        JFLog.log(e);
      }
    }
    pool.release();
    return true;
  }

我不能在NSOpenGLView中使用drawRect函数,所以我只需要lockFocus,完成后使用gl命令和unlockFocus。但是NSOpenGLContext没有分配视图,并且尝试分配我创建的视图会生成'无效的drawable'。

有什么想法吗?

如果你想要一个完整的工作演示goto http://javaforce.sf.net并下载v7.15.0,在/ jf中运行ant,然后在/ projects / jtest3d中运行,然后执行run.sh(单击GLCanvas测试)。

1 个答案:

答案 0 :(得分:0)

我搞定了!问题出在Rococoa(或者可能是JNA中的一个bug)。他们的NSRect结构没有正确传递给[NSOpenGLView initWithFrame]或[NSWindow initWithContentRect]。如果我直接将4个字段(x,y,width,height)传递给函数而不是Structure本身,那么它就可以工作。我还使用[NSObject performSelectorOnMainThread]来确保我在主线程上执行所有GUI内容。

因此可以使用Java中的纯JNA来使用OpenGL。不需要本机代码。
这应该可以在v7.16的javaforce.sf.net中找到,我将在一段时间内发布。

感谢。