RFE/Discussion : glCompressedTexImage2D

[quote]I therefore suggest that JOGL should move to a similar scheme.
[/quote]
Rob: thanks for your detailed post. I agree that in many cases an array offset should be able to be supplied. I am sure this is going to come up in the JSR 231/239 expert groups, and I’ll point the EG to this thread so they can see the ongoing discussion.

I also agree that LWJGL’s use of the position of direct buffers to indicate a pointer in to the buffer is a good idea. It avoids the need to slice() the buffers and is an analogue to providing the offset for arrays.

The expert groups (and me personally as well) are not concerned with maintaining backward compatibility to the existing JOGL APIs. The JSR 231/239 APIs will look different in some fundamental ways and the switch to those APIs a good time to make large changes like these.

I’m just watching JSR231 with interest but have little useful to contribute. Some of the participants don’t appear to do very much OpenGL coding though.
LWJGL is fully able to work with multiple contexts and multiple threads. In fact, we could implement JOGL in terms of LWJGL.

Cas :slight_smile:

[quote]LWJGL is fully able to work with multiple contexts and multiple threads.
[/quote]
Can multiple OpenGL contexts be current simultaneously on multiple threads in LWJGL? To be more precise, if you have OpenGL contexts ctxA and ctxB and threads A and B, can thread A have ctxA current at the same time that thread B has ctxB current?

No, LWJGL can’t handle multiple contexts from multiple threads at the same time. However, I hope that other parts of the LWJGL design will be seriously considered in the JSR (the way we handle Buffer position() and limit() and the way we allow (checked) int offsets into VBO/PBOs being two good ideas in my opinion)

  • elias

…LWJGL can’t handle it directly, but then, neither can OpenGL hardware. To use LWJGL in multiple threads with multiple contexts, you synchronize on the GLContext class. As only one thread can actually render with OpenGL at any time this is the most efficient manner of using it. Trying to do otherwise results in absolutely appalling performance.

Cas :slight_smile:

[quote]No, LWJGL can’t handle multiple contexts from multiple threads at the same time. However, I hope that other parts of the LWJGL design will be seriously considered in the JSR (the way we handle Buffer position() and limit() and the way we allow (checked) int offsets into VBO/PBOs being two good ideas in my opinion)
[/quote]
I agree that there are many good ideas in LWJGL and the use of Buffers’ limit() and position() is one in particular that we didn’t think of when originally designing JOGL that are going to come up again in the expert group. The problem I see with passing offsets down into VBO-related methods is that the OpenGL binding then has to know what methods are affected by the VBO specification and provide alternative entry points, which doesn’t seem maintainable to me. There are a lot of gl*Pointer entry points hidden in various extensions.

Are there other elements of LWJGL’s design that you think we should consider? Hiding of most of the GL_INT / GL_FLOAT data types going down to OpenGL? Others?

[quote]…LWJGL can’t handle it directly, but then, neither can OpenGL hardware. To use LWJGL in multiple threads with multiple contexts, you synchronize on the GLContext class. As only one thread can actually render with OpenGL at any time this is the most efficient manner of using it. Trying to do otherwise results in absolutely appalling performance.
[/quote]
I won’t argue with you about the performance issue, at least on most consumer cards; higher-end hardware, in particular that which supports multiple graphics cards, usually performs better. However, the OpenGL specification allows multiple threads to perform OpenGL rendering to multiple contexts simultaneously, so for generality the JSR-231 and 239 specifications must support this, even if it’s discouraged in general use.

Not everyone agrees on this, but I particularly like the way we split up OpenGL into separate classes, one for each "extensions: GL11, GL12, ARBVertexBufferObject and so on.

Also, but LWJGL never allocates objects in normal OpenGL operation (buffer swapping and calling OpenGL functions), to ensure as smooth animation as possible. I’m not sure the JOGL policy in this, but it sure is a nice property.

  • elias

