diff options
| author | Michael R Sweet <michael.r.sweet@gmail.com> | 1998-10-06 18:46:47 +0000 |
|---|---|---|
| committer | Michael R Sweet <michael.r.sweet@gmail.com> | 1998-10-06 18:46:47 +0000 |
| commit | e7d805a88ca71a0e6499fe72830e58fe594ef05b (patch) | |
| tree | 8c0cd05b0f4098bba4b90b229c23ef8d96a80d8a /src/Fl_Gl_Window.cxx | |
| parent | f9039b2ae21988783feae9b362818e7923e82d14 (diff) | |
Commited Gustavo Hime's NT patches/fixes.
git-svn-id: file:///fltk/svn/fltk/trunk@7 ea41ed52-d2ee-0310-a9c1-e6b18d33e121
Diffstat (limited to 'src/Fl_Gl_Window.cxx')
| -rw-r--r-- | src/Fl_Gl_Window.cxx | 580 |
1 files changed, 293 insertions, 287 deletions
diff --git a/src/Fl_Gl_Window.cxx b/src/Fl_Gl_Window.cxx index acd08e6f3..0879e734e 100644 --- a/src/Fl_Gl_Window.cxx +++ b/src/Fl_Gl_Window.cxx @@ -1,287 +1,293 @@ -// Fl_Gl_Window.C - -#include <config.h> -#if HAVE_GL - -#include <FL/Fl.H> -#include <FL/x.H> -#include <FL/Fl_Gl_Window.H> -#include "Fl_Gl_Choice.H" - -//////////////////////////////////////////////////////////////// - -// The symbol SWAP_TYPE defines what is in the back buffer after doing -// a glXSwapBuffers(). - -// The OpenGl documentation says that the contents of the backbuffer -// are "undefined" after glXSwapBuffers(). However, if we know what -// is in the backbuffers then we can save a good deal of time. For -// this reason you can define some symbols to describe what is left in -// the back buffer. - -// The default of SWAP_SWAP works on an SGI, and will also work (but -// is sub-optimal) on machines that should be SWAP_COPY or SWAP_NODAMAGE. -// The win32 emulation of OpenGL can use COPY, but some (all?) OpenGL -// cards use SWAP. - -// contents of back buffer after glXSwapBuffers(): -#define UNDEFINED 0 // unknown -#define SWAP 1 // former front buffer -#define COPY 2 // unchanged -#define NODAMAGE 3 // unchanged even by X expose() events - -#ifdef MESA -#define SWAP_TYPE NODAMAGE -#else -#define SWAP_TYPE SWAP -#endif - -//////////////////////////////////////////////////////////////// - -int Fl_Gl_Window::can_do(int a, const int *b) { -#ifdef WIN32 - Fl_Gl_Choice *g = Fl_Gl_Choice::find(a,b); - HWND w = GetDesktopWindow(); - HDC dc = GetDC(w); - int r = ChoosePixelFormat(dc, &g->pfd); - ReleaseDC(w,dc); - return r != 0; -#else - return Fl_Gl_Choice::find(a,b) != 0; -#endif -} - -void Fl_Gl_Window::show() { -#ifndef WIN32 - if (!shown()) { - if (!g) { - g = Fl_Gl_Choice::find(mode_,alist); - if (!g) {Fl::error("Insufficient GL support"); return;} - } - Fl_X::make_xid(this, g->vis, g->colormap); - if (overlay && overlay != this) ((Fl_Gl_Window*)overlay)->show(); - } -#endif - Fl_Window::show(); -} - -void Fl_Gl_Window::invalidate() { - valid(0); -#ifndef WIN32 - if (overlay) ((Fl_Gl_Window*)overlay)->valid(0); -#endif -} - -extern GLXContext fl_first_context; // in Fl_Gl_Choice.C - -int Fl_Gl_Window::mode(int m, const int *a) { - if (m == mode_ && a == alist) return 0; - mode_ = m; alist = a; -#ifdef WIN32 - // destroy context and g: - if (shown()) {hide(); show();} -#else - // under X, if the visual changes we must make a new X window (!): - if (shown()) { - Fl_Gl_Choice *g1 = g; - g = Fl_Gl_Choice::find(mode_,alist); - if (!g || g->vis->visualid != g1->vis->visualid || g->d != g1->d) { - hide(); show(); - } - } -#endif - return 1; -} - -#ifdef WIN32 -extern char fl_direct_paint; // true when responding to WM_PAINT -#endif - -void Fl_Gl_Window::make_current() { -#ifdef WIN32 - HDC hdc = fl_private_dc(this, mode_,&g); - if (!context) { - context = wglCreateContext(hdc); - if (fl_first_context) wglShareLists(fl_first_context, (GLXContext)context); - else fl_first_context = (GLXContext)context; - valid(0); - } - wglMakeCurrent(hdc, (GLXContext)context); -#else - if (!context) { - context = glXCreateContext(fl_display, g->vis, fl_first_context, 1); - if (!fl_first_context) fl_first_context = (GLXContext)context; - valid(0); - } - glXMakeCurrent(fl_display, fl_xid(this), (GLXContext)context); -#endif - glDrawBuffer(GL_BACK); -} - -void Fl_Gl_Window::ortho() { - glLoadIdentity(); - glViewport(0, 0, w(), h()); - glOrtho(0, w(), 0, h(), -1, 1); -} - -void Fl_Gl_Window::swap_buffers() { -#ifdef WIN32 - SwapBuffers(Fl_X::i(this)->private_dc); -#else - glXSwapBuffers(fl_display, fl_xid(this)); -#endif -} - -#if HAVE_GL_OVERLAY -#if WIN32 -uchar fl_overlay; // changes how fl_color() works -#endif -#endif - -void Fl_Gl_Window::flush() { - make_current(); - -#if HAVE_GL_OVERLAY -#ifdef WIN32 - uchar save_valid = valid_; - if (overlay && overlay!= this && damage() == 8) goto DRAW_OVERLAY_ONLY; -#endif -#endif - - if (g->d) { - -#if SWAP_TYPE == NODAMAGE - - // don't draw if only overlay damage or expose events: - if ((damage()&~0xA0) || !valid()) draw(); - swap_buffers(); - -#elif SWAP_TYPE == COPY - - // don't draw if only the overlay is damaged: - if (damage() != 8 || !valid()) draw(); - swap_buffers(); - -#else // SWAP_TYPE == SWAP || SWAP_TYPE == UNDEFINED - - if (overlay == this) { // Use CopyPixels to act like SWAP_TYPE == COPY - - // don't draw if only the overlay is damaged: - if (damage1_ || damage() != 8 || !valid()) draw(); - // we use a seperate context for the copy because rasterpos must be 0 - // and depth test needs to be off: - static GLXContext ortho_context; - int init = !ortho_context; -#ifdef WIN32 - if (init) ortho_context = wglCreateContext(Fl_X::i(this)->private_dc); - wglMakeCurrent(Fl_X::i(this)->private_dc, ortho_context); -#else - if (init) - ortho_context = glXCreateContext(fl_display,g->vis,fl_first_context,1); - glXMakeCurrent(fl_display, fl_xid(this), ortho_context); -#endif - if (init) { - glDisable(GL_DEPTH_TEST); - glReadBuffer(GL_BACK); - glDrawBuffer(GL_FRONT); - } - glCopyPixels(0,0,w(),h(),GL_COLOR); - make_current(); // set current context back to draw overlay - damage1_ = 0; - - } else { - -#if SWAP_TYPE == SWAP - uchar old_damage = damage(); - clear_damage(damage1_|old_damage); draw(); - swap_buffers(); - damage1_ = old_damage; -#else // SWAP_TYPE == UNDEFINED - clear_damage(~0); draw(); - swap_buffers(); - damage1_ = ~0; -#endif - - } -#endif - - if (overlay==this) { // fake overlay in front buffer - glDrawBuffer(GL_FRONT); - draw_overlay(); - glDrawBuffer(GL_BACK); - glFlush(); - } - - } else { // single-buffered context is simpler: - - // this faking of the overlay is incorrect but worked good for - // one in-house program: - if (overlay != this || damage()!=8 || !Fl::pushed()) draw(); - if (overlay == this) draw_overlay(); - glFlush(); - - } - -#if HAVE_GL_OVERLAY -#ifdef WIN32 - if (overlay && overlay != this) { - DRAW_OVERLAY_ONLY: - valid_ = save_valid; - wglMakeCurrent(Fl_X::i(this)->private_dc, (GLXContext)overlay); - glDisable(GL_SCISSOR_TEST); - fl_overlay = 1; - glClear(GL_COLOR_BUFFER_BIT); - draw_overlay(); - wglSwapLayerBuffers(Fl_X::i(this)->private_dc,WGL_SWAP_OVERLAY1); - fl_overlay = 0; - } -#endif -#endif - - valid(1); -} - -void Fl_Gl_Window::resize(int X,int Y,int W,int H) { - if (W != w() || H != h()) valid(0); - Fl_Window::resize(X,Y,W,H); -} - -void Fl_Gl_Window::hide() { - if (context) { -#ifdef WIN32 - wglMakeCurrent(0, 0); - if (context && context != fl_first_context) - wglDeleteContext((GLXContext)context); - g = 0; -#else - glXMakeCurrent(fl_display, 0, 0); - if (context != fl_first_context) - glXDestroyContext(fl_display, (GLXContext)context); -#ifdef GLX_MESA_release_buffers - glXReleaseBuffersMESA(fl_display, fl_xid(this)); -#endif -#endif - context = 0; - } - Fl_Window::hide(); -} - -Fl_Gl_Window::~Fl_Gl_Window() { - hide(); -// delete overlay; this is done by ~Fl_Group -} - -void Fl_Gl_Window::init() { - end(); // we probably don't want any children - box(FL_NO_BOX); - mode_ = FL_RGB | FL_DEPTH | FL_DOUBLE; - alist = 0; - context = 0; - g = 0; - overlay = 0; - damage1_ = 0; -} - -void Fl_Gl_Window::draw_overlay() {} - -#endif +// Fl_Gl_Window.C
+
+#include <config.h>
+#if HAVE_GL
+
+#include <FL/Fl.H>
+#include <FL/x.H>
+#include <FL/Fl_Gl_Window.H>
+#include "Fl_Gl_Choice.H"
+
+////////////////////////////////////////////////////////////////
+
+// The symbol SWAP_TYPE defines what is in the back buffer after doing
+// a glXSwapBuffers().
+
+// The OpenGl documentation says that the contents of the backbuffer
+// are "undefined" after glXSwapBuffers(). However, if we know what
+// is in the backbuffers then we can save a good deal of time. For
+// this reason you can define some symbols to describe what is left in
+// the back buffer.
+
+// The default of SWAP_SWAP works on an SGI, and will also work (but
+// is sub-optimal) on machines that should be SWAP_COPY or SWAP_NODAMAGE.
+// The win32 emulation of OpenGL can use COPY, but some (all?) OpenGL
+// cards use SWAP.
+
+// contents of back buffer after glXSwapBuffers():
+#define UNDEFINED 0 // unknown
+#define SWAP 1 // former front buffer
+#define COPY 2 // unchanged
+#define NODAMAGE 3 // unchanged even by X expose() events
+
+#ifdef MESA
+#define SWAP_TYPE NODAMAGE
+#else
+#define SWAP_TYPE SWAP
+#endif
+
+////////////////////////////////////////////////////////////////
+
+HDC fl_GetDC(HWND);
+
+int Fl_Gl_Window::can_do(int a, const int *b) {
+#ifdef WIN32
+ Fl_Gl_Choice *g = Fl_Gl_Choice::find(a,b);
+/*
+ Is this necessary? Don't all windows have the same
+ support for pixel formats?
+ HWND w = GetDesktopWindow();
+ HDC dc = GetDC(w);
+*/
+ if (!fl_gc) fl_GetDC(0);
+ int r = ChoosePixelFormat(fl_gc, &g->pfd);
+ return r != 0;
+#else
+ return Fl_Gl_Choice::find(a,b) != 0;
+#endif
+}
+
+void Fl_Gl_Window::show() {
+#ifndef WIN32
+ if (!shown()) {
+ if (!g) {
+ g = Fl_Gl_Choice::find(mode_,alist);
+ if (!g) {Fl::error("Insufficient GL support"); return;}
+ }
+ Fl_X::make_xid(this, g->vis, g->colormap);
+ if (overlay && overlay != this) ((Fl_Gl_Window*)overlay)->show();
+ }
+#endif
+ Fl_Window::show();
+}
+
+void Fl_Gl_Window::invalidate() {
+ valid(0);
+#ifndef WIN32
+ if (overlay) ((Fl_Gl_Window*)overlay)->valid(0);
+#endif
+}
+
+extern GLXContext fl_first_context; // in Fl_Gl_Choice.C
+
+int Fl_Gl_Window::mode(int m, const int *a) {
+ if (m == mode_ && a == alist) return 0;
+ mode_ = m; alist = a;
+#ifdef WIN32
+ // destroy context and g:
+ if (shown()) {hide(); show();}
+#else
+ // under X, if the visual changes we must make a new X window (!):
+ if (shown()) {
+ Fl_Gl_Choice *g1 = g;
+ g = Fl_Gl_Choice::find(mode_,alist);
+ if (!g || g->vis->visualid != g1->vis->visualid || g->d != g1->d) {
+ hide(); show();
+ }
+ }
+#endif
+ return 1;
+}
+
+#ifdef WIN32
+extern char fl_direct_paint; // true when responding to WM_PAINT
+#endif
+
+void Fl_Gl_Window::make_current() {
+#ifdef WIN32
+ HDC hdc = fl_private_dc(this, mode_,&g);
+ if (!context) {
+ context = wglCreateContext(hdc);
+ if (fl_first_context) wglShareLists(fl_first_context, (GLXContext)context);
+ else fl_first_context = (GLXContext)context;
+ valid(0);
+ }
+ wglMakeCurrent(hdc, (GLXContext)context);
+#else
+ if (!context) {
+ context = glXCreateContext(fl_display, g->vis, fl_first_context, 1);
+ if (!fl_first_context) fl_first_context = (GLXContext)context;
+ valid(0);
+ }
+ glXMakeCurrent(fl_display, fl_xid(this), (GLXContext)context);
+#endif
+ glDrawBuffer(GL_BACK);
+}
+
+void Fl_Gl_Window::ortho() {
+ glLoadIdentity();
+ glViewport(0, 0, w(), h());
+ glOrtho(0, w(), 0, h(), -1, 1);
+}
+
+void Fl_Gl_Window::swap_buffers() {
+#ifdef WIN32
+ SwapBuffers(Fl_X::i(this)->private_dc);
+#else
+ glXSwapBuffers(fl_display, fl_xid(this));
+#endif
+}
+
+#if HAVE_GL_OVERLAY
+#if WIN32
+uchar fl_overlay; // changes how fl_color() works
+#endif
+#endif
+
+void Fl_Gl_Window::flush() {
+ make_current();
+
+#if HAVE_GL_OVERLAY
+#ifdef WIN32
+ uchar save_valid = valid_;
+ if (overlay && overlay!= this && damage() == 8) goto DRAW_OVERLAY_ONLY;
+#endif
+#endif
+
+ if (g->d) {
+
+#if SWAP_TYPE == NODAMAGE
+
+ // don't draw if only overlay damage or expose events:
+ if ((damage()&~0xA0) || !valid()) draw();
+ swap_buffers();
+
+#elif SWAP_TYPE == COPY
+
+ // don't draw if only the overlay is damaged:
+ if (damage() != 8 || !valid()) draw();
+ swap_buffers();
+
+#else // SWAP_TYPE == SWAP || SWAP_TYPE == UNDEFINED
+
+ if (overlay == this) { // Use CopyPixels to act like SWAP_TYPE == COPY
+
+ // don't draw if only the overlay is damaged:
+ if (damage1_ || damage() != 8 || !valid()) draw();
+ // we use a seperate context for the copy because rasterpos must be 0
+ // and depth test needs to be off:
+ static GLXContext ortho_context;
+ int init = !ortho_context;
+#ifdef WIN32
+ if (init) ortho_context = wglCreateContext(Fl_X::i(this)->private_dc);
+ wglMakeCurrent(Fl_X::i(this)->private_dc, ortho_context);
+#else
+ if (init)
+ ortho_context = glXCreateContext(fl_display,g->vis,fl_first_context,1);
+ glXMakeCurrent(fl_display, fl_xid(this), ortho_context);
+#endif
+ if (init) {
+ glDisable(GL_DEPTH_TEST);
+ glReadBuffer(GL_BACK);
+ glDrawBuffer(GL_FRONT);
+ }
+ glCopyPixels(0,0,w(),h(),GL_COLOR);
+ make_current(); // set current context back to draw overlay
+ damage1_ = 0;
+
+ } else {
+
+#if SWAP_TYPE == SWAP
+ uchar old_damage = damage();
+ clear_damage(damage1_|old_damage); draw();
+ swap_buffers();
+ damage1_ = old_damage;
+#else // SWAP_TYPE == UNDEFINED
+ clear_damage(~0); draw();
+ swap_buffers();
+ damage1_ = ~0;
+#endif
+
+ }
+#endif
+
+ if (overlay==this) { // fake overlay in front buffer
+ glDrawBuffer(GL_FRONT);
+ draw_overlay();
+ glDrawBuffer(GL_BACK);
+ glFlush();
+ }
+
+ } else { // single-buffered context is simpler:
+
+ // this faking of the overlay is incorrect but worked good for
+ // one in-house program:
+ if (overlay != this || damage()!=8 || !Fl::pushed()) draw();
+ if (overlay == this) draw_overlay();
+ glFlush();
+
+ }
+
+#if HAVE_GL_OVERLAY
+#ifdef WIN32
+ if (overlay && overlay != this) {
+ DRAW_OVERLAY_ONLY:
+ valid_ = save_valid;
+ wglMakeCurrent(Fl_X::i(this)->private_dc, (GLXContext)overlay);
+ glDisable(GL_SCISSOR_TEST);
+ fl_overlay = 1;
+ glClear(GL_COLOR_BUFFER_BIT);
+ draw_overlay();
+ wglSwapLayerBuffers(Fl_X::i(this)->private_dc,WGL_SWAP_OVERLAY1);
+ fl_overlay = 0;
+ }
+#endif
+#endif
+
+ valid(1);
+}
+
+void Fl_Gl_Window::resize(int X,int Y,int W,int H) {
+ if (W != w() || H != h()) valid(0);
+ Fl_Window::resize(X,Y,W,H);
+}
+
+void Fl_Gl_Window::hide() {
+ if (context) {
+#ifdef WIN32
+ wglMakeCurrent(0, 0);
+ if (context && context != fl_first_context)
+ wglDeleteContext((GLXContext)context);
+ g = 0;
+#else
+ glXMakeCurrent(fl_display, 0, 0);
+ if (context != fl_first_context)
+ glXDestroyContext(fl_display, (GLXContext)context);
+#ifdef GLX_MESA_release_buffers
+ glXReleaseBuffersMESA(fl_display, fl_xid(this));
+#endif
+#endif
+ context = 0;
+ }
+ Fl_Window::hide();
+}
+
+Fl_Gl_Window::~Fl_Gl_Window() {
+ hide();
+// delete overlay; this is done by ~Fl_Group
+}
+
+void Fl_Gl_Window::init() {
+ end(); // we probably don't want any children
+ box(FL_NO_BOX);
+ mode_ = FL_RGB | FL_DEPTH | FL_DOUBLE;
+ alist = 0;
+ context = 0;
+ g = 0;
+ overlay = 0;
+ damage1_ = 0;
+}
+
+void Fl_Gl_Window::draw_overlay() {}
+
+#endif
|
