define GraphicsOutput class
This commit is contained in:
parent
d684df5958
commit
26da9be3e7
|
|
@ -22,8 +22,8 @@
|
|||
#include "directbase.h"
|
||||
|
||||
#include "eventHandler.h"
|
||||
#include "graphicsPipe.h"
|
||||
#include "graphicsWindow.h"
|
||||
#include "graphicsPipe.h"
|
||||
#include "animControl.h"
|
||||
#include "pointerTo.h"
|
||||
#include "dconfig.h"
|
||||
|
|
|
|||
|
|
@ -22,12 +22,15 @@
|
|||
graphicsChannel.I graphicsChannel.h \
|
||||
graphicsEngine.I graphicsEngine.h \
|
||||
graphicsLayer.I \
|
||||
graphicsLayer.h graphicsPipe.I graphicsPipe.h \
|
||||
graphicsLayer.h \
|
||||
graphicsOutput.I graphicsOutput.h \
|
||||
graphicsPipe.I graphicsPipe.h \
|
||||
graphicsPipeSelection.I graphicsPipeSelection.h \
|
||||
graphicsStateGuardian.I \
|
||||
graphicsStateGuardian.h graphicsWindow.I \
|
||||
graphicsStateGuardian.h \
|
||||
graphicsThreadingModel.I graphicsThreadingModel.h \
|
||||
graphicsWindow.h graphicsWindowInputDevice.I \
|
||||
graphicsWindow.I graphicsWindow.h \
|
||||
graphicsWindowInputDevice.I \
|
||||
graphicsWindowInputDevice.h \
|
||||
graphicsDevice.h graphicsDevice.I \
|
||||
windowProperties.I windowProperties.h \
|
||||
|
|
@ -43,7 +46,9 @@
|
|||
frameBufferProperties.cxx \
|
||||
geomContext.cxx geomNodeContext.cxx graphicsChannel.cxx \
|
||||
graphicsEngine.cxx \
|
||||
graphicsLayer.cxx graphicsPipe.cxx \
|
||||
graphicsLayer.cxx \
|
||||
graphicsOutput.cxx \
|
||||
graphicsPipe.cxx \
|
||||
graphicsPipeSelection.cxx \
|
||||
graphicsStateGuardian.cxx \
|
||||
graphicsThreadingModel.cxx \
|
||||
|
|
@ -64,10 +69,12 @@
|
|||
graphicsChannel.I graphicsChannel.h \
|
||||
graphicsEngine.I graphicsEngine.h \
|
||||
graphicsLayer.I graphicsLayer.h \
|
||||
graphicsOutput.I graphicsOutput.h \
|
||||
graphicsPipe.I graphicsPipe.h \
|
||||
graphicsPipeSelection.I graphicsPipeSelection.h \
|
||||
graphicsStateGuardian.I \
|
||||
graphicsStateGuardian.h graphicsWindow.I graphicsWindow.h \
|
||||
graphicsStateGuardian.h \
|
||||
graphicsWindow.I graphicsWindow.h \
|
||||
graphicsThreadingModel.I graphicsThreadingModel.h \
|
||||
graphicsWindowInputDevice.I graphicsWindowInputDevice.h \
|
||||
graphicsDevice.I graphicsDevice.h \
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@
|
|||
|
||||
#include "graphicsLayer.h"
|
||||
#include "graphicsChannel.h"
|
||||
#include "graphicsWindow.h"
|
||||
#include "graphicsOutput.h"
|
||||
#include "config_display.h"
|
||||
#include "displayRegion.h"
|
||||
#include "camera.h"
|
||||
|
|
@ -190,12 +190,9 @@ set_dimensions(float l, float r, float b, float t) {
|
|||
_b = b;
|
||||
_t = t;
|
||||
|
||||
const GraphicsWindow *win = get_window();
|
||||
if (win != (GraphicsWindow *)NULL) {
|
||||
WindowProperties properties = win->get_properties();
|
||||
if (properties.has_size()) {
|
||||
do_compute_pixels(properties.get_x_size(), properties.get_y_size());
|
||||
}
|
||||
const GraphicsOutput *win = get_window();
|
||||
if (win != (GraphicsOutput *)NULL && win->has_size()) {
|
||||
do_compute_pixels(win->get_x_size(), win->get_y_size());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -228,11 +225,11 @@ get_channel() const {
|
|||
////////////////////////////////////////////////////////////////////
|
||||
// Function: DisplayRegion::get_window
|
||||
// Access: Published
|
||||
// Description: Returns the GraphicsWindow that this DisplayRegion is
|
||||
// Description: Returns the GraphicsOutput that this DisplayRegion is
|
||||
// ultimately associated with, or NULL if no window is
|
||||
// associated.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
GraphicsWindow *DisplayRegion::
|
||||
GraphicsOutput *DisplayRegion::
|
||||
get_window() const {
|
||||
MutexHolder holder(_lock);
|
||||
return (_layer != (GraphicsLayer *)NULL) ? _layer->get_window() : NULL;
|
||||
|
|
@ -324,21 +321,11 @@ set_active(bool active) {
|
|||
////////////////////////////////////////////////////////////////////
|
||||
void DisplayRegion::
|
||||
compute_pixels() {
|
||||
const GraphicsWindow *win = get_window();
|
||||
if (win != (GraphicsWindow *)NULL) {
|
||||
const GraphicsOutput *win = get_window();
|
||||
if (win != (GraphicsOutput *)NULL) {
|
||||
MutexHolder holder(_lock);
|
||||
WindowProperties properties = win->get_properties();
|
||||
if (!properties.has_size()) {
|
||||
// If the window doesn't know its size yet, maybe it will
|
||||
// eventually be given the size it's requesting.
|
||||
properties = win->get_requested_properties();
|
||||
}
|
||||
|
||||
if (properties.has_size()) {
|
||||
do_compute_pixels(properties.get_x_size(), properties.get_y_size());
|
||||
} else {
|
||||
do_compute_pixels(0, 0);
|
||||
}
|
||||
do_compute_pixels(win->get_x_size(), win->get_y_size());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@
|
|||
|
||||
class GraphicsLayer;
|
||||
class GraphicsChannel;
|
||||
class GraphicsWindow;
|
||||
class GraphicsOutput;
|
||||
class GraphicsPipe;
|
||||
class CullHandler;
|
||||
class Camera;
|
||||
|
|
@ -64,7 +64,7 @@ PUBLISHED:
|
|||
|
||||
GraphicsLayer *get_layer() const;
|
||||
GraphicsChannel *get_channel() const;
|
||||
GraphicsWindow *get_window() const;
|
||||
GraphicsOutput *get_window() const;
|
||||
GraphicsPipe *get_pipe() const;
|
||||
|
||||
void set_camera(const NodePath &camera);
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@
|
|||
#include "graphicsChannel.cxx"
|
||||
#include "graphicsEngine.cxx"
|
||||
#include "graphicsLayer.cxx"
|
||||
#include "graphicsOutput.cxx"
|
||||
#include "graphicsPipe.cxx"
|
||||
#include "graphicsStateGuardian.cxx"
|
||||
#include "graphicsWindow.cxx"
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@
|
|||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "graphicsChannel.h"
|
||||
#include "graphicsWindow.h"
|
||||
#include "graphicsOutput.h"
|
||||
#include "graphicsLayer.h"
|
||||
#include "config_display.h"
|
||||
#include "mutexHolder.h"
|
||||
|
|
@ -42,10 +42,10 @@ GraphicsChannel() {
|
|||
// Access: Public
|
||||
// Description: This is public just so derived window types can
|
||||
// easily call it. Don't call it directly; instead, use
|
||||
// GraphicsWindow::get_channel() to get a channel.
|
||||
// GraphicsOutput::get_channel() to get a channel.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
GraphicsChannel::
|
||||
GraphicsChannel(GraphicsWindow *window)
|
||||
GraphicsChannel(GraphicsOutput *window)
|
||||
: _window(window)
|
||||
{
|
||||
_is_active = true;
|
||||
|
|
@ -201,14 +201,14 @@ get_layer(int index) const {
|
|||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GraphicsChannel::get_window
|
||||
// Access: Published
|
||||
// Description: Returns the GraphicsWindow that this channel is
|
||||
// Description: Returns the GraphicsOutput that this channel is
|
||||
// associated with. It is possible that the
|
||||
// GraphicsWindow might have been deleted while an
|
||||
// GraphicsOutput might have been deleted while an
|
||||
// outstanding PT(GraphicsChannel) prevented all of its
|
||||
// children channels from also being deleted; in this
|
||||
// unlikely case, get_window() may return NULL.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
GraphicsWindow *GraphicsChannel::
|
||||
GraphicsOutput *GraphicsChannel::
|
||||
get_window() const {
|
||||
MutexHolder holder(_lock);
|
||||
return _window;
|
||||
|
|
@ -224,7 +224,7 @@ get_window() const {
|
|||
GraphicsPipe *GraphicsChannel::
|
||||
get_pipe() const {
|
||||
MutexHolder holder(_lock);
|
||||
return (_window != (GraphicsWindow *)NULL) ? _window->get_pipe() : NULL;
|
||||
return (_window != (GraphicsOutput *)NULL) ? _window->get_pipe() : NULL;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -274,7 +274,7 @@ window_resized(int x_size, int y_size) {
|
|||
////////////////////////////////////////////////////////////////////
|
||||
void GraphicsChannel::
|
||||
win_display_regions_changed() {
|
||||
if (_window != (GraphicsWindow *)NULL) {
|
||||
if (_window != (GraphicsOutput *)NULL) {
|
||||
_window->win_display_regions_changed();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,14 +28,14 @@
|
|||
|
||||
class GraphicsChannel;
|
||||
class GraphicsPipe;
|
||||
class GraphicsWindow;
|
||||
class GraphicsOutput;
|
||||
class CullHandler;
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : GraphicsChannel
|
||||
// Description : This represents a single hardware output. Typically
|
||||
// there is exactly one channel per window, but some
|
||||
// implementations (e.g. SGI) support potentially
|
||||
// there is exactly one channel per GraphicsOutput, but
|
||||
// some implementations (e.g. SGI) support potentially
|
||||
// several different video channel ports connected to
|
||||
// different parts within a window.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -44,7 +44,7 @@ protected:
|
|||
GraphicsChannel();
|
||||
|
||||
public:
|
||||
GraphicsChannel(GraphicsWindow *window);
|
||||
GraphicsChannel(GraphicsOutput *window);
|
||||
|
||||
private:
|
||||
GraphicsChannel(const GraphicsChannel ©);
|
||||
|
|
@ -59,7 +59,7 @@ PUBLISHED:
|
|||
int get_num_layers() const;
|
||||
GraphicsLayer *get_layer(int index) const;
|
||||
|
||||
GraphicsWindow *get_window() const;
|
||||
GraphicsOutput *get_window() const;
|
||||
GraphicsPipe *get_pipe() const;
|
||||
|
||||
void set_active(bool active);
|
||||
|
|
@ -73,7 +73,7 @@ private:
|
|||
|
||||
protected:
|
||||
Mutex _lock;
|
||||
GraphicsWindow *_window;
|
||||
GraphicsOutput *_window;
|
||||
bool _is_active;
|
||||
|
||||
typedef ov_multiset< PT(GraphicsLayer), IndirectLess<GraphicsLayer> > GraphicsLayers;
|
||||
|
|
@ -99,7 +99,7 @@ public:
|
|||
private:
|
||||
static TypeHandle _type_handle;
|
||||
|
||||
friend class GraphicsWindow;
|
||||
friend class GraphicsOutput;
|
||||
friend class GraphicsLayer;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -211,7 +211,7 @@ make_window(GraphicsPipe *pipe, GraphicsStateGuardian *gsg,
|
|||
PT(GraphicsWindow) window = pipe->make_window(gsg);
|
||||
if (window != (GraphicsWindow *)NULL) {
|
||||
MutexHolder holder(_lock);
|
||||
_windows.insert(window);
|
||||
_windows.insert(window.p());
|
||||
|
||||
WindowRenderer *cull = get_window_renderer(threading_model.get_cull_name());
|
||||
WindowRenderer *draw = get_window_renderer(threading_model.get_draw_name());
|
||||
|
|
@ -263,9 +263,9 @@ make_window(GraphicsPipe *pipe, GraphicsStateGuardian *gsg,
|
|||
// at a time.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool GraphicsEngine::
|
||||
remove_window(GraphicsWindow *window) {
|
||||
remove_window(GraphicsOutput *window) {
|
||||
// First, make sure we know what this window is.
|
||||
PT(GraphicsWindow) ptwin = window;
|
||||
PT(GraphicsOutput) ptwin = window;
|
||||
size_t count;
|
||||
{
|
||||
MutexHolder holder(_lock);
|
||||
|
|
@ -291,7 +291,7 @@ void GraphicsEngine::
|
|||
remove_all_windows() {
|
||||
Windows::iterator wi;
|
||||
for (wi = _windows.begin(); wi != _windows.end(); ++wi) {
|
||||
GraphicsWindow *win = (*wi);
|
||||
GraphicsOutput *win = (*wi);
|
||||
do_remove_window(win);
|
||||
}
|
||||
|
||||
|
|
@ -314,7 +314,7 @@ void GraphicsEngine::
|
|||
reset_all_windows(bool swapchain) {
|
||||
Windows::iterator wi;
|
||||
for (wi = _windows.begin(); wi != _windows.end(); ++wi) {
|
||||
GraphicsWindow *win = (*wi);
|
||||
GraphicsOutput *win = (*wi);
|
||||
// if (win->is_active())
|
||||
win->reset_window(swapchain);
|
||||
}
|
||||
|
|
@ -477,7 +477,7 @@ void GraphicsEngine::
|
|||
cull_and_draw_together(const GraphicsEngine::Windows &wlist) {
|
||||
Windows::const_iterator wi;
|
||||
for (wi = wlist.begin(); wi != wlist.end(); ++wi) {
|
||||
GraphicsWindow *win = (*wi);
|
||||
GraphicsOutput *win = (*wi);
|
||||
if (win->is_active()) {
|
||||
if (win->begin_frame()) {
|
||||
win->clear();
|
||||
|
|
@ -533,7 +533,7 @@ void GraphicsEngine::
|
|||
cull_bin_draw(const GraphicsEngine::Windows &wlist) {
|
||||
Windows::const_iterator wi;
|
||||
for (wi = wlist.begin(); wi != wlist.end(); ++wi) {
|
||||
GraphicsWindow *win = (*wi);
|
||||
GraphicsOutput *win = (*wi);
|
||||
if (win->is_active()) {
|
||||
// This should be done in the draw thread, not here.
|
||||
if (win->begin_frame()) {
|
||||
|
|
@ -596,7 +596,7 @@ void GraphicsEngine::
|
|||
process_events(const GraphicsEngine::Windows &wlist) {
|
||||
Windows::const_iterator wi;
|
||||
for (wi = wlist.begin(); wi != wlist.end(); ++wi) {
|
||||
GraphicsWindow *win = (*wi);
|
||||
GraphicsOutput *win = (*wi);
|
||||
win->process_events();
|
||||
}
|
||||
}
|
||||
|
|
@ -612,11 +612,11 @@ void GraphicsEngine::
|
|||
flip_windows(const GraphicsEngine::Windows &wlist) {
|
||||
Windows::const_iterator wi;
|
||||
for (wi = wlist.begin(); wi != wlist.end(); ++wi) {
|
||||
GraphicsWindow *win = (*wi);
|
||||
GraphicsOutput *win = (*wi);
|
||||
win->begin_flip();
|
||||
}
|
||||
for (wi = wlist.begin(); wi != wlist.end(); ++wi) {
|
||||
GraphicsWindow *win = (*wi);
|
||||
GraphicsOutput *win = (*wi);
|
||||
win->end_flip();
|
||||
}
|
||||
}
|
||||
|
|
@ -853,7 +853,7 @@ setup_gsg(GraphicsStateGuardian *gsg, SceneSetup *scene_setup) {
|
|||
// _windows list itself.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void GraphicsEngine::
|
||||
do_remove_window(GraphicsWindow *window) {
|
||||
do_remove_window(GraphicsOutput *window) {
|
||||
PT(GraphicsPipe) pipe = window->get_pipe();
|
||||
window->_pipe = (GraphicsPipe *)NULL;
|
||||
|
||||
|
|
@ -967,7 +967,7 @@ add_gsg(GraphicsStateGuardian *gsg) {
|
|||
// be a member of the WindowRenderer.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void GraphicsEngine::WindowRenderer::
|
||||
add_window(Windows &wlist, GraphicsWindow *window) {
|
||||
add_window(Windows &wlist, GraphicsOutput *window) {
|
||||
MutexHolder holder(_wl_lock);
|
||||
wlist.insert(window);
|
||||
}
|
||||
|
|
@ -981,9 +981,9 @@ add_window(Windows &wlist, GraphicsWindow *window) {
|
|||
// list for later closure.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void GraphicsEngine::WindowRenderer::
|
||||
remove_window(GraphicsWindow *window) {
|
||||
remove_window(GraphicsOutput *window) {
|
||||
MutexHolder holder(_wl_lock);
|
||||
PT(GraphicsWindow) ptwin = window;
|
||||
PT(GraphicsOutput) ptwin = window;
|
||||
|
||||
_cull.erase(ptwin);
|
||||
|
||||
|
|
@ -1020,14 +1020,12 @@ remove_window(GraphicsWindow *window) {
|
|||
// thread.
|
||||
|
||||
// Make sure the window isn't about to request itself open.
|
||||
WindowProperties close_properties;
|
||||
close_properties.set_open(false);
|
||||
ptwin->request_properties(close_properties);
|
||||
ptwin->request_close();
|
||||
|
||||
// If the window is already open, move it to the _pending_close list so
|
||||
// it can be closed later. We can't close it immediately, because
|
||||
// we might not have been called from the subthread.
|
||||
if (!ptwin->is_closed()) {
|
||||
if (ptwin->is_valid()) {
|
||||
_pending_close.insert(ptwin);
|
||||
}
|
||||
|
||||
|
|
@ -1095,7 +1093,7 @@ do_release(GraphicsEngine *) {
|
|||
MutexHolder holder(_wl_lock);
|
||||
Windows::iterator wi;
|
||||
for (wi = _draw.begin(); wi != _draw.end(); ++wi) {
|
||||
GraphicsWindow *win = (*wi);
|
||||
GraphicsOutput *win = (*wi);
|
||||
win->release_gsg();
|
||||
}
|
||||
}
|
||||
|
|
@ -1107,14 +1105,11 @@ do_release(GraphicsEngine *) {
|
|||
////////////////////////////////////////////////////////////////////
|
||||
void GraphicsEngine::WindowRenderer::
|
||||
do_close(GraphicsEngine *engine) {
|
||||
WindowProperties close_properties;
|
||||
close_properties.set_open(false);
|
||||
|
||||
MutexHolder holder(_wl_lock);
|
||||
Windows::iterator wi;
|
||||
for (wi = _window.begin(); wi != _window.end(); ++wi) {
|
||||
GraphicsWindow *win = (*wi);
|
||||
win->set_properties_now(close_properties);
|
||||
GraphicsOutput *win = (*wi);
|
||||
win->set_close_now();
|
||||
}
|
||||
|
||||
// Also close all of the GSG's.
|
||||
|
|
@ -1149,24 +1144,21 @@ do_pending(GraphicsEngine *engine) {
|
|||
// Release any GSG's that were waiting.
|
||||
Windows::iterator wi;
|
||||
for (wi = _pending_release.begin(); wi != _pending_release.end(); ++wi) {
|
||||
GraphicsWindow *win = (*wi);
|
||||
GraphicsOutput *win = (*wi);
|
||||
win->release_gsg();
|
||||
}
|
||||
_pending_release.clear();
|
||||
}
|
||||
|
||||
if (!_pending_close.empty()) {
|
||||
WindowProperties close_properties;
|
||||
close_properties.set_open(false);
|
||||
|
||||
// Close any windows that were pending closure, but only if their
|
||||
// associated GSG has already been released.
|
||||
Windows new_pending_close;
|
||||
Windows::iterator wi;
|
||||
for (wi = _pending_close.begin(); wi != _pending_close.end(); ++wi) {
|
||||
GraphicsWindow *win = (*wi);
|
||||
GraphicsOutput *win = (*wi);
|
||||
if (win->get_gsg() == (GraphicsStateGuardian *)NULL) {
|
||||
win->set_properties_now(close_properties);
|
||||
win->set_close_now();
|
||||
} else {
|
||||
// If the GSG hasn't been released yet, we have to save the
|
||||
// close operation for next frame.
|
||||
|
|
|
|||
|
|
@ -75,7 +75,7 @@ PUBLISHED:
|
|||
GraphicsWindow *make_window(GraphicsPipe *pipe,
|
||||
GraphicsStateGuardian *gsg,
|
||||
const GraphicsThreadingModel &threading_model);
|
||||
bool remove_window(GraphicsWindow *window);
|
||||
bool remove_window(GraphicsOutput *window);
|
||||
void remove_all_windows();
|
||||
void reset_all_windows(bool swapchain);
|
||||
bool is_empty() const;
|
||||
|
|
@ -97,7 +97,7 @@ public:
|
|||
};
|
||||
|
||||
private:
|
||||
typedef pset< PT(GraphicsWindow) > Windows;
|
||||
typedef pset< PT(GraphicsOutput) > Windows;
|
||||
typedef pset< PT(GraphicsStateGuardian) > GSGs;
|
||||
|
||||
void cull_and_draw_together(const Windows &wlist);
|
||||
|
|
@ -121,7 +121,7 @@ private:
|
|||
|
||||
bool setup_gsg(GraphicsStateGuardian *gsg, SceneSetup *scene_setup);
|
||||
|
||||
void do_remove_window(GraphicsWindow *window);
|
||||
void do_remove_window(GraphicsOutput *window);
|
||||
void terminate_threads();
|
||||
|
||||
// The WindowRenderer class records the stages of the pipeline that
|
||||
|
|
@ -130,8 +130,8 @@ private:
|
|||
class WindowRenderer {
|
||||
public:
|
||||
void add_gsg(GraphicsStateGuardian *gsg);
|
||||
void add_window(Windows &wlist, GraphicsWindow *window);
|
||||
void remove_window(GraphicsWindow *window);
|
||||
void add_window(Windows &wlist, GraphicsOutput *window);
|
||||
void remove_window(GraphicsOutput *window);
|
||||
void do_frame(GraphicsEngine *engine);
|
||||
void do_flip(GraphicsEngine *engine);
|
||||
void do_release(GraphicsEngine *engine);
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@
|
|||
|
||||
#include "graphicsLayer.h"
|
||||
#include "graphicsChannel.h"
|
||||
#include "graphicsWindow.h"
|
||||
#include "graphicsOutput.h"
|
||||
#include "config_display.h"
|
||||
#include "notify.h"
|
||||
#include "mutexHolder.h"
|
||||
|
|
@ -222,11 +222,11 @@ get_channel() const {
|
|||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GraphicsLayer::get_window
|
||||
// Access: Published
|
||||
// Description: Returns the GraphicsWindow that this layer is
|
||||
// Description: Returns the GraphicsOutput that this layer is
|
||||
// ultimately associated with, or NULL if no window is
|
||||
// associated.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
GraphicsWindow *GraphicsLayer::
|
||||
GraphicsOutput *GraphicsLayer::
|
||||
get_window() const {
|
||||
MutexHolder holder(_lock);
|
||||
return (_channel != (GraphicsChannel *)NULL) ? _channel->get_window() : NULL;
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@
|
|||
#include "pvector.h"
|
||||
|
||||
class GraphicsChannel;
|
||||
class GraphicsWindow;
|
||||
class GraphicsOutput;
|
||||
class GraphicsPipe;
|
||||
class CullHandler;
|
||||
|
||||
|
|
@ -67,7 +67,7 @@ PUBLISHED:
|
|||
bool remove_dr(DisplayRegion *display_region);
|
||||
|
||||
GraphicsChannel *get_channel() const;
|
||||
GraphicsWindow *get_window() const;
|
||||
GraphicsOutput *get_window() const;
|
||||
GraphicsPipe *get_pipe() const;
|
||||
|
||||
void set_active(bool active);
|
||||
|
|
@ -109,7 +109,7 @@ private:
|
|||
static TypeHandle _type_handle;
|
||||
|
||||
friend class GraphicsChannel;
|
||||
friend class GraphicsWindow;
|
||||
friend class GraphicsOutput;
|
||||
friend class DisplayRegion;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,142 @@
|
|||
// Filename: graphicsOutput.I
|
||||
// Created by: drose (06Feb04)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 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 .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GraphicsOutput::get_gsg
|
||||
// Access: Published
|
||||
// Description: Returns the GSG that is associated with this window.
|
||||
// There is a one-to-one association between windows and
|
||||
// GSG's.
|
||||
//
|
||||
// This may return NULL if the graphics context has not
|
||||
// yet been created for the window, e.g. before the
|
||||
// first frame has rendered; or after the window has
|
||||
// been closed.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE GraphicsStateGuardian *GraphicsOutput::
|
||||
get_gsg() const {
|
||||
return _gsg;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GraphicsOutput::get_pipe
|
||||
// Access: Published
|
||||
// Description: Returns the GraphicsPipe that this window is
|
||||
// associated with. It is possible that the
|
||||
// GraphicsPipe might have been deleted while an
|
||||
// outstanding PT(GraphicsOutput) prevented all of its
|
||||
// children windows from also being deleted; in this
|
||||
// unlikely case, get_pipe() may return NULL.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE GraphicsPipe *GraphicsOutput::
|
||||
get_pipe() const {
|
||||
return _pipe;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GraphicsOutput::get_x_size
|
||||
// Access: Published
|
||||
// Description: Returns the width of the graphics frame buffer, if it
|
||||
// is known. In certain cases (e.g. fullscreen
|
||||
// windows), the size may not be known until after the
|
||||
// object has been fully created. Check has_size()
|
||||
// first.
|
||||
//
|
||||
// Certain objects (like windows) may change size
|
||||
// spontaneously; this method is not thread-safe. To
|
||||
// get the size of a window in a thread-safe manner,
|
||||
// query get_properties().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE int GraphicsOutput::
|
||||
get_x_size() const {
|
||||
return _x_size;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GraphicsOutput::get_y_size
|
||||
// Access: Published
|
||||
// Description: Returns the height of the graphics frame buffer, if it
|
||||
// is known. In certain cases (e.g. fullscreen
|
||||
// windows), the size may not be known until after the
|
||||
// object has been fully created. Check has_size()
|
||||
// first.
|
||||
//
|
||||
// Certain objects (like windows) may change size
|
||||
// spontaneously; this method is not thread-safe. To
|
||||
// get the size of a window in a thread-safe manner,
|
||||
// query get_properties().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE int GraphicsOutput::
|
||||
get_y_size() const {
|
||||
return _y_size;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GraphicsOutput::has_size
|
||||
// Access: Published
|
||||
// Description: Returns true if the size of the window/frame buffer
|
||||
// is known, false otherwise. In certain cases the size
|
||||
// may not be known until after the object has been
|
||||
// fully created. Also, certain objects (like windows)
|
||||
// may change size spontaneously.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE bool GraphicsOutput::
|
||||
has_size() const {
|
||||
return _has_size;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GraphicsOutput::is_valid
|
||||
// Access: Published
|
||||
// Description: Returns true if the output is fully created and ready
|
||||
// for rendering, false otherwise.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE bool GraphicsOutput::
|
||||
is_valid() const {
|
||||
return _is_valid;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GraphicsOutput::win_display_regions_changed
|
||||
// Access: Public
|
||||
// Description: Intended to be called when the active state on a
|
||||
// nested channel or layer or display region changes,
|
||||
// forcing the window to recompute its list of active
|
||||
// display regions.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void GraphicsOutput::
|
||||
win_display_regions_changed() {
|
||||
_display_regions_stale = true;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GraphicsOutput::determine_display_regions
|
||||
// Access: Private
|
||||
// Description: Recomputes the list of active DisplayRegions within
|
||||
// the window, if they have changed recently.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void GraphicsOutput::
|
||||
determine_display_regions() const {
|
||||
// This function isn't strictly speaking const, but we pretend it is
|
||||
// because it only updates a transparent cache value.
|
||||
if (_display_regions_stale) {
|
||||
((GraphicsOutput *)this)->do_determine_display_regions();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,663 @@
|
|||
// Filename: graphicsOutput.cxx
|
||||
// Created by: drose (06Feb04)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 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 "graphicsOutput.h"
|
||||
#include "graphicsPipe.h"
|
||||
#include "config_display.h"
|
||||
#include "mutexHolder.h"
|
||||
#include "hardwareChannel.h"
|
||||
|
||||
TypeHandle GraphicsOutput::_type_handle;
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GraphicsOutput::Constructor
|
||||
// Access: Protected
|
||||
// Description: Normally, the GraphicsOutput constructor is not
|
||||
// called directly; these are created instead via the
|
||||
// GraphicsEngine::make_window() function.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
GraphicsOutput::
|
||||
GraphicsOutput(GraphicsPipe *pipe, GraphicsStateGuardian *gsg) {
|
||||
#ifdef DO_MEMORY_USAGE
|
||||
MemoryUsage::update_type(this, this);
|
||||
#endif
|
||||
_pipe = pipe;
|
||||
_gsg = gsg;
|
||||
_x_size = 0;
|
||||
_y_size = 0;
|
||||
_has_size = false;
|
||||
_is_valid = false;
|
||||
|
||||
_display_regions_stale = false;
|
||||
|
||||
// By default, each new GraphicsOutput is set up to clear color and
|
||||
// depth.
|
||||
set_clear_color_active(true);
|
||||
set_clear_depth_active(true);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GraphicsOutput::Copy Constructor
|
||||
// Access: Private
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
GraphicsOutput::
|
||||
GraphicsOutput(const GraphicsOutput &) {
|
||||
nassertv(false);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GraphicsOutput::Copy Assignment Operator
|
||||
// Access: Private
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void GraphicsOutput::
|
||||
operator = (const GraphicsOutput &) {
|
||||
nassertv(false);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GraphicsOutput::Destructor
|
||||
// Access: Published, Virtual
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
GraphicsOutput::
|
||||
~GraphicsOutput() {
|
||||
// The window should be closed by the time we destruct.
|
||||
nassertv(!is_valid());
|
||||
|
||||
// We shouldn't have a GraphicsPipe pointer anymore.
|
||||
nassertv(_pipe == (GraphicsPipe *)NULL);
|
||||
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GraphicsOutput::is_active
|
||||
// Access: Published, Virtual
|
||||
// Description: Returns true if the window is ready to be rendered
|
||||
// into, false otherwise.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool GraphicsOutput::
|
||||
is_active() const {
|
||||
return is_valid();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GraphicsOutput::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 *GraphicsOutput::
|
||||
get_channel(int index) {
|
||||
MutexHolder holder(_lock);
|
||||
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.
|
||||
GraphicsPipe *pipe = _pipe;
|
||||
if (pipe != (GraphicsPipe *)NULL) {
|
||||
chan = _pipe->get_hw_channel(this, index);
|
||||
if (chan == (GraphicsChannel *)NULL) {
|
||||
display_cat.error()
|
||||
<< "GraphicsOutput::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: GraphicsOutput::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 GraphicsOutput::
|
||||
remove_channel(int index) {
|
||||
MutexHolder holder(_lock);
|
||||
if (index >= 0 && index < (int)_channels.size()) {
|
||||
_channels[index].clear();
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GraphicsOutput::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 GraphicsOutput::
|
||||
get_max_channel_index() const {
|
||||
int result;
|
||||
{
|
||||
MutexHolder holder(_lock);
|
||||
result = _channels.size();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GraphicsOutput::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 GraphicsOutput::
|
||||
is_channel_defined(int index) const {
|
||||
bool result;
|
||||
{
|
||||
MutexHolder holder(_lock);
|
||||
if (index < 0 || index >= (int)_channels.size()) {
|
||||
result = false;
|
||||
} else {
|
||||
result = (_channels[index] != (GraphicsChannel *)NULL);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GraphicsOutput::get_num_display_regions
|
||||
// Access: Published
|
||||
// Description: Returns the number of active DisplayRegions that have
|
||||
// been created within the various layers and channels
|
||||
// of the window.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
int GraphicsOutput::
|
||||
get_num_display_regions() const {
|
||||
determine_display_regions();
|
||||
int result;
|
||||
{
|
||||
MutexHolder holder(_lock);
|
||||
result = _display_regions.size();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GraphicsOutput::get_display_region
|
||||
// Access: Published
|
||||
// Description: Returns the nth active DisplayRegion of those that
|
||||
// have been created within the various layers and
|
||||
// channels of the window. This may return NULL if n is
|
||||
// out of bounds; particularly likely if the number of
|
||||
// display regions has changed since the last call to
|
||||
// get_num_display_regions().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
DisplayRegion *GraphicsOutput::
|
||||
get_display_region(int n) const {
|
||||
determine_display_regions();
|
||||
DisplayRegion *result;
|
||||
{
|
||||
MutexHolder holder(_lock);
|
||||
if (n >= 0 && n < (int)_display_regions.size()) {
|
||||
result = _display_regions[n];
|
||||
} else {
|
||||
result = NULL;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GraphicsOutput::take_screenshot
|
||||
// Access: Published
|
||||
// Description: Saves a screenshot of the window to a default
|
||||
// filename, and returns the filename, or empty string
|
||||
// if the screenshot failed. The default filename is
|
||||
// generated from the supplied prefix and from the
|
||||
// Configrc variable screenshot-filename, which contains
|
||||
// the following strings:
|
||||
//
|
||||
// %~p - the supplied prefix
|
||||
// %~f - the frame count
|
||||
// %~e - the value of screenshot-extension
|
||||
// All other % strings in strftime().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
Filename GraphicsOutput::
|
||||
take_screenshot(const string &prefix) {
|
||||
time_t now = time(NULL);
|
||||
struct tm *ttm = localtime(&now);
|
||||
int frame_count = ClockObject::get_global_clock()->get_frame_count();
|
||||
|
||||
static const int buffer_size = 1024;
|
||||
char buffer[buffer_size];
|
||||
|
||||
ostringstream filename_strm;
|
||||
|
||||
size_t i = 0;
|
||||
while (i < screenshot_filename.length()) {
|
||||
char ch1 = screenshot_filename[i++];
|
||||
if (ch1 == '%' && i < screenshot_filename.length()) {
|
||||
char ch2 = screenshot_filename[i++];
|
||||
if (ch2 == '~' && i < screenshot_filename.length()) {
|
||||
char ch3 = screenshot_filename[i++];
|
||||
switch (ch3) {
|
||||
case 'p':
|
||||
filename_strm << prefix;
|
||||
break;
|
||||
|
||||
case 'f':
|
||||
filename_strm << frame_count;
|
||||
break;
|
||||
|
||||
case 'e':
|
||||
filename_strm << screenshot_extension;
|
||||
break;
|
||||
}
|
||||
|
||||
} else {
|
||||
// Use strftime() to decode the percent code.
|
||||
char format[3] = {'%', ch2, '\0'};
|
||||
if (strftime(buffer, buffer_size, format, ttm)) {
|
||||
for (char *b = buffer; *b != '\0'; b++) {
|
||||
switch (*b) {
|
||||
case ' ':
|
||||
case ':':
|
||||
case '/':
|
||||
filename_strm << '-';
|
||||
break;
|
||||
|
||||
case '\n':
|
||||
break;
|
||||
|
||||
default:
|
||||
filename_strm << *b;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
filename_strm << ch1;
|
||||
}
|
||||
}
|
||||
|
||||
Filename filename = filename_strm.str();
|
||||
if (take_screenshot(filename)) {
|
||||
return filename;
|
||||
}
|
||||
return Filename();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GraphicsOutput::take_screenshot
|
||||
// Access: Published
|
||||
// Description: Saves a screenshot of the window to the indicated
|
||||
// filename. Returns true on success, false on failure.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool GraphicsOutput::
|
||||
take_screenshot(const Filename &filename) {
|
||||
if (_gsg == (GraphicsStateGuardian *)NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!is_valid()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
PixelBuffer p(_x_size, _y_size, 3, 1, PixelBuffer::T_unsigned_byte,
|
||||
PixelBuffer::F_rgb);
|
||||
|
||||
DisplayRegion dr(_x_size, _y_size);
|
||||
RenderBuffer rb = _gsg->get_render_buffer(RenderBuffer::T_front);
|
||||
if (!p.copy(_gsg, &dr, rb)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!p.write(filename)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GraphicsOutput::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) GraphicsOutput::
|
||||
make_scratch_display_region(int x_size, int y_size) const {
|
||||
#ifndef NDEBUG
|
||||
if (x_size > _x_size || y_size > _y_size) {
|
||||
display_cat.error()
|
||||
<< "make_scratch_display_region(): requested region of size "
|
||||
<< x_size << ", " << y_size << " is larger than window of size "
|
||||
<< _x_size << ", " << _y_size << ".\n";
|
||||
x_size = min(x_size, _x_size);
|
||||
y_size = min(y_size, _y_size);
|
||||
}
|
||||
#endif
|
||||
|
||||
PT(DisplayRegion) region = new DisplayRegion(x_size, y_size);
|
||||
region->copy_clear_settings(*this);
|
||||
return region;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GraphicsOutput::request_open
|
||||
// Access: Public, Virtual
|
||||
// Description: This is called by the GraphicsEngine to request that
|
||||
// the window (or whatever) open itself or, in general,
|
||||
// make itself valid, at the next call to
|
||||
// process_events().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void GraphicsOutput::
|
||||
request_open() {
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GraphicsOutput::request_close
|
||||
// Access: Public, Virtual
|
||||
// Description: This is called by the GraphicsEngine to request that
|
||||
// the window (or whatever) close itself or, in general,
|
||||
// make itself invalid, at the next call to
|
||||
// process_events(). By that time we promise the gsg
|
||||
// pointer will be cleared.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void GraphicsOutput::
|
||||
request_close() {
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GraphicsOutput::set_close_now
|
||||
// Access: Public, Virtual
|
||||
// Description: This is called by the GraphicsEngine to insist that
|
||||
// the output be closed immediately. This is only
|
||||
// called from the window thread.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void GraphicsOutput::
|
||||
set_close_now() {
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GraphicsOutput::begin_frame
|
||||
// Access: Public, Virtual
|
||||
// Description: This function will be called within the draw thread
|
||||
// before beginning rendering for a given frame. It
|
||||
// should do whatever setup is required, and return true
|
||||
// if the frame should be rendered, or false if it
|
||||
// should be skipped.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool GraphicsOutput::
|
||||
begin_frame() {
|
||||
if (_gsg == (GraphicsStateGuardian *)NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Okay, we already have a GSG, so activate it.
|
||||
make_current();
|
||||
return _gsg->begin_frame();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GraphicsOutput::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).
|
||||
//
|
||||
// This function is called only within the draw thread.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void GraphicsOutput::
|
||||
clear() {
|
||||
if (is_any_clear_active()) {
|
||||
nassertv(_gsg != (GraphicsStateGuardian *)NULL);
|
||||
|
||||
PT(DisplayRegion) win_dr =
|
||||
make_scratch_display_region(_x_size, _y_size);
|
||||
DisplayRegionStack old_dr = _gsg->push_display_region(win_dr);
|
||||
_gsg->clear(this);
|
||||
_gsg->pop_display_region(old_dr);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GraphicsOutput::end_frame
|
||||
// Access: Public, Virtual
|
||||
// Description: This function will be called within the draw thread
|
||||
// after rendering is completed for a given frame. It
|
||||
// should do whatever finalization is required.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void GraphicsOutput::
|
||||
end_frame() {
|
||||
nassertv(_gsg != (GraphicsStateGuardian *)NULL);
|
||||
_gsg->end_frame();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GraphicsOutput::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 GraphicsOutput::
|
||||
make_current() {
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GraphicsOutput::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 GraphicsOutput::
|
||||
release_gsg() {
|
||||
_gsg.clear();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GraphicsOutput::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 GraphicsOutput::
|
||||
begin_flip() {
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GraphicsOutput::end_flip
|
||||
// Access: Public, Virtual
|
||||
// Description: This function will be called within the draw thread
|
||||
// after begin_flip() has been called on all windows, to
|
||||
// finish the exchange of the front and back buffers.
|
||||
//
|
||||
// This should cause the window to wait for the flip, if
|
||||
// necessary.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void GraphicsOutput::
|
||||
end_flip() {
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GraphicsOutput::process_events
|
||||
// Access: Public, Virtual
|
||||
// Description: Do whatever processing in the window thread is
|
||||
// appropriate for this output object each frame.
|
||||
//
|
||||
// This function is called only within the window
|
||||
// thread.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void GraphicsOutput::
|
||||
process_events() {
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GraphicsOutput::close_window
|
||||
// Access: Protected, Virtual
|
||||
// Description: Closes the window right now. Called from the window
|
||||
// thread.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void GraphicsOutput::
|
||||
close_window() {
|
||||
display_cat.info()
|
||||
<< "Closing " << get_type() << "\n";
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GraphicsOutput::reset_window
|
||||
// Access: Protected, Virtual
|
||||
// Description: resets the window framebuffer from its derived
|
||||
// children. Does nothing here.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void GraphicsOutput::
|
||||
reset_window(bool swapchain) {
|
||||
display_cat.info()
|
||||
<< "Resetting " << get_type() << "\n";
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GraphicsOutput::open_window
|
||||
// Access: Protected, Virtual
|
||||
// Description: Opens the window right now. Called from the window
|
||||
// thread. Returns true if the window is successfully
|
||||
// opened, or false if there was a problem.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool GraphicsOutput::
|
||||
open_window() {
|
||||
return false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GraphicsOutput::declare_channel
|
||||
// Access: Protected
|
||||
// Description: An internal function to add the indicated
|
||||
// newly-created channel to the list at the indicated
|
||||
// channel number.
|
||||
//
|
||||
// The caller must grab and hold _lock before making
|
||||
// this call.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void GraphicsOutput::
|
||||
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: GraphicsOutput::do_determine_display_regions
|
||||
// Access: Private
|
||||
// Description: Recomputes the list of active DisplayRegions within
|
||||
// the window.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void GraphicsOutput::
|
||||
do_determine_display_regions() {
|
||||
MutexHolder holder(_lock);
|
||||
_display_regions_stale = false;
|
||||
_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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,180 @@
|
|||
// Filename: graphicsOutput.h
|
||||
// Created by: drose (06Feb04)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 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 GRAPHICSOUTPUT_H
|
||||
#define GRAPHICSOUTPUT_H
|
||||
|
||||
#include "pandabase.h"
|
||||
|
||||
#include "graphicsChannel.h"
|
||||
#include "graphicsPipe.h"
|
||||
#include "displayRegion.h"
|
||||
#include "graphicsStateGuardian.h"
|
||||
#include "clearableRegion.h"
|
||||
|
||||
#include "typedWritableReferenceCount.h"
|
||||
#include "notify.h"
|
||||
#include "pmutex.h"
|
||||
#include "filename.h"
|
||||
#include "pvector.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : GraphicsOutput
|
||||
// Description : This is a base class for the various different
|
||||
// classes that represent the result of a frame of
|
||||
// rendering. The most common kind of GraphicsOutput is
|
||||
// a GraphicsWindow, which is a real-time window on the
|
||||
// desktop, but other examples are GraphicsBuffer, which
|
||||
// is an offscreen buffer, and GraphicsTexture, which is
|
||||
// an offscreen texture that may be rendered into and
|
||||
// then applied to geometry.
|
||||
//
|
||||
// The actual rendering, and anything associated with
|
||||
// the graphics context itself, is managed by the
|
||||
// associated GraphicsStateGuardian (which might output
|
||||
// to multiple GraphicsOutput objects).
|
||||
//
|
||||
// GraphicsOutputs are not actually writable to bam
|
||||
// files, of course, but they may be passed as event
|
||||
// parameters, so they inherit from
|
||||
// TypedWritableReferenceCount instead of
|
||||
// TypedReferenceCount for that convenience.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
class EXPCL_PANDA GraphicsOutput : public TypedWritableReferenceCount, public ClearableRegion {
|
||||
protected:
|
||||
GraphicsOutput(GraphicsPipe *pipe, GraphicsStateGuardian *gsg);
|
||||
|
||||
private:
|
||||
GraphicsOutput(const GraphicsOutput ©);
|
||||
void operator = (const GraphicsOutput ©);
|
||||
|
||||
PUBLISHED:
|
||||
virtual ~GraphicsOutput();
|
||||
|
||||
INLINE GraphicsStateGuardian *get_gsg() const;
|
||||
INLINE GraphicsPipe *get_pipe() const;
|
||||
|
||||
INLINE int get_x_size() const;
|
||||
INLINE int get_y_size() const;
|
||||
INLINE bool has_size() const;
|
||||
INLINE bool is_valid() const;
|
||||
|
||||
virtual bool is_active() const;
|
||||
|
||||
GraphicsChannel *get_channel(int index);
|
||||
void remove_channel(int index);
|
||||
|
||||
int get_max_channel_index() const;
|
||||
bool is_channel_defined(int index) const;
|
||||
|
||||
int get_num_display_regions() const;
|
||||
DisplayRegion *get_display_region(int n) const;
|
||||
|
||||
Filename take_screenshot(const string &prefix = "screenshot");
|
||||
bool take_screenshot(const Filename &filename);
|
||||
|
||||
public:
|
||||
// No need to publish these.
|
||||
PT(DisplayRegion) make_scratch_display_region(int x_size, int y_size) const;
|
||||
|
||||
public:
|
||||
// These are not intended to be called directly by the user.
|
||||
INLINE void win_display_regions_changed();
|
||||
|
||||
virtual void request_open();
|
||||
virtual void request_close();
|
||||
virtual void set_close_now();
|
||||
|
||||
public:
|
||||
// It is an error to call any of the following methods from any
|
||||
// thread other than the draw thread. These methods are normally
|
||||
// called by the GraphicsEngine.
|
||||
virtual bool begin_frame();
|
||||
void clear();
|
||||
virtual void end_frame();
|
||||
|
||||
// This method is called in the draw thread prior to issuing any
|
||||
// drawing commands for the window.
|
||||
virtual void make_current();
|
||||
virtual void release_gsg();
|
||||
|
||||
// These methods will be called within the app (main) thread.
|
||||
virtual void begin_flip();
|
||||
virtual void end_flip();
|
||||
|
||||
// It is an error to call any of the following methods from any
|
||||
// thread other than the window thread. These methods are normally
|
||||
// called by the GraphicsEngine.
|
||||
virtual void process_events();
|
||||
|
||||
protected:
|
||||
virtual void close_window();
|
||||
virtual bool open_window();
|
||||
virtual void reset_window(bool swapchain);
|
||||
|
||||
void declare_channel(int index, GraphicsChannel *chan);
|
||||
|
||||
protected:
|
||||
PT(GraphicsStateGuardian) _gsg;
|
||||
PT(GraphicsPipe) _pipe;
|
||||
|
||||
private:
|
||||
INLINE void determine_display_regions() const;
|
||||
void do_determine_display_regions();
|
||||
|
||||
protected:
|
||||
Mutex _lock;
|
||||
// protects _channels, _display_regions.
|
||||
|
||||
typedef pvector< PT(GraphicsChannel) > Channels;
|
||||
Channels _channels;
|
||||
|
||||
typedef pvector<DisplayRegion *> DisplayRegions;
|
||||
DisplayRegions _display_regions;
|
||||
bool _display_regions_stale;
|
||||
|
||||
protected:
|
||||
int _x_size;
|
||||
int _y_size;
|
||||
bool _has_size;
|
||||
bool _is_valid;
|
||||
|
||||
public:
|
||||
static TypeHandle get_class_type() {
|
||||
return _type_handle;
|
||||
}
|
||||
static void init_type() {
|
||||
TypedWritableReferenceCount::init_type();
|
||||
register_type(_type_handle, "GraphicsOutput",
|
||||
TypedWritableReferenceCount::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;
|
||||
|
||||
friend class GraphicsPipe;
|
||||
friend class GraphicsEngine;
|
||||
};
|
||||
|
||||
#include "graphicsOutput.I"
|
||||
|
||||
#endif /* GRAPHICSOUTPUT_H */
|
||||
|
|
@ -98,7 +98,7 @@ get_num_hw_channels() {
|
|||
// always return NULL.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
HardwareChannel *GraphicsPipe::
|
||||
get_hw_channel(GraphicsWindow *, int) {
|
||||
get_hw_channel(GraphicsOutput *, int) {
|
||||
return (HardwareChannel*)0L;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -25,16 +25,15 @@
|
|||
#include "typedReferenceCount.h"
|
||||
#include "pointerTo.h"
|
||||
#include "pmutex.h"
|
||||
#include "pvector.h"
|
||||
|
||||
class HardwareChannel;
|
||||
class GraphicsWindow;
|
||||
class GraphicsOutput;
|
||||
class GraphicsStateGuardian;
|
||||
class FrameBufferProperties;
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : GraphicsPipe
|
||||
// Description : An object to create GraphicsWindows that share a
|
||||
// Description : An object to create GraphicsOutputs that share a
|
||||
// particular 3-D API. Normally, there will only be one
|
||||
// GraphicsPipe in an application, although it is
|
||||
// possible to have multiple of these at once if there
|
||||
|
|
@ -74,7 +73,7 @@ PUBLISHED:
|
|||
|
||||
public:
|
||||
virtual int get_num_hw_channels();
|
||||
virtual HardwareChannel *get_hw_channel(GraphicsWindow *window, int index);
|
||||
virtual HardwareChannel *get_hw_channel(GraphicsOutput *window, int index);
|
||||
|
||||
INLINE GraphicsDevice *get_device() const;
|
||||
virtual PT(GraphicsDevice) make_device(void *scrn = NULL);
|
||||
|
|
|
|||
|
|
@ -33,18 +33,6 @@ is_closed() const {
|
|||
return !_properties.get_open();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GraphicsWindow::is_active
|
||||
// Access: Published
|
||||
// Description: Returns true if the window is ready to be rendered
|
||||
// into, false otherwise.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE bool GraphicsWindow::
|
||||
is_active() const {
|
||||
// Make this smarter?
|
||||
return _properties.get_open() && !_properties.get_minimized();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GraphicsWindow::is_fullscreen
|
||||
// Access: Published
|
||||
|
|
@ -55,64 +43,3 @@ INLINE bool GraphicsWindow::
|
|||
is_fullscreen() const {
|
||||
return _properties.get_fullscreen();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GraphicsWindow::get_gsg
|
||||
// Access: Published
|
||||
// Description: Returns the GSG that is associated with this window.
|
||||
// There is a one-to-one association between windows and
|
||||
// GSG's.
|
||||
//
|
||||
// This may return NULL if the graphics context has not
|
||||
// yet been created for the window, e.g. before the
|
||||
// first frame has rendered; or after the window has
|
||||
// been closed.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE GraphicsStateGuardian *GraphicsWindow::
|
||||
get_gsg() const {
|
||||
return _gsg;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GraphicsWindow::get_pipe
|
||||
// Access: Published
|
||||
// Description: Returns the GraphicsPipe that this window is
|
||||
// associated with. It is possible that the
|
||||
// GraphicsPipe might have been deleted while an
|
||||
// outstanding PT(GraphicsWindow) prevented all of its
|
||||
// children windows from also being deleted; in this
|
||||
// unlikely case, get_pipe() may return NULL.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE GraphicsPipe *GraphicsWindow::
|
||||
get_pipe() const {
|
||||
return _pipe;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GraphicsWindow::win_display_regions_changed
|
||||
// Access: Public
|
||||
// Description: Intended to be called when the active state on a
|
||||
// nested channel or layer or display region changes,
|
||||
// forcing the window to recompute its list of active
|
||||
// display regions.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void GraphicsWindow::
|
||||
win_display_regions_changed() {
|
||||
_display_regions_stale = true;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GraphicsWindow::determine_display_regions
|
||||
// Access: Private
|
||||
// Description: Recomputes the list of active DisplayRegions within
|
||||
// the window, if they have changed recently.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void GraphicsWindow::
|
||||
determine_display_regions() const {
|
||||
// This function isn't strictly speaking const, but we pretend it is
|
||||
// because it only updates a transparent cache value.
|
||||
if (_display_regions_stale) {
|
||||
((GraphicsWindow *)this)->do_determine_display_regions();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,8 +25,6 @@
|
|||
#include "hardwareChannel.h"
|
||||
#include "throw_event.h"
|
||||
|
||||
#include "pmap.h"
|
||||
|
||||
TypeHandle GraphicsWindow::_type_handle;
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -37,12 +35,12 @@ TypeHandle GraphicsWindow::_type_handle;
|
|||
// GraphicsEngine::make_window() function.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
GraphicsWindow::
|
||||
GraphicsWindow(GraphicsPipe *pipe, GraphicsStateGuardian *gsg) {
|
||||
GraphicsWindow(GraphicsPipe *pipe, GraphicsStateGuardian *gsg) :
|
||||
GraphicsOutput(pipe, gsg)
|
||||
{
|
||||
#ifdef DO_MEMORY_USAGE
|
||||
MemoryUsage::update_type(this, this);
|
||||
#endif
|
||||
_pipe = pipe;
|
||||
_gsg = gsg;
|
||||
|
||||
if (display_cat.is_debug()) {
|
||||
display_cat.debug()
|
||||
|
|
@ -58,32 +56,7 @@ GraphicsWindow(GraphicsPipe *pipe, GraphicsStateGuardian *gsg) {
|
|||
_properties.set_minimized(false);
|
||||
_properties.set_cursor_hidden(false);
|
||||
|
||||
_display_regions_stale = false;
|
||||
_window_event = "window-event";
|
||||
|
||||
// By default, windows are set up to clear color and depth.
|
||||
set_clear_color_active(true);
|
||||
set_clear_depth_active(true);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GraphicsWindow::Copy Constructor
|
||||
// Access: Private
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
GraphicsWindow::
|
||||
GraphicsWindow(const GraphicsWindow &) {
|
||||
nassertv(false);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GraphicsWindow::Copy Assignment Operator
|
||||
// Access: Private
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void GraphicsWindow::
|
||||
operator = (const GraphicsWindow &) {
|
||||
nassertv(false);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -93,20 +66,6 @@ operator = (const GraphicsWindow &) {
|
|||
////////////////////////////////////////////////////////////////////
|
||||
GraphicsWindow::
|
||||
~GraphicsWindow() {
|
||||
// The window should be closed by the time we destruct.
|
||||
nassertv(!_properties.get_open());
|
||||
|
||||
// And we shouldn't have a GraphicsPipe pointer anymore.
|
||||
nassertv(_pipe == (GraphicsPipe *)NULL);
|
||||
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -118,7 +77,7 @@ WindowProperties GraphicsWindow::
|
|||
get_properties() const {
|
||||
WindowProperties result;
|
||||
{
|
||||
MutexHolder holder(_lock);
|
||||
MutexHolder holder(_properties_lock);
|
||||
result = _properties;
|
||||
}
|
||||
return result;
|
||||
|
|
@ -136,7 +95,7 @@ WindowProperties GraphicsWindow::
|
|||
get_requested_properties() const {
|
||||
WindowProperties result;
|
||||
{
|
||||
MutexHolder holder(_lock);
|
||||
MutexHolder holder(_properties_lock);
|
||||
result = _requested_properties;
|
||||
}
|
||||
return result;
|
||||
|
|
@ -150,7 +109,7 @@ get_requested_properties() const {
|
|||
////////////////////////////////////////////////////////////////////
|
||||
void GraphicsWindow::
|
||||
clear_rejected_properties() {
|
||||
MutexHolder holder(_lock);
|
||||
MutexHolder holder(_properties_lock);
|
||||
_rejected_properties.clear();
|
||||
}
|
||||
|
||||
|
|
@ -167,7 +126,7 @@ WindowProperties GraphicsWindow::
|
|||
get_rejected_properties() const {
|
||||
WindowProperties result;
|
||||
{
|
||||
MutexHolder holder(_lock);
|
||||
MutexHolder holder(_properties_lock);
|
||||
result = _rejected_properties;
|
||||
}
|
||||
return result;
|
||||
|
|
@ -186,10 +145,22 @@ get_rejected_properties() const {
|
|||
////////////////////////////////////////////////////////////////////
|
||||
void GraphicsWindow::
|
||||
request_properties(const WindowProperties &requested_properties) {
|
||||
MutexHolder holder(_lock);
|
||||
MutexHolder holder(_properties_lock);
|
||||
_requested_properties.add_properties(requested_properties);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GraphicsWindow::is_active
|
||||
// Access: Published, Virtual
|
||||
// Description: Returns true if the window is ready to be rendered
|
||||
// into, false otherwise.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool GraphicsWindow::
|
||||
is_active() const {
|
||||
// Make this smarter?
|
||||
return _properties.get_open() && !_properties.get_minimized();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GraphicsWindow::set_window_event
|
||||
// Access: Published
|
||||
|
|
@ -204,7 +175,7 @@ request_properties(const WindowProperties &requested_properties) {
|
|||
////////////////////////////////////////////////////////////////////
|
||||
void GraphicsWindow::
|
||||
set_window_event(const string &window_event) {
|
||||
MutexHolder holder(_lock);
|
||||
MutexHolder holder(_properties_lock);
|
||||
_window_event = window_event;
|
||||
}
|
||||
|
||||
|
|
@ -218,289 +189,11 @@ set_window_event(const string &window_event) {
|
|||
string GraphicsWindow::
|
||||
get_window_event() const {
|
||||
string result;
|
||||
MutexHolder holder(_lock);
|
||||
MutexHolder holder(_properties_lock);
|
||||
result = _window_event;
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// 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) {
|
||||
MutexHolder holder(_lock);
|
||||
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.
|
||||
GraphicsPipe *pipe = _pipe;
|
||||
if (pipe != (GraphicsPipe *)NULL) {
|
||||
chan = _pipe->get_hw_channel(this, index);
|
||||
if (chan == (GraphicsChannel *)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) {
|
||||
MutexHolder holder(_lock);
|
||||
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 {
|
||||
int result;
|
||||
{
|
||||
MutexHolder holder(_lock);
|
||||
result = _channels.size();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// 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 {
|
||||
bool result;
|
||||
{
|
||||
MutexHolder holder(_lock);
|
||||
if (index < 0 || index >= (int)_channels.size()) {
|
||||
result = false;
|
||||
} else {
|
||||
result = (_channels[index] != (GraphicsChannel *)NULL);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GraphicsWindow::get_num_display_regions
|
||||
// Access: Published
|
||||
// Description: Returns the number of active DisplayRegions that have
|
||||
// been created within the various layers and channels
|
||||
// of the window.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
int GraphicsWindow::
|
||||
get_num_display_regions() const {
|
||||
determine_display_regions();
|
||||
int result;
|
||||
{
|
||||
MutexHolder holder(_lock);
|
||||
result = _display_regions.size();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GraphicsWindow::get_display_region
|
||||
// Access: Published
|
||||
// Description: Returns the nth active DisplayRegion of those that
|
||||
// have been created within the various layers and
|
||||
// channels of the window. This may return NULL if n is
|
||||
// out of bounds; particularly likely if the number of
|
||||
// display regions has changed since the last call to
|
||||
// get_num_display_regions().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
DisplayRegion *GraphicsWindow::
|
||||
get_display_region(int n) const {
|
||||
determine_display_regions();
|
||||
DisplayRegion *result;
|
||||
{
|
||||
MutexHolder holder(_lock);
|
||||
if (n >= 0 && n < (int)_display_regions.size()) {
|
||||
result = _display_regions[n];
|
||||
} else {
|
||||
result = NULL;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GraphicsWindow::take_screenshot
|
||||
// Access: Published
|
||||
// Description: Saves a screenshot of the window to a default
|
||||
// filename, and returns the filename, or empty string
|
||||
// if the screenshot failed. The default filename is
|
||||
// generated from the supplied prefix and from the
|
||||
// Configrc variable screenshot-filename, which contains
|
||||
// the following strings:
|
||||
//
|
||||
// %~p - the supplied prefix
|
||||
// %~f - the frame count
|
||||
// %~e - the value of screenshot-extension
|
||||
// All other % strings in strftime().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
Filename GraphicsWindow::
|
||||
take_screenshot(const string &prefix) {
|
||||
time_t now = time(NULL);
|
||||
struct tm *ttm = localtime(&now);
|
||||
int frame_count = ClockObject::get_global_clock()->get_frame_count();
|
||||
|
||||
static const int buffer_size = 1024;
|
||||
char buffer[buffer_size];
|
||||
|
||||
ostringstream filename_strm;
|
||||
|
||||
size_t i = 0;
|
||||
while (i < screenshot_filename.length()) {
|
||||
char ch1 = screenshot_filename[i++];
|
||||
if (ch1 == '%' && i < screenshot_filename.length()) {
|
||||
char ch2 = screenshot_filename[i++];
|
||||
if (ch2 == '~' && i < screenshot_filename.length()) {
|
||||
char ch3 = screenshot_filename[i++];
|
||||
switch (ch3) {
|
||||
case 'p':
|
||||
filename_strm << prefix;
|
||||
break;
|
||||
|
||||
case 'f':
|
||||
filename_strm << frame_count;
|
||||
break;
|
||||
|
||||
case 'e':
|
||||
filename_strm << screenshot_extension;
|
||||
break;
|
||||
}
|
||||
|
||||
} else {
|
||||
// Use strftime() to decode the percent code.
|
||||
char format[3] = {'%', ch2, '\0'};
|
||||
if (strftime(buffer, buffer_size, format, ttm)) {
|
||||
for (char *b = buffer; *b != '\0'; b++) {
|
||||
switch (*b) {
|
||||
case ' ':
|
||||
case ':':
|
||||
case '/':
|
||||
filename_strm << '-';
|
||||
break;
|
||||
|
||||
case '\n':
|
||||
break;
|
||||
|
||||
default:
|
||||
filename_strm << *b;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
filename_strm << ch1;
|
||||
}
|
||||
}
|
||||
|
||||
Filename filename = filename_strm.str();
|
||||
if (take_screenshot(filename)) {
|
||||
return filename;
|
||||
}
|
||||
return Filename();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GraphicsWindow::take_screenshot
|
||||
// Access: Published
|
||||
// Description: Saves a screenshot of the window to the indicated
|
||||
// filename. Returns true on success, false on failure.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool GraphicsWindow::
|
||||
take_screenshot(const Filename &filename) {
|
||||
if (_gsg == (GraphicsStateGuardian *)NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
WindowProperties props = get_properties();
|
||||
if (!props.has_size()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
int x_size = props.get_x_size();
|
||||
int y_size = props.get_y_size();
|
||||
|
||||
PixelBuffer p(x_size, y_size, 3, 1, PixelBuffer::T_unsigned_byte,
|
||||
PixelBuffer::F_rgb);
|
||||
|
||||
DisplayRegion dr(x_size, y_size);
|
||||
RenderBuffer rb = _gsg->get_render_buffer(RenderBuffer::T_front);
|
||||
if (!p.copy(_gsg, &dr, rb)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!p.write(filename)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GraphicsWindow::get_num_input_devices
|
||||
// Access: Published
|
||||
|
|
@ -653,157 +346,50 @@ int GraphicsWindow::
|
|||
verify_window_sizes(int numsizes, int *dimen) {
|
||||
return numsizes;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// 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.
|
||||
// Function: GraphicsWindow::request_open
|
||||
// Access: Public, Virtual
|
||||
// Description: This is called by the GraphicsEngine to request that
|
||||
// the window (or whatever) open itself or, in general,
|
||||
// make itself valid, at the next call to
|
||||
// process_events().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
PT(DisplayRegion) GraphicsWindow::
|
||||
make_scratch_display_region(int x_size, int y_size) const {
|
||||
#ifndef NDEBUG
|
||||
{
|
||||
MutexHolder holder(_lock);
|
||||
if (x_size > _properties.get_x_size() ||
|
||||
y_size > _properties.get_y_size()) {
|
||||
display_cat.error()
|
||||
<< "make_scratch_display_region(): requested region of size "
|
||||
<< x_size << ", " << y_size << " is larger than window of size "
|
||||
<< _properties.get_x_size() << ", " << _properties.get_y_size()
|
||||
<< ".\n";
|
||||
x_size = min(x_size, _properties.get_x_size());
|
||||
y_size = min(y_size, _properties.get_y_size());
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
PT(DisplayRegion) region = new DisplayRegion(x_size, y_size);
|
||||
region->copy_clear_settings(*this);
|
||||
return region;
|
||||
void GraphicsWindow::
|
||||
request_open() {
|
||||
WindowProperties open_properties;
|
||||
open_properties.set_open(true);
|
||||
request_properties(open_properties);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GraphicsWindow::begin_frame
|
||||
// Function: GraphicsWindow::request_close
|
||||
// Access: Public, Virtual
|
||||
// Description: This function will be called within the draw thread
|
||||
// before beginning rendering for a given frame. It
|
||||
// should do whatever setup is required, and return true
|
||||
// if the frame should be rendered, or false if it
|
||||
// should be skipped.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool GraphicsWindow::
|
||||
begin_frame() {
|
||||
if (_gsg == (GraphicsStateGuardian *)NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Okay, we already have a GSG, so activate it.
|
||||
make_current();
|
||||
return _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).
|
||||
//
|
||||
// This function is called only within the draw thread.
|
||||
// Description: This is called by the GraphicsEngine to request that
|
||||
// the window (or whatever) close itself or, in general,
|
||||
// make itself invalid, at the next call to
|
||||
// process_events(). By that time we promise the gsg
|
||||
// pointer will be cleared.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void GraphicsWindow::
|
||||
clear() {
|
||||
if (is_any_clear_active()) {
|
||||
nassertv(_gsg != (GraphicsStateGuardian *)NULL);
|
||||
|
||||
int x_size, y_size;
|
||||
{
|
||||
MutexHolder holder(_lock);
|
||||
x_size = _properties.get_x_size();
|
||||
y_size = _properties.get_y_size();
|
||||
}
|
||||
PT(DisplayRegion) win_dr =
|
||||
make_scratch_display_region(x_size, y_size);
|
||||
DisplayRegionStack old_dr = _gsg->push_display_region(win_dr);
|
||||
_gsg->clear(this);
|
||||
_gsg->pop_display_region(old_dr);
|
||||
}
|
||||
request_close() {
|
||||
WindowProperties close_properties;
|
||||
close_properties.set_open(false);
|
||||
request_properties(close_properties);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GraphicsWindow::end_frame
|
||||
// Function: GraphicsWindow::set_close_now
|
||||
// Access: Public, Virtual
|
||||
// Description: This function will be called within the draw thread
|
||||
// after rendering is completed for a given frame. It
|
||||
// should do whatever finalization is required.
|
||||
// Description: This is called by the GraphicsEngine to insist that
|
||||
// the window be closed immediately. This is only
|
||||
// called from the window thread.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void GraphicsWindow::
|
||||
end_frame() {
|
||||
nassertv(_gsg != (GraphicsStateGuardian *)NULL);
|
||||
_gsg->end_frame();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GraphicsWindow::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 GraphicsWindow::
|
||||
make_current() {
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GraphicsWindow::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 GraphicsWindow::
|
||||
release_gsg() {
|
||||
_gsg.clear();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GraphicsWindow::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 GraphicsWindow::
|
||||
begin_flip() {
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GraphicsWindow::end_flip
|
||||
// Access: Public, Virtual
|
||||
// Description: This function will be called within the draw thread
|
||||
// after begin_flip() has been called on all windows, to
|
||||
// finish the exchange of the front and back buffers.
|
||||
//
|
||||
// This should cause the window to wait for the flip, if
|
||||
// necessary.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void GraphicsWindow::
|
||||
end_flip() {
|
||||
set_close_now() {
|
||||
WindowProperties close_properties;
|
||||
close_properties.set_open(false);
|
||||
set_properties_now(close_properties);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -825,7 +411,7 @@ process_events() {
|
|||
// bitmask after all.
|
||||
WindowProperties properties;
|
||||
{
|
||||
MutexHolder holder(_lock);
|
||||
MutexHolder holder(_properties_lock);
|
||||
properties = _requested_properties;
|
||||
_requested_properties.clear();
|
||||
|
||||
|
|
@ -871,11 +457,15 @@ set_properties_now(WindowProperties &properties) {
|
|||
if (open_window()) {
|
||||
// When the window is first opened, force its size to be
|
||||
// broadcast to its display regions.
|
||||
_x_size = _properties.get_x_size();
|
||||
_y_size = _properties.get_y_size();
|
||||
_has_size = true;
|
||||
_is_valid = true;
|
||||
|
||||
Channels::iterator ci;
|
||||
for (ci = _channels.begin(); ci != _channels.end(); ++ci) {
|
||||
GraphicsChannel *chan = (*ci);
|
||||
chan->window_resized(_properties.get_x_size(),
|
||||
_properties.get_y_size());
|
||||
chan->window_resized(_x_size, _y_size);
|
||||
}
|
||||
|
||||
} else {
|
||||
|
|
@ -893,6 +483,7 @@ set_properties_now(WindowProperties &properties) {
|
|||
// yet.
|
||||
nassertv(_gsg == (GraphicsStateGuardian *)NULL);
|
||||
close_window();
|
||||
_is_valid = false;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
|
@ -947,43 +538,7 @@ set_properties_now(WindowProperties &properties) {
|
|||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GraphicsWindow::close_window
|
||||
// Access: Protected, Virtual
|
||||
// Description: Closes the window right now. Called from the window
|
||||
// thread.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void GraphicsWindow::
|
||||
close_window() {
|
||||
display_cat.info()
|
||||
<< "Closing " << get_type() << "\n";
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GraphicsWindow::reset_window
|
||||
// Access: Protected, Virtual
|
||||
// Description: resets the window framebuffer from its derived
|
||||
// children. Does nothing here.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void GraphicsWindow::
|
||||
reset_window(bool swapchain) {
|
||||
display_cat.info()
|
||||
<< "Resetting " << get_type() << "\n";
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GraphicsWindow::open_window
|
||||
// Access: Protected, Virtual
|
||||
// Description: Opens the window right now. Called from the window
|
||||
// thread. Returns true if the window is successfully
|
||||
// opened, or false if there was a problem.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool GraphicsWindow::
|
||||
open_window() {
|
||||
return false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GraphicsWindow::open_window
|
||||
// Function: GraphicsWindow::do_reshape_request
|
||||
// Access: Protected, Virtual
|
||||
// Description: Called from the window thread in response to a request
|
||||
// from within the code (via request_properties()) to
|
||||
|
|
@ -1006,7 +561,7 @@ do_reshape_request(int x_origin, int y_origin, int x_size, int y_size) {
|
|||
////////////////////////////////////////////////////////////////////
|
||||
void GraphicsWindow::
|
||||
system_changed_properties(const WindowProperties &properties) {
|
||||
MutexHolder holder(_lock);
|
||||
MutexHolder holder(_properties_lock);
|
||||
|
||||
if (properties.has_size()) {
|
||||
system_changed_size(properties.get_x_size(), properties.get_y_size());
|
||||
|
|
@ -1031,6 +586,10 @@ void GraphicsWindow::
|
|||
system_changed_size(int x_size, int y_size) {
|
||||
if (x_size != _properties.get_x_size() ||
|
||||
y_size != _properties.get_y_size()) {
|
||||
_x_size = x_size;
|
||||
_y_size = y_size;
|
||||
_has_size = true;
|
||||
|
||||
Channels::iterator ci;
|
||||
for (ci = _channels.begin(); ci != _channels.end(); ++ci) {
|
||||
GraphicsChannel *chan = (*ci);
|
||||
|
|
@ -1038,61 +597,3 @@ system_changed_size(int x_size, int y_size) {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// 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.
|
||||
//
|
||||
// The caller must grab and hold _lock before making
|
||||
// this call.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
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() {
|
||||
MutexHolder holder(_lock);
|
||||
_display_regions_stale = false;
|
||||
_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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,56 +21,27 @@
|
|||
|
||||
#include "pandabase.h"
|
||||
|
||||
#include "graphicsOutput.h"
|
||||
#include "graphicsWindowInputDevice.h"
|
||||
#include "windowProperties.h"
|
||||
#include "graphicsChannel.h"
|
||||
#include "graphicsPipe.h"
|
||||
#include "displayRegion.h"
|
||||
#include "graphicsStateGuardian.h"
|
||||
#include "clearableRegion.h"
|
||||
|
||||
#include "typedWritableReferenceCount.h"
|
||||
#include "mouseData.h"
|
||||
#include "modifierButtons.h"
|
||||
#include "buttonEvent.h"
|
||||
#include "iterator_types.h"
|
||||
#include "notify.h"
|
||||
#include "pmutex.h"
|
||||
#include "filename.h"
|
||||
|
||||
#include "pvector.h"
|
||||
#include "pdeque.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : GraphicsWindow
|
||||
// Description : An output medium for receiving the results of
|
||||
// rendering. Typically this is a window on the
|
||||
// computer desktop, but it may also be the entire
|
||||
// desktop or console screen (i.e. a fullscreen window),
|
||||
// or a window on another machine, or even a disk file.
|
||||
//
|
||||
// The GraphicsWindow class handles all of the details
|
||||
// about creating a window and its framebuffer, and
|
||||
// managing the properties associated with the windowing
|
||||
// system, such as position and size and keyboard/mouse
|
||||
// input. The actual rendering, and anything associated
|
||||
// with the graphics context itself, is managed by the
|
||||
// window's GraphicsStateGuardian.
|
||||
//
|
||||
// GraphicsWindows are not actually writable to bam
|
||||
// files, of course, but they may be passed as event
|
||||
// parameters, so they inherit from
|
||||
// TypedWritableReferenceCount instead of
|
||||
// TypedReferenceCount for that convenience.
|
||||
// Description : A window, fullscreen or on a desktop, into which a
|
||||
// graphics device sends its output for interactive
|
||||
// display.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
class EXPCL_PANDA GraphicsWindow : public TypedWritableReferenceCount, public ClearableRegion {
|
||||
class EXPCL_PANDA GraphicsWindow : public GraphicsOutput {
|
||||
protected:
|
||||
GraphicsWindow(GraphicsPipe *pipe, GraphicsStateGuardian *gsg);
|
||||
|
||||
private:
|
||||
GraphicsWindow(const GraphicsWindow ©);
|
||||
void operator = (const GraphicsWindow ©);
|
||||
|
||||
PUBLISHED:
|
||||
virtual ~GraphicsWindow();
|
||||
|
||||
|
|
@ -80,27 +51,12 @@ PUBLISHED:
|
|||
WindowProperties get_rejected_properties() const;
|
||||
void request_properties(const WindowProperties &requested_properties);
|
||||
INLINE bool is_closed() const;
|
||||
INLINE bool is_active() const;
|
||||
virtual bool is_active() const;
|
||||
INLINE bool is_fullscreen() const;
|
||||
|
||||
void set_window_event(const string &window_event);
|
||||
string get_window_event() const;
|
||||
|
||||
INLINE GraphicsStateGuardian *get_gsg() const;
|
||||
INLINE GraphicsPipe *get_pipe() const;
|
||||
|
||||
GraphicsChannel *get_channel(int index);
|
||||
void remove_channel(int index);
|
||||
|
||||
int get_max_channel_index() const;
|
||||
bool is_channel_defined(int index) const;
|
||||
|
||||
int get_num_display_regions() const;
|
||||
DisplayRegion *get_display_region(int n) const;
|
||||
|
||||
Filename take_screenshot(const string &prefix = "screenshot");
|
||||
bool take_screenshot(const Filename &filename);
|
||||
|
||||
// Mouse and keyboard routines
|
||||
int get_num_input_devices() const;
|
||||
string get_input_device_name(int device) const;
|
||||
|
|
@ -115,28 +71,10 @@ public:
|
|||
|
||||
virtual int verify_window_sizes(int numsizes, int *dimen);
|
||||
|
||||
PT(DisplayRegion) make_scratch_display_region(int x_size, int y_size) const;
|
||||
|
||||
public:
|
||||
// These are not intended to be called directly by the user.
|
||||
INLINE void win_display_regions_changed();
|
||||
|
||||
public:
|
||||
// It is an error to call any of the following methods from any
|
||||
// thread other than the draw thread. These methods are normally
|
||||
// called by the GraphicsEngine.
|
||||
virtual bool begin_frame();
|
||||
void clear();
|
||||
virtual void end_frame();
|
||||
|
||||
// This method is called in the draw thread prior to issuing any
|
||||
// drawing commands for the window.
|
||||
virtual void make_current();
|
||||
virtual void release_gsg();
|
||||
|
||||
// These methods will be called within the app (main) thread.
|
||||
virtual void begin_flip();
|
||||
virtual void end_flip();
|
||||
virtual void request_open();
|
||||
virtual void request_close();
|
||||
virtual void set_close_now();
|
||||
|
||||
// It is an error to call any of the following methods from any
|
||||
// thread other than the window thread. These methods are normally
|
||||
|
|
@ -145,14 +83,9 @@ public:
|
|||
virtual void set_properties_now(WindowProperties &properties);
|
||||
|
||||
protected:
|
||||
virtual void close_window();
|
||||
virtual bool open_window();
|
||||
virtual void reset_window(bool swapchain);
|
||||
virtual bool do_reshape_request(int x_origin, int y_origin,
|
||||
int x_size, int y_size);
|
||||
|
||||
void declare_channel(int index, GraphicsChannel *chan);
|
||||
|
||||
// It is an error to call any of the following methods from any
|
||||
// thread other than the window thread.
|
||||
void system_changed_properties(const WindowProperties &properties);
|
||||
|
|
@ -163,26 +96,13 @@ protected:
|
|||
InputDevices _input_devices;
|
||||
Mutex _input_lock;
|
||||
|
||||
PT(GraphicsStateGuardian) _gsg;
|
||||
PT(GraphicsPipe) _pipe;
|
||||
|
||||
private:
|
||||
INLINE void determine_display_regions() const;
|
||||
void do_determine_display_regions();
|
||||
|
||||
protected:
|
||||
WindowProperties _properties;
|
||||
|
||||
private:
|
||||
Mutex _lock;
|
||||
// protects _channels, _display_regions, and _requested_properties.
|
||||
|
||||
typedef pvector< PT(GraphicsChannel) > Channels;
|
||||
Channels _channels;
|
||||
|
||||
typedef pvector<DisplayRegion *> DisplayRegions;
|
||||
DisplayRegions _display_regions;
|
||||
bool _display_regions_stale;
|
||||
Mutex _properties_lock;
|
||||
// protects _requested_properties, _rejected_properties, and
|
||||
// _window_event.
|
||||
|
||||
WindowProperties _requested_properties;
|
||||
WindowProperties _rejected_properties;
|
||||
|
|
@ -193,9 +113,9 @@ public:
|
|||
return _type_handle;
|
||||
}
|
||||
static void init_type() {
|
||||
TypedWritableReferenceCount::init_type();
|
||||
GraphicsOutput::init_type();
|
||||
register_type(_type_handle, "GraphicsWindow",
|
||||
TypedWritableReferenceCount::get_class_type());
|
||||
GraphicsOutput::get_class_type());
|
||||
}
|
||||
virtual TypeHandle get_type() const {
|
||||
return get_class_type();
|
||||
|
|
@ -204,9 +124,6 @@ public:
|
|||
|
||||
private:
|
||||
static TypeHandle _type_handle;
|
||||
|
||||
friend class GraphicsPipe;
|
||||
friend class GraphicsEngine;
|
||||
};
|
||||
|
||||
#include "graphicsWindow.I"
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@
|
|||
|
||||
#include "graphicsStateGuardian.h"
|
||||
#include "matrixLens.h"
|
||||
#include "graphicsWindow.h"
|
||||
#include "graphicsOutput.h"
|
||||
#include "graphicsEngine.h"
|
||||
#include "dcast.h"
|
||||
|
||||
|
|
@ -257,7 +257,7 @@ get_screen_active(int index) const {
|
|||
////////////////////////////////////////////////////////////////////
|
||||
int NonlinearImager::
|
||||
add_viewer(DisplayRegion *dr) {
|
||||
GraphicsWindow *win = dr->get_window();
|
||||
GraphicsOutput *win = dr->get_window();
|
||||
GraphicsStateGuardian *gsg = win->get_gsg();
|
||||
nassertr(_viewers.empty() || (gsg == _gsg && win == _win), -1);
|
||||
_gsg = gsg;
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@
|
|||
|
||||
class GraphicsEngine;
|
||||
class GraphicsStateGuardian;
|
||||
class GraphicsWindow;
|
||||
class GraphicsOutput;
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : NonlinearImager
|
||||
|
|
@ -163,7 +163,7 @@ private:
|
|||
Viewers _viewers;
|
||||
Screens _screens;
|
||||
GraphicsStateGuardian *_gsg;
|
||||
GraphicsWindow *_win;
|
||||
GraphicsOutput *_win;
|
||||
|
||||
bool _stale;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -33,8 +33,9 @@ const int win_height = config_framework.GetInt("win-height", 480);
|
|||
const bool fullscreen = config_framework.GetBool("fullscreen", false);
|
||||
const bool undecorated = config_framework.GetBool("undecorated", false);
|
||||
const bool cursor_hidden = config_framework.GetBool("cursor-hidden", false);
|
||||
const float aspect_ratio = config_framework.GetFloat("aspect-ratio", 0.0f);
|
||||
const string window_title = config_framework.GetString("window-title", "Panda");
|
||||
|
||||
const float aspect_ratio = config_framework.GetFloat("aspect-ratio", 0.0f);
|
||||
const bool show_frame_rate_meter = config_framework.GetBool("show-frame-rate-meter", false);
|
||||
|
||||
// The default window background color.
|
||||
|
|
|
|||
|
|
@ -30,8 +30,9 @@ extern const int win_height;
|
|||
extern const bool fullscreen;
|
||||
extern const bool undecorated;
|
||||
extern const bool cursor_hidden;
|
||||
extern const float aspect_ratio;
|
||||
extern const string window_title;
|
||||
|
||||
extern const float aspect_ratio;
|
||||
extern const bool show_frame_rate_meter;
|
||||
|
||||
extern const float win_background_r;
|
||||
|
|
|
|||
|
|
@ -39,7 +39,7 @@ PandaFramework() :
|
|||
_is_open = false;
|
||||
_made_default_pipe = false;
|
||||
_data_root = NodePath("data");
|
||||
_window_title = "Panda";
|
||||
_window_title = window_title;
|
||||
_start_time = 0.0;
|
||||
_frame_count = 0;
|
||||
_wireframe_enabled = false;
|
||||
|
|
|
|||
|
|
@ -808,13 +808,23 @@ make_camera() {
|
|||
_cameras.push_back(camera);
|
||||
|
||||
PT(Lens) lens = new PerspectiveLens;
|
||||
WindowProperties properties = _window->get_properties();
|
||||
if (!properties.has_size()) {
|
||||
properties = _window->get_requested_properties();
|
||||
}
|
||||
if (properties.has_size()) {
|
||||
lens->set_film_size(properties.get_x_size(), properties.get_y_size());
|
||||
|
||||
if (aspect_ratio != 0.0f) {
|
||||
// If we're given an explict aspect ratio, use it
|
||||
lens->set_aspect_ratio(aspect_ratio);
|
||||
|
||||
} else {
|
||||
// Otherwise, infer the aspect ratio from the window size. This
|
||||
// does assume we have square pixels on our output device.
|
||||
WindowProperties properties = _window->get_properties();
|
||||
if (!properties.has_size()) {
|
||||
properties = _window->get_requested_properties();
|
||||
}
|
||||
if (properties.has_size()) {
|
||||
lens->set_film_size(properties.get_x_size(), properties.get_y_size());
|
||||
}
|
||||
}
|
||||
|
||||
camera->set_lens(lens);
|
||||
camera->set_scene(get_render());
|
||||
dr->set_camera(camera_np);
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@
|
|||
#include "pointerTo.h"
|
||||
#include "pvector.h"
|
||||
#include "typedWritableReferenceCount.h"
|
||||
#include "graphicsWindow.h"
|
||||
|
||||
class PandaFramework;
|
||||
class AmbientLight;
|
||||
|
|
|
|||
|
|
@ -123,7 +123,7 @@ issue_transformed_color_gl(const Geom *geom, Geom::ColorIterator &citerator,
|
|||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GLGraphicsStateGuardian::uchar_bgr_to_rgb
|
||||
// Function: uchar_bgr_to_rgb
|
||||
// Description: Recopies the given array of pixels, converting from
|
||||
// BGR to RGB arrangement.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -140,7 +140,7 @@ uchar_bgr_to_rgb(unsigned char *dest, const unsigned char *source,
|
|||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GLGraphicsStateGuardian::uchar_bgra_to_rgba
|
||||
// Function: uchar_bgra_to_rgba
|
||||
// Description: Recopies the given array of pixels, converting from
|
||||
// BGRA to RGBA arrangement.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -157,6 +157,98 @@ uchar_bgra_to_rgba(unsigned char *dest, const unsigned char *source,
|
|||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ushort_bgr_to_rgb
|
||||
// Description: Recopies the given array of pixels, converting from
|
||||
// BGR to RGB arrangement.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
static void
|
||||
ushort_bgr_to_rgb(unsigned short *dest, const unsigned short *source,
|
||||
int num_pixels) {
|
||||
for (int i = 0; i < num_pixels; i++) {
|
||||
dest[0] = source[2];
|
||||
dest[1] = source[1];
|
||||
dest[2] = source[0];
|
||||
dest += 3;
|
||||
source += 3;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ushort_bgra_to_rgba
|
||||
// Description: Recopies the given array of pixels, converting from
|
||||
// BGRA to RGBA arrangement.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
static void
|
||||
ushort_bgra_to_rgba(unsigned short *dest, const unsigned short *source,
|
||||
int num_pixels) {
|
||||
for (int i = 0; i < num_pixels; i++) {
|
||||
dest[0] = source[2];
|
||||
dest[1] = source[1];
|
||||
dest[2] = source[0];
|
||||
dest[3] = source[3];
|
||||
dest += 4;
|
||||
source += 4;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: fix_component_ordering
|
||||
// Description: Reverses the order of the components within the
|
||||
// image, to convert (for instance) GL_BGR to GL_RGB.
|
||||
// Returns the PTA_uchar representing the converted
|
||||
// image, or the original image if it is unchanged.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
static PTA_uchar
|
||||
fix_component_ordering(GLenum external_format, PixelBuffer *pb) {
|
||||
PTA_uchar new_image = pb->_image;
|
||||
|
||||
switch (external_format) {
|
||||
case GL_RGB:
|
||||
switch (pb->get_image_type()) {
|
||||
case PixelBuffer::T_unsigned_byte:
|
||||
new_image = PTA_uchar::empty_array(pb->_image.size());
|
||||
uchar_bgr_to_rgb(new_image, pb->_image, pb->_image.size() / 3);
|
||||
break;
|
||||
|
||||
case PixelBuffer::T_unsigned_short:
|
||||
new_image = PTA_uchar::empty_array(pb->_image.size());
|
||||
ushort_bgr_to_rgb((unsigned short *)new_image.p(),
|
||||
(unsigned short *)pb->_image.p(),
|
||||
pb->_image.size() / 6);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case GL_RGBA:
|
||||
switch (pb->get_image_type()) {
|
||||
case PixelBuffer::T_unsigned_byte:
|
||||
new_image = PTA_uchar::empty_array(pb->_image.size());
|
||||
uchar_bgra_to_rgba(new_image, pb->_image, pb->_image.size() / 4);
|
||||
break;
|
||||
|
||||
case PixelBuffer::T_unsigned_short:
|
||||
new_image = PTA_uchar::empty_array(pb->_image.size());
|
||||
ushort_bgra_to_rgba((unsigned short *)new_image.p(),
|
||||
(unsigned short *)pb->_image.p(),
|
||||
pb->_image.size() / 8);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return new_image;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GLGraphicsStateGuardian::Constructor
|
||||
// Access: Public
|
||||
|
|
@ -2023,16 +2115,7 @@ copy_pixel_buffer(PixelBuffer *pb, const DisplayRegion *dr) {
|
|||
|
||||
// We may have to reverse the byte ordering of the image if GL
|
||||
// didn't do it for us.
|
||||
if (external_format == GL_RGB && pb->get_image_type() == PixelBuffer::T_unsigned_byte) {
|
||||
PTA_uchar new_image = PTA_uchar::empty_array(pb->_image.size());
|
||||
uchar_bgr_to_rgb(new_image, pb->_image, pb->_image.size() / 3);
|
||||
pb->_image = new_image;
|
||||
|
||||
} else if (external_format == GL_RGBA && pb->get_image_type() == PixelBuffer::T_unsigned_byte) {
|
||||
PTA_uchar new_image = PTA_uchar::empty_array(pb->_image.size());
|
||||
uchar_bgra_to_rgba(new_image, pb->_image, pb->_image.size() / 4);
|
||||
pb->_image = new_image;
|
||||
}
|
||||
pb->_image = fix_component_ordering(external_format, pb);
|
||||
|
||||
report_gl_errors();
|
||||
return true;
|
||||
|
|
@ -2829,32 +2912,21 @@ apply_texture_immediate(Texture *tex) {
|
|||
|
||||
int xsize = pb->get_xsize();
|
||||
int ysize = pb->get_ysize();
|
||||
int num_pixels = xsize * ysize;
|
||||
|
||||
GLenum internal_format = get_internal_image_format(pb->get_format());
|
||||
GLenum external_format = get_external_image_format(pb->get_format());
|
||||
GLenum type = get_image_type(pb->get_image_type());
|
||||
|
||||
uchar *image = pb->_image;
|
||||
uchar *locally_allocated_image = (uchar *)NULL;
|
||||
PTA_uchar image = pb->_image;
|
||||
if (!gl_supports_bgr) {
|
||||
// If the GL doesn't claim to support BGR, we may have to reverse
|
||||
// the byte ordering of the image.
|
||||
if (external_format == GL_RGB && pb->get_image_type() == PixelBuffer::T_unsigned_byte) {
|
||||
locally_allocated_image = new uchar[num_pixels * 3];
|
||||
image = locally_allocated_image;
|
||||
uchar_bgr_to_rgb(image, pb->_image, num_pixels);
|
||||
} else if (external_format == GL_RGBA && pb->get_image_type() == PixelBuffer::T_unsigned_byte) {
|
||||
locally_allocated_image = new uchar[num_pixels * 4];
|
||||
image = locally_allocated_image;
|
||||
uchar_bgra_to_rgba(image, pb->_image, num_pixels);
|
||||
}
|
||||
// the component ordering of the image.
|
||||
image = fix_component_ordering(external_format, pb);
|
||||
}
|
||||
|
||||
#ifndef NDEBUG
|
||||
int wanted_size =
|
||||
compute_gl_image_size(xsize, ysize,
|
||||
external_format, type);
|
||||
compute_gl_image_size(xsize, ysize, external_format, type);
|
||||
nassertr(wanted_size == (int)pb->_image.size(), false);
|
||||
#endif // NDEBUG
|
||||
|
||||
|
|
@ -2888,9 +2960,6 @@ apply_texture_immediate(Texture *tex) {
|
|||
}
|
||||
report_gl_errors();
|
||||
|
||||
if (locally_allocated_image != (uchar *)NULL) {
|
||||
delete[] locally_allocated_image;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
@ -2909,9 +2978,6 @@ apply_texture_immediate(Texture *tex) {
|
|||
((error_string != (const GLubyte *)NULL) ? " : " : "") << endl;
|
||||
}
|
||||
|
||||
if (locally_allocated_image != (uchar *)NULL) {
|
||||
delete[] locally_allocated_image;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@
|
|||
#define GLXGRAPHICSPIPE_H
|
||||
|
||||
#include "pandabase.h"
|
||||
#include "graphicsWindow.h"
|
||||
#include "graphicsPipe.h"
|
||||
|
||||
class glxGraphicsWindow;
|
||||
|
|
|
|||
Loading…
Reference in New Issue