| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695 |
- // Filename: graphicsWindow.cxx
- // Created by: mike (09Jan97)
- //
- ////////////////////////////////////////////////////////////////////
- //
- // 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
- // [email protected] .
- //
- ////////////////////////////////////////////////////////////////////
- #include "graphicsWindow.h"
- #include "graphicsPipe.h"
- #include "config_display.h"
- #include <mouseButton.h>
- #include <keyboardButton.h>
- #include "pmap.h"
- ////////////////////////////////////////////////////////////////////
- // Static variables
- ////////////////////////////////////////////////////////////////////
- TypeHandle GraphicsWindow::_type_handle;
- TypeHandle GraphicsWindow::WindowProps::_type_handle;
- TypeHandle GraphicsWindow::WindowPipe::_type_handle;
- GraphicsWindow::WindowFactory *GraphicsWindow::_factory = NULL;
- #ifndef CPPPARSER
- // We must compile these lines, even if DO_PSTATS is not defined,
- // because the symbols for them are declared in the header file.
- // Otherwise they will be undefined symbols at link time. However,
- // there's no runtime overhead to speak of for declaring these, so
- // there's no harm in compiling them all the time.
- PStatCollector GraphicsWindow::_app_pcollector("App");
- PStatCollector GraphicsWindow::_show_code_pcollector("App:Show code");
- PStatCollector GraphicsWindow::_swap_pcollector("Swap buffers");
- PStatCollector GraphicsWindow::_clear_pcollector("Draw:Clear");
- PStatCollector GraphicsWindow::_show_fps_pcollector("Draw:Show fps");
- PStatCollector GraphicsWindow::_make_current_pcollector("Draw:Make current");
- #endif
- ////////////////////////////////////////////////////////////////////
- // Function: GraphicsWindow::Properties::Constructor
- // Access: Published
- // Description:
- ////////////////////////////////////////////////////////////////////
- GraphicsWindow::Properties::
- Properties() {
- _xorg = 0;
- _yorg = 0;
- _xsize = 512;
- _ysize = 512;
- _title = "Panda";
- _border = true;
- _fullscreen = false;
- _mask = W_RGBA | W_DOUBLE | W_DEPTH;
- _want_depth_bits = 1;
- _want_color_bits = 1;
- _bCursorIsVisible=true;
- // By default, windows are set up to clear color and depth.
- set_clear_color_active(true);
- set_clear_depth_active(true);
- }
- ////////////////////////////////////////////////////////////////////
- // Function: GraphicsWindow::Callback::draw
- // Access: Public
- // Description:
- ////////////////////////////////////////////////////////////////////
- void GraphicsWindow::Callback::
- draw(bool) {
- display_cat.error()
- << "Callback::draw() - no class defined for this" << endl;
- }
- ////////////////////////////////////////////////////////////////////
- // Function: GraphicsWindow::Callback::idle
- // Access: Public
- // Description:
- ////////////////////////////////////////////////////////////////////
- void GraphicsWindow::Callback::
- idle() {
- display_cat.error()
- << "Callback::idle() - no class defined for this" << endl;
- }
- GraphicsWindow::WindowProps::~WindowProps(void) {}
- TypeHandle GraphicsWindow::WindowProps::get_class_type(void) {
- return _type_handle;
- }
- void GraphicsWindow::WindowProps::init_type(void) {
- WindowParam::init_type();
- register_type(_type_handle, "GraphicsWindow::WindowProps",
- WindowParam::get_class_type());
- }
- TypeHandle GraphicsWindow::WindowProps::get_type(void) const {
- return get_class_type();
- }
- TypeHandle GraphicsWindow::WindowProps::force_init_type(void) {
- init_type();
- return get_class_type();
- }
- GraphicsWindow::WindowPipe::~WindowPipe(void) {}
- TypeHandle GraphicsWindow::WindowPipe::get_class_type(void) {
- return _type_handle;
- }
- void GraphicsWindow::WindowPipe::init_type(void) {
- WindowParam::init_type();
- register_type(_type_handle, "GraphicsWindow::WindowPipe",
- WindowParam::get_class_type());
- }
- TypeHandle GraphicsWindow::WindowPipe::get_type(void) const {
- return get_class_type();
- }
- TypeHandle GraphicsWindow::WindowPipe::force_init_type(void) {
- init_type();
- return get_class_type();
- }
- ////////////////////////////////////////////////////////////////////
- // Function: GraphicsWindow::Constructor
- // Access: Public
- // Description:
- ////////////////////////////////////////////////////////////////////
- GraphicsWindow::
- GraphicsWindow(GraphicsPipe *pipe,
- const GraphicsWindow::Properties &props) :
- Configurable(),
- ClearableRegion(props)
- {
- #ifdef DO_MEMORY_USAGE
- MemoryUsage::update_type(this, this);
- #endif
- _pipe = pipe;
- _props = props;
- _draw_callback = NULL;
- _idle_callback = NULL;
- _frame_number = 0;
- _is_synced = false;
- _window_active = true;
- _display_regions_stale = false;
- }
- ////////////////////////////////////////////////////////////////////
- // Function: GraphicsWindow::Copy Constructor
- // Access: Public
- // Description:
- ////////////////////////////////////////////////////////////////////
- GraphicsWindow::
- GraphicsWindow(const GraphicsWindow&) {
- display_cat.error()
- << "GraphicsWindows should not be copied" << endl;
- }
- ////////////////////////////////////////////////////////////////////
- // Function: GraphicsWindow::Copy Assignment Operator
- // Access: Public
- // Description:
- ////////////////////////////////////////////////////////////////////
- GraphicsWindow& GraphicsWindow::
- operator=(const GraphicsWindow&) {
- display_cat.error()
- << "GraphicsWindows should not be assigned" << endl;
- return *this;
- }
- ////////////////////////////////////////////////////////////////////
- // Function: GraphicsWindow::Destructor
- // Access: Public, Virtual
- // Description:
- ////////////////////////////////////////////////////////////////////
- GraphicsWindow::
- ~GraphicsWindow() {
- // First, call close_window(). This tells our GSG to let go of its
- // pointer to us, and also eventually calls do_close_window().
- // However, do_close_window() is a virtual function that might be
- // extended in a derived class, but we don't have any derived
- // virtual functions by the time the destructor is called.
-
- // Therefore, if a derived class has redefined do_close_window(), it
- // should also call close_window() in its own destructor.
- close_window();
- // We don't have to destruct our child channels explicitly, since
- // they are all reference-counted and will go away when their
- // pointers do. However, we do need to zero out their pointers to
- // us.
- Channels::iterator ci;
- for (ci = _channels.begin(); ci != _channels.end(); ++ci) {
- (*ci)->_window = NULL;
- }
- // We don't need to remove ourself from the pipe's list of windows.
- // We must have already been removed, or we wouldn't be destructing!
- }
- ////////////////////////////////////////////////////////////////////
- // Function: GraphicsWindow::get_channel
- // Access: Public
- // Description: Returns a GraphicsChannel pointer that can be used to
- // access the indicated channel number. All windows
- // have at least one channel, channel 0, which
- // corresponds to the entire window. If the hardware
- // supports it, some kinds of windows may also have a
- // number of hardware channels available at indices
- // 1..n, which will correspond to a subregion of the
- // window.
- //
- // This function returns a GraphicsChannel pointer if a
- // channel is available, or NULL if it is not. If
- // called twice with the same index number, it will
- // return the same pointer.
- ////////////////////////////////////////////////////////////////////
- GraphicsChannel *GraphicsWindow::
- get_channel(int index) {
- nassertr(index >= 0, NULL);
- if (index < (int)_channels.size()) {
- if (_channels[index] != (GraphicsChannel *)NULL) {
- return _channels[index];
- }
- }
- // This channel has never been requested before; define it.
- PT(GraphicsChannel) chan;
- if (index == 0) {
- // Channel 0 is the default channel: the entire screen.
- chan = new GraphicsChannel(this);
- } else {
- // Any other channel is some hardware-specific channel.
- nassertr(_pipe != NULL, NULL);
- chan = _pipe->get_hw_channel(this, index);
- if (chan == NULL) {
- display_cat.error()
- << "GraphicsWindow::get_channel() - got a NULL channel" << endl;
- } else {
- if (chan->get_window() != this) {
- chan = NULL;
- }
- }
- }
- if (chan != (GraphicsChannel *)NULL) {
- declare_channel(index, chan);
- }
- return chan;
- }
- ////////////////////////////////////////////////////////////////////
- // Function: GraphicsWindow::remove_channel
- // Access: Public
- // Description: Deletes a GraphicsChannel that was previously created
- // via a call to get_channel(). Note that the channel
- // is not actually deleted until all pointers to it are
- // cleared.
- ////////////////////////////////////////////////////////////////////
- void GraphicsWindow::
- remove_channel(int index) {
- if (index >= 0 && index < (int)_channels.size()) {
- _channels[index].clear();
- }
- }
- ////////////////////////////////////////////////////////////////////
- // Function: GraphicsWindow::get_max_channel_index
- // Access: Public
- // Description: Returns the largest channel index number yet created,
- // plus 1. All channels associated with this window
- // will have an index number in the range [0,
- // get_max_channel_index()). This function, in
- // conjunction with is_channel_defined(), below, may be
- // used to determine the complete set of channels
- // associated with the window.
- ////////////////////////////////////////////////////////////////////
- int GraphicsWindow::
- get_max_channel_index() const {
- return _channels.size();
- }
- ////////////////////////////////////////////////////////////////////
- // Function: GraphicsWindow::is_channel_defined
- // Access: Public
- // Description: Returns true if the channel with the given index
- // number has already been defined, false if it hasn't.
- // If this returns true, calling get_channel() on the
- // given index number will return the channel pointer.
- // If it returns false, calling get_channel() will
- // create and return a new channel pointer.
- ////////////////////////////////////////////////////////////////////
- bool GraphicsWindow::
- is_channel_defined(int index) const {
- if (index < 0 || index >= (int)_channels.size()) {
- return false;
- }
- return (_channels[index] != (GraphicsChannel *)NULL);
- }
- ////////////////////////////////////////////////////////////////////
- // Function: GraphicsWindow::declare_channel
- // Access: Protected
- // Description: An internal function to add the indicated
- // newly-created channel to the list at the indicated
- // channel number.
- ////////////////////////////////////////////////////////////////////
- void GraphicsWindow::
- declare_channel(int index, GraphicsChannel *chan) {
- nassertv(index >= 0);
- if (index >= (int)_channels.size()) {
- _channels.reserve(index);
- while (index >= (int)_channels.size()) {
- _channels.push_back(NULL);
- }
- }
- nassertv(index < (int)_channels.size());
- _channels[index] = chan;
- }
- ////////////////////////////////////////////////////////////////////
- // Function: GraphicsWindow::do_determine_display_regions
- // Access: Private
- // Description: Recomputes the list of active DisplayRegions within
- // the window.
- ////////////////////////////////////////////////////////////////////
- void GraphicsWindow::
- do_determine_display_regions() {
- _display_regions.clear();
- Channels::const_iterator ci;
- for (ci = _channels.begin(); ci != _channels.end(); ++ci) {
- GraphicsChannel *chan = (*ci);
- if (chan->is_active()) {
- GraphicsChannel::GraphicsLayers::const_iterator li;
- for (li = chan->_layers.begin(); li != chan->_layers.end(); ++li) {
- GraphicsLayer *layer = (*li);
- if (layer->is_active()) {
- GraphicsLayer::DisplayRegions::const_iterator dri;
- for (dri = layer->_display_regions.begin();
- dri != layer->_display_regions.end();
- ++dri) {
- DisplayRegion *dr = (*dri);
- if (dr->is_active()) {
- _display_regions.push_back(dr);
- }
- }
- }
- }
- }
- }
- _display_regions_stale = false;
- }
- ////////////////////////////////////////////////////////////////////
- // Function: GraphicsWindow::resized
- // Access: Public, Virtual
- // Description: Called whenever the window gets the resize event.
- ////////////////////////////////////////////////////////////////////
- void GraphicsWindow::
- resized(const unsigned int x, const unsigned int y) {
- Channels::iterator ci;
- for (ci = _channels.begin(); ci != _channels.end(); ++ci) {
- GraphicsChannel *chan = (*ci);
- chan->window_resized(x, y);
- }
- _props._xsize = x;
- _props._ysize = y;
- }
- ////////////////////////////////////////////////////////////////////
- // Function: GraphicsWindow::make_scratch_display_region
- // Access: Public
- // Description: Allocates and returns a temporary DisplayRegion that
- // may be used to render offscreen into. This
- // DisplayRegion is not associated with any layer.
- //
- // To allocate a normal DisplayRegion for rendering, use
- // the interface provided in GraphicsLayer.
- ////////////////////////////////////////////////////////////////////
- PT(DisplayRegion) GraphicsWindow::
- make_scratch_display_region(int xsize, int ysize) const {
- if (xsize > _props._xsize) {
- display_cat.error()
- << "GraphicsWindow::make_scratch_display_region() - x size is larger "
- << "than window x size" << endl;
- xsize = _props._xsize;
- }
- if (ysize > _props._ysize) {
- display_cat.error()
- << "GraphicsWindow::make_scratch_display_region() - y size is larger "
- << "than window y size" << endl;
- ysize = _props._ysize;
- }
- PT(DisplayRegion) region = new DisplayRegion(xsize, ysize);
- region->copy_clear_settings(*this);
- return region;
- }
- ////////////////////////////////////////////////////////////////////
- // Function: GraphicsWindow::make_current
- // Access: Public, Virtual
- // Description: Makes the window's graphics context the currently
- // active context that will be next rendered into by the
- // GSG, if this makes sense for the particular type of
- // GraphicsWindow.
- ////////////////////////////////////////////////////////////////////
- void GraphicsWindow::
- make_current(void) {
- }
- ////////////////////////////////////////////////////////////////////
- // Function: GraphicsWindow::unmake_current
- // Access: Public, Virtual
- // Description:
- ////////////////////////////////////////////////////////////////////
- void GraphicsWindow::
- unmake_current(void) {
- }
- ////////////////////////////////////////////////////////////////////
- // Function: GraphicsWindow::flag_redisplay
- // Access: Public, Virtual
- // Description:
- ////////////////////////////////////////////////////////////////////
- void GraphicsWindow::
- flag_redisplay() {
- }
- ////////////////////////////////////////////////////////////////////
- // Function: GraphicsWindow::register_draw_function
- // Access: Public, Virtual
- // Description:
- ////////////////////////////////////////////////////////////////////
- void GraphicsWindow::
- register_draw_function(GraphicsWindow::vfn f) {
- _draw_function = f;
- }
- ////////////////////////////////////////////////////////////////////
- // Function: GraphicsWindow::register_idle_function
- // Access: Public, Virtual
- // Description:
- ////////////////////////////////////////////////////////////////////
- void GraphicsWindow::
- register_idle_function(GraphicsWindow::vfn f) {
- _idle_function = f;
- }
- ////////////////////////////////////////////////////////////////////
- // Function: GraphicsWindow::begin_frame
- // Access: Public, Virtual
- // Description: This function will be called by the GSG before
- // beginning processing for a given frame. It should do
- // whatever setup is required.
- ////////////////////////////////////////////////////////////////////
- void GraphicsWindow::
- begin_frame() {
- _gsg->begin_frame();
- }
- ////////////////////////////////////////////////////////////////////
- // Function: GraphicsWindow::clear
- // Access: Public
- // Description: Clears the entire framebuffer before rendering,
- // according to the settings of get_color_clear_active()
- // and get_depth_clear_active() (inherited from
- // ClearableRegion).
- ////////////////////////////////////////////////////////////////////
- void GraphicsWindow::
- clear() {
- if (is_any_clear_active()) {
- nassertv(_gsg != (GraphicsStateGuardian *)NULL);
- PT(DisplayRegion) win_dr =
- make_scratch_display_region(get_width(), get_height());
- DisplayRegionStack old_dr = _gsg->push_display_region(win_dr);
- _gsg->clear(this);
- _gsg->pop_display_region(old_dr);
- }
- }
- ////////////////////////////////////////////////////////////////////
- // Function: GraphicsWindow::end_frame
- // Access: Public, Virtual
- // Description: This function will be called by the GSG after
- // processing is completed for a given frame. It should
- // do whatever finalization is required.
- ////////////////////////////////////////////////////////////////////
- void GraphicsWindow::
- end_frame() {
- _gsg->end_frame();
- _frame_number++;
- }
- ////////////////////////////////////////////////////////////////////
- // Function: GraphicsWindow::process_events
- // Access: Public, Virtual
- // Description: Do whatever processing is necessary to ensure that
- // the window responds to user events.
- ////////////////////////////////////////////////////////////////////
- void GraphicsWindow::
- process_events() {
- }
- ////////////////////////////////////////////////////////////////////
- // Function: GraphicsWindow::deactivate_window
- // Access: Public, Virtual
- // Description: Indicates the window should stop rendering
- // temporarily, and does whatever else is associated
- // with that. This is normally called only by the
- // GraphicsWindow itself, or by the GSG.
- ////////////////////////////////////////////////////////////////////
- void GraphicsWindow::
- deactivate_window() {
- _window_active = false;
- }
- ////////////////////////////////////////////////////////////////////
- // Function: GraphicsWindow::reactivate_window
- // Access: Public, Virtual
- // Description: Restores the normal window rendering behavior after a
- // previous call to deactivate_window().
- ////////////////////////////////////////////////////////////////////
- void GraphicsWindow::
- reactivate_window() {
- _window_active = true;
- }
- ////////////////////////////////////////////////////////////////////
- // Function: GraphicsWindow::make_gsg
- // Access: Protected
- // Description: Creates a new GSG for the window and stores it in the
- // _gsg pointer.
- ////////////////////////////////////////////////////////////////////
- void GraphicsWindow::
- make_gsg() {
- FactoryParams params;
- params.add_param(new GraphicsStateGuardian::GsgWindow(this));
- _gsg = GraphicsStateGuardian::get_factory().
- make_instance(get_gsg_type(), params);
- nassertv(_gsg != (GraphicsStateGuardian *)NULL);
- }
- ////////////////////////////////////////////////////////////////////
- // Function: GraphicsWindow::release_gsg
- // Access: Protected
- // Description: Releases the current GSG pointer, if it is currently
- // held. This invalidates the window and marks it
- // closed; it should not be called unless the code to
- // close the window is also called.
- ////////////////////////////////////////////////////////////////////
- void GraphicsWindow::
- release_gsg() {
- if (_gsg != (GraphicsStateGuardian *)NULL) {
- // First, we save the GSG pointer and then NULL it out. That way,
- // if the GSG happens to call close_window() while it is closing
- // itself, it won't be recursive (because we'll already be marked
- // closed).
- PT(GraphicsStateGuardian) gsg = _gsg;
- _gsg.clear();
- // Now we tell the GSG it's time to sleep.
- gsg->close_gsg();
- }
- }
- ////////////////////////////////////////////////////////////////////
- // Function: GraphicsWindow::do_close_window
- // Access: Protected, Virtual
- // Description: An internal function to release whatever system
- // resources are held by the window and actually close
- // it. This is called by close_window().
- //
- // If a derived class redefines this function, it should
- // also arrange to call close_window() (or its
- // equivalent) from its own destructor, since we cannot
- // call a virtual function from this destructor.
- ////////////////////////////////////////////////////////////////////
- void GraphicsWindow::
- do_close_window() {
- display_cat.info()
- << "Closing " << get_type() << "\n";
- }
- ////////////////////////////////////////////////////////////////////
- // Function: GraphicsWindow::get_factory
- // Access: Public, Static
- // Description: Returns the factory object that can be used to
- // register new kinds of GraphicsWindow objects that may
- // be created.
- ////////////////////////////////////////////////////////////////////
- GraphicsWindow::WindowFactory &GraphicsWindow::
- get_factory() {
- if (_factory == (WindowFactory *)NULL) {
- _factory = new WindowFactory;
- }
- return (*_factory);
- }
- void GraphicsWindow::read_priorities(void) {
- WindowFactory &factory = get_factory();
- if (factory.get_num_preferred() == 0) {
- Config::ConfigTable::Symbol::iterator i;
- for (i = preferred_window_begin(); i != preferred_window_end(); ++i) {
- ConfigString type_name = (*i).Val();
- TypeHandle type = TypeRegistry::ptr()->find_type(type_name);
- if (type == TypeHandle::none()) {
- display_cat.warning()
- << "Unknown type requested for window preference: " << type_name
- << "\n";
- } else {
- display_cat.debug()
- << "Specifying type " << type << " for window preference.\n";
- factory.add_preferred(type);
- }
- }
- }
- }
- ////////////////////////////////////////////////////////////////////
- // Function: GraphicsWindow::swap
- // Access: Public
- // Description: Swaps buffers explicitely as synchronization
- // mechanism.
- ////////////////////////////////////////////////////////////////////
- void GraphicsWindow::
- swap() {
- display_cat.warning() << "swap() unimplemented by " << get_type() << endl;
- }
- ////////////////////////////////////////////////////////////////////
- // Function: GraphicsWindow::resize
- // Access: Public
- // Description: Resizes the window to the given size.
- // Should try to preserve current window bitdepths,
- // if possible. If it is not possible to resize window to
- // the given size, return false and maintain current
- // window size.
- ////////////////////////////////////////////////////////////////////
- bool GraphicsWindow::
- resize(unsigned int xsize,unsigned int ysize) {
- display_cat.warning() << "resize() unimplemented by " << get_type() << endl;
- return false;
- }
- unsigned int GraphicsWindow::
- verify_window_sizes(unsigned int numsizes,unsigned int *dimen) {
- // see if window sizes are supported (i.e. in fullscrn mode)
- // dimen is an array containing contiguous x,y pairs specifying
- // possible display sizes, it is numsizes*2 long. fn will zero
- // out any invalid x,y size pairs. return value is number of valid
- // sizes that were found.
- //
- // note: it might be better to implement some sort of query
- // interface that returns an array of supported sizes,
- // but this way is somewhat simpler and will do the job
- // on most cards, assuming they handle the std sizes the app
- // knows about.
- // Also note this doesnt guarantee resize() will work, you still need to check its return value.
- display_cat.warning() << "verify_window_sizes() unimplemented by " << get_type() << endl;
- return numsizes;
- }
- int GraphicsWindow::
- get_depth_bitwidth(void) {
- display_cat.warning() << "get_depth_bitwidth() unimplemented by " << get_type() << endl;
- return -1;
- }
|