You don't need a new context because you can reuse the same device context of the first one. Btw, you can specify another device context, but depending on your platform you should take care about it (on Windows, device contextes must have the same pixel format), otherwise you could fail to share objects between two contextes
Create both context in the main thread, the second one sharing with the first one. Then, make the first one current on the main thread, while making the other one current on the secondary thread.
Note that you can share with any render context: all sharing contextes "see" the same object by its name, indeed they share an object name space. Two different object name spaces (i.e. two non-sharing contextes) can have defined the same object (i.e. texture object name is 1), but the same name actually points to different object depending on the current context.
Objects created by the secondary thread are visible concurrently and consistently. However, not all objects can be shared across contextes. Keep in mind that sometimes it happens that the driver supports unexpected objects, and other times it happens that driver doesn't support correctly an expected object.
OpenGL is becoming an object oriented language. You can see a certain pattern for creating objects:
- Generate name (GenTextures, GenBuffers)
- Define object (BindTexture, BindBuffer)
- Object existence (IsTexture, IsShader, IsFramebuffer)
- Delete name (and object)
(Note that an object created with Gen routines exists only when they are bound)
Object classes could be
- Display lists
- Texture objects
- Buffer objects
- Shader objects and program objects
- Renderbuffer objects
- Framebuffer objects
- Query objects
- Sync objects
- Transform feedback objects
I would suggest to use a "runtime" test, like the following:
private bool TestSharingObject(RenderContext rContextShare)
{
uint texture = 0;
// rContextShader is a context sharing with this RenderCOntext
this.MakeCurrent(true);
if (Caps.TextureObject.Supported == true) {
// Generate texture name
Gl.GenTextures(1, out texture);
// Ensure existing texture object
Gl.BindTexture(Gl.TEXTURE_2D, texture);
Gl.BindTexture(Gl.TEXTURE_2D, 0);
// Self test
if (Gl.IsTexture(texture) == false)
throw new NotSupportedException();
}
// Make current sharing context
rContextShare.MakeCurrent(true);
return ((texture != 0) && (Gl.IsTexture(texture) == true));
}
Another suggestion would be to run on secondary thread operations that are CPU intensive, and not directly affecting drawing system windows buffers. A good example would be a shader compilation, since the compilation runs on CPU side; keep also in mind that the driver could async your operations, and that OpenGL implementations may pipeline different operations..
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…