I do wonder that you might be overcomplicating JOGL in an attempt to please everybody and ending pleasing nobody :frowning: How many systems out there are your bog standard 1-or-2 CPU, single consumer class 3D card on an AGP bus, single monitor system versus oddball workstations with multiple graphics cards? I’d say the ratio was something like 99.9999% and to make the entire API cater for the 0.00001% of uses at the expense of a ton of complexity is a bit baffling. After all most of the rest of the Java APIs are a big concession to lowest common denominators, or hacked together slightly inefficiently :wink:

Cas :slight_smile:

[quote]Not everyone agrees on this, but I particularly like the way we split up OpenGL into separate classes, one for each "extensions: GL11, GL12, ARBVertexBufferObject and so on.
[/quote]
I like this too. We’ve considered doing at least the GL11, GL12, etc. split in the expert group; I don’t know whether we reached a firm decision on it. There’s something I don’t understand about the splitting of the extensions in to different classes, though. Frequently an extension will accept not only the tokens it defines, but also many other GL_ constants from either the core or another extension, as a parameter to a certain function. How do you organize the extension classes in this case? As one example, I see you’ve cleverly made e.g. ARBVertexBufferObject and ARBPixelBufferObject extend ARBBufferObject; do you have other examples of this?

Is all of the LWJGL OpenGL interface code handwritten, or do you have any tools that help automate the process?

[quote]Also, but LWJGL never allocates objects in normal OpenGL operation (buffer swapping and calling OpenGL functions), to ensure as smooth animation as possible. I’m not sure the JOGL policy in this, but it sure is a nice property.
[/quote]
JOGL does allocate a few objects during makeCurrent() and free() due to the structure of the glue code that GlueGen makes for the JAWT. It doesn’t allocate anything during the calling of OpenGL routines. One of the members of the expert group, Alex Radeski, has done some profiling of the code and was/is trying to eliminate these object allocations.

[quote]I do wonder that you might be overcomplicating JOGL in an attempt to please everybody and ending pleasing nobody :frowning: How many systems out there are your bog standard 1-or-2 CPU, single consumer class 3D card on an AGP bus, single monitor system versus oddball workstations with multiple graphics cards? I’d say the ratio was something like 99.9999% and to make the entire API cater for the 0.00001% of uses at the expense of a ton of complexity is a bit baffling. After all most of the rest of the Java APIs are a big concession to lowest common denominators, or hacked together slightly inefficiently :wink:
[/quote]
Having multiple OpenGL context support is an absolute requirement for JSR-231. This effectively implies that the OpenGL function calls must be contained in an object and not be static, so that there can be a per-context function pointer table; otherwise you have to do a lookup in thread-local storage per call. That’s one of the few major API design decisions forced by multiple context support. JOGL’s current use of high-level callbacks was done principally for better multithreading safety in most people’s programs when dealing with the AWT. The JSR will still have the high-level callback mechanism, but will also expose the GLContext and makeCurrent/free to the programmer, which can result in simpler code in some situations.

Incidentally, the other requirement of AWT interoperability introduces much more complexity in the implementation than multiple context support. Many OpenGL drivers, especially older ones, aren’t multithread-safe and require some sort of workaround or another to work correctly in an MT environment. The issue of having the window torn out from under you by the AWT while you’re doing OpenGL rendering on another thread is another tricky one. I’m don’t think JOGL handles this 100% correctly yet, and it may become more difficult given the APIs the JSR exposes.

[quote]Frequently an extension will accept not only the tokens it defines, but also many other GL_ constants from either the core or another extension, as a parameter to a certain function. How do you organize the extension classes in this case?
[/quote]
The “contract” is simple; Any constant/function that appears in the New Tokens/New Procedures and Functions of a given extension, will be present in the corresponding LWJGL class. For extensions that use constants (or even functions) of other extensions, a user is responsible for reading the extension spec and knowing which other extensions are involved (and use them accordingly).

