add share_with to make_gsg()

This commit is contained in:
David Rose 2004-02-27 22:12:18 +00:00
parent e6862c11f9
commit a4f08870fa
21 changed files with 195 additions and 29 deletions

View File

@ -77,7 +77,7 @@ get_auto_flip() const {
////////////////////////////////////////////////////////////////////
INLINE PT(GraphicsStateGuardian) GraphicsEngine::
make_gsg(GraphicsPipe *pipe) {
return make_gsg(pipe, get_frame_buffer_properties());
return make_gsg(pipe, get_frame_buffer_properties(), NULL);
}

View File

@ -183,9 +183,10 @@ get_threading_model() const {
// runs one more time.
////////////////////////////////////////////////////////////////////
PT(GraphicsStateGuardian) GraphicsEngine::
make_gsg(GraphicsPipe *pipe, const FrameBufferProperties &properties) {
make_gsg(GraphicsPipe *pipe, const FrameBufferProperties &properties,
GraphicsStateGuardian *share_with) {
// TODO: ask the draw thread to make the GSG.
PT(GraphicsStateGuardian) gsg = pipe->make_gsg(properties);
PT(GraphicsStateGuardian) gsg = pipe->make_gsg(properties, share_with);
if (gsg != (GraphicsStateGuardian *)NULL) {
gsg->_threading_model = get_threading_model();
gsg->_pipe = pipe;

View File

@ -71,7 +71,8 @@ PUBLISHED:
INLINE PT(GraphicsStateGuardian) make_gsg(GraphicsPipe *pipe);
PT(GraphicsStateGuardian) make_gsg(GraphicsPipe *pipe,
const FrameBufferProperties &properties);
const FrameBufferProperties &properties,
GraphicsStateGuardian *share_with);
GraphicsWindow *make_window(GraphicsStateGuardian *gsg, const string &name,
int sort);

View File

@ -124,7 +124,8 @@ make_device(void *scrn) {
// be called in the draw thread for the GSG.
////////////////////////////////////////////////////////////////////
PT(GraphicsStateGuardian) GraphicsPipe::
make_gsg(const FrameBufferProperties &properties) {
make_gsg(const FrameBufferProperties &properties,
GraphicsStateGuardian *share_with) {
display_cat.error()
<< "make_gsg() unimplemented by " << get_type() << "\n";
return NULL;

View File

@ -93,7 +93,8 @@ protected:
// The make_window() and make_gsg() interfaces on GraphicsPipe are
// protected; don't try to call them directly. Instead, use
// the interface on GraphicsEngine to make a new window or gsg.
virtual PT(GraphicsStateGuardian) make_gsg(const FrameBufferProperties &properties);
virtual PT(GraphicsStateGuardian) make_gsg(const FrameBufferProperties &properties,
GraphicsStateGuardian *share_with);
virtual void close_gsg(GraphicsStateGuardian *gsg);
virtual PT(GraphicsWindow) make_window(GraphicsStateGuardian *gsg,
const string &name);

View File

@ -85,7 +85,13 @@ make_window(GraphicsStateGuardian *gsg, const string &name) {
PT(GraphicsStateGuardian) wdxGraphicsPipe7::
make_gsg(const FrameBufferProperties &properties) {
make_gsg(const FrameBufferProperties &properties,
GraphicsStateGuardian *share_with) {
if (share_with != (GraphicsStateGuardian *)NULL) {
wdxdisplay7_cat.error()
<< "wdxGraphicsPipe7 does not presently support sharing texture contexts.\n";
return NULL;
}
// FrameBufferProperties really belongs as part of the window/renderbuffer specification
// put here because of GLX multithreading requirement

View File

@ -34,7 +34,8 @@ public:
virtual string get_interface_name() const;
static PT(GraphicsPipe) pipe_constructor();
virtual PT(GraphicsStateGuardian) make_gsg(const FrameBufferProperties &properties);
virtual PT(GraphicsStateGuardian) make_gsg(const FrameBufferProperties &properties,
GraphicsStateGuardian *share_with);
protected:
virtual PT(GraphicsWindow) make_window(GraphicsStateGuardian *gsg, const string &name);

View File

@ -801,8 +801,13 @@ make_device(void *scrn) {
////////////////////////////////////////////////////////////////////
PT(GraphicsStateGuardian) wdxGraphicsPipe8::
make_gsg(const FrameBufferProperties &properties) {
make_gsg(const FrameBufferProperties &properties,
GraphicsStateGuardian *share_with) {
if (share_with != (GraphicsStateGuardian *)NULL) {
wdxdisplay8_cat.error()
<< "wdxGraphicsPipe8 does not presently support sharing texture contexts.\n";
return NULL;
}
// FrameBufferProperties really belongs as part of the window/renderbuffer specification
// put here because of GLX multithreading requirement

View File

@ -48,7 +48,8 @@ public:
virtual string get_interface_name() const;
static PT(GraphicsPipe) pipe_constructor();
virtual PT(GraphicsStateGuardian) make_gsg(const FrameBufferProperties &properties);
virtual PT(GraphicsStateGuardian) make_gsg(const FrameBufferProperties &properties,
GraphicsStateGuardian *share_with);
virtual PT(GraphicsDevice) make_device(void *scrn);
bool find_best_depth_format(DXScreenData &Display, D3DDISPLAYMODE &TestDisplayMode,

View File

@ -820,8 +820,13 @@ make_device(void *scrn) {
////////////////////////////////////////////////////////////////////
PT(GraphicsStateGuardian) wdxGraphicsPipe9::
make_gsg(const FrameBufferProperties &properties) {
make_gsg(const FrameBufferProperties &properties,
GraphicsStateGuardian *share_with) {
if (share_with != (GraphicsStateGuardian *)NULL) {
wdxdisplay9_cat.error()
<< "wdxGraphicsPipe9 does not presently support sharing texture contexts.\n";
return NULL;
}
// FrameBufferProperties really belongs as part of the window/renderbuffer specification
// put here because of GLX multithreading requirement

View File

@ -48,7 +48,8 @@ public:
virtual string get_interface_name() const;
static PT(GraphicsPipe) pipe_constructor();
virtual PT(GraphicsStateGuardian) make_gsg(const FrameBufferProperties &properties);
virtual PT(GraphicsStateGuardian) make_gsg(const FrameBufferProperties &properties,
GraphicsStateGuardian *share_with);
virtual PT(GraphicsDevice) make_device(void *scrn);
bool find_best_depth_format(DXScreenData &Display, D3DDISPLAYMODE &TestDisplayMode,

View File

@ -161,11 +161,27 @@ pipe_constructor() {
// be called in the draw thread for the GSG.
////////////////////////////////////////////////////////////////////
PT(GraphicsStateGuardian) glxGraphicsPipe::
make_gsg(const FrameBufferProperties &properties) {
make_gsg(const FrameBufferProperties &properties,
GraphicsStateGuardian *share_with) {
if (!_is_valid) {
return NULL;
}
glxGraphicsStateGuardian *share_gsg = NULL;
GLXContext share_context = NULL;
if (share_with != (GraphicsStateGuardian *)NULL) {
if (!share_with->is_exact_type(glxGraphicsStateGuardian::get_class_type())) {
glxdisplay_cat.error()
<< "Cannot share context between glxGraphicsStateGuardian and "
<< share_with->get_type() << "\n";
return NULL;
}
DCAST_INTO_R(share_gsg, share_with, NULL);
share_context = share_gsg->_context;
}
FrameBufferProperties new_properties = properties;
GLXFBConfig fbconfig = choose_fbconfig(new_properties);
if (fbconfig == None) {
@ -174,7 +190,8 @@ make_gsg(const FrameBufferProperties &properties) {
// Attempt to create a GL context.
GLXContext context =
glXCreateNewContext(_display, fbconfig, GLX_RGBA_TYPE, NULL, GL_TRUE);
glXCreateNewContext(_display, fbconfig, GLX_RGBA_TYPE, share_context,
GL_TRUE);
if (context == NULL) {
glxdisplay_cat.error()
<< "Could not create GL context.\n";
@ -183,7 +200,7 @@ make_gsg(const FrameBufferProperties &properties) {
// Now we can make a GSG.
PT(glxGraphicsStateGuardian) gsg =
new glxGraphicsStateGuardian(new_properties, NULL, context, fbconfig,
new glxGraphicsStateGuardian(new_properties, share_gsg, context, fbconfig,
_display, _screen);
return gsg.p();
}

View File

@ -78,7 +78,8 @@ public:
INLINE Atom get_wm_delete_window() const;
protected:
virtual PT(GraphicsStateGuardian) make_gsg(const FrameBufferProperties &properties);
virtual PT(GraphicsStateGuardian) make_gsg(const FrameBufferProperties &properties,
GraphicsStateGuardian *share_with);
virtual PT(GraphicsWindow) make_window(GraphicsStateGuardian *gsg,
const string &name);
virtual PT(GraphicsBuffer) make_buffer(GraphicsStateGuardian *gsg,

View File

@ -80,8 +80,23 @@ pipe_constructor() {
// be called in the draw thread for the GSG.
////////////////////////////////////////////////////////////////////
PT(GraphicsStateGuardian) OsMesaGraphicsPipe::
make_gsg(const FrameBufferProperties &properties) {
return new OSMesaGraphicsStateGuardian(properties);
make_gsg(const FrameBufferProperties &properties,
GraphicsStateGuardian *share_with) {
OSMesaGraphicsStateGuardian *share_gsg = NULL;
if (share_with != (GraphicsStateGuardian *)NULL) {
if (!share_with->is_exact_type(OSMesaGraphicsStateGuardian::get_class_type())) {
mesadisplay_cat.error()
<< "Cannot share context between OSMesaGraphicsStateGuardian and "
<< share_with->get_type() << "\n";
return NULL;
}
DCAST_INTO_R(share_gsg, share_with, NULL);
}
return new OSMesaGraphicsStateGuardian(properties, share_gsg);
}
////////////////////////////////////////////////////////////////////

View File

@ -46,7 +46,8 @@ public:
static PT(GraphicsPipe) pipe_constructor();
protected:
virtual PT(GraphicsStateGuardian) make_gsg(const FrameBufferProperties &properties);
virtual PT(GraphicsStateGuardian) make_gsg(const FrameBufferProperties &properties,
GraphicsStateGuardian *share_with);
virtual PT(GraphicsBuffer) make_buffer(GraphicsStateGuardian *gsg,
const string &name,
int x_size, int y_size, bool want_texture);

View File

@ -26,10 +26,17 @@ TypeHandle OSMesaGraphicsStateGuardian::_type_handle;
// Description:
////////////////////////////////////////////////////////////////////
OSMesaGraphicsStateGuardian::
OSMesaGraphicsStateGuardian(const FrameBufferProperties &properties) :
OSMesaGraphicsStateGuardian(const FrameBufferProperties &properties,
OSMesaGraphicsStateGuardian *share_with) :
MesaGraphicsStateGuardian(properties)
{
_context = OSMesaCreateContext(OSMESA_RGBA, NULL);
OSMesaContext share_context = NULL;
if (share_with != (OSMesaGraphicsStateGuardian *)NULL) {
share_context = share_with->_context;
_prepared_objects = share_with->get_prepared_objects();
}
_context = OSMesaCreateContext(OSMESA_RGBA, share_context);
// I think OSMesa always creates single-buffered contexts. I don't
// see any documentation to this effect, but it seems to be the

View File

@ -29,7 +29,8 @@
////////////////////////////////////////////////////////////////////
class EXPCL_PANDAMESA OSMesaGraphicsStateGuardian : public MesaGraphicsStateGuardian {
public:
OSMesaGraphicsStateGuardian(const FrameBufferProperties &properties);
OSMesaGraphicsStateGuardian(const FrameBufferProperties &properties,
OSMesaGraphicsStateGuardian *share_with);
virtual ~OSMesaGraphicsStateGuardian();
OSMesaContext _context;

View File

@ -81,11 +81,25 @@ pipe_constructor() {
// be called in the draw thread for the GSG.
////////////////////////////////////////////////////////////////////
PT(GraphicsStateGuardian) wglGraphicsPipe::
make_gsg(const FrameBufferProperties &properties) {
make_gsg(const FrameBufferProperties &properties,
GraphicsStateGuardian *share_with) {
if (!_is_valid) {
return NULL;
}
wglGraphicsStateGuardian *share_gsg = NULL;
if (share_with != (GraphicsStateGuardian *)NULL) {
if (!share_with->is_exact_type(wglGraphicsStateGuardian::get_class_type())) {
wgldisplay_cat.error()
<< "Cannot share context between wglGraphicsStateGuardian and "
<< share_with->get_type() << "\n";
return NULL;
}
DCAST_INTO_R(share_gsg, share_with, NULL);
}
// Make a copy of the supplied properties so we can possibly modify
// them to suit our available properties.
FrameBufferProperties new_properties = properties;
@ -109,7 +123,14 @@ make_gsg(const FrameBufferProperties &properties) {
}
PT(wglGraphicsStateGuardian) gsg =
new wglGraphicsStateGuardian(properties, pfnum);
new wglGraphicsStateGuardian(properties, share_gsg, pfnum);
// Ideally, we should be able to detect whether the share_gsg will
// be successful, and return NULL if it won't work. But we can't do
// that yet, because we can't try to actually share the gsg until we
// create the context, for which we need to have a window. That
// means the app will just have to trust it will work; if it doesn't
// work, too bad.
return gsg.p();
}

View File

@ -37,7 +37,8 @@ public:
static PT(GraphicsPipe) pipe_constructor();
protected:
virtual PT(GraphicsStateGuardian) make_gsg(const FrameBufferProperties &properties);
virtual PT(GraphicsStateGuardian) make_gsg(const FrameBufferProperties &properties,
GraphicsStateGuardian *share_with);
virtual PT(GraphicsWindow) make_window(GraphicsStateGuardian *gsg,
const string &name);
virtual PT(GraphicsBuffer) make_buffer(GraphicsStateGuardian *gsg,

View File

@ -28,8 +28,10 @@ TypeHandle wglGraphicsStateGuardian::_type_handle;
////////////////////////////////////////////////////////////////////
wglGraphicsStateGuardian::
wglGraphicsStateGuardian(const FrameBufferProperties &properties,
wglGraphicsStateGuardian *share_with,
int pfnum) :
GLGraphicsStateGuardian(properties),
_share_with(share_with),
_pfnum(pfnum)
{
_made_context = false;
@ -163,4 +165,72 @@ make_context(HDC hdc) {
<< "Could not create GL context.\n";
return;
}
// Now share texture context with the indicated GSG.
if (_share_with != (wglGraphicsStateGuardian *)NULL) {
HGLRC share_context = _share_with->get_share_context();
if (share_context == NULL) {
// Whoops, the target context hasn't yet made its own context.
// In that case, it will share context with us.
_share_with->redirect_share_pool(this);
} else {
if (!wglShareLists(share_context, _context)) {
wgldisplay_cat.error()
<< "Could not share texture contexts between wglGraphicsStateGuardians.\n";
// Too bad we couldn't detect this error sooner. Now there's
// really no way to tell the application it's hosed.
} else {
_prepared_objects = _share_with->get_prepared_objects();
}
}
_share_with = (wglGraphicsStateGuardian *)NULL;
}
}
////////////////////////////////////////////////////////////////////
// Function: wglGraphicsStateGuardian::get_share_context
// Access: Private
// Description: Returns a wgl context handle for the purpose of
// sharing texture context with this GSG. This will
// either be the GSG's own context handle, if it exists
// yet, or the context handle of some other GSG that
// this GSG is planning to share with. If this returns
// NULL, none of the GSG's in this share pool have yet
// created their context.
////////////////////////////////////////////////////////////////////
HGLRC wglGraphicsStateGuardian::
get_share_context() const {
if (_made_context) {
return _context;
}
if (_share_with != (wglGraphicsStateGuardian *)NULL) {
return _share_with->get_share_context();
}
return NULL;
}
////////////////////////////////////////////////////////////////////
// Function: wglGraphicsStateGuardian::redirect_share_pool
// Access: Private
// Description: Directs the GSG (along with all GSG's it is planning
// to share a texture context with) to share texture
// context with the indicated GSG.
//
// This assumes that this GSG's context has not yet been
// created, and neither have any of the GSG's it is
// planning to share texture context with; but the
// graphics context for the indicated GSG has already
// been created.
////////////////////////////////////////////////////////////////////
void wglGraphicsStateGuardian::
redirect_share_pool(wglGraphicsStateGuardian *share_with) {
nassertv(!_made_context);
if (_share_with != (wglGraphicsStateGuardian *)NULL) {
_share_with->redirect_share_pool(share_with);
} else {
_share_with = share_with;
}
}

View File

@ -34,7 +34,9 @@
////////////////////////////////////////////////////////////////////
class wglGraphicsStateGuardian : public GLGraphicsStateGuardian {
public:
wglGraphicsStateGuardian(const FrameBufferProperties &properties, int pfnum);
wglGraphicsStateGuardian(const FrameBufferProperties &properties,
wglGraphicsStateGuardian *share_with,
int pfnum);
virtual ~wglGraphicsStateGuardian();
INLINE int get_pfnum() const;
@ -48,6 +50,13 @@ protected:
private:
void make_context(HDC hdc);
HGLRC get_share_context() const;
void redirect_share_pool(wglGraphicsStateGuardian *share_with);
// We have to save a pointer to the GSG we intend to share texture
// context with, since we don't create our own context in the
// constructor.
PT(wglGraphicsStateGuardian) _share_with;
// All windows that share a particular GL context must also share
// the same pixel format; therefore, we store the pixel format