From a6163888f3c56123b1db313743c6147ba498732c Mon Sep 17 00:00:00 2001 From: Yuval Adam Date: Fri, 8 Aug 2014 14:42:07 +0300 Subject: Add third_party libs --- .../windows/fltk-1.1.10/src/Fl_Gl_Window.cxx | 440 +++++++++++++++++++++ 1 file changed, 440 insertions(+) create mode 100644 third_party/windows/fltk-1.1.10/src/Fl_Gl_Window.cxx (limited to 'third_party/windows/fltk-1.1.10/src/Fl_Gl_Window.cxx') diff --git a/third_party/windows/fltk-1.1.10/src/Fl_Gl_Window.cxx b/third_party/windows/fltk-1.1.10/src/Fl_Gl_Window.cxx new file mode 100644 index 0000000..0deecca --- /dev/null +++ b/third_party/windows/fltk-1.1.10/src/Fl_Gl_Window.cxx @@ -0,0 +1,440 @@ +// +// "$Id: Fl_Gl_Window.cxx 6807 2009-06-30 13:38:52Z matt $" +// +// OpenGL window code for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2006 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +#include "flstring.h" +#if HAVE_GL + +#include +#include +#include "Fl_Gl_Choice.H" +#include +#include + +//////////////////////////////////////////////////////////////// + +// 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. + +// Having not found any way to determine this from glx (or wgl) I have +// resorted to letting the user specify it with an environment variable, +// GL_SWAP_TYPE, it should be equal to one of these symbols: + +// contents of back buffer after glXSwapBuffers(): +#define UNDEFINED 1 // anything +#define SWAP 2 // former front buffer (same as unknown) +#define COPY 3 // unchanged +#define NODAMAGE 4 // unchanged even by X expose() events + +static char SWAP_TYPE = 0 ; // 0 = determine it from environment variable + +//////////////////////////////////////////////////////////////// + +int Fl_Gl_Window::can_do(int a, const int *b) { + return Fl_Gl_Choice::find(a,b) != 0; +} + +void Fl_Gl_Window::show() { + if (!shown()) { + if (!g) { + g = Fl_Gl_Choice::find(mode_,alist); + + if (!g && (mode_ & FL_DOUBLE) == FL_SINGLE) { + g = Fl_Gl_Choice::find(mode_ | FL_DOUBLE,alist); + if (g) mode_ |= FL_FAKE_SINGLE; + } + + if (!g) { + Fl::error("Insufficient GL support"); + return; + } + } +#if !defined(WIN32) && !defined(__APPLE__) + Fl_X::make_xid(this, g->vis, g->colormap); + if (overlay && overlay != this) ((Fl_Gl_Window*)overlay)->show(); +#endif + } + Fl_Window::show(); + +#ifdef __APPLE__ + set_visible(); +#endif /* __APPLE__ */ +} + +void Fl_Gl_Window::invalidate() { + valid(0); + context_valid(0); +#ifndef WIN32 + if (overlay) { + ((Fl_Gl_Window*)overlay)->valid(0); + ((Fl_Gl_Window*)overlay)->context_valid(0); + } +#endif +} + +int Fl_Gl_Window::mode(int m, const int *a) { + if (m == mode_ && a == alist) return 0; +#ifndef __APPLE__ + int oldmode = mode_; +#endif // !__APPLE__ +#if !defined(WIN32) && !defined(__APPLE__) + Fl_Gl_Choice* oldg = g; +#endif // !WIN32 && !__APPLE__ + context(0); + mode_ = m; alist = a; + if (shown()) { + g = Fl_Gl_Choice::find(m, a); +#if defined(WIN32) + if (!g || (oldmode^m)&(FL_DOUBLE|FL_STEREO)) { + hide(); + show(); + } +#elif defined(__APPLE_QD__) + redraw(); +#elif defined(__APPLE_QUARTZ__) + // warning: the Quartz version should probably use Core GL (CGL) instead of AGL + redraw(); +#else + // under X, if the visual changes we must make a new X window (yuck!): + if (!g || g->vis->visualid!=oldg->vis->visualid || (oldmode^m)&FL_DOUBLE) { + hide(); + show(); + } +#endif + } else { + g = 0; + } + return 1; +} + +#define NON_LOCAL_CONTEXT 0x80000000 + +void Fl_Gl_Window::make_current() { +// puts("Fl_Gl_Window::make_current()"); +// printf("make_current: context_=%p\n", context_); + if (!context_) { + mode_ &= ~NON_LOCAL_CONTEXT; + context_ = fl_create_gl_context(this, g); + valid(0); + context_valid(0); + } + fl_set_gl_context(this, context_); + +#ifdef __APPLE__ + // Set the buffer rectangle here, since in resize() we won't have the + // correct parent window size to work with... + GLint xywh[4]; + + if (window()) { + xywh[0] = x(); + xywh[1] = window()->h() - y() - h(); + } else { + xywh[0] = 0; + xywh[1] = 0; + } + + xywh[2] = w(); + xywh[3] = h(); + + aglSetInteger(context_, AGL_BUFFER_RECT, xywh); + aglEnable(context_, AGL_BUFFER_RECT); +// printf("make_current: xywh=[%d %d %d %d]\n", xywh[0], xywh[1], xywh[2], xywh[3]); +#endif // __APPLE__ + +#if defined(WIN32) && USE_COLORMAP + if (fl_palette) { + fl_GetDC(fl_xid(this)); + SelectPalette(fl_gc, fl_palette, FALSE); + RealizePalette(fl_gc); + } +#endif // USE_COLORMAP + if (mode_ & FL_FAKE_SINGLE) { + glDrawBuffer(GL_FRONT); + glReadBuffer(GL_FRONT); + } + current_ = this; +} + +void Fl_Gl_Window::ortho() { +// Alpha NT seems to have a broken OpenGL that does not like negative coords: +#ifdef _M_ALPHA + glLoadIdentity(); + glViewport(0, 0, w(), h()); + glOrtho(0, w(), 0, h(), -1, 1); +#else + GLint v[2]; + glGetIntegerv(GL_MAX_VIEWPORT_DIMS, v); + glLoadIdentity(); + glViewport(w()-v[0], h()-v[1], v[0], v[1]); + glOrtho(w()-v[0], w(), h()-v[1], h(), -1, 1); +#endif +} + +void Fl_Gl_Window::swap_buffers() { +#ifdef WIN32 +# if HAVE_GL_OVERLAY + // Do not swap the overlay, to match GLX: + BOOL ret = wglSwapLayerBuffers(Fl_X::i(this)->private_dc, WGL_SWAP_MAIN_PLANE); + DWORD err = GetLastError();; +# else + SwapBuffers(Fl_X::i(this)->private_dc); +# endif +#elif defined(__APPLE_QD__) + aglSwapBuffers((AGLContext)context_); +#elif defined(__APPLE_QUARTZ__) + // warning: the Quartz version should probably use Core GL (CGL) instead of AGL + aglSwapBuffers((AGLContext)context_); +#else + glXSwapBuffers(fl_display, fl_xid(this)); +#endif +} + +#if HAVE_GL_OVERLAY && defined(WIN32) +uchar fl_overlay; // changes how fl_color() works +int fl_overlay_depth = 0; +#endif + +void Fl_Gl_Window::flush() { + uchar save_valid = valid_f_ & 1; +#if HAVE_GL_OVERLAY && defined(WIN32) + uchar save_valid_f = valid_f_; +#endif + +#ifdef __APPLE_QD__ + //: clear previous clipping in this shared port + GrafPtr port = GetWindowPort( fl_xid(this) ); + Rect rect; SetRect( &rect, 0, 0, 0x7fff, 0x7fff ); + GrafPtr old; GetPort( &old ); + SetPort( port ); + ClipRect( &rect ); + SetPort( old ); +#elif defined(__APPLE_QUARTZ__) + // warning: the Quartz version should probably use Core GL (CGL) instead of AGL + //: clear previous clipping in this shared port + GrafPtr port = GetWindowPort( fl_xid(this) ); + Rect rect; SetRect( &rect, 0, 0, 0x7fff, 0x7fff ); + GrafPtr old; GetPort( &old ); + SetPort( port ); + ClipRect( &rect ); + SetPort( old ); +#endif + +#if HAVE_GL_OVERLAY && defined(WIN32) + + bool fixcursor = false; // for fixing the SGI 320 bug + + // Draw into hardware overlay planes if they are damaged: + if (overlay && overlay != this + && (damage()&(FL_DAMAGE_OVERLAY|FL_DAMAGE_EXPOSE) || !save_valid)) { + // SGI 320 messes up overlay with user-defined cursors: + if (Fl_X::i(this)->cursor && Fl_X::i(this)->cursor != fl_default_cursor) { + fixcursor = true; // make it restore cursor later + SetCursor(0); + } + fl_set_gl_context(this, (GLContext)overlay); + if (fl_overlay_depth) + wglRealizeLayerPalette(Fl_X::i(this)->private_dc, 1, TRUE); + glDisable(GL_SCISSOR_TEST); + glClear(GL_COLOR_BUFFER_BIT); + fl_overlay = 1; + draw_overlay(); + fl_overlay = 0; + valid_f_ = save_valid_f; + wglSwapLayerBuffers(Fl_X::i(this)->private_dc, WGL_SWAP_OVERLAY1); + // if only the overlay was damaged we are done, leave main layer alone: + if (damage() == FL_DAMAGE_OVERLAY) { + if (fixcursor) SetCursor(Fl_X::i(this)->cursor); + return; + } + } +#endif + + make_current(); + + if (mode_ & FL_DOUBLE) { + + glDrawBuffer(GL_BACK); + + if (!SWAP_TYPE) { +#ifdef __APPLE_QD__ + SWAP_TYPE = COPY; +#elif defined __APPLE_QUARTZ__ + // warning: the Quartz version should probably use Core GL (CGL) instead of AGL + SWAP_TYPE = COPY; +#else + SWAP_TYPE = UNDEFINED; +#endif + const char* c = getenv("GL_SWAP_TYPE"); + if (c) { + if (!strcmp(c,"COPY")) SWAP_TYPE = COPY; + else if (!strcmp(c, "NODAMAGE")) SWAP_TYPE = NODAMAGE; + else if (!strcmp(c, "SWAP")) SWAP_TYPE = SWAP; + } + } + + if (SWAP_TYPE == NODAMAGE) { + + // don't draw if only overlay damage or expose events: + if ((damage()&~(FL_DAMAGE_OVERLAY|FL_DAMAGE_EXPOSE)) || !save_valid) + draw(); + swap_buffers(); + + } else if (SWAP_TYPE == COPY) { + + // don't draw if only the overlay is damaged: + if (damage() != FL_DAMAGE_OVERLAY || !save_valid) draw(); + swap_buffers(); + + } else { // SWAP_TYPE == UNDEFINED + + // If we are faking the overlay, use CopyPixels to act like + // SWAP_TYPE == COPY. Otherwise overlay redraw is way too slow. + if (overlay == this) { + // don't draw if only the overlay is damaged: + if (damage1_ || damage() != FL_DAMAGE_OVERLAY || !save_valid) draw(); + // we use a seperate context for the copy because rasterpos must be 0 + // and depth test needs to be off: + static GLContext ortho_context = 0; + static Fl_Gl_Window* ortho_window = 0; + int orthoinit = !ortho_context; + if (orthoinit) ortho_context = fl_create_gl_context(this, g); + fl_set_gl_context(this, ortho_context); + if (orthoinit || !save_valid || ortho_window != this) { + glDisable(GL_DEPTH_TEST); + glReadBuffer(GL_BACK); + glDrawBuffer(GL_FRONT); + glLoadIdentity(); + glViewport(0, 0, w(), h()); + glOrtho(0, w(), 0, h(), -1, 1); + glRasterPos2i(0,0); + ortho_window = this; + } + glCopyPixels(0,0,w(),h(),GL_COLOR); + make_current(); // set current context back to draw overlay + damage1_ = 0; + + } else { + damage1_ = damage(); + clear_damage(0xff); draw(); + swap_buffers(); + } + + } + + if (overlay==this) { // fake overlay in front buffer + glDrawBuffer(GL_FRONT); + draw_overlay(); + glDrawBuffer(GL_BACK); + glFlush(); + } + + } else { // single-buffered context is simpler: + + draw(); + if (overlay == this) draw_overlay(); + glFlush(); + + } + +#if HAVE_GL_OVERLAY && defined(WIN32) + if (fixcursor) SetCursor(Fl_X::i(this)->cursor); +#endif + valid(1); + context_valid(1); +} + +void Fl_Gl_Window::resize(int X,int Y,int W,int H) { +// printf("Fl_Gl_Window::resize(X=%d, Y=%d, W=%d, H=%d)\n", X, Y, W, H); +// printf("current: x()=%d, y()=%d, w()=%d, h()=%d\n", x(), y(), w(), h()); + + if (W != w() || H != h()) valid(0); + +#ifdef __APPLE__ + if (X != x() || Y != y() || W != w() || H != h()) aglUpdateContext(context_); +#elif !defined(WIN32) + if ((W != w() || H != h()) && !resizable() && overlay && overlay != this) { + ((Fl_Gl_Window*)overlay)->resize(0,0,W,H); + } +#endif + + Fl_Window::resize(X,Y,W,H); +} + +void Fl_Gl_Window::context(void* v, int destroy_flag) { + if (context_ && !(mode_&NON_LOCAL_CONTEXT)) fl_delete_gl_context(context_); + context_ = (GLContext)v; + if (destroy_flag) mode_ &= ~NON_LOCAL_CONTEXT; + else mode_ |= NON_LOCAL_CONTEXT; +} + +void Fl_Gl_Window::hide() { + context(0); +#if HAVE_GL_OVERLAY && defined(WIN32) + if (overlay && overlay != this) { + fl_delete_gl_context((GLContext)overlay); + overlay = 0; + } +#endif + 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; + valid_f_ = 0; + damage1_ = 0; + +#if 0 // This breaks resizing on Linux/X11 + int H = h(); + h(1); // Make sure we actually do something in resize()... + resize(x(), y(), w(), H); +#endif // 0 +} + +void Fl_Gl_Window::draw_overlay() {} + +#endif + +// +// End of "$Id: Fl_Gl_Window.cxx 6807 2009-06-30 13:38:52Z matt $". +// -- cgit v1.3.1