diff --git a/panda/src/wgldisplay/wglGraphicsBuffer.cxx b/panda/src/wgldisplay/wglGraphicsBuffer.cxx index e17a46bdfa..47bbdd1f76 100644 --- a/panda/src/wgldisplay/wglGraphicsBuffer.cxx +++ b/panda/src/wgldisplay/wglGraphicsBuffer.cxx @@ -43,6 +43,7 @@ wglGraphicsBuffer(GraphicsPipe *pipe, GraphicsStateGuardian *gsg, // Since the pbuffer never gets flipped, we get screenshots from the // same buffer we draw into. _screenshot_buffer_type = _draw_buffer_type; + _render_texture = false; } //////////////////////////////////////////////////////////////////// @@ -72,6 +73,12 @@ begin_frame() { wglGraphicsStateGuardian *wglgsg; DCAST_INTO_R(wglgsg, _gsg, false); + if (_render_texture) { + // Release the texture so we can render into the pbuffer. + // wglgsg->_wglReleaseTexImageARB(_pbuffer, get_draw_buffer_type() == RenderBuffer::T_back ? WGL_BACK_LEFT_ARB : WGL_FRONT_LEFT_ARB); + wglgsg->_wglReleaseTexImageARB(_pbuffer, WGL_FRONT_LEFT_ARB); + } + if (_pbuffer_dc) { int flag = 0; wglgsg->_wglQueryPbufferARB(_pbuffer, WGL_PBUFFER_LOST_ARB, &flag); @@ -100,6 +107,7 @@ end_frame() { nassertv(_gsg != (GraphicsStateGuardian *)NULL); _gsg->end_frame(); + if (_copy_texture) { wglGraphicsStateGuardian *wglgsg; DCAST_INTO_V(wglgsg, _gsg); @@ -118,15 +126,29 @@ end_frame() { } } - // For now, we copy the framebuffer to the texture every frame. - // Eventually we can take advantage of the render_texture - // extension, if it is available, to render directly into a - // texture in the first place (but I don't have a card that - // supports that right now). nassertv(has_texture()); + Texture *tex = get_texture(); - RenderBuffer buffer = _gsg->get_render_buffer(get_draw_buffer_type()); - _gsg->copy_texture(get_texture(), _default_display_region, buffer); + if (_render_texture) { + // Bind the pbuffer to our associated texture. This is a newer + // extension that might allow us to use the same memory directly + // without having to pay for a copy operation. But we can't + // render again to the pbuffer while the texture is valid. + TextureContext *tc = tex->prepare_now(wglgsg->get_prepared_objects(), wglgsg); + nassertv(tc != (TextureContext *)NULL); + wglgsg->bind_texture(tc); + + // wglgsg->_wglBindTexImageARB(_pbuffer, get_draw_buffer_type() == RenderBuffer::T_back ? WGL_BACK_LEFT_ARB : WGL_FRONT_LEFT_ARB); + wglgsg->_wglBindTexImageARB(_pbuffer, WGL_FRONT_LEFT_ARB); + + } else { + // Copy the contents of the frame buffer to our associated + // texture. This is an older interface that guarantees a copy + // operation will take place, and it might even require + // reformatting pixels on the way, so it may be slower. + RenderBuffer buffer = wglgsg->get_render_buffer(get_draw_buffer_type()); + wglgsg->copy_texture(tex, _default_display_region, buffer); + } } } @@ -245,6 +267,13 @@ open_buffer() { if (wgldisplay_cat.is_debug()) { wgldisplay_cat.debug() << "Created PBuffer " << _pbuffer << ", DC " << _pbuffer_dc << "\n"; + if (_render_texture) { + wgldisplay_cat.debug() + << "pbuffer renders directly to texture.\n"; + } else if (_copy_texture) { + wgldisplay_cat.debug() + << "pbuffer copies indirectly into texture.\n"; + } } wglMakeCurrent(_pbuffer_dc, wglgsg->get_context(_pbuffer_dc)); @@ -277,154 +306,60 @@ make_pbuffer(HDC twindow_dc) { int pbformat = wglgsg->get_pfnum(); if (wglgsg->_supports_pixel_format) { - // Select a suitable pixel format that matches the GSG's existing - // format, and also is appropriate for a pixel buffer. + bool got_pbuffer_format = false; - static const int max_attrib_list = 64; - int iattrib_list[max_attrib_list]; - int ivalue_list[max_attrib_list]; - int ni = 0; - - int acceleration_i, pixel_type_i, double_buffer_i, stereo_i, - red_bits_i, green_bits_i, blue_bits_i, alpha_bits_i, - accum_red_bits_i, accum_green_bits_i, accum_blue_bits_i, - accum_alpha_bits_i, depth_bits_i, - stencil_bits_i, sample_buffers_i, multisamples_i; - - iattrib_list[acceleration_i = ni++] = WGL_ACCELERATION_ARB; - iattrib_list[pixel_type_i = ni++] = WGL_PIXEL_TYPE_ARB; - iattrib_list[double_buffer_i = ni++] = WGL_DOUBLE_BUFFER_ARB; - iattrib_list[stereo_i = ni++] = WGL_STEREO_ARB; - iattrib_list[red_bits_i = ni++] = WGL_RED_BITS_ARB; - iattrib_list[green_bits_i = ni++] = WGL_GREEN_BITS_ARB; - iattrib_list[blue_bits_i = ni++] = WGL_BLUE_BITS_ARB; - iattrib_list[alpha_bits_i = ni++] = WGL_ALPHA_BITS_ARB; - iattrib_list[accum_red_bits_i = ni++] = WGL_ACCUM_RED_BITS_ARB; - iattrib_list[accum_green_bits_i = ni++] = WGL_ACCUM_GREEN_BITS_ARB; - iattrib_list[accum_blue_bits_i = ni++] = WGL_ACCUM_BLUE_BITS_ARB; - iattrib_list[accum_alpha_bits_i = ni++] = WGL_ACCUM_ALPHA_BITS_ARB; - iattrib_list[depth_bits_i = ni++] = WGL_DEPTH_BITS_ARB; - iattrib_list[stencil_bits_i = ni++] = WGL_STENCIL_BITS_ARB; - - if (wglgsg->_supports_wgl_multisample) { - iattrib_list[sample_buffers_i = ni++] = WGL_SAMPLE_BUFFERS_ARB; - iattrib_list[multisamples_i = ni++] = WGL_SAMPLES_ARB; + if (_copy_texture && wglgsg->_supports_render_texture) { + // First, try to get a pbuffer format that supports + // render-to-texture. + int new_pbformat = choose_pbuffer_format(twindow_dc, true); + if (new_pbformat != 0) { + pbformat = new_pbformat; + got_pbuffer_format = true; + _render_texture = true; + } } - // Terminate the list. - nassertr(ni <= max_attrib_list, false); - - if (!wglgsg->_wglGetPixelFormatAttribivARB(twindow_dc, pbformat, 0, - ni, iattrib_list, ivalue_list)) { - return false; + if (!got_pbuffer_format) { + // Failing that, just get a matching pbuffer format. + int new_pbformat = choose_pbuffer_format(twindow_dc, false); + if (new_pbformat != 0) { + pbformat = new_pbformat; + got_pbuffer_format = true; + } } - ni = 0; - float fattrib_list[max_attrib_list]; - int nf = 0; - - // Since we are trying to create a pbuffer, the pixel format we - // request (and subsequently use) must be "pbuffer capable". - iattrib_list[ni++] = WGL_DRAW_TO_PBUFFER_ARB; - iattrib_list[ni++] = true; - iattrib_list[ni++] = WGL_SUPPORT_OPENGL_ARB; - iattrib_list[ni++] = true; - - // Match up the framebuffer bits. - iattrib_list[ni++] = WGL_RED_BITS_ARB; - iattrib_list[ni++] = ivalue_list[red_bits_i]; - iattrib_list[ni++] = WGL_GREEN_BITS_ARB; - iattrib_list[ni++] = ivalue_list[green_bits_i]; - iattrib_list[ni++] = WGL_BLUE_BITS_ARB; - iattrib_list[ni++] = ivalue_list[blue_bits_i]; - iattrib_list[ni++] = WGL_ALPHA_BITS_ARB; - iattrib_list[ni++] = ivalue_list[alpha_bits_i]; - - iattrib_list[ni++] = WGL_ACCUM_RED_BITS_ARB; - iattrib_list[ni++] = ivalue_list[accum_red_bits_i]; - iattrib_list[ni++] = WGL_ACCUM_GREEN_BITS_ARB; - iattrib_list[ni++] = ivalue_list[accum_green_bits_i]; - iattrib_list[ni++] = WGL_ACCUM_BLUE_BITS_ARB; - iattrib_list[ni++] = ivalue_list[accum_blue_bits_i]; - iattrib_list[ni++] = WGL_ACCUM_ALPHA_BITS_ARB; - iattrib_list[ni++] = ivalue_list[accum_alpha_bits_i]; - - iattrib_list[ni++] = WGL_DEPTH_BITS_ARB; - iattrib_list[ni++] = ivalue_list[depth_bits_i]; - - iattrib_list[ni++] = WGL_STENCIL_BITS_ARB; - iattrib_list[ni++] = ivalue_list[stencil_bits_i]; - - if (wglgsg->_supports_wgl_multisample) { - iattrib_list[ni++] = WGL_SAMPLE_BUFFERS_ARB; - iattrib_list[ni++] = ivalue_list[sample_buffers_i]; - iattrib_list[ni++] = WGL_SAMPLES_ARB; - iattrib_list[ni++] = ivalue_list[multisamples_i]; - } - - // Match up properties. - iattrib_list[ni++] = WGL_DOUBLE_BUFFER_ARB; - iattrib_list[ni++] = ivalue_list[double_buffer_i]; - iattrib_list[ni++] = WGL_STEREO_ARB; - iattrib_list[ni++] = ivalue_list[stereo_i]; - - // Terminate the lists. - nassertr(ni < max_attrib_list && nf < max_attrib_list, NULL); - iattrib_list[ni] = 0; - fattrib_list[nf] = 0; - - // Now obtain a list of pixel formats that meet these minimum - // requirements. - static const unsigned int max_pformats = 32; - int pformat[max_pformats]; - memset(pformat, 0, sizeof(pformat)); - unsigned int nformats = 0; - if (!wglgsg->_wglChoosePixelFormatARB(twindow_dc, iattrib_list, fattrib_list, - max_pformats, pformat, &nformats) - || nformats == 0) { - wgldisplay_cat.info() - << "Couldn't find a suitable pixel format for creating a pbuffer.\n"; - return false; - } - - nformats = min(nformats, max_pformats); - if (wgldisplay_cat.is_debug()) { + FrameBufferProperties properties; + wglGraphicsPipe::get_properties_advanced(properties, wglgsg, + twindow_dc, pbformat); wgldisplay_cat.debug() - << "Found " << nformats << " pbuffer formats: ["; - for (unsigned int i = 0; i < nformats; i++) { - wgldisplay_cat.debug(false) - << " " << pformat[i]; - } - wgldisplay_cat.debug(false) - << " ]\n"; - } - - // If one of the options is the original pixfmt, keep it. - bool found_pbformat = false; - for (unsigned int i = 0; i < nformats && !found_pbformat; i++) { - if (pformat[i] == pbformat) { - found_pbformat = true; - } - } - - if (!found_pbformat) { - // Otherwise, pick any of them. - pbformat = pformat[0]; + << "Chose pixfmt #" << pbformat << " for pbuffer = " + << properties << "\n"; } } - if (wgldisplay_cat.is_debug()) { - wgldisplay_cat.debug() - << "Chose pixfmt #" << pbformat << " for pbuffer\n"; - } - - int attrib_list[] = { - 0, - }; + static const int max_attrib_list = 64; + int iattrib_list[max_attrib_list]; + int ni = 0; + + if (_render_texture) { + if (_gsg->get_properties().get_frame_buffer_mode() & FrameBufferProperties::FM_alpha) { + iattrib_list[ni++] = WGL_TEXTURE_FORMAT_ARB; + iattrib_list[ni++] = WGL_TEXTURE_RGBA_ARB; + } else { + iattrib_list[ni++] = WGL_TEXTURE_FORMAT_ARB; + iattrib_list[ni++] = WGL_TEXTURE_RGB_ARB; + } + iattrib_list[ni++] = WGL_TEXTURE_TARGET_ARB; + iattrib_list[ni++] = WGL_TEXTURE_2D_ARB; + } + + // Terminate the list. + nassertr(ni <= max_attrib_list, false); + iattrib_list[ni] = 0; _pbuffer = wglgsg->_wglCreatePbufferARB(twindow_dc, pbformat, - _x_size, _y_size, attrib_list); + _x_size, _y_size, iattrib_list); if (_pbuffer == 0) { wgldisplay_cat.info() @@ -435,6 +370,180 @@ make_pbuffer(HDC twindow_dc) { return true; } +//////////////////////////////////////////////////////////////////// +// Function: wglGraphicsBuffer::choose_pbuffer_format +// Access: Private +// Description: Select a suitable pixel format that matches the GSG's +// existing format, and also is appropriate for a pixel +// buffer. Returns the selected pfnum if successful, or +// 0 on failure. +//////////////////////////////////////////////////////////////////// +int wglGraphicsBuffer:: +choose_pbuffer_format(HDC twindow_dc, bool draw_to_texture) { + if (wgldisplay_cat.is_debug()) { + wgldisplay_cat.debug() + << "choose_pbuffer_format(twindow_dc, draw_to_texture = " + << draw_to_texture << ")\n"; + } + + wglGraphicsStateGuardian *wglgsg; + DCAST_INTO_R(wglgsg, _gsg, false); + + int pbformat = wglgsg->get_pfnum(); + + static const int max_attrib_list = 64; + int iattrib_list[max_attrib_list]; + int ivalue_list[max_attrib_list]; + int ni = 0; + + int acceleration_i, pixel_type_i, double_buffer_i, stereo_i, + red_bits_i, green_bits_i, blue_bits_i, alpha_bits_i, + accum_red_bits_i, accum_green_bits_i, accum_blue_bits_i, + accum_alpha_bits_i, depth_bits_i, + stencil_bits_i, sample_buffers_i, multisamples_i; + + iattrib_list[acceleration_i = ni++] = WGL_ACCELERATION_ARB; + iattrib_list[pixel_type_i = ni++] = WGL_PIXEL_TYPE_ARB; + iattrib_list[double_buffer_i = ni++] = WGL_DOUBLE_BUFFER_ARB; + iattrib_list[stereo_i = ni++] = WGL_STEREO_ARB; + iattrib_list[red_bits_i = ni++] = WGL_RED_BITS_ARB; + iattrib_list[green_bits_i = ni++] = WGL_GREEN_BITS_ARB; + iattrib_list[blue_bits_i = ni++] = WGL_BLUE_BITS_ARB; + iattrib_list[alpha_bits_i = ni++] = WGL_ALPHA_BITS_ARB; + iattrib_list[accum_red_bits_i = ni++] = WGL_ACCUM_RED_BITS_ARB; + iattrib_list[accum_green_bits_i = ni++] = WGL_ACCUM_GREEN_BITS_ARB; + iattrib_list[accum_blue_bits_i = ni++] = WGL_ACCUM_BLUE_BITS_ARB; + iattrib_list[accum_alpha_bits_i = ni++] = WGL_ACCUM_ALPHA_BITS_ARB; + iattrib_list[depth_bits_i = ni++] = WGL_DEPTH_BITS_ARB; + iattrib_list[stencil_bits_i = ni++] = WGL_STENCIL_BITS_ARB; + + if (wglgsg->_supports_wgl_multisample) { + iattrib_list[sample_buffers_i = ni++] = WGL_SAMPLE_BUFFERS_ARB; + iattrib_list[multisamples_i = ni++] = WGL_SAMPLES_ARB; + } + + // Terminate the list. + nassertr(ni <= max_attrib_list, false); + + if (!wglgsg->_wglGetPixelFormatAttribivARB(twindow_dc, pbformat, 0, + ni, iattrib_list, ivalue_list)) { + if (wgldisplay_cat.is_debug()) { + wgldisplay_cat.debug() + << "Could not query old format " << pbformat << ".\n"; + } + return 0; + } + + ni = 0; + float fattrib_list[max_attrib_list]; + int nf = 0; + + // Since we are trying to create a pbuffer, the pixel format we + // request (and subsequently use) must be "pbuffer capable". + iattrib_list[ni++] = WGL_DRAW_TO_PBUFFER_ARB; + iattrib_list[ni++] = true; + iattrib_list[ni++] = WGL_SUPPORT_OPENGL_ARB; + iattrib_list[ni++] = true; + + if (draw_to_texture) { + // If we want to be able to render-to-texture, request that. + if (_gsg->get_properties().get_frame_buffer_mode() & FrameBufferProperties::FM_alpha) { + iattrib_list[ni++] = WGL_BIND_TO_TEXTURE_RGBA_ARB; + iattrib_list[ni++] = true; + } else { + iattrib_list[ni++] = WGL_BIND_TO_TEXTURE_RGB_ARB; + iattrib_list[ni++] = true; + } + } + + // Match up the framebuffer bits. + iattrib_list[ni++] = WGL_RED_BITS_ARB; + iattrib_list[ni++] = ivalue_list[red_bits_i]; + iattrib_list[ni++] = WGL_GREEN_BITS_ARB; + iattrib_list[ni++] = ivalue_list[green_bits_i]; + iattrib_list[ni++] = WGL_BLUE_BITS_ARB; + iattrib_list[ni++] = ivalue_list[blue_bits_i]; + iattrib_list[ni++] = WGL_ALPHA_BITS_ARB; + iattrib_list[ni++] = ivalue_list[alpha_bits_i]; + + iattrib_list[ni++] = WGL_ACCUM_RED_BITS_ARB; + iattrib_list[ni++] = ivalue_list[accum_red_bits_i]; + iattrib_list[ni++] = WGL_ACCUM_GREEN_BITS_ARB; + iattrib_list[ni++] = ivalue_list[accum_green_bits_i]; + iattrib_list[ni++] = WGL_ACCUM_BLUE_BITS_ARB; + iattrib_list[ni++] = ivalue_list[accum_blue_bits_i]; + iattrib_list[ni++] = WGL_ACCUM_ALPHA_BITS_ARB; + iattrib_list[ni++] = ivalue_list[accum_alpha_bits_i]; + + iattrib_list[ni++] = WGL_DEPTH_BITS_ARB; + iattrib_list[ni++] = ivalue_list[depth_bits_i]; + + iattrib_list[ni++] = WGL_STENCIL_BITS_ARB; + iattrib_list[ni++] = ivalue_list[stencil_bits_i]; + + if (wglgsg->_supports_wgl_multisample) { + iattrib_list[ni++] = WGL_SAMPLE_BUFFERS_ARB; + iattrib_list[ni++] = ivalue_list[sample_buffers_i]; + iattrib_list[ni++] = WGL_SAMPLES_ARB; + iattrib_list[ni++] = ivalue_list[multisamples_i]; + } + + // Match up properties. + iattrib_list[ni++] = WGL_DOUBLE_BUFFER_ARB; + iattrib_list[ni++] = ivalue_list[double_buffer_i]; + iattrib_list[ni++] = WGL_STEREO_ARB; + iattrib_list[ni++] = ivalue_list[stereo_i]; + + // Terminate the lists. + nassertr(ni < max_attrib_list && nf < max_attrib_list, NULL); + iattrib_list[ni] = 0; + fattrib_list[nf] = 0; + + // Now obtain a list of pixel formats that meet these minimum + // requirements. + static const unsigned int max_pformats = 32; + int pformat[max_pformats]; + memset(pformat, 0, sizeof(pformat)); + unsigned int nformats = 0; + if (!wglgsg->_wglChoosePixelFormatARB(twindow_dc, iattrib_list, fattrib_list, + max_pformats, pformat, &nformats) + || nformats == 0) { + if (wgldisplay_cat.is_debug()) { + wgldisplay_cat.debug() + << "No formats meet the criteria.\n"; + } + return 0; + } + + nformats = min(nformats, max_pformats); + + if (wgldisplay_cat.is_debug()) { + wgldisplay_cat.debug() + << "Found " << nformats << " pbuffer formats: ["; + for (unsigned int i = 0; i < nformats; i++) { + wgldisplay_cat.debug(false) + << " " << pformat[i]; + } + wgldisplay_cat.debug(false) + << " ]\n"; + } + + // If one of the options is the original pixfmt, keep it. + bool found_pbformat = false; + for (unsigned int i = 0; i < nformats && !found_pbformat; i++) { + if (pformat[i] == pbformat) { + found_pbformat = true; + } + } + + if (!found_pbformat) { + // Otherwise, pick any of them. + pbformat = pformat[0]; + } + + return pbformat; +} + //////////////////////////////////////////////////////////////////// // Function: wglGraphicsBuffer::process_1_event // Access: Private, Static diff --git a/panda/src/wgldisplay/wglGraphicsBuffer.h b/panda/src/wgldisplay/wglGraphicsBuffer.h index e839b3d248..d5b0beed45 100644 --- a/panda/src/wgldisplay/wglGraphicsBuffer.h +++ b/panda/src/wgldisplay/wglGraphicsBuffer.h @@ -60,11 +60,13 @@ protected: private: bool make_pbuffer(HDC window_dc); + int choose_pbuffer_format(HDC twindow_dc, bool draw_to_texture); static void process_1_event(); HPBUFFERARB _pbuffer; HDC _pbuffer_dc; + bool _render_texture; public: static TypeHandle get_class_type() { diff --git a/panda/src/wgldisplay/wglGraphicsPipe.cxx b/panda/src/wgldisplay/wglGraphicsPipe.cxx index 2657510a05..9021e23a18 100644 --- a/panda/src/wgldisplay/wglGraphicsPipe.cxx +++ b/panda/src/wgldisplay/wglGraphicsPipe.cxx @@ -329,6 +329,18 @@ int wglGraphicsPipe:: try_for_pfnum(HDC hdc, bool hardware, bool software, int frame_buffer_mode, int want_depth_bits, int want_color_bits, int want_alpha_bits, int want_stencil_bits) { + if (wgldisplay_cat.is_debug()) { + wgldisplay_cat.debug() + << "try_for_pfnum(hdc, hardware = " << hardware + << ", software = " << software + << ", frame_buffer_mode = 0x" << hex << frame_buffer_mode << dec + << ", want_depth_bits = " << want_depth_bits + << ", want_color_bits = " << want_color_bits + << ", want_alpha_bits = " << want_alpha_bits + << ", want_stencil_bits = " << want_stencil_bits + << ")\n"; + } + PIXELFORMATDESCRIPTOR pfd; ZeroMemory(&pfd,sizeof(PIXELFORMATDESCRIPTOR)); pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR); @@ -348,16 +360,6 @@ try_for_pfnum(HDC hdc, bool hardware, bool software, int frame_buffer_mode, break; } - wgldisplay_cat.debug() - << "try_for_pfnum(hdc, hardware = " << hardware - << ", software = " << software - << ", frame_buffer_mode = 0x" << hex << frame_buffer_mode << dec - << ", want_depth_bits = " << want_depth_bits - << ", want_color_bits = " << want_color_bits - << ", want_alpha_bits = " << want_alpha_bits - << ", want_stencil_bits = " << want_stencil_bits - << ")\n"; - // We have to call DescribePixelFormat() once just to get the // highest pfnum available. Then we can iterate through all of the // pfnums. @@ -647,6 +649,18 @@ try_for_pfnum_advanced(int orig_pfnum, const wglGraphicsStateGuardian *wglgsg, int want_depth_bits, int want_color_bits, int want_alpha_bits, int want_stencil_bits, int want_multisamples) { + if (wgldisplay_cat.is_debug()) { + wgldisplay_cat.debug() + << "try_for_pfnum_advanced(orig_pfnum = " << orig_pfnum + << ", wglgsg, window_dc, frame_buffer_mode = 0x" << hex << frame_buffer_mode << dec + << ", want_depth_bits = " << want_depth_bits + << ", want_color_bits = " << want_color_bits + << ", want_alpha_bits = " << want_alpha_bits + << ", want_stencil_bits = " << want_stencil_bits + << ", want_multisamples = " << want_multisamples + << ")\n"; + } + static const int max_attrib_list = 32; int iattrib_list[max_attrib_list]; float fattrib_list[max_attrib_list]; @@ -727,8 +741,8 @@ try_for_pfnum_advanced(int orig_pfnum, const wglGraphicsStateGuardian *wglgsg, max_pformats, pformat, &nformats) || nformats == 0) { if (wgldisplay_cat.is_debug()) { - wgldisplay_cat.info() - << "Couldn't find a suitable advanced pixel format.\n"; + wgldisplay_cat.debug() + << "No formats meet the criteria.\n"; } return 0; } diff --git a/panda/src/wgldisplay/wglGraphicsPipe.h b/panda/src/wgldisplay/wglGraphicsPipe.h index 2e6763597e..07816a2d4c 100644 --- a/panda/src/wgldisplay/wglGraphicsPipe.h +++ b/panda/src/wgldisplay/wglGraphicsPipe.h @@ -86,6 +86,8 @@ public: private: static TypeHandle _type_handle; + + friend class wglGraphicsBuffer; }; #include "wglGraphicsPipe.I" diff --git a/panda/src/wgldisplay/wglGraphicsStateGuardian.cxx b/panda/src/wgldisplay/wglGraphicsStateGuardian.cxx index b93783d32a..1859897e0e 100755 --- a/panda/src/wgldisplay/wglGraphicsStateGuardian.cxx +++ b/panda/src/wgldisplay/wglGraphicsStateGuardian.cxx @@ -46,6 +46,7 @@ wglGraphicsStateGuardian(const FrameBufferProperties &properties, _supports_pbuffer = false; _supports_pixel_format = false; _supports_wgl_multisample = false; + _supports_render_texture = false; } //////////////////////////////////////////////////////////////////// @@ -75,6 +76,7 @@ reset() { _supports_pbuffer = has_extension("WGL_ARB_pbuffer"); _supports_pixel_format = has_extension("WGL_ARB_pixel_format"); _supports_wgl_multisample = has_extension("WGL_ARB_multisample"); + _supports_render_texture = has_extension("WGL_ARB_render_texture"); _wglCreatePbufferARB = (PFNWGLCREATEPBUFFERARBPROC)wglGetProcAddress("wglCreatePbufferARB"); @@ -115,6 +117,23 @@ reset() { _supports_pixel_format = false; } } + + _wglBindTexImageARB = + (PFNWGLBINDTEXIMAGEARBPROC)wglGetProcAddress("wglBindTexImageARB"); + _wglReleaseTexImageARB = + (PFNWGLRELEASETEXIMAGEARBPROC)wglGetProcAddress("wglReleaseTexImageARB"); + _wglSetPbufferAttribARB = + (PFNWGLSETPBUFFERATTRIBARBPROC)wglGetProcAddress("wglSetPbufferAttribARB"); + + if (_supports_render_texture) { + if (_wglBindTexImageARB == NULL || + _wglReleaseTexImageARB == NULL || + _wglSetPbufferAttribARB == NULL) { + wgldisplay_cat.error() + << "Driver claims to support WGL_ARB_render_texture, but does not define all functions.\n"; + _supports_render_texture = false; + } + } } //////////////////////////////////////////////////////////////////// diff --git a/panda/src/wgldisplay/wglGraphicsStateGuardian.h b/panda/src/wgldisplay/wglGraphicsStateGuardian.h index 9f0e73fe62..a96cd24d80 100755 --- a/panda/src/wgldisplay/wglGraphicsStateGuardian.h +++ b/panda/src/wgldisplay/wglGraphicsStateGuardian.h @@ -82,7 +82,6 @@ private: public: bool _supports_pbuffer; - PFNWGLCREATEPBUFFERARBPROC _wglCreatePbufferARB; PFNWGLGETPBUFFERDCARBPROC _wglGetPbufferDCARB; PFNWGLRELEASEPBUFFERDCARBPROC _wglReleasePbufferDCARB; @@ -90,13 +89,17 @@ public: PFNWGLQUERYPBUFFERARBPROC _wglQueryPbufferARB; bool _supports_pixel_format; - PFNWGLGETPIXELFORMATATTRIBIVARBPROC _wglGetPixelFormatAttribivARB; PFNWGLGETPIXELFORMATATTRIBFVARBPROC _wglGetPixelFormatAttribfvARB; PFNWGLCHOOSEPIXELFORMATARBPROC _wglChoosePixelFormatARB; bool _supports_wgl_multisample; + bool _supports_render_texture; + PFNWGLBINDTEXIMAGEARBPROC _wglBindTexImageARB; + PFNWGLRELEASETEXIMAGEARBPROC _wglReleaseTexImageARB; + PFNWGLSETPBUFFERATTRIBARBPROC _wglSetPbufferAttribARB; + public: static TypeHandle get_class_type() { return _type_handle; @@ -113,6 +116,8 @@ public: private: static TypeHandle _type_handle; + + friend class wglGraphicsBuffer; }; #include "wglGraphicsStateGuardian.I"