[quote]As one example, I see you’ve cleverly made e.g. ARBVertexBufferObject and ARBPixelBufferObject extend ARBBufferObject; do you have other examples of this?
[/quote]
Yes, this is (almost) an exception to the above rule, to avoid code duplication and it’s more natural too. Other examples:

  • ARBProgram => ARBVertexProgram, ARBFragmentProgram
  • NVProgram => NVVertexProgram, NVFragmentProgram

[quote]Is all of the LWJGL OpenGL interface code handwritten, or do you have any tools that help automate the process?
[/quote]
Java-side, yes it is. For C code, we once had a nice tool that auto-generated the functions (signature only, with parameter names, plus some special support for Buffer parameters). After several revisions and changes to how the extensions are initialised, it is so straightforward now that we just do it by hand.

I’m curious as to why you went the instanced GL objects route instead of the static route with a thread local function pointer table. With static GL methods, you can’t ever call the wrong gl function by accidentially caching an GL instance, and you avoid having to pass it around altogether. And you keep the multithreaded properties of the instance objects of course.

I did a quick and dirty test of thread local storage on my linux 1.4.2 JVM, and initial measurements shows that ThreadLocal.get() is quite fast; in fact, it is much faster than a single env->GetDirectBufferAddress() (and probably even more faster than the array pinning equivalent). Using the server vm makes the overhead even smaller.

  • elias

[quote]I’m curious as to why you went the instanced GL objects route instead of the static route with a thread local function pointer table.
[/quote]
There were a few reasons. First, we wanted to support the composable pipeline paradigm introduced by the Magician Java/OpenGL binding. This can be done with static functions, but you end up implementing the GL object wrapping behind the scenes anyway. Second, because of the per-context nature of the function pointer table, we felt it was better to make it explicit to the programmer that they are dealing with a specific drawable’s GL interface.

We can still implement checking of the validity of the GL instances, especially with some of the bookkeeping that now goes on behind the scenes in JOGL. We just have to make sure the GL’s context is current on the thread before dispatching to the function; this could be done in the DebugGL pipeline.

Cas,

[quote] Yeah, maybe I’m just trolling anyway.

Cas
[/quote]
I’m pretty much agnostic on the whole LWJGL vs. JOGL issue - the rendering layer in my apps is a thin layer (only 2 small classes) under the scene graph where all the heavy lifting is done. I can have multiple independent renderers and so far have JOGL and ‘null’ renderers. It’d be easy for me to add support for LWJGL as another renderer if it met all my needs.

When I looked at LWJGL, there were a number of goals/stated targets of the project that just don’t coincide with my goals and requirements - note that this is not a criticism of LWJGL - it’s designed with tight focus with a specific problem domain in mind, and I think it’s a great API for that domain.

The drop-dead issues for me so far with LWJGL are the lack of AWT/Swing integration (I need a subclass of java.awt.Component); I need to be able to render into multiple windows at the same time; I need a version of glBufferDataARB that takes a float[]; and I want to be able to render even when there isn’t hardware acceleration. (I also seriously dislike the static method style of LWJGL, but that’s purely an emotional response :slight_smile: )

I think (hope!) that JOGL is aiming for a wider audience than LWJGL - i.e. that of supporting OpenGL programming in a wider sense and not with such a tight focus on full-screen games.

Note that I’m not trying to suggest that LWJGL be changed to meet my needs - I think that the focus it has is entirely laudable - but that does leave JOGL as my hope for getting these wider needs addressed.

Rob

Ken,

[quote] Rob: thanks for your detailed post. I agree that in many cases an array offset should be able to be supplied. I am sure this is going to come up in the JSR 231/239 expert groups, and I’ll point the EG to this thread so they can see the ongoing discussion.
[/quote]
Thanks for that - you could no doubt tell that the post was deliberately written for a wider audience than just yourself.

Rob