From fbca2647f9f4cab8f72b1597ebbfd9dd6430f6ed Mon Sep 17 00:00:00 2001 From: David Rose Date: Mon, 9 Feb 2004 18:47:57 +0000 Subject: [PATCH] add glxGraphicsBuffer --- panda/src/glxdisplay/Sources.pp | 9 +- panda/src/glxdisplay/config_glxdisplay.cxx | 2 + panda/src/glxdisplay/glxGraphicsBuffer.I | 18 ++ panda/src/glxdisplay/glxGraphicsBuffer.cxx | 193 +++++++++++++++++++++ panda/src/glxdisplay/glxGraphicsBuffer.h | 72 ++++++++ panda/src/glxdisplay/glxGraphicsPipe.cxx | 15 ++ panda/src/glxdisplay/glxGraphicsPipe.h | 2 + 7 files changed, 307 insertions(+), 4 deletions(-) create mode 100644 panda/src/glxdisplay/glxGraphicsBuffer.I create mode 100644 panda/src/glxdisplay/glxGraphicsBuffer.cxx create mode 100644 panda/src/glxdisplay/glxGraphicsBuffer.h diff --git a/panda/src/glxdisplay/Sources.pp b/panda/src/glxdisplay/Sources.pp index 32264f9a2a..b7e96306b4 100644 --- a/panda/src/glxdisplay/Sources.pp +++ b/panda/src/glxdisplay/Sources.pp @@ -11,13 +11,14 @@ #define SOURCES \ config_glxdisplay.cxx config_glxdisplay.h \ - glxGraphicsPipe.I glxGraphicsPipe.cxx \ - glxGraphicsPipe.h glxGraphicsWindow.I glxGraphicsWindow.cxx \ + glxGraphicsBuffer.h glxGraphicsBuffer.I glxGraphicsBuffer.cxx \ + glxGraphicsPipe.I glxGraphicsPipe.cxx glxGraphicsPipe.h \ + glxGraphicsWindow.h glxGraphicsWindow.I glxGraphicsWindow.cxx \ glxGraphicsStateGuardian.h glxGraphicsStateGuardian.I \ - glxGraphicsStateGuardian.cxx \ - glxGraphicsWindow.h + glxGraphicsStateGuardian.cxx #define INSTALL_HEADERS \ + glxGraphicsBuffer.I glxGraphicsBuffer.h \ glxGraphicsPipe.I glxGraphicsPipe.h \ glxGraphicsWindow.I glxGraphicsWindow.h diff --git a/panda/src/glxdisplay/config_glxdisplay.cxx b/panda/src/glxdisplay/config_glxdisplay.cxx index be1ddb4098..8f867f623d 100644 --- a/panda/src/glxdisplay/config_glxdisplay.cxx +++ b/panda/src/glxdisplay/config_glxdisplay.cxx @@ -17,6 +17,7 @@ //////////////////////////////////////////////////////////////////// #include "config_glxdisplay.h" +#include "glxGraphicsBuffer.h" #include "glxGraphicsPipe.h" #include "glxGraphicsWindow.h" #include "glxGraphicsStateGuardian.h" @@ -46,6 +47,7 @@ init_libglxdisplay() { } initialized = true; + glxGraphicsBuffer::init_type(); glxGraphicsPipe::init_type(); glxGraphicsWindow::init_type(); glxGraphicsStateGuardian::init_type(); diff --git a/panda/src/glxdisplay/glxGraphicsBuffer.I b/panda/src/glxdisplay/glxGraphicsBuffer.I new file mode 100644 index 0000000000..0388999adb --- /dev/null +++ b/panda/src/glxdisplay/glxGraphicsBuffer.I @@ -0,0 +1,18 @@ +// Filename: glxGraphicsBuffer.I +// Created by: drose (09Feb04) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved +// +// All use of this software is subject to the terms of the Panda 3d +// Software license. You should have received a copy of this license +// along with this source code; you will also find a current copy of +// the license at http://www.panda3d.org/license.txt . +// +// To contact the maintainers of this program write to +// panda3d@yahoogroups.com . +// +//////////////////////////////////////////////////////////////////// + diff --git a/panda/src/glxdisplay/glxGraphicsBuffer.cxx b/panda/src/glxdisplay/glxGraphicsBuffer.cxx new file mode 100644 index 0000000000..995f68bf80 --- /dev/null +++ b/panda/src/glxdisplay/glxGraphicsBuffer.cxx @@ -0,0 +1,193 @@ +// Filename: glxGraphicsBuffer.cxx +// Created by: drose (09Feb04) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved +// +// All use of this software is subject to the terms of the Panda 3d +// Software license. You should have received a copy of this license +// along with this source code; you will also find a current copy of +// the license at http://www.panda3d.org/license.txt . +// +// To contact the maintainers of this program write to +// panda3d@yahoogroups.com . +// +//////////////////////////////////////////////////////////////////// + +#include "glxGraphicsBuffer.h" +#include "glxGraphicsStateGuardian.h" +#include "config_glxdisplay.h" +#include "glxGraphicsPipe.h" + +#include "graphicsPipe.h" +#include "keyboardButton.h" +#include "mouseButton.h" +#include "glGraphicsStateGuardian.h" +#include "clockObject.h" + +#include +#include +#include +#include + +TypeHandle glxGraphicsBuffer::_type_handle; + +//////////////////////////////////////////////////////////////////// +// Function: glxGraphicsBuffer::Constructor +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +glxGraphicsBuffer:: +glxGraphicsBuffer(GraphicsPipe *pipe, GraphicsStateGuardian *gsg, + int x_size, int y_size, bool want_texture) : + GraphicsBuffer(pipe, gsg, x_size, y_size, want_texture) +{ + glxGraphicsPipe *glx_pipe; + DCAST_INTO_V(glx_pipe, _pipe); + _display = glx_pipe->get_display(); + _pbuffer = None; +} + +//////////////////////////////////////////////////////////////////// +// Function: glxGraphicsBuffer::Destructor +// Access: Public, Virtual +// Description: +//////////////////////////////////////////////////////////////////// +glxGraphicsBuffer:: +~glxGraphicsBuffer() { + nassertv(_pbuffer == None); +} + +//////////////////////////////////////////////////////////////////// +// Function: glxGraphicsBuffer::make_current +// Access: Public, Virtual +// Description: This function will be called within the draw thread +// during begin_frame() to ensure the graphics context +// is ready for drawing. +//////////////////////////////////////////////////////////////////// +void glxGraphicsBuffer:: +make_current() { + glxGraphicsStateGuardian *glxgsg; + DCAST_INTO_V(glxgsg, _gsg); + glXMakeCurrent(_display, _pbuffer, glxgsg->_context); + + // Now that we have made the context current to a window, we can + // reset the GSG state if this is the first time it has been used. + // (We can't just call reset() when we construct the GSG, because + // reset() requires having a current context.) + glxgsg->reset_if_new(); +} + +//////////////////////////////////////////////////////////////////// +// Function: glxGraphicsBuffer::release_gsg +// Access: Public +// Description: Releases the current GSG pointer, if it is currently +// held, and resets the GSG to NULL. The window will be +// permanently unable to render; this is normally called +// only just before destroying the window. This should +// only be called from within the draw thread. +//////////////////////////////////////////////////////////////////// +void glxGraphicsBuffer:: +release_gsg() { + glXMakeCurrent(_display, None, NULL); + GraphicsBuffer::release_gsg(); +} + +//////////////////////////////////////////////////////////////////// +// Function: glxGraphicsBuffer::begin_flip +// Access: Public, Virtual +// Description: This function will be called within the draw thread +// after end_frame() has been called on all windows, to +// initiate the exchange of the front and back buffers. +// +// This should instruct the window to prepare for the +// flip at the next video sync, but it should not wait. +// +// We have the two separate functions, begin_flip() and +// end_flip(), to make it easier to flip all of the +// windows at the same time. +//////////////////////////////////////////////////////////////////// +void glxGraphicsBuffer:: +begin_flip() { + if (_gsg != (GraphicsStateGuardian *)NULL) { + make_current(); + + if (has_texture()) { + // Use glCopyTexImage2D to copy the framebuffer to the texture. + // This appears to be the only way to "render to a texture" in + // OpenGL; there's no interface to make the offscreen buffer + // itself be a texture. + DisplayRegion dr(_x_size, _y_size); + get_texture()->copy(_gsg, &dr, _gsg->get_render_buffer(RenderBuffer::T_back)); + } + + glXSwapBuffers(_display, _pbuffer); + } +} + +//////////////////////////////////////////////////////////////////// +// Function: glxGraphicsBuffer::close_buffer +// Access: Protected, Virtual +// Description: Closes the buffer right now. Called from the window +// thread. +//////////////////////////////////////////////////////////////////// +void glxGraphicsBuffer:: +close_buffer() { + if (_pbuffer != None) { + glXDestroyPbuffer(_display, _pbuffer); + _pbuffer = None; + } + + _is_valid = false; +} + +//////////////////////////////////////////////////////////////////// +// Function: glxGraphicsBuffer::open_buffer +// Access: Protected, Virtual +// Description: Opens the buffer right now. Called from the window +// thread. Returns true if the buffer is successfully +// opened, or false if there was a problem. +//////////////////////////////////////////////////////////////////// +bool glxGraphicsBuffer:: +open_buffer() { + glxGraphicsPipe *glx_pipe; + DCAST_INTO_R(glx_pipe, _pipe, false); + glxGraphicsStateGuardian *glxgsg; + DCAST_INTO_R(glxgsg, _gsg, false); + + static const int max_attrib_list = 32; + int attrib_list[max_attrib_list]; + int n=0; + +#ifdef GLX_VERSION_1_3 + // The official GLX 1.3 version passes in the size in the attrib + // list. + attrib_list[n++] = GLX_PBUFFER_WIDTH; + attrib_list[n++] = _x_size; + attrib_list[n++] = GLX_PBUFFER_HEIGHT; + attrib_list[n++] = _y_size; + + nassertr(n < max_attrib_list, false); + attrib_list[n] = (int)None; + _pbuffer = glXCreatePbuffer(glxgsg->_display, glxgsg->_fbconfig, + attrib_list); + +#else + // The pre-GLX 1.3 version passed in the size in the parameter list. + nassertr(n < max_attrib_list, false); + attrib_list[n] = (int)None; + _pbuffer = glXCreateGLXPbufferSGIX(glxgsg->_display, glxgsg->_fbconfig, + _x_size, _y_size, attrib_list); +#endif + + if (_pbuffer == None) { + glxdisplay_cat.error() + << "failed to create GLX pbuffer.\n"; + return false; + } + + _is_valid = true; + return true; +} diff --git a/panda/src/glxdisplay/glxGraphicsBuffer.h b/panda/src/glxdisplay/glxGraphicsBuffer.h new file mode 100644 index 0000000000..220339689b --- /dev/null +++ b/panda/src/glxdisplay/glxGraphicsBuffer.h @@ -0,0 +1,72 @@ +// Filename: glxGraphicsBuffer.h +// Created by: drose (09Feb04) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved +// +// All use of this software is subject to the terms of the Panda 3d +// Software license. You should have received a copy of this license +// along with this source code; you will also find a current copy of +// the license at http://www.panda3d.org/license.txt . +// +// To contact the maintainers of this program write to +// panda3d@yahoogroups.com . +// +//////////////////////////////////////////////////////////////////// + +#ifndef GLXGRAPHICSBUFFER_H +#define GLXGRAPHICSBUFFER_H + +#include "pandabase.h" + +#include "glxGraphicsPipe.h" +#include "graphicsBuffer.h" + +//////////////////////////////////////////////////////////////////// +// Class : glxGraphicsBuffer +// Description : An offscreen buffer in the GLX environment. This +// creates a GLXPbuffer. +//////////////////////////////////////////////////////////////////// +class glxGraphicsBuffer : public GraphicsBuffer { +public: + glxGraphicsBuffer(GraphicsPipe *pipe, GraphicsStateGuardian *gsg, + int x_size, int y_size, bool want_texture); + + virtual ~glxGraphicsBuffer(); + + virtual void make_current(); + virtual void release_gsg(); + + virtual void begin_flip(); + +protected: + virtual void close_buffer(); + virtual bool open_buffer(); + +private: + Display *_display; + GLXPbuffer _pbuffer; + +public: + static TypeHandle get_class_type() { + return _type_handle; + } + static void init_type() { + GraphicsBuffer::init_type(); + register_type(_type_handle, "glxGraphicsBuffer", + GraphicsBuffer::get_class_type()); + } + virtual TypeHandle get_type() const { + return get_class_type(); + } + virtual TypeHandle force_init_type() {init_type(); return get_class_type();} + +private: + static TypeHandle _type_handle; +}; + +#include "glxGraphicsBuffer.I" + +#endif diff --git a/panda/src/glxdisplay/glxGraphicsPipe.cxx b/panda/src/glxdisplay/glxGraphicsPipe.cxx index 7a4c885ffb..e93822ee6c 100644 --- a/panda/src/glxdisplay/glxGraphicsPipe.cxx +++ b/panda/src/glxdisplay/glxGraphicsPipe.cxx @@ -18,6 +18,7 @@ #include "glxGraphicsPipe.h" #include "glxGraphicsWindow.h" +#include "glxGraphicsBuffer.h" #include "glxGraphicsStateGuardian.h" #include "config_glxdisplay.h" #include "frameBufferProperties.h" @@ -200,6 +201,20 @@ make_window(GraphicsStateGuardian *gsg) { return new glxGraphicsWindow(this, gsg); } +//////////////////////////////////////////////////////////////////// +// Function: glxGraphicsPipe::make_buffer +// Access: Protected, Virtual +// Description: Creates a new offscreen buffer on the pipe, if possible. +//////////////////////////////////////////////////////////////////// +PT(GraphicsBuffer) glxGraphicsPipe:: +make_buffer(GraphicsStateGuardian *gsg, int x_size, int y_size, bool want_texture) { + if (!_is_valid) { + return NULL; + } + + return new glxGraphicsBuffer(this, gsg, x_size, y_size, want_texture); +} + //////////////////////////////////////////////////////////////////// // Function: glxGraphicsPipe::choose_fbconfig // Access: Private diff --git a/panda/src/glxdisplay/glxGraphicsPipe.h b/panda/src/glxdisplay/glxGraphicsPipe.h index 6e7e9c0d13..48217fc9df 100644 --- a/panda/src/glxdisplay/glxGraphicsPipe.h +++ b/panda/src/glxdisplay/glxGraphicsPipe.h @@ -79,6 +79,8 @@ public: protected: virtual PT(GraphicsStateGuardian) make_gsg(const FrameBufferProperties &properties); virtual PT(GraphicsWindow) make_window(GraphicsStateGuardian *gsg); + virtual PT(GraphicsBuffer) make_buffer(GraphicsStateGuardian *gsg, + int x_size, int y_size, bool want_texture); private: GLXFBConfig choose_fbconfig(FrameBufferProperties &properties) const;