merge window_devel_2003_02_21 to trunk
This commit is contained in:
parent
5c48c68569
commit
a16fe56c74
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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 \
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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 ©);
|
||||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -43,9 +43,6 @@ operator = (const WindowProperties ©) {
|
|||
_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() << " ";
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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
|
|
@ -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 ¶ms);
|
||||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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() {
|
||||
|
|
|
|||
|
|
@ -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";
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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
|
|
@ -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 ¶ms);
|
||||
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
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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";
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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, >c->_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
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
||||
|
|
|
|||
|
|
@ -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 \
|
||||
|
|
|
|||
|
|
@ -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", "");
|
||||
|
|
|
|||
|
|
@ -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__ */
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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]
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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() {
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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() {
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
#include "config_wgldisplay.cxx"
|
||||
#include "wglGraphicsPipe.cxx"
|
||||
#include "wglGraphicsStateGuardian.cxx"
|
||||
#include "wglGraphicsWindow.cxx"
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Reference in New Issue