Fix issues resizing OpenGL FBOs. Use LVecBase2i for storing buffer size.

This commit is contained in:
rdb 2014-09-16 14:51:13 +00:00
parent 89b824597c
commit b24adbcad1
10 changed files with 86 additions and 69 deletions

View File

@ -41,19 +41,19 @@ GraphicsBuffer(GraphicsEngine *engine, GraphicsPipe *pipe,
<< "Creating new offscreen buffer " << get_name() << "\n"; << "Creating new offscreen buffer " << get_name() << "\n";
} }
_overlay_display_region->compute_pixels(_x_size, _y_size); _overlay_display_region->compute_pixels(_size.get_x(), _size.get_y());
_open_request = OR_none; _open_request = OR_none;
} }
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
// Function: GraphicsBuffer::Destructor // Function: GraphicsBuffer::Destructor
// Access: Published, Virtual // Access: Published, Virtual
// Description: // Description:
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
GraphicsBuffer:: GraphicsBuffer::
~GraphicsBuffer() { ~GraphicsBuffer() {
} }
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
// Function: GraphicsBuffer::set_size // Function: GraphicsBuffer::set_size
// Access: Public, Virtual // Access: Public, Virtual

View File

@ -40,7 +40,7 @@ protected:
PUBLISHED: PUBLISHED:
virtual ~GraphicsBuffer(); virtual ~GraphicsBuffer();
void set_size(int x, int y); virtual void set_size(int x, int y);
public: public:
virtual void request_open(); virtual void request_open();

View File

