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);
|
float win_background_b = chanconfig.GetFloat("win-background-b", 0.41);
|
||||||
|
|
||||||
// visual? nope, that's handled with the mode.
|
// visual? nope, that's handled with the mode.
|
||||||
int framebuffer_mode =
|
int frame_buffer_mode =
|
||||||
WindowProperties::FM_rgba |
|
FrameBufferProperties::FM_rgba |
|
||||||
WindowProperties::FM_double_buffer |
|
FrameBufferProperties::FM_double_buffer |
|
||||||
WindowProperties::FM_depth;
|
FrameBufferProperties::FM_depth;
|
||||||
framebuffer_mode = overrides.defined(ChanCfgOverrides::Mask) ?
|
frame_buffer_mode = overrides.defined(ChanCfgOverrides::Mask) ?
|
||||||
overrides.getUInt(ChanCfgOverrides::Mask) : framebuffer_mode;
|
overrides.getUInt(ChanCfgOverrides::Mask) : frame_buffer_mode;
|
||||||
|
|
||||||
std::string title = cfg;
|
std::string title = cfg;
|
||||||
title = overrides.defined(ChanCfgOverrides::Title) ?
|
title = overrides.defined(ChanCfgOverrides::Title) ?
|
||||||
overrides.getString(ChanCfgOverrides::Title) : 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;
|
WindowProperties props;
|
||||||
props.set_open(true);
|
props.set_open(true);
|
||||||
props.set_origin(origX, origY);
|
props.set_origin(origX, origY);
|
||||||
props.set_size(sizeX, sizeY);
|
props.set_size(sizeX, sizeY);
|
||||||
props.set_title(title);
|
props.set_title(title);
|
||||||
props.set_framebuffer_mode(framebuffer_mode);
|
|
||||||
props.set_undecorated(undecorated);
|
props.set_undecorated(undecorated);
|
||||||
props.set_fullscreen(fullscreen);
|
props.set_fullscreen(fullscreen);
|
||||||
props.set_depth_bits(want_depth_bits);
|
|
||||||
props.set_color_bits(want_color_bits);
|
|
||||||
props.set_cursor_hidden(!use_cursor);
|
props.set_cursor_hidden(!use_cursor);
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -454,7 +457,9 @@ ChanConfig::ChanConfig(GraphicsEngine *engine, GraphicsPipe* pipe,
|
||||||
overrides.getBool(ChanCfgOverrides::Cameras) : true;
|
overrides.getBool(ChanCfgOverrides::Cameras) : true;
|
||||||
|
|
||||||
// open that sucker
|
// 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) {
|
if(win == (GraphicsWindow *)NULL) {
|
||||||
chancfg_cat.error() << "Could not create window" << endl;
|
chancfg_cat.error() << "Could not create window" << endl;
|
||||||
_graphics_window = (GraphicsWindow *)NULL;
|
_graphics_window = (GraphicsWindow *)NULL;
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,7 @@
|
||||||
displayRegion.I displayRegion.h \
|
displayRegion.I displayRegion.h \
|
||||||
displayRegionStack.I \
|
displayRegionStack.I \
|
||||||
displayRegionStack.h \
|
displayRegionStack.h \
|
||||||
|
frameBufferProperties.I frameBufferProperties.h \
|
||||||
frameBufferStack.I frameBufferStack.h \
|
frameBufferStack.I frameBufferStack.h \
|
||||||
geomContext.I geomContext.h geomNodeContext.I geomNodeContext.h \
|
geomContext.I geomContext.h geomNodeContext.I geomNodeContext.h \
|
||||||
graphicsChannel.I graphicsChannel.h \
|
graphicsChannel.I graphicsChannel.h \
|
||||||
|
|
@ -24,6 +25,7 @@
|
||||||
graphicsPipeSelection.I graphicsPipeSelection.h \
|
graphicsPipeSelection.I graphicsPipeSelection.h \
|
||||||
graphicsStateGuardian.I \
|
graphicsStateGuardian.I \
|
||||||
graphicsStateGuardian.h graphicsWindow.I \
|
graphicsStateGuardian.h graphicsWindow.I \
|
||||||
|
graphicsThreadingModel.I graphicsThreadingModel.h \
|
||||||
graphicsWindow.h graphicsWindowInputDevice.I \
|
graphicsWindow.h graphicsWindowInputDevice.I \
|
||||||
graphicsWindowInputDevice.h \
|
graphicsWindowInputDevice.h \
|
||||||
windowProperties.I windowProperties.h \
|
windowProperties.I windowProperties.h \
|
||||||
|
|
@ -36,11 +38,13 @@
|
||||||
config_display.cxx \
|
config_display.cxx \
|
||||||
clearableRegion.cxx \
|
clearableRegion.cxx \
|
||||||
displayRegion.cxx \
|
displayRegion.cxx \
|
||||||
|
frameBufferProperties.cxx \
|
||||||
geomContext.cxx geomNodeContext.cxx graphicsChannel.cxx \
|
geomContext.cxx geomNodeContext.cxx graphicsChannel.cxx \
|
||||||
graphicsEngine.cxx \
|
graphicsEngine.cxx \
|
||||||
graphicsLayer.cxx graphicsPipe.cxx \
|
graphicsLayer.cxx graphicsPipe.cxx \
|
||||||
graphicsPipeSelection.cxx \
|
graphicsPipeSelection.cxx \
|
||||||
graphicsStateGuardian.cxx \
|
graphicsStateGuardian.cxx \
|
||||||
|
graphicsThreadingModel.cxx \
|
||||||
graphicsWindow.cxx graphicsWindowInputDevice.cxx \
|
graphicsWindow.cxx graphicsWindowInputDevice.cxx \
|
||||||
windowProperties.cxx \
|
windowProperties.cxx \
|
||||||
hardwareChannel.cxx \
|
hardwareChannel.cxx \
|
||||||
|
|
@ -51,6 +55,7 @@
|
||||||
clearableRegion.I clearableRegion.h \
|
clearableRegion.I clearableRegion.h \
|
||||||
displayRegion.I displayRegion.h displayRegionStack.I \
|
displayRegion.I displayRegion.h displayRegionStack.I \
|
||||||
displayRegionStack.h \
|
displayRegionStack.h \
|
||||||
|
frameBufferProperties.I frameBufferProperties.h \
|
||||||
frameBufferStack.I frameBufferStack.h \
|
frameBufferStack.I frameBufferStack.h \
|
||||||
geomContext.I geomContext.h geomNodeContext.I geomNodeContext.h \
|
geomContext.I geomContext.h geomNodeContext.I geomNodeContext.h \
|
||||||
graphicsChannel.I graphicsChannel.h \
|
graphicsChannel.I graphicsChannel.h \
|
||||||
|
|
@ -60,6 +65,7 @@
|
||||||
graphicsPipeSelection.I graphicsPipeSelection.h \
|
graphicsPipeSelection.I graphicsPipeSelection.h \
|
||||||
graphicsStateGuardian.I \
|
graphicsStateGuardian.I \
|
||||||
graphicsStateGuardian.h graphicsWindow.I graphicsWindow.h \
|
graphicsStateGuardian.h graphicsWindow.I graphicsWindow.h \
|
||||||
|
graphicsThreadingModel.I graphicsThreadingModel.h \
|
||||||
graphicsWindowInputDevice.I graphicsWindowInputDevice.h \
|
graphicsWindowInputDevice.I graphicsWindowInputDevice.h \
|
||||||
windowProperties.I windowProperties.h \
|
windowProperties.I windowProperties.h \
|
||||||
hardwareChannel.I hardwareChannel.h \
|
hardwareChannel.I hardwareChannel.h \
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,7 @@
|
||||||
#include "config_display.cxx"
|
#include "config_display.cxx"
|
||||||
|
#include "frameBufferProperties.cxx"
|
||||||
#include "graphicsPipeSelection.cxx"
|
#include "graphicsPipeSelection.cxx"
|
||||||
|
#include "graphicsThreadingModel.cxx"
|
||||||
#include "hardwareChannel.cxx"
|
#include "hardwareChannel.cxx"
|
||||||
#include "savedFrameBuffer.cxx"
|
#include "savedFrameBuffer.cxx"
|
||||||
#include "windowProperties.cxx"
|
#include "windowProperties.cxx"
|
||||||
|
|
|
||||||
|
|
@ -56,17 +56,53 @@ get_auto_flip() const {
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Function: GraphicsEngine::make_window
|
// Function: GraphicsEngine::make_gsg
|
||||||
// Access: Published
|
// Access: Published
|
||||||
// Description: Creates a new window using the indicated GraphicsPipe
|
// Description: Creates a new gsg using the indicated GraphicsPipe
|
||||||
// and returns it. The GraphicsEngine becomes the owner
|
// and returns it. The GraphicsEngine does not
|
||||||
// of the window; it will persist at least until
|
// officially own the pointer to the gsg; but if any
|
||||||
// remove_window() is called later.
|
// 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().
|
// threading model, specified via set_threading_model().
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
INLINE GraphicsWindow *GraphicsEngine::
|
INLINE PT(GraphicsStateGuardian) GraphicsEngine::
|
||||||
make_window(GraphicsPipe *pipe) {
|
make_gsg(GraphicsPipe *pipe) {
|
||||||
return make_window(pipe, get_threading_model());
|
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) {
|
if (_pipeline == (Pipeline *)NULL) {
|
||||||
_pipeline = Pipeline::get_render_pipeline();
|
_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()
|
display_cat.info()
|
||||||
<< "Using threading model " << _threading_model << "\n";
|
<< "Using threading model " << _threading_model << "\n";
|
||||||
}
|
}
|
||||||
|
|
@ -70,49 +79,46 @@ GraphicsEngine::
|
||||||
remove_all_windows();
|
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
|
// Function: GraphicsEngine::set_threading_model
|
||||||
// Access: Published
|
// Access: Published
|
||||||
// Description: Specifies how windows created using future calls to
|
// Description: Specifies how windows created using future calls to
|
||||||
// the one-parameter version of make_window() will be
|
// the one-parameter version of make_gsg() will be
|
||||||
// threaded. (The two-parameter flavor of make_window()
|
// threaded.
|
||||||
// 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.
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
void GraphicsEngine::
|
void GraphicsEngine::
|
||||||
set_threading_model(const string &threading_model) {
|
set_threading_model(const GraphicsThreadingModel &threading_model) {
|
||||||
if (!threading_model.empty() && !Thread::is_threading_supported()) {
|
if (!threading_model.is_single_threaded() &&
|
||||||
|
!Thread::is_threading_supported()) {
|
||||||
display_cat.warning()
|
display_cat.warning()
|
||||||
<< "Threading model " << threading_model
|
<< "Threading model " << threading_model
|
||||||
<< " requested but threading not supported.\n";
|
<< " 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
|
// Description: Returns the current default threading model. See
|
||||||
// set_threading_model().
|
// set_threading_model().
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
string GraphicsEngine::
|
GraphicsThreadingModel GraphicsEngine::
|
||||||
get_threading_model() const {
|
get_threading_model() const {
|
||||||
string result;
|
GraphicsThreadingModel result;
|
||||||
{
|
{
|
||||||
MutexHolder holder(_lock);
|
MutexHolder holder(_lock);
|
||||||
result = _threading_model;
|
result = _threading_model;
|
||||||
|
|
@ -138,51 +144,64 @@ get_threading_model() const {
|
||||||
return result;
|
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
|
// Function: GraphicsEngine::make_window
|
||||||
// Access: Published
|
// Access: Published
|
||||||
// Description: Creates a new window using the indicated GraphicsPipe
|
// Description: Creates a new window using the indicated
|
||||||
// and returns it. The GraphicsEngine becomes the owner
|
// GraphicsStateGuardian and returns it. The
|
||||||
// of the window; it will persist at least until
|
// GraphicsEngine becomes the owner of the window; it
|
||||||
// remove_window() is called later.
|
// will persist at least until remove_window() is called
|
||||||
|
// later.
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
GraphicsWindow *GraphicsEngine::
|
GraphicsWindow *GraphicsEngine::
|
||||||
make_window(GraphicsPipe *pipe, const string &threading_model) {
|
make_window(GraphicsPipe *pipe, GraphicsStateGuardian *gsg,
|
||||||
PT(GraphicsWindow) window = pipe->make_window();
|
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) {
|
if (window != (GraphicsWindow *)NULL) {
|
||||||
MutexHolder holder(_lock);
|
MutexHolder holder(_lock);
|
||||||
_windows.insert(window);
|
_windows.insert(window);
|
||||||
|
|
||||||
// Now figure out the threading model.
|
WindowRenderer *cull = get_window_renderer(threading_model.get_cull_name());
|
||||||
string cull_name;
|
WindowRenderer *draw = get_window_renderer(threading_model.get_draw_name());
|
||||||
string draw_name;
|
draw->add_gsg(gsg);
|
||||||
bool cull_sorting = true;
|
|
||||||
size_t start = 0;
|
|
||||||
if (!threading_model.empty() && threading_model[0] == '-') {
|
|
||||||
start = 1;
|
|
||||||
cull_sorting = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t slash = threading_model.find('/', start);
|
if (threading_model.get_cull_sorting()) {
|
||||||
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) {
|
|
||||||
cull->add_window(cull->_cull, window);
|
cull->add_window(cull->_cull, window);
|
||||||
draw->add_window(draw->_draw, window);
|
draw->add_window(draw->_draw, window);
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -869,6 +888,18 @@ get_window_renderer(const string &name) {
|
||||||
return thread.p();
|
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
|
// Function: GraphicsEngine::WindowRenderer::add_window
|
||||||
// Access: Public
|
// Access: Public
|
||||||
|
|
@ -958,6 +989,26 @@ do_frame(GraphicsEngine *engine) {
|
||||||
engine->cull_bin_draw(_cull);
|
engine->cull_bin_draw(_cull);
|
||||||
engine->cull_and_draw_together(_cdraw);
|
engine->cull_and_draw_together(_cdraw);
|
||||||
engine->process_events(_window);
|
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.
|
// Description: Closes all the windows on the _window list.
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
void GraphicsEngine::WindowRenderer::
|
void GraphicsEngine::WindowRenderer::
|
||||||
do_close(GraphicsEngine *) {
|
do_close(GraphicsEngine *engine) {
|
||||||
WindowProperties close_properties;
|
WindowProperties close_properties;
|
||||||
close_properties.set_open(false);
|
close_properties.set_open(false);
|
||||||
|
|
||||||
|
|
@ -1005,6 +1056,23 @@ do_close(GraphicsEngine *) {
|
||||||
GraphicsWindow *win = (*wi);
|
GraphicsWindow *win = (*wi);
|
||||||
win->set_properties_now(close_properties);
|
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
|
// Function: GraphicsEngine::RenderThread::Constructor
|
||||||
// Access: Public
|
// Access: Public
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,8 @@
|
||||||
|
|
||||||
#include "pandabase.h"
|
#include "pandabase.h"
|
||||||
#include "graphicsWindow.h"
|
#include "graphicsWindow.h"
|
||||||
|
#include "frameBufferProperties.h"
|
||||||
|
#include "graphicsThreadingModel.h"
|
||||||
#include "sceneSetup.h"
|
#include "sceneSetup.h"
|
||||||
#include "pointerTo.h"
|
#include "pointerTo.h"
|
||||||
#include "thread.h"
|
#include "thread.h"
|
||||||
|
|
@ -32,6 +34,7 @@
|
||||||
class Pipeline;
|
class Pipeline;
|
||||||
class DisplayRegion;
|
class DisplayRegion;
|
||||||
class GraphicsPipe;
|
class GraphicsPipe;
|
||||||
|
class FrameBufferProperties;
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Class : GraphicsEngine
|
// Class : GraphicsEngine
|
||||||
|
|
@ -53,15 +56,25 @@ PUBLISHED:
|
||||||
GraphicsEngine(Pipeline *pipeline = NULL);
|
GraphicsEngine(Pipeline *pipeline = NULL);
|
||||||
~GraphicsEngine();
|
~GraphicsEngine();
|
||||||
|
|
||||||
void set_threading_model(const string &threading_model);
|
void set_frame_buffer_properties(const FrameBufferProperties &properties);
|
||||||
string get_threading_model() const;
|
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 void set_auto_flip(bool auto_flip);
|
||||||
INLINE bool get_auto_flip() const;
|
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,
|
GraphicsWindow *make_window(GraphicsPipe *pipe,
|
||||||
const string &threading_model);
|
GraphicsStateGuardian *gsg,
|
||||||
|
const GraphicsThreadingModel &threading_model);
|
||||||
bool remove_window(GraphicsWindow *window);
|
bool remove_window(GraphicsWindow *window);
|
||||||
void remove_all_windows();
|
void remove_all_windows();
|
||||||
bool is_empty() const;
|
bool is_empty() const;
|
||||||
|
|
@ -75,6 +88,7 @@ PUBLISHED:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
typedef pset< PT(GraphicsWindow) > Windows;
|
typedef pset< PT(GraphicsWindow) > Windows;
|
||||||
|
typedef pset< PT(GraphicsStateGuardian) > GSGs;
|
||||||
|
|
||||||
void cull_and_draw_together(const Windows &wlist);
|
void cull_and_draw_together(const Windows &wlist);
|
||||||
void cull_and_draw_together(GraphicsStateGuardian *gsg, DisplayRegion *dr);
|
void cull_and_draw_together(GraphicsStateGuardian *gsg, DisplayRegion *dr);
|
||||||
|
|
@ -86,6 +100,7 @@ private:
|
||||||
void flip_windows(const GraphicsEngine::Windows &wlist);
|
void flip_windows(const GraphicsEngine::Windows &wlist);
|
||||||
void do_sync_frame();
|
void do_sync_frame();
|
||||||
void do_flip_frame();
|
void do_flip_frame();
|
||||||
|
INLINE void close_gsg(GraphicsPipe *pipe, GraphicsStateGuardian *gsg);
|
||||||
|
|
||||||
PT(SceneSetup) setup_scene(const NodePath &camera,
|
PT(SceneSetup) setup_scene(const NodePath &camera,
|
||||||
GraphicsStateGuardian *gsg);
|
GraphicsStateGuardian *gsg);
|
||||||
|
|
@ -104,6 +119,7 @@ private:
|
||||||
// process, and the list of windows for each stage.
|
// process, and the list of windows for each stage.
|
||||||
class WindowRenderer {
|
class WindowRenderer {
|
||||||
public:
|
public:
|
||||||
|
void add_gsg(GraphicsStateGuardian *gsg);
|
||||||
void add_window(Windows &wlist, GraphicsWindow *window);
|
void add_window(Windows &wlist, GraphicsWindow *window);
|
||||||
void remove_window(GraphicsWindow *window);
|
void remove_window(GraphicsWindow *window);
|
||||||
void do_frame(GraphicsEngine *engine);
|
void do_frame(GraphicsEngine *engine);
|
||||||
|
|
@ -111,6 +127,7 @@ private:
|
||||||
void do_release(GraphicsEngine *engine);
|
void do_release(GraphicsEngine *engine);
|
||||||
void do_close(GraphicsEngine *engine);
|
void do_close(GraphicsEngine *engine);
|
||||||
void do_pending(GraphicsEngine *engine);
|
void do_pending(GraphicsEngine *engine);
|
||||||
|
bool any_done_gsgs() const;
|
||||||
|
|
||||||
Windows _cull; // cull stage
|
Windows _cull; // cull stage
|
||||||
Windows _cdraw; // cull-and-draw-together stage
|
Windows _cdraw; // cull-and-draw-together stage
|
||||||
|
|
@ -118,6 +135,7 @@ private:
|
||||||
Windows _window; // window stage, i.e. process windowing events
|
Windows _window; // window stage, i.e. process windowing events
|
||||||
Windows _pending_release; // moved from _draw, pending release_gsg.
|
Windows _pending_release; // moved from _draw, pending release_gsg.
|
||||||
Windows _pending_close; // moved from _window, pending close.
|
Windows _pending_close; // moved from _window, pending close.
|
||||||
|
GSGs _gsgs; // draw stage
|
||||||
Mutex _wl_lock;
|
Mutex _wl_lock;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -148,7 +166,8 @@ private:
|
||||||
WindowRenderer _app;
|
WindowRenderer _app;
|
||||||
typedef pmap<string, PT(RenderThread) > Threads;
|
typedef pmap<string, PT(RenderThread) > Threads;
|
||||||
Threads _threads;
|
Threads _threads;
|
||||||
string _threading_model;
|
FrameBufferProperties _frame_buffer_properties;
|
||||||
|
GraphicsThreadingModel _threading_model;
|
||||||
bool _auto_flip;
|
bool _auto_flip;
|
||||||
|
|
||||||
enum FlipState {
|
enum FlipState {
|
||||||
|
|
|
||||||
|
|
@ -100,3 +100,35 @@ HardwareChannel *GraphicsPipe::
|
||||||
get_hw_channel(GraphicsWindow *, int) {
|
get_hw_channel(GraphicsWindow *, int) {
|
||||||
return (HardwareChannel*)0L;
|
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 HardwareChannel;
|
||||||
class GraphicsWindow;
|
class GraphicsWindow;
|
||||||
|
class GraphicsStateGuardian;
|
||||||
|
class FrameBufferProperties;
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Class : GraphicsPipe
|
// Class : GraphicsPipe
|
||||||
|
|
@ -69,11 +71,12 @@ public:
|
||||||
virtual HardwareChannel *get_hw_channel(GraphicsWindow *window, int index);
|
virtual HardwareChannel *get_hw_channel(GraphicsWindow *window, int index);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// The make_window() interface on GraphicsPipe is protected; don't
|
// The make_window() and make_gsg() interfaces on GraphicsPipe are
|
||||||
// try to call it directly. Instead, use
|
// protected; don't try to call them directly. Instead, use
|
||||||
// GraphicsEngine::make_window() to make a new window on a
|
// the interface on GraphicsEngine to make a new window or gsg.
|
||||||
// particular pipe.
|
virtual PT(GraphicsStateGuardian) make_gsg(const FrameBufferProperties &properties);
|
||||||
virtual PT(GraphicsWindow) make_window()=0;
|
virtual void close_gsg(GraphicsStateGuardian *gsg);
|
||||||
|
virtual PT(GraphicsWindow) make_window(GraphicsStateGuardian *gsg)=0;
|
||||||
|
|
||||||
Mutex _lock;
|
Mutex _lock;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -41,15 +41,37 @@ ClipPlaneInfo() {
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Function: GraphicsStateGuardian::is_closed
|
// Function: GraphicsStateGuardian::get_properties
|
||||||
// Access: Public
|
// Access: Public
|
||||||
// Description: Returns true if the window associated with this GSG
|
// Description: Returns the frame buffer properties requested for
|
||||||
// has been closed, and hence the resources associated
|
// this GSG. All windows created for this GSG must be
|
||||||
// with this GSG have been freed.
|
// created with the same properties.
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
INLINE bool GraphicsStateGuardian::
|
INLINE const FrameBufferProperties &GraphicsStateGuardian::
|
||||||
is_closed() const {
|
get_properties() const {
|
||||||
return (_win == (GraphicsWindow *)NULL);
|
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);
|
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
|
// Function: GraphicsStateGuardian::modify_state
|
||||||
// Access: Public
|
// Access: Public
|
||||||
|
|
|
||||||
|
|
@ -81,12 +81,13 @@ TypeHandle GraphicsStateGuardian::_type_handle;
|
||||||
// Description:
|
// Description:
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
GraphicsStateGuardian::
|
GraphicsStateGuardian::
|
||||||
GraphicsStateGuardian(GraphicsWindow *win) {
|
GraphicsStateGuardian(const FrameBufferProperties &properties) {
|
||||||
_win = win;
|
_properties = properties;
|
||||||
_coordinate_system = default_coordinate_system;
|
_coordinate_system = default_coordinate_system;
|
||||||
_current_display_region = (DisplayRegion*)0L;
|
_current_display_region = (DisplayRegion*)0L;
|
||||||
_current_lens = (Lens *)NULL;
|
_current_lens = (Lens *)NULL;
|
||||||
reset();
|
_needs_reset = true;
|
||||||
|
_closing_gsg = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
|
|
@ -106,6 +107,8 @@ GraphicsStateGuardian::
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
void GraphicsStateGuardian::
|
void GraphicsStateGuardian::
|
||||||
reset() {
|
reset() {
|
||||||
|
_needs_reset = false;
|
||||||
|
|
||||||
_display_region_stack_level = 0;
|
_display_region_stack_level = 0;
|
||||||
_frame_buffer_stack_level = 0;
|
_frame_buffer_stack_level = 0;
|
||||||
_lens_stack_level = 0;
|
_lens_stack_level = 0;
|
||||||
|
|
@ -1374,11 +1377,10 @@ free_pointers() {
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
void GraphicsStateGuardian::
|
void GraphicsStateGuardian::
|
||||||
close_gsg() {
|
close_gsg() {
|
||||||
|
_closing_gsg = true;
|
||||||
free_pointers();
|
free_pointers();
|
||||||
release_all_textures();
|
release_all_textures();
|
||||||
release_all_geoms();
|
release_all_geoms();
|
||||||
|
|
||||||
_win = (GraphicsWindow *)NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef DO_PSTATS
|
#ifdef DO_PSTATS
|
||||||
|
|
|
||||||
|
|
@ -23,10 +23,13 @@
|
||||||
|
|
||||||
#include "savedFrameBuffer.h"
|
#include "savedFrameBuffer.h"
|
||||||
#include "frameBufferStack.h"
|
#include "frameBufferStack.h"
|
||||||
|
#include "frameBufferProperties.h"
|
||||||
#include "displayRegionStack.h"
|
#include "displayRegionStack.h"
|
||||||
#include "lensStack.h"
|
#include "lensStack.h"
|
||||||
|
|
||||||
#include "graphicsStateGuardianBase.h"
|
#include "graphicsStateGuardianBase.h"
|
||||||
|
#include "graphicsThreadingModel.h"
|
||||||
|
#include "graphicsPipe.h"
|
||||||
#include "sceneSetup.h"
|
#include "sceneSetup.h"
|
||||||
#include "luse.h"
|
#include "luse.h"
|
||||||
#include "coordinateSystem.h"
|
#include "coordinateSystem.h"
|
||||||
|
|
@ -61,7 +64,7 @@ class EXPCL_PANDA GraphicsStateGuardian : public GraphicsStateGuardianBase {
|
||||||
// Interfaces all GSGs should have
|
// Interfaces all GSGs should have
|
||||||
//
|
//
|
||||||
public:
|
public:
|
||||||
GraphicsStateGuardian(GraphicsWindow *win);
|
GraphicsStateGuardian(const FrameBufferProperties &properties);
|
||||||
virtual ~GraphicsStateGuardian();
|
virtual ~GraphicsStateGuardian();
|
||||||
|
|
||||||
PUBLISHED:
|
PUBLISHED:
|
||||||
|
|
@ -69,7 +72,9 @@ PUBLISHED:
|
||||||
void release_all_geoms();
|
void release_all_geoms();
|
||||||
|
|
||||||
public:
|
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 void set_scene(SceneSetup *scene_setup);
|
||||||
INLINE SceneSetup *get_scene() const;
|
INLINE SceneSetup *get_scene() const;
|
||||||
|
|
@ -119,6 +124,7 @@ public:
|
||||||
virtual CPT(RenderState) begin_decal_base_second();
|
virtual CPT(RenderState) begin_decal_base_second();
|
||||||
virtual void finish_decal();
|
virtual void finish_decal();
|
||||||
|
|
||||||
|
INLINE void reset_if_new();
|
||||||
virtual void reset();
|
virtual void reset();
|
||||||
|
|
||||||
INLINE void modify_state(const RenderState *state);
|
INLINE void modify_state(const RenderState *state);
|
||||||
|
|
@ -232,8 +238,6 @@ protected:
|
||||||
int _frame_buffer_stack_level;
|
int _frame_buffer_stack_level;
|
||||||
int _lens_stack_level;
|
int _lens_stack_level;
|
||||||
|
|
||||||
GraphicsWindow *_win;
|
|
||||||
|
|
||||||
CPT(DisplayRegion) _current_display_region;
|
CPT(DisplayRegion) _current_display_region;
|
||||||
CPT(Lens) _current_lens;
|
CPT(Lens) _current_lens;
|
||||||
|
|
||||||
|
|
@ -261,6 +265,9 @@ protected:
|
||||||
ColorBlendAttrib::Mode _color_blend_mode;
|
ColorBlendAttrib::Mode _color_blend_mode;
|
||||||
TransparencyAttrib::Mode _transparency_mode;
|
TransparencyAttrib::Mode _transparency_mode;
|
||||||
|
|
||||||
|
bool _needs_reset;
|
||||||
|
bool _closing_gsg;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// Statistics
|
// Statistics
|
||||||
static PStatCollector _total_texusage_pcollector;
|
static PStatCollector _total_texusage_pcollector;
|
||||||
|
|
@ -324,11 +331,12 @@ private:
|
||||||
typedef pset<GeomNodeContext *> GeomNodes;
|
typedef pset<GeomNodeContext *> GeomNodes;
|
||||||
GeomNodes _prepared_geom_nodes;
|
GeomNodes _prepared_geom_nodes;
|
||||||
|
|
||||||
public:
|
FrameBufferProperties _properties;
|
||||||
void traverse_prepared_textures(bool (*pertex_callbackfn)(TextureContext *,void *),void *callback_arg);
|
PT(GraphicsPipe) _pipe;
|
||||||
|
GraphicsThreadingModel _threading_model;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
INLINE GraphicsWindow* get_window(void) const { return _win; }
|
void traverse_prepared_textures(bool (*pertex_callbackfn)(TextureContext *,void *),void *callback_arg);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static TypeHandle get_class_type() {
|
static TypeHandle get_class_type() {
|
||||||
|
|
@ -351,6 +359,7 @@ private:
|
||||||
|
|
||||||
friend class GraphicsPipe;
|
friend class GraphicsPipe;
|
||||||
friend class GraphicsWindow;
|
friend class GraphicsWindow;
|
||||||
|
friend class GraphicsEngine;
|
||||||
};
|
};
|
||||||
|
|
||||||
#include "graphicsStateGuardian.I"
|
#include "graphicsStateGuardian.I"
|
||||||
|
|
|
||||||
|
|
@ -37,11 +37,12 @@ TypeHandle GraphicsWindow::_type_handle;
|
||||||
// GraphicsEngine::make_window() function.
|
// GraphicsEngine::make_window() function.
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
GraphicsWindow::
|
GraphicsWindow::
|
||||||
GraphicsWindow(GraphicsPipe *pipe) {
|
GraphicsWindow(GraphicsPipe *pipe, GraphicsStateGuardian *gsg) {
|
||||||
#ifdef DO_MEMORY_USAGE
|
#ifdef DO_MEMORY_USAGE
|
||||||
MemoryUsage::update_type(this, this);
|
MemoryUsage::update_type(this, this);
|
||||||
#endif
|
#endif
|
||||||
_pipe = pipe;
|
_pipe = pipe;
|
||||||
|
_gsg = gsg;
|
||||||
|
|
||||||
// Some default properties for windows unless specified otherwise.
|
// Some default properties for windows unless specified otherwise.
|
||||||
// Other properties (size, title, etc.) must be explicitly
|
// Other properties (size, title, etc.) must be explicitly
|
||||||
|
|
@ -51,11 +52,7 @@ GraphicsWindow(GraphicsPipe *pipe) {
|
||||||
_properties.set_fullscreen(false);
|
_properties.set_fullscreen(false);
|
||||||
_properties.set_minimized(false);
|
_properties.set_minimized(false);
|
||||||
_properties.set_cursor_hidden(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;
|
_display_regions_stale = false;
|
||||||
_window_event = "window-event";
|
_window_event = "window-event";
|
||||||
|
|
||||||
|
|
@ -581,32 +578,11 @@ make_scratch_display_region(int x_size, int y_size) const {
|
||||||
bool GraphicsWindow::
|
bool GraphicsWindow::
|
||||||
begin_frame() {
|
begin_frame() {
|
||||||
if (_gsg == (GraphicsStateGuardian *)NULL) {
|
if (_gsg == (GraphicsStateGuardian *)NULL) {
|
||||||
MutexHolder holder(_lock);
|
return false;
|
||||||
// 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();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Okay, we already have a GSG, so activate it.
|
||||||
|
make_current();
|
||||||
return _gsg->begin_frame();
|
return _gsg->begin_frame();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -652,32 +628,6 @@ end_frame() {
|
||||||
_gsg->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
|
// Function: GraphicsWindow::make_current
|
||||||
// Access: Public, Virtual
|
// Access: Public, Virtual
|
||||||
|
|
@ -689,6 +639,20 @@ void GraphicsWindow::
|
||||||
make_current() {
|
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
|
// Function: GraphicsWindow::begin_flip
|
||||||
// Access: Public, Virtual
|
// Access: Public, Virtual
|
||||||
|
|
|
||||||
|
|
@ -58,7 +58,7 @@
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
class EXPCL_PANDA GraphicsWindow : public TypedReferenceCount, public ClearableRegion {
|
class EXPCL_PANDA GraphicsWindow : public TypedReferenceCount, public ClearableRegion {
|
||||||
protected:
|
protected:
|
||||||
GraphicsWindow(GraphicsPipe *pipe);
|
GraphicsWindow(GraphicsPipe *pipe, GraphicsStateGuardian *gsg);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
GraphicsWindow(const GraphicsWindow ©);
|
GraphicsWindow(const GraphicsWindow ©);
|
||||||
|
|
@ -119,12 +119,10 @@ public:
|
||||||
void clear();
|
void clear();
|
||||||
virtual void end_frame();
|
virtual void end_frame();
|
||||||
|
|
||||||
virtual void make_gsg();
|
|
||||||
virtual void release_gsg();
|
|
||||||
|
|
||||||
// This method is called in the draw thread prior to issuing any
|
// This method is called in the draw thread prior to issuing any
|
||||||
// drawing commands for the window.
|
// drawing commands for the window.
|
||||||
virtual void make_current();
|
virtual void make_current();
|
||||||
|
virtual void release_gsg();
|
||||||
|
|
||||||
// These methods will be called within the app (main) thread.
|
// These methods will be called within the app (main) thread.
|
||||||
virtual void begin_flip();
|
virtual void begin_flip();
|
||||||
|
|
|
||||||
|
|
@ -513,150 +513,6 @@ clear_cursor_hidden() {
|
||||||
_flags &= ~F_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 &
|
INLINE ostream &
|
||||||
operator << (ostream &out, const WindowProperties &properties) {
|
operator << (ostream &out, const WindowProperties &properties) {
|
||||||
properties.output(out);
|
properties.output(out);
|
||||||
|
|
|
||||||
|
|
@ -43,9 +43,6 @@ operator = (const WindowProperties ©) {
|
||||||
_y_size = copy._y_size;
|
_y_size = copy._y_size;
|
||||||
_title = copy._title;
|
_title = copy._title;
|
||||||
_flags = copy._flags;
|
_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 &&
|
_y_origin == other._y_origin &&
|
||||||
_x_size == other._x_size &&
|
_x_size == other._x_size &&
|
||||||
_y_size == other._y_size &&
|
_y_size == other._y_size &&
|
||||||
_title == other._title &&
|
_title == other._title);
|
||||||
_framebuffer_mode == other._framebuffer_mode &&
|
|
||||||
_depth_bits == other._depth_bits &&
|
|
||||||
_color_bits == other._color_bits);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
|
|
@ -83,9 +77,6 @@ clear() {
|
||||||
_y_size = 0;
|
_y_size = 0;
|
||||||
_title = string();
|
_title = string();
|
||||||
_flags = 0;
|
_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()) {
|
if (other.has_cursor_hidden()) {
|
||||||
set_cursor_hidden(other.get_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()) {
|
if (has_cursor_hidden()) {
|
||||||
out << (get_cursor_hidden() ? "cursor_hidden " : "!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;
|
bool operator == (const WindowProperties &other) const;
|
||||||
INLINE 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();
|
void clear();
|
||||||
INLINE bool is_any_specified() const;
|
INLINE bool is_any_specified() const;
|
||||||
|
|
||||||
|
|
@ -104,21 +88,6 @@ PUBLISHED:
|
||||||
INLINE bool has_cursor_hidden() const;
|
INLINE bool has_cursor_hidden() const;
|
||||||
INLINE void clear_cursor_hidden();
|
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 add_properties(const WindowProperties &other);
|
||||||
|
|
||||||
void output(ostream &out) const;
|
void output(ostream &out) const;
|
||||||
|
|
@ -137,9 +106,6 @@ private:
|
||||||
S_minimized = 0x0040,
|
S_minimized = 0x0040,
|
||||||
S_open = 0x0080,
|
S_open = 0x0080,
|
||||||
S_cursor_hidden = 0x0100,
|
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
|
// This bitmask represents the true/false settings for various
|
||||||
|
|
@ -161,9 +127,6 @@ private:
|
||||||
int _y_size;
|
int _y_size;
|
||||||
string _title;
|
string _title;
|
||||||
int _flags;
|
int _flags;
|
||||||
int _framebuffer_mode;
|
|
||||||
int _depth_bits;
|
|
||||||
int _color_bits;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
INLINE ostream &operator << (ostream &out, const WindowProperties &properties);
|
INLINE ostream &operator << (ostream &out, const WindowProperties &properties);
|
||||||
|
|
|
||||||
|
|
@ -259,8 +259,9 @@ int NonlinearImager::
|
||||||
add_viewer(DisplayRegion *dr) {
|
add_viewer(DisplayRegion *dr) {
|
||||||
GraphicsWindow *win = dr->get_window();
|
GraphicsWindow *win = dr->get_window();
|
||||||
GraphicsStateGuardian *gsg = win->get_gsg();
|
GraphicsStateGuardian *gsg = win->get_gsg();
|
||||||
nassertr(_viewers.empty() || gsg == _gsg, -1);
|
nassertr(_viewers.empty() || (gsg == _gsg && win == _win), -1);
|
||||||
_gsg = gsg;
|
_gsg = gsg;
|
||||||
|
_win = win;
|
||||||
|
|
||||||
int previous_vi = find_viewer(dr);
|
int previous_vi = find_viewer(dr);
|
||||||
if (previous_vi >= 0) {
|
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
|
// Make a display region of the proper size and clear it to prepare for
|
||||||
// rendering the scene.
|
// rendering the scene.
|
||||||
PT(DisplayRegion) scratch_region =
|
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);
|
scratch_region->set_camera(screen._source_camera);
|
||||||
engine->render_subframe(_gsg, scratch_region, true);
|
engine->render_subframe(_gsg, scratch_region, true);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -32,6 +32,7 @@
|
||||||
|
|
||||||
class GraphicsEngine;
|
class GraphicsEngine;
|
||||||
class GraphicsStateGuardian;
|
class GraphicsStateGuardian;
|
||||||
|
class GraphicsWindow;
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Class : NonlinearImager
|
// Class : NonlinearImager
|
||||||
|
|
@ -162,6 +163,7 @@ private:
|
||||||
Viewers _viewers;
|
Viewers _viewers;
|
||||||
Screens _screens;
|
Screens _screens;
|
||||||
GraphicsStateGuardian *_gsg;
|
GraphicsStateGuardian *_gsg;
|
||||||
|
GraphicsWindow *_win;
|
||||||
|
|
||||||
bool _stale;
|
bool _stale;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -30,12 +30,12 @@ enable_line_smooth(bool val) {
|
||||||
_line_smooth_enabled = val;
|
_line_smooth_enabled = val;
|
||||||
#ifdef NDEBUG
|
#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";
|
dxgsg7_cat.error() << "no HW support for line smoothing!!\n";
|
||||||
}
|
}
|
||||||
#endif
|
#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
|
#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";
|
dxgsg7_cat.error() << "no HW support for color dithering!!\n";
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
_dither_enabled = val;
|
_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) {
|
enable_stencil_test(bool val) {
|
||||||
if (_stencil_test_enabled != val) {
|
if (_stencil_test_enabled != val) {
|
||||||
_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) {
|
enable_blend(bool val) {
|
||||||
if (_blend_enabled != val) {
|
if (_blend_enabled != val) {
|
||||||
_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) {
|
set_shademode(D3DSHADEMODE val) {
|
||||||
if (_CurShadeMode != val) {
|
if (_CurShadeMode != val) {
|
||||||
_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) {
|
enable_primitive_clipping(bool val) {
|
||||||
if (_clipping_enabled != val) {
|
if (_clipping_enabled != val) {
|
||||||
_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) {
|
enable_fog(bool val) {
|
||||||
if ((_fog_enabled != val) && (_doFogType!=None)) {
|
if ((_fog_enabled != val) && (_doFogType!=None)) {
|
||||||
_fog_enabled = val;
|
_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) {
|
if (_alpha_test_enabled != val) {
|
||||||
_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
|
#ifdef GSG_VERBOSE
|
||||||
dxgsg7_cat.debug() << "dxLightModel(LIGHT_MODEL_AMBIENT, " << color << ")" << endl;
|
dxgsg7_cat.debug() << "dxLightModel(LIGHT_MODEL_AMBIENT, " << color << ")" << endl;
|
||||||
#endif
|
#endif
|
||||||
scrn.pD3DDevice->SetRenderState( D3DRENDERSTATE_AMBIENT,
|
_pScrn->pD3DDevice->SetRenderState( D3DRENDERSTATE_AMBIENT,
|
||||||
D3DRGBA(color[0], color[1], color[2], color[3]));
|
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;
|
dxgsg7_cat.debug() << " , " << reference_alpha << ")" << endl;
|
||||||
#endif
|
#endif
|
||||||
scrn.pD3DDevice->SetRenderState(D3DRENDERSTATE_ALPHAFUNC, func);
|
_pScrn->pD3DDevice->SetRenderState(D3DRENDERSTATE_ALPHAFUNC, func);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(_alpha_func_refval != reference_alpha) {
|
if(_alpha_func_refval != reference_alpha) {
|
||||||
_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)
|
if (_blend_source_func != sfunc)
|
||||||
{
|
{
|
||||||
_blend_source_func = sfunc;
|
_blend_source_func = sfunc;
|
||||||
scrn.pD3DDevice->SetRenderState(D3DRENDERSTATE_SRCBLEND, sfunc);
|
_pScrn->pD3DDevice->SetRenderState(D3DRENDERSTATE_SRCBLEND, sfunc);
|
||||||
#ifdef GSG_VERBOSE
|
#ifdef GSG_VERBOSE
|
||||||
dxgsg7_cat.debug() << "dxSrcBlendFunc(";
|
dxgsg7_cat.debug() << "dxSrcBlendFunc(";
|
||||||
switch (sfunc)
|
switch (sfunc)
|
||||||
|
|
@ -265,7 +265,7 @@ call_dxBlendFunc(D3DBLEND sfunc, D3DBLEND dfunc )
|
||||||
if ( _blend_dest_func != dfunc)
|
if ( _blend_dest_func != dfunc)
|
||||||
{
|
{
|
||||||
_blend_dest_func = dfunc;
|
_blend_dest_func = dfunc;
|
||||||
scrn.pD3DDevice->SetRenderState(D3DRENDERSTATE_DESTBLEND, dfunc);
|
_pScrn->pD3DDevice->SetRenderState(D3DRENDERSTATE_DESTBLEND, dfunc);
|
||||||
#ifdef GSG_VERBOSE
|
#ifdef GSG_VERBOSE
|
||||||
dxgsg7_cat.debug() << "dxDstBlendFunc(";
|
dxgsg7_cat.debug() << "dxDstBlendFunc(";
|
||||||
switch (dfunc)
|
switch (dfunc)
|
||||||
|
|
@ -307,7 +307,7 @@ INLINE void DXGraphicsStateGuardian7::
|
||||||
enable_zwritemask(bool val) {
|
enable_zwritemask(bool val) {
|
||||||
if (_depth_write_enabled != val) {
|
if (_depth_write_enabled != val) {
|
||||||
_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;
|
friend class DXTextureContext7;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
DXGraphicsStateGuardian7(GraphicsWindow *win);
|
DXGraphicsStateGuardian7(const FrameBufferProperties &properties);
|
||||||
~DXGraphicsStateGuardian7();
|
~DXGraphicsStateGuardian7();
|
||||||
|
|
||||||
virtual void reset();
|
virtual void reset();
|
||||||
|
|
@ -128,7 +128,7 @@ public:
|
||||||
virtual void bind_light(DirectionalLight *light, int light_id);
|
virtual void bind_light(DirectionalLight *light, int light_id);
|
||||||
virtual void bind_light(Spotlight *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 bool begin_scene();
|
||||||
virtual void end_scene();
|
virtual void end_scene();
|
||||||
virtual void end_frame();
|
virtual void end_frame();
|
||||||
|
|
@ -144,7 +144,8 @@ public:
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// recreate_tex_callback needs pDD,pD3DDevice to be 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
|
#ifndef USE_TEXFMTVEC
|
||||||
LPDDPIXELFORMAT _pTexPixFmts;
|
LPDDPIXELFORMAT _pTexPixFmts;
|
||||||
|
|
@ -225,6 +226,7 @@ protected:
|
||||||
INLINE void enable_stencil_test(bool val);
|
INLINE void enable_stencil_test(bool val);
|
||||||
void report_texmgr_stats();
|
void report_texmgr_stats();
|
||||||
void draw_multitri(Geom *geom, D3DPRIMITIVETYPE tri_id);
|
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(int nVerts, const Geom *geom, ushort perFlags);
|
||||||
void draw_prim_inner_loop_coordtexonly(int nVerts, const Geom *geom);
|
void draw_prim_inner_loop_coordtexonly(int nVerts, const Geom *geom);
|
||||||
|
|
@ -301,7 +303,7 @@ protected:
|
||||||
DWORD _clip_plane_bits;
|
DWORD _clip_plane_bits;
|
||||||
|
|
||||||
RenderModeAttrib::Mode _current_fill_mode; //poinr/wireframe/solid
|
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
|
// Cur Texture State
|
||||||
TextureApplyAttrib::Mode _CurTexBlendMode;
|
TextureApplyAttrib::Mode _CurTexBlendMode;
|
||||||
|
|
@ -321,6 +323,16 @@ protected:
|
||||||
|
|
||||||
bool _overlay_windows_supported;
|
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:
|
public:
|
||||||
static GraphicsStateGuardian*
|
static GraphicsStateGuardian*
|
||||||
make_DXGraphicsStateGuardian(const FactoryParams ¶ms);
|
make_DXGraphicsStateGuardian(const FactoryParams ¶ms);
|
||||||
|
|
@ -329,12 +341,6 @@ public:
|
||||||
static void init_type(void);
|
static void init_type(void);
|
||||||
virtual TypeHandle get_type(void) const;
|
virtual TypeHandle get_type(void) const;
|
||||||
virtual TypeHandle force_init_type() {init_type(); return get_class_type();}
|
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; }
|
// INLINE void Set_HDC(HDC hdc) { _front_hdc = hdc; }
|
||||||
void adjust_view_rect(int x, int y);
|
void adjust_view_rect(int x, int y);
|
||||||
INLINE void SetDXReady(bool stat) { _dx_ready = stat; }
|
INLINE void SetDXReady(bool stat) { _dx_ready = stat; }
|
||||||
|
|
@ -346,7 +352,7 @@ public:
|
||||||
#define DO_REACTIVATE_WINDOW true
|
#define DO_REACTIVATE_WINDOW true
|
||||||
bool CheckCooperativeLevel(bool bDoReactivateWindow = false);
|
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_frame();
|
||||||
void show_full_screen_frame();
|
void show_full_screen_frame();
|
||||||
void show_windowed_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!
|
#error DX7 headers not available, you need to install MS Platform SDK or DirectX 8+ SDK!
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <pandabase.h>
|
#include "pandabase.h"
|
||||||
|
|
||||||
// disable nameless struct 'warning'
|
// disable nameless struct 'warning'
|
||||||
#pragma warning (disable : 4201)
|
#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(p) { if(p) { delete (p); (p)=NULL; } }
|
||||||
#define SAFE_DELETE_ARRAY(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()
|
// this is bDoDownToZero argument to RELEASE()
|
||||||
#define RELEASE_DOWN_TO_ZERO true
|
#define RELEASE_DOWN_TO_ZERO true
|
||||||
#define RELEASE_ONCE false
|
#define RELEASE_ONCE false
|
||||||
|
|
||||||
// #define DEBUG_RELEASES
|
#define DEBUG_RELEASES
|
||||||
|
|
||||||
#ifdef DEBUG_RELEASES
|
#ifdef DEBUG_RELEASES
|
||||||
#define RELEASE(OBJECT,MODULE,DBGSTR,bDoDownToZero) \
|
#define RELEASE(OBJECT,MODULE,DBGSTR,bDoDownToZero) \
|
||||||
|
|
@ -124,6 +126,7 @@ typedef struct {
|
||||||
bool bIsLowVidMemCard;
|
bool bIsLowVidMemCard;
|
||||||
bool bIsTNLDevice;
|
bool bIsTNLDevice;
|
||||||
bool bIsSWRast;
|
bool bIsSWRast;
|
||||||
|
bool bIsFullScreen;
|
||||||
WORD depth_buffer_bitdepth; //GetSurfaceDesc is not reliable so must store this explicitly
|
WORD depth_buffer_bitdepth; //GetSurfaceDesc is not reliable so must store this explicitly
|
||||||
WORD CardIDNum; // its posn in DisplayArray, for dbgprint purposes
|
WORD CardIDNum; // its posn in DisplayArray, for dbgprint purposes
|
||||||
DDDEVICEIDENTIFIER2 DXDeviceID;
|
DDDEVICEIDENTIFIER2 DXDeviceID;
|
||||||
|
|
|
||||||
|
|
@ -40,10 +40,7 @@ wdxGraphicsPipe7() {
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
wdxGraphicsPipe7::
|
wdxGraphicsPipe7::
|
||||||
~wdxGraphicsPipe7() {
|
~wdxGraphicsPipe7() {
|
||||||
if (_hDDrawDLL != NULL) {
|
SAFE_FREELIB(_hDDrawDLL);
|
||||||
FreeLibrary(_hDDrawDLL);
|
|
||||||
_hDDrawDLL = NULL;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
|
|
@ -79,8 +76,21 @@ pipe_constructor() {
|
||||||
// Description: Creates a new window on the pipe, if possible.
|
// Description: Creates a new window on the pipe, if possible.
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
PT(GraphicsWindow) wdxGraphicsPipe7::
|
PT(GraphicsWindow) wdxGraphicsPipe7::
|
||||||
make_window() {
|
make_window(GraphicsStateGuardian *gsg) {
|
||||||
return new wdxGraphicsWindow7(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 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::
|
bool wdxGraphicsPipe7::
|
||||||
init() {
|
init() {
|
||||||
static const char * const ddraw_name = "ddraw.dll";
|
|
||||||
_hDDrawDLL = LoadLibrary(ddraw_name);
|
if(!MyLoadLib(_hDDrawDLL,"ddraw.dll")) {
|
||||||
if(_hDDrawDLL == 0) {
|
goto error;
|
||||||
wdxdisplay7_cat.error()
|
|
||||||
<< "can't locate " << ddraw_name << "!\n";
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_DirectDrawCreateEx =
|
if(!MyGetProcAddr(_hDDrawDLL, (FARPROC*)&_DirectDrawCreateEx, "DirectDrawCreateEx")) {
|
||||||
(LPDIRECTDRAWCREATEEX)GetProcAddress(_hDDrawDLL, "DirectDrawCreateEx");
|
goto error;
|
||||||
if (_DirectDrawCreateEx == NULL) {
|
|
||||||
wdxdisplay7_cat.error()
|
|
||||||
<< "GetProcAddr failed for DDCreateEx" << endl;
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
error:
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -34,9 +34,10 @@ public:
|
||||||
|
|
||||||
virtual string get_interface_name() const;
|
virtual string get_interface_name() const;
|
||||||
static PT(GraphicsPipe) pipe_constructor();
|
static PT(GraphicsPipe) pipe_constructor();
|
||||||
|
virtual PT(GraphicsStateGuardian) make_gsg(const FrameBufferProperties &properties);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual PT(GraphicsWindow) make_window();
|
virtual PT(GraphicsWindow) make_window(GraphicsStateGuardian *gsg);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool init();
|
bool init();
|
||||||
|
|
@ -61,6 +62,7 @@ public:
|
||||||
}
|
}
|
||||||
virtual TypeHandle force_init_type() {init_type(); return get_class_type();}
|
virtual TypeHandle force_init_type() {init_type(); return get_class_type();}
|
||||||
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static TypeHandle _type_handle;
|
static TypeHandle _type_handle;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -116,10 +116,11 @@ TypeHandle wdxGraphicsWindow7::_type_handle;
|
||||||
// Description:
|
// Description:
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
wdxGraphicsWindow7::
|
wdxGraphicsWindow7::
|
||||||
wdxGraphicsWindow7(GraphicsPipe *pipe) :
|
wdxGraphicsWindow7(GraphicsPipe *pipe, GraphicsStateGuardian *gsg) :
|
||||||
WinGraphicsWindow(pipe)
|
WinGraphicsWindow(pipe, gsg)
|
||||||
{
|
{
|
||||||
_dxgsg = (DXGraphicsStateGuardian7 *)NULL;
|
_dxgsg = DCAST(DXGraphicsStateGuardian7, gsg);
|
||||||
|
ZeroMemory(&_wcontext,sizeof(_wcontext));
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
|
|
@ -131,6 +132,47 @@ wdxGraphicsWindow7::
|
||||||
~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
|
// Function: wdxGraphicsWindow7::make_gsg
|
||||||
// Access: Public, Virtual
|
// Access: Public, Virtual
|
||||||
|
|
@ -144,9 +186,9 @@ make_gsg() {
|
||||||
_dxgsg = new DXGraphicsStateGuardian7(this);
|
_dxgsg = new DXGraphicsStateGuardian7(this);
|
||||||
_gsg = _dxgsg;
|
_gsg = _dxgsg;
|
||||||
// Tell the associated dxGSG about the window handle.
|
// 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()
|
wdxdisplay7_cat.error()
|
||||||
<< "Unable to find suitable rendering device.\n";
|
<< "Unable to find suitable rendering device.\n";
|
||||||
release_gsg();
|
release_gsg();
|
||||||
|
|
@ -156,30 +198,7 @@ make_gsg() {
|
||||||
set_coop_levels_and_display_modes();
|
set_coop_levels_and_display_modes();
|
||||||
create_screen_buffers_and_device(_dxgsg->scrn, dx_force_16bpp_zbuffer);
|
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
|
// Function: wdxGraphicsWindow7::end_flip
|
||||||
|
|
@ -234,15 +253,15 @@ handle_reshape() {
|
||||||
if (_dxgsg!=NULL) {
|
if (_dxgsg!=NULL) {
|
||||||
HRESULT hr;
|
HRESULT hr;
|
||||||
|
|
||||||
if (_dxgsg->scrn.pddsBack == NULL) {
|
if (_wcontext.pddsBack == NULL) {
|
||||||
// assume this is initial creation reshape and ignore this call
|
// assume this is initial creation reshape and ignore this call
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Clear the back/primary surface to black
|
// Clear the back/primary surface to black using ddraw
|
||||||
DX_DECLARE_CLEAN(DDBLTFX, bltfx);
|
DX_DECLARE_CLEAN(DDBLTFX, bltfx);
|
||||||
bltfx.dwDDFX |= DDBLTFX_NOTEARING;
|
bltfx.dwDDFX |= DDBLTFX_NOTEARING;
|
||||||
hr = _dxgsg->scrn.pddsPrimary->Blt
|
hr = _wcontext.pddsPrimary->Blt
|
||||||
(NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &bltfx);
|
(NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &bltfx);
|
||||||
if (FAILED(hr)) {
|
if (FAILED(hr)) {
|
||||||
wdxdisplay7_cat.fatal()
|
wdxdisplay7_cat.fatal()
|
||||||
|
|
@ -251,7 +270,7 @@ handle_reshape() {
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
hr = _dxgsg->scrn.pDD->TestCooperativeLevel();
|
hr = _wcontext.pDD->TestCooperativeLevel();
|
||||||
if (FAILED(hr)) {
|
if (FAILED(hr)) {
|
||||||
wdxdisplay7_cat.error()
|
wdxdisplay7_cat.error()
|
||||||
<< "TestCooperativeLevel failed : result = "
|
<< "TestCooperativeLevel failed : result = "
|
||||||
|
|
@ -264,10 +283,13 @@ handle_reshape() {
|
||||||
set_to_temp_rendertarget();
|
set_to_temp_rendertarget();
|
||||||
|
|
||||||
// create the new resized rendertargets
|
// 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;
|
RECT view_rect;
|
||||||
HWND hWnd = _dxgsg->scrn.hWnd;
|
get_client_rect_screen(_wcontext.hWnd, &view_rect);
|
||||||
get_client_rect_screen(hWnd, &view_rect);
|
_dxgsg->dx_setup_after_resize(&view_rect);
|
||||||
_dxgsg->dx_setup_after_resize(view_rect, hWnd);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -285,7 +307,7 @@ do_fullscreen_resize(int x_size, int y_size) {
|
||||||
|
|
||||||
DX_DECLARE_CLEAN(DDSURFACEDESC2,ddsd_curmode);
|
DX_DECLARE_CLEAN(DDSURFACEDESC2,ddsd_curmode);
|
||||||
|
|
||||||
hr = _dxgsg->scrn.pDD->GetDisplayMode(&ddsd_curmode);
|
hr = _wcontext.pDD->GetDisplayMode(&ddsd_curmode);
|
||||||
if (FAILED(hr)) {
|
if (FAILED(hr)) {
|
||||||
wdxdisplay7_cat.fatal()
|
wdxdisplay7_cat.fatal()
|
||||||
<< "resize() - GetDisplayMode failed, result = "
|
<< "resize() - GetDisplayMode failed, result = "
|
||||||
|
|
@ -310,7 +332,7 @@ do_fullscreen_resize(int x_size, int y_size) {
|
||||||
DMI.maxHeight = y_size;
|
DMI.maxHeight = y_size;
|
||||||
DMI.pDDSD_Arr = DDSD_Arr;
|
DMI.pDDSD_Arr = DDSD_Arr;
|
||||||
|
|
||||||
hr = _dxgsg->scrn.pDD->EnumDisplayModes(DDEDM_REFRESHRATES, &ddsd_search,
|
hr = _wcontext.pDD->EnumDisplayModes(DDEDM_REFRESHRATES, &ddsd_search,
|
||||||
&DMI, EnumDisplayModesCallBack);
|
&DMI, EnumDisplayModesCallBack);
|
||||||
if (FAILED(hr)) {
|
if (FAILED(hr)) {
|
||||||
wdxdisplay7_cat.fatal()
|
wdxdisplay7_cat.fatal()
|
||||||
|
|
@ -319,7 +341,7 @@ do_fullscreen_resize(int x_size, int y_size) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
DMI.supportedBitDepths &= _dxgsg->scrn.D3DDevDesc.dwDeviceRenderBitDepth;
|
DMI.supportedBitDepths &= _wcontext.D3DDevDesc.dwDeviceRenderBitDepth;
|
||||||
|
|
||||||
DWORD dwFullScreenBitDepth;
|
DWORD dwFullScreenBitDepth;
|
||||||
DWORD requested_bpp = ddsd_curmode.ddpfPixelFormat.dwRGBBitCount;
|
DWORD requested_bpp = ddsd_curmode.ddpfPixelFormat.dwRGBBitCount;
|
||||||
|
|
@ -341,7 +363,7 @@ do_fullscreen_resize(int x_size, int y_size) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
hr = _dxgsg->scrn.pDD->TestCooperativeLevel();
|
hr = _wcontext.pDD->TestCooperativeLevel();
|
||||||
if (FAILED(hr)) {
|
if (FAILED(hr)) {
|
||||||
wdxdisplay7_cat.error()
|
wdxdisplay7_cat.error()
|
||||||
<< "TestCooperativeLevel failed : result = "
|
<< "TestCooperativeLevel failed : result = "
|
||||||
|
|
@ -354,7 +376,7 @@ do_fullscreen_resize(int x_size, int y_size) {
|
||||||
_dxgsg->free_dxgsg_objects();
|
_dxgsg->free_dxgsg_objects();
|
||||||
|
|
||||||
// let driver choose default refresh rate (hopefully its >=60Hz)
|
// 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);
|
0L, 0L);
|
||||||
if (FAILED(hr)) {
|
if (FAILED(hr)) {
|
||||||
wdxdisplay7_cat.error()
|
wdxdisplay7_cat.error()
|
||||||
|
|
@ -366,17 +388,17 @@ do_fullscreen_resize(int x_size, int y_size) {
|
||||||
|
|
||||||
if (wdxdisplay7_cat.is_debug()) {
|
if (wdxdisplay7_cat.is_debug()) {
|
||||||
DX_DECLARE_CLEAN(DDSURFACEDESC2,ddsd34);
|
DX_DECLARE_CLEAN(DDSURFACEDESC2,ddsd34);
|
||||||
_dxgsg->scrn.pDD->GetDisplayMode(&ddsd34);
|
_wcontext.pDD->GetDisplayMode(&ddsd34);
|
||||||
wdxdisplay7_cat.debug()
|
wdxdisplay7_cat.debug()
|
||||||
<< "set displaymode to " << ddsd34.dwWidth << "x" << ddsd34.dwHeight
|
<< "set displaymode to " << ddsd34.dwWidth << "x" << ddsd34.dwHeight
|
||||||
<< " at "<< ddsd34.ddpfPixelFormat.dwRGBBitCount << "bpp, "
|
<< " at "<< ddsd34.ddpfPixelFormat.dwRGBBitCount << "bpp, "
|
||||||
<< ddsd34.dwRefreshRate << "Hz\n";
|
<< ddsd34.dwRefreshRate << "Hz\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
_dxgsg->scrn.dwRenderWidth = x_size;
|
_wcontext.dwRenderWidth = x_size;
|
||||||
_dxgsg->scrn.dwRenderHeight = y_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->RecreateAllVideoSurfaces();
|
||||||
_dxgsg->SetDXReady(true);
|
_dxgsg->SetDXReady(true);
|
||||||
return true;
|
return true;
|
||||||
|
|
@ -400,8 +422,8 @@ set_to_temp_rendertarget() {
|
||||||
|
|
||||||
DX_DECLARE_CLEAN(DDSURFACEDESC2, ddsd);
|
DX_DECLARE_CLEAN(DDSURFACEDESC2, ddsd);
|
||||||
|
|
||||||
_dxgsg->scrn.pddsBack->GetSurfaceDesc(&ddsd);
|
_wcontext.pddsBack->GetSurfaceDesc(&ddsd);
|
||||||
LPDIRECTDRAW7 pDD = _dxgsg->scrn.pDD;
|
LPDIRECTDRAW7 pDD = _wcontext.pDD;
|
||||||
|
|
||||||
ddsd.dwFlags &= ~DDSD_PITCH;
|
ddsd.dwFlags &= ~DDSD_PITCH;
|
||||||
ddsd.dwWidth = 1;
|
ddsd.dwWidth = 1;
|
||||||
|
|
@ -418,9 +440,9 @@ set_to_temp_rendertarget() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_dxgsg->scrn.pddsZBuf != NULL) {
|
if (_wcontext.pddsZBuf != NULL) {
|
||||||
DX_DECLARE_CLEAN(DDSURFACEDESC2, ddsdZ);
|
DX_DECLARE_CLEAN(DDSURFACEDESC2, ddsdZ);
|
||||||
_dxgsg->scrn.pddsZBuf->GetSurfaceDesc(&ddsdZ);
|
_wcontext.pddsZBuf->GetSurfaceDesc(&ddsdZ);
|
||||||
ddsdZ.dwFlags &= ~DDSD_PITCH;
|
ddsdZ.dwFlags &= ~DDSD_PITCH;
|
||||||
ddsdZ.dwWidth = 1;
|
ddsdZ.dwWidth = 1;
|
||||||
ddsdZ.dwHeight = 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)) {
|
if (FAILED(hr)) {
|
||||||
wdxdisplay7_cat.error()
|
wdxdisplay7_cat.error()
|
||||||
<< "Resize failed to set render target to temporary surface, result = "
|
<< "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_PRIMARYSURFACE | DDSCAPS_3DDEVICE |
|
||||||
DDSCAPS_FLIP | DDSCAPS_COMPLEX;
|
DDSCAPS_FLIP | DDSCAPS_COMPLEX;
|
||||||
ddsd.dwBackBufferCount = 1;
|
ddsd.dwBackBufferCount = 1;
|
||||||
|
Display.bIsFullScreen=true;
|
||||||
|
|
||||||
if (dx_full_screen_antialiasing) {
|
if (dx_full_screen_antialiasing) {
|
||||||
// cant check that d3ddevice has this capability yet, so got to
|
// 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
|
// 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
|
#ifndef NDEBUG
|
||||||
if ((framebuffer_mode & WindowProperties::FM_depth) == 0) {
|
if ((frame_buffer_mode & FrameBufferProperties::FM_depth) == 0) {
|
||||||
wdxdisplay7_cat.info()
|
wdxdisplay7_cat.info()
|
||||||
<< "no zbuffer requested, skipping zbuffer creation\n";
|
<< "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
|
// Check if the device supports z-bufferless hidden surface
|
||||||
// removal. If so, we don't really need a z-buffer
|
// removal. If so, we don't really need a z-buffer
|
||||||
if ((!(pD3DDevDesc->dpcTriCaps.dwRasterCaps & D3DPRASTERCAPS_ZBUFFERLESSHSR )) &&
|
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
|
// Get z-buffer dimensions from the render target
|
||||||
DX_DECLARE_CLEAN(DDSURFACEDESC2,ddsd);
|
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.
|
// Setup the surface desc for the z-buffer.
|
||||||
ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_PIXELFORMAT;
|
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];
|
DDPIXELFORMAT ZBufPixFmts[MAX_DX_ZBUF_FMTS];
|
||||||
cNumZBufFmts=0;
|
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?
|
// should we pay attn to these at some point?
|
||||||
//int want_depth_bits = _props._want_depth_bits;
|
//int want_depth_bits = _props._want_depth_bits;
|
||||||
//int want_color_bits = _props._want_color_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;
|
LPDDPIXELFORMAT pCurPixFmt, pz16 = NULL, pz24 = NULL, pz32 = NULL;
|
||||||
for (i = 0, pCurPixFmt = ZBufPixFmts;
|
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;}
|
#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
|
SET_ZBUF_DEPTH(16); // need this for fast path rasterizers
|
||||||
} else {
|
} else {
|
||||||
if (IS_NVIDIA(Display.DXDeviceID)) {
|
if (IS_NVIDIA(Display.DXDeviceID)) {
|
||||||
|
|
@ -945,6 +968,7 @@ create_screen_buffers_and_device(DXScreenData &Display, bool force_16bpp_zbuffer
|
||||||
Display.pddsZBuf = pZDDSurf;
|
Display.pddsZBuf = pZDDSurf;
|
||||||
Display.view_rect = view_rect;
|
Display.view_rect = view_rect;
|
||||||
|
|
||||||
|
_dxgsg->set_context(&Display);
|
||||||
//pDD, pPrimaryDDSurf, pBackDDSurf, pZDDSurf, pD3DI, pD3DDevice, view_rect);
|
//pDD, pPrimaryDDSurf, pBackDDSurf, pZDDSurf, pD3DI, pD3DDevice, view_rect);
|
||||||
_dxgsg->dx_init();
|
_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
|
// Access: Private
|
||||||
// Description: Searches for a suitable hardware device for
|
// Description: Searches for a suitable hardware device for
|
||||||
// rendering.
|
// rendering.
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
bool wdxGraphicsWindow7::
|
bool wdxGraphicsWindow7::
|
||||||
search_for_device(int devnum, DXDeviceInfo *pDevinfo) {
|
choose_device(int devnum, DXDeviceInfo *pDevinfo) {
|
||||||
wdxGraphicsPipe7 *dxpipe;
|
wdxGraphicsPipe7 *dxpipe;
|
||||||
DCAST_INTO_R(dxpipe, _pipe, false);
|
DCAST_INTO_R(dxpipe, _pipe, false);
|
||||||
|
|
||||||
|
|
@ -992,16 +1016,16 @@ search_for_device(int devnum, DXDeviceInfo *pDevinfo) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
_dxgsg->scrn.pDD = pDD;
|
_wcontext.pDD = pDD;
|
||||||
|
|
||||||
// GetDeviceID bug writes an extra 4 bytes, so need xtra space
|
// GetDeviceID bug writes an extra 4 bytes, so need xtra space
|
||||||
BYTE id_arr[sizeof(DDDEVICEIDENTIFIER2) + 4];
|
BYTE id_arr[sizeof(DDDEVICEIDENTIFIER2) + 4];
|
||||||
pDD->GetDeviceIdentifier((DDDEVICEIDENTIFIER2 *)&id_arr, 0x0);
|
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()) {
|
if (wdxdisplay7_cat.is_info()) {
|
||||||
DDDEVICEIDENTIFIER2 *pDevID = &_dxgsg->scrn.DXDeviceID;
|
DDDEVICEIDENTIFIER2 *pDevID = &_wcontext.DXDeviceID;
|
||||||
wdxdisplay7_cat.info()
|
wdxdisplay7_cat.info()
|
||||||
<< "GfxCard: " << pDevID->szDescription << "; DriverFile: '"
|
<< "GfxCard: " << pDevID->szDescription << "; DriverFile: '"
|
||||||
<< pDevID->szDriver
|
<< pDevID->szDriver
|
||||||
|
|
@ -1015,7 +1039,7 @@ search_for_device(int devnum, DXDeviceInfo *pDevinfo) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Query DirectDraw for access to Direct3D
|
// 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) {
|
if(hr != DD_OK) {
|
||||||
wdxdisplay7_cat.fatal()
|
wdxdisplay7_cat.fatal()
|
||||||
<< "QI for D3D failed : result = " << ConvD3DErrorToString(hr) << endl;
|
<< "QI for D3D failed : result = " << ConvD3DErrorToString(hr) << endl;
|
||||||
|
|
@ -1029,7 +1053,7 @@ search_for_device(int devnum, DXDeviceInfo *pDevinfo) {
|
||||||
|
|
||||||
ZeroMemory(d3ddevs,3*sizeof(D3DDEVICEDESC7));
|
ZeroMemory(d3ddevs,3*sizeof(D3DDEVICEDESC7));
|
||||||
|
|
||||||
hr = _dxgsg->scrn.pD3D->EnumDevices(EnumDevicesCallback, d3ddevs);
|
hr = _wcontext.pD3D->EnumDevices(EnumDevicesCallback, d3ddevs);
|
||||||
if(hr != DD_OK) {
|
if(hr != DD_OK) {
|
||||||
wdxdisplay7_cat.fatal()
|
wdxdisplay7_cat.fatal()
|
||||||
<< "EnumDevices failed : result = " << ConvD3DErrorToString(hr) << endl;
|
<< "EnumDevices failed : result = " << ConvD3DErrorToString(hr) << endl;
|
||||||
|
|
@ -1048,7 +1072,7 @@ search_for_device(int devnum, DXDeviceInfo *pDevinfo) {
|
||||||
} else {
|
} else {
|
||||||
wdxdisplay7_cat.error()
|
wdxdisplay7_cat.error()
|
||||||
<< "No 3D HW present on device #" << devnum << ", skipping it... ("
|
<< "No 3D HW present on device #" << devnum << ", skipping it... ("
|
||||||
<< _dxgsg->scrn.DXDeviceID.szDescription<<")\n";
|
<< _wcontext.DXDeviceID.szDescription<<")\n";
|
||||||
goto error_exit;
|
goto error_exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1056,10 +1080,10 @@ search_for_device(int devnum, DXDeviceInfo *pDevinfo) {
|
||||||
DeviceIdx = SWRASTIDX;
|
DeviceIdx = SWRASTIDX;
|
||||||
}
|
}
|
||||||
|
|
||||||
memcpy(&_dxgsg->scrn.D3DDevDesc, &d3ddevs[DeviceIdx],
|
memcpy(&_wcontext.D3DDevDesc, &d3ddevs[DeviceIdx],
|
||||||
sizeof(D3DDEVICEDESC7));
|
sizeof(D3DDEVICEDESC7));
|
||||||
|
|
||||||
_dxgsg->scrn.bIsTNLDevice = (DeviceIdx == TNLHALIDX);
|
_wcontext.bIsTNLDevice = (DeviceIdx == TNLHALIDX);
|
||||||
|
|
||||||
// Get Current VidMem avail. Note this is only an estimate, when we
|
// Get Current VidMem avail. Note this is only an estimate, when we
|
||||||
// switch to fullscreen mode from desktop, more vidmem will be
|
// 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
|
// 1.2 meg (contradicting above comment and what I think would be
|
||||||
// correct behavior (shouldnt FS mode release the desktop vidmem?),
|
// correct behavior (shouldnt FS mode release the desktop vidmem?),
|
||||||
// so this is the true value
|
// so this is the true value
|
||||||
_dxgsg->scrn.MaxAvailVidMem = dwVidMemTotal;
|
_wcontext.MaxAvailVidMem = dwVidMemTotal;
|
||||||
|
|
||||||
#define LOWVIDMEMTHRESHOLD 5500000
|
#define LOWVIDMEMTHRESHOLD 5500000
|
||||||
#define CRAPPY_DRIVER_IS_LYING_VIDMEMTHRESHOLD 1000000 // every vidcard we deal with should have at least 1MB
|
#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
|
// 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>CRAPPY_DRIVER_IS_LYING_VIDMEMTHRESHOLD) &&
|
||||||
(dwVidMemTotal< LOWVIDMEMTHRESHOLD));
|
(dwVidMemTotal< LOWVIDMEMTHRESHOLD));
|
||||||
|
|
||||||
if (!dx_do_vidmemsize_check) {
|
if (!dx_do_vidmemsize_check) {
|
||||||
_dxgsg->scrn.MaxAvailVidMem = 0xFFFFFFFF;
|
_wcontext.MaxAvailVidMem = 0xFFFFFFFF;
|
||||||
_dxgsg->scrn.bIsLowVidMemCard = false;
|
_wcontext.bIsLowVidMemCard = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (DeviceIdx == SWRASTIDX) {
|
if (DeviceIdx == SWRASTIDX) {
|
||||||
// this will force 640x480x16, is this what we want for all sw rast?
|
// this will force 640x480x16, is this what we want for all sw rast?
|
||||||
_dxgsg->scrn.bIsLowVidMemCard = true;
|
_wcontext.bIsLowVidMemCard = true;
|
||||||
_dxgsg->scrn.bIsSWRast = true;
|
_wcontext.bIsSWRast = true;
|
||||||
dx_force_16bpp_zbuffer = true;
|
dx_force_16bpp_zbuffer = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1125,7 +1149,7 @@ search_for_device(int devnum, DXDeviceInfo *pDevinfo) {
|
||||||
if (FAILED(hr)) {
|
if (FAILED(hr)) {
|
||||||
wdxdisplay7_cat.fatal()
|
wdxdisplay7_cat.fatal()
|
||||||
<< "EnumDisplayModes failed for device #" << devnum
|
<< "EnumDisplayModes failed for device #" << devnum
|
||||||
<< " (" << _dxgsg->scrn.DXDeviceID.szDescription
|
<< " (" << _wcontext.DXDeviceID.szDescription
|
||||||
<< "), result = " << ConvD3DErrorToString(hr) << endl;
|
<< "), result = " << ConvD3DErrorToString(hr) << endl;
|
||||||
// goto skip_device;
|
// goto skip_device;
|
||||||
exit(1); // probably want to exit, since it may be my fault
|
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
|
// resolution and best rendertarget bpp and still have at least 2
|
||||||
// meg of texture vidmem
|
// meg of texture vidmem
|
||||||
|
|
||||||
DMI.supportedBitDepths &= _dxgsg->scrn.D3DDevDesc.dwDeviceRenderBitDepth;
|
DMI.supportedBitDepths &= _wcontext.D3DDevDesc.dwDeviceRenderBitDepth;
|
||||||
|
|
||||||
DWORD dwFullScreenBitDepth;
|
DWORD dwFullScreenBitDepth;
|
||||||
|
|
||||||
|
|
@ -1158,12 +1182,12 @@ search_for_device(int devnum, DXDeviceInfo *pDevinfo) {
|
||||||
wdxdisplay7_cat.fatal()
|
wdxdisplay7_cat.fatal()
|
||||||
<< "No Supported FullScreen resolutions at " << dwRenderWidth
|
<< "No Supported FullScreen resolutions at " << dwRenderWidth
|
||||||
<< "x" << dwRenderHeight << " for device #" << devnum
|
<< "x" << dwRenderHeight << " for device #" << devnum
|
||||||
<< " (" << _dxgsg->scrn.DXDeviceID.szDescription
|
<< " (" << _wcontext.DXDeviceID.szDescription
|
||||||
<< "), skipping device...\n";
|
<< "), skipping device...\n";
|
||||||
goto error_exit;
|
goto error_exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_dxgsg->scrn.bIsLowVidMemCard) {
|
if (_wcontext.bIsLowVidMemCard) {
|
||||||
{
|
{
|
||||||
// hack: figuring out exactly what res to use is tricky,
|
// hack: figuring out exactly what res to use is tricky,
|
||||||
// instead I will just use 640x480 if we have < 3 meg avail
|
// 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;
|
_wcontext.dwRenderWidth = dwRenderWidth;
|
||||||
_dxgsg->scrn.dwRenderHeight = dwRenderHeight;
|
_wcontext.dwRenderHeight = dwRenderHeight;
|
||||||
if (pDevinfo) {
|
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;
|
return true;
|
||||||
|
|
||||||
// handle errors within this for device loop
|
// handle errors within this for device loop
|
||||||
|
|
||||||
error_exit:
|
error_exit:
|
||||||
if (_dxgsg->scrn.pD3D != NULL)
|
if (_wcontext.pD3D != NULL)
|
||||||
_dxgsg->scrn.pD3D->Release();
|
_wcontext.pD3D->Release();
|
||||||
if (_dxgsg->scrn.pDD != NULL)
|
if (_wcontext.pDD != NULL)
|
||||||
_dxgsg->scrn.pDD->Release();
|
_wcontext.pDD->Release();
|
||||||
|
|
||||||
_dxgsg->scrn.pDD = NULL;
|
_wcontext.pDD = NULL;
|
||||||
_dxgsg->scrn.pD3D = NULL;
|
_wcontext.pD3D = NULL;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1220,16 +1244,15 @@ set_coop_levels_and_display_modes() {
|
||||||
// tell d3d to preserve the fpu state across calls. this hurts
|
// tell d3d to preserve the fpu state across calls. this hurts
|
||||||
// perf, but is good for dbgging
|
// perf, but is good for dbgging
|
||||||
SCL_FPUFlag = DDSCL_FPUPRESERVE;
|
SCL_FPUFlag = DDSCL_FPUPRESERVE;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
SCL_FPUFlag = DDSCL_FPUSETUP;
|
SCL_FPUFlag = DDSCL_FPUSETUP;
|
||||||
}
|
}
|
||||||
|
|
||||||
DXScreenData *pScrn = &_dxgsg->scrn;
|
// DXScreenData *pScrn = &_dxgsg->scrn;
|
||||||
|
|
||||||
if (!is_fullscreen()) {
|
if (!is_fullscreen()) {
|
||||||
hr = pScrn->pDD->SetCooperativeLevel(_mwindow,
|
hr = _wcontext.pDD->SetCooperativeLevel(_hWnd,
|
||||||
SCL_FPUFlag | DDSCL_NORMAL);
|
SCL_FPUFlag | DDSCL_NORMAL);
|
||||||
if (FAILED(hr)) {
|
if (FAILED(hr)) {
|
||||||
wdxdisplay7_cat.fatal()
|
wdxdisplay7_cat.fatal()
|
||||||
<< "SetCooperativeLevel failed : result = "
|
<< "SetCooperativeLevel failed : result = "
|
||||||
|
|
@ -1246,7 +1269,7 @@ set_coop_levels_and_display_modes() {
|
||||||
// restore that functionality.
|
// restore that functionality.
|
||||||
DWORD devnum = 0;
|
DWORD devnum = 0;
|
||||||
{
|
{
|
||||||
DXScreenData *pScrn = &_dxgsg->scrn;
|
// DXScreenData *pScrn = &_dxgsg->scrn;
|
||||||
|
|
||||||
// need to set focus/device windows for multimon
|
// need to set focus/device windows for multimon
|
||||||
// focus window is primary monitor that will receive keybd input
|
// 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
|
// SetCoopLevel twice. so we do it, it really shouldnt be necessary
|
||||||
// if drivers werent buggy
|
// if drivers werent buggy
|
||||||
for (int jj=0; jj<2; jj++) {
|
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)) {
|
if (FAILED(hr)) {
|
||||||
wdxdisplay7_cat.fatal()
|
wdxdisplay7_cat.fatal()
|
||||||
<< "SetCooperativeLevel failed for device #" << devnum
|
<< "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)) {
|
if (FAILED(hr)) {
|
||||||
wdxdisplay7_cat.fatal()
|
wdxdisplay7_cat.fatal()
|
||||||
<< "TestCooperativeLevel failed: result = " << ConvD3DErrorToString(hr)
|
<< "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";
|
<< "Full screen app failed to get exclusive mode on init, exiting..\n";
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// note: its important we call SetDisplayMode on all cards before
|
// note: its important we call SetDisplayMode on all cards before
|
||||||
// creating surfaces on any of them to let driver choose default
|
// creating surfaces on any of them to let driver choose default
|
||||||
// refresh rate (hopefully its >=60Hz)
|
// refresh rate (hopefully its >=60Hz)
|
||||||
hr = pScrn->pDD->SetDisplayMode(pScrn->dwRenderWidth,
|
hr = _wcontext.pDD->SetDisplayMode(_wcontext.dwRenderWidth,
|
||||||
pScrn->dwRenderHeight,
|
_wcontext.dwRenderHeight,
|
||||||
pScrn->dwFullScreenBitDepth, 0, 0);
|
_wcontext.dwFullScreenBitDepth, 0, 0);
|
||||||
if (FAILED(hr)) {
|
if (FAILED(hr)) {
|
||||||
wdxdisplay7_cat.fatal()
|
wdxdisplay7_cat.fatal()
|
||||||
<< "SetDisplayMode failed to set (" << pScrn->dwRenderWidth
|
<< "SetDisplayMode failed to set (" << _wcontext.dwRenderWidth
|
||||||
<< "x" <<pScrn->dwRenderHeight << "x" << pScrn->dwFullScreenBitDepth
|
<< "x" <<_wcontext.dwRenderHeight << "x" << _wcontext.dwFullScreenBitDepth
|
||||||
<< ") on device #" << pScrn->CardIDNum << ": result = "
|
<< ") on device #" << _wcontext.CardIDNum << ": result = "
|
||||||
<< ConvD3DErrorToString(hr) << endl;
|
<< ConvD3DErrorToString(hr) << endl;
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(wdxdisplay7_cat.is_debug()) {
|
if(wdxdisplay7_cat.is_debug()) {
|
||||||
DX_DECLARE_CLEAN(DDSURFACEDESC2,ddsd34);
|
DX_DECLARE_CLEAN(DDSURFACEDESC2,ddsd_temp);
|
||||||
pScrn->pDD->GetDisplayMode(&ddsd34);
|
_wcontext.pDD->GetDisplayMode(&ddsd_temp);
|
||||||
wdxdisplay7_cat.debug()
|
wdxdisplay7_cat.debug()
|
||||||
<< "set displaymode to " << ddsd34.dwWidth << "x" << ddsd34.dwHeight
|
<< "set displaymode to " << ddsd_temp.dwWidth << "x" << ddsd_temp.dwHeight
|
||||||
<< " at " << ddsd34.ddpfPixelFormat.dwRGBBitCount << "bpp, "
|
<< " at " << ddsd_temp.ddpfPixelFormat.dwRGBBitCount << "bpp, "
|
||||||
<< ddsd34.dwRefreshRate<< "Hz\n";
|
<< 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 {
|
class EXPCL_PANDADX wdxGraphicsWindow7 : public WinGraphicsWindow {
|
||||||
public:
|
public:
|
||||||
wdxGraphicsWindow7(GraphicsPipe *pipe);
|
wdxGraphicsWindow7(GraphicsPipe *pipe, GraphicsStateGuardian *gsg);
|
||||||
virtual ~wdxGraphicsWindow7();
|
virtual ~wdxGraphicsWindow7();
|
||||||
|
|
||||||
virtual void make_gsg();
|
|
||||||
virtual void release_gsg();
|
|
||||||
|
|
||||||
virtual void end_flip();
|
virtual void end_flip();
|
||||||
|
//virtual bool begin_frame();
|
||||||
|
virtual void make_current(void);
|
||||||
|
virtual bool open_window(void);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual void fullscreen_restored(WindowProperties &properties);
|
virtual void fullscreen_restored(WindowProperties &properties);
|
||||||
|
|
@ -59,10 +58,11 @@ private:
|
||||||
bool set_to_temp_rendertarget();
|
bool set_to_temp_rendertarget();
|
||||||
void create_screen_buffers_and_device(DXScreenData &Display,
|
void create_screen_buffers_and_device(DXScreenData &Display,
|
||||||
bool force_16bpp_zbuffer);
|
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();
|
void set_coop_levels_and_display_modes();
|
||||||
|
|
||||||
DXGraphicsStateGuardian7 *_dxgsg;
|
DXGraphicsStateGuardian7 *_dxgsg;
|
||||||
|
DXScreenData _wcontext;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static TypeHandle get_class_type() {
|
static TypeHandle get_class_type() {
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,8 @@
|
||||||
#include <dconfig.h>
|
#include <dconfig.h>
|
||||||
|
|
||||||
Configure(config_dxgsg8);
|
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");
|
NotifyCategoryDef(wdxdisplay8, "windisplay");
|
||||||
|
|
||||||
// Configure this variable true to cause the DXGSG to show each
|
// Configure this variable true to cause the DXGSG to show each
|
||||||
|
|
@ -196,58 +197,5 @@ init_libdxgsg8() {
|
||||||
GraphicsPipeSelection *selection = GraphicsPipeSelection::get_global_ptr();
|
GraphicsPipeSelection *selection = GraphicsPipeSelection::get_global_ptr();
|
||||||
selection->add_pipe_type(wdxGraphicsPipe8::get_class_type(),
|
selection->add_pipe_type(wdxGraphicsPipe8::get_class_type(),
|
||||||
wdxGraphicsPipe8::pipe_constructor);
|
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 "pandabase.h"
|
||||||
#include "notifyCategoryProxy.h"
|
#include "notifyCategoryProxy.h"
|
||||||
#include <d3d8.h>
|
#include "dxgsg8base.h"
|
||||||
|
|
||||||
NotifyCategoryDecl(dxgsg8, EXPCL_PANDADX, EXPTP_PANDADX);
|
NotifyCategoryDecl(dxgsg8, EXPCL_PANDADX, EXPTP_PANDADX);
|
||||||
NotifyCategoryDecl(wdxdisplay8, 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 const bool link_tristrips;
|
||||||
extern DWORD dx_multisample_antialiasing_level;
|
extern DWORD dx_multisample_antialiasing_level;
|
||||||
extern bool dx_use_triangle_mipgen_filter;
|
extern bool dx_use_triangle_mipgen_filter;
|
||||||
extern const char *D3DFormatStr(D3DFORMAT fmt);
|
|
||||||
extern bool dx_use_dx_cursor;
|
extern bool dx_use_dx_cursor;
|
||||||
|
|
||||||
|
|
||||||
// debug flags we might want to use in full optimized build
|
// debug flags we might want to use in full optimized build
|
||||||
extern bool dx_ignore_mipmaps;
|
extern bool dx_ignore_mipmaps;
|
||||||
extern bool dx_mipmap_everything;
|
extern bool dx_mipmap_everything;
|
||||||
|
|
|
||||||
|
|
@ -30,12 +30,12 @@ enable_line_smooth(bool val) {
|
||||||
_line_smooth_enabled = val;
|
_line_smooth_enabled = val;
|
||||||
#ifdef NDEBUG
|
#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";
|
dxgsg8_cat.error() << "no HW support for line smoothing!!\n";
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
scrn.pD3DDevice->SetRenderState(D3DRS_EDGEANTIALIAS, (DWORD)val);
|
_pD3DDevice->SetRenderState(D3DRS_EDGEANTIALIAS, (DWORD)val);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -50,14 +50,14 @@ enable_dither(bool val) {
|
||||||
|
|
||||||
#ifdef _DEBUG
|
#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";
|
dxgsg8_cat.error() << "no HW support for color dithering!!\n";
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
_dither_enabled = val;
|
_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) {
|
enable_stencil_test(bool val) {
|
||||||
if (_stencil_test_enabled != val) {
|
if (_stencil_test_enabled != val) {
|
||||||
_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) {
|
enable_blend(bool val) {
|
||||||
if (_blend_enabled != val) {
|
if (_blend_enabled != val) {
|
||||||
_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) {
|
set_color_writemask(UINT color_writemask) {
|
||||||
if (_color_writemask != color_writemask) {
|
if (_color_writemask != color_writemask) {
|
||||||
_color_writemask = color_writemask;
|
_color_writemask = color_writemask;
|
||||||
if(scrn.bCanDirectDisableColorWrites) {
|
if(_pScrn->bCanDirectDisableColorWrites) {
|
||||||
// only newer HW supports this rstate
|
// only newer HW supports this rstate
|
||||||
scrn.pD3DDevice->SetRenderState(D3DRS_COLORWRITEENABLE, (DWORD)color_writemask);
|
_pD3DDevice->SetRenderState(D3DRS_COLORWRITEENABLE, (DWORD)color_writemask);
|
||||||
} else {
|
} else {
|
||||||
// blending can only handle on/off
|
// blending can only handle on/off
|
||||||
assert((color_writemask==0x0)||(color_writemask==0xFFFFFFFF));
|
assert((color_writemask==0x0)||(color_writemask==0xFFFFFFFF));
|
||||||
|
|
@ -129,7 +129,7 @@ INLINE void DXGraphicsStateGuardian8::
|
||||||
enable_gouraud_shading(bool val) {
|
enable_gouraud_shading(bool val) {
|
||||||
if (_bGouraudShadingOn != val) {
|
if (_bGouraudShadingOn != val) {
|
||||||
_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) {
|
enable_primitive_clipping(bool val) {
|
||||||
if (_clipping_enabled != val) {
|
if (_clipping_enabled != val) {
|
||||||
_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) {
|
enable_fog(bool val) {
|
||||||
if ((_fog_enabled != val) && (_doFogType!=None)) {
|
if ((_fog_enabled != val) && (_doFogType!=None)) {
|
||||||
_fog_enabled = val;
|
_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
|
#ifdef USE_VERTEX_SHADERS
|
||||||
if(_CurVertexShader!=NULL) {
|
if(_CurVertexShader!=NULL) {
|
||||||
// this needs optimization
|
// this needs optimization
|
||||||
HRESULT hr = scrn.pD3DDevice->SetVertexShader(_CurVertexShader);
|
HRESULT hr = _pD3DDevice->SetVertexShader(_CurVertexShader);
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
if(FAILED(hr)) {
|
if(FAILED(hr)) {
|
||||||
dxgsg8_cat.error() << "SetVertexShader for custom vtx shader failed" << D3DERRORSTRING(hr);
|
dxgsg8_cat.error() << "SetVertexShader for custom vtx shader failed" << D3DERRORSTRING(hr);
|
||||||
|
|
@ -179,7 +179,7 @@ set_vertex_format(DWORD NewFvfType) {
|
||||||
if (_CurFVFType != NewFvfType) {
|
if (_CurFVFType != NewFvfType) {
|
||||||
_CurFVFType = NewFvfType;
|
_CurFVFType = NewFvfType;
|
||||||
|
|
||||||
HRESULT hr = scrn.pD3DDevice->SetVertexShader(NewFvfType);
|
HRESULT hr = _pD3DDevice->SetVertexShader(NewFvfType);
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
if(FAILED(hr)) {
|
if(FAILED(hr)) {
|
||||||
dxgsg8_cat.error() << "SetVertexShader(0x" << (void*)NewFvfType<<") failed" << D3DERRORSTRING(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) {
|
if (_alpha_test_enabled != val) {
|
||||||
_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
|
#ifdef GSG_VERBOSE
|
||||||
dxgsg8_cat.debug() << "dxLightModel(LIGHT_MODEL_AMBIENT, " << color << ")" << endl;
|
dxgsg8_cat.debug() << "dxLightModel(LIGHT_MODEL_AMBIENT, " << color << ")" << endl;
|
||||||
#endif
|
#endif
|
||||||
scrn.pD3DDevice->SetRenderState( D3DRS_AMBIENT,
|
_pD3DDevice->SetRenderState( D3DRS_AMBIENT,
|
||||||
D3DCOLOR_COLORVALUE(color[0], color[1], color[2], color[3]));
|
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;
|
dxgsg8_cat.debug() << " , " << reference_alpha << ")" << endl;
|
||||||
#endif
|
#endif
|
||||||
scrn.pD3DDevice->SetRenderState(D3DRS_ALPHAFUNC, func);
|
_pD3DDevice->SetRenderState(D3DRS_ALPHAFUNC, func);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(_alpha_func_refval != reference_alpha) {
|
if(_alpha_func_refval != reference_alpha) {
|
||||||
_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)
|
if (_blend_source_func != sfunc)
|
||||||
{
|
{
|
||||||
_blend_source_func = sfunc;
|
_blend_source_func = sfunc;
|
||||||
scrn.pD3DDevice->SetRenderState(D3DRS_SRCBLEND, sfunc);
|
_pD3DDevice->SetRenderState(D3DRS_SRCBLEND, sfunc);
|
||||||
#ifdef GSG_VERBOSE
|
#ifdef GSG_VERBOSE
|
||||||
dxgsg8_cat.debug() << "dxSrcBlendFunc(";
|
dxgsg8_cat.debug() << "dxSrcBlendFunc(";
|
||||||
switch (sfunc)
|
switch (sfunc)
|
||||||
|
|
@ -323,7 +323,7 @@ call_dxBlendFunc(D3DBLEND sfunc, D3DBLEND dfunc )
|
||||||
if ( _blend_dest_func != dfunc)
|
if ( _blend_dest_func != dfunc)
|
||||||
{
|
{
|
||||||
_blend_dest_func = dfunc;
|
_blend_dest_func = dfunc;
|
||||||
scrn.pD3DDevice->SetRenderState(D3DRS_DESTBLEND, dfunc);
|
_pD3DDevice->SetRenderState(D3DRS_DESTBLEND, dfunc);
|
||||||
#ifdef GSG_VERBOSE
|
#ifdef GSG_VERBOSE
|
||||||
dxgsg8_cat.debug() << "dxDstBlendFunc(";
|
dxgsg8_cat.debug() << "dxDstBlendFunc(";
|
||||||
switch (dfunc)
|
switch (dfunc)
|
||||||
|
|
@ -365,7 +365,7 @@ INLINE void DXGraphicsStateGuardian8::
|
||||||
enable_zwritemask(bool val) {
|
enable_zwritemask(bool val) {
|
||||||
if (_depth_write_enabled != val) {
|
if (_depth_write_enabled != val) {
|
||||||
_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;
|
friend class DXTextureContext8;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
DXGraphicsStateGuardian8(GraphicsWindow *win);
|
DXGraphicsStateGuardian8(const FrameBufferProperties &properties);
|
||||||
~DXGraphicsStateGuardian8();
|
~DXGraphicsStateGuardian8();
|
||||||
|
|
||||||
virtual void reset();
|
virtual void reset();
|
||||||
|
|
@ -150,7 +150,8 @@ public:
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// recreate_tex_callback needs these to be public
|
// recreate_tex_callback needs these to be public
|
||||||
DXScreenData scrn;
|
DXScreenData *_pScrn;
|
||||||
|
LPDIRECT3DDEVICE8 _pD3DDevice; // same as pScrn->_pD3DDevice, cached for spd
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual void enable_lighting(bool enable);
|
virtual void enable_lighting(bool enable);
|
||||||
|
|
@ -303,7 +304,9 @@ protected:
|
||||||
DWORD _clip_plane_bits;
|
DWORD _clip_plane_bits;
|
||||||
|
|
||||||
RenderModeAttrib::Mode _current_fill_mode; //poinr/wireframe/solid
|
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
|
// Cur Texture State
|
||||||
TextureApplyAttrib::Mode _CurTexBlendMode;
|
TextureApplyAttrib::Mode _CurTexBlendMode;
|
||||||
|
|
@ -320,9 +323,20 @@ protected:
|
||||||
|
|
||||||
bool _overlay_windows_supported;
|
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:
|
public:
|
||||||
static GraphicsStateGuardian*
|
static GraphicsStateGuardian*
|
||||||
make_DXGraphicsStateGuardian8(const FactoryParams ¶ms);
|
make_DXGraphicsStateGuardian8(const FactoryParams ¶ms);
|
||||||
|
void set_context(DXScreenData *pNewContextData);
|
||||||
|
|
||||||
static TypeHandle get_class_type(void);
|
static TypeHandle get_class_type(void);
|
||||||
static void init_type(void);
|
static void init_type(void);
|
||||||
|
|
@ -347,7 +361,7 @@ public:
|
||||||
bool CheckCooperativeLevel(bool bDoReactivateWindow = false);
|
bool CheckCooperativeLevel(bool bDoReactivateWindow = false);
|
||||||
|
|
||||||
void show_frame(bool bNoNewFrameDrawn = false);
|
void show_frame(bool bNoNewFrameDrawn = false);
|
||||||
void dx_init(HCURSOR hMouseCursor);
|
void dx_init(void);
|
||||||
|
|
||||||
void support_overlay_window(bool flag);
|
void support_overlay_window(bool flag);
|
||||||
|
|
||||||
|
|
@ -355,7 +369,8 @@ private:
|
||||||
static TypeHandle _type_handle;
|
static TypeHandle _type_handle;
|
||||||
};
|
};
|
||||||
|
|
||||||
#include "DXGraphicsStateGuardian8.I"
|
HRESULT CreateDX8Cursor(LPDIRECT3DDEVICE8 pd3dDevice, HCURSOR hCursor,BOOL bAddWatermark);
|
||||||
|
|
||||||
|
#include "DXGraphicsStateGuardian8.I"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1000,6 +1000,8 @@ IDirect3DTexture8 *DXTextureContext8::CreateTexture(DXScreenData &scrn) {
|
||||||
assert(pbuf->get_component_width()==sizeof(BYTE)); // cant handle anything else now
|
assert(pbuf->get_component_width()==sizeof(BYTE)); // cant handle anything else now
|
||||||
assert(pixbuf_type==PixelBuffer::T_unsigned_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)) {
|
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";
|
dxgsg8_cat.error() << "CreateTexture failed, havent handled non 8-bit channel pixelbuffer types yet! \n";
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
@ -1411,7 +1413,7 @@ IDirect3DTexture8 *DXTextureContext8::CreateTexture(DXScreenData &scrn) {
|
||||||
|
|
||||||
if(FAILED( hr = scrn.pD3DDevice->CreateTexture(TargetWidth,TargetHeight,cMipLevelCount,0x0,
|
if(FAILED( hr = scrn.pD3DDevice->CreateTexture(TargetWidth,TargetHeight,cMipLevelCount,0x0,
|
||||||
TargetPixFmt,D3DPOOL_MANAGED,&_pD3DTexture8) )) {
|
TargetPixFmt,D3DPOOL_MANAGED,&_pD3DTexture8) )) {
|
||||||
dxgsg8_cat.error() << "pD3DDevice->CreateTexture() failed!" << D3DERRORSTRING(hr);
|
dxgsg8_cat.error() << "D3D CreateTexture failed!" << D3DERRORSTRING(hr);
|
||||||
goto error_exit;
|
goto error_exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1427,11 +1429,21 @@ IDirect3DTexture8 *DXTextureContext8::CreateTexture(DXScreenData &scrn) {
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
hr = FillDDSurfTexturePixels();
|
// Note: user may want to create an empty "texture" that will be written to by rendering and copy operations.
|
||||||
if(FAILED(hr)) {
|
// this will never have a backing store of main memory in panda fmt, and on disk in a file.
|
||||||
goto error_exit;
|
// 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 the newly created texture
|
||||||
return _pD3DTexture8;
|
return _pD3DTexture8;
|
||||||
|
|
||||||
|
|
@ -1547,18 +1559,21 @@ FillDDSurfTexturePixels(void) {
|
||||||
if(bUsingTempPixBuf) {
|
if(bUsingTempPixBuf) {
|
||||||
SAFE_DELETE_ARRAY(pPixels);
|
SAFE_DELETE_ARRAY(pPixels);
|
||||||
}
|
}
|
||||||
RELEASE(pMipLevel0,dxgsg8,"texture",RELEASE_ONCE);
|
RELEASE(pMipLevel0,dxgsg8,"FillDDSurf MipLev0 texture ptr",RELEASE_ONCE);
|
||||||
return hr;
|
return hr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// Name: DeleteTexture()
|
// Name: DeleteTexture()
|
||||||
// Desc: Release the surface used to store the texture
|
// Desc: Release the surface used to store the texture
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
void DXTextureContext8::
|
void DXTextureContext8::
|
||||||
DeleteTexture( ) {
|
DeleteTexture( ) {
|
||||||
|
if(_pD3DTexture8==NULL) {
|
||||||
|
// dont bother printing the msg below, since we already released it.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if(dxgsg8_cat.is_spam()) {
|
if(dxgsg8_cat.is_spam()) {
|
||||||
dxgsg8_cat.spam() << "Deleting DX texture for " << _tex->get_name() << "\n";
|
dxgsg8_cat.spam() << "Deleting DX texture for " << _tex->get_name() << "\n";
|
||||||
}
|
}
|
||||||
|
|
@ -1603,6 +1618,9 @@ TextureContext(tex) {
|
||||||
|
|
||||||
DXTextureContext8::
|
DXTextureContext8::
|
||||||
~DXTextureContext8() {
|
~DXTextureContext8() {
|
||||||
|
if(dxgsg8_cat.is_spam()) {
|
||||||
|
dxgsg8_cat.spam() << "Deleting DX8 TexContext for " << _tex->get_name() << "\n";
|
||||||
|
}
|
||||||
DeleteTexture();
|
DeleteTexture();
|
||||||
TextureContext::~TextureContext();
|
TextureContext::~TextureContext();
|
||||||
_tex = NULL;
|
_tex = NULL;
|
||||||
|
|
|
||||||
|
|
@ -19,9 +19,6 @@
|
||||||
#ifndef DXGSG8BASE_H
|
#ifndef DXGSG8BASE_H
|
||||||
#define 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
|
// include win32 defns for everything up to WinServer2003, and assume I'm smart enough to
|
||||||
// use GetProcAddress for backward compat on newer fns
|
// use GetProcAddress for backward compat on newer fns
|
||||||
// Note DX8 cannot be installed on w95, so OK to assume base of win98
|
// Note DX8 cannot be installed on w95, so OK to assume base of win98
|
||||||
|
|
@ -41,6 +38,9 @@
|
||||||
#include <dxerr8.h>
|
#include <dxerr8.h>
|
||||||
#undef WIN32_LEAN_AND_MEAN
|
#undef WIN32_LEAN_AND_MEAN
|
||||||
|
|
||||||
|
#include "pandabase.h"
|
||||||
|
#include "graphicsWindow.h"
|
||||||
|
|
||||||
#if D3D_SDK_VERSION != 220
|
#if D3D_SDK_VERSION != 220
|
||||||
#error you have DX 8.0 headers, not DX 8.1, you need to install DX 8.1 SDK!
|
#error you have DX 8.0 headers, not DX 8.1, you need to install DX 8.1 SDK!
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -61,6 +61,11 @@
|
||||||
#endif
|
#endif
|
||||||
#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
|
#define D3D_MAXTEXTURESTAGES 8
|
||||||
|
|
||||||
typedef enum {VertexShader,PixelShader} ShaderType;
|
typedef enum {VertexShader,PixelShader} ShaderType;
|
||||||
|
|
@ -82,12 +87,15 @@ typedef DWORD DXShaderHandle;
|
||||||
|
|
||||||
// for stuff outside a panda class
|
// for stuff outside a panda class
|
||||||
#define SAFE_RELEASE(p) { if(p) { assert(IS_VALID_PTR(p)); (p)->Release(); (p)=NULL; } }
|
#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()
|
// this is bDoDownToZero argument to RELEASE()
|
||||||
#define RELEASE_DOWN_TO_ZERO true
|
#define RELEASE_DOWN_TO_ZERO true
|
||||||
#define RELEASE_ONCE false
|
#define RELEASE_ONCE false
|
||||||
|
|
||||||
//#define DEBUG_RELEASES
|
|
||||||
|
// uncomment to add refcnt debug output
|
||||||
|
#define DEBUG_RELEASES
|
||||||
|
|
||||||
#ifdef DEBUG_RELEASES
|
#ifdef DEBUG_RELEASES
|
||||||
#define RELEASE(OBJECT,MODULE,DBGSTR,bDoDownToZero) { \
|
#define RELEASE(OBJECT,MODULE,DBGSTR,bDoDownToZero) { \
|
||||||
|
|
@ -183,7 +191,7 @@ typedef enum {
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
LPDIRECT3DDEVICE8 pD3DDevice;
|
LPDIRECT3DDEVICE8 pD3DDevice;
|
||||||
LPDIRECT3D8 pD3D8;
|
LPDIRECT3D8 pD3D8; // copied from DXGraphicsPipe8 for convenience
|
||||||
HWND hWnd;
|
HWND hWnd;
|
||||||
HMONITOR hMon;
|
HMONITOR hMon;
|
||||||
DWORD MaxAvailVidMem;
|
DWORD MaxAvailVidMem;
|
||||||
|
|
@ -203,5 +211,11 @@ typedef struct {
|
||||||
D3DADAPTER_IDENTIFIER8 DXDeviceID;
|
D3DADAPTER_IDENTIFIER8 DXDeviceID;
|
||||||
} DXScreenData;
|
} DXScreenData;
|
||||||
|
|
||||||
|
|
||||||
|
//utility stuff
|
||||||
|
extern map<D3DFORMAT_FLAG,D3DFORMAT> g_D3DFORMATmap;
|
||||||
|
extern void Init_D3DFORMAT_map(void);
|
||||||
|
extern const char *D3DFormatStr(D3DFORMAT fmt);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -23,10 +23,8 @@
|
||||||
TypeHandle wdxGraphicsPipe8::_type_handle;
|
TypeHandle wdxGraphicsPipe8::_type_handle;
|
||||||
|
|
||||||
// #define LOWVIDMEMTHRESHOLD 3500000
|
// #define LOWVIDMEMTHRESHOLD 3500000
|
||||||
// #define CRAPPY_DRIVER_IS_LYING_VIDMEMTHRESHOLD 1000000
|
|
||||||
#define LOWVIDMEMTHRESHOLD 5700000 // 4MB cards should fall below this
|
#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 CRAPPY_DRIVER_IS_LYING_VIDMEMTHRESHOLD 1000000 // if # is > 1MB, card is lying and I cant tell what it is
|
||||||
|
|
||||||
#define UNKNOWN_VIDMEM_SIZE 0xFFFFFFFF
|
#define UNKNOWN_VIDMEM_SIZE 0xFFFFFFFF
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
|
|
@ -38,6 +36,7 @@ wdxGraphicsPipe8::
|
||||||
wdxGraphicsPipe8() {
|
wdxGraphicsPipe8() {
|
||||||
_hDDrawDLL = NULL;
|
_hDDrawDLL = NULL;
|
||||||
_hD3D8_DLL = NULL;
|
_hD3D8_DLL = NULL;
|
||||||
|
_pD3D8 = NULL;
|
||||||
_is_valid = init();
|
_is_valid = init();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -48,14 +47,10 @@ wdxGraphicsPipe8() {
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
wdxGraphicsPipe8::
|
wdxGraphicsPipe8::
|
||||||
~wdxGraphicsPipe8() {
|
~wdxGraphicsPipe8() {
|
||||||
if (_hDDrawDLL != NULL) {
|
|
||||||
FreeLibrary(_hDDrawDLL);
|
RELEASE(_pD3D8,wdxdisplay8,"ID3D8",RELEASE_DOWN_TO_ZERO);
|
||||||
_hDDrawDLL = NULL;
|
SAFE_FREELIB(_hD3D8_DLL);
|
||||||
}
|
SAFE_FREELIB(_hDDrawDLL);
|
||||||
if(_hD3D8_DLL != NULL) {
|
|
||||||
FreeLibrary(_hD3D8_DLL);
|
|
||||||
_hD3D8_DLL = NULL;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
|
|
@ -91,12 +86,14 @@ pipe_constructor() {
|
||||||
// Description: Creates a new window on the pipe, if possible.
|
// Description: Creates a new window on the pipe, if possible.
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
PT(GraphicsWindow) wdxGraphicsPipe8::
|
PT(GraphicsWindow) wdxGraphicsPipe8::
|
||||||
make_window() {
|
make_window(GraphicsStateGuardian *gsg) {
|
||||||
if (!_is_valid) {
|
if (!_is_valid) {
|
||||||
return NULL;
|
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::
|
bool wdxGraphicsPipe8::
|
||||||
init() {
|
init() {
|
||||||
static const char * const ddraw_name = "ddraw.dll";
|
if(!MyLoadLib(_hDDrawDLL,"ddraw.dll")) {
|
||||||
_hDDrawDLL = LoadLibrary(ddraw_name);
|
goto error;
|
||||||
if(_hDDrawDLL == 0) {
|
|
||||||
wdxdisplay8_cat.error()
|
|
||||||
<< "can't locate " << ddraw_name << "!\n";
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_DirectDrawCreateEx =
|
if(!MyGetProcAddr(_hDDrawDLL, (FARPROC*)&_DirectDrawCreateEx, "DirectDrawCreateEx")) {
|
||||||
(LPDIRECTDRAWCREATEEX)GetProcAddress(_hDDrawDLL, "DirectDrawCreateEx");
|
goto error;
|
||||||
if (_DirectDrawCreateEx == NULL) {
|
|
||||||
wdxdisplay8_cat.error()
|
|
||||||
<< "GetProcAddr failed for DDCreateEx" << endl;
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_DirectDrawEnumerateExA = (LPDIRECTDRAWENUMERATEEX)GetProcAddress(_hDDrawDLL, "DirectDrawEnumerateExA");
|
if(!MyGetProcAddr(_hDDrawDLL, (FARPROC*)&_DirectDrawEnumerateExA, "DirectDrawEnumerateExA")) {
|
||||||
if (_DirectDrawEnumerateExA == NULL) {
|
goto error;
|
||||||
wdxdisplay8_cat.error()
|
|
||||||
<< "GetProcAddr failed for DirectDrawEnumerateEx! (win95 system?)\n";
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char * const d3d8_name = "d3d8.dll";
|
if(!MyLoadLib(_hD3D8_DLL,"d3d8.dll")) {
|
||||||
_hD3D8_DLL = LoadLibrary(d3d8_name);
|
goto error;
|
||||||
if (_hD3D8_DLL == 0) {
|
|
||||||
wdxdisplay8_cat.error()
|
|
||||||
<< "PandaDX8 requires DX8, can't locate " << d3d8_name << "!\n";
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// dont want to statically link to possibly non-existent d3d8 dll,
|
if(!MyGetProcAddr(_hD3D8_DLL, (FARPROC*)&_Direct3DCreate8, "Direct3DCreate8")) {
|
||||||
// so must call D3DCr8 indirectly
|
goto error;
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
|
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();
|
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);
|
hr = pDD->GetAvailableVidMem(&ddsGAVMCaps, &dwVidMemTotal, &dwVidMemFree);
|
||||||
if (FAILED(hr)) {
|
if (FAILED(hr)) {
|
||||||
wdxdisplay8_cat.error()
|
wdxdisplay8_cat.error() << "GetAvailableVidMem failed for device #"<< i<< D3DERRORSTRING(hr);
|
||||||
<< "GetAvailableVidMem failed for device #"<< i<< D3DERRORSTRING(hr);
|
// sometimes GetAvailableVidMem fails with hr=DDERR_NODIRECTDRAWHW for some unknown reason (bad drivers?)
|
||||||
// goto skip_device;
|
// 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
|
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
|
// registry location for a given card
|
||||||
|
|
||||||
// assume buggy drivers (this means you, FireGL2) may return zero
|
// assume buggy drivers (this means you, FireGL2) may return zero
|
||||||
// (or small amts) for dwVidMemTotal, so ignore value if its <
|
// (or small amts) for dwVidMemTotal, so ignore value if its < CRAPPY_DRIVER_IS_LYING_VIDMEMTHRESHOLD
|
||||||
// CRAPPY_DRIVER_IS_LYING_VIDMEMTHRESHOLD
|
|
||||||
bool bLowVidMemFlag =
|
bool bLowVidMemFlag =
|
||||||
((dwVidMemTotal > CRAPPY_DRIVER_IS_LYING_VIDMEMTHRESHOLD) &&
|
((dwVidMemTotal > CRAPPY_DRIVER_IS_LYING_VIDMEMTHRESHOLD) &&
|
||||||
(dwVidMemTotal< LOWVIDMEMTHRESHOLD));
|
(dwVidMemTotal< LOWVIDMEMTHRESHOLD));
|
||||||
|
|
@ -352,3 +372,519 @@ dx7_driver_enum_callback(GUID *pGUID, TCHAR *strDesc, TCHAR *strName,
|
||||||
|
|
||||||
return DDENUMRET_OK;
|
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 "pandabase.h"
|
||||||
#include "winGraphicsPipe.h"
|
#include "winGraphicsPipe.h"
|
||||||
#include "pvector.h"
|
#include "pvector.h"
|
||||||
|
#include "dxgsg8base.h"
|
||||||
#include <ddraw.h>
|
#include <ddraw.h>
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
|
@ -48,8 +48,25 @@ public:
|
||||||
virtual string get_interface_name() const;
|
virtual string get_interface_name() const;
|
||||||
static PT(GraphicsPipe) pipe_constructor();
|
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:
|
protected:
|
||||||
virtual PT(GraphicsWindow) make_window();
|
virtual PT(GraphicsWindow) make_window(GraphicsStateGuardian *gsg);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool init();
|
bool init();
|
||||||
|
|
@ -62,6 +79,8 @@ private:
|
||||||
private:
|
private:
|
||||||
HINSTANCE _hDDrawDLL;
|
HINSTANCE _hDDrawDLL;
|
||||||
HINSTANCE _hD3D8_DLL;
|
HINSTANCE _hD3D8_DLL;
|
||||||
|
LPDIRECT3D8 _pD3D8;
|
||||||
|
|
||||||
|
|
||||||
typedef LPDIRECT3D8 (WINAPI *Direct3DCreate8_ProcPtr)(UINT SDKVersion);
|
typedef LPDIRECT3D8 (WINAPI *Direct3DCreate8_ProcPtr)(UINT SDKVersion);
|
||||||
typedef HRESULT (WINAPI * LPDIRECTDRAWCREATEEX)(GUID FAR * lpGuid, LPVOID *lplpDD, REFIID iid, IUnknown FAR *pUnkOuter);
|
typedef HRESULT (WINAPI * LPDIRECTDRAWCREATEEX)(GUID FAR * lpGuid, LPVOID *lplpDD, REFIID iid, IUnknown FAR *pUnkOuter);
|
||||||
|
|
@ -83,7 +102,7 @@ private:
|
||||||
|
|
||||||
typedef pvector<CardID> CardIDs;
|
typedef pvector<CardID> CardIDs;
|
||||||
CardIDs _card_ids;
|
CardIDs _card_ids;
|
||||||
|
bool _bIsDX81;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static TypeHandle get_class_type() {
|
static TypeHandle get_class_type() {
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load Diff
|
|
@ -16,8 +16,8 @@
|
||||||
//
|
//
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
#ifndef WDXGRAPHICSWINDOW8_H
|
#ifndef wdxGraphicsWindow8_H
|
||||||
#define WDXGRAPHICSWINDOW8_H
|
#define wdxGraphicsWindow8_H
|
||||||
|
|
||||||
#include "pandabase.h"
|
#include "pandabase.h"
|
||||||
#include "winGraphicsWindow.h"
|
#include "winGraphicsWindow.h"
|
||||||
|
|
@ -39,16 +39,16 @@ static const int WDXWIN_EVENT = 8;
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
class EXPCL_PANDADX wdxGraphicsWindow8 : public WinGraphicsWindow {
|
class EXPCL_PANDADX wdxGraphicsWindow8 : public WinGraphicsWindow {
|
||||||
public:
|
public:
|
||||||
wdxGraphicsWindow8(GraphicsPipe *pipe);
|
wdxGraphicsWindow8(GraphicsPipe *pipe, GraphicsStateGuardian *gsg);
|
||||||
virtual ~wdxGraphicsWindow8();
|
virtual ~wdxGraphicsWindow8();
|
||||||
|
virtual bool open_window(void);
|
||||||
virtual void make_gsg();
|
|
||||||
virtual void release_gsg();
|
|
||||||
|
|
||||||
virtual int verify_window_sizes(int numsizes, int *dimen);
|
virtual int verify_window_sizes(int numsizes, int *dimen);
|
||||||
|
|
||||||
virtual bool begin_frame();
|
virtual bool begin_frame();
|
||||||
virtual void end_flip();
|
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:
|
protected:
|
||||||
virtual void fullscreen_restored(WindowProperties &properties);
|
virtual void fullscreen_restored(WindowProperties &properties);
|
||||||
|
|
@ -60,30 +60,26 @@ private:
|
||||||
void create_screen_buffers_and_device(DXScreenData &Display,
|
void create_screen_buffers_and_device(DXScreenData &Display,
|
||||||
bool force_16bpp_zbuffer);
|
bool force_16bpp_zbuffer);
|
||||||
|
|
||||||
bool choose_adapter(LPDIRECT3D8 pD3D8);
|
bool choose_device(void);
|
||||||
bool search_for_device(LPDIRECT3D8 pD3D8, DXDeviceInfo *device_info);
|
bool search_for_device(wdxGraphicsPipe8 *dxpipe, DXDeviceInfo *device_info);
|
||||||
|
|
||||||
// void set_coop_levels_and_display_modes();
|
// 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,
|
void search_for_valid_displaymode(UINT RequestedX_Size, UINT RequestedY_Size,
|
||||||
bool bWantZBuffer, bool bWantStencil,
|
bool bWantZBuffer, bool bWantStencil,
|
||||||
UINT *pSupportedScreenDepthsMask,
|
UINT *pSupportedScreenDepthsMask,
|
||||||
bool *pCouldntFindAnyValidZBuf,
|
bool *pCouldntFindAnyValidZBuf,
|
||||||
D3DFORMAT *pSuggestedPixFmt,
|
D3DFORMAT *pSuggestedPixFmt,
|
||||||
bool bVerboseMode = false);
|
bool bVerboseMode = false);
|
||||||
|
*/
|
||||||
bool reset_device_resize_window(UINT new_xsize, UINT new_ysize);
|
bool reset_device_resize_window(UINT new_xsize, UINT new_ysize);
|
||||||
void init_resized_window();
|
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 int D3DFMT_to_DepthBits(D3DFORMAT fmt);
|
||||||
static bool is_badvidmem_card(D3DADAPTER_IDENTIFIER8 *pDevID);
|
static bool is_badvidmem_card(D3DADAPTER_IDENTIFIER8 *pDevID);
|
||||||
|
|
||||||
DXGraphicsStateGuardian8 *_dxgsg;
|
DXGraphicsStateGuardian8 *_dxgsg;
|
||||||
|
DXScreenData _wcontext;
|
||||||
|
|
||||||
int _depth_buffer_bpp;
|
int _depth_buffer_bpp;
|
||||||
bool _awaiting_restore;
|
bool _awaiting_restore;
|
||||||
|
|
||||||
|
|
@ -100,6 +96,7 @@ public:
|
||||||
return get_class_type();
|
return get_class_type();
|
||||||
}
|
}
|
||||||
virtual TypeHandle force_init_type() {init_type(); return get_class_type();}
|
virtual TypeHandle force_init_type() {init_type(); return get_class_type();}
|
||||||
|
virtual void make_current(void);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static TypeHandle _type_handle;
|
static TypeHandle _type_handle;
|
||||||
|
|
|
||||||
|
|
@ -198,10 +198,15 @@ open_window(const WindowProperties &props, GraphicsPipe *pipe) {
|
||||||
wf->set_two_sided(get_two_sided());
|
wf->set_two_sided(get_two_sided());
|
||||||
wf->set_lighting(get_lighting());
|
wf->set_lighting(get_lighting());
|
||||||
wf->set_background_type(get_background_type());
|
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);
|
_windows.push_back(wf);
|
||||||
|
|
||||||
wf->open_window(props, &_engine, pipe);
|
|
||||||
|
|
||||||
return wf;
|
return wf;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -95,7 +95,14 @@ open_window(const WindowProperties &props, GraphicsEngine *engine,
|
||||||
GraphicsPipe *pipe) {
|
GraphicsPipe *pipe) {
|
||||||
nassertr(_window == (GraphicsWindow *)NULL, _window);
|
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) {
|
if (_window != (GraphicsWindow *)NULL) {
|
||||||
_window->request_properties(props);
|
_window->request_properties(props);
|
||||||
set_background_type(_background_type);
|
set_background_type(_background_type);
|
||||||
|
|
|
||||||
|
|
@ -163,8 +163,9 @@ uchar_bgra_to_rgba(unsigned char *dest, const unsigned char *source,
|
||||||
// Description:
|
// Description:
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
GLGraphicsStateGuardian::
|
GLGraphicsStateGuardian::
|
||||||
GLGraphicsStateGuardian(GraphicsWindow *win) : GraphicsStateGuardian(win) {
|
GLGraphicsStateGuardian(const FrameBufferProperties &properties) :
|
||||||
reset();
|
GraphicsStateGuardian(properties)
|
||||||
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
|
|
@ -174,9 +175,7 @@ GLGraphicsStateGuardian(GraphicsWindow *win) : GraphicsStateGuardian(win) {
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
GLGraphicsStateGuardian::
|
GLGraphicsStateGuardian::
|
||||||
~GLGraphicsStateGuardian() {
|
~GLGraphicsStateGuardian() {
|
||||||
free_pointers();
|
close_gsg();
|
||||||
release_all_textures();
|
|
||||||
release_all_geoms();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
|
|
@ -1637,7 +1636,9 @@ release_texture(TextureContext *tc) {
|
||||||
GLTextureContext *gtc = DCAST(GLTextureContext, tc);
|
GLTextureContext *gtc = DCAST(GLTextureContext, tc);
|
||||||
Texture *tex = tc->_texture;
|
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);
|
glDeleteTextures(1, >c->_index);
|
||||||
}
|
}
|
||||||
gtc->_index = 0;
|
gtc->_index = 0;
|
||||||
|
|
@ -1651,7 +1652,9 @@ release_texture(TextureContext *tc) {
|
||||||
tex->clear_gsg(this);
|
tex->clear_gsg(this);
|
||||||
|
|
||||||
delete gtc;
|
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::
|
void GLGraphicsStateGuardian::
|
||||||
texture_to_pixel_buffer(TextureContext *tc, PixelBuffer *pb) {
|
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);
|
nassertv(tc != NULL && pb != NULL);
|
||||||
Texture *tex = tc->_texture;
|
Texture *tex = tc->_texture;
|
||||||
|
|
||||||
|
|
@ -1914,6 +1920,7 @@ texture_to_pixel_buffer(TextureContext *tc, PixelBuffer *pb) {
|
||||||
|
|
||||||
pop_frame_buffer(old_fb);
|
pop_frame_buffer(old_fb);
|
||||||
report_gl_errors();
|
report_gl_errors();
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
|
|
@ -3000,6 +3007,9 @@ draw_texture(TextureContext *tc, const DisplayRegion *dr,
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
void GLGraphicsStateGuardian::
|
void GLGraphicsStateGuardian::
|
||||||
draw_pixel_buffer(PixelBuffer *pb, const DisplayRegion *dr) {
|
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 != NULL && dr != NULL);
|
||||||
nassertv(!pb->_image.empty());
|
nassertv(!pb->_image.empty());
|
||||||
DisplayRegionStack old_dr = push_display_region(dr);
|
DisplayRegionStack old_dr = push_display_region(dr);
|
||||||
|
|
@ -3109,6 +3119,7 @@ draw_pixel_buffer(PixelBuffer *pb, const DisplayRegion *dr) {
|
||||||
|
|
||||||
pop_display_region(old_dr);
|
pop_display_region(old_dr);
|
||||||
report_gl_errors();
|
report_gl_errors();
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
|
|
|
||||||
|
|
@ -63,8 +63,8 @@ INLINE ostream &operator << (ostream &out, GLenum v) {
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
class EXPCL_PANDAGL GLGraphicsStateGuardian : public GraphicsStateGuardian {
|
class EXPCL_PANDAGL GLGraphicsStateGuardian : public GraphicsStateGuardian {
|
||||||
public:
|
public:
|
||||||
GLGraphicsStateGuardian(GraphicsWindow *win);
|
GLGraphicsStateGuardian(const FrameBufferProperties &properties);
|
||||||
~GLGraphicsStateGuardian();
|
virtual ~GLGraphicsStateGuardian();
|
||||||
|
|
||||||
virtual void reset();
|
virtual void reset();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,8 @@
|
||||||
config_glxdisplay.cxx config_glxdisplay.h \
|
config_glxdisplay.cxx config_glxdisplay.h \
|
||||||
glxGraphicsPipe.I glxGraphicsPipe.cxx \
|
glxGraphicsPipe.I glxGraphicsPipe.cxx \
|
||||||
glxGraphicsPipe.h glxGraphicsWindow.I glxGraphicsWindow.cxx \
|
glxGraphicsPipe.h glxGraphicsWindow.I glxGraphicsWindow.cxx \
|
||||||
|
glxGraphicsStateGuardian.h glxGraphicsStateGuardian.I \
|
||||||
|
glxGraphicsStateGuardian.cxx \
|
||||||
glxGraphicsWindow.h
|
glxGraphicsWindow.h
|
||||||
|
|
||||||
#define INSTALL_HEADERS \
|
#define INSTALL_HEADERS \
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,7 @@
|
||||||
#include "config_glxdisplay.h"
|
#include "config_glxdisplay.h"
|
||||||
#include "glxGraphicsPipe.h"
|
#include "glxGraphicsPipe.h"
|
||||||
#include "glxGraphicsWindow.h"
|
#include "glxGraphicsWindow.h"
|
||||||
|
#include "glxGraphicsStateGuardian.h"
|
||||||
#include "graphicsPipeSelection.h"
|
#include "graphicsPipeSelection.h"
|
||||||
#include "dconfig.h"
|
#include "dconfig.h"
|
||||||
|
|
||||||
|
|
@ -47,12 +48,11 @@ init_libglxdisplay() {
|
||||||
|
|
||||||
glxGraphicsPipe::init_type();
|
glxGraphicsPipe::init_type();
|
||||||
glxGraphicsWindow::init_type();
|
glxGraphicsWindow::init_type();
|
||||||
|
glxGraphicsStateGuardian::init_type();
|
||||||
|
|
||||||
GraphicsPipeSelection *selection = GraphicsPipeSelection::get_global_ptr();
|
GraphicsPipeSelection *selection = GraphicsPipeSelection::get_global_ptr();
|
||||||
selection->add_pipe_type(glxGraphicsPipe::get_class_type(),
|
selection->add_pipe_type(glxGraphicsPipe::get_class_type(),
|
||||||
glxGraphicsPipe::pipe_constructor);
|
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", "");
|
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 EXPCL_PANDAGL void init_libglxdisplay();
|
||||||
|
|
||||||
extern bool gl_show_fps_meter;
|
|
||||||
extern float gl_fps_meter_update_interval;
|
|
||||||
extern const string display_cfg;
|
extern const string display_cfg;
|
||||||
|
|
||||||
#endif /* __CONFIG_GLXDISPLAY_H__ */
|
#endif /* __CONFIG_GLXDISPLAY_H__ */
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,9 @@
|
||||||
|
|
||||||
#include "glxGraphicsPipe.h"
|
#include "glxGraphicsPipe.h"
|
||||||
#include "glxGraphicsWindow.h"
|
#include "glxGraphicsWindow.h"
|
||||||
|
#include "glxGraphicsStateGuardian.h"
|
||||||
#include "config_glxdisplay.h"
|
#include "config_glxdisplay.h"
|
||||||
|
#include "frameBufferProperties.h"
|
||||||
#include "mutexHolder.h"
|
#include "mutexHolder.h"
|
||||||
|
|
||||||
#include <GL/glx.h>
|
#include <GL/glx.h>
|
||||||
|
|
@ -116,18 +118,363 @@ pipe_constructor() {
|
||||||
return new glxGraphicsPipe;
|
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
|
// Function: glxGraphicsPipe::make_window
|
||||||
// Access: Protected, Virtual
|
// Access: Protected, Virtual
|
||||||
// Description: Creates a new window on the pipe, if possible.
|
// Description: Creates a new window on the pipe, if possible.
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
PT(GraphicsWindow) glxGraphicsPipe::
|
PT(GraphicsWindow) glxGraphicsPipe::
|
||||||
make_window() {
|
make_window(GraphicsStateGuardian *gsg) {
|
||||||
if (!_is_valid) {
|
if (!_is_valid) {
|
||||||
return NULL;
|
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 "pandabase.h"
|
||||||
#include "graphicsPipe.h"
|
#include "graphicsPipe.h"
|
||||||
|
|
||||||
#include <X11/Xlib.h>
|
|
||||||
|
|
||||||
class glxGraphicsWindow;
|
class glxGraphicsWindow;
|
||||||
|
class FrameBufferProperties;
|
||||||
|
|
||||||
#ifdef CPPPARSER
|
#ifdef CPPPARSER
|
||||||
// A simple hack so interrogate can parse this file.
|
// A simple hack so interrogate can parse this file.
|
||||||
typedef int Display;
|
typedef int Display;
|
||||||
typedef int Window;
|
typedef int Window;
|
||||||
typedef int XErrorEvent;
|
typedef int XErrorEvent;
|
||||||
|
typedef int XVisualInfo;
|
||||||
typedef int Atom;
|
typedef int Atom;
|
||||||
#endif
|
#else
|
||||||
|
#include <X11/Xlib.h>
|
||||||
|
#include <GL/glx.h>
|
||||||
|
#endif // CPPPARSER
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Class : glxGraphicsPipe
|
// Class : glxGraphicsPipe
|
||||||
|
|
@ -55,9 +58,14 @@ public:
|
||||||
INLINE Atom get_wm_delete_window() const;
|
INLINE Atom get_wm_delete_window() const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual PT(GraphicsWindow) make_window();
|
virtual PT(GraphicsStateGuardian) make_gsg(const FrameBufferProperties &properties);
|
||||||
|
virtual PT(GraphicsWindow) make_window(GraphicsStateGuardian *gsg);
|
||||||
|
|
||||||
private:
|
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 void install_error_handlers();
|
||||||
static int error_handler(Display *display, XErrorEvent *error);
|
static int error_handler(Display *display, XErrorEvent *error);
|
||||||
static int io_error_handler(Display *display);
|
static int io_error_handler(Display *display);
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,7 @@
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
#include "glxGraphicsWindow.h"
|
#include "glxGraphicsWindow.h"
|
||||||
|
#include "glxGraphicsStateGuardian.h"
|
||||||
#include "config_glxdisplay.h"
|
#include "config_glxdisplay.h"
|
||||||
#include "glxGraphicsPipe.h"
|
#include "glxGraphicsPipe.h"
|
||||||
|
|
||||||
|
|
@ -39,16 +40,14 @@ TypeHandle glxGraphicsWindow::_type_handle;
|
||||||
// Description:
|
// Description:
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
glxGraphicsWindow::
|
glxGraphicsWindow::
|
||||||
glxGraphicsWindow(GraphicsPipe *pipe) :
|
glxGraphicsWindow(GraphicsPipe *pipe, GraphicsStateGuardian *gsg) :
|
||||||
GraphicsWindow(pipe)
|
GraphicsWindow(pipe, gsg)
|
||||||
{
|
{
|
||||||
glxGraphicsPipe *glx_pipe;
|
glxGraphicsPipe *glx_pipe;
|
||||||
DCAST_INTO_V(glx_pipe, _pipe);
|
DCAST_INTO_V(glx_pipe, _pipe);
|
||||||
_display = glx_pipe->get_display();
|
_display = glx_pipe->get_display();
|
||||||
_screen = glx_pipe->get_screen();
|
_screen = glx_pipe->get_screen();
|
||||||
_xwindow = (Window)0;
|
_xwindow = (Window)NULL;
|
||||||
_context = (GLXContext)0;
|
|
||||||
_visual = (XVisualInfo *)NULL;
|
|
||||||
_awaiting_configure = false;
|
_awaiting_configure = false;
|
||||||
_wm_delete_window = glx_pipe->get_wm_delete_window();
|
_wm_delete_window = glx_pipe->get_wm_delete_window();
|
||||||
|
|
||||||
|
|
@ -66,49 +65,6 @@ glxGraphicsWindow::
|
||||||
~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
|
// Function: glxGraphicsWindow::make_current
|
||||||
// Access: Public, Virtual
|
// Access: Public, Virtual
|
||||||
|
|
@ -118,8 +74,30 @@ release_gsg() {
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
void glxGraphicsWindow::
|
void glxGraphicsWindow::
|
||||||
make_current() {
|
make_current() {
|
||||||
nassertv(_gsg != (GraphicsStateGuardian *)NULL);
|
glxGraphicsStateGuardian *glxgsg;
|
||||||
glXMakeCurrent(_display, _xwindow, _context);
|
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::
|
void glxGraphicsWindow::
|
||||||
begin_flip() {
|
begin_flip() {
|
||||||
if (_gsg != (GraphicsStateGuardian *)NULL) {
|
if (_gsg != (GraphicsStateGuardian *)NULL) {
|
||||||
glXMakeCurrent(_display, _xwindow, _context);
|
make_current();
|
||||||
glXSwapBuffers(_display, _xwindow);
|
glXSwapBuffers(_display, _xwindow);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -371,7 +349,7 @@ set_properties_now(WindowProperties &properties) {
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
void glxGraphicsWindow::
|
void glxGraphicsWindow::
|
||||||
close_window() {
|
close_window() {
|
||||||
if (_xwindow != (Window)0) {
|
if (_xwindow != (Window)NULL) {
|
||||||
XDestroyWindow(_display, _xwindow);
|
XDestroyWindow(_display, _xwindow);
|
||||||
_xwindow = (Window)0;
|
_xwindow = (Window)0;
|
||||||
|
|
||||||
|
|
@ -404,12 +382,12 @@ open_window() {
|
||||||
|
|
||||||
glxGraphicsPipe *glx_pipe;
|
glxGraphicsPipe *glx_pipe;
|
||||||
DCAST_INTO_R(glx_pipe, _pipe, false);
|
DCAST_INTO_R(glx_pipe, _pipe, false);
|
||||||
|
glxGraphicsStateGuardian *glxgsg;
|
||||||
|
DCAST_INTO_R(glxgsg, _gsg, false);
|
||||||
|
|
||||||
Window root_window = glx_pipe->get_root();
|
Window root_window = glx_pipe->get_root();
|
||||||
|
|
||||||
if (!choose_visual()) {
|
setup_colormap(glxgsg->_visual);
|
||||||
return false;
|
|
||||||
}
|
|
||||||
setup_colormap();
|
|
||||||
|
|
||||||
_event_mask =
|
_event_mask =
|
||||||
ButtonPressMask | ButtonReleaseMask |
|
ButtonPressMask | ButtonReleaseMask |
|
||||||
|
|
@ -434,7 +412,7 @@ open_window() {
|
||||||
_properties.get_x_origin(), _properties.get_y_origin(),
|
_properties.get_x_origin(), _properties.get_y_origin(),
|
||||||
_properties.get_x_size(), _properties.get_y_size(),
|
_properties.get_x_size(), _properties.get_y_size(),
|
||||||
0,
|
0,
|
||||||
_visual->depth, InputOutput, _visual->visual,
|
glxgsg->_visual->depth, InputOutput, glxgsg->_visual->visual,
|
||||||
attrib_mask, &wa);
|
attrib_mask, &wa);
|
||||||
|
|
||||||
if (_xwindow == (Window)0) {
|
if (_xwindow == (Window)0) {
|
||||||
|
|
@ -538,315 +516,6 @@ set_wm_properties(const WindowProperties &properties) {
|
||||||
sizeof(protocols) / sizeof(Atom));
|
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
|
// Function: glxGraphicsWindow::setup_colormap
|
||||||
// Access: Private
|
// Access: Private
|
||||||
|
|
@ -854,17 +523,17 @@ choose_visual() {
|
||||||
// stores in in the _colormap method.
|
// stores in in the _colormap method.
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
void glxGraphicsWindow::
|
void glxGraphicsWindow::
|
||||||
setup_colormap() {
|
setup_colormap(XVisualInfo *visual) {
|
||||||
glxGraphicsPipe *glx_pipe;
|
glxGraphicsPipe *glx_pipe;
|
||||||
DCAST_INTO_V(glx_pipe, _pipe);
|
DCAST_INTO_V(glx_pipe, _pipe);
|
||||||
Window root_window = glx_pipe->get_root();
|
Window root_window = glx_pipe->get_root();
|
||||||
|
|
||||||
int visual_class = _visual->c_class;
|
int visual_class = visual->c_class;
|
||||||
int rc, is_rgb;
|
int rc, is_rgb;
|
||||||
|
|
||||||
switch (visual_class) {
|
switch (visual_class) {
|
||||||
case PseudoColor:
|
case PseudoColor:
|
||||||
rc = glXGetConfig(_display, _visual, GLX_RGBA, &is_rgb);
|
rc = glXGetConfig(_display, visual, GLX_RGBA, &is_rgb);
|
||||||
if (rc == 0 && is_rgb) {
|
if (rc == 0 && is_rgb) {
|
||||||
glxdisplay_cat.warning()
|
glxdisplay_cat.warning()
|
||||||
<< "mesa pseudocolor not supported.\n";
|
<< "mesa pseudocolor not supported.\n";
|
||||||
|
|
@ -873,19 +542,19 @@ setup_colormap() {
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
_colormap = XCreateColormap(_display, root_window,
|
_colormap = XCreateColormap(_display, root_window,
|
||||||
_visual->visual, AllocAll);
|
visual->visual, AllocAll);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case TrueColor:
|
case TrueColor:
|
||||||
case DirectColor:
|
case DirectColor:
|
||||||
_colormap = XCreateColormap(_display, root_window,
|
_colormap = XCreateColormap(_display, root_window,
|
||||||
_visual->visual, AllocNone);
|
visual->visual, AllocNone);
|
||||||
break;
|
break;
|
||||||
case StaticColor:
|
case StaticColor:
|
||||||
case StaticGray:
|
case StaticGray:
|
||||||
case GrayScale:
|
case GrayScale:
|
||||||
_colormap = XCreateColormap(_display, root_window,
|
_colormap = XCreateColormap(_display, root_window,
|
||||||
_visual->visual, AllocNone);
|
visual->visual, AllocNone);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
glxdisplay_cat.error()
|
glxdisplay_cat.error()
|
||||||
|
|
|
||||||
|
|
@ -36,12 +36,11 @@ class glxGraphicsPipe;
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
class glxGraphicsWindow : public GraphicsWindow {
|
class glxGraphicsWindow : public GraphicsWindow {
|
||||||
public:
|
public:
|
||||||
glxGraphicsWindow(GraphicsPipe *pipe);
|
glxGraphicsWindow(GraphicsPipe *pipe, GraphicsStateGuardian *gsg);
|
||||||
virtual ~glxGraphicsWindow();
|
virtual ~glxGraphicsWindow();
|
||||||
|
|
||||||
virtual void make_gsg();
|
|
||||||
virtual void release_gsg();
|
|
||||||
virtual void make_current();
|
virtual void make_current();
|
||||||
|
virtual void release_gsg();
|
||||||
|
|
||||||
virtual bool begin_frame();
|
virtual bool begin_frame();
|
||||||
virtual void begin_flip();
|
virtual void begin_flip();
|
||||||
|
|
@ -56,10 +55,7 @@ protected:
|
||||||
private:
|
private:
|
||||||
void set_wm_properties(const WindowProperties &properties);
|
void set_wm_properties(const WindowProperties &properties);
|
||||||
|
|
||||||
XVisualInfo *try_for_visual(int framebuffer_mode,
|
void setup_colormap(XVisualInfo *visual);
|
||||||
int want_depth_bits, int want_color_bits) const;
|
|
||||||
bool choose_visual();
|
|
||||||
void setup_colormap();
|
|
||||||
ButtonHandle get_button(XKeyEvent *key_event);
|
ButtonHandle get_button(XKeyEvent *key_event);
|
||||||
|
|
||||||
static Bool check_event(Display *display, XEvent *event, char *arg);
|
static Bool check_event(Display *display, XEvent *event, char *arg);
|
||||||
|
|
@ -68,8 +64,6 @@ private:
|
||||||
Display *_display;
|
Display *_display;
|
||||||
int _screen;
|
int _screen;
|
||||||
Window _xwindow;
|
Window _xwindow;
|
||||||
GLXContext _context;
|
|
||||||
XVisualInfo *_visual;
|
|
||||||
Colormap _colormap;
|
Colormap _colormap;
|
||||||
long _event_mask;
|
long _event_mask;
|
||||||
bool _awaiting_configure;
|
bool _awaiting_configure;
|
||||||
|
|
|
||||||
|
|
@ -15,11 +15,15 @@
|
||||||
#define INSTALL_HEADERS \
|
#define INSTALL_HEADERS \
|
||||||
config_wgldisplay.h \
|
config_wgldisplay.h \
|
||||||
wglGraphicsPipe.I wglGraphicsPipe.h \
|
wglGraphicsPipe.I wglGraphicsPipe.h \
|
||||||
|
wglGraphicsStateGuardian.I wglGraphicsStateGuardian.h \
|
||||||
wglGraphicsWindow.I wglGraphicsWindow.h
|
wglGraphicsWindow.I wglGraphicsWindow.h
|
||||||
// Win32Defs.h
|
// Win32Defs.h
|
||||||
|
|
||||||
#define INCLUDED_SOURCES \
|
#define INCLUDED_SOURCES \
|
||||||
config_wgldisplay.cxx wglGraphicsPipe.cxx wglGraphicsWindow.cxx
|
config_wgldisplay.cxx \
|
||||||
|
wglGraphicsPipe.cxx \
|
||||||
|
wglGraphicsStateGuardian.cxx \
|
||||||
|
wglGraphicsWindow.cxx
|
||||||
|
|
||||||
#define SOURCES \
|
#define SOURCES \
|
||||||
$[INSTALL_HEADERS]
|
$[INSTALL_HEADERS]
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,7 @@
|
||||||
|
|
||||||
#include "config_wgldisplay.h"
|
#include "config_wgldisplay.h"
|
||||||
#include "wglGraphicsPipe.h"
|
#include "wglGraphicsPipe.h"
|
||||||
|
#include "wglGraphicsStateGuardian.h"
|
||||||
#include "wglGraphicsWindow.h"
|
#include "wglGraphicsWindow.h"
|
||||||
#include "graphicsPipeSelection.h"
|
#include "graphicsPipeSelection.h"
|
||||||
#include "dconfig.h"
|
#include "dconfig.h"
|
||||||
|
|
@ -46,6 +47,7 @@ init_libwgldisplay() {
|
||||||
initialized = true;
|
initialized = true;
|
||||||
|
|
||||||
wglGraphicsPipe::init_type();
|
wglGraphicsPipe::init_type();
|
||||||
|
wglGraphicsStateGuardian::init_type();
|
||||||
wglGraphicsWindow::init_type();
|
wglGraphicsWindow::init_type();
|
||||||
|
|
||||||
GraphicsPipeSelection *selection = GraphicsPipeSelection::get_global_ptr();
|
GraphicsPipeSelection *selection = GraphicsPipeSelection::get_global_ptr();
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,10 @@
|
||||||
|
|
||||||
#include "wglGraphicsPipe.h"
|
#include "wglGraphicsPipe.h"
|
||||||
#include "config_wgldisplay.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;
|
TypeHandle wglGraphicsPipe::_type_handle;
|
||||||
|
|
||||||
|
|
@ -66,12 +70,241 @@ pipe_constructor() {
|
||||||
return new wglGraphicsPipe;
|
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
|
// Function: wglGraphicsPipe::make_window
|
||||||
// Access: Protected, Virtual
|
// Access: Protected, Virtual
|
||||||
// Description: Creates a new window on the pipe, if possible.
|
// Description: Creates a new window on the pipe, if possible.
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
PT(GraphicsWindow) wglGraphicsPipe::
|
PT(GraphicsWindow) wglGraphicsPipe::
|
||||||
make_window() {
|
make_window(GraphicsStateGuardian *gsg) {
|
||||||
return new wglGraphicsWindow(this);
|
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();
|
static PT(GraphicsPipe) pipe_constructor();
|
||||||
|
|
||||||
protected:
|
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:
|
public:
|
||||||
static TypeHandle get_class_type() {
|
static TypeHandle get_class_type() {
|
||||||
|
|
|
||||||
|
|
@ -15,3 +15,31 @@
|
||||||
// panda3d@yahoogroups.com .
|
// 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:
|
// Description:
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
wglGraphicsStateGuardian::
|
wglGraphicsStateGuardian::
|
||||||
wglGraphicsStateGuardian(const FrameBufferProperties &properties) :
|
wglGraphicsStateGuardian(const FrameBufferProperties &properties,
|
||||||
GLGraphicsStateGuardian(properties)
|
int pfnum) :
|
||||||
|
GLGraphicsStateGuardian(properties),
|
||||||
|
_pfnum(pfnum)
|
||||||
{
|
{
|
||||||
_context = (HGLRC)0;
|
_made_context = false;
|
||||||
|
_context = (HGLRC)NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
|
|
@ -45,3 +48,27 @@ wglGraphicsStateGuardian::
|
||||||
_context = (HGLRC)NULL;
|
_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 {
|
class wglGraphicsStateGuardian : public GLGraphicsStateGuardian {
|
||||||
public:
|
public:
|
||||||
wglGraphicsStateGuardian(const FrameBufferProperties &properties);
|
wglGraphicsStateGuardian(const FrameBufferProperties &properties, int pfnum);
|
||||||
virtual ~wglGraphicsStateGuardian();
|
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;
|
int _pfnum;
|
||||||
PIXELFORMATDESCRIPTOR _pixelformat;
|
HGLRC _context;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static TypeHandle get_class_type() {
|
static TypeHandle get_class_type() {
|
||||||
|
|
|
||||||
|
|
@ -25,9 +25,6 @@
|
||||||
#include <wingdi.h>
|
#include <wingdi.h>
|
||||||
#include <ddraw.h>
|
#include <ddraw.h>
|
||||||
|
|
||||||
typedef enum {Software, MCD, ICD} OGLDriverType;
|
|
||||||
static const char * const OGLDrvStrings[] = { "Software", "MCD", "ICD" };
|
|
||||||
|
|
||||||
TypeHandle wglGraphicsWindow::_type_handle;
|
TypeHandle wglGraphicsWindow::_type_handle;
|
||||||
|
|
||||||
static char *ConvDDErrorToString(const HRESULT &error);
|
static char *ConvDDErrorToString(const HRESULT &error);
|
||||||
|
|
@ -132,10 +129,9 @@ GetAvailVidMem() {
|
||||||
// Description:
|
// Description:
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
wglGraphicsWindow::
|
wglGraphicsWindow::
|
||||||
wglGraphicsWindow(GraphicsPipe *pipe) :
|
wglGraphicsWindow(GraphicsPipe *pipe, GraphicsStateGuardian *gsg) :
|
||||||
WinGraphicsWindow(pipe)
|
WinGraphicsWindow(pipe, gsg)
|
||||||
{
|
{
|
||||||
_context = (HGLRC)0;
|
|
||||||
_hdc = (HDC)0;
|
_hdc = (HDC)0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -148,49 +144,6 @@ wglGraphicsWindow::
|
||||||
~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
|
// Function: wglGraphicsWindow::make_current
|
||||||
// Access: Public, Virtual
|
// Access: Public, Virtual
|
||||||
|
|
@ -200,8 +153,30 @@ release_gsg() {
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
void wglGraphicsWindow::
|
void wglGraphicsWindow::
|
||||||
make_current() {
|
make_current() {
|
||||||
nassertv(_gsg != (GraphicsStateGuardian *)NULL);
|
wglGraphicsStateGuardian *wglgsg;
|
||||||
wglMakeCurrent(_hdc, _context);
|
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::
|
void wglGraphicsWindow::
|
||||||
begin_flip() {
|
begin_flip() {
|
||||||
if (_gsg != (GraphicsStateGuardian *)NULL) {
|
if (_gsg != (GraphicsStateGuardian *)NULL) {
|
||||||
wglMakeCurrent(_hdc, _context);
|
make_current();
|
||||||
glFinish();
|
glFinish();
|
||||||
SwapBuffers(_hdc);
|
SwapBuffers(_hdc);
|
||||||
}
|
}
|
||||||
|
|
@ -235,7 +210,7 @@ begin_flip() {
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
void wglGraphicsWindow::
|
void wglGraphicsWindow::
|
||||||
close_window() {
|
close_window() {
|
||||||
ReleaseDC(_mwindow, _hdc);
|
ReleaseDC(_hWnd, _hdc);
|
||||||
_hdc = (HDC)0;
|
_hdc = (HDC)0;
|
||||||
WinGraphicsWindow::close_window();
|
WinGraphicsWindow::close_window();
|
||||||
}
|
}
|
||||||
|
|
@ -253,42 +228,31 @@ open_window() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
wglGraphicsStateGuardian *wglgsg;
|
||||||
|
DCAST_INTO_R(wglgsg, _gsg, false);
|
||||||
|
|
||||||
|
_hdc = GetDC(_hWnd);
|
||||||
|
|
||||||
// Set up the pixel format of the window appropriately for GL.
|
// Set up the pixel format of the window appropriately for GL.
|
||||||
_hdc = GetDC(_mwindow);
|
int pfnum = wglgsg->get_pfnum();
|
||||||
|
|
||||||
int pfnum = choose_pfnum();
|
PIXELFORMATDESCRIPTOR pixelformat;
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
DescribePixelFormat(_hdc, pfnum, sizeof(PIXELFORMATDESCRIPTOR),
|
DescribePixelFormat(_hdc, pfnum, sizeof(PIXELFORMATDESCRIPTOR),
|
||||||
&_pixelformat);
|
&pixelformat);
|
||||||
|
|
||||||
#ifdef _DEBUG
|
#ifdef _DEBUG
|
||||||
char msg[200];
|
char msg[200];
|
||||||
sprintf(msg, "Selected GL PixelFormat is #%d", pfnum);
|
sprintf(msg, "Selected GL PixelFormat is #%d", pfnum);
|
||||||
print_pfd(&_pixelformat, msg);
|
print_pfd(&pixelformat, msg);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (!SetPixelFormat(_hdc, pfnum, &_pixelformat)) {
|
if (!SetPixelFormat(_hdc, pfnum, &pixelformat)) {
|
||||||
wgldisplay_cat.error()
|
wgldisplay_cat.error()
|
||||||
<< "SetPixelFormat(" << pfnum << ") failed after window create\n";
|
<< "SetPixelFormat(" << pfnum << ") failed after window create\n";
|
||||||
close_window();
|
close_window();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initializes _colormap
|
|
||||||
setup_colormap();
|
|
||||||
|
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
if (gl_force_invalid) {
|
if (gl_force_invalid) {
|
||||||
wgldisplay_cat.error()
|
wgldisplay_cat.error()
|
||||||
|
|
@ -298,6 +262,9 @@ open_window() {
|
||||||
}
|
}
|
||||||
#endif // NDEBUG
|
#endif // NDEBUG
|
||||||
|
|
||||||
|
// Initializes _colormap
|
||||||
|
setup_colormap(pixelformat);
|
||||||
|
|
||||||
return true;
|
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
|
// Function: wglGraphicsWindow::setup_colormap
|
||||||
// Access: Private
|
// Access: Private
|
||||||
|
|
@ -523,21 +309,15 @@ find_pixfmtnum(bool bLookforHW) const {
|
||||||
// creating a GL context.
|
// creating a GL context.
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
void wglGraphicsWindow::
|
void wglGraphicsWindow::
|
||||||
setup_colormap() {
|
setup_colormap(const PIXELFORMATDESCRIPTOR &pixelformat) {
|
||||||
PIXELFORMATDESCRIPTOR pfd;
|
|
||||||
LOGPALETTE *logical;
|
LOGPALETTE *logical;
|
||||||
int n;
|
int n;
|
||||||
|
|
||||||
/* grab the pixel format */
|
if (!(pixelformat.dwFlags & PFD_NEED_PALETTE ||
|
||||||
memset(&pfd, 0, sizeof(PIXELFORMATDESCRIPTOR));
|
pixelformat.iPixelType == PFD_TYPE_COLORINDEX))
|
||||||
DescribePixelFormat(_hdc, GetPixelFormat(_hdc),
|
|
||||||
sizeof(PIXELFORMATDESCRIPTOR), &pfd);
|
|
||||||
|
|
||||||
if (!(pfd.dwFlags & PFD_NEED_PALETTE ||
|
|
||||||
pfd.iPixelType == PFD_TYPE_COLORINDEX))
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
n = 1 << pfd.cColorBits;
|
n = 1 << pixelformat.cColorBits;
|
||||||
|
|
||||||
/* allocate a bunch of memory for the logical palette (assume 256
|
/* allocate a bunch of memory for the logical palette (assume 256
|
||||||
colors in a Win32 palette */
|
colors in a Win32 palette */
|
||||||
|
|
@ -552,20 +332,20 @@ setup_colormap() {
|
||||||
/* start with a copy of the current system palette */
|
/* start with a copy of the current system palette */
|
||||||
GetSystemPaletteEntries(_hdc, 0, 256, &logical->palPalEntry[0]);
|
GetSystemPaletteEntries(_hdc, 0, 256, &logical->palPalEntry[0]);
|
||||||
|
|
||||||
if (pfd.iPixelType == PFD_TYPE_RGBA) {
|
if (pixelformat.iPixelType == PFD_TYPE_RGBA) {
|
||||||
int redMask = (1 << pfd.cRedBits) - 1;
|
int redMask = (1 << pixelformat.cRedBits) - 1;
|
||||||
int greenMask = (1 << pfd.cGreenBits) - 1;
|
int greenMask = (1 << pixelformat.cGreenBits) - 1;
|
||||||
int blueMask = (1 << pfd.cBlueBits) - 1;
|
int blueMask = (1 << pixelformat.cBlueBits) - 1;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
/* fill in an RGBA color palette */
|
/* fill in an RGBA color palette */
|
||||||
for (i = 0; i < n; ++i) {
|
for (i = 0; i < n; ++i) {
|
||||||
logical->palPalEntry[i].peRed =
|
logical->palPalEntry[i].peRed =
|
||||||
(((i >> pfd.cRedShift) & redMask) * 255) / redMask;
|
(((i >> pixelformat.cRedShift) & redMask) * 255) / redMask;
|
||||||
logical->palPalEntry[i].peGreen =
|
logical->palPalEntry[i].peGreen =
|
||||||
(((i >> pfd.cGreenShift) & greenMask) * 255) / greenMask;
|
(((i >> pixelformat.cGreenShift) & greenMask) * 255) / greenMask;
|
||||||
logical->palPalEntry[i].peBlue =
|
logical->palPalEntry[i].peBlue =
|
||||||
(((i >> pfd.cBlueShift) & blueMask) * 255) / blueMask;
|
(((i >> pixelformat.cBlueShift) & blueMask) * 255) / blueMask;
|
||||||
logical->palPalEntry[i].peFlags = 0;
|
logical->palPalEntry[i].peFlags = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -29,12 +29,11 @@
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
class EXPCL_PANDAGL wglGraphicsWindow : public WinGraphicsWindow {
|
class EXPCL_PANDAGL wglGraphicsWindow : public WinGraphicsWindow {
|
||||||
public:
|
public:
|
||||||
wglGraphicsWindow(GraphicsPipe *pipe);
|
wglGraphicsWindow(GraphicsPipe *pipe, GraphicsStateGuardian *gsg);
|
||||||
virtual ~wglGraphicsWindow();
|
virtual ~wglGraphicsWindow();
|
||||||
|
|
||||||
virtual void make_gsg();
|
|
||||||
virtual void release_gsg();
|
|
||||||
virtual void make_current();
|
virtual void make_current();
|
||||||
|
virtual void release_gsg();
|
||||||
|
|
||||||
virtual void begin_flip();
|
virtual void begin_flip();
|
||||||
|
|
||||||
|
|
@ -45,17 +44,13 @@ protected:
|
||||||
DWORD &bitdepth);
|
DWORD &bitdepth);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int choose_pfnum() const;
|
void setup_colormap(const PIXELFORMATDESCRIPTOR &pixelformat);
|
||||||
int find_pixfmtnum(bool bLookforHW) const;
|
|
||||||
void setup_colormap();
|
|
||||||
|
|
||||||
#ifdef _DEBUG
|
#ifdef _DEBUG
|
||||||
static void print_pfd(PIXELFORMATDESCRIPTOR *pfd, char *msg);
|
static void print_pfd(PIXELFORMATDESCRIPTOR *pfd, char *msg);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
HGLRC _context;
|
|
||||||
HDC _hdc;
|
HDC _hdc;
|
||||||
PIXELFORMATDESCRIPTOR _pixelformat;
|
|
||||||
HPALETTE _colormap;
|
HPALETTE _colormap;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
#include "config_wgldisplay.cxx"
|
#include "config_wgldisplay.cxx"
|
||||||
#include "wglGraphicsPipe.cxx"
|
#include "wglGraphicsPipe.cxx"
|
||||||
|
#include "wglGraphicsStateGuardian.cxx"
|
||||||
#include "wglGraphicsWindow.cxx"
|
#include "wglGraphicsWindow.cxx"
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -51,3 +51,21 @@ WinGraphicsPipe::
|
||||||
_hUser32 = NULL;
|
_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;
|
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"
|
#include "winGraphicsPipe.I"
|
||||||
|
|
||||||
#endif
|
#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
|
// Function: WinGraphicsWindow::handle_keypress
|
||||||
// Access: Private
|
// Access: Private
|
||||||
|
|
|
||||||
|
|
@ -56,13 +56,13 @@ static const char * const errorbox_title = "Panda3D Error";
|
||||||
// Description:
|
// Description:
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
WinGraphicsWindow::
|
WinGraphicsWindow::
|
||||||
WinGraphicsWindow(GraphicsPipe *pipe) :
|
WinGraphicsWindow(GraphicsPipe *pipe, GraphicsStateGuardian *gsg) :
|
||||||
GraphicsWindow(pipe)
|
GraphicsWindow(pipe, gsg)
|
||||||
{
|
{
|
||||||
GraphicsWindowInputDevice device =
|
GraphicsWindowInputDevice device =
|
||||||
GraphicsWindowInputDevice::pointer_and_keyboard("keyboard/mouse");
|
GraphicsWindowInputDevice::pointer_and_keyboard("keyboard/mouse");
|
||||||
_input_devices.push_back(device);
|
_input_devices.push_back(device);
|
||||||
_mwindow = (HWND)0;
|
_hWnd = (HWND)0;
|
||||||
_ime_open = false;
|
_ime_open = false;
|
||||||
_ime_active = false;
|
_ime_active = false;
|
||||||
_ime_composition_w = false;
|
_ime_composition_w = false;
|
||||||
|
|
@ -174,11 +174,11 @@ set_properties_now(WindowProperties &properties) {
|
||||||
void WinGraphicsWindow::
|
void WinGraphicsWindow::
|
||||||
close_window() {
|
close_window() {
|
||||||
set_cursor_out_of_window();
|
set_cursor_out_of_window();
|
||||||
DestroyWindow(_mwindow);
|
DestroyWindow(_hWnd);
|
||||||
|
|
||||||
// Remove the window handle from our global map.
|
// Remove the window handle from our global map.
|
||||||
_window_handles.erase(_mwindow);
|
_window_handles.erase(_hWnd);
|
||||||
_mwindow = (HWND)0;
|
_hWnd = (HWND)0;
|
||||||
|
|
||||||
if (is_fullscreen()) {
|
if (is_fullscreen()) {
|
||||||
// revert to default display mode.
|
// 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
|
// Now that we have a window handle, store it in our global map, so
|
||||||
// future messages for this window can be routed properly.
|
// 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.
|
// 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);
|
SWP_NOMOVE | SWP_NOSENDCHANGING | SWP_NOSIZE);
|
||||||
|
|
||||||
// need to do twice to override any minimized flags in StartProcessInfo
|
// need to do twice to override any minimized flags in StartProcessInfo
|
||||||
ShowWindow(_mwindow, SW_SHOWNORMAL);
|
ShowWindow(_hWnd, SW_SHOWNORMAL);
|
||||||
ShowWindow(_mwindow, SW_SHOWNORMAL);
|
ShowWindow(_hWnd, SW_SHOWNORMAL);
|
||||||
|
|
||||||
if (!SetForegroundWindow(_mwindow)) {
|
if (!SetForegroundWindow(_hWnd)) {
|
||||||
windisplay_cat.warning()
|
windisplay_cat.warning()
|
||||||
<< "SetForegroundWindow() failed!\n";
|
<< "SetForegroundWindow() failed!\n";
|
||||||
}
|
}
|
||||||
|
|
@ -232,10 +232,10 @@ open_window() {
|
||||||
// Determine the initial open status of the IME.
|
// Determine the initial open status of the IME.
|
||||||
_ime_open = false;
|
_ime_open = false;
|
||||||
_ime_active = false;
|
_ime_active = false;
|
||||||
HIMC hIMC = ImmGetContext(_mwindow);
|
HIMC hIMC = ImmGetContext(_hWnd);
|
||||||
if (hIMC != 0) {
|
if (hIMC != 0) {
|
||||||
_ime_open = (ImmGetOpenStatus(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
|
// 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,
|
SetRect(&view_rect, x_origin, y_origin,
|
||||||
x_origin + x_size, y_origin + y_size);
|
x_origin + x_size, y_origin + y_size);
|
||||||
WINDOWINFO wi;
|
WINDOWINFO wi;
|
||||||
GetWindowInfo(_mwindow, &wi);
|
GetWindowInfo(_hWnd, &wi);
|
||||||
AdjustWindowRectEx(&view_rect, wi.dwStyle, false, wi.dwExStyle);
|
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.right - view_rect.left,
|
||||||
view_rect.bottom - view_rect.top,
|
view_rect.bottom - view_rect.top,
|
||||||
SWP_NOZORDER | SWP_NOMOVE | SWP_NOSENDCHANGING);
|
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::
|
void WinGraphicsWindow::
|
||||||
handle_reshape() {
|
handle_reshape() {
|
||||||
RECT view_rect;
|
RECT view_rect;
|
||||||
GetClientRect(_mwindow, &view_rect);
|
GetClientRect(_hWnd, &view_rect);
|
||||||
ClientToScreen(_mwindow, (POINT*)&view_rect.left); // translates top,left pnt
|
ClientToScreen(_hWnd, (POINT*)&view_rect.left); // translates top,left pnt
|
||||||
ClientToScreen(_mwindow, (POINT*)&view_rect.right); // translates right,bottom pnt
|
ClientToScreen(_hWnd, (POINT*)&view_rect.right); // translates right,bottom pnt
|
||||||
|
|
||||||
WindowProperties properties;
|
WindowProperties properties;
|
||||||
properties.set_size((view_rect.right - view_rect.left),
|
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
|
// 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);
|
SWP_NOZORDER | SWP_NOMOVE | SWP_NOSENDCHANGING);
|
||||||
int chg_result = ChangeDisplaySettings(&dm, CDS_FULLSCREEN);
|
int chg_result = ChangeDisplaySettings(&dm, CDS_FULLSCREEN);
|
||||||
|
|
||||||
|
|
@ -437,32 +437,6 @@ void WinGraphicsWindow::
|
||||||
reconsider_fullscreen_size(DWORD &, DWORD &, DWORD &) {
|
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
|
// Function: WinGraphicsWindow::open_fullscreen_window
|
||||||
// Access: Private
|
// Access: Private
|
||||||
|
|
@ -516,10 +490,10 @@ open_fullscreen_window() {
|
||||||
// up the desktop during the mode change
|
// up the desktop during the mode change
|
||||||
register_window_class();
|
register_window_class();
|
||||||
HINSTANCE hinstance = GetModuleHandle(NULL);
|
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,
|
0, 0, dwWidth, dwHeight,
|
||||||
hDesktopWindow, NULL, hinstance, 0);
|
hDesktopWindow, NULL, hinstance, 0);
|
||||||
if (!_mwindow) {
|
if (!_hWnd) {
|
||||||
windisplay_cat.error()
|
windisplay_cat.error()
|
||||||
<< "CreateWindow() failed!" << endl;
|
<< "CreateWindow() failed!" << endl;
|
||||||
show_error_message();
|
show_error_message();
|
||||||
|
|
@ -601,13 +575,13 @@ open_regular_window() {
|
||||||
|
|
||||||
register_window_class();
|
register_window_class();
|
||||||
HINSTANCE hinstance = GetModuleHandle(NULL);
|
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.left, win_rect.top,
|
||||||
win_rect.right - win_rect.left,
|
win_rect.right - win_rect.left,
|
||||||
win_rect.bottom - win_rect.top,
|
win_rect.bottom - win_rect.top,
|
||||||
NULL, NULL, hinstance, 0);
|
NULL, NULL, hinstance, 0);
|
||||||
|
|
||||||
if (!_mwindow) {
|
if (!_hWnd) {
|
||||||
windisplay_cat.error()
|
windisplay_cat.error()
|
||||||
<< "CreateWindow() failed!" << endl;
|
<< "CreateWindow() failed!" << endl;
|
||||||
show_error_message();
|
show_error_message();
|
||||||
|
|
@ -672,342 +646,373 @@ window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) {
|
||||||
int button = -1;
|
int button = -1;
|
||||||
|
|
||||||
switch (msg) {
|
switch (msg) {
|
||||||
case WM_MOUSEMOVE:
|
case WM_MOUSEMOVE:
|
||||||
if (!_tracking_mouse_leaving) {
|
if (!_tracking_mouse_leaving) {
|
||||||
// need to re-call TrackMouseEvent every time mouse re-enters window
|
// need to re-call TrackMouseEvent every time mouse re-enters window
|
||||||
track_mouse_leaving(hwnd);
|
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);
|
|
||||||
}
|
}
|
||||||
} else {
|
set_cursor_in_window();
|
||||||
// On the other hand, ImmGetCompositionStringW() doesn't
|
if(handle_mouse_motion(translate_mouse(LOWORD(lparam)), translate_mouse(HIWORD(lparam))))
|
||||||
// work on Win95 or Win98; for these OS's we must use
|
return 0;
|
||||||
// ImmGetCompositionStringA().
|
break;
|
||||||
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:
|
case WM_MOUSELEAVE:
|
||||||
// Ignore WM_CHAR messages if we have the IME open, since
|
_tracking_mouse_leaving = false;
|
||||||
// everything will come in through WM_IME_COMPOSITION. (It's
|
handle_mouse_exit();
|
||||||
// supposed to come in through WM_CHAR, too, but there seems to
|
set_cursor_out_of_window();
|
||||||
// be a bug in Win2000 in that it only sends question mark
|
break;
|
||||||
// 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:
|
// if cursor is invisible, make it visible when moving in the window bars & menus, so user can use click in them
|
||||||
{
|
case WM_NCMOUSEMOVE: {
|
||||||
POINT point;
|
if(!_properties.get_cursor_hidden()) {
|
||||||
|
if(!_bCursor_in_WindowClientArea) {
|
||||||
GetCursorPos(&point);
|
// SetCursor(_pParentWindowGroup->_hMouseCursor);
|
||||||
ScreenToClient(hwnd, &point);
|
ShowCursor(true);
|
||||||
handle_keypress(lookup_key(wparam), point.x, point.y);
|
_bCursor_in_WindowClientArea=true;
|
||||||
|
}
|
||||||
// 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);
|
|
||||||
}
|
}
|
||||||
}
|
break;
|
||||||
CloseClipboard();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
break;
|
case WM_NCMOUSELEAVE: {
|
||||||
|
if(!_properties.get_cursor_hidden()) {
|
||||||
case WM_SYSKEYUP:
|
ShowCursor(false);
|
||||||
case WM_KEYUP:
|
// SetCursor(NULL);
|
||||||
handle_keyrelease(lookup_key(wparam));
|
_bCursor_in_WindowClientArea=false;
|
||||||
break;
|
}
|
||||||
|
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.
|
case WM_CREATE: {
|
||||||
GetKeyboardState(_keyboard_state);
|
track_mouse_leaving(hwnd);
|
||||||
break;
|
_bCursor_in_WindowClientArea=false;
|
||||||
|
ClearToBlack(hwnd,_properties);
|
||||||
case WM_SETFOCUS:
|
|
||||||
{
|
POINT cpos;
|
||||||
// When we lose focus, the app may miss key-up events for keys
|
GetCursorPos(&cpos);
|
||||||
// that were formerly held down (and vice-versa). Therefore,
|
ScreenToClient(hwnd,&cpos);
|
||||||
// when focus is regained, compare the state of the keyboard to
|
RECT clientRect;
|
||||||
// the last known state (stored above, when focus was lost) to
|
GetClientRect(hwnd, &clientRect);
|
||||||
// regenerate the lost keyboard events.
|
if(PtInRect(&clientRect,cpos))
|
||||||
|
set_cursor_in_window(); // should window focus be true as well?
|
||||||
if (GetForegroundWindow() != _mwindow) {
|
else set_cursor_out_of_window();
|
||||||
// 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";
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
BYTE new_keyboard_state[num_virtual_keys];
|
case WM_CLOSE:
|
||||||
GetKeyboardState(new_keyboard_state);
|
properties.set_open(false);
|
||||||
for (int i = 0; i < num_virtual_keys; i++) {
|
system_changed_properties(properties);
|
||||||
// Filter out these particular three. We don't want to test
|
|
||||||
// these, because these are virtual duplicates for
|
// TODO: make sure we release the GSG properly.
|
||||||
// VK_LSHIFT/VK_RSHIFT, etc.; and the left/right equivalent is
|
break;
|
||||||
// also in the table. If we respect both VK_LSHIFT as well as
|
|
||||||
// VK_SHIFT, we'll generate two keyboard messages when
|
case WM_ACTIVATE:
|
||||||
// VK_LSHIFT changes state.
|
properties.set_minimized((wparam & 0xffff0000) != 0);
|
||||||
if (i != VK_SHIFT && i != VK_CONTROL && i != VK_MENU) {
|
if ((wparam & 0xffff) != WA_INACTIVE) {
|
||||||
if (((new_keyboard_state[i] ^ _keyboard_state[i]) & 0x80) != 0) {
|
properties.set_foreground(true);
|
||||||
// This key has changed state.
|
if (is_fullscreen()) {
|
||||||
if ((new_keyboard_state[i] & 0x80) != 0) {
|
// When a fullscreen window goes active, it automatically gets
|
||||||
// The key is now held down.
|
// un-minimized.
|
||||||
handle_keyresume(lookup_key(i));
|
ChangeDisplaySettings(&_fullscreen_display_mode, CDS_FULLSCREEN);
|
||||||
} else {
|
GdiFlush();
|
||||||
// The key is now released.
|
SetWindowPos(_hWnd, HWND_TOP, 0,0,0,0,
|
||||||
handle_keyrelease(lookup_key(i));
|
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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
break;
|
||||||
|
|
||||||
// Save the new keyboard state, just for good measure. This
|
case WM_SYSKEYUP:
|
||||||
// really shouldn't be necessary, but it protects against
|
case WM_KEYUP:
|
||||||
// inadvertently getting WM_SETFOCUS twice in a row, for
|
handle_keyrelease(lookup_key(wparam));
|
||||||
// instance.
|
break;
|
||||||
memcpy(_keyboard_state, new_keyboard_state,
|
|
||||||
sizeof(BYTE) * num_virtual_keys);
|
case WM_KILLFOCUS:
|
||||||
}
|
// Record the current state of the keyboard when the focus is
|
||||||
break;
|
// 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);
|
return DefWindowProc(hwnd, msg, wparam, lparam);
|
||||||
|
|
@ -1370,3 +1375,90 @@ lookup_key(WPARAM wparam) const {
|
||||||
}
|
}
|
||||||
return ButtonHandle::none();
|
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 {
|
class EXPCL_PANDAWIN WinGraphicsWindow : public GraphicsWindow {
|
||||||
public:
|
public:
|
||||||
WinGraphicsWindow(GraphicsPipe *pipe);
|
WinGraphicsWindow(GraphicsPipe *pipe, GraphicsStateGuardian *gsg);
|
||||||
virtual ~WinGraphicsWindow();
|
virtual ~WinGraphicsWindow();
|
||||||
|
|
||||||
virtual void begin_flip();
|
virtual void begin_flip();
|
||||||
|
|
||||||
virtual void process_events();
|
virtual void process_events();
|
||||||
virtual void set_properties_now(WindowProperties &properties);
|
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:
|
protected:
|
||||||
virtual void close_window();
|
virtual void close_window();
|
||||||
|
|
@ -71,20 +76,13 @@ protected:
|
||||||
virtual void reconsider_fullscreen_size(DWORD &x_size, DWORD &y_size,
|
virtual void reconsider_fullscreen_size(DWORD &x_size, DWORD &y_size,
|
||||||
DWORD &bitdepth);
|
DWORD &bitdepth);
|
||||||
|
|
||||||
void get_client_rect_screen(HWND hwnd, RECT *view_rect);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool open_fullscreen_window();
|
bool open_fullscreen_window();
|
||||||
bool open_regular_window();
|
bool open_regular_window();
|
||||||
void track_mouse_leaving(HWND hwnd);
|
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();
|
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_keypress(ButtonHandle key, int x, int y);
|
||||||
INLINE void handle_keyresume(ButtonHandle key);
|
INLINE void handle_keyresume(ButtonHandle key);
|
||||||
INLINE void handle_keyrelease(ButtonHandle key);
|
INLINE void handle_keyrelease(ButtonHandle key);
|
||||||
|
|
@ -100,7 +98,7 @@ private:
|
||||||
static void show_error_message(DWORD message_id = 0);
|
static void show_error_message(DWORD message_id = 0);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
HWND _mwindow;
|
HWND _hWnd;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool _ime_open;
|
bool _ime_open;
|
||||||
|
|
@ -108,6 +106,7 @@ private:
|
||||||
bool _ime_composition_w;
|
bool _ime_composition_w;
|
||||||
bool _tracking_mouse_leaving;
|
bool _tracking_mouse_leaving;
|
||||||
bool _maximized;
|
bool _maximized;
|
||||||
|
bool _bCursor_in_WindowClientArea;
|
||||||
DEVMODE _fullscreen_display_mode;
|
DEVMODE _fullscreen_display_mode;
|
||||||
|
|
||||||
// This is used to remember the state of the keyboard when keyboard
|
// This is used to remember the state of the keyboard when keyboard
|
||||||
|
|
@ -164,6 +163,12 @@ private:
|
||||||
static TypeHandle _type_handle;
|
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"
|
#include "winGraphicsWindow.I"
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue