merge window_devel_2003_02_21 to trunk

This commit is contained in:
David Rose 2003-04-09 17:28:00 +00:00
parent 5c48c68569
commit a16fe56c74
63 changed files with 3997 additions and 3090 deletions

View File

@ -424,26 +424,29 @@ ChanConfig::ChanConfig(GraphicsEngine *engine, GraphicsPipe* pipe,
float win_background_b = chanconfig.GetFloat("win-background-b", 0.41);
// visual? nope, that's handled with the mode.
int framebuffer_mode =
WindowProperties::FM_rgba |
WindowProperties::FM_double_buffer |
WindowProperties::FM_depth;
framebuffer_mode = overrides.defined(ChanCfgOverrides::Mask) ?
overrides.getUInt(ChanCfgOverrides::Mask) : framebuffer_mode;
int frame_buffer_mode =
FrameBufferProperties::FM_rgba |
FrameBufferProperties::FM_double_buffer |
FrameBufferProperties::FM_depth;
frame_buffer_mode = overrides.defined(ChanCfgOverrides::Mask) ?
overrides.getUInt(ChanCfgOverrides::Mask) : frame_buffer_mode;
std::string title = cfg;
title = overrides.defined(ChanCfgOverrides::Title) ?
overrides.getString(ChanCfgOverrides::Title) : title;
FrameBufferProperties fbprops;
fbprops.set_frame_buffer_mode(frame_buffer_mode);
fbprops.set_depth_bits(want_depth_bits);
fbprops.set_color_bits(want_color_bits);
WindowProperties props;
props.set_open(true);
props.set_origin(origX, origY);
props.set_size(sizeX, sizeY);
props.set_title(title);
props.set_framebuffer_mode(framebuffer_mode);
props.set_undecorated(undecorated);
props.set_fullscreen(fullscreen);
props.set_depth_bits(want_depth_bits);
props.set_color_bits(want_color_bits);
props.set_cursor_hidden(!use_cursor);
@ -454,7 +457,9 @@ ChanConfig::ChanConfig(GraphicsEngine *engine, GraphicsPipe* pipe,
overrides.getBool(ChanCfgOverrides::Cameras) : true;
// open that sucker
PT(GraphicsWindow) win = engine->make_window(pipe);
PT(GraphicsStateGuardian) gsg =
engine->make_gsg(pipe, fbprops, engine->get_threading_model());
PT(GraphicsWindow) win = engine->make_window(pipe, gsg);
if(win == (GraphicsWindow *)NULL) {
chancfg_cat.error() << "Could not create window" << endl;
_graphics_window = (GraphicsWindow *)NULL;

View File

@ -15,6 +15,7 @@
displayRegion.I displayRegion.h \
displayRegionStack.I \
displayRegionStack.h \
frameBufferProperties.I frameBufferProperties.h \
frameBufferStack.I frameBufferStack.h \
geomContext.I geomContext.h geomNodeContext.I geomNodeContext.h \
graphicsChannel.I graphicsChannel.h \
@ -24,6 +25,7 @@
graphicsPipeSelection.I graphicsPipeSelection.h \
graphicsStateGuardian.I \
graphicsStateGuardian.h graphicsWindow.I \
graphicsThreadingModel.I graphicsThreadingModel.h \
graphicsWindow.h graphicsWindowInputDevice.I \
graphicsWindowInputDevice.h \
windowProperties.I windowProperties.h \
@ -36,11 +38,13 @@
config_display.cxx \
clearableRegion.cxx \
displayRegion.cxx \
frameBufferProperties.cxx \
geomContext.cxx geomNodeContext.cxx graphicsChannel.cxx \
graphicsEngine.cxx \
graphicsLayer.cxx graphicsPipe.cxx \
graphicsPipeSelection.cxx \
graphicsStateGuardian.cxx \
graphicsThreadingModel.cxx \
graphicsWindow.cxx graphicsWindowInputDevice.cxx \
windowProperties.cxx \
hardwareChannel.cxx \
@ -51,6 +55,7 @@
clearableRegion.I clearableRegion.h \
displayRegion.I displayRegion.h displayRegionStack.I \
displayRegionStack.h \
frameBufferProperties.I frameBufferProperties.h \
frameBufferStack.I frameBufferStack.h \
geomContext.I geomContext.h geomNodeContext.I geomNodeContext.h \
graphicsChannel.I graphicsChannel.h \
@ -60,6 +65,7 @@
graphicsPipeSelection.I graphicsPipeSelection.h \
graphicsStateGuardian.I \
graphicsStateGuardian.h graphicsWindow.I graphicsWindow.h \
graphicsThreadingModel.I graphicsThreadingModel.h \
graphicsWindowInputDevice.I graphicsWindowInputDevice.h \
windowProperties.I windowProperties.h \
hardwareChannel.I hardwareChannel.h \

View File

@ -1,5 +1,7 @@
#include "config_display.cxx"
#include "frameBufferProperties.cxx"
#include "graphicsPipeSelection.cxx"
#include "graphicsThreadingModel.cxx"
#include "hardwareChannel.cxx"
#include "savedFrameBuffer.cxx"
#include "windowProperties.cxx"

View File

@ -56,17 +56,53 @@ get_auto_flip() const {
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsEngine::make_window
// Function: GraphicsEngine::make_gsg
// Access: Published
// Description: Creates a new window using the indicated GraphicsPipe
// and returns it. The GraphicsEngine becomes the owner
// of the window; it will persist at least until
// remove_window() is called later.
// Description: Creates a new gsg using the indicated GraphicsPipe
// and returns it. The GraphicsEngine does not
// officially own the pointer to the gsg; but if any
// windows are created using this GSG, the
// GraphicsEngine will own the pointers to these
// windows, which in turn will own the pointer to the
// GSG.
//
// This flavor of make_window() uses the default
// There is no explicit way to release a GSG, but it
// will be destructed when all windows that reference it
// are destructed, and the draw thread that owns the GSG
// runs one more time.
//
// This flavor of make_gsg() uses the default
// threading model, specified via set_threading_model().
////////////////////////////////////////////////////////////////////
INLINE GraphicsWindow *GraphicsEngine::
make_window(GraphicsPipe *pipe) {
return make_window(pipe, get_threading_model());
INLINE PT(GraphicsStateGuardian) GraphicsEngine::
make_gsg(GraphicsPipe *pipe) {
return make_gsg(pipe, get_frame_buffer_properties(), get_threading_model());
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsEngine::make_window
// Access: Published
// Description: Creates a new window using the indicated
// GraphicsStateGuardian and returns it. The
// GraphicsEngine becomes the owner of the window; it
// will persist at least until remove_window() is called
// later.
////////////////////////////////////////////////////////////////////
INLINE GraphicsWindow *GraphicsEngine::
make_window(GraphicsPipe *pipe, GraphicsStateGuardian *gsg) {
return make_window(pipe, gsg, get_threading_model());
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsEngine::close_gsg
// Access: Published
// Description: Calls GraphicsPipe::close_gsg() on the indicated pipe
// and GSG. This function mainly exists to allow
// GraphicsEngine::WindowRenderer to call the protected
// method GraphicsPipe::close_gsg().
////////////////////////////////////////////////////////////////////
INLINE void GraphicsEngine::
close_gsg(GraphicsPipe *pipe, GraphicsStateGuardian *gsg) {
pipe->close_gsg(gsg);
}

View File

@ -50,8 +50,17 @@ GraphicsEngine(Pipeline *pipeline) :
if (_pipeline == (Pipeline *)NULL) {
_pipeline = Pipeline::get_render_pipeline();
}
set_threading_model(threading_model);
if (!_threading_model.empty()) {
// Default frame buffer properties.
_frame_buffer_properties.set_depth_bits(1);
_frame_buffer_properties.set_color_bits(1);
_frame_buffer_properties.set_frame_buffer_mode
(FrameBufferProperties::FM_rgba |
FrameBufferProperties::FM_double_buffer |
FrameBufferProperties::FM_depth);
set_threading_model(GraphicsThreadingModel(threading_model));
if (!_threading_model.is_default()) {
display_cat.info()
<< "Using threading model " << _threading_model << "\n";
}
@ -70,49 +79,46 @@ GraphicsEngine::
remove_all_windows();
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsEngine::set_frame_buffer_properties
// Access: Published
// Description: Specifies the default frame buffer properties for
// future gsg's created using the one-parameter
// make_gsg() method.
////////////////////////////////////////////////////////////////////
void GraphicsEngine::
set_frame_buffer_properties(const FrameBufferProperties &properties) {
MutexHolder holder(_lock);
_frame_buffer_properties = properties;
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsEngine::get_frame_buffer_properties
// Access: Published
// Description: Returns the current default threading model. See
// set_frame_buffer_properties().
////////////////////////////////////////////////////////////////////
FrameBufferProperties GraphicsEngine::
get_frame_buffer_properties() const {
FrameBufferProperties result;
{
MutexHolder holder(_lock);
result = _frame_buffer_properties;
}
return result;
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsEngine::set_threading_model
// Access: Published
// Description: Specifies how windows created using future calls to
// the one-parameter version of make_window() will be
// threaded. (The two-parameter flavor of make_window()
// allows this to be specified on a per-window basis.)
//
// The threading model is a string representing the
// names of the two threads that will process cull and
// draw for the given window, separated by a slash. The
// names are completely arbitrary and are used only to
// differentiate threads. The two names may be the
// same, meaning the same thread, or each may be the
// empty string, which represents the previous thread.
//
// Thus, for example, "cull/draw" indicates that the
// window will be culled in a thread called "cull", and
// drawn in a separate thread called "draw".
// "draw/draw" or simply "draw/" indicates the window
// will be culled and drawn in the same thread, "draw".
// On the other hand, "/draw" indicates the thread will
// be culled in the main, or app thread, and drawn in a
// separate thread named "draw". The empty string, ""
// or "/", indicates the thread will be culled and drawn
// in the main thread; that is to say, a single-process
// model.
//
// Finally, if the threading model begins with a "-"
// character, then cull and draw are run simultaneously,
// in the same thread, with no binning or state sorting.
// It simplifies the cull process but it forces the
// scene to render in scene graph order; state sorting
// and alpha sorting is lost.
//
// You can create as many different threads as you like;
// each thread is uniquified based on its name, so
// multiple windows may easily be handled by the same or
// different threads.
// the one-parameter version of make_gsg() will be
// threaded.
////////////////////////////////////////////////////////////////////
void GraphicsEngine::
set_threading_model(const string &threading_model) {
if (!threading_model.empty() && !Thread::is_threading_supported()) {
set_threading_model(const GraphicsThreadingModel &threading_model) {
if (!threading_model.is_single_threaded() &&
!Thread::is_threading_supported()) {
display_cat.warning()
<< "Threading model " << threading_model
<< " requested but threading not supported.\n";
@ -128,9 +134,9 @@ set_threading_model(const string &threading_model) {
// Description: Returns the current default threading model. See
// set_threading_model().
////////////////////////////////////////////////////////////////////
string GraphicsEngine::
GraphicsThreadingModel GraphicsEngine::
get_threading_model() const {
string result;
GraphicsThreadingModel result;
{
MutexHolder holder(_lock);
result = _threading_model;
@ -138,51 +144,64 @@ get_threading_model() const {
return result;
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsEngine::make_gsg
// Access: Published
// Description: Creates a new gsg using the indicated GraphicsPipe
// and returns it. The GraphicsEngine does not
// officially own the pointer to the gsg; but if any
// windows are created using this GSG, the
// GraphicsEngine will own the pointers to these
// windows, which in turn will own the pointer to the
// GSG.
//
// There is no explicit way to release a GSG, but it
// will be destructed when all windows that reference it
// are destructed, and the draw thread that owns the GSG
// runs one more time.
////////////////////////////////////////////////////////////////////
PT(GraphicsStateGuardian) GraphicsEngine::
make_gsg(GraphicsPipe *pipe, const FrameBufferProperties &properties,
const GraphicsThreadingModel &threading_model) {
// TODO: ask the draw thread to make the GSG.
PT(GraphicsStateGuardian) gsg = pipe->make_gsg(properties);
if (gsg != (GraphicsStateGuardian *)NULL) {
gsg->_threading_model = threading_model;
gsg->_pipe = pipe;
}
return gsg;
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsEngine::make_window
// Access: Published
// Description: Creates a new window using the indicated GraphicsPipe
// and returns it. The GraphicsEngine becomes the owner
// of the window; it will persist at least until
// remove_window() is called later.
// Description: Creates a new window using the indicated
// GraphicsStateGuardian and returns it. The
// GraphicsEngine becomes the owner of the window; it
// will persist at least until remove_window() is called
// later.
////////////////////////////////////////////////////////////////////
GraphicsWindow *GraphicsEngine::
make_window(GraphicsPipe *pipe, const string &threading_model) {
PT(GraphicsWindow) window = pipe->make_window();
make_window(GraphicsPipe *pipe, GraphicsStateGuardian *gsg,
const GraphicsThreadingModel &threading_model) {
if (gsg != (GraphicsStateGuardian *)NULL) {
nassertr(pipe == gsg->get_pipe(), NULL);
nassertr(threading_model.get_draw_name() ==
gsg->get_threading_model().get_draw_name(), NULL);
}
// TODO: ask the window thread to make the window.
PT(GraphicsWindow) window = pipe->make_window(gsg);
if (window != (GraphicsWindow *)NULL) {
MutexHolder holder(_lock);
_windows.insert(window);
// Now figure out the threading model.
string cull_name;
string draw_name;
bool cull_sorting = true;
size_t start = 0;
if (!threading_model.empty() && threading_model[0] == '-') {
start = 1;
cull_sorting = false;
}
WindowRenderer *cull = get_window_renderer(threading_model.get_cull_name());
WindowRenderer *draw = get_window_renderer(threading_model.get_draw_name());
draw->add_gsg(gsg);
size_t slash = threading_model.find('/', start);
if (slash == string::npos) {
cull_name = threading_model;
} else {
cull_name = threading_model.substr(start, slash - start);
draw_name = threading_model.substr(slash + 1);
}
if (!cull_sorting || draw_name.empty()) {
draw_name = cull_name;
}
/*
cerr << "cull_name = " << cull_name << " draw_name = " << draw_name
<< " cull_sorting = " << cull_sorting << "\n";
*/
WindowRenderer *cull = get_window_renderer(cull_name);
WindowRenderer *draw = get_window_renderer(draw_name);
if (cull_sorting) {
if (threading_model.get_cull_sorting()) {
cull->add_window(cull->_cull, window);
draw->add_window(draw->_draw, window);
} else {
@ -869,6 +888,18 @@ get_window_renderer(const string &name) {
return thread.p();
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsEngine::WindowRenderer::add_gsg
// Access: Public
// Description: Adds a new GSG to the _gsg list, if it is not already
// there.
////////////////////////////////////////////////////////////////////
void GraphicsEngine::WindowRenderer::
add_gsg(GraphicsStateGuardian *gsg) {
MutexHolder holder(_wl_lock);
_gsgs.insert(gsg);
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsEngine::WindowRenderer::add_window
// Access: Public
@ -958,6 +989,26 @@ do_frame(GraphicsEngine *engine) {
engine->cull_bin_draw(_cull);
engine->cull_and_draw_together(_cdraw);
engine->process_events(_window);
// If any GSG's on the list have no more outstanding pointers, clean
// them up. (We are in the draw thread for all of these GSG's.)
if (any_done_gsgs()) {
GSGs new_gsgs;
GSGs::iterator gi;
for (gi = _gsgs.begin(); gi != _gsgs.end(); ++gi) {
GraphicsStateGuardian *gsg = (*gi);
if (gsg->get_ref_count() == 1) {
// This one has no outstanding pointers; clean it up.
GraphicsPipe *pipe = gsg->get_pipe();
engine->close_gsg(pipe, gsg);
} else {
// This one is ok; preserve it.
new_gsgs.insert(gsg);
}
}
_gsgs.swap(new_gsgs);
}
}
////////////////////////////////////////////////////////////////////
@ -995,7 +1046,7 @@ do_release(GraphicsEngine *) {
// Description: Closes all the windows on the _window list.
////////////////////////////////////////////////////////////////////
void GraphicsEngine::WindowRenderer::
do_close(GraphicsEngine *) {
do_close(GraphicsEngine *engine) {
WindowProperties close_properties;
close_properties.set_open(false);
@ -1005,6 +1056,23 @@ do_close(GraphicsEngine *) {
GraphicsWindow *win = (*wi);
win->set_properties_now(close_properties);
}
// Also close all of the GSG's.
GSGs new_gsgs;
GSGs::iterator gi;
for (gi = _gsgs.begin(); gi != _gsgs.end(); ++gi) {
GraphicsStateGuardian *gsg = (*gi);
if (gsg->get_ref_count() == 1) {
// This one has no outstanding pointers; clean it up.
GraphicsPipe *pipe = gsg->get_pipe();
engine->close_gsg(pipe, gsg);
} else {
// This one is ok; preserve it.
new_gsgs.insert(gsg);
}
}
_gsgs.swap(new_gsgs);
}
////////////////////////////////////////////////////////////////////
@ -1049,6 +1117,26 @@ do_pending(GraphicsEngine *engine) {
}
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsEngine::WindowRenderer::any_done_gsgs
// Access: Public
// Description: Returns true if any of the GSG's on this thread's
// draw list are done (they have no outstanding pointers
// other than this one), or false if all of them are
// still good.
////////////////////////////////////////////////////////////////////
bool GraphicsEngine::WindowRenderer::
any_done_gsgs() const {
GSGs::const_iterator gi;
for (gi = _gsgs.begin(); gi != _gsgs.end(); ++gi) {
if ((*gi)->get_ref_count() == 1) {
return true;
}
}
return false;
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsEngine::RenderThread::Constructor
// Access: Public

View File

@ -21,6 +21,8 @@
#include "pandabase.h"
#include "graphicsWindow.h"
#include "frameBufferProperties.h"
#include "graphicsThreadingModel.h"
#include "sceneSetup.h"
#include "pointerTo.h"
#include "thread.h"
@ -32,6 +34,7 @@
class Pipeline;
class DisplayRegion;
class GraphicsPipe;
class FrameBufferProperties;
////////////////////////////////////////////////////////////////////
// Class : GraphicsEngine
@ -53,15 +56,25 @@ PUBLISHED:
GraphicsEngine(Pipeline *pipeline = NULL);
~GraphicsEngine();
void set_threading_model(const string &threading_model);
string get_threading_model() const;
void set_frame_buffer_properties(const FrameBufferProperties &properties);
FrameBufferProperties get_frame_buffer_properties() const;
void set_threading_model(const GraphicsThreadingModel &threading_model);
GraphicsThreadingModel get_threading_model() const;
INLINE void set_auto_flip(bool auto_flip);
INLINE bool get_auto_flip() const;
INLINE GraphicsWindow *make_window(GraphicsPipe *pipe);
INLINE PT(GraphicsStateGuardian) make_gsg(GraphicsPipe *pipe);
PT(GraphicsStateGuardian) make_gsg(GraphicsPipe *pipe,
const FrameBufferProperties &properties,
const GraphicsThreadingModel &threading_model);
INLINE GraphicsWindow *make_window(GraphicsPipe *pipe,
GraphicsStateGuardian *gsg);
GraphicsWindow *make_window(GraphicsPipe *pipe,
const string &threading_model);
GraphicsStateGuardian *gsg,
const GraphicsThreadingModel &threading_model);
bool remove_window(GraphicsWindow *window);
void remove_all_windows();
bool is_empty() const;
@ -75,6 +88,7 @@ PUBLISHED:
private:
typedef pset< PT(GraphicsWindow) > Windows;
typedef pset< PT(GraphicsStateGuardian) > GSGs;
void cull_and_draw_together(const Windows &wlist);
void cull_and_draw_together(GraphicsStateGuardian *gsg, DisplayRegion *dr);
@ -86,6 +100,7 @@ private:
void flip_windows(const GraphicsEngine::Windows &wlist);
void do_sync_frame();
void do_flip_frame();
INLINE void close_gsg(GraphicsPipe *pipe, GraphicsStateGuardian *gsg);
PT(SceneSetup) setup_scene(const NodePath &camera,
GraphicsStateGuardian *gsg);
@ -104,6 +119,7 @@ private:
// process, and the list of windows for each stage.
class WindowRenderer {
public:
void add_gsg(GraphicsStateGuardian *gsg);
void add_window(Windows &wlist, GraphicsWindow *window);
void remove_window(GraphicsWindow *window);
void do_frame(GraphicsEngine *engine);
@ -111,6 +127,7 @@ private:
void do_release(GraphicsEngine *engine);
void do_close(GraphicsEngine *engine);
void do_pending(GraphicsEngine *engine);
bool any_done_gsgs() const;
Windows _cull; // cull stage
Windows _cdraw; // cull-and-draw-together stage
@ -118,6 +135,7 @@ private:
Windows _window; // window stage, i.e. process windowing events
Windows _pending_release; // moved from _draw, pending release_gsg.
Windows _pending_close; // moved from _window, pending close.
GSGs _gsgs; // draw stage
Mutex _wl_lock;
};
@ -148,7 +166,8 @@ private:
WindowRenderer _app;
typedef pmap<string, PT(RenderThread) > Threads;
Threads _threads;
string _threading_model;
FrameBufferProperties _frame_buffer_properties;
GraphicsThreadingModel _threading_model;
bool _auto_flip;
enum FlipState {

View File

@ -100,3 +100,35 @@ HardwareChannel *GraphicsPipe::
get_hw_channel(GraphicsWindow *, int) {
return (HardwareChannel*)0L;
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsPipe::make_gsg
// Access: Protected, Virtual
// Description: Creates a new GSG to use the pipe (but no windows
// have been created yet for the GSG). This method will
// be called in the draw thread for the GSG.
////////////////////////////////////////////////////////////////////
PT(GraphicsStateGuardian) GraphicsPipe::
make_gsg(const FrameBufferProperties &properties) {
// shouldnt this method really be pure virtual? it's an error for a pipe to not implement it
display_cat.error() << "Error: make_gsg() unimplemented by graphicsPipe!\n";
return NULL;
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsPipe::close_gsg
// Access: Protected, Virtual
// Description: This will be called in the draw thread (the same
// thread in which the GSG was created via make_gsg,
// above) to close the indicated GSG and free its
// associated graphics objects just before it is
// destructed. This method exists to provide a hook for
// the graphics pipe to do any necessary cleanup, if
// any.
////////////////////////////////////////////////////////////////////
void GraphicsPipe::
close_gsg(GraphicsStateGuardian *gsg) {
if (gsg != (GraphicsStateGuardian *)NULL) {
gsg->close_gsg();
}
}

View File

@ -28,6 +28,8 @@
class HardwareChannel;
class GraphicsWindow;
class GraphicsStateGuardian;
class FrameBufferProperties;
////////////////////////////////////////////////////////////////////
// Class : GraphicsPipe
@ -69,11 +71,12 @@ public:
virtual HardwareChannel *get_hw_channel(GraphicsWindow *window, int index);
protected:
// The make_window() interface on GraphicsPipe is protected; don't
// try to call it directly. Instead, use
// GraphicsEngine::make_window() to make a new window on a
// particular pipe.
virtual PT(GraphicsWindow) make_window()=0;
// The make_window() and make_gsg() interfaces on GraphicsPipe are
// protected; don't try to call them directly. Instead, use
// the interface on GraphicsEngine to make a new window or gsg.
virtual PT(GraphicsStateGuardian) make_gsg(const FrameBufferProperties &properties);
virtual void close_gsg(GraphicsStateGuardian *gsg);
virtual PT(GraphicsWindow) make_window(GraphicsStateGuardian *gsg)=0;
Mutex _lock;

View File

@ -41,15 +41,37 @@ ClipPlaneInfo() {
////////////////////////////////////////////////////////////////////
// Function: GraphicsStateGuardian::is_closed
// Function: GraphicsStateGuardian::get_properties
// Access: Public
// Description: Returns true if the window associated with this GSG
// has been closed, and hence the resources associated
// with this GSG have been freed.
// Description: Returns the frame buffer properties requested for
// this GSG. All windows created for this GSG must be
// created with the same properties.
////////////////////////////////////////////////////////////////////
INLINE bool GraphicsStateGuardian::
is_closed() const {
return (_win == (GraphicsWindow *)NULL);
INLINE const FrameBufferProperties &GraphicsStateGuardian::
get_properties() const {
return _properties;
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsStateGuardian::get_pipe
// Access: Public
// Description: Returns the graphics pipe on which this GSG was
// created.
////////////////////////////////////////////////////////////////////
INLINE GraphicsPipe *GraphicsStateGuardian::
get_pipe() const {
return _pipe;
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsStateGuardian::get_threading_model
// Access: Public
// Description: Returns the threading model that was used to create
// this GSG.
////////////////////////////////////////////////////////////////////
INLINE const GraphicsThreadingModel &GraphicsStateGuardian::
get_threading_model() const {
return _threading_model;
}
////////////////////////////////////////////////////////////////////
@ -92,6 +114,19 @@ clear(DisplayRegion *dr) {
pop_display_region(old_dr);
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsStateGuardian::reset_if_new
// Access: Public
// Description: Calls reset() to initialize the GSG, but only if it
// hasn't been called yet.
////////////////////////////////////////////////////////////////////
INLINE void GraphicsStateGuardian::
reset_if_new() {
if (_needs_reset) {
reset();
}
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsStateGuardian::modify_state
// Access: Public

View File

@ -81,12 +81,13 @@ TypeHandle GraphicsStateGuardian::_type_handle;
// Description:
////////////////////////////////////////////////////////////////////
GraphicsStateGuardian::
GraphicsStateGuardian(GraphicsWindow *win) {
_win = win;
GraphicsStateGuardian(const FrameBufferProperties &properties) {
_properties = properties;
_coordinate_system = default_coordinate_system;
_current_display_region = (DisplayRegion*)0L;
_current_lens = (Lens *)NULL;
reset();
_needs_reset = true;
_closing_gsg = false;
}
////////////////////////////////////////////////////////////////////
@ -106,6 +107,8 @@ GraphicsStateGuardian::
////////////////////////////////////////////////////////////////////
void GraphicsStateGuardian::
reset() {
_needs_reset = false;
_display_region_stack_level = 0;
_frame_buffer_stack_level = 0;
_lens_stack_level = 0;
@ -1374,11 +1377,10 @@ free_pointers() {
////////////////////////////////////////////////////////////////////
void GraphicsStateGuardian::
close_gsg() {
_closing_gsg = true;
free_pointers();
release_all_textures();
release_all_geoms();
_win = (GraphicsWindow *)NULL;
}
#ifdef DO_PSTATS

View File

@ -23,10 +23,13 @@
#include "savedFrameBuffer.h"
#include "frameBufferStack.h"
#include "frameBufferProperties.h"
#include "displayRegionStack.h"
#include "lensStack.h"
#include "graphicsStateGuardianBase.h"
#include "graphicsThreadingModel.h"
#include "graphicsPipe.h"
#include "sceneSetup.h"
#include "luse.h"
#include "coordinateSystem.h"
@ -61,7 +64,7 @@ class EXPCL_PANDA GraphicsStateGuardian : public GraphicsStateGuardianBase {
// Interfaces all GSGs should have
//
public:
GraphicsStateGuardian(GraphicsWindow *win);
GraphicsStateGuardian(const FrameBufferProperties &properties);
virtual ~GraphicsStateGuardian();
PUBLISHED:
@ -69,7 +72,9 @@ PUBLISHED:
void release_all_geoms();
public:
INLINE bool is_closed() const;
INLINE const FrameBufferProperties &get_properties() const;
INLINE GraphicsPipe *get_pipe() const;
INLINE const GraphicsThreadingModel &get_threading_model() const;
INLINE void set_scene(SceneSetup *scene_setup);
INLINE SceneSetup *get_scene() const;
@ -119,6 +124,7 @@ public:
virtual CPT(RenderState) begin_decal_base_second();
virtual void finish_decal();
INLINE void reset_if_new();
virtual void reset();
INLINE void modify_state(const RenderState *state);
@ -232,8 +238,6 @@ protected:
int _frame_buffer_stack_level;
int _lens_stack_level;
GraphicsWindow *_win;
CPT(DisplayRegion) _current_display_region;
CPT(Lens) _current_lens;
@ -261,6 +265,9 @@ protected:
ColorBlendAttrib::Mode _color_blend_mode;
TransparencyAttrib::Mode _transparency_mode;
bool _needs_reset;
bool _closing_gsg;
public:
// Statistics
static PStatCollector _total_texusage_pcollector;
@ -324,11 +331,12 @@ private:
typedef pset<GeomNodeContext *> GeomNodes;
GeomNodes _prepared_geom_nodes;
public:
void traverse_prepared_textures(bool (*pertex_callbackfn)(TextureContext *,void *),void *callback_arg);
FrameBufferProperties _properties;
PT(GraphicsPipe) _pipe;
GraphicsThreadingModel _threading_model;
public:
INLINE GraphicsWindow* get_window(void) const { return _win; }
void traverse_prepared_textures(bool (*pertex_callbackfn)(TextureContext *,void *),void *callback_arg);
public:
static TypeHandle get_class_type() {
@ -351,6 +359,7 @@ private:
friend class GraphicsPipe;
friend class GraphicsWindow;
friend class GraphicsEngine;
};
#include "graphicsStateGuardian.I"

View File

@ -37,11 +37,12 @@ TypeHandle GraphicsWindow::_type_handle;
// GraphicsEngine::make_window() function.
////////////////////////////////////////////////////////////////////
GraphicsWindow::
GraphicsWindow(GraphicsPipe *pipe) {
GraphicsWindow(GraphicsPipe *pipe, GraphicsStateGuardian *gsg) {
#ifdef DO_MEMORY_USAGE
MemoryUsage::update_type(this, this);
#endif
_pipe = pipe;
_gsg = gsg;
// Some default properties for windows unless specified otherwise.
// Other properties (size, title, etc.) must be explicitly
@ -51,11 +52,7 @@ GraphicsWindow(GraphicsPipe *pipe) {
_properties.set_fullscreen(false);
_properties.set_minimized(false);
_properties.set_cursor_hidden(false);
_properties.set_depth_bits(1);
_properties.set_color_bits(1);
_properties.set_framebuffer_mode(WindowProperties::FM_rgba |
WindowProperties::FM_double_buffer |
WindowProperties::FM_depth);
_display_regions_stale = false;
_window_event = "window-event";
@ -581,32 +578,11 @@ make_scratch_display_region(int x_size, int y_size) const {
bool GraphicsWindow::
begin_frame() {
if (_gsg == (GraphicsStateGuardian *)NULL) {
MutexHolder holder(_lock);
// Oops, we don't have a GSG yet.
if (!_properties.get_open()) {
return false;
}
make_gsg();
if (_gsg == (GraphicsStateGuardian *)NULL) {
// Still couldn't make the GSG for some reason. We should pass
// an appropriate diagnostic up to the application; for now,
// we'll just shut down the window.
// WARNING: this is a non-thread-safe hack. This really should
// happen in the window thread, not here in the draw thread.
display_cat.info()
<< "Could not open GSG, closing " << get_type() << ".\n";
close_window();
WindowProperties properties;
properties.set_open(false);
system_changed_properties(properties);
return false;
}
} else {
// Okay, we already have a GSG, so activate it.
make_current();
return false;
}
// Okay, we already have a GSG, so activate it.
make_current();
return _gsg->begin_frame();
}
@ -652,32 +628,6 @@ end_frame() {
_gsg->end_frame();
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsWindow::make_gsg
// Access: Public, Virtual
// Description: Creates a new GSG for the window and stores it in the
// _gsg pointer. This should only be called from within
// the draw thread.
////////////////////////////////////////////////////////////////////
void GraphicsWindow::
make_gsg() {
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsWindow::release_gsg
// Access: Public, Virtual
// Description: Releases the current GSG pointer, if it is currently
// held, and resets the GSG to NULL. This should only
// be called from within the draw thread.
////////////////////////////////////////////////////////////////////
void GraphicsWindow::
release_gsg() {
if (_gsg != (GraphicsStateGuardian *)NULL) {
_gsg->close_gsg();
_gsg.clear();
}
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsWindow::make_current
// Access: Public, Virtual
@ -689,6 +639,20 @@ 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

View File

@ -58,7 +58,7 @@
////////////////////////////////////////////////////////////////////
class EXPCL_PANDA GraphicsWindow : public TypedReferenceCount, public ClearableRegion {
protected:
GraphicsWindow(GraphicsPipe *pipe);
GraphicsWindow(GraphicsPipe *pipe, GraphicsStateGuardian *gsg);
private:
GraphicsWindow(const GraphicsWindow &copy);
@ -119,12 +119,10 @@ public:
void clear();
virtual void end_frame();
virtual void make_gsg();
virtual void release_gsg();
// 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();

View File

@ -513,150 +513,6 @@ clear_cursor_hidden() {
_flags &= ~F_cursor_hidden;
}
////////////////////////////////////////////////////////////////////
// Function: WindowProperties::set_framebuffer_mode
// Access: Published
// Description: Specifies the set of graphics properties that are
// required for the context associated with the window.
// This should be the union of the appropriate bits
// defined in FramebufferMode.
////////////////////////////////////////////////////////////////////
INLINE void WindowProperties::
set_framebuffer_mode(int framebuffer_mode) {
_framebuffer_mode = framebuffer_mode;
_specified |= S_framebuffer_mode;
}
////////////////////////////////////////////////////////////////////
// Function: WindowProperties::get_framebuffer_mode
// Access: Published
// Description: Returns the set of graphics properties that are
// in effect for the window. This will be the union of
// the corresponding bits from FramebufferMode.
////////////////////////////////////////////////////////////////////
INLINE int WindowProperties::
get_framebuffer_mode() const {
nassertr(has_framebuffer_mode(), false);
return _framebuffer_mode;
}
////////////////////////////////////////////////////////////////////
// Function: WindowProperties::has_framebuffer_mode
// Access: Published
// Description: Returns true if the framebuffer mode has been
// specified, false otherwise.
////////////////////////////////////////////////////////////////////
INLINE bool WindowProperties::
has_framebuffer_mode() const {
return ((_specified & S_framebuffer_mode) != 0);
}
////////////////////////////////////////////////////////////////////
// Function: WindowProperties::clear_framebuffer_mode
// Access: Published
// Description: Removes the framebuffer_mode specification from the
// properties.
////////////////////////////////////////////////////////////////////
INLINE void WindowProperties::
clear_framebuffer_mode() {
_specified &= ~S_framebuffer_mode;
_framebuffer_mode = 0;
}
////////////////////////////////////////////////////////////////////
// Function: WindowProperties::set_depth_bits
// Access: Published
// Description: Specifies the minimum number of bits that are
// required for the depth buffer.
////////////////////////////////////////////////////////////////////
INLINE void WindowProperties::
set_depth_bits(int depth_bits) {
_depth_bits = depth_bits;
_specified |= S_depth_bits;
}
////////////////////////////////////////////////////////////////////
// Function: WindowProperties::get_depth_bits
// Access: Published
// Description: Returns the number of bits specified for the depth
// buffer.
////////////////////////////////////////////////////////////////////
INLINE int WindowProperties::
get_depth_bits() const {
return _depth_bits;
}
////////////////////////////////////////////////////////////////////
// Function: WindowProperties::has_depth_bits
// Access: Published
// Description: Returns true if the number of bits for the depth
// buffer has been specified, false otherwise.
////////////////////////////////////////////////////////////////////
INLINE bool WindowProperties::
has_depth_bits() const {
return ((_specified & S_depth_bits) != 0);
}
////////////////////////////////////////////////////////////////////
// Function: WindowProperties::clear_depth_bits
// Access: Published
// Description: Removes the depth_bits specification from the
// properties.
////////////////////////////////////////////////////////////////////
INLINE void WindowProperties::
clear_depth_bits() {
_specified &= ~S_depth_bits;
_depth_bits = 0;
}
////////////////////////////////////////////////////////////////////
// Function: WindowProperties::set_color_bits
// Access: Published
// Description: Specifies the minimum number of bits that are
// required for all three channels of the color buffer.
// That is, this is the per-channel color requirement
// times three.
////////////////////////////////////////////////////////////////////
INLINE void WindowProperties::
set_color_bits(int color_bits) {
_color_bits = color_bits;
_specified |= S_color_bits;
}
////////////////////////////////////////////////////////////////////
// Function: WindowProperties::get_color_bits
// Access: Published
// Description: Returns the number of bits specified for the color
// buffer.
////////////////////////////////////////////////////////////////////
INLINE int WindowProperties::
get_color_bits() const {
return _color_bits;
}
////////////////////////////////////////////////////////////////////
// Function: WindowProperties::has_color_bits
// Access: Published
// Description: Returns true if the number of bits for the color
// buffer has been specified, false otherwise.
////////////////////////////////////////////////////////////////////
INLINE bool WindowProperties::
has_color_bits() const {
return ((_specified & S_color_bits) != 0);
}
////////////////////////////////////////////////////////////////////
// Function: WindowProperties::clear_color_bits
// Access: Published
// Description: Removes the color_bits specification from the
// properties.
////////////////////////////////////////////////////////////////////
INLINE void WindowProperties::
clear_color_bits() {
_specified &= ~S_color_bits;
_color_bits = 0;
}
INLINE ostream &
operator << (ostream &out, const WindowProperties &properties) {
properties.output(out);

View File

@ -43,9 +43,6 @@ operator = (const WindowProperties &copy) {
_y_size = copy._y_size;
_title = copy._title;
_flags = copy._flags;
_framebuffer_mode = copy._framebuffer_mode;
_depth_bits = copy._depth_bits;
_color_bits = copy._color_bits;
}
////////////////////////////////////////////////////////////////////
@ -61,10 +58,7 @@ operator == (const WindowProperties &other) const {
_y_origin == other._y_origin &&
_x_size == other._x_size &&
_y_size == other._y_size &&
_title == other._title &&
_framebuffer_mode == other._framebuffer_mode &&
_depth_bits == other._depth_bits &&
_color_bits == other._color_bits);
_title == other._title);
}
////////////////////////////////////////////////////////////////////
@ -83,9 +77,6 @@ clear() {
_y_size = 0;
_title = string();
_flags = 0;
_framebuffer_mode = 0;
_depth_bits = 0;
_color_bits = 0;
}
////////////////////////////////////////////////////////////////////
@ -124,15 +115,6 @@ add_properties(const WindowProperties &other) {
if (other.has_cursor_hidden()) {
set_cursor_hidden(other.get_cursor_hidden());
}
if (other.has_framebuffer_mode()) {
set_framebuffer_mode(other.get_framebuffer_mode());
}
if (other.has_depth_bits()) {
set_depth_bits(other.get_depth_bits());
}
if (other.has_color_bits()) {
set_color_bits(other.get_color_bits());
}
}
////////////////////////////////////////////////////////////////////
@ -171,50 +153,4 @@ output(ostream &out) const {
if (has_cursor_hidden()) {
out << (get_cursor_hidden() ? "cursor_hidden " : "!cursor_hidden ");
}
if (has_framebuffer_mode()) {
out << "framebuffer_mode=";
int framebuffer_mode = get_framebuffer_mode();
if ((framebuffer_mode & FM_index) != 0) {
out << "FM_index";
} else {
out << "FM_rgb";
}
if ((framebuffer_mode & FM_triple_buffer) != 0) {
out << "|FM_triple_buffer";
} else if ((framebuffer_mode & FM_double_buffer) != 0) {
out << "|FM_double_buffer";
} else {
out << "|FM_single_buffer";
}
if ((framebuffer_mode & FM_accum) != 0) {
out << "|FM_accum";
}
if ((framebuffer_mode & FM_alpha) != 0) {
out << "|FM_alpha";
}
if ((framebuffer_mode & FM_depth) != 0) {
out << "|FM_depth";
}
if ((framebuffer_mode & FM_stencil) != 0) {
out << "|FM_stencil";
}
if ((framebuffer_mode & FM_multisample) != 0) {
out << "|FM_multisample";
}
if ((framebuffer_mode & FM_stereo) != 0) {
out << "|FM_stereo";
}
if ((framebuffer_mode & FM_luminance) != 0) {
out << "|FM_luminance";
}
out << " ";
}
if (has_depth_bits()) {
out << "depth_bits=" << get_depth_bits() << " ";
}
if (has_color_bits()) {
out << "color_bits=" << get_color_bits() << " ";
}
}

View File

@ -38,22 +38,6 @@ PUBLISHED:
bool operator == (const WindowProperties &other) const;
INLINE bool operator != (const WindowProperties &other) const;
enum FramebufferMode {
FM_rgba = 0x0000,
FM_rgb = 0x0000,
FM_index = 0x0001,
FM_single_buffer = 0x0000,
FM_double_buffer = 0x0002,
FM_triple_buffer = 0x0004,
FM_accum = 0x0008,
FM_alpha = 0x0010,
FM_depth = 0x0020,
FM_stencil = 0x0040,
FM_multisample = 0x0080,
FM_stereo = 0x0100,
FM_luminance = 0x0200,
};
void clear();
INLINE bool is_any_specified() const;
@ -104,21 +88,6 @@ PUBLISHED:
INLINE bool has_cursor_hidden() const;
INLINE void clear_cursor_hidden();
INLINE void set_framebuffer_mode(int framebuffer_mode);
INLINE int get_framebuffer_mode() const;
INLINE bool has_framebuffer_mode() const;
INLINE void clear_framebuffer_mode();
INLINE void set_depth_bits(int depth_bits);
INLINE int get_depth_bits() const;
INLINE bool has_depth_bits() const;
INLINE void clear_depth_bits();
INLINE void set_color_bits(int color_bits);
INLINE int get_color_bits() const;
INLINE bool has_color_bits() const;
INLINE void clear_color_bits();
void add_properties(const WindowProperties &other);
void output(ostream &out) const;
@ -137,9 +106,6 @@ private:
S_minimized = 0x0040,
S_open = 0x0080,
S_cursor_hidden = 0x0100,
S_framebuffer_mode = 0x0200,
S_depth_bits = 0x0400,
S_color_bits = 0x0800,
};
// This bitmask represents the true/false settings for various
@ -161,9 +127,6 @@ private:
int _y_size;
string _title;
int _flags;
int _framebuffer_mode;
int _depth_bits;
int _color_bits;
};
INLINE ostream &operator << (ostream &out, const WindowProperties &properties);

View File

@ -259,8 +259,9 @@ int NonlinearImager::
add_viewer(DisplayRegion *dr) {
GraphicsWindow *win = dr->get_window();
GraphicsStateGuardian *gsg = win->get_gsg();
nassertr(_viewers.empty() || gsg == _gsg, -1);
nassertr(_viewers.empty() || (gsg == _gsg && win == _win), -1);
_gsg = gsg;
_win = win;
int previous_vi = find_viewer(dr);
if (previous_vi >= 0) {
@ -601,7 +602,7 @@ render_screen(GraphicsEngine *engine, NonlinearImager::Screen &screen) {
// Make a display region of the proper size and clear it to prepare for
// rendering the scene.
PT(DisplayRegion) scratch_region =
_gsg->get_window()->make_scratch_display_region(screen._tex_width, screen._tex_height);
_win->make_scratch_display_region(screen._tex_width, screen._tex_height);
scratch_region->set_camera(screen._source_camera);
engine->render_subframe(_gsg, scratch_region, true);

View File

@ -32,6 +32,7 @@
class GraphicsEngine;
class GraphicsStateGuardian;
class GraphicsWindow;
////////////////////////////////////////////////////////////////////
// Class : NonlinearImager
@ -162,6 +163,7 @@ private:
Viewers _viewers;
Screens _screens;
GraphicsStateGuardian *_gsg;
GraphicsWindow *_win;
bool _stale;
};

View File

@ -30,12 +30,12 @@ enable_line_smooth(bool val) {
_line_smooth_enabled = val;
#ifdef NDEBUG
{
if(val && (scrn.D3DDevDesc.dpcTriCaps.dwRasterCaps & D3DPRASTERCAPS_ANTIALIASEDGES))
if(val && (_pScrn->D3DDevDesc.dpcTriCaps.dwRasterCaps & D3DPRASTERCAPS_ANTIALIASEDGES))
dxgsg7_cat.error() << "no HW support for line smoothing!!\n";
}
#endif
scrn.pD3DDevice->SetRenderState(D3DRENDERSTATE_EDGEANTIALIAS, (DWORD)val);
_pScrn->pD3DDevice->SetRenderState(D3DRENDERSTATE_EDGEANTIALIAS, (DWORD)val);
}
}
@ -50,14 +50,14 @@ enable_dither(bool val) {
#ifdef _DEBUG
{
if(val && !(scrn.D3DDevDesc.dpcTriCaps.dwRasterCaps & D3DPRASTERCAPS_DITHER))
if(val && !(_pScrn->D3DDevDesc.dpcTriCaps.dwRasterCaps & D3DPRASTERCAPS_DITHER))
dxgsg7_cat.error() << "no HW support for color dithering!!\n";
return;
}
#endif
_dither_enabled = val;
scrn.pD3DDevice->SetRenderState(D3DRENDERSTATE_DITHERENABLE, (DWORD)val);
_pScrn->pD3DDevice->SetRenderState(D3DRENDERSTATE_DITHERENABLE, (DWORD)val);
}
}
@ -70,7 +70,7 @@ INLINE void DXGraphicsStateGuardian7::
enable_stencil_test(bool val) {
if (_stencil_test_enabled != val) {
_stencil_test_enabled = val;
scrn.pD3DDevice->SetRenderState(D3DRENDERSTATE_STENCILENABLE, (DWORD)val);
_pScrn->pD3DDevice->SetRenderState(D3DRENDERSTATE_STENCILENABLE, (DWORD)val);
}
}
@ -95,7 +95,7 @@ INLINE void DXGraphicsStateGuardian7::
enable_blend(bool val) {
if (_blend_enabled != val) {
_blend_enabled = val;
scrn.pD3DDevice->SetRenderState(D3DRENDERSTATE_ALPHABLENDENABLE, (DWORD)val);
_pScrn->pD3DDevice->SetRenderState(D3DRENDERSTATE_ALPHABLENDENABLE, (DWORD)val);
}
}
@ -108,7 +108,7 @@ INLINE void DXGraphicsStateGuardian7::
set_shademode(D3DSHADEMODE val) {
if (_CurShadeMode != val) {
_CurShadeMode = val;
scrn.pD3DDevice->SetRenderState(D3DRENDERSTATE_SHADEMODE, (DWORD)val);
_pScrn->pD3DDevice->SetRenderState(D3DRENDERSTATE_SHADEMODE, (DWORD)val);
}
}
@ -116,7 +116,7 @@ INLINE void DXGraphicsStateGuardian7::
enable_primitive_clipping(bool val) {
if (_clipping_enabled != val) {
_clipping_enabled = val;
scrn.pD3DDevice->SetRenderState(D3DRENDERSTATE_CLIPPING, (DWORD)val);
_pScrn->pD3DDevice->SetRenderState(D3DRENDERSTATE_CLIPPING, (DWORD)val);
}
}
@ -129,7 +129,7 @@ INLINE void DXGraphicsStateGuardian7::
enable_fog(bool val) {
if ((_fog_enabled != val) && (_doFogType!=None)) {
_fog_enabled = val;
scrn.pD3DDevice->SetRenderState(D3DRENDERSTATE_FOGENABLE, (DWORD)val);
_pScrn->pD3DDevice->SetRenderState(D3DRENDERSTATE_FOGENABLE, (DWORD)val);
}
}
@ -143,7 +143,7 @@ enable_alpha_test(bool val )
{
if (_alpha_test_enabled != val) {
_alpha_test_enabled = val;
scrn.pD3DDevice->SetRenderState(D3DRENDERSTATE_ALPHATESTENABLE, (DWORD)val);
_pScrn->pD3DDevice->SetRenderState(D3DRENDERSTATE_ALPHATESTENABLE, (DWORD)val);
}
}
@ -160,7 +160,7 @@ call_dxLightModelAmbient( const Colorf& color)
#ifdef GSG_VERBOSE
dxgsg7_cat.debug() << "dxLightModel(LIGHT_MODEL_AMBIENT, " << color << ")" << endl;
#endif
scrn.pD3DDevice->SetRenderState( D3DRENDERSTATE_AMBIENT,
_pScrn->pD3DDevice->SetRenderState( D3DRENDERSTATE_AMBIENT,
D3DRGBA(color[0], color[1], color[2], color[3]));
}
}
@ -208,12 +208,12 @@ call_dxAlphaFunc(D3DCMPFUNC func, float reference_alpha) {
}
dxgsg7_cat.debug() << " , " << reference_alpha << ")" << endl;
#endif
scrn.pD3DDevice->SetRenderState(D3DRENDERSTATE_ALPHAFUNC, func);
_pScrn->pD3DDevice->SetRenderState(D3DRENDERSTATE_ALPHAFUNC, func);
}
if(_alpha_func_refval != reference_alpha) {
_alpha_func_refval = reference_alpha;
scrn.pD3DDevice->SetRenderState(D3DRENDERSTATE_ALPHAREF, (UINT) (reference_alpha*255.0f)); //d3d uses 0x0-0xFF, not a float
_pScrn->pD3DDevice->SetRenderState(D3DRENDERSTATE_ALPHAREF, (UINT) (reference_alpha*255.0f)); //d3d uses 0x0-0xFF, not a float
}
}
@ -223,7 +223,7 @@ call_dxBlendFunc(D3DBLEND sfunc, D3DBLEND dfunc )
if (_blend_source_func != sfunc)
{
_blend_source_func = sfunc;
scrn.pD3DDevice->SetRenderState(D3DRENDERSTATE_SRCBLEND, sfunc);
_pScrn->pD3DDevice->SetRenderState(D3DRENDERSTATE_SRCBLEND, sfunc);
#ifdef GSG_VERBOSE
dxgsg7_cat.debug() << "dxSrcBlendFunc(";
switch (sfunc)
@ -265,7 +265,7 @@ call_dxBlendFunc(D3DBLEND sfunc, D3DBLEND dfunc )
if ( _blend_dest_func != dfunc)
{
_blend_dest_func = dfunc;
scrn.pD3DDevice->SetRenderState(D3DRENDERSTATE_DESTBLEND, dfunc);
_pScrn->pD3DDevice->SetRenderState(D3DRENDERSTATE_DESTBLEND, dfunc);
#ifdef GSG_VERBOSE
dxgsg7_cat.debug() << "dxDstBlendFunc(";
switch (dfunc)
@ -307,7 +307,7 @@ INLINE void DXGraphicsStateGuardian7::
enable_zwritemask(bool val) {
if (_depth_write_enabled != val) {
_depth_write_enabled = val;
scrn.pD3DDevice->SetRenderState(D3DRENDERSTATE_ZWRITEENABLE, val);
_pScrn->pD3DDevice->SetRenderState(D3DRENDERSTATE_ZWRITEENABLE, val);
}
}

File diff suppressed because it is too large Load Diff

View File

@ -65,7 +65,7 @@ class EXPCL_PANDADX DXGraphicsStateGuardian7 : public GraphicsStateGuardian {
friend class DXTextureContext7;
public:
DXGraphicsStateGuardian7(GraphicsWindow *win);
DXGraphicsStateGuardian7(const FrameBufferProperties &properties);
~DXGraphicsStateGuardian7();
virtual void reset();
@ -128,7 +128,7 @@ public:
virtual void bind_light(DirectionalLight *light, int light_id);
virtual void bind_light(Spotlight *light, int light_id);
virtual bool begin_frame();
//virtual bool begin_frame();
virtual bool begin_scene();
virtual void end_scene();
virtual void end_frame();
@ -144,7 +144,8 @@ public:
public:
// recreate_tex_callback needs pDD,pD3DDevice to be public
DXScreenData scrn;
DXScreenData *_pScrn;
LPDIRECT3DDEVICE7 _pD3DDevice; // cache copy of _pScrn->pD3DDevice, just for speedier access
#ifndef USE_TEXFMTVEC
LPDDPIXELFORMAT _pTexPixFmts;
@ -225,6 +226,7 @@ protected:
INLINE void enable_stencil_test(bool val);
void report_texmgr_stats();
void draw_multitri(Geom *geom, D3DPRIMITIVETYPE tri_id);
void set_context(DXScreenData *pNewContextData);
void draw_prim_inner_loop(int nVerts, const Geom *geom, ushort perFlags);
void draw_prim_inner_loop_coordtexonly(int nVerts, const Geom *geom);
@ -301,7 +303,7 @@ protected:
DWORD _clip_plane_bits;
RenderModeAttrib::Mode _current_fill_mode; //poinr/wireframe/solid
GraphicsChannel *_panda_gfx_channel; // cache the 1 channel dx supports
// GraphicsChannel *_panda_gfx_channel; // cache the 1 channel dx supports
// Cur Texture State
TextureApplyAttrib::Mode _CurTexBlendMode;
@ -321,6 +323,16 @@ protected:
bool _overlay_windows_supported;
#if 0
// This is here just as a temporary hack so this file will still
// compile. However, it is never initialized and will certainly
// cause the code to crash when it is referenced. (This used to be
// inherited from the base class, but the new design requires that a
// GSG may be used for multiple windows, so it doesn't make sense to
// store a window pointer any more.)
GraphicsWindow *_win;
#endif
public:
static GraphicsStateGuardian*
make_DXGraphicsStateGuardian(const FactoryParams &params);
@ -329,12 +341,6 @@ public:
static void init_type(void);
virtual TypeHandle get_type(void) const;
virtual TypeHandle force_init_type() {init_type(); return get_class_type();}
/*
LPDIRECT3DDEVICE7 GetD3DDevice() { return scrn.pD3DDevice; }
LPDIRECTDRAW7 GetDDInterface() { return scrn.pDD; }
LPDIRECTDRAWSURFACE7 GetBackBuffer() { return scrn.pddsBackBuffer; }
LPDIRECTDRAWSURFACE7 GetZBuffer() { return _zbuf; }
*/
// INLINE void Set_HDC(HDC hdc) { _front_hdc = hdc; }
void adjust_view_rect(int x, int y);
INLINE void SetDXReady(bool stat) { _dx_ready = stat; }
@ -346,7 +352,7 @@ public:
#define DO_REACTIVATE_WINDOW true
bool CheckCooperativeLevel(bool bDoReactivateWindow = false);
void dx_setup_after_resize(RECT viewrect,HWND mwindow) ;
void dx_setup_after_resize(RECT *pViewRect);
void show_frame();
void show_full_screen_frame();
void show_windowed_frame();

View File

@ -40,7 +40,7 @@
#error DX7 headers not available, you need to install MS Platform SDK or DirectX 8+ SDK!
#endif
#include <pandabase.h>
#include "pandabase.h"
// disable nameless struct 'warning'
#pragma warning (disable : 4201)
@ -63,12 +63,14 @@ typedef pvector<DDPIXELFORMAT> DDPixelFormatVec;
#define SAFE_DELETE(p) { if(p) { delete (p); (p)=NULL; } }
#define SAFE_DELETE_ARRAY(p) { if(p) { delete[] (p); (p)=NULL; } }
#define SAFE_FREELIB(hDLL) { if(hDLL!=NULL) { FreeLibrary(hDLL); hDLL = NULL; } }
#define IS_VALID_PTR(PTR) (!IsBadWritePtr(PTR,sizeof(void*)))
// this is bDoDownToZero argument to RELEASE()
#define RELEASE_DOWN_TO_ZERO true
#define RELEASE_ONCE false
// #define DEBUG_RELEASES
#define DEBUG_RELEASES
#ifdef DEBUG_RELEASES
#define RELEASE(OBJECT,MODULE,DBGSTR,bDoDownToZero) \
@ -124,6 +126,7 @@ typedef struct {
bool bIsLowVidMemCard;
bool bIsTNLDevice;
bool bIsSWRast;
bool bIsFullScreen;
WORD depth_buffer_bitdepth; //GetSurfaceDesc is not reliable so must store this explicitly
WORD CardIDNum; // its posn in DisplayArray, for dbgprint purposes
DDDEVICEIDENTIFIER2 DXDeviceID;

View File

@ -40,10 +40,7 @@ wdxGraphicsPipe7() {
////////////////////////////////////////////////////////////////////
wdxGraphicsPipe7::
~wdxGraphicsPipe7() {
if (_hDDrawDLL != NULL) {
FreeLibrary(_hDDrawDLL);
_hDDrawDLL = NULL;
}
SAFE_FREELIB(_hDDrawDLL);
}
////////////////////////////////////////////////////////////////////
@ -79,8 +76,21 @@ pipe_constructor() {
// Description: Creates a new window on the pipe, if possible.
////////////////////////////////////////////////////////////////////
PT(GraphicsWindow) wdxGraphicsPipe7::
make_window() {
return new wdxGraphicsWindow7(this);
make_window(GraphicsStateGuardian *gsg) {
// thanks to the dumb threading requirements this constructor actually does nothing but create an empty c++ object
// no windows are really opened until wdxGraphicsWindow8->open_window() is called
return new wdxGraphicsWindow7(this, gsg);
}
PT(GraphicsStateGuardian) wdxGraphicsPipe7::
make_gsg(const FrameBufferProperties &properties) {
// FrameBufferProperties really belongs as part of the window/renderbuffer specification
// put here because of GLX multithreading requirement
PT(DXGraphicsStateGuardian7) gsg = new DXGraphicsStateGuardian7(properties);
return gsg.p();
}
////////////////////////////////////////////////////////////////////
@ -94,21 +104,17 @@ make_window() {
////////////////////////////////////////////////////////////////////
bool wdxGraphicsPipe7::
init() {
static const char * const ddraw_name = "ddraw.dll";
_hDDrawDLL = LoadLibrary(ddraw_name);
if(_hDDrawDLL == 0) {
wdxdisplay7_cat.error()
<< "can't locate " << ddraw_name << "!\n";
return false;
if(!MyLoadLib(_hDDrawDLL,"ddraw.dll")) {
goto error;
}
_DirectDrawCreateEx =
(LPDIRECTDRAWCREATEEX)GetProcAddress(_hDDrawDLL, "DirectDrawCreateEx");
if (_DirectDrawCreateEx == NULL) {
wdxdisplay7_cat.error()
<< "GetProcAddr failed for DDCreateEx" << endl;
return false;
if(!MyGetProcAddr(_hDDrawDLL, (FARPROC*)&_DirectDrawCreateEx, "DirectDrawCreateEx")) {
goto error;
}
return true;
error:
return false;
}

View File

@ -34,9 +34,10 @@ public:
virtual string get_interface_name() const;
static PT(GraphicsPipe) pipe_constructor();
virtual PT(GraphicsStateGuardian) make_gsg(const FrameBufferProperties &properties);
protected:
virtual PT(GraphicsWindow) make_window();
virtual PT(GraphicsWindow) make_window(GraphicsStateGuardian *gsg);
private:
bool init();
@ -61,6 +62,7 @@ public:
}
virtual TypeHandle force_init_type() {init_type(); return get_class_type();}
private:
static TypeHandle _type_handle;

View File

@ -116,10 +116,11 @@ TypeHandle wdxGraphicsWindow7::_type_handle;
// Description:
////////////////////////////////////////////////////////////////////
wdxGraphicsWindow7::
wdxGraphicsWindow7(GraphicsPipe *pipe) :
WinGraphicsWindow(pipe)
wdxGraphicsWindow7(GraphicsPipe *pipe, GraphicsStateGuardian *gsg) :
WinGraphicsWindow(pipe, gsg)
{
_dxgsg = (DXGraphicsStateGuardian7 *)NULL;
_dxgsg = DCAST(DXGraphicsStateGuardian7, gsg);
ZeroMemory(&_wcontext,sizeof(_wcontext));
}
////////////////////////////////////////////////////////////////////
@ -131,6 +132,47 @@ wdxGraphicsWindow7::
~wdxGraphicsWindow7() {
}
void wdxGraphicsWindow7::
make_current(void) {
DXGraphicsStateGuardian7 *dxgsg;
DCAST_INTO_V(dxgsg, _gsg);
//wglMakeCurrent(_hdc, wdxgsg->_context);
dxgsg->set_context(&_wcontext);
// Now that we have made the context current to a window, we can
// reset the GSG state if this is the first time it has been used.
// (We can't just call reset() when we construct the GSG, because
// reset() requires having a current context.)
dxgsg->reset_if_new();
}
////////////////////////////////////////////////////////////////////
// Function: wdxGraphicsWindow7::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 wdxGraphicsWindow7::
open_window(void) {
if (!choose_device(0, NULL)) {
wdxdisplay7_cat.error() << "Unable to find suitable rendering device.\n";
return false;
}
if (!WinGraphicsWindow::open_window()) {
return false;
}
_wcontext.hWnd = _hWnd;
set_coop_levels_and_display_modes();
create_screen_buffers_and_device(_wcontext, dx_force_16bpp_zbuffer);
return true;
}
/*
////////////////////////////////////////////////////////////////////
// Function: wdxGraphicsWindow7::make_gsg
// Access: Public, Virtual
@ -144,9 +186,9 @@ make_gsg() {
_dxgsg = new DXGraphicsStateGuardian7(this);
_gsg = _dxgsg;
// Tell the associated dxGSG about the window handle.
_dxgsg->scrn.hWnd = _mwindow;
_wcontext.hWnd = _hWnd;
if (!search_for_device(0, NULL)) {
if (!choose_device(0, NULL)) {
wdxdisplay7_cat.error()
<< "Unable to find suitable rendering device.\n";
release_gsg();
@ -156,30 +198,7 @@ make_gsg() {
set_coop_levels_and_display_modes();
create_screen_buffers_and_device(_dxgsg->scrn, dx_force_16bpp_zbuffer);
}
////////////////////////////////////////////////////////////////////
// Function: wdxGraphicsWindow7::release_gsg
// Access: Public, Virtual
// Description: Releases the current GSG pointer, if it is currently
// held, and resets the GSG to NULL. This should only
// be called from within the draw thread.
////////////////////////////////////////////////////////////////////
void wdxGraphicsWindow7::
release_gsg() {
if (_gsg != (GraphicsStateGuardian *)NULL) {
if (is_fullscreen()) {
// Release the cooperative level we grabbed when we created the
// GSG.
DXScreenData *pScrn = &_dxgsg->scrn;
nassertv(pScrn != (DXScreenData *)NULL);
if (pScrn->pDD != (LPDIRECTDRAW7)NULL) {
pScrn->pDD->SetCooperativeLevel(_mwindow, DDSCL_NORMAL);
}
}
GraphicsWindow::release_gsg();
}
}
*/
////////////////////////////////////////////////////////////////////
// Function: wdxGraphicsWindow7::end_flip
@ -234,15 +253,15 @@ handle_reshape() {
if (_dxgsg!=NULL) {
HRESULT hr;
if (_dxgsg->scrn.pddsBack == NULL) {
if (_wcontext.pddsBack == NULL) {
// assume this is initial creation reshape and ignore this call
return;
}
// Clear the back/primary surface to black
// Clear the back/primary surface to black using ddraw
DX_DECLARE_CLEAN(DDBLTFX, bltfx);
bltfx.dwDDFX |= DDBLTFX_NOTEARING;
hr = _dxgsg->scrn.pddsPrimary->Blt
hr = _wcontext.pddsPrimary->Blt
(NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &bltfx);
if (FAILED(hr)) {
wdxdisplay7_cat.fatal()
@ -251,7 +270,7 @@ handle_reshape() {
exit(1);
}
hr = _dxgsg->scrn.pDD->TestCooperativeLevel();
hr = _wcontext.pDD->TestCooperativeLevel();
if (FAILED(hr)) {
wdxdisplay7_cat.error()
<< "TestCooperativeLevel failed : result = "
@ -264,10 +283,13 @@ handle_reshape() {
set_to_temp_rendertarget();
// create the new resized rendertargets
//RECT view_rect;
//get_client_rect_screen(hWnd, &view_rect);
//_dxgsg->dx_setup_after_resize(view_rect, &_wcontext);
RECT view_rect;
HWND hWnd = _dxgsg->scrn.hWnd;
get_client_rect_screen(hWnd, &view_rect);
_dxgsg->dx_setup_after_resize(view_rect, hWnd);
get_client_rect_screen(_wcontext.hWnd, &view_rect);
_dxgsg->dx_setup_after_resize(&view_rect);
}
}
@ -285,7 +307,7 @@ do_fullscreen_resize(int x_size, int y_size) {
DX_DECLARE_CLEAN(DDSURFACEDESC2,ddsd_curmode);
hr = _dxgsg->scrn.pDD->GetDisplayMode(&ddsd_curmode);
hr = _wcontext.pDD->GetDisplayMode(&ddsd_curmode);
if (FAILED(hr)) {
wdxdisplay7_cat.fatal()
<< "resize() - GetDisplayMode failed, result = "
@ -310,7 +332,7 @@ do_fullscreen_resize(int x_size, int y_size) {
DMI.maxHeight = y_size;
DMI.pDDSD_Arr = DDSD_Arr;
hr = _dxgsg->scrn.pDD->EnumDisplayModes(DDEDM_REFRESHRATES, &ddsd_search,
hr = _wcontext.pDD->EnumDisplayModes(DDEDM_REFRESHRATES, &ddsd_search,
&DMI, EnumDisplayModesCallBack);
if (FAILED(hr)) {
wdxdisplay7_cat.fatal()
@ -319,7 +341,7 @@ do_fullscreen_resize(int x_size, int y_size) {
return false;
}
DMI.supportedBitDepths &= _dxgsg->scrn.D3DDevDesc.dwDeviceRenderBitDepth;
DMI.supportedBitDepths &= _wcontext.D3DDevDesc.dwDeviceRenderBitDepth;
DWORD dwFullScreenBitDepth;
DWORD requested_bpp = ddsd_curmode.ddpfPixelFormat.dwRGBBitCount;
@ -341,7 +363,7 @@ do_fullscreen_resize(int x_size, int y_size) {
return false;
}
hr = _dxgsg->scrn.pDD->TestCooperativeLevel();
hr = _wcontext.pDD->TestCooperativeLevel();
if (FAILED(hr)) {
wdxdisplay7_cat.error()
<< "TestCooperativeLevel failed : result = "
@ -354,7 +376,7 @@ do_fullscreen_resize(int x_size, int y_size) {
_dxgsg->free_dxgsg_objects();
// let driver choose default refresh rate (hopefully its >=60Hz)
hr = _dxgsg->scrn.pDD->SetDisplayMode(x_size, y_size, dwFullScreenBitDepth,
hr = _wcontext.pDD->SetDisplayMode(x_size, y_size, dwFullScreenBitDepth,
0L, 0L);
if (FAILED(hr)) {
wdxdisplay7_cat.error()
@ -366,17 +388,17 @@ do_fullscreen_resize(int x_size, int y_size) {
if (wdxdisplay7_cat.is_debug()) {
DX_DECLARE_CLEAN(DDSURFACEDESC2,ddsd34);
_dxgsg->scrn.pDD->GetDisplayMode(&ddsd34);
_wcontext.pDD->GetDisplayMode(&ddsd34);
wdxdisplay7_cat.debug()
<< "set displaymode to " << ddsd34.dwWidth << "x" << ddsd34.dwHeight
<< " at "<< ddsd34.ddpfPixelFormat.dwRGBBitCount << "bpp, "
<< ddsd34.dwRefreshRate << "Hz\n";
}
_dxgsg->scrn.dwRenderWidth = x_size;
_dxgsg->scrn.dwRenderHeight = y_size;
_wcontext.dwRenderWidth = x_size;
_wcontext.dwRenderHeight = y_size;
create_screen_buffers_and_device(_dxgsg->scrn, dx_force_16bpp_zbuffer);
create_screen_buffers_and_device(_wcontext, dx_force_16bpp_zbuffer);
_dxgsg->RecreateAllVideoSurfaces();
_dxgsg->SetDXReady(true);
return true;
@ -400,8 +422,8 @@ set_to_temp_rendertarget() {
DX_DECLARE_CLEAN(DDSURFACEDESC2, ddsd);
_dxgsg->scrn.pddsBack->GetSurfaceDesc(&ddsd);
LPDIRECTDRAW7 pDD = _dxgsg->scrn.pDD;
_wcontext.pddsBack->GetSurfaceDesc(&ddsd);
LPDIRECTDRAW7 pDD = _wcontext.pDD;
ddsd.dwFlags &= ~DDSD_PITCH;
ddsd.dwWidth = 1;
@ -418,9 +440,9 @@ set_to_temp_rendertarget() {
return false;
}
if (_dxgsg->scrn.pddsZBuf != NULL) {
if (_wcontext.pddsZBuf != NULL) {
DX_DECLARE_CLEAN(DDSURFACEDESC2, ddsdZ);
_dxgsg->scrn.pddsZBuf->GetSurfaceDesc(&ddsdZ);
_wcontext.pddsZBuf->GetSurfaceDesc(&ddsdZ);
ddsdZ.dwFlags &= ~DDSD_PITCH;
ddsdZ.dwWidth = 1;
ddsdZ.dwHeight = 1;
@ -444,7 +466,7 @@ set_to_temp_rendertarget() {
}
}
hr = _dxgsg->scrn.pD3DDevice->SetRenderTarget(pddsDummy, 0x0);
hr = _wcontext.pD3DDevice->SetRenderTarget(pddsDummy, 0x0);
if (FAILED(hr)) {
wdxdisplay7_cat.error()
<< "Resize failed to set render target to temporary surface, result = "
@ -499,6 +521,7 @@ create_screen_buffers_and_device(DXScreenData &Display, bool force_16bpp_zbuffer
DDSCAPS_PRIMARYSURFACE | DDSCAPS_3DDEVICE |
DDSCAPS_FLIP | DDSCAPS_COMPLEX;
ddsd.dwBackBufferCount = 1;
Display.bIsFullScreen=true;
if (dx_full_screen_antialiasing) {
// cant check that d3ddevice has this capability yet, so got to
@ -704,10 +727,10 @@ create_screen_buffers_and_device(DXScreenData &Display, bool force_16bpp_zbuffer
// resized(dwRenderWidth, dwRenderHeight); // update panda channel/display rgn info
int framebuffer_mode = get_properties().get_framebuffer_mode();
int frame_buffer_mode = _gsg->get_properties().get_frame_buffer_mode();
#ifndef NDEBUG
if ((framebuffer_mode & WindowProperties::FM_depth) == 0) {
if ((frame_buffer_mode & FrameBufferProperties::FM_depth) == 0) {
wdxdisplay7_cat.info()
<< "no zbuffer requested, skipping zbuffer creation\n";
}
@ -716,7 +739,7 @@ create_screen_buffers_and_device(DXScreenData &Display, bool force_16bpp_zbuffer
// Check if the device supports z-bufferless hidden surface
// removal. If so, we don't really need a z-buffer
if ((!(pD3DDevDesc->dpcTriCaps.dwRasterCaps & D3DPRASTERCAPS_ZBUFFERLESSHSR )) &&
((framebuffer_mode & WindowProperties::FM_depth) != 0)) {
((frame_buffer_mode & FrameBufferProperties::FM_depth) != 0)) {
// Get z-buffer dimensions from the render target
DX_DECLARE_CLEAN(DDSURFACEDESC2,ddsd);
@ -724,7 +747,7 @@ create_screen_buffers_and_device(DXScreenData &Display, bool force_16bpp_zbuffer
// Setup the surface desc for the z-buffer.
ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_PIXELFORMAT;
ddsd.ddsCaps.dwCaps = DDSCAPS_ZBUFFER | ((_dxgsg->scrn.bIsSWRast) ? DDSCAPS_SYSTEMMEMORY : DDSCAPS_VIDEOMEMORY);
ddsd.ddsCaps.dwCaps = DDSCAPS_ZBUFFER | ((_wcontext.bIsSWRast) ? DDSCAPS_SYSTEMMEMORY : DDSCAPS_VIDEOMEMORY);
DDPIXELFORMAT ZBufPixFmts[MAX_DX_ZBUF_FMTS];
cNumZBufFmts=0;
@ -756,7 +779,7 @@ create_screen_buffers_and_device(DXScreenData &Display, bool force_16bpp_zbuffer
// should we pay attn to these at some point?
//int want_depth_bits = _props._want_depth_bits;
//int want_color_bits = _props._want_color_bits;
bool bWantStencil = ((framebuffer_mode & WindowProperties::FM_stencil) != 0);
bool bWantStencil = ((frame_buffer_mode & FrameBufferProperties::FM_stencil) != 0);
LPDDPIXELFORMAT pCurPixFmt, pz16 = NULL, pz24 = NULL, pz32 = NULL;
for (i = 0, pCurPixFmt = ZBufPixFmts;
@ -790,7 +813,7 @@ create_screen_buffers_and_device(DXScreenData &Display, bool force_16bpp_zbuffer
#define SET_ZBUF_DEPTH(DEPTH) { assert(pz##DEPTH != NULL); Display.depth_buffer_bitdepth=DEPTH; ddsd.ddpfPixelFormat = *pz##DEPTH;}
if (_dxgsg->scrn.bIsSWRast) {
if (_wcontext.bIsSWRast) {
SET_ZBUF_DEPTH(16); // need this for fast path rasterizers
} else {
if (IS_NVIDIA(Display.DXDeviceID)) {
@ -945,6 +968,7 @@ create_screen_buffers_and_device(DXScreenData &Display, bool force_16bpp_zbuffer
Display.pddsZBuf = pZDDSurf;
Display.view_rect = view_rect;
_dxgsg->set_context(&Display);
//pDD, pPrimaryDDSurf, pBackDDSurf, pZDDSurf, pD3DI, pD3DDevice, view_rect);
_dxgsg->dx_init();
@ -956,13 +980,13 @@ create_screen_buffers_and_device(DXScreenData &Display, bool force_16bpp_zbuffer
}
////////////////////////////////////////////////////////////////////
// Function: wdxGraphicsWindow7::search_for_device
// Function: wdxGraphicsWindow7::choose_device
// Access: Private
// Description: Searches for a suitable hardware device for
// rendering.
////////////////////////////////////////////////////////////////////
bool wdxGraphicsWindow7::
search_for_device(int devnum, DXDeviceInfo *pDevinfo) {
choose_device(int devnum, DXDeviceInfo *pDevinfo) {
wdxGraphicsPipe7 *dxpipe;
DCAST_INTO_R(dxpipe, _pipe, false);
@ -992,16 +1016,16 @@ search_for_device(int devnum, DXDeviceInfo *pDevinfo) {
return false;
}
_dxgsg->scrn.pDD = pDD;
_wcontext.pDD = pDD;
// GetDeviceID bug writes an extra 4 bytes, so need xtra space
BYTE id_arr[sizeof(DDDEVICEIDENTIFIER2) + 4];
pDD->GetDeviceIdentifier((DDDEVICEIDENTIFIER2 *)&id_arr, 0x0);
memcpy(&_dxgsg->scrn.DXDeviceID, id_arr, sizeof(DDDEVICEIDENTIFIER2));
memcpy(&_wcontext.DXDeviceID, id_arr, sizeof(DDDEVICEIDENTIFIER2));
if (wdxdisplay7_cat.is_info()) {
DDDEVICEIDENTIFIER2 *pDevID = &_dxgsg->scrn.DXDeviceID;
DDDEVICEIDENTIFIER2 *pDevID = &_wcontext.DXDeviceID;
wdxdisplay7_cat.info()
<< "GfxCard: " << pDevID->szDescription << "; DriverFile: '"
<< pDevID->szDriver
@ -1015,7 +1039,7 @@ search_for_device(int devnum, DXDeviceInfo *pDevinfo) {
}
// Query DirectDraw for access to Direct3D
hr = pDD->QueryInterface(IID_IDirect3D7, (VOID**)&_dxgsg->scrn.pD3D);
hr = pDD->QueryInterface(IID_IDirect3D7, (VOID**)&_wcontext.pD3D);
if(hr != DD_OK) {
wdxdisplay7_cat.fatal()
<< "QI for D3D failed : result = " << ConvD3DErrorToString(hr) << endl;
@ -1029,7 +1053,7 @@ search_for_device(int devnum, DXDeviceInfo *pDevinfo) {
ZeroMemory(d3ddevs,3*sizeof(D3DDEVICEDESC7));
hr = _dxgsg->scrn.pD3D->EnumDevices(EnumDevicesCallback, d3ddevs);
hr = _wcontext.pD3D->EnumDevices(EnumDevicesCallback, d3ddevs);
if(hr != DD_OK) {
wdxdisplay7_cat.fatal()
<< "EnumDevices failed : result = " << ConvD3DErrorToString(hr) << endl;
@ -1048,7 +1072,7 @@ search_for_device(int devnum, DXDeviceInfo *pDevinfo) {
} else {
wdxdisplay7_cat.error()
<< "No 3D HW present on device #" << devnum << ", skipping it... ("
<< _dxgsg->scrn.DXDeviceID.szDescription<<")\n";
<< _wcontext.DXDeviceID.szDescription<<")\n";
goto error_exit;
}
@ -1056,10 +1080,10 @@ search_for_device(int devnum, DXDeviceInfo *pDevinfo) {
DeviceIdx = SWRASTIDX;
}
memcpy(&_dxgsg->scrn.D3DDevDesc, &d3ddevs[DeviceIdx],
memcpy(&_wcontext.D3DDevDesc, &d3ddevs[DeviceIdx],
sizeof(D3DDEVICEDESC7));
_dxgsg->scrn.bIsTNLDevice = (DeviceIdx == TNLHALIDX);
_wcontext.bIsTNLDevice = (DeviceIdx == TNLHALIDX);
// Get Current VidMem avail. Note this is only an estimate, when we
// switch to fullscreen mode from desktop, more vidmem will be
@ -1084,25 +1108,25 @@ search_for_device(int devnum, DXDeviceInfo *pDevinfo) {
// 1.2 meg (contradicting above comment and what I think would be
// correct behavior (shouldnt FS mode release the desktop vidmem?),
// so this is the true value
_dxgsg->scrn.MaxAvailVidMem = dwVidMemTotal;
_wcontext.MaxAvailVidMem = dwVidMemTotal;
#define LOWVIDMEMTHRESHOLD 5500000
#define CRAPPY_DRIVER_IS_LYING_VIDMEMTHRESHOLD 1000000 // every vidcard we deal with should have at least 1MB
// assume buggy drivers (this means you, FireGL2) may return zero for dwVidMemTotal, so ignore value if its < CRAPPY_DRIVER_IS_LYING_VIDMEMTHRESHOLD
_dxgsg->scrn.bIsLowVidMemCard =
_wcontext.bIsLowVidMemCard =
((dwVidMemTotal>CRAPPY_DRIVER_IS_LYING_VIDMEMTHRESHOLD) &&
(dwVidMemTotal< LOWVIDMEMTHRESHOLD));
if (!dx_do_vidmemsize_check) {
_dxgsg->scrn.MaxAvailVidMem = 0xFFFFFFFF;
_dxgsg->scrn.bIsLowVidMemCard = false;
_wcontext.MaxAvailVidMem = 0xFFFFFFFF;
_wcontext.bIsLowVidMemCard = false;
}
if (DeviceIdx == SWRASTIDX) {
// this will force 640x480x16, is this what we want for all sw rast?
_dxgsg->scrn.bIsLowVidMemCard = true;
_dxgsg->scrn.bIsSWRast = true;
_wcontext.bIsLowVidMemCard = true;
_wcontext.bIsSWRast = true;
dx_force_16bpp_zbuffer = true;
}
@ -1125,7 +1149,7 @@ search_for_device(int devnum, DXDeviceInfo *pDevinfo) {
if (FAILED(hr)) {
wdxdisplay7_cat.fatal()
<< "EnumDisplayModes failed for device #" << devnum
<< " (" << _dxgsg->scrn.DXDeviceID.szDescription
<< " (" << _wcontext.DXDeviceID.szDescription
<< "), result = " << ConvD3DErrorToString(hr) << endl;
// goto skip_device;
exit(1); // probably want to exit, since it may be my fault
@ -1142,7 +1166,7 @@ search_for_device(int devnum, DXDeviceInfo *pDevinfo) {
// resolution and best rendertarget bpp and still have at least 2
// meg of texture vidmem
DMI.supportedBitDepths &= _dxgsg->scrn.D3DDevDesc.dwDeviceRenderBitDepth;
DMI.supportedBitDepths &= _wcontext.D3DDevDesc.dwDeviceRenderBitDepth;
DWORD dwFullScreenBitDepth;
@ -1158,12 +1182,12 @@ search_for_device(int devnum, DXDeviceInfo *pDevinfo) {
wdxdisplay7_cat.fatal()
<< "No Supported FullScreen resolutions at " << dwRenderWidth
<< "x" << dwRenderHeight << " for device #" << devnum
<< " (" << _dxgsg->scrn.DXDeviceID.szDescription
<< " (" << _wcontext.DXDeviceID.szDescription
<< "), skipping device...\n";
goto error_exit;
}
if (_dxgsg->scrn.bIsLowVidMemCard) {
if (_wcontext.bIsLowVidMemCard) {
{
// hack: figuring out exactly what res to use is tricky,
// instead I will just use 640x480 if we have < 3 meg avail
@ -1181,28 +1205,28 @@ search_for_device(int devnum, DXDeviceInfo *pDevinfo) {
}
}
_dxgsg->scrn.dwFullScreenBitDepth = dwFullScreenBitDepth;
_wcontext.dwFullScreenBitDepth = dwFullScreenBitDepth;
}
_dxgsg->scrn.dwRenderWidth = dwRenderWidth;
_dxgsg->scrn.dwRenderHeight = dwRenderHeight;
_wcontext.dwRenderWidth = dwRenderWidth;
_wcontext.dwRenderHeight = dwRenderHeight;
if (pDevinfo) {
_dxgsg->scrn.hMon = pDevinfo->hMon;
_wcontext.hMon = pDevinfo->hMon;
}
_dxgsg->scrn.CardIDNum = devnum; // add ID tag for dbgprint purposes
_wcontext.CardIDNum = devnum; // add ID tag for dbgprint purposes
return true;
// handle errors within this for device loop
error_exit:
if (_dxgsg->scrn.pD3D != NULL)
_dxgsg->scrn.pD3D->Release();
if (_dxgsg->scrn.pDD != NULL)
_dxgsg->scrn.pDD->Release();
if (_wcontext.pD3D != NULL)
_wcontext.pD3D->Release();
if (_wcontext.pDD != NULL)
_wcontext.pDD->Release();
_dxgsg->scrn.pDD = NULL;
_dxgsg->scrn.pD3D = NULL;
_wcontext.pDD = NULL;
_wcontext.pD3D = NULL;
return false;
}
@ -1220,16 +1244,15 @@ set_coop_levels_and_display_modes() {
// tell d3d to preserve the fpu state across calls. this hurts
// perf, but is good for dbgging
SCL_FPUFlag = DDSCL_FPUPRESERVE;
} else {
SCL_FPUFlag = DDSCL_FPUSETUP;
}
DXScreenData *pScrn = &_dxgsg->scrn;
// DXScreenData *pScrn = &_dxgsg->scrn;
if (!is_fullscreen()) {
hr = pScrn->pDD->SetCooperativeLevel(_mwindow,
SCL_FPUFlag | DDSCL_NORMAL);
hr = _wcontext.pDD->SetCooperativeLevel(_hWnd,
SCL_FPUFlag | DDSCL_NORMAL);
if (FAILED(hr)) {
wdxdisplay7_cat.fatal()
<< "SetCooperativeLevel failed : result = "
@ -1246,7 +1269,7 @@ set_coop_levels_and_display_modes() {
// restore that functionality.
DWORD devnum = 0;
{
DXScreenData *pScrn = &_dxgsg->scrn;
// DXScreenData *pScrn = &_dxgsg->scrn;
// need to set focus/device windows for multimon
// focus window is primary monitor that will receive keybd input
@ -1264,7 +1287,7 @@ set_coop_levels_and_display_modes() {
// SetCoopLevel twice. so we do it, it really shouldnt be necessary
// if drivers werent buggy
for (int jj=0; jj<2; jj++) {
hr = pScrn->pDD->SetCooperativeLevel(pScrn->hWnd, SCL_FLAGS);
hr = _wcontext.pDD->SetCooperativeLevel(_wcontext.hWnd, SCL_FLAGS);
if (FAILED(hr)) {
wdxdisplay7_cat.fatal()
<< "SetCooperativeLevel failed for device #" << devnum
@ -1273,7 +1296,7 @@ set_coop_levels_and_display_modes() {
}
}
hr = pScrn->pDD->TestCooperativeLevel();
hr = _wcontext.pDD->TestCooperativeLevel();
if (FAILED(hr)) {
wdxdisplay7_cat.fatal()
<< "TestCooperativeLevel failed: result = " << ConvD3DErrorToString(hr)
@ -1282,31 +1305,59 @@ set_coop_levels_and_display_modes() {
<< "Full screen app failed to get exclusive mode on init, exiting..\n";
exit(1);
}
// note: its important we call SetDisplayMode on all cards before
// creating surfaces on any of them to let driver choose default
// refresh rate (hopefully its >=60Hz)
hr = pScrn->pDD->SetDisplayMode(pScrn->dwRenderWidth,
pScrn->dwRenderHeight,
pScrn->dwFullScreenBitDepth, 0, 0);
hr = _wcontext.pDD->SetDisplayMode(_wcontext.dwRenderWidth,
_wcontext.dwRenderHeight,
_wcontext.dwFullScreenBitDepth, 0, 0);
if (FAILED(hr)) {
wdxdisplay7_cat.fatal()
<< "SetDisplayMode failed to set (" << pScrn->dwRenderWidth
<< "x" <<pScrn->dwRenderHeight << "x" << pScrn->dwFullScreenBitDepth
<< ") on device #" << pScrn->CardIDNum << ": result = "
<< "SetDisplayMode failed to set (" << _wcontext.dwRenderWidth
<< "x" <<_wcontext.dwRenderHeight << "x" << _wcontext.dwFullScreenBitDepth
<< ") on device #" << _wcontext.CardIDNum << ": result = "
<< ConvD3DErrorToString(hr) << endl;
exit(1);
}
if(wdxdisplay7_cat.is_debug()) {
DX_DECLARE_CLEAN(DDSURFACEDESC2,ddsd34);
pScrn->pDD->GetDisplayMode(&ddsd34);
DX_DECLARE_CLEAN(DDSURFACEDESC2,ddsd_temp);
_wcontext.pDD->GetDisplayMode(&ddsd_temp);
wdxdisplay7_cat.debug()
<< "set displaymode to " << ddsd34.dwWidth << "x" << ddsd34.dwHeight
<< " at " << ddsd34.ddpfPixelFormat.dwRGBBitCount << "bpp, "
<< ddsd34.dwRefreshRate<< "Hz\n";
<< "set displaymode to " << ddsd_temp.dwWidth << "x" << ddsd_temp.dwHeight
<< " at " << ddsd_temp.ddpfPixelFormat.dwRGBBitCount << "bpp, "
<< ddsd_temp.dwRefreshRate<< "Hz\n";
}
}
}
#if 0
// probably need this here similar to dx8
////////////////////////////////////////////////////////////////////
// Function: wdxGraphicsWindow8::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 wdxGraphicsWindow7::
begin_frame() {
if (_awaiting_restore) {
// The fullscreen window was recently restored; we can't continue
// until the GSG says we can.
if (!_dxgsg->CheckCooperativeLevel()) {
// Keep waiting.
return false;
}
_awaiting_restore = false;
init_resized_window();
}
return WinGraphicsWindow::begin_frame();
}
#endif

View File

@ -42,13 +42,12 @@ typedef HRESULT (WINAPI * LPDIRECTDRAWCREATEEX)(GUID FAR * lpGuid, LPVOID *lplp
////////////////////////////////////////////////////////////////////
class EXPCL_PANDADX wdxGraphicsWindow7 : public WinGraphicsWindow {
public:
wdxGraphicsWindow7(GraphicsPipe *pipe);
wdxGraphicsWindow7(GraphicsPipe *pipe, GraphicsStateGuardian *gsg);
virtual ~wdxGraphicsWindow7();
virtual void make_gsg();
virtual void release_gsg();
virtual void end_flip();
//virtual bool begin_frame();
virtual void make_current(void);
virtual bool open_window(void);
protected:
virtual void fullscreen_restored(WindowProperties &properties);
@ -59,10 +58,11 @@ private:
bool set_to_temp_rendertarget();
void create_screen_buffers_and_device(DXScreenData &Display,
bool force_16bpp_zbuffer);
bool search_for_device(int devnum, DXDeviceInfo *pDevinfo);
bool choose_device(int devnum, DXDeviceInfo *pDevinfo);
void set_coop_levels_and_display_modes();
DXGraphicsStateGuardian7 *_dxgsg;
DXScreenData _wcontext;
public:
static TypeHandle get_class_type() {

View File

@ -27,7 +27,8 @@
#include <dconfig.h>
Configure(config_dxgsg8);
NotifyCategoryDef(dxgsg8, ":display:gsg");
//NotifyCategoryDef(dxgsg8, ":display:gsg"); dont want to merge this with the regular parent class dbg output
NotifyCategoryDef(dxgsg8, "dxgsg");
NotifyCategoryDef(wdxdisplay8, "windisplay");
// Configure this variable true to cause the DXGSG to show each
@ -196,58 +197,5 @@ init_libdxgsg8() {
GraphicsPipeSelection *selection = GraphicsPipeSelection::get_global_ptr();
selection->add_pipe_type(wdxGraphicsPipe8::get_class_type(),
wdxGraphicsPipe8::pipe_constructor);
}
const char *D3DFormatStr(D3DFORMAT fmt) {
#define CASESTR(XX) case XX: return #XX;
switch(fmt) {
CASESTR(D3DFMT_UNKNOWN);
CASESTR(D3DFMT_R8G8B8);
CASESTR(D3DFMT_A8R8G8B8);
CASESTR(D3DFMT_X8R8G8B8);
CASESTR(D3DFMT_R5G6B5);
CASESTR(D3DFMT_X1R5G5B5);
CASESTR(D3DFMT_A1R5G5B5);
CASESTR(D3DFMT_A4R4G4B4);
CASESTR(D3DFMT_R3G3B2);
CASESTR(D3DFMT_A8);
CASESTR(D3DFMT_A8R3G3B2);
CASESTR(D3DFMT_X4R4G4B4);
CASESTR(D3DFMT_A2B10G10R10);
CASESTR(D3DFMT_G16R16);
CASESTR(D3DFMT_A8P8);
CASESTR(D3DFMT_P8);
CASESTR(D3DFMT_L8);
CASESTR(D3DFMT_A8L8);
CASESTR(D3DFMT_A4L4);
CASESTR(D3DFMT_V8U8);
CASESTR(D3DFMT_L6V5U5);
CASESTR(D3DFMT_X8L8V8U8);
CASESTR(D3DFMT_Q8W8V8U8);
CASESTR(D3DFMT_V16U16);
CASESTR(D3DFMT_W11V11U10);
CASESTR(D3DFMT_A2W10V10U10);
CASESTR(D3DFMT_UYVY);
CASESTR(D3DFMT_YUY2);
CASESTR(D3DFMT_DXT1);
CASESTR(D3DFMT_DXT2);
CASESTR(D3DFMT_DXT3);
CASESTR(D3DFMT_DXT4);
CASESTR(D3DFMT_DXT5);
CASESTR(D3DFMT_D16_LOCKABLE);
CASESTR(D3DFMT_D32);
CASESTR(D3DFMT_D15S1);
CASESTR(D3DFMT_D24S8);
CASESTR(D3DFMT_D16);
CASESTR(D3DFMT_D24X8);
CASESTR(D3DFMT_D24X4S4);
CASESTR(D3DFMT_VERTEXDATA);
CASESTR(D3DFMT_INDEX16);
CASESTR(D3DFMT_INDEX32);
}
return "Invalid D3DFORMAT";
}

View File

@ -21,7 +21,7 @@
#include "pandabase.h"
#include "notifyCategoryProxy.h"
#include <d3d8.h>
#include "dxgsg8base.h"
NotifyCategoryDecl(dxgsg8, EXPCL_PANDADX, EXPTP_PANDADX);
NotifyCategoryDecl(wdxdisplay8, EXPCL_PANDADX, EXPTP_PANDADX);
@ -39,9 +39,9 @@ extern bool dx_use_rangebased_fog;
extern const bool link_tristrips;
extern DWORD dx_multisample_antialiasing_level;
extern bool dx_use_triangle_mipgen_filter;
extern const char *D3DFormatStr(D3DFORMAT fmt);
extern bool dx_use_dx_cursor;
// debug flags we might want to use in full optimized build
extern bool dx_ignore_mipmaps;
extern bool dx_mipmap_everything;

View File

@ -30,12 +30,12 @@ enable_line_smooth(bool val) {
_line_smooth_enabled = val;
#ifdef NDEBUG
{
if(val && (scrn.d3dcaps.RasterCaps & D3DPRASTERCAPS_ANTIALIASEDGES))
if(val && (_pScrn->d3dcaps.RasterCaps & D3DPRASTERCAPS_ANTIALIASEDGES))
dxgsg8_cat.error() << "no HW support for line smoothing!!\n";
}
#endif
scrn.pD3DDevice->SetRenderState(D3DRS_EDGEANTIALIAS, (DWORD)val);
_pD3DDevice->SetRenderState(D3DRS_EDGEANTIALIAS, (DWORD)val);
}
}
@ -50,14 +50,14 @@ enable_dither(bool val) {
#ifdef _DEBUG
{
if(val && !(scrn.d3dcaps.RasterCaps & D3DPRASTERCAPS_DITHER))
if(val && !(_pScrn->d3dcaps.RasterCaps & D3DPRASTERCAPS_DITHER))
dxgsg8_cat.error() << "no HW support for color dithering!!\n";
return;
}
#endif
_dither_enabled = val;
scrn.pD3DDevice->SetRenderState(D3DRS_DITHERENABLE, (DWORD)val);
_pD3DDevice->SetRenderState(D3DRS_DITHERENABLE, (DWORD)val);
}
}
@ -70,7 +70,7 @@ INLINE void DXGraphicsStateGuardian8::
enable_stencil_test(bool val) {
if (_stencil_test_enabled != val) {
_stencil_test_enabled = val;
scrn.pD3DDevice->SetRenderState(D3DRS_STENCILENABLE, (DWORD)val);
_pD3DDevice->SetRenderState(D3DRS_STENCILENABLE, (DWORD)val);
}
}
@ -96,7 +96,7 @@ INLINE void DXGraphicsStateGuardian8::
enable_blend(bool val) {
if (_blend_enabled != val) {
_blend_enabled = val;
scrn.pD3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, (DWORD)val);
_pD3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, (DWORD)val);
}
}
@ -109,9 +109,9 @@ INLINE void DXGraphicsStateGuardian8::
set_color_writemask(UINT color_writemask) {
if (_color_writemask != color_writemask) {
_color_writemask = color_writemask;
if(scrn.bCanDirectDisableColorWrites) {
if(_pScrn->bCanDirectDisableColorWrites) {
// only newer HW supports this rstate
scrn.pD3DDevice->SetRenderState(D3DRS_COLORWRITEENABLE, (DWORD)color_writemask);
_pD3DDevice->SetRenderState(D3DRS_COLORWRITEENABLE, (DWORD)color_writemask);
} else {
// blending can only handle on/off
assert((color_writemask==0x0)||(color_writemask==0xFFFFFFFF));
@ -129,7 +129,7 @@ INLINE void DXGraphicsStateGuardian8::
enable_gouraud_shading(bool val) {
if (_bGouraudShadingOn != val) {
_bGouraudShadingOn = val;
scrn.pD3DDevice->SetRenderState(D3DRS_SHADEMODE, (val ? D3DSHADE_GOURAUD : D3DSHADE_FLAT));
_pD3DDevice->SetRenderState(D3DRS_SHADEMODE, (val ? D3DSHADE_GOURAUD : D3DSHADE_FLAT));
}
}
@ -137,7 +137,7 @@ INLINE void DXGraphicsStateGuardian8::
enable_primitive_clipping(bool val) {
if (_clipping_enabled != val) {
_clipping_enabled = val;
scrn.pD3DDevice->SetRenderState(D3DRS_CLIPPING, (DWORD)val);
_pD3DDevice->SetRenderState(D3DRS_CLIPPING, (DWORD)val);
}
}
@ -150,7 +150,7 @@ INLINE void DXGraphicsStateGuardian8::
enable_fog(bool val) {
if ((_fog_enabled != val) && (_doFogType!=None)) {
_fog_enabled = val;
scrn.pD3DDevice->SetRenderState(D3DRS_FOGENABLE, (DWORD)val);
_pD3DDevice->SetRenderState(D3DRS_FOGENABLE, (DWORD)val);
}
}
@ -164,7 +164,7 @@ set_vertex_format(DWORD NewFvfType) {
#ifdef USE_VERTEX_SHADERS
if(_CurVertexShader!=NULL) {
// this needs optimization
HRESULT hr = scrn.pD3DDevice->SetVertexShader(_CurVertexShader);
HRESULT hr = _pD3DDevice->SetVertexShader(_CurVertexShader);
#ifndef NDEBUG
if(FAILED(hr)) {
dxgsg8_cat.error() << "SetVertexShader for custom vtx shader failed" << D3DERRORSTRING(hr);
@ -179,7 +179,7 @@ set_vertex_format(DWORD NewFvfType) {
if (_CurFVFType != NewFvfType) {
_CurFVFType = NewFvfType;
HRESULT hr = scrn.pD3DDevice->SetVertexShader(NewFvfType);
HRESULT hr = _pD3DDevice->SetVertexShader(NewFvfType);
#ifndef NDEBUG
if(FAILED(hr)) {
dxgsg8_cat.error() << "SetVertexShader(0x" << (void*)NewFvfType<<") failed" << D3DERRORSTRING(hr);
@ -199,7 +199,7 @@ enable_alpha_test(bool val )
{
if (_alpha_test_enabled != val) {
_alpha_test_enabled = val;
scrn.pD3DDevice->SetRenderState(D3DRS_ALPHATESTENABLE, (DWORD)val);
_pD3DDevice->SetRenderState(D3DRS_ALPHATESTENABLE, (DWORD)val);
}
}
@ -216,7 +216,7 @@ call_dxLightModelAmbient( const Colorf& color)
#ifdef GSG_VERBOSE
dxgsg8_cat.debug() << "dxLightModel(LIGHT_MODEL_AMBIENT, " << color << ")" << endl;
#endif
scrn.pD3DDevice->SetRenderState( D3DRS_AMBIENT,
_pD3DDevice->SetRenderState( D3DRS_AMBIENT,
D3DCOLOR_COLORVALUE(color[0], color[1], color[2], color[3]));
}
}
@ -265,12 +265,12 @@ call_dxAlphaFunc(D3DCMPFUNC func, float reference_alpha) {
}
dxgsg8_cat.debug() << " , " << reference_alpha << ")" << endl;
#endif
scrn.pD3DDevice->SetRenderState(D3DRS_ALPHAFUNC, func);
_pD3DDevice->SetRenderState(D3DRS_ALPHAFUNC, func);
}
if(_alpha_func_refval != reference_alpha) {
_alpha_func_refval = reference_alpha;
scrn.pD3DDevice->SetRenderState(D3DRS_ALPHAREF, (UINT) (reference_alpha*255.0f)); //d3d uses 0x0-0xFF, not a float
_pD3DDevice->SetRenderState(D3DRS_ALPHAREF, (UINT) (reference_alpha*255.0f)); //d3d uses 0x0-0xFF, not a float
}
}
@ -281,7 +281,7 @@ call_dxBlendFunc(D3DBLEND sfunc, D3DBLEND dfunc )
if (_blend_source_func != sfunc)
{
_blend_source_func = sfunc;
scrn.pD3DDevice->SetRenderState(D3DRS_SRCBLEND, sfunc);
_pD3DDevice->SetRenderState(D3DRS_SRCBLEND, sfunc);
#ifdef GSG_VERBOSE
dxgsg8_cat.debug() << "dxSrcBlendFunc(";
switch (sfunc)
@ -323,7 +323,7 @@ call_dxBlendFunc(D3DBLEND sfunc, D3DBLEND dfunc )
if ( _blend_dest_func != dfunc)
{
_blend_dest_func = dfunc;
scrn.pD3DDevice->SetRenderState(D3DRS_DESTBLEND, dfunc);
_pD3DDevice->SetRenderState(D3DRS_DESTBLEND, dfunc);
#ifdef GSG_VERBOSE
dxgsg8_cat.debug() << "dxDstBlendFunc(";
switch (dfunc)
@ -365,7 +365,7 @@ INLINE void DXGraphicsStateGuardian8::
enable_zwritemask(bool val) {
if (_depth_write_enabled != val) {
_depth_write_enabled = val;
scrn.pD3DDevice->SetRenderState(D3DRS_ZWRITEENABLE, val);
_pD3DDevice->SetRenderState(D3DRS_ZWRITEENABLE, val);
}
}

File diff suppressed because it is too large Load Diff

View File

@ -70,7 +70,7 @@ class EXPCL_PANDADX DXGraphicsStateGuardian8 : public GraphicsStateGuardian {
friend class DXTextureContext8;
public:
DXGraphicsStateGuardian8(GraphicsWindow *win);
DXGraphicsStateGuardian8(const FrameBufferProperties &properties);
~DXGraphicsStateGuardian8();
virtual void reset();
@ -150,7 +150,8 @@ public:
public:
// recreate_tex_callback needs these to be public
DXScreenData scrn;
DXScreenData *_pScrn;
LPDIRECT3DDEVICE8 _pD3DDevice; // same as pScrn->_pD3DDevice, cached for spd
protected:
virtual void enable_lighting(bool enable);
@ -303,7 +304,9 @@ protected:
DWORD _clip_plane_bits;
RenderModeAttrib::Mode _current_fill_mode; //poinr/wireframe/solid
GraphicsChannel *_panda_gfx_channel; // cache the 1 channel dx supports
// unused right now
//GraphicsChannel *_panda_gfx_channel; // cache the 1 channel dx supports
// Cur Texture State
TextureApplyAttrib::Mode _CurTexBlendMode;
@ -320,9 +323,20 @@ protected:
bool _overlay_windows_supported;
#if 0
// This is here just as a temporary hack so this file will still
// compile. However, it is never initialized and will certainly
// cause the code to crash when it is referenced. (This used to be
// inherited from the base class, but the new design requires that a
// GSG may be used for multiple windows, so it doesn't make sense to
// store a single window pointer any more.)
GraphicsWindow *_win;
#endif
public:
static GraphicsStateGuardian*
make_DXGraphicsStateGuardian8(const FactoryParams &params);
void set_context(DXScreenData *pNewContextData);
static TypeHandle get_class_type(void);
static void init_type(void);
@ -347,7 +361,7 @@ public:
bool CheckCooperativeLevel(bool bDoReactivateWindow = false);
void show_frame(bool bNoNewFrameDrawn = false);
void dx_init(HCURSOR hMouseCursor);
void dx_init(void);
void support_overlay_window(bool flag);
@ -355,7 +369,8 @@ private:
static TypeHandle _type_handle;
};
#include "DXGraphicsStateGuardian8.I"
HRESULT CreateDX8Cursor(LPDIRECT3DDEVICE8 pd3dDevice, HCURSOR hCursor,BOOL bAddWatermark);
#include "DXGraphicsStateGuardian8.I"
#endif

View File

@ -1000,6 +1000,8 @@ IDirect3DTexture8 *DXTextureContext8::CreateTexture(DXScreenData &scrn) {
assert(pbuf->get_component_width()==sizeof(BYTE)); // cant handle anything else now
assert(pixbuf_type==PixelBuffer::T_unsigned_byte); // cant handle anything else now
//PRINT_REFCNT(dxgsg8,scrn.pD3D8);
if((pixbuf_type!=PixelBuffer::T_unsigned_byte) || (pbuf->get_component_width()!=1)) {
dxgsg8_cat.error() << "CreateTexture failed, havent handled non 8-bit channel pixelbuffer types yet! \n";
return NULL;
@ -1411,7 +1413,7 @@ IDirect3DTexture8 *DXTextureContext8::CreateTexture(DXScreenData &scrn) {
if(FAILED( hr = scrn.pD3DDevice->CreateTexture(TargetWidth,TargetHeight,cMipLevelCount,0x0,
TargetPixFmt,D3DPOOL_MANAGED,&_pD3DTexture8) )) {
dxgsg8_cat.error() << "pD3DDevice->CreateTexture() failed!" << D3DERRORSTRING(hr);
dxgsg8_cat.error() << "D3D CreateTexture failed!" << D3DERRORSTRING(hr);
goto error_exit;
}
@ -1427,11 +1429,21 @@ IDirect3DTexture8 *DXTextureContext8::CreateTexture(DXScreenData &scrn) {
#endif
#endif
hr = FillDDSurfTexturePixels();
if(FAILED(hr)) {
goto error_exit;
// Note: user may want to create an empty "texture" that will be written to by rendering and copy operations.
// this will never have a backing store of main memory in panda fmt, and on disk in a file.
// so for this case, you dont want to call FillDDSurf.
// need a better way for user to indicate this usage than lack of ram_image, because it conflicts
// with the multi-open case mentioned below
if(_texture->has_ram_image()) {
hr = FillDDSurfTexturePixels();
if(FAILED(hr)) {
goto error_exit;
}
}
// PRINT_REFCNT(dxgsg8,scrn.pD3D8);
// Return the newly created texture
return _pD3DTexture8;
@ -1547,18 +1559,21 @@ FillDDSurfTexturePixels(void) {
if(bUsingTempPixBuf) {
SAFE_DELETE_ARRAY(pPixels);
}
RELEASE(pMipLevel0,dxgsg8,"texture",RELEASE_ONCE);
RELEASE(pMipLevel0,dxgsg8,"FillDDSurf MipLev0 texture ptr",RELEASE_ONCE);
return hr;
}
//-----------------------------------------------------------------------------
// Name: DeleteTexture()
// Desc: Release the surface used to store the texture
//-----------------------------------------------------------------------------
void DXTextureContext8::
DeleteTexture( ) {
if(_pD3DTexture8==NULL) {
// dont bother printing the msg below, since we already released it.
return;
}
if(dxgsg8_cat.is_spam()) {
dxgsg8_cat.spam() << "Deleting DX texture for " << _tex->get_name() << "\n";
}
@ -1603,6 +1618,9 @@ TextureContext(tex) {
DXTextureContext8::
~DXTextureContext8() {
if(dxgsg8_cat.is_spam()) {
dxgsg8_cat.spam() << "Deleting DX8 TexContext for " << _tex->get_name() << "\n";
}
DeleteTexture();
TextureContext::~TextureContext();
_tex = NULL;

View File

@ -19,9 +19,6 @@
#ifndef DXGSG8BASE_H
#define DXGSG8BASE_H
#include <pandabase.h>
#include <graphicsWindow.h>
// include win32 defns for everything up to WinServer2003, and assume I'm smart enough to
// use GetProcAddress for backward compat on newer fns
// Note DX8 cannot be installed on w95, so OK to assume base of win98
@ -41,6 +38,9 @@
#include <dxerr8.h>
#undef WIN32_LEAN_AND_MEAN
#include "pandabase.h"
#include "graphicsWindow.h"
#if D3D_SDK_VERSION != 220
#error you have DX 8.0 headers, not DX 8.1, you need to install DX 8.1 SDK!
#endif
@ -61,6 +61,11 @@
#endif
#endif
// imperfect method to ID NVid? could also scan desc str, but that isnt fullproof either
#define IS_NVIDIA(DDDEVICEID) ((DDDEVICEID.VendorId==0x10DE) || (DDDEVICEID.VendorId==0x12D2))
#define IS_ATI(DDDEVICEID) (DDDEVICEID.VendorId==0x1002)
#define IS_MATROX(DDDEVICEID) (DDDEVICEID.VendorId==0x102B)
#define D3D_MAXTEXTURESTAGES 8
typedef enum {VertexShader,PixelShader} ShaderType;
@ -82,12 +87,15 @@ typedef DWORD DXShaderHandle;
// for stuff outside a panda class
#define SAFE_RELEASE(p) { if(p) { assert(IS_VALID_PTR(p)); (p)->Release(); (p)=NULL; } }
#define SAFE_FREELIB(hDLL) { if(hDLL!=NULL) { FreeLibrary(hDLL);hDLL = NULL; } }
// this is bDoDownToZero argument to RELEASE()
#define RELEASE_DOWN_TO_ZERO true
#define RELEASE_ONCE false
//#define DEBUG_RELEASES
// uncomment to add refcnt debug output
#define DEBUG_RELEASES
#ifdef DEBUG_RELEASES
#define RELEASE(OBJECT,MODULE,DBGSTR,bDoDownToZero) { \
@ -183,7 +191,7 @@ typedef enum {
typedef struct {
LPDIRECT3DDEVICE8 pD3DDevice;
LPDIRECT3D8 pD3D8;
LPDIRECT3D8 pD3D8; // copied from DXGraphicsPipe8 for convenience
HWND hWnd;
HMONITOR hMon;
DWORD MaxAvailVidMem;
@ -203,5 +211,11 @@ typedef struct {
D3DADAPTER_IDENTIFIER8 DXDeviceID;
} DXScreenData;
//utility stuff
extern map<D3DFORMAT_FLAG,D3DFORMAT> g_D3DFORMATmap;
extern void Init_D3DFORMAT_map(void);
extern const char *D3DFormatStr(D3DFORMAT fmt);
#endif

View File

@ -23,10 +23,8 @@
TypeHandle wdxGraphicsPipe8::_type_handle;
// #define LOWVIDMEMTHRESHOLD 3500000
// #define CRAPPY_DRIVER_IS_LYING_VIDMEMTHRESHOLD 1000000
#define LOWVIDMEMTHRESHOLD 5700000 // 4MB cards should fall below this
#define CRAPPY_DRIVER_IS_LYING_VIDMEMTHRESHOLD 1000000 // if # is > 1MB, card is lying and I cant tell what it is
#define UNKNOWN_VIDMEM_SIZE 0xFFFFFFFF
////////////////////////////////////////////////////////////////////
@ -38,6 +36,7 @@ wdxGraphicsPipe8::
wdxGraphicsPipe8() {
_hDDrawDLL = NULL;
_hD3D8_DLL = NULL;
_pD3D8 = NULL;
_is_valid = init();
}
@ -48,14 +47,10 @@ wdxGraphicsPipe8() {
////////////////////////////////////////////////////////////////////
wdxGraphicsPipe8::
~wdxGraphicsPipe8() {
if (_hDDrawDLL != NULL) {
FreeLibrary(_hDDrawDLL);
_hDDrawDLL = NULL;
}
if(_hD3D8_DLL != NULL) {
FreeLibrary(_hD3D8_DLL);
_hD3D8_DLL = NULL;
}
RELEASE(_pD3D8,wdxdisplay8,"ID3D8",RELEASE_DOWN_TO_ZERO);
SAFE_FREELIB(_hD3D8_DLL);
SAFE_FREELIB(_hDDrawDLL);
}
////////////////////////////////////////////////////////////////////
@ -91,12 +86,14 @@ pipe_constructor() {
// Description: Creates a new window on the pipe, if possible.
////////////////////////////////////////////////////////////////////
PT(GraphicsWindow) wdxGraphicsPipe8::
make_window() {
make_window(GraphicsStateGuardian *gsg) {
if (!_is_valid) {
return NULL;
}
return new wdxGraphicsWindow8(this);
// thanks to the dumb threading requirements this constructor actually does nothing but create an empty c++ object
// no windows are really opened until wdxGraphicsWindow8->open_window() is called
return new wdxGraphicsWindow8(this, gsg);
}
////////////////////////////////////////////////////////////////////
@ -110,50 +107,72 @@ make_window() {
////////////////////////////////////////////////////////////////////
bool wdxGraphicsPipe8::
init() {
static const char * const ddraw_name = "ddraw.dll";
_hDDrawDLL = LoadLibrary(ddraw_name);
if(_hDDrawDLL == 0) {
wdxdisplay8_cat.error()
<< "can't locate " << ddraw_name << "!\n";
return false;
if(!MyLoadLib(_hDDrawDLL,"ddraw.dll")) {
goto error;
}
_DirectDrawCreateEx =
(LPDIRECTDRAWCREATEEX)GetProcAddress(_hDDrawDLL, "DirectDrawCreateEx");
if (_DirectDrawCreateEx == NULL) {
wdxdisplay8_cat.error()
<< "GetProcAddr failed for DDCreateEx" << endl;
return false;
if(!MyGetProcAddr(_hDDrawDLL, (FARPROC*)&_DirectDrawCreateEx, "DirectDrawCreateEx")) {
goto error;
}
_DirectDrawEnumerateExA = (LPDIRECTDRAWENUMERATEEX)GetProcAddress(_hDDrawDLL, "DirectDrawEnumerateExA");
if (_DirectDrawEnumerateExA == NULL) {
wdxdisplay8_cat.error()
<< "GetProcAddr failed for DirectDrawEnumerateEx! (win95 system?)\n";
return false;
if(!MyGetProcAddr(_hDDrawDLL, (FARPROC*)&_DirectDrawEnumerateExA, "DirectDrawEnumerateExA")) {
goto error;
}
static const char * const d3d8_name = "d3d8.dll";
_hD3D8_DLL = LoadLibrary(d3d8_name);
if (_hD3D8_DLL == 0) {
wdxdisplay8_cat.error()
<< "PandaDX8 requires DX8, can't locate " << d3d8_name << "!\n";
return false;
if(!MyLoadLib(_hD3D8_DLL,"d3d8.dll")) {
goto error;
}
// dont want to statically link to possibly non-existent d3d8 dll,
// so must call D3DCr8 indirectly
static const char * const d3dcreate8_name = "Direct3DCreate8";
_Direct3DCreate8 =
(Direct3DCreate8_ProcPtr)GetProcAddress(_hD3D8_DLL, d3dcreate8_name);
if (_Direct3DCreate8 == NULL) {
wdxdisplay8_cat.error()
<< "GetProcAddress for " << d3dcreate8_name << "failed!" << endl;
return false;
if(!MyGetProcAddr(_hD3D8_DLL, (FARPROC*)&_Direct3DCreate8, "Direct3DCreate8")) {
goto error;
}
/*
wdxGraphicsPipe8 *dxpipe;
DCAST_INTO_V(dxpipe, _pipe);
nassertv(_gsg == (GraphicsStateGuardian *)NULL);
_dxgsg = new DXGraphicsStateGuardian8(this);
_gsg = _dxgsg;
// Tell the associated dxGSG about the window handle.
_dxgsg->scrn.hWnd = _hWnd;
*/
// Create a Direct3D object.
// these were taken from the 8.0 and 8.1 d3d8.h SDK headers
#define D3D_SDK_VERSION_8_0 120
#define D3D_SDK_VERSION_8_1 220
// are we using 8.0 or 8.1?
WIN32_FIND_DATA TempFindData;
HANDLE hFind;
char tmppath[_MAX_PATH + 128];
GetSystemDirectory(tmppath, MAX_PATH);
strcat(tmppath, "\\dpnhpast.dll");
hFind = FindFirstFile (tmppath, &TempFindData);
if (hFind != INVALID_HANDLE_VALUE) {
FindClose(hFind);
_bIsDX81 = true;
_pD3D8 = (*_Direct3DCreate8)(D3D_SDK_VERSION_8_1);
} else {
_bIsDX81 = false;
_pD3D8 = (*_Direct3DCreate8)(D3D_SDK_VERSION_8_0);
}
if (_pD3D8 == NULL) {
wdxdisplay8_cat.error() << "Direct3DCreate8(8." << (_bIsDX81 ? "1" : "0") << ") failed!, error=" << GetLastError() << endl;
//release_gsg();
goto error;
}
Init_D3DFORMAT_map();
return find_all_card_memavails();
error:
// wdxdisplay8_cat.error() << ", error=" << GetLastError << endl;
return false;
}
////////////////////////////////////////////////////////////////////
@ -260,9 +279,11 @@ find_all_card_memavails() {
hr = pDD->GetAvailableVidMem(&ddsGAVMCaps, &dwVidMemTotal, &dwVidMemFree);
if (FAILED(hr)) {
wdxdisplay8_cat.error()
<< "GetAvailableVidMem failed for device #"<< i<< D3DERRORSTRING(hr);
// goto skip_device;
wdxdisplay8_cat.error() << "GetAvailableVidMem failed for device #"<< i<< D3DERRORSTRING(hr);
// sometimes GetAvailableVidMem fails with hr=DDERR_NODIRECTDRAWHW for some unknown reason (bad drivers?)
// see bugs: 15327,18122, others. is it because D3D8 object has already been created?
if(hr==DDERR_NODIRECTDRAWHW)
continue;
exit(1); // probably want to exit, since it may be my fault
}
@ -306,8 +327,7 @@ find_all_card_memavails() {
// registry location for a given card
// assume buggy drivers (this means you, FireGL2) may return zero
// (or small amts) for dwVidMemTotal, so ignore value if its <
// CRAPPY_DRIVER_IS_LYING_VIDMEMTHRESHOLD
// (or small amts) for dwVidMemTotal, so ignore value if its < CRAPPY_DRIVER_IS_LYING_VIDMEMTHRESHOLD
bool bLowVidMemFlag =
((dwVidMemTotal > CRAPPY_DRIVER_IS_LYING_VIDMEMTHRESHOLD) &&
(dwVidMemTotal< LOWVIDMEMTHRESHOLD));
@ -352,3 +372,519 @@ dx7_driver_enum_callback(GUID *pGUID, TCHAR *strDesc, TCHAR *strName,
return DDENUMRET_OK;
}
//////////////////////////////////////////////////////////////////
// Function: wdxGraphicsWindow8::find_best_depth_format
// Access: Private
// Description:
////////////////////////////////////////////////////////////////////
bool wdxGraphicsPipe8::
find_best_depth_format(DXScreenData &Display, D3DDISPLAYMODE &TestDisplayMode,
D3DFORMAT *pBestFmt, bool bWantStencil,
bool bForce16bpp, bool bVerboseMode) const {
// list fmts in order of preference
#define NUM_TEST_ZFMTS 3
static D3DFORMAT NoStencilPrefList[NUM_TEST_ZFMTS]={D3DFMT_D32,D3DFMT_D24X8,D3DFMT_D16};
static D3DFORMAT StencilPrefList[NUM_TEST_ZFMTS]={D3DFMT_D24S8,D3DFMT_D24X4S4,D3DFMT_D15S1};
// do not use Display.DisplayMode since that is probably not set yet, use TestDisplayMode instead
// int want_color_bits = _props._want_color_bits;
// int want_depth_bits = _props._want_depth_bits; should we pay attn to these so panda user can select bitdepth?
*pBestFmt = D3DFMT_UNKNOWN;
HRESULT hr;
// nvidia likes zbuf depth to match rendertarget depth
bool bOnlySelect16bpp = (bForce16bpp ||
(IS_NVIDIA(Display.DXDeviceID) && IS_16BPP_DISPLAY_FORMAT(TestDisplayMode.Format)));
if (bVerboseMode) {
wdxdisplay8_cat.info()
<< "FindBestDepthFmt: bSelectOnly16bpp: " << bOnlySelect16bpp << endl;
}
for (int i=0; i < NUM_TEST_ZFMTS; i++) {
D3DFORMAT TestDepthFmt =
(bWantStencil ? StencilPrefList[i] : NoStencilPrefList[i]);
if (bOnlySelect16bpp && !IS_16BPP_ZBUFFER(TestDepthFmt)) {
continue;
}
hr = Display.pD3D8->CheckDeviceFormat(Display.CardIDNum,
D3DDEVTYPE_HAL,
TestDisplayMode.Format,
D3DUSAGE_DEPTHSTENCIL,
D3DRTYPE_SURFACE,TestDepthFmt);
if (FAILED(hr)) {
if (hr == D3DERR_NOTAVAILABLE) {
if (bVerboseMode)
wdxdisplay8_cat.info()
<< "FindBestDepthFmt: ChkDevFmt returns NotAvail for "
<< D3DFormatStr(TestDepthFmt) << endl;
continue;
}
wdxdisplay8_cat.error()
<< "unexpected CheckDeviceFormat failure" << D3DERRORSTRING(hr)
<< endl;
exit(1);
}
hr = Display.pD3D8->CheckDepthStencilMatch(Display.CardIDNum,
D3DDEVTYPE_HAL,
TestDisplayMode.Format, // adapter format
TestDisplayMode.Format, // backbuffer fmt (should be the same in my apps)
TestDepthFmt);
if (SUCCEEDED(hr)) {
*pBestFmt = TestDepthFmt;
break;
} else {
if (hr==D3DERR_NOTAVAILABLE) {
if (bVerboseMode) {
wdxdisplay8_cat.info()
<< "FindBestDepthFmt: ChkDepMatch returns NotAvail for "
<< D3DFormatStr(TestDisplayMode.Format) << ", "
<< D3DFormatStr(TestDepthFmt) << endl;
}
} else {
wdxdisplay8_cat.error()
<< "unexpected CheckDepthStencilMatch failure for "
<< D3DFormatStr(TestDisplayMode.Format) << ", "
<< D3DFormatStr(TestDepthFmt) << endl;
exit(1);
}
}
}
if (bVerboseMode) {
wdxdisplay8_cat.info()
<< "FindBestDepthFmt returns fmt " << D3DFormatStr(*pBestFmt) << endl;
}
return (*pBestFmt != D3DFMT_UNKNOWN);
}
////////////////////////////////////////////////////////////////////
// Function: wdxGraphicsWindow8::special_check_fullscreen_resolution
// Access: Private
// Description: overrides of the general estimator for known working
// cases
////////////////////////////////////////////////////////////////////
bool wdxGraphicsPipe8::
special_check_fullscreen_resolution(DXScreenData &scrn,UINT x_size,UINT y_size) {
DWORD VendorId = scrn.DXDeviceID.VendorId;
DWORD DeviceId = scrn.DXDeviceID.DeviceId;
switch (VendorId) {
case 0x8086: // Intel
/*for now, just validate all the intel cards at these resolutions.
I dont have a complete list of intel deviceIDs (missing 82830, 845, etc)
// Intel i810,i815,82810
if ((DeviceId==0x7121)||(DeviceId==0x7123)||(DeviceId==0x7125)||
(DeviceId==0x1132))
*/
if ((x_size == 640) && (y_size == 480)) {
return true;
}
if ((x_size == 800) && (y_size == 600)) {
return true;
}
if ((x_size == 1024) && (y_size == 768)) {
return true;
}
break;
}
return false;
}
////////////////////////////////////////////////////////////////////
// Function: wdxGraphicsWindow8::search_for_valid_displaymode
// Access: Private
// Description: All ptr args are output parameters. If no valid mode
// found, returns *pSuggestedPixFmt = D3DFMT_UNKNOWN;
////////////////////////////////////////////////////////////////////
void wdxGraphicsPipe8::
search_for_valid_displaymode(DXScreenData &scrn,
UINT RequestedX_Size, UINT RequestedY_Size,
bool bWantZBuffer, bool bWantStencil,
UINT *pSupportedScreenDepthsMask,
bool *pCouldntFindAnyValidZBuf,
D3DFORMAT *pSuggestedPixFmt,
bool bForce16bppZBuffer,
bool bVerboseMode) {
assert(IS_VALID_PTR(scrn.pD3D8));
HRESULT hr;
#ifndef NDEBUG
// no longer true, due to special_check_fullscreen_res, where lowvidmem cards are allowed higher resolutions
// if (_dxgsg->scrn.bIsLowVidMemCard)
// nassertv((RequestedX_Size==640)&&(RequestedY_Size==480));
#endif
*pSuggestedPixFmt = D3DFMT_UNKNOWN;
*pSupportedScreenDepthsMask = 0x0;
*pCouldntFindAnyValidZBuf = false;
int cNumModes = scrn.pD3D8->GetAdapterModeCount(scrn.CardIDNum);
D3DDISPLAYMODE BestDispMode;
ZeroMemory(&BestDispMode,sizeof(BestDispMode));
if (bVerboseMode) {
wdxdisplay8_cat.info()
<< "searching for valid display modes at res: ("
<< RequestedX_Size << "," << RequestedY_Size
<< "), TotalModes: " << cNumModes << endl;
}
// ignore memory based checks for min res 640x480. some cards just
// dont give accurate memavails. (should I do the check anyway for
// 640x480 32bpp?)
bool bDoMemBasedChecks =
((!((RequestedX_Size==640)&&(RequestedY_Size==480))) &&
(scrn.MaxAvailVidMem!=UNKNOWN_VIDMEM_SIZE) &&
(!special_check_fullscreen_resolution(scrn,RequestedX_Size,RequestedY_Size)));
if (bVerboseMode || wdxdisplay8_cat.is_spam()) {
wdxdisplay8_cat.info()
<< "DoMemBasedChecks = " << bDoMemBasedChecks << endl;
}
for (int i=0; i < cNumModes; i++) {
D3DDISPLAYMODE dispmode;
hr = scrn.pD3D8->EnumAdapterModes(scrn.CardIDNum,i,&dispmode);
if (FAILED(hr)) {
wdxdisplay8_cat.error()
<< "EnumAdapterDisplayMode failed for device #"
<< scrn.CardIDNum << D3DERRORSTRING(hr);
exit(1);
}
if ((dispmode.Width!=RequestedX_Size) ||
(dispmode.Height!=RequestedY_Size)) {
continue;
}
if ((dispmode.RefreshRate<60) && (dispmode.RefreshRate>1)) {
// dont want refresh rates under 60Hz, but 0 or 1 might indicate
// a default refresh rate, which is usually >=60
if (bVerboseMode) {
wdxdisplay8_cat.info()
<< "skipping mode[" << i << "], bad refresh rate: "
<< dispmode.RefreshRate << endl;
}
continue;
}
// Note no attempt is made to verify if format will work at
// requested size, so even if this call succeeds, could still get
// an out-of-video-mem error
hr = scrn.pD3D8->CheckDeviceFormat(scrn.CardIDNum, D3DDEVTYPE_HAL, dispmode.Format,
D3DUSAGE_RENDERTARGET, D3DRTYPE_SURFACE,
dispmode.Format);
if (FAILED(hr)) {
if (hr==D3DERR_NOTAVAILABLE) {
if (bVerboseMode) {
wdxdisplay8_cat.info()
<< "skipping mode[" << i
<< "], CheckDevFmt returns NotAvail for fmt: "
<< D3DFormatStr(dispmode.Format) << endl;
}
continue;
} else {
wdxdisplay8_cat.error()
<< "CheckDeviceFormat failed for device #"
<< scrn.CardIDNum << D3DERRORSTRING(hr);
exit(1);
}
}
bool bIs16bppRenderTgt = IS_16BPP_DISPLAY_FORMAT(dispmode.Format);
float RendTgtMinMemReqmt;
// if we have a valid memavail value, try to determine if we have
// enough space
if (bDoMemBasedChecks) {
// assume user is testing fullscreen, not windowed, so use the
// dwTotal value see if 3 scrnbufs (front/back/z)at 16bpp at
// x_size*y_size will fit with a few extra megs for texmem
// 8MB Rage Pro says it has 6.8 megs Total free and will run at
// 1024x768, so formula makes it so that is OK
#define REQD_TEXMEM 1800000
float bytes_per_pixel = (bIs16bppRenderTgt ? 2 : 4);
// cant do this check yet since gsg doesnt exist!
// assert((_gsg->get_properties().get_frame_buffer_mode() & FrameBufferProperties::FM_double_buffer) != 0);
// *2 for double buffer
RendTgtMinMemReqmt =
((float)RequestedX_Size) * ((float)RequestedY_Size) *
bytes_per_pixel * 2 + REQD_TEXMEM;
if (bVerboseMode || wdxdisplay8_cat.is_spam())
wdxdisplay8_cat.info()
<< "Testing Mode (" <<RequestedX_Size<<"x" << RequestedY_Size
<< "," << D3DFormatStr(dispmode.Format) << ")\nReqdVidMem: "
<< (int)RendTgtMinMemReqmt << " AvailVidMem: "
<< scrn.MaxAvailVidMem << endl;
if (RendTgtMinMemReqmt > scrn.MaxAvailVidMem) {
if (bVerboseMode || wdxdisplay8_cat.is_debug())
wdxdisplay8_cat.info()
<< "not enough VidMem for render tgt, skipping display fmt "
<< D3DFormatStr(dispmode.Format) << " ("
<< (int)RendTgtMinMemReqmt << " > "
<< scrn.MaxAvailVidMem << ")\n";
continue;
}
}
if (bWantZBuffer) {
D3DFORMAT zformat;
if (!find_best_depth_format(scrn,dispmode, &zformat,
bWantStencil, bForce16bppZBuffer)) {
*pCouldntFindAnyValidZBuf=true;
continue;
}
float MinMemReqmt = 0.0f;
if (bDoMemBasedChecks) {
// test memory again, this time including zbuf size
float zbytes_per_pixel = (IS_16BPP_ZBUFFER(zformat) ? 2 : 4);
float MinMemReqmt = RendTgtMinMemReqmt + ((float)RequestedX_Size)*((float)RequestedY_Size)*zbytes_per_pixel;
if (bVerboseMode || wdxdisplay8_cat.is_spam())
wdxdisplay8_cat.info()
<< "Testing Mode w/Z (" << RequestedX_Size << "x"
<< RequestedY_Size << "," << D3DFormatStr(dispmode.Format)
<< ")\nReqdVidMem: "<< (int)MinMemReqmt << " AvailVidMem: "
<< scrn.MaxAvailVidMem << endl;
if (MinMemReqmt > scrn.MaxAvailVidMem) {
if (bVerboseMode || wdxdisplay8_cat.is_debug())
wdxdisplay8_cat.info()
<< "not enough VidMem for RendTgt+zbuf, skipping display fmt "
<< D3DFormatStr(dispmode.Format) << " (" << (int)MinMemReqmt
<< " > " << scrn.MaxAvailVidMem << ")\n";
continue;
}
}
if ((!bDoMemBasedChecks) || (MinMemReqmt<scrn.MaxAvailVidMem)) {
if (!IS_16BPP_ZBUFFER(zformat)) {
// see if things fit with a 16bpp zbuffer
if (!find_best_depth_format(scrn, dispmode, &zformat,
bWantStencil, true, bVerboseMode)) {
if (bVerboseMode)
wdxdisplay8_cat.info()
<< "FindBestDepthFmt rejected Mode[" << i << "] ("
<< RequestedX_Size << "x" << RequestedY_Size
<< "," << D3DFormatStr(dispmode.Format) << endl;
*pCouldntFindAnyValidZBuf=true;
continue;
}
// right now I'm not going to use these flags, just let the
// create fail out-of-mem and retry at 16bpp
*pSupportedScreenDepthsMask |=
(IS_16BPP_DISPLAY_FORMAT(dispmode.Format) ? DISPLAY_16BPP_REQUIRES_16BPP_ZBUFFER_FLAG : DISPLAY_32BPP_REQUIRES_16BPP_ZBUFFER_FLAG);
}
}
}
if (bVerboseMode || wdxdisplay8_cat.is_spam())
wdxdisplay8_cat.info()
<< "Validated Mode (" << RequestedX_Size << "x"
<< RequestedY_Size << "," << D3DFormatStr(dispmode.Format) << endl;
switch (dispmode.Format) {
case D3DFMT_X1R5G5B5:
*pSupportedScreenDepthsMask |= X1R5G5B5_FLAG;
break;
case D3DFMT_X8R8G8B8:
*pSupportedScreenDepthsMask |= X8R8G8B8_FLAG;
break;
case D3DFMT_R8G8B8:
*pSupportedScreenDepthsMask |= R8G8B8_FLAG;
break;
case D3DFMT_R5G6B5:
*pSupportedScreenDepthsMask |= R5G6B5_FLAG;
break;
default:
// Render target formats should be only D3DFMT_X1R5G5B5,
// D3DFMT_R5G6B5, D3DFMT_X8R8G8B8 (or R8G8B8?)
wdxdisplay8_cat.error()
<< "unrecognized supported fmt "<< D3DFormatStr(dispmode.Format)
<< " returned by EnumAdapterDisplayModes!\n";
}
}
// note: this chooses 32bpp, which may not be preferred over 16 for
// memory & speed reasons on some older cards in particular
if (*pSupportedScreenDepthsMask & X8R8G8B8_FLAG) {
*pSuggestedPixFmt = D3DFMT_X8R8G8B8;
} else if (*pSupportedScreenDepthsMask & R8G8B8_FLAG) {
*pSuggestedPixFmt = D3DFMT_R8G8B8;
} else if (*pSupportedScreenDepthsMask & R5G6B5_FLAG) {
*pSuggestedPixFmt = D3DFMT_R5G6B5;
} else if (*pSupportedScreenDepthsMask & X1R5G5B5_FLAG) {
*pSuggestedPixFmt = D3DFMT_X1R5G5B5;
}
if (bVerboseMode || wdxdisplay8_cat.is_spam()) {
wdxdisplay8_cat.info()
<< "search_for_valid_device returns fmt: "
<< D3DFormatStr(*pSuggestedPixFmt) << endl;
}
}
////////////////////////////////////////////////////////////////////
// Function: wdxGraphicsPipew8::make_gsg
// Access: Public, Virtual
// Description: Creates a new empty GSG. Can do no real initialization
// until window is opened, and we know the full device requirements
////////////////////////////////////////////////////////////////////
PT(GraphicsStateGuardian) wdxGraphicsPipe8::
make_gsg(const FrameBufferProperties &properties) {
// FrameBufferProperties really belongs as part of the window/renderbuffer specification
// put here because of GLX multithreading requirement
PT(DXGraphicsStateGuardian8) gsg = new DXGraphicsStateGuardian8(properties);
return gsg.p();
/*
nassertv(_gsg == (GraphicsStateGuardian *)NULL);
_dxgsg = new DXGraphicsStateGuardian8(this);
_gsg = _dxgsg;
// Tell the associated dxGSG about the window handle.
_dxgsg->scrn.hWnd = _hWnd;
if (pD3D8 == NULL) {
wdxdisplay8_cat.error()
<< "Direct3DCreate8 failed!\n";
release_gsg();
return;
}
if (!choose_adapter(pD3D8)) {
wdxdisplay8_cat.error()
<< "Unable to find suitable rendering device.\n";
release_gsg();
return;
}
create_screen_buffers_and_device(_dxgsg->scrn, dx_force_16bpp_zbuffer);
*/
}
map<D3DFORMAT_FLAG,D3DFORMAT> g_D3DFORMATmap;
void Init_D3DFORMAT_map(void) {
if(g_D3DFORMATmap.size()!=0)
return;
#define INSERT_ELEM(XX) g_D3DFORMATmap[XX##_FLAG] = D3DFMT_##XX;
INSERT_ELEM(R8G8B8);
INSERT_ELEM(A8R8G8B8);
INSERT_ELEM(X8R8G8B8);
INSERT_ELEM(R5G6B5);
INSERT_ELEM(X1R5G5B5);
INSERT_ELEM(A1R5G5B5);
INSERT_ELEM(A4R4G4B4);
INSERT_ELEM(R3G3B2);
INSERT_ELEM(A8);
INSERT_ELEM(A8R3G3B2);
INSERT_ELEM(X4R4G4B4);
INSERT_ELEM(A2B10G10R10);
INSERT_ELEM(G16R16);
INSERT_ELEM(A8P8);
INSERT_ELEM(P8);
INSERT_ELEM(L8);
INSERT_ELEM(A8L8);
INSERT_ELEM(A4L4);
INSERT_ELEM(V8U8);
INSERT_ELEM(L6V5U5);
INSERT_ELEM(X8L8V8U8);
INSERT_ELEM(Q8W8V8U8);
INSERT_ELEM(V16U16);
INSERT_ELEM(W11V11U10);
INSERT_ELEM(A2W10V10U10);
INSERT_ELEM(UYVY);
INSERT_ELEM(YUY2);
INSERT_ELEM(DXT1);
INSERT_ELEM(DXT2);
INSERT_ELEM(DXT3);
INSERT_ELEM(DXT4);
INSERT_ELEM(DXT5);
}
const char *D3DFormatStr(D3DFORMAT fmt) {
#define CASESTR(XX) case XX: return #XX;
switch(fmt) {
CASESTR(D3DFMT_UNKNOWN);
CASESTR(D3DFMT_R8G8B8);
CASESTR(D3DFMT_A8R8G8B8);
CASESTR(D3DFMT_X8R8G8B8);
CASESTR(D3DFMT_R5G6B5);
CASESTR(D3DFMT_X1R5G5B5);
CASESTR(D3DFMT_A1R5G5B5);
CASESTR(D3DFMT_A4R4G4B4);
CASESTR(D3DFMT_R3G3B2);
CASESTR(D3DFMT_A8);
CASESTR(D3DFMT_A8R3G3B2);
CASESTR(D3DFMT_X4R4G4B4);
CASESTR(D3DFMT_A2B10G10R10);
CASESTR(D3DFMT_G16R16);
CASESTR(D3DFMT_A8P8);
CASESTR(D3DFMT_P8);
CASESTR(D3DFMT_L8);
CASESTR(D3DFMT_A8L8);
CASESTR(D3DFMT_A4L4);
CASESTR(D3DFMT_V8U8);
CASESTR(D3DFMT_L6V5U5);
CASESTR(D3DFMT_X8L8V8U8);
CASESTR(D3DFMT_Q8W8V8U8);
CASESTR(D3DFMT_V16U16);
CASESTR(D3DFMT_W11V11U10);
CASESTR(D3DFMT_A2W10V10U10);
CASESTR(D3DFMT_UYVY);
CASESTR(D3DFMT_YUY2);
CASESTR(D3DFMT_DXT1);
CASESTR(D3DFMT_DXT2);
CASESTR(D3DFMT_DXT3);
CASESTR(D3DFMT_DXT4);
CASESTR(D3DFMT_DXT5);
CASESTR(D3DFMT_D16_LOCKABLE);
CASESTR(D3DFMT_D32);
CASESTR(D3DFMT_D15S1);
CASESTR(D3DFMT_D24S8);
CASESTR(D3DFMT_D16);
CASESTR(D3DFMT_D24X8);
CASESTR(D3DFMT_D24X4S4);
CASESTR(D3DFMT_VERTEXDATA);
CASESTR(D3DFMT_INDEX16);
CASESTR(D3DFMT_INDEX32);
}
return "Invalid D3DFORMAT";
}

View File

@ -22,7 +22,7 @@
#include "pandabase.h"
#include "winGraphicsPipe.h"
#include "pvector.h"
#include "dxgsg8base.h"
#include <ddraw.h>
typedef struct {
@ -48,8 +48,25 @@ public:
virtual string get_interface_name() const;
static PT(GraphicsPipe) pipe_constructor();
virtual PT(GraphicsStateGuardian) make_gsg(const FrameBufferProperties &properties);
bool find_best_depth_format(DXScreenData &Display, D3DDISPLAYMODE &TestDisplayMode,
D3DFORMAT *pBestFmt, bool bWantStencil,
bool bForce16bpp, bool bVerboseMode = false) const;
void search_for_valid_displaymode(DXScreenData &scrn,
UINT RequestedX_Size, UINT RequestedY_Size,
bool bWantZBuffer, bool bWantStencil,
UINT *pSupportedScreenDepthsMask,
bool *pCouldntFindAnyValidZBuf,
D3DFORMAT *pSuggestedPixFmt,
bool bForce16bppZBuffer,
bool bVerboseMode = false);
bool special_check_fullscreen_resolution(DXScreenData &scrn, UINT x_size,UINT y_size);
protected:
virtual PT(GraphicsWindow) make_window();
virtual PT(GraphicsWindow) make_window(GraphicsStateGuardian *gsg);
private:
bool init();
@ -62,6 +79,8 @@ private:
private:
HINSTANCE _hDDrawDLL;
HINSTANCE _hD3D8_DLL;
LPDIRECT3D8 _pD3D8;
typedef LPDIRECT3D8 (WINAPI *Direct3DCreate8_ProcPtr)(UINT SDKVersion);
typedef HRESULT (WINAPI * LPDIRECTDRAWCREATEEX)(GUID FAR * lpGuid, LPVOID *lplpDD, REFIID iid, IUnknown FAR *pUnkOuter);
@ -83,7 +102,7 @@ private:
typedef pvector<CardID> CardIDs;
CardIDs _card_ids;
bool _bIsDX81;
public:
static TypeHandle get_class_type() {

File diff suppressed because it is too large Load Diff

View File

@ -16,8 +16,8 @@
//
////////////////////////////////////////////////////////////////////
#ifndef WDXGRAPHICSWINDOW8_H
#define WDXGRAPHICSWINDOW8_H
#ifndef wdxGraphicsWindow8_H
#define wdxGraphicsWindow8_H
#include "pandabase.h"
#include "winGraphicsWindow.h"
@ -39,16 +39,16 @@ static const int WDXWIN_EVENT = 8;
////////////////////////////////////////////////////////////////////
class EXPCL_PANDADX wdxGraphicsWindow8 : public WinGraphicsWindow {
public:
wdxGraphicsWindow8(GraphicsPipe *pipe);
wdxGraphicsWindow8(GraphicsPipe *pipe, GraphicsStateGuardian *gsg);
virtual ~wdxGraphicsWindow8();
virtual void make_gsg();
virtual void release_gsg();
virtual bool open_window(void);
virtual int verify_window_sizes(int numsizes, int *dimen);
virtual bool begin_frame();
virtual void end_flip();
virtual LONG window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam);
virtual bool handle_mouse_motion(int x, int y);
protected:
virtual void fullscreen_restored(WindowProperties &properties);
@ -60,30 +60,26 @@ private:
void create_screen_buffers_and_device(DXScreenData &Display,
bool force_16bpp_zbuffer);
bool choose_adapter(LPDIRECT3D8 pD3D8);
bool search_for_device(LPDIRECT3D8 pD3D8, DXDeviceInfo *device_info);
bool choose_device(void);
bool search_for_device(wdxGraphicsPipe8 *dxpipe, DXDeviceInfo *device_info);
// void set_coop_levels_and_display_modes();
bool special_check_fullscreen_resolution(UINT x_size,UINT y_size);
/*
void search_for_valid_displaymode(UINT RequestedX_Size, UINT RequestedY_Size,
bool bWantZBuffer, bool bWantStencil,
UINT *pSupportedScreenDepthsMask,
bool *pCouldntFindAnyValidZBuf,
D3DFORMAT *pSuggestedPixFmt,
bool bVerboseMode = false);
*/
bool reset_device_resize_window(UINT new_xsize, UINT new_ysize);
void init_resized_window();
bool find_best_depth_format(DXScreenData &Display,
D3DDISPLAYMODE &TestDisplayMode,
D3DFORMAT *pBestFmt, bool bWantStencil,
bool bForce16bpp, bool bVerboseMode = false) const;
static int D3DFMT_to_DepthBits(D3DFORMAT fmt);
static bool is_badvidmem_card(D3DADAPTER_IDENTIFIER8 *pDevID);
DXGraphicsStateGuardian8 *_dxgsg;
DXScreenData _wcontext;
int _depth_buffer_bpp;
bool _awaiting_restore;
@ -100,6 +96,7 @@ public:
return get_class_type();
}
virtual TypeHandle force_init_type() {init_type(); return get_class_type();}
virtual void make_current(void);
private:
static TypeHandle _type_handle;

View File

@ -198,10 +198,15 @@ open_window(const WindowProperties &props, GraphicsPipe *pipe) {
wf->set_two_sided(get_two_sided());
wf->set_lighting(get_lighting());
wf->set_background_type(get_background_type());
GraphicsWindow *win = wf->open_window(props, &_engine, pipe);
if (win == (GraphicsWindow *)NULL) {
// Oops, couldn't make an actual window.
delete wf;
return NULL;
}
_windows.push_back(wf);
wf->open_window(props, &_engine, pipe);
return wf;
}

View File

@ -95,7 +95,14 @@ open_window(const WindowProperties &props, GraphicsEngine *engine,
GraphicsPipe *pipe) {
nassertr(_window == (GraphicsWindow *)NULL, _window);
_window = engine->make_window(pipe);
PT(GraphicsStateGuardian) gsg = engine->make_gsg(pipe);
if (gsg == (GraphicsStateGuardian *)NULL) {
// No GSG, no window.
framework_cat.fatal() << "open_window: failed to create gsg object!\n";
return NULL;
}
_window = engine->make_window(pipe, gsg);
if (_window != (GraphicsWindow *)NULL) {
_window->request_properties(props);
set_background_type(_background_type);

View File

@ -163,8 +163,9 @@ uchar_bgra_to_rgba(unsigned char *dest, const unsigned char *source,
// Description:
////////////////////////////////////////////////////////////////////
GLGraphicsStateGuardian::
GLGraphicsStateGuardian(GraphicsWindow *win) : GraphicsStateGuardian(win) {
reset();
GLGraphicsStateGuardian(const FrameBufferProperties &properties) :
GraphicsStateGuardian(properties)
{
}
////////////////////////////////////////////////////////////////////
@ -174,9 +175,7 @@ GLGraphicsStateGuardian(GraphicsWindow *win) : GraphicsStateGuardian(win) {
////////////////////////////////////////////////////////////////////
GLGraphicsStateGuardian::
~GLGraphicsStateGuardian() {
free_pointers();
release_all_textures();
release_all_geoms();
close_gsg();
}
////////////////////////////////////////////////////////////////////
@ -1637,7 +1636,9 @@ release_texture(TextureContext *tc) {
GLTextureContext *gtc = DCAST(GLTextureContext, tc);
Texture *tex = tc->_texture;
if (!is_closed()) {
if (!_closing_gsg) {
// Don't bother to delete the GL texture if we're about to destroy
// the context anyway.
glDeleteTextures(1, &gtc->_index);
}
gtc->_index = 0;
@ -1651,7 +1652,9 @@ release_texture(TextureContext *tc) {
tex->clear_gsg(this);
delete gtc;
report_gl_errors();
if (!_closing_gsg) {
report_gl_errors();
}
}
////////////////////////////////////////////////////////////////////
@ -1898,6 +1901,9 @@ copy_texture(TextureContext *tc, const DisplayRegion *dr, const RenderBuffer &rb
////////////////////////////////////////////////////////////////////
void GLGraphicsStateGuardian::
texture_to_pixel_buffer(TextureContext *tc, PixelBuffer *pb) {
// This code is now invalidated by the new design; perhaps the
// interface is not needed anyway.
#if 0
nassertv(tc != NULL && pb != NULL);
Texture *tex = tc->_texture;
@ -1914,6 +1920,7 @@ texture_to_pixel_buffer(TextureContext *tc, PixelBuffer *pb) {
pop_frame_buffer(old_fb);
report_gl_errors();
#endif
}
////////////////////////////////////////////////////////////////////
@ -3000,6 +3007,9 @@ draw_texture(TextureContext *tc, const DisplayRegion *dr,
////////////////////////////////////////////////////////////////////
void GLGraphicsStateGuardian::
draw_pixel_buffer(PixelBuffer *pb, const DisplayRegion *dr) {
// This code is now invalidated by the new design; perhaps the
// interface is not needed anyway.
#if 0
nassertv(pb != NULL && dr != NULL);
nassertv(!pb->_image.empty());
DisplayRegionStack old_dr = push_display_region(dr);
@ -3109,6 +3119,7 @@ draw_pixel_buffer(PixelBuffer *pb, const DisplayRegion *dr) {
pop_display_region(old_dr);
report_gl_errors();
#endif
}
////////////////////////////////////////////////////////////////////

View File

@ -63,8 +63,8 @@ INLINE ostream &operator << (ostream &out, GLenum v) {
////////////////////////////////////////////////////////////////////
class EXPCL_PANDAGL GLGraphicsStateGuardian : public GraphicsStateGuardian {
public:
GLGraphicsStateGuardian(GraphicsWindow *win);
~GLGraphicsStateGuardian();
GLGraphicsStateGuardian(const FrameBufferProperties &properties);
virtual ~GLGraphicsStateGuardian();
virtual void reset();

View File

@ -13,6 +13,8 @@
config_glxdisplay.cxx config_glxdisplay.h \
glxGraphicsPipe.I glxGraphicsPipe.cxx \
glxGraphicsPipe.h glxGraphicsWindow.I glxGraphicsWindow.cxx \
glxGraphicsStateGuardian.h glxGraphicsStateGuardian.I \
glxGraphicsStateGuardian.cxx \
glxGraphicsWindow.h
#define INSTALL_HEADERS \

View File

@ -19,6 +19,7 @@
#include "config_glxdisplay.h"
#include "glxGraphicsPipe.h"
#include "glxGraphicsWindow.h"
#include "glxGraphicsStateGuardian.h"
#include "graphicsPipeSelection.h"
#include "dconfig.h"
@ -47,12 +48,11 @@ init_libglxdisplay() {
glxGraphicsPipe::init_type();
glxGraphicsWindow::init_type();
glxGraphicsStateGuardian::init_type();
GraphicsPipeSelection *selection = GraphicsPipeSelection::get_global_ptr();
selection->add_pipe_type(glxGraphicsPipe::get_class_type(),
glxGraphicsPipe::pipe_constructor);
}
bool gl_show_fps_meter = config_glxdisplay.GetBool("show-fps-meter", false);
float gl_fps_meter_update_interval = max((float)0.5,config_glxdisplay.GetFloat("fps-meter-update-interval", 1.7));
const string display_cfg = config_glxdisplay.GetString("display", "");

View File

@ -26,8 +26,6 @@ NotifyCategoryDecl(glxdisplay, EXPCL_PANDAGL, EXPTP_PANDAGL);
extern EXPCL_PANDAGL void init_libglxdisplay();
extern bool gl_show_fps_meter;
extern float gl_fps_meter_update_interval;
extern const string display_cfg;
#endif /* __CONFIG_GLXDISPLAY_H__ */

View File

@ -18,7 +18,9 @@
#include "glxGraphicsPipe.h"
#include "glxGraphicsWindow.h"
#include "glxGraphicsStateGuardian.h"
#include "config_glxdisplay.h"
#include "frameBufferProperties.h"
#include "mutexHolder.h"
#include <GL/glx.h>
@ -116,18 +118,363 @@ pipe_constructor() {
return new glxGraphicsPipe;
}
////////////////////////////////////////////////////////////////////
// Function: glxGraphicsPipe::make_gsg
// Access: Protected, Virtual
// Description: Creates a new GSG to use the pipe (but no windows
// have been created yet for the GSG). This method will
// be called in the draw thread for the GSG.
////////////////////////////////////////////////////////////////////
PT(GraphicsStateGuardian) glxGraphicsPipe::
make_gsg(const FrameBufferProperties &properties) {
if (!_is_valid) {
return NULL;
}
FrameBufferProperties new_properties = properties;
XVisualInfo *visual = choose_visual(new_properties);
// Attempt to create a GL context.
GLXContext context = glXCreateContext(_display, visual, None, GL_TRUE);
if (context == NULL) {
glxdisplay_cat.error()
<< "Could not create GL context.\n";
XFree(visual);
return NULL;
}
// Now we can make a GSG.
PT(glxGraphicsStateGuardian) gsg =
new glxGraphicsStateGuardian(new_properties);
gsg->_context = context;
gsg->_visual = visual;
gsg->_display = _display;
return gsg.p();
}
////////////////////////////////////////////////////////////////////
// Function: glxGraphicsPipe::make_window
// Access: Protected, Virtual
// Description: Creates a new window on the pipe, if possible.
////////////////////////////////////////////////////////////////////
PT(GraphicsWindow) glxGraphicsPipe::
make_window() {
make_window(GraphicsStateGuardian *gsg) {
if (!_is_valid) {
return NULL;
}
return new glxGraphicsWindow(this);
return new glxGraphicsWindow(this, gsg);
}
////////////////////////////////////////////////////////////////////
// Function: glxGraphicsPipe::choose visual
// Access: Private
// Description: Selects an appropriate X visual for the given frame
// buffer properties. Returns the visual pointer if
// successful, or NULL otherwise.
//
// If successful, this may modify properties to reflect
// the actual visual chosen.
////////////////////////////////////////////////////////////////////
XVisualInfo *glxGraphicsPipe::
choose_visual(FrameBufferProperties &properties) const {
int frame_buffer_mode = 0;
int want_depth_bits = 0;
int want_color_bits = 0;
if (properties.has_frame_buffer_mode()) {
frame_buffer_mode = properties.get_frame_buffer_mode();
}
if (properties.has_depth_bits()) {
want_depth_bits = properties.get_depth_bits();
}
if (properties.has_color_bits()) {
want_color_bits = properties.get_color_bits();
}
/*
if (frame_buffer_mode & FrameBufferProperties::FM_multisample) {
if (!glx_supports("GLX_SGIS_multisample")) {
glxdisplay_cat.info()
<< "multisample not supported by this glx implementation.\n";
frame_buffer_mode &= ~FrameBufferProperties::FM_multisample;
}
}
*/
XVisualInfo *visual =
try_for_visual(frame_buffer_mode, want_depth_bits, want_color_bits);
// This is the severity level at which we'll report the details of
// the visual we actually do find. Normally, it's debug-level
// information: we don't care about that much detail.
NotifySeverity show_visual_severity = NS_debug;
if (visual == NULL) {
glxdisplay_cat.info()
<< "glxGraphicsWindow::choose_visual() - visual with requested\n"
<< " capabilities not found; trying for lesser visual.\n";
// If we're unable to get the visual we asked for, however, we
// probably *do* care to know the details about what we actually
// got, even if we don't have debug mode set. So we'll report the
// visual at a higher level.
show_visual_severity = NS_info;
bool special_size_request =
(want_depth_bits != 1 || want_color_bits != 1);
// We try to be smart about choosing a close match for the visual.
// First, we'll eliminate some of the more esoteric options one at
// a time, then two at a time, and finally we'll try just the bare
// minimum.
if (special_size_request) {
// Actually, first we'll eliminate all of the minimum sizes, to
// try to open a window with all of the requested options, but
// maybe not as many bits in some options as we'd like.
visual = try_for_visual(frame_buffer_mode, 1, 1);
}
if (visual == NULL) {
// Ok, not good enough. Now try to eliminate options, but keep
// as many bits as we asked for.
// This array keeps the bitmasks of options that we pull out of
// the requested frame_buffer_mode, in order.
static const int strip_properties[] = {
// One esoteric option removed.
FrameBufferProperties::FM_multisample,
FrameBufferProperties::FM_stencil,
FrameBufferProperties::FM_accum,
FrameBufferProperties::FM_alpha,
FrameBufferProperties::FM_stereo,
// Two esoteric options removed.
FrameBufferProperties::FM_stencil | FrameBufferProperties::FM_multisample,
FrameBufferProperties::FM_accum | FrameBufferProperties::FM_multisample,
FrameBufferProperties::FM_alpha | FrameBufferProperties::FM_multisample,
FrameBufferProperties::FM_stereo | FrameBufferProperties::FM_multisample,
FrameBufferProperties::FM_stencil | FrameBufferProperties::FM_accum,
FrameBufferProperties::FM_alpha | FrameBufferProperties::FM_stereo,
FrameBufferProperties::FM_stencil | FrameBufferProperties::FM_accum | FrameBufferProperties::FM_multisample,
FrameBufferProperties::FM_alpha | FrameBufferProperties::FM_stereo | FrameBufferProperties::FM_multisample,
// All esoteric options removed.
FrameBufferProperties::FM_stencil | FrameBufferProperties::FM_accum | FrameBufferProperties::FM_alpha | FrameBufferProperties::FM_stereo | FrameBufferProperties::FM_multisample,
// All esoteric options, plus some we'd really really prefer,
// removed.
FrameBufferProperties::FM_stencil | FrameBufferProperties::FM_accum | FrameBufferProperties::FM_alpha | FrameBufferProperties::FM_stereo | FrameBufferProperties::FM_multisample | FrameBufferProperties::FM_double_buffer,
// A zero marks the end of the array.
0
};
pset<int> tried_masks;
tried_masks.insert(frame_buffer_mode);
int i;
for (i = 0; visual == NULL && strip_properties[i] != 0; i++) {
int new_frame_buffer_mode = frame_buffer_mode & ~strip_properties[i];
if (tried_masks.insert(new_frame_buffer_mode).second) {
visual = try_for_visual(new_frame_buffer_mode, want_depth_bits,
want_color_bits);
}
}
if (special_size_request) {
tried_masks.clear();
tried_masks.insert(frame_buffer_mode);
if (visual == NULL) {
// Try once more, this time eliminating all of the size
// requests.
for (i = 0; visual == NULL && strip_properties[i] != 0; i++) {
int new_frame_buffer_mode = frame_buffer_mode & ~strip_properties[i];
if (tried_masks.insert(new_frame_buffer_mode).second) {
visual = try_for_visual(new_frame_buffer_mode, 1, 1);
}
}
}
}
if (visual == NULL) {
// Here's our last-ditch desparation attempt: give us any GLX
// visual at all!
visual = try_for_visual(0, 1, 1);
}
if (visual == NULL) {
glxdisplay_cat.error()
<< "Could not get any GLX visual.\n";
return NULL;
}
}
}
glxdisplay_cat.info()
<< "Got visual 0x" << hex << (int)visual->visualid << dec << ".\n";
// Now update our frambuffer_mode and bit depth appropriately.
int render_mode, double_buffer, stereo, red_size, green_size, blue_size,
alpha_size, ared_size, agreen_size, ablue_size, aalpha_size,
depth_size, stencil_size;
glXGetConfig(_display, visual, GLX_RGBA, &render_mode);
glXGetConfig(_display, visual, GLX_DOUBLEBUFFER, &double_buffer);
glXGetConfig(_display, visual, GLX_STEREO, &stereo);
glXGetConfig(_display, visual, GLX_RED_SIZE, &red_size);
glXGetConfig(_display, visual, GLX_GREEN_SIZE, &green_size);
glXGetConfig(_display, visual, GLX_BLUE_SIZE, &blue_size);
glXGetConfig(_display, visual, GLX_ALPHA_SIZE, &alpha_size);
glXGetConfig(_display, visual, GLX_ACCUM_RED_SIZE, &ared_size);
glXGetConfig(_display, visual, GLX_ACCUM_GREEN_SIZE, &agreen_size);
glXGetConfig(_display, visual, GLX_ACCUM_BLUE_SIZE, &ablue_size);
glXGetConfig(_display, visual, GLX_ACCUM_ALPHA_SIZE, &aalpha_size);
glXGetConfig(_display, visual, GLX_DEPTH_SIZE, &depth_size);
glXGetConfig(_display, visual, GLX_STENCIL_SIZE, &stencil_size);
frame_buffer_mode = 0;
if (double_buffer) {
frame_buffer_mode |= FrameBufferProperties::FM_double_buffer;
}
if (stereo) {
frame_buffer_mode |= FrameBufferProperties::FM_stereo;
}
if (!render_mode) {
frame_buffer_mode |= FrameBufferProperties::FM_index;
}
if (stencil_size != 0) {
frame_buffer_mode |= FrameBufferProperties::FM_stencil;
}
if (depth_size != 0) {
frame_buffer_mode |= FrameBufferProperties::FM_depth;
}
if (alpha_size != 0) {
frame_buffer_mode |= FrameBufferProperties::FM_alpha;
}
if (ared_size + agreen_size + ablue_size != 0) {
frame_buffer_mode |= FrameBufferProperties::FM_accum;
}
properties.set_frame_buffer_mode(frame_buffer_mode);
properties.set_color_bits(red_size + green_size + blue_size + alpha_size);
properties.set_depth_bits(depth_size);
if (glxdisplay_cat.is_on(show_visual_severity)) {
glxdisplay_cat.out(show_visual_severity)
<< "GLX Visual Info (# bits of each):" << endl
<< " RGBA: " << red_size << " " << green_size << " " << blue_size
<< " " << alpha_size << endl
<< " Accum RGBA: " << ared_size << " " << agreen_size << " "
<< ablue_size << " " << aalpha_size << endl
<< " Depth: " << depth_size << endl
<< " Stencil: " << stencil_size << endl
<< " DoubleBuffer? " << double_buffer << endl
<< " Stereo? " << stereo << endl;
}
return visual;
}
////////////////////////////////////////////////////////////////////
// Function: glxGraphicsPipe::try_for_visual
// Access: Private
// Description: Attempt to get the requested visual, if it is
// available. It's just a wrapper around
// glXChooseVisual(). It returns the visual information
// if possible, or NULL if it is not.
////////////////////////////////////////////////////////////////////
XVisualInfo *glxGraphicsPipe::
try_for_visual(int framebuffer_mode,
int want_depth_bits, int want_color_bits) const {
static const int max_attrib_list = 32;
int attrib_list[max_attrib_list];
int n=0;
glxdisplay_cat.debug()
<< "Trying for visual with: RGB(" << want_color_bits << ")";
int want_color_component_bits;
if (framebuffer_mode & FrameBufferProperties::FM_alpha) {
want_color_component_bits = max(want_color_bits / 4, 1);
} else {
want_color_component_bits = max(want_color_bits / 3, 1);
}
attrib_list[n++] = GLX_RGBA;
attrib_list[n++] = GLX_RED_SIZE;
attrib_list[n++] = want_color_component_bits;
attrib_list[n++] = GLX_GREEN_SIZE;
attrib_list[n++] = want_color_component_bits;
attrib_list[n++] = GLX_BLUE_SIZE;
attrib_list[n++] = want_color_component_bits;
if (framebuffer_mode & FrameBufferProperties::FM_alpha) {
glxdisplay_cat.debug(false) << " ALPHA";
attrib_list[n++] = GLX_ALPHA_SIZE;
attrib_list[n++] = want_color_component_bits;
}
if (framebuffer_mode & FrameBufferProperties::FM_double_buffer) {
glxdisplay_cat.debug(false) << " DOUBLEBUFFER";
attrib_list[n++] = GLX_DOUBLEBUFFER;
}
if (framebuffer_mode & FrameBufferProperties::FM_stereo) {
glxdisplay_cat.debug(false) << " STEREO";
attrib_list[n++] = GLX_STEREO;
}
if (framebuffer_mode & FrameBufferProperties::FM_depth) {
glxdisplay_cat.debug(false) << " DEPTH(" << want_depth_bits << ")";
attrib_list[n++] = GLX_DEPTH_SIZE;
attrib_list[n++] = want_depth_bits;
}
if (framebuffer_mode & FrameBufferProperties::FM_stencil) {
glxdisplay_cat.debug(false) << " STENCIL";
attrib_list[n++] = GLX_STENCIL_SIZE;
attrib_list[n++] = 1;
}
if (framebuffer_mode & FrameBufferProperties::FM_accum) {
glxdisplay_cat.debug(false) << " ACCUM";
attrib_list[n++] = GLX_ACCUM_RED_SIZE;
attrib_list[n++] = want_color_component_bits;
attrib_list[n++] = GLX_ACCUM_GREEN_SIZE;
attrib_list[n++] = want_color_component_bits;
attrib_list[n++] = GLX_ACCUM_BLUE_SIZE;
attrib_list[n++] = want_color_component_bits;
if (framebuffer_mode & FrameBufferProperties::FM_alpha) {
attrib_list[n++] = GLX_ACCUM_ALPHA_SIZE;
attrib_list[n++] = want_color_component_bits;
}
}
#if defined(GLX_VERSION_1_1) && defined(GLX_SGIS_multisample)
if (framebuffer_mode & FrameBufferProperties::FM_multisample) {
glxdisplay_cat.debug(false) << " MULTISAMPLE";
attrib_list[n++] = GLX_SAMPLES_SGIS;
// We decide 4 is minimum number of samples
attrib_list[n++] = 4;
}
#endif
// Terminate the list
nassertr(n < max_attrib_list, NULL);
attrib_list[n] = (int)None;
XVisualInfo *vinfo = glXChooseVisual(_display, _screen, attrib_list);
if (glxdisplay_cat.is_debug()) {
if (vinfo != NULL) {
glxdisplay_cat.debug(false) << ", match found!\n";
} else {
glxdisplay_cat.debug(false) << ", no match.\n";
}
}
return vinfo;
}
////////////////////////////////////////////////////////////////////

View File

@ -22,17 +22,20 @@
#include "pandabase.h"
#include "graphicsPipe.h"
#include <X11/Xlib.h>
class glxGraphicsWindow;
class FrameBufferProperties;
#ifdef CPPPARSER
// A simple hack so interrogate can parse this file.
typedef int Display;
typedef int Window;
typedef int XErrorEvent;
typedef int XVisualInfo;
typedef int Atom;
#endif
#else
#include <X11/Xlib.h>
#include <GL/glx.h>
#endif // CPPPARSER
////////////////////////////////////////////////////////////////////
// Class : glxGraphicsPipe
@ -55,9 +58,14 @@ public:
INLINE Atom get_wm_delete_window() const;
protected:
virtual PT(GraphicsWindow) make_window();
virtual PT(GraphicsStateGuardian) make_gsg(const FrameBufferProperties &properties);
virtual PT(GraphicsWindow) make_window(GraphicsStateGuardian *gsg);
private:
XVisualInfo *choose_visual(FrameBufferProperties &properties) const;
XVisualInfo *try_for_visual(int framebuffer_mode,
int want_depth_bits, int want_color_bits) const;
static void install_error_handlers();
static int error_handler(Display *display, XErrorEvent *error);
static int io_error_handler(Display *display);

View File

@ -17,6 +17,7 @@
////////////////////////////////////////////////////////////////////
#include "glxGraphicsWindow.h"
#include "glxGraphicsStateGuardian.h"
#include "config_glxdisplay.h"
#include "glxGraphicsPipe.h"
@ -39,16 +40,14 @@ TypeHandle glxGraphicsWindow::_type_handle;
// Description:
////////////////////////////////////////////////////////////////////
glxGraphicsWindow::
glxGraphicsWindow(GraphicsPipe *pipe) :
GraphicsWindow(pipe)
glxGraphicsWindow(GraphicsPipe *pipe, GraphicsStateGuardian *gsg) :
GraphicsWindow(pipe, gsg)
{
glxGraphicsPipe *glx_pipe;
DCAST_INTO_V(glx_pipe, _pipe);
_display = glx_pipe->get_display();
_screen = glx_pipe->get_screen();
_xwindow = (Window)0;
_context = (GLXContext)0;
_visual = (XVisualInfo *)NULL;
_xwindow = (Window)NULL;
_awaiting_configure = false;
_wm_delete_window = glx_pipe->get_wm_delete_window();
@ -66,49 +65,6 @@ glxGraphicsWindow::
~glxGraphicsWindow() {
}
////////////////////////////////////////////////////////////////////
// Function: glxGraphicsWindow::make_gsg
// Access: Public, Virtual
// Description: Creates a new GSG for the window and stores it in the
// _gsg pointer. This should only be called from within
// the draw thread.
////////////////////////////////////////////////////////////////////
void glxGraphicsWindow::
make_gsg() {
nassertv(_gsg == (GraphicsStateGuardian *)NULL);
// First, we need to create the rendering context.
_context = glXCreateContext(_display, _visual, None, GL_TRUE);
if (!_context) {
glxdisplay_cat.error()
<< "Could not create GLX context.\n";
return;
}
// And make sure the new context is current.
glXMakeCurrent(_display, _xwindow, _context);
// Now we can make a GSG.
_gsg = new GLGraphicsStateGuardian(this);
}
////////////////////////////////////////////////////////////////////
// Function: glxGraphicsWindow::release_gsg
// Access: Public, Virtual
// Description: Releases the current GSG pointer, if it is currently
// held, and resets the GSG to NULL. This should only
// be called from within the draw thread.
////////////////////////////////////////////////////////////////////
void glxGraphicsWindow::
release_gsg() {
if (_gsg != (GraphicsStateGuardian *)NULL) {
glXMakeCurrent(_display, _xwindow, _context);
GraphicsWindow::release_gsg();
glXDestroyContext(_display, _context);
_context = (GLXContext)0;
}
}
////////////////////////////////////////////////////////////////////
// Function: glxGraphicsWindow::make_current
// Access: Public, Virtual
@ -118,8 +74,30 @@ release_gsg() {
////////////////////////////////////////////////////////////////////
void glxGraphicsWindow::
make_current() {
nassertv(_gsg != (GraphicsStateGuardian *)NULL);
glXMakeCurrent(_display, _xwindow, _context);
glxGraphicsStateGuardian *glxgsg;
DCAST_INTO_V(glxgsg, _gsg);
glXMakeCurrent(_display, _xwindow, glxgsg->_context);
// Now that we have made the context current to a window, we can
// reset the GSG state if this is the first time it has been used.
// (We can't just call reset() when we construct the GSG, because
// reset() requires having a current context.)
glxgsg->reset_if_new();
}
////////////////////////////////////////////////////////////////////
// Function: glxGraphicsWindow::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 glxGraphicsWindow::
release_gsg() {
glXMakeCurrent(_display, None, NULL);
GraphicsWindow::release_gsg();
}
////////////////////////////////////////////////////////////////////
@ -159,7 +137,7 @@ begin_frame() {
void glxGraphicsWindow::
begin_flip() {
if (_gsg != (GraphicsStateGuardian *)NULL) {
glXMakeCurrent(_display, _xwindow, _context);
make_current();
glXSwapBuffers(_display, _xwindow);
}
}
@ -371,7 +349,7 @@ set_properties_now(WindowProperties &properties) {
////////////////////////////////////////////////////////////////////
void glxGraphicsWindow::
close_window() {
if (_xwindow != (Window)0) {
if (_xwindow != (Window)NULL) {
XDestroyWindow(_display, _xwindow);
_xwindow = (Window)0;
@ -404,12 +382,12 @@ open_window() {
glxGraphicsPipe *glx_pipe;
DCAST_INTO_R(glx_pipe, _pipe, false);
glxGraphicsStateGuardian *glxgsg;
DCAST_INTO_R(glxgsg, _gsg, false);
Window root_window = glx_pipe->get_root();
if (!choose_visual()) {
return false;
}
setup_colormap();
setup_colormap(glxgsg->_visual);
_event_mask =
ButtonPressMask | ButtonReleaseMask |
@ -434,7 +412,7 @@ open_window() {
_properties.get_x_origin(), _properties.get_y_origin(),
_properties.get_x_size(), _properties.get_y_size(),
0,
_visual->depth, InputOutput, _visual->visual,
glxgsg->_visual->depth, InputOutput, glxgsg->_visual->visual,
attrib_mask, &wa);
if (_xwindow == (Window)0) {
@ -538,315 +516,6 @@ set_wm_properties(const WindowProperties &properties) {
sizeof(protocols) / sizeof(Atom));
}
////////////////////////////////////////////////////////////////////
// Function: glxGraphicsWindow::try_for_visual
// Access: Private
// Description: Attempt to get the requested visual, if it is
// available. It's just a wrapper around
// glXChooseVisual(). It returns the visual information
// if possible, or NULL if it is not.
////////////////////////////////////////////////////////////////////
XVisualInfo *glxGraphicsWindow::
try_for_visual(int framebuffer_mode,
int want_depth_bits, int want_color_bits) const {
static const int max_attrib_list = 32;
int attrib_list[max_attrib_list];
int n=0;
glxdisplay_cat.debug()
<< "Trying for visual with: RGB(" << want_color_bits << ")";
int want_color_component_bits;
if (framebuffer_mode & WindowProperties::FM_alpha) {
want_color_component_bits = max(want_color_bits / 4, 1);
} else {
want_color_component_bits = max(want_color_bits / 3, 1);
}
attrib_list[n++] = GLX_RGBA;
attrib_list[n++] = GLX_RED_SIZE;
attrib_list[n++] = want_color_component_bits;
attrib_list[n++] = GLX_GREEN_SIZE;
attrib_list[n++] = want_color_component_bits;
attrib_list[n++] = GLX_BLUE_SIZE;
attrib_list[n++] = want_color_component_bits;
if (framebuffer_mode & WindowProperties::FM_alpha) {
glxdisplay_cat.debug(false) << " ALPHA";
attrib_list[n++] = GLX_ALPHA_SIZE;
attrib_list[n++] = want_color_component_bits;
}
if (framebuffer_mode & WindowProperties::FM_double_buffer) {
glxdisplay_cat.debug(false) << " DOUBLEBUFFER";
attrib_list[n++] = GLX_DOUBLEBUFFER;
}
if (framebuffer_mode & WindowProperties::FM_stereo) {
glxdisplay_cat.debug(false) << " STEREO";
attrib_list[n++] = GLX_STEREO;
}
if (framebuffer_mode & WindowProperties::FM_depth) {
glxdisplay_cat.debug(false) << " DEPTH(" << want_depth_bits << ")";
attrib_list[n++] = GLX_DEPTH_SIZE;
attrib_list[n++] = want_depth_bits;
}
if (framebuffer_mode & WindowProperties::FM_stencil) {
glxdisplay_cat.debug(false) << " STENCIL";
attrib_list[n++] = GLX_STENCIL_SIZE;
attrib_list[n++] = 1;
}
if (framebuffer_mode & WindowProperties::FM_accum) {
glxdisplay_cat.debug(false) << " ACCUM";
attrib_list[n++] = GLX_ACCUM_RED_SIZE;
attrib_list[n++] = want_color_component_bits;
attrib_list[n++] = GLX_ACCUM_GREEN_SIZE;
attrib_list[n++] = want_color_component_bits;
attrib_list[n++] = GLX_ACCUM_BLUE_SIZE;
attrib_list[n++] = want_color_component_bits;
if (framebuffer_mode & WindowProperties::FM_alpha) {
attrib_list[n++] = GLX_ACCUM_ALPHA_SIZE;
attrib_list[n++] = want_color_component_bits;
}
}
#if defined(GLX_VERSION_1_1) && defined(GLX_SGIS_multisample)
if (framebuffer_mode & WindowProperties::FM_multisample) {
glxdisplay_cat.debug(false) << " MULTISAMPLE";
attrib_list[n++] = GLX_SAMPLES_SGIS;
// We decide 4 is minimum number of samples
attrib_list[n++] = 4;
}
#endif
// Terminate the list
nassertr(n < max_attrib_list, NULL);
attrib_list[n] = (int)None;
XVisualInfo *vinfo = glXChooseVisual(_display, _screen, attrib_list);
if (glxdisplay_cat.is_debug()) {
if (vinfo != NULL) {
glxdisplay_cat.debug(false) << ", match found!\n";
} else {
glxdisplay_cat.debug(false) << ", no match.\n";
}
}
return vinfo;
}
////////////////////////////////////////////////////////////////////
// Function: glxGraphicsWindow::choose visual
// Access: Private
// Description: Selects an appropriate X visual for the window based
// on the window properties. Returns true if
// successful, false otherwise.
//
// Initializes _visual, and modifies _properties
// according to the actual visual chosen.
////////////////////////////////////////////////////////////////////
bool glxGraphicsWindow::
choose_visual() {
int framebuffer_mode = 0;
int want_depth_bits = 0;
int want_color_bits = 0;
if (_properties.has_framebuffer_mode()) {
framebuffer_mode = _properties.get_framebuffer_mode();
}
if (_properties.has_depth_bits()) {
want_depth_bits = _properties.get_depth_bits();
}
if (_properties.has_color_bits()) {
want_color_bits = _properties.get_color_bits();
}
/*
if (framebuffer_mode & WindowProperties::FM_multisample) {
if (!glx_supports("GLX_SGIS_multisample")) {
glxdisplay_cat.info()
<< "multisample not supported by this glx implementation.\n";
framebuffer_mode &= ~WindowProperties::FM_multisample;
}
}
*/
_visual = try_for_visual(framebuffer_mode, want_depth_bits, want_color_bits);
// This is the severity level at which we'll report the details of
// the visual we actually do find. Normally, it's debug-level
// information: we don't care about that much detail.
NotifySeverity show_visual_severity = NS_debug;
if (_visual == NULL) {
glxdisplay_cat.info()
<< "glxGraphicsWindow::choose_visual() - visual with requested\n"
<< " capabilities not found; trying for lesser visual.\n";
// If we're unable to get the visual we asked for, however, we
// probably *do* care to know the details about what we actually
// got, even if we don't have debug mode set. So we'll report the
// visual at a higher level.
show_visual_severity = NS_info;
bool special_size_request =
(want_depth_bits != 1 || want_color_bits != 1);
// We try to be smart about choosing a close match for the visual.
// First, we'll eliminate some of the more esoteric options one at
// a time, then two at a time, and finally we'll try just the bare
// minimum.
if (special_size_request) {
// Actually, first we'll eliminate all of the minimum sizes, to
// try to open a window with all of the requested options, but
// maybe not as many bits in some options as we'd like.
_visual = try_for_visual(framebuffer_mode, 1, 1);
}
if (_visual == NULL) {
// Ok, not good enough. Now try to eliminate options, but keep
// as many bits as we asked for.
// This array keeps the bitmasks of options that we pull out of
// the requested framebuffer_mode, in order.
static const int strip_properties[] = {
// One esoteric option removed.
WindowProperties::FM_multisample,
WindowProperties::FM_stencil,
WindowProperties::FM_accum,
WindowProperties::FM_alpha,
WindowProperties::FM_stereo,
// Two esoteric options removed.
WindowProperties::FM_stencil | WindowProperties::FM_multisample,
WindowProperties::FM_accum | WindowProperties::FM_multisample,
WindowProperties::FM_alpha | WindowProperties::FM_multisample,
WindowProperties::FM_stereo | WindowProperties::FM_multisample,
WindowProperties::FM_stencil | WindowProperties::FM_accum,
WindowProperties::FM_alpha | WindowProperties::FM_stereo,
WindowProperties::FM_stencil | WindowProperties::FM_accum | WindowProperties::FM_multisample,
WindowProperties::FM_alpha | WindowProperties::FM_stereo | WindowProperties::FM_multisample,
// All esoteric options removed.
WindowProperties::FM_stencil | WindowProperties::FM_accum | WindowProperties::FM_alpha | WindowProperties::FM_stereo | WindowProperties::FM_multisample,
// All esoteric options, plus some we'd really really prefer,
// removed.
WindowProperties::FM_stencil | WindowProperties::FM_accum | WindowProperties::FM_alpha | WindowProperties::FM_stereo | WindowProperties::FM_multisample | WindowProperties::FM_double_buffer,
// A zero marks the end of the array.
0
};
pset<int> tried_masks;
tried_masks.insert(framebuffer_mode);
int i;
for (i = 0; _visual == NULL && strip_properties[i] != 0; i++) {
int new_framebuffer_mode = framebuffer_mode & ~strip_properties[i];
if (tried_masks.insert(new_framebuffer_mode).second) {
_visual = try_for_visual(new_framebuffer_mode, want_depth_bits,
want_color_bits);
}
}
if (special_size_request) {
tried_masks.clear();
tried_masks.insert(framebuffer_mode);
if (_visual == NULL) {
// Try once more, this time eliminating all of the size
// requests.
for (i = 0; _visual == NULL && strip_properties[i] != 0; i++) {
int new_framebuffer_mode = framebuffer_mode & ~strip_properties[i];
if (tried_masks.insert(new_framebuffer_mode).second) {
_visual = try_for_visual(new_framebuffer_mode, 1, 1);
}
}
}
}
if (_visual == NULL) {
// Here's our last-ditch desparation attempt: give us any GLX
// visual at all!
_visual = try_for_visual(0, 1, 1);
}
if (_visual == NULL) {
glxdisplay_cat.error()
<< "Could not get any GLX visual.\n";
return false;
}
}
}
glxdisplay_cat.info()
<< "Got visual 0x" << hex << (int)_visual->visualid << dec << ".\n";
// Now update our frambuffer_mode and bit depth appropriately.
int render_mode, double_buffer, stereo, red_size, green_size, blue_size,
alpha_size, ared_size, agreen_size, ablue_size, aalpha_size,
depth_size, stencil_size;
glXGetConfig(_display, _visual, GLX_RGBA, &render_mode);
glXGetConfig(_display, _visual, GLX_DOUBLEBUFFER, &double_buffer);
glXGetConfig(_display, _visual, GLX_STEREO, &stereo);
glXGetConfig(_display, _visual, GLX_RED_SIZE, &red_size);
glXGetConfig(_display, _visual, GLX_GREEN_SIZE, &green_size);
glXGetConfig(_display, _visual, GLX_BLUE_SIZE, &blue_size);
glXGetConfig(_display, _visual, GLX_ALPHA_SIZE, &alpha_size);
glXGetConfig(_display, _visual, GLX_ACCUM_RED_SIZE, &ared_size);
glXGetConfig(_display, _visual, GLX_ACCUM_GREEN_SIZE, &agreen_size);
glXGetConfig(_display, _visual, GLX_ACCUM_BLUE_SIZE, &ablue_size);
glXGetConfig(_display, _visual, GLX_ACCUM_ALPHA_SIZE, &aalpha_size);
glXGetConfig(_display, _visual, GLX_DEPTH_SIZE, &depth_size);
glXGetConfig(_display, _visual, GLX_STENCIL_SIZE, &stencil_size);
framebuffer_mode = 0;
if (double_buffer) {
framebuffer_mode |= WindowProperties::FM_double_buffer;
}
if (stereo) {
framebuffer_mode |= WindowProperties::FM_stereo;
}
if (!render_mode) {
framebuffer_mode |= WindowProperties::FM_index;
}
if (stencil_size != 0) {
framebuffer_mode |= WindowProperties::FM_stencil;
}
if (depth_size != 0) {
framebuffer_mode |= WindowProperties::FM_depth;
}
if (alpha_size != 0) {
framebuffer_mode |= WindowProperties::FM_alpha;
}
if (ared_size + agreen_size + ablue_size != 0) {
framebuffer_mode |= WindowProperties::FM_accum;
}
_properties.set_framebuffer_mode(framebuffer_mode);
_properties.set_color_bits(red_size + green_size + blue_size + alpha_size);
_properties.set_depth_bits(depth_size);
if (glxdisplay_cat.is_on(show_visual_severity)) {
glxdisplay_cat.out(show_visual_severity)
<< "GLX Visual Info (# bits of each):" << endl
<< " RGBA: " << red_size << " " << green_size << " " << blue_size
<< " " << alpha_size << endl
<< " Accum RGBA: " << ared_size << " " << agreen_size << " "
<< ablue_size << " " << aalpha_size << endl
<< " Depth: " << depth_size << endl
<< " Stencil: " << stencil_size << endl
<< " DoubleBuffer? " << double_buffer << endl
<< " Stereo? " << stereo << endl;
}
return true;
}
////////////////////////////////////////////////////////////////////
// Function: glxGraphicsWindow::setup_colormap
// Access: Private
@ -854,17 +523,17 @@ choose_visual() {
// stores in in the _colormap method.
////////////////////////////////////////////////////////////////////
void glxGraphicsWindow::
setup_colormap() {
setup_colormap(XVisualInfo *visual) {
glxGraphicsPipe *glx_pipe;
DCAST_INTO_V(glx_pipe, _pipe);
Window root_window = glx_pipe->get_root();
int visual_class = _visual->c_class;
int visual_class = visual->c_class;
int rc, is_rgb;
switch (visual_class) {
case PseudoColor:
rc = glXGetConfig(_display, _visual, GLX_RGBA, &is_rgb);
rc = glXGetConfig(_display, visual, GLX_RGBA, &is_rgb);
if (rc == 0 && is_rgb) {
glxdisplay_cat.warning()
<< "mesa pseudocolor not supported.\n";
@ -873,19 +542,19 @@ setup_colormap() {
} else {
_colormap = XCreateColormap(_display, root_window,
_visual->visual, AllocAll);
visual->visual, AllocAll);
}
break;
case TrueColor:
case DirectColor:
_colormap = XCreateColormap(_display, root_window,
_visual->visual, AllocNone);
visual->visual, AllocNone);
break;
case StaticColor:
case StaticGray:
case GrayScale:
_colormap = XCreateColormap(_display, root_window,
_visual->visual, AllocNone);
visual->visual, AllocNone);
break;
default:
glxdisplay_cat.error()

View File

@ -36,12 +36,11 @@ class glxGraphicsPipe;
////////////////////////////////////////////////////////////////////
class glxGraphicsWindow : public GraphicsWindow {
public:
glxGraphicsWindow(GraphicsPipe *pipe);
glxGraphicsWindow(GraphicsPipe *pipe, GraphicsStateGuardian *gsg);
virtual ~glxGraphicsWindow();
virtual void make_gsg();
virtual void release_gsg();
virtual void make_current();
virtual void release_gsg();
virtual bool begin_frame();
virtual void begin_flip();
@ -56,10 +55,7 @@ protected:
private:
void set_wm_properties(const WindowProperties &properties);
XVisualInfo *try_for_visual(int framebuffer_mode,
int want_depth_bits, int want_color_bits) const;
bool choose_visual();
void setup_colormap();
void setup_colormap(XVisualInfo *visual);
ButtonHandle get_button(XKeyEvent *key_event);
static Bool check_event(Display *display, XEvent *event, char *arg);
@ -68,8 +64,6 @@ private:
Display *_display;
int _screen;
Window _xwindow;
GLXContext _context;
XVisualInfo *_visual;
Colormap _colormap;
long _event_mask;
bool _awaiting_configure;

View File

@ -15,11 +15,15 @@
#define INSTALL_HEADERS \
config_wgldisplay.h \
wglGraphicsPipe.I wglGraphicsPipe.h \
wglGraphicsStateGuardian.I wglGraphicsStateGuardian.h \
wglGraphicsWindow.I wglGraphicsWindow.h
// Win32Defs.h
#define INCLUDED_SOURCES \
config_wgldisplay.cxx wglGraphicsPipe.cxx wglGraphicsWindow.cxx
config_wgldisplay.cxx \
wglGraphicsPipe.cxx \
wglGraphicsStateGuardian.cxx \
wglGraphicsWindow.cxx
#define SOURCES \
$[INSTALL_HEADERS]

View File

@ -18,6 +18,7 @@
#include "config_wgldisplay.h"
#include "wglGraphicsPipe.h"
#include "wglGraphicsStateGuardian.h"
#include "wglGraphicsWindow.h"
#include "graphicsPipeSelection.h"
#include "dconfig.h"
@ -46,6 +47,7 @@ init_libwgldisplay() {
initialized = true;
wglGraphicsPipe::init_type();
wglGraphicsStateGuardian::init_type();
wglGraphicsWindow::init_type();
GraphicsPipeSelection *selection = GraphicsPipeSelection::get_global_ptr();

View File

@ -18,6 +18,10 @@
#include "wglGraphicsPipe.h"
#include "config_wgldisplay.h"
#include "config_windisplay.h"
typedef enum {Software, MCD, ICD} OGLDriverType;
static const char * const OGLDrvStrings[] = { "Software", "MCD", "ICD" };
TypeHandle wglGraphicsPipe::_type_handle;
@ -66,12 +70,241 @@ pipe_constructor() {
return new wglGraphicsPipe;
}
////////////////////////////////////////////////////////////////////
// Function: wglGraphicsPipe::make_gsg
// Access: Protected, Virtual
// Description: Creates a new GSG to use the pipe (but no windows
// have been created yet for the GSG). This method will
// be called in the draw thread for the GSG.
////////////////////////////////////////////////////////////////////
PT(GraphicsStateGuardian) wglGraphicsPipe::
make_gsg(const FrameBufferProperties &properties) {
if (!_is_valid) {
return NULL;
}
FrameBufferProperties new_properties = properties;
// Get a handle to the screen's DC so we can choose a pixel format
// (and a corresponding set of frame buffer properties) suitable for
// rendering to windows on this screen.
HDC hdc = GetDC(NULL);
int pfnum = choose_pfnum(new_properties, hdc);
if (gl_force_pixfmt != 0) {
wgldisplay_cat.info()
<< "overriding pixfmt choice algorithm (" << pfnum
<< ") with gl-force-pixfmt(" << gl_force_pixfmt << ")\n";
pfnum = gl_force_pixfmt;
}
if (wgldisplay_cat.is_debug()) {
wgldisplay_cat.debug()
<< "config() - picking pixfmt #" << pfnum <<endl;
}
// Now we're done with the screen's hdc, so release it.
ReleaseDC(NULL, hdc);
// Now we can make a GSG.
PT(wglGraphicsStateGuardian) gsg =
new wglGraphicsStateGuardian(new_properties, pfnum);
return gsg.p();
}
////////////////////////////////////////////////////////////////////
// Function: wglGraphicsPipe::make_window
// Access: Protected, Virtual
// Description: Creates a new window on the pipe, if possible.
////////////////////////////////////////////////////////////////////
PT(GraphicsWindow) wglGraphicsPipe::
make_window() {
return new wglGraphicsWindow(this);
make_window(GraphicsStateGuardian *gsg) {
return new wglGraphicsWindow(this, gsg);
}
////////////////////////////////////////////////////////////////////
// Function: wglGraphicsPipe::choose_pfnum
// Access: Private
// Description: Selects a suitable pixel format number for the given
// frame buffer properties. Returns the selected number
// if successful, or 0 otherwise.
//
// If successful, this may modify properties to reflect
// the actual visual chosen.
////////////////////////////////////////////////////////////////////
int wglGraphicsPipe::
choose_pfnum(FrameBufferProperties &properties, HDC hdc) const {
int pfnum;
bool bUsingSoftware = false;
if (force_software_renderer) {
pfnum = find_pixfmtnum(properties, hdc, false);
if (pfnum == 0) {
wgldisplay_cat.error()
<< "Couldn't find compatible software-renderer OpenGL pixfmt, check your window properties!\n";
return 0;
}
bUsingSoftware = true;
} else {
pfnum = find_pixfmtnum(properties, hdc, true);
if (pfnum == 0) {
if (allow_software_renderer) {
pfnum = find_pixfmtnum(properties, hdc, false);
if (pfnum == 0) {
wgldisplay_cat.error()
<< "Couldn't find HW or Software OpenGL pixfmt appropriate for this desktop!!\n";
}
} else {
wgldisplay_cat.error()
<< "Couldn't find HW-accelerated OpenGL pixfmt appropriate for this desktop!!\n";
}
if (pfnum == 0) {
wgldisplay_cat.error()
<< "make sure OpenGL driver is installed, and try reducing the screen size, reducing the\n"
<< "desktop screen pixeldepth to 16bpp,and check your panda window properties\n";
return 0;
}
bUsingSoftware = true;
}
}
if (bUsingSoftware) {
wgldisplay_cat.info()
<< "Couldn't find compatible OGL HW pixelformat, using software rendering.\n";
}
return pfnum;
}
////////////////////////////////////////////////////////////////////
// Function: wglGraphicsPipe::find_pixfmtnum
// Access: Private
// Description: This helper routine looks for either HW-only or
// SW-only format, but not both. Returns the
// pixelformat number, or 0 if a suitable format could
// not be found.
////////////////////////////////////////////////////////////////////
int wglGraphicsPipe::
find_pixfmtnum(FrameBufferProperties &properties, HDC hdc,
bool bLookforHW) const {
int frame_buffer_mode = properties.get_frame_buffer_mode();
bool want_depth_bits = properties.has_depth_bits();
bool want_color_bits = properties.has_color_bits();
OGLDriverType drvtype;
PIXELFORMATDESCRIPTOR pfd;
ZeroMemory(&pfd,sizeof(PIXELFORMATDESCRIPTOR));
pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR);
pfd.nVersion = 1;
// just use the pixfmt of the current desktop
int MaxPixFmtNum =
DescribePixelFormat(hdc, 1, sizeof(PIXELFORMATDESCRIPTOR), &pfd);
int cur_bpp = GetDeviceCaps(hdc,BITSPIXEL);
int pfnum;
for(pfnum = 1; pfnum <= MaxPixFmtNum; pfnum++) {
DescribePixelFormat(hdc, pfnum, sizeof(PIXELFORMATDESCRIPTOR), &pfd);
// official, nvidia sanctioned way.
if ((pfd.dwFlags & PFD_GENERIC_FORMAT) != 0) {
drvtype = Software;
} else if (pfd.dwFlags & PFD_GENERIC_ACCELERATED) {
drvtype = MCD;
} else {
drvtype = ICD;
}
// skip driver types we are not looking for
if (bLookforHW) {
if (drvtype == Software) {
continue;
}
} else {
if (drvtype != Software) {
continue;
}
}
if ((pfd.iPixelType == PFD_TYPE_COLORINDEX) &&
(frame_buffer_mode & FrameBufferProperties::FM_index) == 0) {
continue;
}
DWORD dwReqFlags = (PFD_SUPPORT_OPENGL | PFD_DRAW_TO_WINDOW);
if (wgldisplay_cat.is_debug()) {
wgldisplay_cat->debug()
<< "----------------" << endl;
if ((frame_buffer_mode & FrameBufferProperties::FM_alpha) != 0) {
wgldisplay_cat->debug()
<< "want alpha, pfd says '"
<< (int)(pfd.cAlphaBits) << "'" << endl;
}
if ((frame_buffer_mode & FrameBufferProperties::FM_depth) != 0) {
wgldisplay_cat->debug()
<< "want depth, pfd says '"
<< (int)(pfd.cDepthBits) << "'" << endl;
}
if ((frame_buffer_mode & FrameBufferProperties::FM_stencil) != 0) {
wgldisplay_cat->debug()
<< "want stencil, pfd says '"
<< (int)(pfd.cStencilBits) << "'" << endl;
}
wgldisplay_cat->debug()
<< "final flag check " << (int)(pfd.dwFlags & dwReqFlags) << " =? "
<< (int)dwReqFlags << endl;
wgldisplay_cat->debug()
<< "pfd bits = " << (int)(pfd.cColorBits) << endl;
wgldisplay_cat->debug()
<< "cur_bpp = " << cur_bpp << endl;
}
if ((frame_buffer_mode & FrameBufferProperties::FM_double_buffer) != 0) {
dwReqFlags|= PFD_DOUBLEBUFFER;
}
if ((frame_buffer_mode & FrameBufferProperties::FM_alpha) != 0 &&
(pfd.cAlphaBits==0)) {
continue;
}
if ((frame_buffer_mode & FrameBufferProperties::FM_depth) != 0 &&
(pfd.cDepthBits==0)) {
continue;
}
if ((frame_buffer_mode & FrameBufferProperties::FM_stencil) != 0 &&
(pfd.cStencilBits==0)) {
continue;
}
if ((pfd.dwFlags & dwReqFlags) != dwReqFlags) {
continue;
}
// now we ignore the specified want_color_bits for windowed mode
// instead we use the current screen depth
if ((pfd.cColorBits!=cur_bpp) &&
(!((cur_bpp==16) && (pfd.cColorBits==15))) &&
(!((cur_bpp==32) && (pfd.cColorBits==24)))) {
continue;
}
// We've passed all the tests, go ahead and pick this fmt.
// Note: could go continue looping looking for more alpha bits or
// more depth bits so this would pick 16bpp depth buffer, probably
// not 24bpp
break;
}
if (pfnum > MaxPixFmtNum) {
pfnum = 0;
}
return pfnum;
}

View File

@ -37,7 +37,13 @@ public:
static PT(GraphicsPipe) pipe_constructor();
protected:
virtual PT(GraphicsWindow) make_window();
virtual PT(GraphicsStateGuardian) make_gsg(const FrameBufferProperties &properties);
virtual PT(GraphicsWindow) make_window(GraphicsStateGuardian *gsg);
private:
int choose_pfnum(FrameBufferProperties &properties, HDC hdc) const;
int find_pixfmtnum(FrameBufferProperties &properties, HDC hdc,
bool bLookforHW) const;
public:
static TypeHandle get_class_type() {

View File

@ -15,3 +15,31 @@
// panda3d@yahoogroups.com .
//
////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////
// Function: wglGraphicsStateGuardian::get_pfnum
// Access: Public
// Description: Returns the pixel format number chosen for windows
// that use this context.
////////////////////////////////////////////////////////////////////
INLINE int wglGraphicsStateGuardian::
get_pfnum() const {
return _pfnum;
}
////////////////////////////////////////////////////////////////////
// Function: wglGraphicsStateGuardian::get_context
// Access: Public
// Description: Returns the GL context associated with the GSG. If
// the context has not yet been created, this creates a
// suitable context for rendering to the indicated
// window. This means that this method may only be
// called from within the draw thread.
////////////////////////////////////////////////////////////////////
INLINE HGLRC wglGraphicsStateGuardian::
get_context(HDC hdc) {
if (!_made_context) {
make_context(hdc);
}
return _context;
}

View File

@ -27,10 +27,13 @@ TypeHandle wglGraphicsStateGuardian::_type_handle;
// Description:
////////////////////////////////////////////////////////////////////
wglGraphicsStateGuardian::
wglGraphicsStateGuardian(const FrameBufferProperties &properties) :
GLGraphicsStateGuardian(properties)
wglGraphicsStateGuardian(const FrameBufferProperties &properties,
int pfnum) :
GLGraphicsStateGuardian(properties),
_pfnum(pfnum)
{
_context = (HGLRC)0;
_made_context = false;
_context = (HGLRC)NULL;
}
////////////////////////////////////////////////////////////////////
@ -45,3 +48,27 @@ wglGraphicsStateGuardian::
_context = (HGLRC)NULL;
}
}
////////////////////////////////////////////////////////////////////
// Function: wglGraphicsStateGuardian::make_context
// Access: Private
// Description: Creates a suitable context for rendering into the
// given window. This should only be called from the
// draw thread.
////////////////////////////////////////////////////////////////////
void wglGraphicsStateGuardian::
make_context(HDC hdc) {
// We should only call this once for a particular GSG.
nassertv(!_made_context);
_made_context = true;
// Attempt to create a context.
_context = wglCreateContext(hdc);
if (_context == NULL) {
wgldisplay_cat.error()
<< "Could not create GL context.\n";
return;
}
}

View File

@ -30,12 +30,18 @@
////////////////////////////////////////////////////////////////////
class wglGraphicsStateGuardian : public GLGraphicsStateGuardian {
public:
wglGraphicsStateGuardian(const FrameBufferProperties &properties);
wglGraphicsStateGuardian(const FrameBufferProperties &properties, int pfnum);
virtual ~wglGraphicsStateGuardian();
HGLRC _context;
INLINE int get_pfnum() const;
INLINE HGLRC get_context(HDC hdc);
private:
void make_context(HDC hdc);
bool _made_context;
int _pfnum;
PIXELFORMATDESCRIPTOR _pixelformat;
HGLRC _context;
public:
static TypeHandle get_class_type() {

View File

@ -25,9 +25,6 @@
#include <wingdi.h>
#include <ddraw.h>
typedef enum {Software, MCD, ICD} OGLDriverType;
static const char * const OGLDrvStrings[] = { "Software", "MCD", "ICD" };
TypeHandle wglGraphicsWindow::_type_handle;
static char *ConvDDErrorToString(const HRESULT &error);
@ -132,10 +129,9 @@ GetAvailVidMem() {
// Description:
////////////////////////////////////////////////////////////////////
wglGraphicsWindow::
wglGraphicsWindow(GraphicsPipe *pipe) :
WinGraphicsWindow(pipe)
wglGraphicsWindow(GraphicsPipe *pipe, GraphicsStateGuardian *gsg) :
WinGraphicsWindow(pipe, gsg)
{
_context = (HGLRC)0;
_hdc = (HDC)0;
}
@ -148,49 +144,6 @@ wglGraphicsWindow::
~wglGraphicsWindow() {
}
////////////////////////////////////////////////////////////////////
// Function: wglGraphicsWindow::make_gsg
// Access: Public, Virtual
// Description: Creates a new GSG for the window and stores it in the
// _gsg pointer. This should only be called from within
// the draw thread.
////////////////////////////////////////////////////////////////////
void wglGraphicsWindow::
make_gsg() {
nassertv(_gsg == (GraphicsStateGuardian *)NULL);
_context = wglCreateContext(_hdc);
if (!_context) {
wgldisplay_cat.error()
<< "Could not create GL context.\n";
return;
}
// And make sure the new context is current.
wglMakeCurrent(_hdc, _context);
// Now we can make a GSG.
_gsg = new GLGraphicsStateGuardian(this);
}
////////////////////////////////////////////////////////////////////
// Function: wglGraphicsWindow::release_gsg
// Access: Public, Virtual
// Description: Releases the current GSG pointer, if it is currently
// held, and resets the GSG to NULL. This should only
// be called from within the draw thread.
////////////////////////////////////////////////////////////////////
void wglGraphicsWindow::
release_gsg() {
if (_gsg != (GraphicsStateGuardian *)NULL) {
wglMakeCurrent(_hdc, _context);
GraphicsWindow::release_gsg();
wglDeleteContext(_context);
wglMakeCurrent(_hdc, NULL);
_context = (HGLRC)0;
}
}
////////////////////////////////////////////////////////////////////
// Function: wglGraphicsWindow::make_current
// Access: Public, Virtual
@ -200,8 +153,30 @@ release_gsg() {
////////////////////////////////////////////////////////////////////
void wglGraphicsWindow::
make_current() {
nassertv(_gsg != (GraphicsStateGuardian *)NULL);
wglMakeCurrent(_hdc, _context);
wglGraphicsStateGuardian *wglgsg;
DCAST_INTO_V(wglgsg, _gsg);
wglMakeCurrent(_hdc, wglgsg->get_context(_hdc));
// Now that we have made the context current to a window, we can
// reset the GSG state if this is the first time it has been used.
// (We can't just call reset() when we construct the GSG, because
// reset() requires having a current context.)
wglgsg->reset_if_new();
}
////////////////////////////////////////////////////////////////////
// Function: wglGraphicsWindow::release_gsg
// Access: Public, Virtual
// 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 wglGraphicsWindow::
release_gsg() {
wglMakeCurrent(_hdc, NULL);
GraphicsWindow::release_gsg();
}
////////////////////////////////////////////////////////////////////
@ -221,7 +196,7 @@ make_current() {
void wglGraphicsWindow::
begin_flip() {
if (_gsg != (GraphicsStateGuardian *)NULL) {
wglMakeCurrent(_hdc, _context);
make_current();
glFinish();
SwapBuffers(_hdc);
}
@ -235,7 +210,7 @@ begin_flip() {
////////////////////////////////////////////////////////////////////
void wglGraphicsWindow::
close_window() {
ReleaseDC(_mwindow, _hdc);
ReleaseDC(_hWnd, _hdc);
_hdc = (HDC)0;
WinGraphicsWindow::close_window();
}
@ -253,42 +228,31 @@ open_window() {
return false;
}
wglGraphicsStateGuardian *wglgsg;
DCAST_INTO_R(wglgsg, _gsg, false);
_hdc = GetDC(_hWnd);
// Set up the pixel format of the window appropriately for GL.
_hdc = GetDC(_mwindow);
int pfnum = wglgsg->get_pfnum();
int pfnum = choose_pfnum();
if (gl_force_pixfmt != 0) {
wgldisplay_cat.info()
<< "overriding pixfmt choice algorithm (" << pfnum
<< ") with gl-force-pixfmt(" << gl_force_pixfmt << ")\n";
pfnum = gl_force_pixfmt;
}
if (wgldisplay_cat.is_debug()) {
wgldisplay_cat.debug()
<< "config() - picking pixfmt #" << pfnum <<endl;
}
PIXELFORMATDESCRIPTOR pixelformat;
DescribePixelFormat(_hdc, pfnum, sizeof(PIXELFORMATDESCRIPTOR),
&_pixelformat);
&pixelformat);
#ifdef _DEBUG
char msg[200];
sprintf(msg, "Selected GL PixelFormat is #%d", pfnum);
print_pfd(&_pixelformat, msg);
print_pfd(&pixelformat, msg);
#endif
if (!SetPixelFormat(_hdc, pfnum, &_pixelformat)) {
if (!SetPixelFormat(_hdc, pfnum, &pixelformat)) {
wgldisplay_cat.error()
<< "SetPixelFormat(" << pfnum << ") failed after window create\n";
close_window();
return false;
}
// Initializes _colormap
setup_colormap();
#ifndef NDEBUG
if (gl_force_invalid) {
wgldisplay_cat.error()
@ -298,6 +262,9 @@ open_window() {
}
#endif // NDEBUG
// Initializes _colormap
setup_colormap(pixelformat);
return true;
}
@ -334,187 +301,6 @@ reconsider_fullscreen_size(DWORD &x_size, DWORD &y_size, DWORD &bitdepth) {
}
}
////////////////////////////////////////////////////////////////////
// Function: wglGraphicsWindow::choose_pfnum
// Access: Private
// Description: Selects a suitable pixel format number for the
// window, based on the requested properties.
////////////////////////////////////////////////////////////////////
int wglGraphicsWindow::
choose_pfnum() const {
int pfnum;
bool bUsingSoftware = false;
if (force_software_renderer) {
pfnum = find_pixfmtnum(false);
if (pfnum == 0) {
wgldisplay_cat.error()
<< "Couldn't find compatible software-renderer OpenGL pixfmt, check your window properties!\n";
return 0;
}
bUsingSoftware = true;
} else {
pfnum = find_pixfmtnum(true);
if (pfnum == 0) {
if (allow_software_renderer) {
pfnum = find_pixfmtnum(false);
if(pfnum == 0) {
wgldisplay_cat.error()
<< "Couldn't find HW or Software OpenGL pixfmt appropriate for this desktop!!\n";
}
} else {
wgldisplay_cat.error()
<< "Couldn't find HW-accelerated OpenGL pixfmt appropriate for this desktop!!\n";
}
if (pfnum == 0) {
wgldisplay_cat.error()
<< "make sure OpenGL driver is installed, and try reducing the screen size, reducing the\n"
<< "desktop screen pixeldepth to 16bpp,and check your panda window properties\n";
return 0;
}
bUsingSoftware=true;
}
}
if (bUsingSoftware) {
wgldisplay_cat.info()
<< "Couldn't find compatible OGL HW pixelformat, using software rendering.\n";
}
return pfnum;
}
////////////////////////////////////////////////////////////////////
// Function: wglGraphicsWindow::find_pixfmtnum
// Access: Private
// Description: This helper routine looks for either HW-only or
// SW-only format, but not both. Returns the
// pixelformat number, or 0 if a suitable format could
// not be found.
////////////////////////////////////////////////////////////////////
int wglGraphicsWindow::
find_pixfmtnum(bool bLookforHW) const {
int framebuffer_mode = _properties.get_framebuffer_mode();
bool want_depth_bits = _properties.has_depth_bits();
bool want_color_bits = _properties.has_color_bits();
OGLDriverType drvtype;
PIXELFORMATDESCRIPTOR pfd;
ZeroMemory(&pfd,sizeof(PIXELFORMATDESCRIPTOR));
pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR);
pfd.nVersion = 1;
// just use the pixfmt of the current desktop
int MaxPixFmtNum =
DescribePixelFormat(_hdc, 1, sizeof(PIXELFORMATDESCRIPTOR), &pfd);
int cur_bpp = GetDeviceCaps(_hdc,BITSPIXEL);
int pfnum;
for(pfnum = 1; pfnum <= MaxPixFmtNum; pfnum++) {
DescribePixelFormat(_hdc, pfnum, sizeof(PIXELFORMATDESCRIPTOR), &pfd);
// official, nvidia sanctioned way.
if ((pfd.dwFlags & PFD_GENERIC_FORMAT) != 0) {
drvtype = Software;
} else if (pfd.dwFlags & PFD_GENERIC_ACCELERATED) {
drvtype = MCD;
} else {
drvtype = ICD;
}
// skip driver types we are not looking for
if (bLookforHW) {
if (drvtype == Software) {
continue;
}
} else {
if (drvtype != Software) {
continue;
}
}
if ((pfd.iPixelType == PFD_TYPE_COLORINDEX) &&
(framebuffer_mode & WindowProperties::FM_index) == 0) {
continue;
}
DWORD dwReqFlags = (PFD_SUPPORT_OPENGL | PFD_DRAW_TO_WINDOW);
if (wgldisplay_cat.is_debug()) {
wgldisplay_cat->debug()
<< "----------------" << endl;
if ((framebuffer_mode & WindowProperties::FM_alpha) != 0) {
wgldisplay_cat->debug()
<< "want alpha, pfd says '"
<< (int)(pfd.cAlphaBits) << "'" << endl;
}
if ((framebuffer_mode & WindowProperties::FM_depth) != 0) {
wgldisplay_cat->debug()
<< "want depth, pfd says '"
<< (int)(pfd.cDepthBits) << "'" << endl;
}
if ((framebuffer_mode & WindowProperties::FM_stencil) != 0) {
wgldisplay_cat->debug()
<< "want stencil, pfd says '"
<< (int)(pfd.cStencilBits) << "'" << endl;
}
wgldisplay_cat->debug()
<< "final flag check " << (int)(pfd.dwFlags & dwReqFlags) << " =? "
<< (int)dwReqFlags << endl;
wgldisplay_cat->debug()
<< "pfd bits = " << (int)(pfd.cColorBits) << endl;
wgldisplay_cat->debug()
<< "cur_bpp = " << cur_bpp << endl;
}
if ((framebuffer_mode & WindowProperties::FM_double_buffer) != 0) {
dwReqFlags|= PFD_DOUBLEBUFFER;
}
if ((framebuffer_mode & WindowProperties::FM_alpha) != 0 &&
(pfd.cAlphaBits==0)) {
continue;
}
if ((framebuffer_mode & WindowProperties::FM_depth) != 0 &&
(pfd.cDepthBits==0)) {
continue;
}
if ((framebuffer_mode & WindowProperties::FM_stencil) != 0 &&
(pfd.cStencilBits==0)) {
continue;
}
if ((pfd.dwFlags & dwReqFlags) != dwReqFlags) {
continue;
}
// now we ignore the specified want_color_bits for windowed mode
// instead we use the current screen depth
if ((pfd.cColorBits!=cur_bpp) &&
(!((cur_bpp==16) && (pfd.cColorBits==15))) &&
(!((cur_bpp==32) && (pfd.cColorBits==24)))) {
continue;
}
// We've passed all the tests, go ahead and pick this fmt.
// Note: could go continue looping looking for more alpha bits or
// more depth bits so this would pick 16bpp depth buffer, probably
// not 24bpp
break;
}
if (pfnum > MaxPixFmtNum) {
pfnum = 0;
}
return pfnum;
}
////////////////////////////////////////////////////////////////////
// Function: wglGraphicsWindow::setup_colormap
// Access: Private
@ -523,21 +309,15 @@ find_pixfmtnum(bool bLookforHW) const {
// creating a GL context.
////////////////////////////////////////////////////////////////////
void wglGraphicsWindow::
setup_colormap() {
PIXELFORMATDESCRIPTOR pfd;
setup_colormap(const PIXELFORMATDESCRIPTOR &pixelformat) {
LOGPALETTE *logical;
int n;
/* grab the pixel format */
memset(&pfd, 0, sizeof(PIXELFORMATDESCRIPTOR));
DescribePixelFormat(_hdc, GetPixelFormat(_hdc),
sizeof(PIXELFORMATDESCRIPTOR), &pfd);
if (!(pfd.dwFlags & PFD_NEED_PALETTE ||
pfd.iPixelType == PFD_TYPE_COLORINDEX))
if (!(pixelformat.dwFlags & PFD_NEED_PALETTE ||
pixelformat.iPixelType == PFD_TYPE_COLORINDEX))
return;
n = 1 << pfd.cColorBits;
n = 1 << pixelformat.cColorBits;
/* allocate a bunch of memory for the logical palette (assume 256
colors in a Win32 palette */
@ -552,20 +332,20 @@ setup_colormap() {
/* start with a copy of the current system palette */
GetSystemPaletteEntries(_hdc, 0, 256, &logical->palPalEntry[0]);
if (pfd.iPixelType == PFD_TYPE_RGBA) {
int redMask = (1 << pfd.cRedBits) - 1;
int greenMask = (1 << pfd.cGreenBits) - 1;
int blueMask = (1 << pfd.cBlueBits) - 1;
if (pixelformat.iPixelType == PFD_TYPE_RGBA) {
int redMask = (1 << pixelformat.cRedBits) - 1;
int greenMask = (1 << pixelformat.cGreenBits) - 1;
int blueMask = (1 << pixelformat.cBlueBits) - 1;
int i;
/* fill in an RGBA color palette */
for (i = 0; i < n; ++i) {
logical->palPalEntry[i].peRed =
(((i >> pfd.cRedShift) & redMask) * 255) / redMask;
(((i >> pixelformat.cRedShift) & redMask) * 255) / redMask;
logical->palPalEntry[i].peGreen =
(((i >> pfd.cGreenShift) & greenMask) * 255) / greenMask;
(((i >> pixelformat.cGreenShift) & greenMask) * 255) / greenMask;
logical->palPalEntry[i].peBlue =
(((i >> pfd.cBlueShift) & blueMask) * 255) / blueMask;
(((i >> pixelformat.cBlueShift) & blueMask) * 255) / blueMask;
logical->palPalEntry[i].peFlags = 0;
}
}

View File

@ -29,12 +29,11 @@
////////////////////////////////////////////////////////////////////
class EXPCL_PANDAGL wglGraphicsWindow : public WinGraphicsWindow {
public:
wglGraphicsWindow(GraphicsPipe *pipe);
wglGraphicsWindow(GraphicsPipe *pipe, GraphicsStateGuardian *gsg);
virtual ~wglGraphicsWindow();
virtual void make_gsg();
virtual void release_gsg();
virtual void make_current();
virtual void release_gsg();
virtual void begin_flip();
@ -45,17 +44,13 @@ protected:
DWORD &bitdepth);
private:
int choose_pfnum() const;
int find_pixfmtnum(bool bLookforHW) const;
void setup_colormap();
void setup_colormap(const PIXELFORMATDESCRIPTOR &pixelformat);
#ifdef _DEBUG
static void print_pfd(PIXELFORMATDESCRIPTOR *pfd, char *msg);
#endif
HGLRC _context;
HDC _hdc;
PIXELFORMATDESCRIPTOR _pixelformat;
HPALETTE _colormap;
public:

View File

@ -1,4 +1,5 @@
#include "config_wgldisplay.cxx"
#include "wglGraphicsPipe.cxx"
#include "wglGraphicsStateGuardian.cxx"
#include "wglGraphicsWindow.cxx"

View File

@ -51,3 +51,21 @@ WinGraphicsPipe::
_hUser32 = NULL;
}
}
bool MyGetProcAddr(HINSTANCE hDLL, FARPROC *pFn, const char *szExportedFnName) {
*pFn = (FARPROC) GetProcAddress(hDLL, szExportedFnName);
if (*pFn == NULL) {
windisplay_cat.error() << "GetProcAddr failed for " << szExportedFnName << ", error=" << GetLastError() <<endl;
return false;
}
return true;
}
bool MyLoadLib(HINSTANCE &hDLL, const char *DLLname) {
hDLL = LoadLibrary(DLLname);
if(hDLL == NULL) {
windisplay_cat.error() << "LoadLibrary failed for " << DLLname << ", error=" << GetLastError() <<endl;
return false;
}
return true;
}

View File

@ -66,6 +66,9 @@ private:
friend class WinGraphicsWindow;
};
extern EXPCL_PANDAWIN bool MyLoadLib(HINSTANCE &hDLL, const char *DLLname);
extern EXPCL_PANDAWIN bool MyGetProcAddr(HINSTANCE hDLL, FARPROC *pFn, const char *szExportedFnName);
#include "winGraphicsPipe.I"
#endif

View File

@ -17,27 +17,6 @@
////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////
// Function: WinGraphicsWindow::handle_mouse_motion
// Access: Private
// Description:
////////////////////////////////////////////////////////////////////
INLINE void WinGraphicsWindow::
handle_mouse_motion(int x, int y) {
_input_devices[0].set_pointer_in_window(x, y);
}
////////////////////////////////////////////////////////////////////
// Function: WinGraphicsWindow::handle_mouse_exit
// Access: Private
// Description:
////////////////////////////////////////////////////////////////////
INLINE void WinGraphicsWindow::
handle_mouse_exit() {
// note: 'mouse_motion' is considered the 'entry' event
_input_devices[0].set_pointer_out_of_window();
}
////////////////////////////////////////////////////////////////////
// Function: WinGraphicsWindow::handle_keypress
// Access: Private

View File

@ -56,13 +56,13 @@ static const char * const errorbox_title = "Panda3D Error";
// Description:
////////////////////////////////////////////////////////////////////
WinGraphicsWindow::
WinGraphicsWindow(GraphicsPipe *pipe) :
GraphicsWindow(pipe)
WinGraphicsWindow(GraphicsPipe *pipe, GraphicsStateGuardian *gsg) :
GraphicsWindow(pipe, gsg)
{
GraphicsWindowInputDevice device =
GraphicsWindowInputDevice::pointer_and_keyboard("keyboard/mouse");
GraphicsWindowInputDevice::pointer_and_keyboard("keyboard/mouse");
_input_devices.push_back(device);
_mwindow = (HWND)0;
_hWnd = (HWND)0;
_ime_open = false;
_ime_active = false;
_ime_composition_w = false;
@ -174,11 +174,11 @@ set_properties_now(WindowProperties &properties) {
void WinGraphicsWindow::
close_window() {
set_cursor_out_of_window();
DestroyWindow(_mwindow);
DestroyWindow(_hWnd);
// Remove the window handle from our global map.
_window_handles.erase(_mwindow);
_mwindow = (HWND)0;
_window_handles.erase(_hWnd);
_hWnd = (HWND)0;
if (is_fullscreen()) {
// revert to default display mode.
@ -214,17 +214,17 @@ open_window() {
// Now that we have a window handle, store it in our global map, so
// future messages for this window can be routed properly.
_window_handles.insert(WindowHandles::value_type(_mwindow, this));
_window_handles.insert(WindowHandles::value_type(_hWnd, this));
// move window to top of zorder.
SetWindowPos(_mwindow, HWND_TOP, 0,0,0,0,
SetWindowPos(_hWnd, HWND_TOP, 0,0,0,0,
SWP_NOMOVE | SWP_NOSENDCHANGING | SWP_NOSIZE);
// need to do twice to override any minimized flags in StartProcessInfo
ShowWindow(_mwindow, SW_SHOWNORMAL);
ShowWindow(_mwindow, SW_SHOWNORMAL);
ShowWindow(_hWnd, SW_SHOWNORMAL);
ShowWindow(_hWnd, SW_SHOWNORMAL);
if (!SetForegroundWindow(_mwindow)) {
if (!SetForegroundWindow(_hWnd)) {
windisplay_cat.warning()
<< "SetForegroundWindow() failed!\n";
}
@ -232,10 +232,10 @@ open_window() {
// Determine the initial open status of the IME.
_ime_open = false;
_ime_active = false;
HIMC hIMC = ImmGetContext(_mwindow);
HIMC hIMC = ImmGetContext(_hWnd);
if (hIMC != 0) {
_ime_open = (ImmGetOpenStatus(hIMC) != 0);
ImmReleaseContext(_mwindow, hIMC);
ImmReleaseContext(_hWnd, hIMC);
}
// Check the version of the OS we are running. If we are running
@ -323,10 +323,10 @@ do_reshape_request(int x_origin, int y_origin, int x_size, int y_size) {
SetRect(&view_rect, x_origin, y_origin,
x_origin + x_size, y_origin + y_size);
WINDOWINFO wi;
GetWindowInfo(_mwindow, &wi);
GetWindowInfo(_hWnd, &wi);
AdjustWindowRectEx(&view_rect, wi.dwStyle, false, wi.dwExStyle);
SetWindowPos(_mwindow, NULL, view_rect.left, view_rect.top,
SetWindowPos(_hWnd, NULL, view_rect.left, view_rect.top,
view_rect.right - view_rect.left,
view_rect.bottom - view_rect.top,
SWP_NOZORDER | SWP_NOMOVE | SWP_NOSENDCHANGING);
@ -353,9 +353,9 @@ do_reshape_request(int x_origin, int y_origin, int x_size, int y_size) {
void WinGraphicsWindow::
handle_reshape() {
RECT view_rect;
GetClientRect(_mwindow, &view_rect);
ClientToScreen(_mwindow, (POINT*)&view_rect.left); // translates top,left pnt
ClientToScreen(_mwindow, (POINT*)&view_rect.right); // translates right,bottom pnt
GetClientRect(_hWnd, &view_rect);
ClientToScreen(_hWnd, (POINT*)&view_rect.left); // translates top,left pnt
ClientToScreen(_hWnd, (POINT*)&view_rect.right); // translates right,bottom pnt
WindowProperties properties;
properties.set_size((view_rect.right - view_rect.left),
@ -403,7 +403,7 @@ do_fullscreen_resize(int x_size, int y_size) {
}
// this causes WM_SIZE msg to be produced
SetWindowPos(_mwindow, NULL, 0,0, x_size, y_size,
SetWindowPos(_hWnd, NULL, 0,0, x_size, y_size,
SWP_NOZORDER | SWP_NOMOVE | SWP_NOSENDCHANGING);
int chg_result = ChangeDisplaySettings(&dm, CDS_FULLSCREEN);
@ -437,32 +437,6 @@ void WinGraphicsWindow::
reconsider_fullscreen_size(DWORD &, DWORD &, DWORD &) {
}
////////////////////////////////////////////////////////////////////
// Function: WinGraphicsWindow::get_client_rect_screen
// Access: Protected
// Description: Fills view_rect with the coordinates of the client
// area of the indicated window, converted to screen
// coordinates.
////////////////////////////////////////////////////////////////////
void WinGraphicsWindow::
get_client_rect_screen(HWND hwnd, RECT *view_rect) {
GetClientRect(hwnd, view_rect);
POINT ul, lr;
ul.x = view_rect->left;
ul.y = view_rect->top;
lr.x = view_rect->right;
lr.y = view_rect->bottom;
ClientToScreen(hwnd, &ul);
ClientToScreen(hwnd, &lr);
view_rect->left = ul.x;
view_rect->top = ul.y;
view_rect->right = lr.x;
view_rect->bottom = lr.y;
}
////////////////////////////////////////////////////////////////////
// Function: WinGraphicsWindow::open_fullscreen_window
// Access: Private
@ -516,10 +490,10 @@ open_fullscreen_window() {
// up the desktop during the mode change
register_window_class();
HINSTANCE hinstance = GetModuleHandle(NULL);
_mwindow = CreateWindow(_window_class_name, title.c_str(), window_style,
_hWnd = CreateWindow(_window_class_name, title.c_str(), window_style,
0, 0, dwWidth, dwHeight,
hDesktopWindow, NULL, hinstance, 0);
if (!_mwindow) {
if (!_hWnd) {
windisplay_cat.error()
<< "CreateWindow() failed!" << endl;
show_error_message();
@ -601,13 +575,13 @@ open_regular_window() {
register_window_class();
HINSTANCE hinstance = GetModuleHandle(NULL);
_mwindow = CreateWindow(_window_class_name, title.c_str(), window_style,
_hWnd = CreateWindow(_window_class_name, title.c_str(), window_style,
win_rect.left, win_rect.top,
win_rect.right - win_rect.left,
win_rect.bottom - win_rect.top,
NULL, NULL, hinstance, 0);
if (!_mwindow) {
if (!_hWnd) {
windisplay_cat.error()
<< "CreateWindow() failed!" << endl;
show_error_message();
@ -672,342 +646,373 @@ window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) {
int button = -1;
switch (msg) {
case WM_MOUSEMOVE:
if (!_tracking_mouse_leaving) {
// need to re-call TrackMouseEvent every time mouse re-enters window
track_mouse_leaving(hwnd);
}
set_cursor_in_window();
handle_mouse_motion(translate_mouse(LOWORD(lparam)),
translate_mouse(HIWORD(lparam)));
break;
case WM_MOUSELEAVE:
_tracking_mouse_leaving = false;
handle_mouse_exit();
set_cursor_out_of_window();
break;
case WM_CREATE:
track_mouse_leaving(hwnd);
// Assume the mouse cursor is within the window initially. It
// remains to be seen whether this is assumption does any harm.
set_cursor_in_window();
break;
case WM_CLOSE:
properties.set_open(false);
system_changed_properties(properties);
// TODO: make sure we release the GSG properly.
break;
case WM_ACTIVATE:
properties.set_minimized((wparam & 0xffff0000) != 0);
if ((wparam & 0xffff) != WA_INACTIVE) {
properties.set_foreground(true);
if (is_fullscreen()) {
// When a fullscreen window goes active, it automatically gets
// un-minimized.
ChangeDisplaySettings(&_fullscreen_display_mode, CDS_FULLSCREEN);
GdiFlush();
SetWindowPos(_mwindow, HWND_TOP, 0,0,0,0,
SWP_NOMOVE | SWP_NOSENDCHANGING | SWP_NOSIZE | SWP_NOOWNERZORDER);
fullscreen_restored(properties);
}
} else {
properties.set_foreground(false);
if (is_fullscreen()) {
// When a fullscreen window goes inactive, it automatically
// gets minimized.
properties.set_minimized(true);
// It seems order is important here. We must minimize the
// window before restoring the display settings, or risk
// losing the graphics context.
ShowWindow(_mwindow, SW_MINIMIZE);
GdiFlush();
ChangeDisplaySettings(NULL, 0x0);
fullscreen_minimized(properties);
}
}
system_changed_properties(properties);
break;
case WM_SIZE:
// for maximized, unmaximize, need to call resize code
// artificially since no WM_EXITSIZEMOVE is generated.
if (wparam == SIZE_MAXIMIZED) {
_maximized = true;
handle_reshape();
} else if (wparam == SIZE_RESTORED && _maximized) {
// SIZE_RESTORED might mean we restored to its original size
// before the maximize, but it might also be called while the
// user is resizing the window by hand. Checking the _maximized
// flag that we set above allows us to differentiate the two
// cases.
_maximized = false;
handle_reshape();
}
break;
case WM_EXITSIZEMOVE:
handle_reshape();
break;
case WM_LBUTTONDOWN:
button = 0;
// fall through
case WM_MBUTTONDOWN:
if (button < 0) {
button = 1;
}
// fall through
case WM_RBUTTONDOWN:
if (button < 0) {
button = 2;
}
SetCapture(hwnd);
handle_keypress(MouseButton::button(button),
translate_mouse(LOWORD(lparam)), translate_mouse(HIWORD(lparam)));
break;
case WM_LBUTTONUP:
button = 0;
// fall through
case WM_MBUTTONUP:
if (button < 0) {
button = 1;
}
// fall through
case WM_RBUTTONUP:
if (button < 0) {
button = 2;
}
ReleaseCapture();
handle_keyrelease(MouseButton::button(button));
break;
case WM_IME_NOTIFY:
if (wparam == IMN_SETOPENSTATUS) {
HIMC hIMC = ImmGetContext(hwnd);
nassertr(hIMC != 0, 0);
_ime_open = (ImmGetOpenStatus(hIMC) != 0);
if (!_ime_open) {
_ime_active = false; // Sanity enforcement.
}
ImmReleaseContext(hwnd, hIMC);
}
break;
case WM_IME_STARTCOMPOSITION:
_ime_active = true;
break;
case WM_IME_ENDCOMPOSITION:
_ime_active = false;
break;
case WM_IME_COMPOSITION:
if (lparam & GCS_RESULTSTR) {
HIMC hIMC = ImmGetContext(hwnd);
nassertr(hIMC != 0, 0);
static const int max_ime_result = 128;
static char ime_result[max_ime_result];
if (_ime_composition_w) {
// Since ImmGetCompositionStringA() doesn't seem to work
// for Win2000 (it always returns question mark
// characters), we have to use ImmGetCompositionStringW()
// on this OS. This is actually the easier of the two
// functions to use.
DWORD result_size =
ImmGetCompositionStringW(hIMC, GCS_RESULTSTR,
ime_result, max_ime_result);
// Add this string into the text buffer of the application.
// ImmGetCompositionStringW() returns a string, but it's
// filled in with wstring data: every two characters defines a
// 16-bit unicode char. The docs aren't clear on the
// endianness of this. I guess it's safe to assume all Win32
// machines are little-endian.
for (DWORD i = 0; i < result_size; i += 2) {
int result =
((int)(unsigned char)ime_result[i + 1] << 8) |
(unsigned char)ime_result[i];
_input_devices[0].keystroke(result);
case WM_MOUSEMOVE:
if (!_tracking_mouse_leaving) {
// need to re-call TrackMouseEvent every time mouse re-enters window
track_mouse_leaving(hwnd);
}
} else {
// On the other hand, ImmGetCompositionStringW() doesn't
// work on Win95 or Win98; for these OS's we must use
// ImmGetCompositionStringA().
DWORD result_size =
ImmGetCompositionStringA(hIMC, GCS_RESULTSTR,
ime_result, max_ime_result);
// ImmGetCompositionStringA() returns an encoded ANSI
// string, which we now have to map to wide-character
// Unicode.
static const int max_wide_result = 128;
static wchar_t wide_result[max_wide_result];
int wide_size =
MultiByteToWideChar(CP_ACP, 0,
ime_result, result_size,
wide_result, max_wide_result);
if (wide_size == 0) {
show_error_message();
}
for (int i = 0; i < wide_size; i++) {
_input_devices[0].keystroke(wide_result[i]);
}
}
ImmReleaseContext(hwnd, hIMC);
return 0;
}
break;
set_cursor_in_window();
if(handle_mouse_motion(translate_mouse(LOWORD(lparam)), translate_mouse(HIWORD(lparam))))
return 0;
break;
case WM_CHAR:
// Ignore WM_CHAR messages if we have the IME open, since
// everything will come in through WM_IME_COMPOSITION. (It's
// supposed to come in through WM_CHAR, too, but there seems to
// be a bug in Win2000 in that it only sends question mark
// characters through here.)
if (!_ime_open) {
_input_devices[0].keystroke(wparam);
}
break;
case WM_SYSKEYDOWN:
{
// Alt and F10 are sent as WM_SYSKEYDOWN instead of WM_KEYDOWN
// want to use defwindproc on Alt syskey so std windows cmd
// Alt-F4 works, etc
POINT point;
GetCursorPos(&point);
ScreenToClient(hwnd, &point);
handle_keypress(lookup_key(wparam), point.x, point.y);
if (wparam == VK_F10) {
// bypass default windproc F10 behavior (it activates the main
// menu, but we have none)
return 0;
}
}
break;
case WM_SYSCOMMAND:
if (wparam == SC_KEYMENU) {
// if Alt is released (alone w/o other keys), defwindproc will
// send this command, which will 'activate' the title bar menu
// (we have none) and give focus to it. we dont want this to
// happen, so kill this msg
return 0;
}
break;
case WM_MOUSELEAVE:
_tracking_mouse_leaving = false;
handle_mouse_exit();
set_cursor_out_of_window();
break;
case WM_KEYDOWN:
{
POINT point;
GetCursorPos(&point);
ScreenToClient(hwnd, &point);
handle_keypress(lookup_key(wparam), point.x, point.y);
// Handle Cntrl-V paste from clipboard. Is there a better way
// to detect this hotkey?
if ((wparam=='V') && (GetKeyState(VK_CONTROL) < 0) &&
!_input_devices.empty()) {
HGLOBAL hglb;
char *lptstr;
if (IsClipboardFormatAvailable(CF_TEXT) && OpenClipboard(NULL)) {
// Maybe we should support CF_UNICODETEXT if it is available
// too?
hglb = GetClipboardData(CF_TEXT);
if (hglb!=NULL) {
lptstr = (char *) GlobalLock(hglb);
if (lptstr != NULL) {
char *pChar;
for (pChar=lptstr; *pChar!=NULL; pChar++) {
_input_devices[0].keystroke((uchar)*pChar);
}
GlobalUnlock(hglb);
// if cursor is invisible, make it visible when moving in the window bars & menus, so user can use click in them
case WM_NCMOUSEMOVE: {
if(!_properties.get_cursor_hidden()) {
if(!_bCursor_in_WindowClientArea) {
// SetCursor(_pParentWindowGroup->_hMouseCursor);
ShowCursor(true);
_bCursor_in_WindowClientArea=true;
}
}
}
CloseClipboard();
}
break;
}
}
break;
case WM_SYSKEYUP:
case WM_KEYUP:
handle_keyrelease(lookup_key(wparam));
break;
case WM_KILLFOCUS:
// Record the current state of the keyboard when the focus is
// lost, so we can check it for changes when we regain focus.
GetKeyboardState(_keyboard_state);
break;
case WM_SETFOCUS:
{
// When we lose focus, the app may miss key-up events for keys
// that were formerly held down (and vice-versa). Therefore,
// when focus is regained, compare the state of the keyboard to
// the last known state (stored above, when focus was lost) to
// regenerate the lost keyboard events.
if (GetForegroundWindow() != _mwindow) {
// Sometimes, particularly on window create, it appears we get
// a WM_SETFOCUS event even though the window hasn't really
// received focus yet. That's bad and confuses the
// GetKeyboardState logic, below. The above check filters out
// this case (while testing GetFocus() instead of
// GetForegroundWindow() doesn't).
windisplay_cat.debug()
<< "Got incorrect WM_SETFOCUS\n";
case WM_NCMOUSELEAVE: {
if(!_properties.get_cursor_hidden()) {
ShowCursor(false);
// SetCursor(NULL);
_bCursor_in_WindowClientArea=false;
}
break;
}
case WM_CREATE: {
track_mouse_leaving(hwnd);
_bCursor_in_WindowClientArea=false;
ClearToBlack(hwnd,_properties);
POINT cpos;
GetCursorPos(&cpos);
ScreenToClient(hwnd,&cpos);
RECT clientRect;
GetClientRect(hwnd, &clientRect);
if(PtInRect(&clientRect,cpos))
set_cursor_in_window(); // should window focus be true as well?
else set_cursor_out_of_window();
break;
}
BYTE new_keyboard_state[num_virtual_keys];
GetKeyboardState(new_keyboard_state);
for (int i = 0; i < num_virtual_keys; i++) {
// Filter out these particular three. We don't want to test
// these, because these are virtual duplicates for
// VK_LSHIFT/VK_RSHIFT, etc.; and the left/right equivalent is
// also in the table. If we respect both VK_LSHIFT as well as
// VK_SHIFT, we'll generate two keyboard messages when
// VK_LSHIFT changes state.
if (i != VK_SHIFT && i != VK_CONTROL && i != VK_MENU) {
if (((new_keyboard_state[i] ^ _keyboard_state[i]) & 0x80) != 0) {
// This key has changed state.
if ((new_keyboard_state[i] & 0x80) != 0) {
// The key is now held down.
handle_keyresume(lookup_key(i));
} else {
// The key is now released.
handle_keyrelease(lookup_key(i));
case WM_CLOSE:
properties.set_open(false);
system_changed_properties(properties);
// TODO: make sure we release the GSG properly.
break;
case WM_ACTIVATE:
properties.set_minimized((wparam & 0xffff0000) != 0);
if ((wparam & 0xffff) != WA_INACTIVE) {
properties.set_foreground(true);
if (is_fullscreen()) {
// When a fullscreen window goes active, it automatically gets
// un-minimized.
ChangeDisplaySettings(&_fullscreen_display_mode, CDS_FULLSCREEN);
GdiFlush();
SetWindowPos(_hWnd, HWND_TOP, 0,0,0,0,
SWP_NOMOVE | SWP_NOSENDCHANGING | SWP_NOSIZE | SWP_NOOWNERZORDER);
fullscreen_restored(properties);
}
} else {
properties.set_foreground(false);
if (is_fullscreen()) {
// When a fullscreen window goes inactive, it automatically
// gets minimized.
properties.set_minimized(true);
// It seems order is important here. We must minimize the
// window before restoring the display settings, or risk
// losing the graphics context.
ShowWindow(_hWnd, SW_MINIMIZE);
GdiFlush();
ChangeDisplaySettings(NULL, 0x0);
fullscreen_minimized(properties);
}
}
system_changed_properties(properties);
break;
case WM_SIZE:
// for maximized, unmaximize, need to call resize code
// artificially since no WM_EXITSIZEMOVE is generated.
if (wparam == SIZE_MAXIMIZED) {
_maximized = true;
handle_reshape();
} else if (wparam == SIZE_RESTORED && _maximized) {
// SIZE_RESTORED might mean we restored to its original size
// before the maximize, but it might also be called while the
// user is resizing the window by hand. Checking the _maximized
// flag that we set above allows us to differentiate the two
// cases.
_maximized = false;
handle_reshape();
}
break;
case WM_EXITSIZEMOVE:
handle_reshape();
break;
case WM_LBUTTONDOWN:
button = 0;
// fall through
case WM_MBUTTONDOWN:
if (button < 0) {
button = 1;
}
// fall through
case WM_RBUTTONDOWN:
if (button < 0) {
button = 2;
}
SetCapture(hwnd);
handle_keypress(MouseButton::button(button),
translate_mouse(LOWORD(lparam)), translate_mouse(HIWORD(lparam)));
break;
case WM_LBUTTONUP:
button = 0;
// fall through
case WM_MBUTTONUP:
if (button < 0) {
button = 1;
}
// fall through
case WM_RBUTTONUP:
if (button < 0) {
button = 2;
}
ReleaseCapture();
handle_keyrelease(MouseButton::button(button));
break;
case WM_IME_NOTIFY:
if (wparam == IMN_SETOPENSTATUS) {
HIMC hIMC = ImmGetContext(hwnd);
nassertr(hIMC != 0, 0);
_ime_open = (ImmGetOpenStatus(hIMC) != 0);
if (!_ime_open) {
_ime_active = false; // Sanity enforcement.
}
ImmReleaseContext(hwnd, hIMC);
}
break;
case WM_IME_STARTCOMPOSITION:
_ime_active = true;
break;
case WM_IME_ENDCOMPOSITION:
_ime_active = false;
break;
case WM_IME_COMPOSITION:
if (lparam & GCS_RESULTSTR) {
HIMC hIMC = ImmGetContext(hwnd);
nassertr(hIMC != 0, 0);
static const int max_ime_result = 128;
static char ime_result[max_ime_result];
if (_ime_composition_w) {
// Since ImmGetCompositionStringA() doesn't seem to work
// for Win2000 (it always returns question mark
// characters), we have to use ImmGetCompositionStringW()
// on this OS. This is actually the easier of the two
// functions to use.
DWORD result_size =
ImmGetCompositionStringW(hIMC, GCS_RESULTSTR,
ime_result, max_ime_result);
// Add this string into the text buffer of the application.
// ImmGetCompositionStringW() returns a string, but it's
// filled in with wstring data: every two characters defines a
// 16-bit unicode char. The docs aren't clear on the
// endianness of this. I guess it's safe to assume all Win32
// machines are little-endian.
for (DWORD i = 0; i < result_size; i += 2) {
int result =
((int)(unsigned char)ime_result[i + 1] << 8) |
(unsigned char)ime_result[i];
_input_devices[0].keystroke(result);
}
} else {
// On the other hand, ImmGetCompositionStringW() doesn't
// work on Win95 or Win98; for these OS's we must use
// ImmGetCompositionStringA().
DWORD result_size =
ImmGetCompositionStringA(hIMC, GCS_RESULTSTR,
ime_result, max_ime_result);
// ImmGetCompositionStringA() returns an encoded ANSI
// string, which we now have to map to wide-character
// Unicode.
static const int max_wide_result = 128;
static wchar_t wide_result[max_wide_result];
int wide_size =
MultiByteToWideChar(CP_ACP, 0,
ime_result, result_size,
wide_result, max_wide_result);
if (wide_size == 0) {
show_error_message();
}
for (int i = 0; i < wide_size; i++) {
_input_devices[0].keystroke(wide_result[i]);
}
}
ImmReleaseContext(hwnd, hIMC);
return 0;
}
break;
case WM_CHAR:
// Ignore WM_CHAR messages if we have the IME open, since
// everything will come in through WM_IME_COMPOSITION. (It's
// supposed to come in through WM_CHAR, too, but there seems to
// be a bug in Win2000 in that it only sends question mark
// characters through here.)
if (!_ime_open) {
_input_devices[0].keystroke(wparam);
}
break;
case WM_SYSKEYDOWN:
{
// Alt and F10 are sent as WM_SYSKEYDOWN instead of WM_KEYDOWN
// want to use defwindproc on Alt syskey so std windows cmd
// Alt-F4 works, etc
POINT point;
GetCursorPos(&point);
ScreenToClient(hwnd, &point);
handle_keypress(lookup_key(wparam), point.x, point.y);
if (wparam == VK_F10) {
// bypass default windproc F10 behavior (it activates the main
// menu, but we have none)
return 0;
}
}
break;
case WM_SYSCOMMAND:
if (wparam == SC_KEYMENU) {
// if Alt is released (alone w/o other keys), defwindproc will
// send this command, which will 'activate' the title bar menu
// (we have none) and give focus to it. we dont want this to
// happen, so kill this msg
return 0;
}
break;
case WM_KEYDOWN:
{
POINT point;
GetCursorPos(&point);
ScreenToClient(hwnd, &point);
handle_keypress(lookup_key(wparam), point.x, point.y);
// Handle Cntrl-V paste from clipboard. Is there a better way
// to detect this hotkey?
if ((wparam=='V') && (GetKeyState(VK_CONTROL) < 0) &&
!_input_devices.empty()) {
HGLOBAL hglb;
char *lptstr;
if (IsClipboardFormatAvailable(CF_TEXT) && OpenClipboard(NULL)) {
// Maybe we should support CF_UNICODETEXT if it is available
// too?
hglb = GetClipboardData(CF_TEXT);
if (hglb!=NULL) {
lptstr = (char *) GlobalLock(hglb);
if (lptstr != NULL) {
char *pChar;
for (pChar=lptstr; *pChar!=NULL; pChar++) {
_input_devices[0].keystroke((uchar)*pChar);
}
GlobalUnlock(hglb);
}
}
CloseClipboard();
}
}
}
}
// Save the new keyboard state, just for good measure. This
// really shouldn't be necessary, but it protects against
// inadvertently getting WM_SETFOCUS twice in a row, for
// instance.
memcpy(_keyboard_state, new_keyboard_state,
sizeof(BYTE) * num_virtual_keys);
}
break;
break;
case WM_SYSKEYUP:
case WM_KEYUP:
handle_keyrelease(lookup_key(wparam));
break;
case WM_KILLFOCUS:
// Record the current state of the keyboard when the focus is
// lost, so we can check it for changes when we regain focus.
GetKeyboardState(_keyboard_state);
break;
case WM_SETFOCUS:
{
// When we lose focus, the app may miss key-up events for keys
// that were formerly held down (and vice-versa). Therefore,
// when focus is regained, compare the state of the keyboard to
// the last known state (stored above, when focus was lost) to
// regenerate the lost keyboard events.
if (GetForegroundWindow() != _hWnd) {
// Sometimes, particularly on window create, it appears we get
// a WM_SETFOCUS event even though the window hasn't really
// received focus yet. That's bad and confuses the
// GetKeyboardState logic, below. The above check filters out
// this case (while testing GetFocus() instead of
// GetForegroundWindow() doesn't).
if(windisplay_cat.is_debug())
windisplay_cat.debug() << "Ignoring non-foreground WM_SETFOCUS\n";
break;
}
BYTE new_keyboard_state[num_virtual_keys];
GetKeyboardState(new_keyboard_state);
for (int i = 0; i < num_virtual_keys; i++) {
// Filter out these particular three. We don't want to test
// these, because these are virtual duplicates for
// VK_LSHIFT/VK_RSHIFT, etc.; and the left/right equivalent is
// also in the table. If we respect both VK_LSHIFT as well as
// VK_SHIFT, we'll generate two keyboard messages when
// VK_LSHIFT changes state.
if (i != VK_SHIFT && i != VK_CONTROL && i != VK_MENU) {
if (((new_keyboard_state[i] ^ _keyboard_state[i]) & 0x80) != 0) {
// This key has changed state.
if ((new_keyboard_state[i] & 0x80) != 0) {
// The key is now held down.
// cerr << "key is down: " << lookup_key(i) << "\n";
handle_keyresume(lookup_key(i));
} else {
// The key is now released.
handle_keyrelease(lookup_key(i));
}
}
}
}
// Save the new keyboard state, just for good measure. This
// really shouldn't be necessary, but it protects against
// inadvertently getting WM_SETFOCUS twice in a row, for
// instance.
memcpy(_keyboard_state, new_keyboard_state,
sizeof(BYTE) * num_virtual_keys);
}
break;
}
return DefWindowProc(hwnd, msg, wparam, lparam);
@ -1370,3 +1375,90 @@ lookup_key(WPARAM wparam) const {
}
return ButtonHandle::none();
}
////////////////////////////////////////////////////////////////////
// Function: WinGraphicsWindow::handle_mouse_motion
// Access: Private
// Description:
////////////////////////////////////////////////////////////////////
bool WinGraphicsWindow::
handle_mouse_motion(int x, int y) {
_input_devices[0].set_pointer_in_window(x, y);
return false;
}
////////////////////////////////////////////////////////////////////
// Function: WinGraphicsWindow::handle_mouse_exit
// Access: Private
// Description:
////////////////////////////////////////////////////////////////////
void WinGraphicsWindow::
handle_mouse_exit() {
// note: 'mouse_motion' is considered the 'entry' event
_input_devices[0].set_pointer_out_of_window();
}
// pops up MsgBox w/system error msg
void PrintErrorMessage(DWORD msgID) {
LPTSTR pMessageBuffer;
if (msgID==PRINT_LAST_ERROR)
msgID=GetLastError();
FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
NULL,msgID,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), //The user default language
(LPTSTR) &pMessageBuffer, // the weird ptrptr->ptr cast is intentional, see FORMAT_MESSAGE_ALLOCATE_BUFFER
1024, NULL);
MessageBox(GetDesktopWindow(),pMessageBuffer,_T(errorbox_title),MB_OK);
windisplay_cat.fatal() << "System error msg: " << pMessageBuffer << endl;
LocalFree( pMessageBuffer );
}
void
ClearToBlack(HWND hWnd, const WindowProperties &props) {
if (!props.has_origin()) {
windisplay_cat.info()
<< "Skipping ClearToBlack, no origin specified yet.\n";
return;
}
if (windisplay_cat.is_debug()) {
windisplay_cat.debug()
<< "ClearToBlack(" << hWnd << ", " << props << ")\n";
}
// clear to black
HDC hDC=GetDC(hWnd); // GetDC is not particularly fast. if this needs to be super-quick, we should cache GetDC's hDC
RECT clrRect = {
props.get_x_origin(), props.get_y_origin(),
props.get_x_origin() + props.get_x_size(),
props.get_y_origin() + props.get_y_size()
};
FillRect(hDC,&clrRect,(HBRUSH)GetStockObject(BLACK_BRUSH));
ReleaseDC(hWnd,hDC);
GdiFlush();
}
////////////////////////////////////////////////////////////////////
// Function: get_client_rect_screen
// Description: Fills view_rect with the coordinates of the client
// area of the indicated window, converted to screen
// coordinates.
////////////////////////////////////////////////////////////////////
void get_client_rect_screen(HWND hwnd, RECT *view_rect) {
GetClientRect(hwnd, view_rect);
POINT ul, lr;
ul.x = view_rect->left;
ul.y = view_rect->top;
lr.x = view_rect->right;
lr.y = view_rect->bottom;
ClientToScreen(hwnd, &ul);
ClientToScreen(hwnd, &lr);
view_rect->left = ul.x;
view_rect->top = ul.y;
view_rect->right = lr.x;
view_rect->bottom = lr.y;
}

View File

@ -48,13 +48,18 @@ class WinGraphicsPipe;
////////////////////////////////////////////////////////////////////
class EXPCL_PANDAWIN WinGraphicsWindow : public GraphicsWindow {
public:
WinGraphicsWindow(GraphicsPipe *pipe);
WinGraphicsWindow(GraphicsPipe *pipe, GraphicsStateGuardian *gsg);
virtual ~WinGraphicsWindow();
virtual void begin_flip();
virtual void process_events();
virtual void set_properties_now(WindowProperties &properties);
virtual LONG window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam);
static LONG WINAPI static_window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam);
virtual bool handle_mouse_motion(int x, int y);
virtual void handle_mouse_exit(void);
protected:
virtual void close_window();
@ -71,20 +76,13 @@ protected:
virtual void reconsider_fullscreen_size(DWORD &x_size, DWORD &y_size,
DWORD &bitdepth);
void get_client_rect_screen(HWND hwnd, RECT *view_rect);
private:
bool open_fullscreen_window();
bool open_regular_window();
void track_mouse_leaving(HWND hwnd);
LONG window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam);
static LONG WINAPI
static_window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam);
static void process_1_event();
INLINE void handle_mouse_motion(int x, int y);
INLINE void handle_mouse_exit(void);
INLINE void handle_keypress(ButtonHandle key, int x, int y);
INLINE void handle_keyresume(ButtonHandle key);
INLINE void handle_keyrelease(ButtonHandle key);
@ -100,7 +98,7 @@ private:
static void show_error_message(DWORD message_id = 0);
protected:
HWND _mwindow;
HWND _hWnd;
private:
bool _ime_open;
@ -108,6 +106,7 @@ private:
bool _ime_composition_w;
bool _tracking_mouse_leaving;
bool _maximized;
bool _bCursor_in_WindowClientArea;
DEVMODE _fullscreen_display_mode;
// This is used to remember the state of the keyboard when keyboard
@ -164,6 +163,12 @@ private:
static TypeHandle _type_handle;
};
#define PRINT_LAST_ERROR 0
extern EXPCL_PANDAWIN void PrintErrorMessage(DWORD msgID);
extern EXPCL_PANDAWIN void ClearToBlack(HWND hWnd, const WindowProperties &props);
extern EXPCL_PANDAWIN void get_client_rect_screen(HWND hwnd, RECT *view_rect);
#include "winGraphicsWindow.I"
#endif