@ -150,6 +150,25 @@ get_rtm_mode(int i) const {
return cdata->_textures[i]._rtm_mode; return cdata->_textures[i]._rtm_mode;
} }
////////////////////////////////////////////////////////////////////
// Function: GraphicsOutput::get_size
// Access: Published
// Description: Returns the visible size of the window or buffer, if
// it is known. In certain cases (e.g. fullscreen
// windows), the size may not be known until after the
// object has been fully created. Check has_size()
// first.
//
// Certain objects (like windows) may change size
// spontaneously; this method is not thread-safe. To
// get the size of a window in a thread-safe manner,
// query get_properties().
////////////////////////////////////////////////////////////////////
INLINE const LVecBase2i &GraphicsOutput::
get_size() const {
return _size;
}
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
// Function: GraphicsOutput::get_x_size // Function: GraphicsOutput::get_x_size
// Access: Published // Access: Published
@ -166,7 +185,7 @@ get_rtm_mode(int i) const {
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
INLINE int GraphicsOutput:: INLINE int GraphicsOutput::
get_x_size() const { get_x_size() const {
return _x_size; return _size.get_x();
} }
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
@ -185,7 +204,7 @@ get_x_size() const {
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
INLINE int GraphicsOutput:: INLINE int GraphicsOutput::
get_y_size() const { get_y_size() const {
return _y_size; return _size.get_y();
} }
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
@ -198,7 +217,7 @@ get_y_size() const {
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
INLINE int GraphicsOutput:: INLINE int GraphicsOutput::
get_fb_x_size() const { get_fb_x_size() const {
return max(int(_x_size * get_pixel_factor()), 1); return max(int(_size.get_x() * get_pixel_factor()), 1);
} }
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
@ -211,7 +230,7 @@ get_fb_x_size() const {
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
INLINE int GraphicsOutput:: INLINE int GraphicsOutput::
get_fb_y_size() const { get_fb_y_size() const {
return max(int(_y_size * get_pixel_factor()), 1); return max(int(_size.get_y() * get_pixel_factor()), 1);
} }
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
@ -226,7 +245,7 @@ get_fb_y_size() const {
INLINE int GraphicsOutput:: INLINE int GraphicsOutput::
get_sbs_left_x_size() const { get_sbs_left_x_size() const {
PN_stdfloat left_w = _sbs_left_dimensions[1] - _sbs_left_dimensions[0]; PN_stdfloat left_w = _sbs_left_dimensions[1] - _sbs_left_dimensions[0];
return max(int(_x_size * left_w), 1); return max(int(_size.get_x() * left_w), 1);
} }
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
@ -241,7 +260,7 @@ get_sbs_left_x_size() const {
INLINE int GraphicsOutput:: INLINE int GraphicsOutput::
get_sbs_left_y_size() const { get_sbs_left_y_size() const {
PN_stdfloat left_h = _sbs_left_dimensions[3] - _sbs_left_dimensions[2]; PN_stdfloat left_h = _sbs_left_dimensions[3] - _sbs_left_dimensions[2];
return max(int(_y_size * left_h), 1); return max(int(_size.get_y() * left_h), 1);
} }
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
@ -256,7 +275,7 @@ get_sbs_left_y_size() const {
INLINE int GraphicsOutput:: INLINE int GraphicsOutput::
get_sbs_right_x_size() const { get_sbs_right_x_size() const {
PN_stdfloat right_w = _sbs_right_dimensions[1] - _sbs_right_dimensions[0]; PN_stdfloat right_w = _sbs_right_dimensions[1] - _sbs_right_dimensions[0];
return max(int(_x_size * right_w), 1); return max(int(_size.get_x() * right_w), 1);
} }
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
@ -271,7 +290,7 @@ get_sbs_right_x_size() const {
INLINE int GraphicsOutput:: INLINE int GraphicsOutput::
get_sbs_right_y_size() const { get_sbs_right_y_size() const {
PN_stdfloat right_h = _sbs_right_dimensions[3] - _sbs_right_dimensions[2]; PN_stdfloat right_h = _sbs_right_dimensions[3] - _sbs_right_dimensions[2];
return max(int(_y_size * right_h), 1); return max(int(_size.get_y() * right_h), 1);
} }
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////

View File

@ -78,7 +78,8 @@ GraphicsOutput(GraphicsEngine *engine, GraphicsPipe *pipe,
bool default_stereo_flags) : bool default_stereo_flags) :
_lock("GraphicsOutput"), _lock("GraphicsOutput"),
_cull_window_pcollector(_cull_pcollector, name), _cull_window_pcollector(_cull_pcollector, name),
_draw_window_pcollector(_draw_pcollector, name) _draw_window_pcollector(_draw_pcollector, name),
_size(0, 0)
{ {
#ifdef DO_MEMORY_USAGE #ifdef DO_MEMORY_USAGE
MemoryUsage::update_type(this, this); MemoryUsage::update_type(this, this);
@ -90,13 +91,11 @@ GraphicsOutput(GraphicsEngine *engine, GraphicsPipe *pipe,
_fb_properties = fb_prop; _fb_properties = fb_prop;
_name = name; _name = name;
_creation_flags = flags; _creation_flags = flags;
_x_size = _y_size = 0;
_has_size = win_prop.has_size(); _has_size = win_prop.has_size();
_is_nonzero_size = false; _is_nonzero_size = false;
if (_has_size) { if (_has_size) {
_x_size = win_prop.get_x_size(); _size = win_prop.get_size();
_y_size = win_prop.get_y_size(); _is_nonzero_size = (_size[0] > 0 && _size[1] > 0);
_is_nonzero_size = (_x_size > 0 && _y_size > 0);
} }
if (_creation_flags & GraphicsPipe::BF_size_track_host) { if (_creation_flags & GraphicsPipe::BF_size_track_host) {
// If we're tracking the host size, we assume we'll be nonzero // If we're tracking the host size, we assume we'll be nonzero
@ -546,14 +545,14 @@ set_inverted(bool inverted) {
if (_inverted != inverted) { if (_inverted != inverted) {
_inverted = inverted; _inverted = inverted;
if (_y_size != 0) { if (get_y_size() != 0) {
// All of our DisplayRegions need to recompute their pixel // All of our DisplayRegions need to recompute their pixel
// positions now. // positions now.
TotalDisplayRegions::iterator dri; TotalDisplayRegions::iterator dri;
for (dri = _total_display_regions.begin(); for (dri = _total_display_regions.begin();
dri != _total_display_regions.end(); dri != _total_display_regions.end();
++dri) { ++dri) {
(*dri)->compute_pixels(_x_size, _y_size); (*dri)->compute_pixels(get_x_size(), get_y_size());
} }
} }
} }
@ -1102,7 +1101,7 @@ make_cube_map(const string &name, int size, NodePath &camera_rig,
NodePath GraphicsOutput:: NodePath GraphicsOutput::
get_texture_card() { get_texture_card() {
if (_texture_card == 0) { if (_texture_card == 0) {
PT(GeomVertexData) vdata = create_texture_card_vdata(_x_size, _y_size); PT(GeomVertexData) vdata = create_texture_card_vdata(get_x_size(), get_y_size());
PT(GeomTristrips) strip = new GeomTristrips(Geom::UH_static); PT(GeomTristrips) strip = new GeomTristrips(Geom::UH_static);
strip->set_shade_model(Geom::SM_uniform); strip->set_shade_model(Geom::SM_uniform);
strip->add_next_vertices(4); strip->add_next_vertices(4);
@ -1262,11 +1261,10 @@ clear_pipe() {
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
void GraphicsOutput:: void GraphicsOutput::
set_size_and_recalc(int x, int y) { set_size_and_recalc(int x, int y) {
_x_size = x; _size.set(x, y);
_y_size = y;
_has_size = true; _has_size = true;
_is_nonzero_size = (_x_size > 0 && _y_size > 0); _is_nonzero_size = (x > 0 && y > 0);
int fb_x_size = get_fb_x_size(); int fb_x_size = get_fb_x_size();
int fb_y_size = get_fb_y_size(); int fb_y_size = get_fb_y_size();
@ -1498,7 +1496,7 @@ process_events() {
void GraphicsOutput:: void GraphicsOutput::
pixel_factor_changed() { pixel_factor_changed() {
if (_has_size) { if (_has_size) {
set_size_and_recalc(_x_size, _y_size); set_size_and_recalc(get_x_size(), get_y_size());
} }
} }

View File

@ -128,10 +128,11 @@ PUBLISHED:
INLINE RenderTexturePlane get_texture_plane(int i=0) const; INLINE RenderTexturePlane get_texture_plane(int i=0) const;
INLINE RenderTextureMode get_rtm_mode(int i=0) const; INLINE RenderTextureMode get_rtm_mode(int i=0) const;
void clear_render_textures(); void clear_render_textures();
void add_render_texture(Texture *tex, RenderTextureMode mode, void add_render_texture(Texture *tex, RenderTextureMode mode,
RenderTexturePlane bitplane=RTP_COUNT); RenderTexturePlane bitplane=RTP_COUNT);
void setup_render_texture(Texture *tex, bool allow_bind, bool to_ram); void setup_render_texture(Texture *tex, bool allow_bind, bool to_ram);
INLINE const LVecBase2i &get_size() const;
INLINE int get_x_size() const; INLINE int get_x_size() const;
INLINE int get_y_size() const; INLINE int get_y_size() const;
INLINE int get_fb_x_size() const; INLINE int get_fb_x_size() const;
@ -290,7 +291,7 @@ protected:
private: private:
PT(GeomVertexData) create_texture_card_vdata(int x, int y); PT(GeomVertexData) create_texture_card_vdata(int x, int y);
DisplayRegion *add_display_region(DisplayRegion *display_region); DisplayRegion *add_display_region(DisplayRegion *display_region);
bool do_remove_display_region(DisplayRegion *display_region); bool do_remove_display_region(DisplayRegion *display_region);
@ -323,7 +324,7 @@ protected:
RenderTextureMode _rtm_mode; RenderTextureMode _rtm_mode;
}; };
typedef pvector<RenderTexture> RenderTextures; typedef pvector<RenderTexture> RenderTextures;
private: private:
int _sort; int _sort;
int _child_sort; int _child_sort;
@ -346,9 +347,9 @@ protected:
// have, we don't auto-close the buffer (since that would deallocate // have, we don't auto-close the buffer (since that would deallocate
// the memory associated with the texture). // the memory associated with the texture).
pvector<WPT(Texture)> _hold_textures; pvector<WPT(Texture)> _hold_textures;
protected: protected:
LightMutex _lock; LightMutex _lock;
// protects _display_regions. // protects _display_regions.
PT(DisplayRegion) _overlay_display_region; PT(DisplayRegion) _overlay_display_region;
typedef pvector< PT(DisplayRegion) > TotalDisplayRegions; typedef pvector< PT(DisplayRegion) > TotalDisplayRegions;
@ -382,8 +383,7 @@ protected:
protected: protected:
int _creation_flags; int _creation_flags;
int _x_size; LVecBase2i _size;
int _y_size;
bool _has_size; bool _has_size;
bool _is_valid; bool _is_valid;
bool _is_nonzero_size; bool _is_nonzero_size;
@ -394,7 +394,7 @@ protected:
static PStatCollector _draw_pcollector; static PStatCollector _draw_pcollector;
PStatCollector _cull_window_pcollector; PStatCollector _cull_window_pcollector;
PStatCollector _draw_window_pcollector; PStatCollector _draw_window_pcollector;
public: public:
static TypeHandle get_class_type() { static TypeHandle get_class_type() {
return _type_handle; return _type_handle;

View File

@ -170,8 +170,7 @@ request_properties(const WindowProperties &requested_properties) {
// stick. This is helpful for the MultitexReducer, which needs to // stick. This is helpful for the MultitexReducer, which needs to
// know the size of the textures that it will be working with, // know the size of the textures that it will be working with,
// even if the texture hasn't been fully generated yet. // even if the texture hasn't been fully generated yet.
_x_size = _requested_properties.get_x_size(); _size = _requested_properties.get_size();
_y_size = _requested_properties.get_y_size();
// Don't set _has_size yet, because we don't really know yet. // Don't set _has_size yet, because we don't really know yet.
} }

View File

@ -27,15 +27,15 @@ TypeHandle ParasiteBuffer::_type_handle;
ParasiteBuffer:: ParasiteBuffer::
ParasiteBuffer(GraphicsOutput *host, const string &name, ParasiteBuffer(GraphicsOutput *host, const string &name,
int x_size, int y_size, int flags) : int x_size, int y_size, int flags) :
GraphicsOutput(host->get_engine(), host->get_pipe(), GraphicsOutput(host->get_engine(), host->get_pipe(),
name, host->get_fb_properties(), name, host->get_fb_properties(),
WindowProperties::size(x_size, y_size), flags, WindowProperties::size(x_size, y_size), flags,
host->get_gsg(), host, false) host->get_gsg(), host, false)
{ {
#ifdef DO_MEMORY_USAGE #ifdef DO_MEMORY_USAGE
MemoryUsage::update_type(this, this); MemoryUsage::update_type(this, this);
#endif #endif
if (display_cat.is_debug()) { if (display_cat.is_debug()) {
display_cat.debug() display_cat.debug()
<< "Creating new parasite buffer " << get_name() << "Creating new parasite buffer " << get_name()
@ -43,25 +43,24 @@ ParasiteBuffer(GraphicsOutput *host, const string &name,
} }
_creation_flags = flags; _creation_flags = flags;
if (flags & GraphicsPipe::BF_size_track_host) { if (flags & GraphicsPipe::BF_size_track_host) {
x_size = host->get_x_size(); _size = host->get_size();
y_size = host->get_y_size(); } else {
_size.set(x_size, y_size);
} }
_x_size = x_size;
_y_size = y_size;
_has_size = true; _has_size = true;
_overlay_display_region->compute_pixels(_x_size, _y_size); _overlay_display_region->compute_pixels(_size.get_x(), _size.get_y());
_is_valid = true; _is_valid = true;
set_inverted(host->get_gsg()->get_copy_texture_inverted()); set_inverted(host->get_gsg()->get_copy_texture_inverted());
} }
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
// Function: ParasiteBuffer::Destructor // Function: ParasiteBuffer::Destructor
// Access: Published, Virtual // Access: Published, Virtual
// Description: // Description:
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
ParasiteBuffer:: ParasiteBuffer::
~ParasiteBuffer() { ~ParasiteBuffer() {
@ -201,19 +200,18 @@ begin_frame(FrameMode mode, Thread *current_thread) {
} }
if (_creation_flags & GraphicsPipe::BF_size_track_host) { if (_creation_flags & GraphicsPipe::BF_size_track_host) {
if ((_host->get_x_size() != _x_size)|| if (_host->get_size() != _size) {
(_host->get_y_size() != _y_size)) {
set_size_and_recalc(_host->get_x_size(), set_size_and_recalc(_host->get_x_size(),
_host->get_y_size()); _host->get_y_size());
} }
} else { } else {
if (_host->get_x_size() < _x_size || if (_host->get_x_size() < get_x_size() ||
_host->get_y_size() < _y_size) { _host->get_y_size() < get_y_size()) {
set_size_and_recalc(min(_x_size, _host->get_x_size()), set_size_and_recalc(min(get_x_size(), _host->get_x_size()),
min(_y_size, _host->get_y_size())); min(get_y_size(), _host->get_y_size()));
} }
} }
clear_cube_map_selection(); clear_cube_map_selection();
return true; return true;
} }

View File

@ -155,8 +155,7 @@ begin_frame(FrameMode mode, Thread *current_thread) {
} }
} }
if (_creation_flags & GraphicsPipe::BF_size_track_host) { if (_creation_flags & GraphicsPipe::BF_size_track_host) {
if ((_host->get_x_size() != _x_size)|| if (_host->get_size() != _size) {
(_host->get_y_size() != _y_size)) {
// We also need to rebuild if we need to change size. // We also need to rebuild if we need to change size.
_needs_rebuild = true; _needs_rebuild = true;
} }
@ -277,14 +276,14 @@ rebuild_bitplanes() {
// Calculate bitplane size. This can be larger than the buffer. // Calculate bitplane size. This can be larger than the buffer.
if (_creation_flags & GraphicsPipe::BF_size_track_host) { if (_creation_flags & GraphicsPipe::BF_size_track_host) {
if ((_host->get_x_size() != _x_size)|| if (_host->get_size() != _size) {
(_host->get_y_size() != _y_size)) {
set_size_and_recalc(_host->get_x_size(), set_size_and_recalc(_host->get_x_size(),
_host->get_y_size()); _host->get_y_size());
} }
} }
int bitplane_x = _x_size;
int bitplane_y = _y_size; int bitplane_x = get_x_size();
int bitplane_y = get_y_size();
if (Texture::get_textures_power_2() != ATS_none) { if (Texture::get_textures_power_2() != ATS_none) {
bitplane_x = Texture::up_to_power_2(bitplane_x); bitplane_x = Texture::up_to_power_2(bitplane_x);
bitplane_y = Texture::up_to_power_2(bitplane_y); bitplane_y = Texture::up_to_power_2(bitplane_y);
@ -602,7 +601,7 @@ bind_slot(int layer, bool rb_resize, Texture **attach, RenderTexturePlane slot,
if (tex->get_texture_type() != Texture::TT_cube_map && _rb_size_z > 1) { if (tex->get_texture_type() != Texture::TT_cube_map && _rb_size_z > 1) {
tex->set_z_size(_rb_size_z); tex->set_z_size(_rb_size_z);
} }
tex->set_pad_size(_rb_size_x - _x_size, _rb_size_y - _y_size); tex->set_pad_size(_rb_size_x - get_x_size(), _rb_size_y - get_y_size());
// Adjust the texture format based on the requested framebuffer settings. // Adjust the texture format based on the requested framebuffer settings.
switch (slot) { switch (slot) {
@ -1072,6 +1071,10 @@ attach_tex(int layer, int view, Texture *attach, GLenum attachpoint) {
gtc->set_active(true); gtc->set_active(true);
_texture_contexts.push_back(gtc); _texture_contexts.push_back(gtc);
// It seems that binding the texture is necessary before binding
// to a framebuffer attachment.
glgsg->apply_texture(gtc);
#ifndef OPENGLES #ifndef OPENGLES
GLclampf priority = 1.0f; GLclampf priority = 1.0f;
glPrioritizeTextures(1, &gtc->_index, &priority); glPrioritizeTextures(1, &gtc->_index, &priority);
@ -1191,7 +1194,7 @@ end_frame(FrameMode mode, Thread *current_thread) {
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
void CLP(GraphicsBuffer):: void CLP(GraphicsBuffer)::
set_size(int x, int y) { set_size(int x, int y) {
if (_x_size != x || _y_size != y) { if (_size.get_x() != x || _size.get_y() != y) {
_needs_rebuild = true; _needs_rebuild = true;
} }

View File

@ -178,7 +178,7 @@ open_buffer() {
// new one that shares with the old gsg. // new one that shares with the old gsg.
DCAST_INTO_R(glxgsg, _gsg, false); DCAST_INTO_R(glxgsg, _gsg, false);
if (!glxgsg->_context_has_pbuffer || if (!glxgsg->_context_has_pbuffer ||
!glxgsg->get_fb_properties().subsumes(_fb_properties)) { !glxgsg->get_fb_properties().subsumes(_fb_properties)) {
// We need a new pixel format, and hence a new GSG. // We need a new pixel format, and hence a new GSG.
glxgsg = new glxGraphicsStateGuardian(_engine, _pipe, glxgsg); glxgsg = new glxGraphicsStateGuardian(_engine, _pipe, glxgsg);
@ -186,7 +186,7 @@ open_buffer() {
_gsg = glxgsg; _gsg = glxgsg;
} }
} }
if (glxgsg->_fbconfig == None || !glxgsg->_context_has_pbuffer) { if (glxgsg->_fbconfig == None || !glxgsg->_context_has_pbuffer) {
// If we didn't use an fbconfig to create the GSG, or it doesn't // If we didn't use an fbconfig to create the GSG, or it doesn't
// support buffers, we can't create a PBuffer. // support buffers, we can't create a PBuffer.
@ -204,15 +204,15 @@ open_buffer() {
nassertr(n < max_attrib_list, false); nassertr(n < max_attrib_list, false);
attrib_list[n] = (int)None; attrib_list[n] = (int)None;
_pbuffer = glxgsg->_glXCreateGLXPbufferSGIX(glxgsg->_display, glxgsg->_fbconfig, _pbuffer = glxgsg->_glXCreateGLXPbufferSGIX(glxgsg->_display, glxgsg->_fbconfig,
_x_size, _y_size, attrib_list); get_x_size(), get_y_size(), attrib_list);
} else { } else {
// The official GLX 1.3 version passes in the size in the attrib // The official GLX 1.3 version passes in the size in the attrib
// list. // list.
attrib_list[n++] = GLX_PBUFFER_WIDTH; attrib_list[n++] = GLX_PBUFFER_WIDTH;
attrib_list[n++] = _x_size; attrib_list[n++] = get_x_size();
attrib_list[n++] = GLX_PBUFFER_HEIGHT; attrib_list[n++] = GLX_PBUFFER_HEIGHT;
attrib_list[n++] = _y_size; attrib_list[n++] = get_y_size();
nassertr(n < max_attrib_list, false); nassertr(n < max_attrib_list, false);
attrib_list[n] = (int)None; attrib_list[n] = (int)None;
_pbuffer = glxgsg->_glXCreatePbuffer(glxgsg->_display, glxgsg->_fbconfig, _pbuffer = glxgsg->_glXCreatePbuffer(glxgsg->_display, glxgsg->_fbconfig,

View File

@ -213,8 +213,8 @@ open_buffer() {
} }
} }
_x_pixmap = XCreatePixmap(_display, _drawable, _x_pixmap = XCreatePixmap(_display, _drawable,
_x_size, _y_size, visual_info->depth); get_x_size(), get_y_size(), visual_info->depth);
if (_x_pixmap == None) { if (_x_pixmap == None) {
glxdisplay_cat.error() glxdisplay_cat.error()
<< "Failed to create X pixmap.\n"; << "Failed to create X pixmap.\n";