diff options
| author | Matthias Melcher <fltk@matthiasm.com> | 2016-01-21 16:37:42 +0000 |
|---|---|---|
| committer | Matthias Melcher <fltk@matthiasm.com> | 2016-01-21 16:37:42 +0000 |
| commit | 5ff6efd52913ba1d3ec6f22bc61e416a26e70361 (patch) | |
| tree | 1debe4f2511064f890ad00500953f55bc0f38ec9 | |
| parent | 84e9be966d40bd6d74b5165987049051127f3a04 (diff) | |
Removed OpenGL graphics driver from public view. For the parts that are implemented, it will 'just work' by allowing fl_* rendering into OpenGL contexts (such as widgets, etc.)
git-svn-id: file:///fltk/svn/fltk/branches/branch-1.3-porting@11021 ea41ed52-d2ee-0310-a9c1-e6b18d33e121
| -rw-r--r-- | src/cfg_gfx/opengl.H | 784 | ||||
| -rw-r--r-- | src/cfg_gfx/opengl_rect.cxx | 879 | ||||
| -rw-r--r-- | src/cfg_gfx/quartz_rect.cxx | 6 |
3 files changed, 198 insertions, 1471 deletions
diff --git a/src/cfg_gfx/opengl.H b/src/cfg_gfx/opengl.H index 82b38fd14..7737757b3 100644 --- a/src/cfg_gfx/opengl.H +++ b/src/cfg_gfx/opengl.H @@ -1,9 +1,10 @@ // // "$Id$" // -// OpenGL window code for the Fast Light Tool Kit (FLTK). +// Definition of OpenGL graphics driver +// for the Fast Light Tool Kit (FLTK). // -// Copyright 1998-2015 by Bill Spitzak and others. +// Copyright 1998-2016 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this @@ -16,767 +17,54 @@ // http://www.fltk.org/str.php // -#include "flstring.h" -#include "config_lib.h" -#if HAVE_GL +/** + \file opengl.H + \brief Definition of OpenGL graphics driver. + */ -extern int fl_gl_load_plugin; +#ifndef FL_CFG_GFX_OPENGL_H +#define FL_CFG_GFX_OPENGL_H -#include <FL/Fl.H> -#include <FL/x.H> -#include "Fl_Gl_Choice.H" -#ifdef __APPLE__ -#include <FL/gl.h> -#include <OpenGL/OpenGL.h> -#endif -#include <FL/Fl_Gl_Window.H> #include <FL/Fl_Device.H> -#include <stdlib.h> -#include <FL/fl_utf8.h> - -#if defined(WIN32) || defined(__APPLE__) -#elif defined(FL_PORTING) -# pragma message "FL_PORTING: implement the creation and destruction of OpenGL surfaces" -#else -#endif -// ------ this should be in a separate file! ----------------------------------- -#ifdef FL_CFG_GFX_OPENGL - -#include <FL/Fl_Device.H> -#include <FL/gl.h> - /** - \brief OpenGL pecific graphics class. - * - This class is implemented only on the Mac OS X platform. + \brief OpenGL specific graphics class. */ class FL_EXPORT Fl_OpenGL_Graphics_Driver : public Fl_Graphics_Driver { public: static const char *class_id; const char *class_name() {return class_id;}; - void draw(const char* str, int n, int x, int y) { - gl_draw(str, n, x, y); - } - void color(Fl_Color c) { - gl_color(c); - } - void color(uchar r, uchar g, uchar b) { - unsigned int c = (r<<24)|(g<<16)|(b<<8); - gl_color(c); - } - // --- implementation will eventually be in src/fl_rect.cxx which includes src/cfg_gfx/xlib_rect.cxx - // --- line and polygon drawing with integer coordinates - void point(int x, int y) { - glBegin(GL_POINTS); - glVertex2i(x, y); - glEnd(); - } - void rect(int x, int y, int w, int h) { - glBegin(GL_LINE_LOOP); - glVertex2i(x, y); - glVertex2i(x+w, y); - glVertex2i(x+w, y+h); - glVertex2i(x, y+h); - glEnd(); - } - void rectf(int x, int y, int w, int h) { - if (w<=0 || h<=0) return; - // OpenGL has the natural origin at the bottom left. Drawing in FLTK - // coordinates requires that we shift the rectangle one pixel up. - glBegin(GL_POLYGON); - glVertex2i(x, y-1); - glVertex2i(x+w, y-1); - glVertex2i(x+w, y+h-1); - glVertex2i(x, y+h-1); - glEnd(); - } - void line(int x, int y, int x1, int y1) { - glBegin(GL_LINE_STRIP); - glVertex2i(x, y); - glVertex2i(x1, y1); - glEnd(); - point(x1, y1); - } - void line(int x, int y, int x1, int y1, int x2, int y2) { - glBegin(GL_LINE_STRIP); - glVertex2i(x, y); - glVertex2i(x1, y1); - glVertex2i(x2, y2); - glEnd(); - point(x2, y2); - } - void xyline(int x, int y, int x1) { - glBegin(GL_LINE_STRIP); - glVertex2i(x, y); - glVertex2i(x1, y); - glEnd(); - point(x1, y); - } - void xyline(int x, int y, int x1, int y2) { - glBegin(GL_LINE_STRIP); - glVertex2i(x, y); - glVertex2i(x1, y); - glVertex2i(x1, y2); - glEnd(); - point(x1, y2); - } - void xyline(int x, int y, int x1, int y2, int x3) { - glBegin(GL_LINE_STRIP); - glVertex2i(x, y); - glVertex2i(x1, y); - glVertex2i(x1, y2); - glVertex2i(x3, y2); - glEnd(); - point(x3, y2); - } - void yxline(int x, int y, int y1) { - glBegin(GL_LINE_STRIP); - glVertex2i(x, y); - glVertex2i(x, y1); - glEnd(); - point(x, y1); - } - void yxline(int x, int y, int y1, int x2) { - glBegin(GL_LINE_STRIP); - glVertex2i(x, y); - glVertex2i(x, y1); - glVertex2i(x2, y1); - glEnd(); - point(x2, y1); - } - void yxline(int x, int y, int y1, int x2, int y3) { - glBegin(GL_LINE_STRIP); - glVertex2i(x, y); - glVertex2i(x, y1); - glVertex2i(x2, y1); - glVertex2i(x2, y3); - glEnd(); - point(x2, y3); - } - void loop(int x0, int y0, int x1, int y1, int x2, int y2) { - glBegin(GL_LINE_LOOP); - glVertex2i(x0, y0); - glVertex2i(x1, y1); - glVertex2i(x2, y2); - glEnd(); - } - void loop(int x0, int y0, int x1, int y1, int x2, int y2, int x3, int y3) { - glBegin(GL_LINE_LOOP); - glVertex2i(x0, y0); - glVertex2i(x1, y1); - glVertex2i(x2, y2); - glVertex2i(x3, y3); - glEnd(); - } - void polygon(int x0, int y0, int x1, int y1, int x2, int y2) { - glBegin(GL_POLYGON); - glVertex2i(x0, y0); - glVertex2i(x1, y1); - glVertex2i(x2, y2); - glEnd(); - } - void polygon(int x0, int y0, int x1, int y1, int x2, int y2, int x3, int y3) { - glBegin(GL_POLYGON); - glVertex2i(x0, y0); - glVertex2i(x1, y1); - glVertex2i(x2, y2); - glVertex2i(x3, y3); - glEnd(); - } - void push_clip(int x, int y, int w, int h) { - // TODO: implement OpenGL clipping - if (rstackptr < region_stack_max) rstack[++rstackptr] = 0L; - else Fl::warning("Fl_OpenGL_Graphics_Driver::push_clip: clip stack overflow!\n"); - } - int clip_box(int x, int y, int w, int h, int &X, int &Y, int &W, int &H) { - // TODO: implement OpenGL clipping - X = x; Y = y; W = w, H = h; - return 0; - } - int not_clipped(int x, int y, int w, int h) { - // TODO: implement OpenGL clipping - return 1; - } - void push_no_clip() { - // TODO: implement OpenGL clipping - if (rstackptr < region_stack_max) rstack[++rstackptr] = 0; - else Fl::warning("Fl_OpenGL_Graphics_Driver::push_no_clip: clip stack overflow!\n"); - restore_clip(); - } - void pop_clip() { - // TODO: implement OpenGL clipping - if (rstackptr > 0) { - rstackptr--; - } else Fl::warning("Fl_OpenGL_Graphics_Driver::pop_clip: clip stack underflow!\n"); - restore_clip(); - } - void restore_clip() { - // TODO: implement OpenGL clipping - fl_clip_state_number++; - } -}; - -const char *Fl_OpenGL_Graphics_Driver::class_id = "Fl_OpenGL_Graphics_Driver"; + void draw(const char* str, int n, int x, int y); + void color(Fl_Color c); + void color(uchar r, uchar g, uchar b); -Fl_OpenGL_Display_Device *Fl_OpenGL_Display_Device::display_device() { - static Fl_OpenGL_Display_Device *display = new Fl_OpenGL_Display_Device(new Fl_OpenGL_Graphics_Driver()); - return display; + // --- line and polygon drawing with integer coordinates + void point(int x, int y); + void rect(int x, int y, int w, int h); + void rectf(int x, int y, int w, int h); + void line(int x, int y, int x1, int y1); + void line(int x, int y, int x1, int y1, int x2, int y2); + void xyline(int x, int y, int x1); + void xyline(int x, int y, int x1, int y2); + void xyline(int x, int y, int x1, int y2, int x3); + void yxline(int x, int y, int y1); + void yxline(int x, int y, int y1, int x2); + void yxline(int x, int y, int y1, int x2, int y3); + void loop(int x0, int y0, int x1, int y1, int x2, int y2); + void loop(int x0, int y0, int x1, int y1, int x2, int y2, int x3, int y3); + void polygon(int x0, int y0, int x1, int y1, int x2, int y2); + void polygon(int x0, int y0, int x1, int y1, int x2, int y2, int x3, int y3); + void push_clip(int x, int y, int w, int h); + int clip_box(int x, int y, int w, int h, int &X, int &Y, int &W, int &H); + int not_clipped(int x, int y, int w, int h); + void push_no_clip(); + void pop_clip(); + void restore_clip(); }; -Fl_OpenGL_Display_Device::Fl_OpenGL_Display_Device(Fl_OpenGL_Graphics_Driver *graphics_driver) -: Fl_Surface_Device(graphics_driver) -{ -} - - -const char *Fl_OpenGL_Display_Device::class_id = "Fl_OpenGL_Display_Device"; - - - -#endif -// ------ end of separate file! ------------------------------------------------ - - -//////////////////////////////////////////////////////////////// - -// 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 - -//////////////////////////////////////////////////////////////// - -/** Returns non-zero if the hardware supports the given or current OpenGL mode. */ -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 defined(__APPLE__) - int need_redraw = 0; -#endif - 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(); -#elif defined(__APPLE__) - if( ! parent() ) need_redraw=1; -#endif - } - Fl_Window::show(); - -#ifdef __APPLE__ - set_visible(); - if(need_redraw) redraw();//necessary only after creation of a top-level GL window -#endif /* __APPLE__ */ -} - -#if defined(__APPLE__) - -int Fl_Gl_Window::pixels_per_unit() -{ - return (fl_mac_os_version >= 100700 && Fl::use_high_res_GL() && Fl_X::i(this) && Fl_X::i(this)->mapped_to_retina()) ? 2 : 1; -} - -#endif // __APPLE__ - -/** - The invalidate() method turns off valid() and is - equivalent to calling value(0). -*/ -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 -#if defined(__APPLE__) || defined(USE_X11) - if (a) { // when the mode is set using the a array of system-dependent values, and if asking for double buffer, - // the FL_DOUBLE flag must be set in the mode_ member variable - const int *aa = a; - while (*aa) { - if (*(aa++) == -# if defined(__APPLE__) - kCGLPFADoubleBuffer -# else - GLX_DOUBLEBUFFER -# endif - ) { m |= FL_DOUBLE; break; } - } - } -#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(USE_X11) - // 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(); - } -#elif defined(WIN32) - if (!g || (oldmode^m)&(FL_DOUBLE|FL_STEREO)) { - hide(); - show(); - } -#elif defined(__APPLE_QUARTZ__) - redraw(); -#else -# error unsupported platform -#endif - } else { - g = 0; - } - return 1; -} - -#define NON_LOCAL_CONTEXT 0x80000000 - -/** - The make_current() method selects the OpenGL context for the - widget. It is called automatically prior to the draw() method - being called and can also be used to implement feedback and/or - selection within the handle() method. -*/ - -void Fl_Gl_Window::make_current() { -// puts("Fl_Gl_Window::make_current()"); -// printf("make_current: context_=%p\n", context_); -#if defined(__APPLE__) - // detect if the window was moved between low and high resolution displays - if (Fl_X::i(this)->changed_resolution()){ - Fl_X::i(this)->changed_resolution(false); - invalidate(); - Fl_X::GLcontext_update(context_); - } -#endif - if (!context_) { - mode_ &= ~NON_LOCAL_CONTEXT; - context_ = fl_create_gl_context(this, g); - valid(0); - context_valid(0); - } - fl_set_gl_context(this, context_); - -#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; -} - -/** - Sets the projection so 0,0 is in the lower left of the window and each - pixel is 1 unit wide/tall. If you are drawing 2D images, your - draw() method may want to call this if valid() is false. -*/ -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(pixel_w()-v[0], pixel_h()-v[1], v[0], v[1]); - glOrtho(pixel_w()-v[0], pixel_w(), pixel_h()-v[1], pixel_h(), -1, 1); -#endif -} - -/** - The swap_buffers() method swaps the back and front buffers. - It is called automatically after the draw() method is called. -*/ -void Fl_Gl_Window::swap_buffers() { -#if defined(USE_X11) - glXSwapBuffers(fl_display, fl_xid(this)); -#elif defined(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_QUARTZ__) - if(overlay != NULL) { - // STR# 2944 [1] - // Save matrixmode/proj/modelview/rasterpos before doing overlay. - // - int wo=pixel_w(), ho=pixel_h(); - GLint matrixmode; - GLfloat pos[4]; - glGetIntegerv(GL_MATRIX_MODE, &matrixmode); - glGetFloatv(GL_CURRENT_RASTER_POSITION, pos); // save original glRasterPos - glMatrixMode(GL_PROJECTION); // save proj/model matrices - glPushMatrix(); - glLoadIdentity(); - glMatrixMode(GL_MODELVIEW); - glPushMatrix(); - glLoadIdentity(); - glScalef(2.0f/wo, 2.0f/ho, 1.0f); - glTranslatef(-wo/2.0f, -ho/2.0f, 0.0f); // set transform so 0,0 is bottom/left of Gl_Window - glRasterPos2i(0,0); // set glRasterPos to bottom left corner - { - // Emulate overlay by doing copypixels - glReadBuffer(GL_BACK); - glDrawBuffer(GL_FRONT); - glCopyPixels(0, 0, wo, ho, GL_COLOR); // copy GL_BACK to GL_FRONT - } - glPopMatrix(); // GL_MODELVIEW // restore model/proj matrices - glMatrixMode(GL_PROJECTION); - glPopMatrix(); - glMatrixMode(matrixmode); - glRasterPos3f(pos[0], pos[1], pos[2]); // restore original glRasterPos - } - /* // nothing to do here under Cocoa because [NSOpenGLContext -flushBuffer] done later replaces it - else - aglSwapBuffers((AGLContext)context_); - */ -#else -# error unsupported platform -#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() { - if (!shown()) return; - uchar save_valid = valid_f_ & 1; -#if HAVE_GL_OVERLAY && defined(WIN32) - uchar save_valid_f = valid_f_; -#endif - -#if HAVE_GL_OVERLAY && defined(WIN32) - - // Draw into hardware overlay planes if they are damaged: - if (overlay && overlay != this - && (damage()&(FL_DAMAGE_OVERLAY|FL_DAMAGE_EXPOSE) || !save_valid)) { - 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) { - return; - } - } -#endif - - make_current(); - - if (mode_ & FL_DOUBLE) { - - glDrawBuffer(GL_BACK); - - if (!SWAP_TYPE) { -#if defined (__APPLE_QUARTZ__) || defined (USE_X11) - SWAP_TYPE = COPY; -#else - SWAP_TYPE = UNDEFINED; -#endif - const char* c = fl_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; - else SWAP_TYPE = UNDEFINED; - } - } - - 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 if (SWAP_TYPE == SWAP){ - damage(FL_DAMAGE_ALL); - draw(); - if (overlay == this) draw_overlay(); - swap_buffers(); - } else if (SWAP_TYPE == UNDEFINED){ // 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 separate 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, pixel_w(), pixel_h()); - glOrtho(0, pixel_w(), 0, pixel_h(), -1, 1); - glRasterPos2i(0,0); - ortho_window = this; - } - glCopyPixels(0,0,pixel_w(),pixel_h(),GL_COLOR); - make_current(); // set current context back to draw overlay - damage1_ = 0; - - } else { - damage1_ = damage(); - clear_damage(0xff); draw(); - swap_buffers(); - } - - } -#ifdef __APPLE__ - Fl_X::GLcontext_flushbuffer(context_); -#endif - - if (overlay==this && SWAP_TYPE != SWAP) { // 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(); - - } - - 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()); - - int is_a_resize = (W != Fl_Widget::w() || H != Fl_Widget::h()); - if (is_a_resize) valid(0); - -#ifdef __APPLE__ - Fl_X *flx = Fl_X::i(this); - if (flx && flx->in_windowDidResize()) Fl_X::GLcontext_update(context_); -#endif - -#if ! ( defined(__APPLE__) || defined(WIN32) ) - if (is_a_resize && !resizable() && overlay && overlay != this) { - ((Fl_Gl_Window*)overlay)->resize(0,0,W,H); - } -#endif - - Fl_Window::resize(X,Y,W,H); -} - -/** - Sets a pointer to the GLContext that this window is using. - This is a system-dependent structure, but it is portable to copy - the context from one window to another. You can also set it to NULL, - which will force FLTK to recreate the context the next time make_current() - is called, this is useful for getting around bugs in OpenGL implementations. - - If <i>destroy_flag</i> is true the context will be destroyed by - fltk when the window is destroyed, or when the mode() is changed, - or the next time context(x) is called. -*/ -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; -} - -/** - Hides the window and destroys the OpenGL 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(); -} - -/** - The destructor removes the widget and destroys the OpenGL context - associated with it. -*/ -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 -} - -/** - You must implement this virtual function if you want to draw into the - overlay. The overlay is cleared before this is called. You should - draw anything that is not clear using OpenGL. You must use - gl_color(i) to choose colors (it allocates them from the colormap - using system-specific calls), and remember that you are in an indexed - OpenGL mode and drawing anything other than flat-shaded will probably - not work. - - Both this function and Fl_Gl_Window::draw() should check - Fl_Gl_Window::valid() and set the same transformation. If you - don't your code may not work on other systems. Depending on the OS, - and on whether overlays are real or simulated, the OpenGL context may - be the same or different between the overlay and main window. -*/ -void Fl_Gl_Window::draw_overlay() {} - -#endif - - /** - You \e \b must subclass Fl_Gl_Window and provide an implementation for - draw(). You may also provide an implementation of draw_overlay() - if you want to draw into the overlay planes. You can avoid - reinitializing the viewport and lights and other things by checking - valid() at the start of draw() and only doing the - initialization if it is false. - - The draw() method can <I>only</I> use OpenGL calls. Do not - attempt to call X, any of the functions in <FL/fl_draw.H>, or glX - directly. Do not call gl_start() or gl_finish(). - - If double-buffering is enabled in the window, the back and front - buffers are swapped after this function is completed. -*/ -void Fl_Gl_Window::draw() { -#ifdef FL_CFG_GFX_OPENGL - Fl_Surface_Device *prev_device = Fl_Surface_Device::surface(); - Fl_OpenGL_Display_Device::display_device()->set_current(); - glPushAttrib(GL_ENABLE_BIT); - glDisable(GL_DEPTH_TEST); - glPushMatrix(); - glLoadIdentity(); - glOrtho(-0.5, w()-0.5, h()-0.5, -0.5, -1, 1); -// glOrtho(0, w(), h(), 0, -1, 1); - glLineWidth(pixels_per_unit()); // should be 1 or 2 (2 if highres OpenGL) - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // FIXME: push on state stack - glEnable(GL_BLEND); // FIXME: push on state stack - - Fl_Window::draw(); - - glPopMatrix(); - glPushAttrib(GL_ENABLE_BIT); - prev_device->set_current(); -#else - Fl::fatal("Fl_Gl_Window::draw() *must* be overriden. Please refer to the documentation."); -#endif -} - - -/** - Handle some FLTK events as needed. - */ -int Fl_Gl_Window::handle(int event) -{ - return Fl_Window::handle(event); -} - -// don't remove me! this serves only to force linking of Fl_Gl_Device_Plugin.o -int Fl_Gl_Window::gl_plugin_linkage() { - return fl_gl_load_plugin; -} +#endif // FL_CFG_GFX_OPENGL_H // // End of "$Id$". diff --git a/src/cfg_gfx/opengl_rect.cxx b/src/cfg_gfx/opengl_rect.cxx index 82b38fd14..63038a19c 100644 --- a/src/cfg_gfx/opengl_rect.cxx +++ b/src/cfg_gfx/opengl_rect.cxx @@ -1,9 +1,9 @@ // // "$Id$" // -// OpenGL window code for the Fast Light Tool Kit (FLTK). +// Rectangle drawing routines for the Fast Light Tool Kit (FLTK). // -// Copyright 1998-2015 by Bill Spitzak and others. +// Copyright 1998-2016 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this @@ -16,767 +16,206 @@ // http://www.fltk.org/str.php // -#include "flstring.h" -#include "config_lib.h" -#if HAVE_GL +#ifndef FL_CFG_GFX_OPENGL_RECT_CXX +#define FL_CFG_GFX_OPENGL_RECT_CXX -extern int fl_gl_load_plugin; - -#include <FL/Fl.H> -#include <FL/x.H> -#include "Fl_Gl_Choice.H" -#ifdef __APPLE__ -#include <FL/gl.h> -#include <OpenGL/OpenGL.h> -#endif -#include <FL/Fl_Gl_Window.H> -#include <FL/Fl_Device.H> -#include <stdlib.h> -#include <FL/fl_utf8.h> - -#if defined(WIN32) || defined(__APPLE__) -#elif defined(FL_PORTING) -# pragma message "FL_PORTING: implement the creation and destruction of OpenGL surfaces" -#else -#endif - - -// ------ this should be in a separate file! ----------------------------------- -#ifdef FL_CFG_GFX_OPENGL - -#include <FL/Fl_Device.H> -#include <FL/gl.h> /** - \brief OpenGL pecific graphics class. - * - This class is implemented only on the Mac OS X platform. + \file quartz_rect.cxx + \brief OpenGL specific line and polygon drawing with integer coordinates. */ -class FL_EXPORT Fl_OpenGL_Graphics_Driver : public Fl_Graphics_Driver { -public: - static const char *class_id; - const char *class_name() {return class_id;}; - void draw(const char* str, int n, int x, int y) { - gl_draw(str, n, x, y); - } - void color(Fl_Color c) { - gl_color(c); - } - void color(uchar r, uchar g, uchar b) { - unsigned int c = (r<<24)|(g<<16)|(b<<8); - gl_color(c); - } - // --- implementation will eventually be in src/fl_rect.cxx which includes src/cfg_gfx/xlib_rect.cxx - // --- line and polygon drawing with integer coordinates - void point(int x, int y) { - glBegin(GL_POINTS); - glVertex2i(x, y); - glEnd(); - } - void rect(int x, int y, int w, int h) { - glBegin(GL_LINE_LOOP); - glVertex2i(x, y); - glVertex2i(x+w, y); - glVertex2i(x+w, y+h); - glVertex2i(x, y+h); - glEnd(); - } - void rectf(int x, int y, int w, int h) { - if (w<=0 || h<=0) return; - // OpenGL has the natural origin at the bottom left. Drawing in FLTK - // coordinates requires that we shift the rectangle one pixel up. - glBegin(GL_POLYGON); - glVertex2i(x, y-1); - glVertex2i(x+w, y-1); - glVertex2i(x+w, y+h-1); - glVertex2i(x, y+h-1); - glEnd(); - } - void line(int x, int y, int x1, int y1) { - glBegin(GL_LINE_STRIP); - glVertex2i(x, y); - glVertex2i(x1, y1); - glEnd(); - point(x1, y1); - } - void line(int x, int y, int x1, int y1, int x2, int y2) { - glBegin(GL_LINE_STRIP); - glVertex2i(x, y); - glVertex2i(x1, y1); - glVertex2i(x2, y2); - glEnd(); - point(x2, y2); - } - void xyline(int x, int y, int x1) { - glBegin(GL_LINE_STRIP); - glVertex2i(x, y); - glVertex2i(x1, y); - glEnd(); - point(x1, y); - } - void xyline(int x, int y, int x1, int y2) { - glBegin(GL_LINE_STRIP); - glVertex2i(x, y); - glVertex2i(x1, y); - glVertex2i(x1, y2); - glEnd(); - point(x1, y2); - } - void xyline(int x, int y, int x1, int y2, int x3) { - glBegin(GL_LINE_STRIP); - glVertex2i(x, y); - glVertex2i(x1, y); - glVertex2i(x1, y2); - glVertex2i(x3, y2); - glEnd(); - point(x3, y2); - } - void yxline(int x, int y, int y1) { - glBegin(GL_LINE_STRIP); - glVertex2i(x, y); - glVertex2i(x, y1); - glEnd(); - point(x, y1); - } - void yxline(int x, int y, int y1, int x2) { - glBegin(GL_LINE_STRIP); - glVertex2i(x, y); - glVertex2i(x, y1); - glVertex2i(x2, y1); - glEnd(); - point(x2, y1); - } - void yxline(int x, int y, int y1, int x2, int y3) { - glBegin(GL_LINE_STRIP); - glVertex2i(x, y); - glVertex2i(x, y1); - glVertex2i(x2, y1); - glVertex2i(x2, y3); - glEnd(); - point(x2, y3); - } - void loop(int x0, int y0, int x1, int y1, int x2, int y2) { - glBegin(GL_LINE_LOOP); - glVertex2i(x0, y0); - glVertex2i(x1, y1); - glVertex2i(x2, y2); - glEnd(); - } - void loop(int x0, int y0, int x1, int y1, int x2, int y2, int x3, int y3) { - glBegin(GL_LINE_LOOP); - glVertex2i(x0, y0); - glVertex2i(x1, y1); - glVertex2i(x2, y2); - glVertex2i(x3, y3); - glEnd(); - } - void polygon(int x0, int y0, int x1, int y1, int x2, int y2) { - glBegin(GL_POLYGON); - glVertex2i(x0, y0); - glVertex2i(x1, y1); - glVertex2i(x2, y2); - glEnd(); - } - void polygon(int x0, int y0, int x1, int y1, int x2, int y2, int x3, int y3) { - glBegin(GL_POLYGON); - glVertex2i(x0, y0); - glVertex2i(x1, y1); - glVertex2i(x2, y2); - glVertex2i(x3, y3); - glEnd(); - } - void push_clip(int x, int y, int w, int h) { - // TODO: implement OpenGL clipping - if (rstackptr < region_stack_max) rstack[++rstackptr] = 0L; - else Fl::warning("Fl_OpenGL_Graphics_Driver::push_clip: clip stack overflow!\n"); - } - int clip_box(int x, int y, int w, int h, int &X, int &Y, int &W, int &H) { - // TODO: implement OpenGL clipping - X = x; Y = y; W = w, H = h; - return 0; - } - int not_clipped(int x, int y, int w, int h) { - // TODO: implement OpenGL clipping - return 1; - } - void push_no_clip() { - // TODO: implement OpenGL clipping - if (rstackptr < region_stack_max) rstack[++rstackptr] = 0; - else Fl::warning("Fl_OpenGL_Graphics_Driver::push_no_clip: clip stack overflow!\n"); - restore_clip(); - } - void pop_clip() { - // TODO: implement OpenGL clipping - if (rstackptr > 0) { - rstackptr--; - } else Fl::warning("Fl_OpenGL_Graphics_Driver::pop_clip: clip stack underflow!\n"); - restore_clip(); - } - void restore_clip() { - // TODO: implement OpenGL clipping - fl_clip_state_number++; - } -}; - -const char *Fl_OpenGL_Graphics_Driver::class_id = "Fl_OpenGL_Graphics_Driver"; - -Fl_OpenGL_Display_Device *Fl_OpenGL_Display_Device::display_device() { - static Fl_OpenGL_Display_Device *display = new Fl_OpenGL_Display_Device(new Fl_OpenGL_Graphics_Driver()); - return display; -}; +#include <FL/gl.h> +#include "opengl.h" -Fl_OpenGL_Display_Device::Fl_OpenGL_Display_Device(Fl_OpenGL_Graphics_Driver *graphics_driver) -: Fl_Surface_Device(graphics_driver) -{ +void Fl_OpenGL_Graphics_Driver::draw(const char* str, int n, int x, int y) { + gl_draw(str, n, x, y); } +void Fl_OpenGL_Graphics_Driver::color(Fl_Color c) { + gl_color(c); +} -const char *Fl_OpenGL_Display_Device::class_id = "Fl_OpenGL_Display_Device"; - - - -#endif -// ------ end of separate file! ------------------------------------------------ - - -//////////////////////////////////////////////////////////////// - -// 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 +void Fl_OpenGL_Graphics_Driver::color(uchar r, uchar g, uchar b) { + unsigned int c = (r<<24)|(g<<16)|(b<<8); + gl_color(c); +} -//////////////////////////////////////////////////////////////// +// --- line and polygon drawing with integer coordinates -/** Returns non-zero if the hardware supports the given or current OpenGL mode. */ -int Fl_Gl_Window::can_do(int a, const int *b) { - return Fl_Gl_Choice::find(a,b) != 0; +void Fl_OpenGL_Graphics_Driver::point(int x, int y) { + glBegin(GL_POINTS); + glVertex2i(x, y); + glEnd(); } -void Fl_Gl_Window::show() { -#if defined(__APPLE__) - int need_redraw = 0; -#endif - 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(); -#elif defined(__APPLE__) - if( ! parent() ) need_redraw=1; -#endif - } - Fl_Window::show(); - -#ifdef __APPLE__ - set_visible(); - if(need_redraw) redraw();//necessary only after creation of a top-level GL window -#endif /* __APPLE__ */ +void Fl_OpenGL_Graphics_Driver::rect(int x, int y, int w, int h) { + glBegin(GL_LINE_LOOP); + glVertex2i(x, y); + glVertex2i(x+w, y); + glVertex2i(x+w, y+h); + glVertex2i(x, y+h); + glEnd(); } -#if defined(__APPLE__) - -int Fl_Gl_Window::pixels_per_unit() -{ - return (fl_mac_os_version >= 100700 && Fl::use_high_res_GL() && Fl_X::i(this) && Fl_X::i(this)->mapped_to_retina()) ? 2 : 1; +void Fl_OpenGL_Graphics_Driver::rectf(int x, int y, int w, int h) { + if (w<=0 || h<=0) return; + // OpenGL has the natural origin at the bottom left. Drawing in FLTK + // coordinates requires that we shift the rectangle one pixel up. + glBegin(GL_POLYGON); + glVertex2i(x, y-1); + glVertex2i(x+w, y-1); + glVertex2i(x+w, y+h-1); + glVertex2i(x, y+h-1); + glEnd(); } -#endif // __APPLE__ - -/** - The invalidate() method turns off valid() and is - equivalent to calling value(0). -*/ -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 +void Fl_OpenGL_Graphics_Driver::line(int x, int y, int x1, int y1) { + glBegin(GL_LINE_STRIP); + glVertex2i(x, y); + glVertex2i(x1, y1); + glEnd(); + point(x1, y1); } -int Fl_Gl_Window::mode(int m, const int *a) { - if (m == mode_ && a == alist) return 0; -#ifndef __APPLE__ - int oldmode = mode_; -#endif -#if defined(__APPLE__) || defined(USE_X11) - if (a) { // when the mode is set using the a array of system-dependent values, and if asking for double buffer, - // the FL_DOUBLE flag must be set in the mode_ member variable - const int *aa = a; - while (*aa) { - if (*(aa++) == -# if defined(__APPLE__) - kCGLPFADoubleBuffer -# else - GLX_DOUBLEBUFFER -# endif - ) { m |= FL_DOUBLE; break; } - } - } -#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(USE_X11) - // 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(); - } -#elif defined(WIN32) - if (!g || (oldmode^m)&(FL_DOUBLE|FL_STEREO)) { - hide(); - show(); - } -#elif defined(__APPLE_QUARTZ__) - redraw(); -#else -# error unsupported platform -#endif - } else { - g = 0; - } - return 1; +void Fl_OpenGL_Graphics_Driver::line(int x, int y, int x1, int y1, int x2, int y2) { + glBegin(GL_LINE_STRIP); + glVertex2i(x, y); + glVertex2i(x1, y1); + glVertex2i(x2, y2); + glEnd(); + point(x2, y2); } -#define NON_LOCAL_CONTEXT 0x80000000 +void Fl_OpenGL_Graphics_Driver::xyline(int x, int y, int x1) { + glBegin(GL_LINE_STRIP); + glVertex2i(x, y); + glVertex2i(x1, y); + glEnd(); + point(x1, y); +} -/** - The make_current() method selects the OpenGL context for the - widget. It is called automatically prior to the draw() method - being called and can also be used to implement feedback and/or - selection within the handle() method. -*/ - -void Fl_Gl_Window::make_current() { -// puts("Fl_Gl_Window::make_current()"); -// printf("make_current: context_=%p\n", context_); -#if defined(__APPLE__) - // detect if the window was moved between low and high resolution displays - if (Fl_X::i(this)->changed_resolution()){ - Fl_X::i(this)->changed_resolution(false); - invalidate(); - Fl_X::GLcontext_update(context_); - } -#endif - if (!context_) { - mode_ &= ~NON_LOCAL_CONTEXT; - context_ = fl_create_gl_context(this, g); - valid(0); - context_valid(0); - } - fl_set_gl_context(this, context_); - -#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_OpenGL_Graphics_Driver::xyline(int x, int y, int x1, int y2) { + glBegin(GL_LINE_STRIP); + glVertex2i(x, y); + glVertex2i(x1, y); + glVertex2i(x1, y2); + glEnd(); + point(x1, y2); } -/** - Sets the projection so 0,0 is in the lower left of the window and each - pixel is 1 unit wide/tall. If you are drawing 2D images, your - draw() method may want to call this if valid() is false. -*/ -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(pixel_w()-v[0], pixel_h()-v[1], v[0], v[1]); - glOrtho(pixel_w()-v[0], pixel_w(), pixel_h()-v[1], pixel_h(), -1, 1); -#endif +void Fl_OpenGL_Graphics_Driver::xyline(int x, int y, int x1, int y2, int x3) { + glBegin(GL_LINE_STRIP); + glVertex2i(x, y); + glVertex2i(x1, y); + glVertex2i(x1, y2); + glVertex2i(x3, y2); + glEnd(); + point(x3, y2); } -/** - The swap_buffers() method swaps the back and front buffers. - It is called automatically after the draw() method is called. -*/ -void Fl_Gl_Window::swap_buffers() { -#if defined(USE_X11) - glXSwapBuffers(fl_display, fl_xid(this)); -#elif defined(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_QUARTZ__) - if(overlay != NULL) { - // STR# 2944 [1] - // Save matrixmode/proj/modelview/rasterpos before doing overlay. - // - int wo=pixel_w(), ho=pixel_h(); - GLint matrixmode; - GLfloat pos[4]; - glGetIntegerv(GL_MATRIX_MODE, &matrixmode); - glGetFloatv(GL_CURRENT_RASTER_POSITION, pos); // save original glRasterPos - glMatrixMode(GL_PROJECTION); // save proj/model matrices - glPushMatrix(); - glLoadIdentity(); - glMatrixMode(GL_MODELVIEW); - glPushMatrix(); - glLoadIdentity(); - glScalef(2.0f/wo, 2.0f/ho, 1.0f); - glTranslatef(-wo/2.0f, -ho/2.0f, 0.0f); // set transform so 0,0 is bottom/left of Gl_Window - glRasterPos2i(0,0); // set glRasterPos to bottom left corner - { - // Emulate overlay by doing copypixels - glReadBuffer(GL_BACK); - glDrawBuffer(GL_FRONT); - glCopyPixels(0, 0, wo, ho, GL_COLOR); // copy GL_BACK to GL_FRONT - } - glPopMatrix(); // GL_MODELVIEW // restore model/proj matrices - glMatrixMode(GL_PROJECTION); - glPopMatrix(); - glMatrixMode(matrixmode); - glRasterPos3f(pos[0], pos[1], pos[2]); // restore original glRasterPos - } - /* // nothing to do here under Cocoa because [NSOpenGLContext -flushBuffer] done later replaces it - else - aglSwapBuffers((AGLContext)context_); - */ -#else -# error unsupported platform -#endif +void Fl_OpenGL_Graphics_Driver::yxline(int x, int y, int y1) { + glBegin(GL_LINE_STRIP); + glVertex2i(x, y); + glVertex2i(x, y1); + glEnd(); + point(x, y1); } -#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() { - if (!shown()) return; - uchar save_valid = valid_f_ & 1; -#if HAVE_GL_OVERLAY && defined(WIN32) - uchar save_valid_f = valid_f_; -#endif - -#if HAVE_GL_OVERLAY && defined(WIN32) - - // Draw into hardware overlay planes if they are damaged: - if (overlay && overlay != this - && (damage()&(FL_DAMAGE_OVERLAY|FL_DAMAGE_EXPOSE) || !save_valid)) { - 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) { - return; - } - } -#endif - - make_current(); - - if (mode_ & FL_DOUBLE) { - - glDrawBuffer(GL_BACK); - - if (!SWAP_TYPE) { -#if defined (__APPLE_QUARTZ__) || defined (USE_X11) - SWAP_TYPE = COPY; -#else - SWAP_TYPE = UNDEFINED; -#endif - const char* c = fl_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; - else SWAP_TYPE = UNDEFINED; - } - } - - 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 if (SWAP_TYPE == SWAP){ - damage(FL_DAMAGE_ALL); - draw(); - if (overlay == this) draw_overlay(); - swap_buffers(); - } else if (SWAP_TYPE == UNDEFINED){ // 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 separate 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, pixel_w(), pixel_h()); - glOrtho(0, pixel_w(), 0, pixel_h(), -1, 1); - glRasterPos2i(0,0); - ortho_window = this; - } - glCopyPixels(0,0,pixel_w(),pixel_h(),GL_COLOR); - make_current(); // set current context back to draw overlay - damage1_ = 0; - - } else { - damage1_ = damage(); - clear_damage(0xff); draw(); - swap_buffers(); - } - - } -#ifdef __APPLE__ - Fl_X::GLcontext_flushbuffer(context_); -#endif - - if (overlay==this && SWAP_TYPE != SWAP) { // 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(); - - } - - valid(1); - context_valid(1); +void Fl_OpenGL_Graphics_Driver::yxline(int x, int y, int y1, int x2) { + glBegin(GL_LINE_STRIP); + glVertex2i(x, y); + glVertex2i(x, y1); + glVertex2i(x2, y1); + glEnd(); + point(x2, y1); } -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()); - - int is_a_resize = (W != Fl_Widget::w() || H != Fl_Widget::h()); - if (is_a_resize) valid(0); - -#ifdef __APPLE__ - Fl_X *flx = Fl_X::i(this); - if (flx && flx->in_windowDidResize()) Fl_X::GLcontext_update(context_); -#endif - -#if ! ( defined(__APPLE__) || defined(WIN32) ) - if (is_a_resize && !resizable() && overlay && overlay != this) { - ((Fl_Gl_Window*)overlay)->resize(0,0,W,H); - } -#endif - - Fl_Window::resize(X,Y,W,H); +void Fl_OpenGL_Graphics_Driver::yxline(int x, int y, int y1, int x2, int y3) { + glBegin(GL_LINE_STRIP); + glVertex2i(x, y); + glVertex2i(x, y1); + glVertex2i(x2, y1); + glVertex2i(x2, y3); + glEnd(); + point(x2, y3); +} + +void Fl_OpenGL_Graphics_Driver::loop(int x0, int y0, int x1, int y1, int x2, int y2) { + glBegin(GL_LINE_LOOP); + glVertex2i(x0, y0); + glVertex2i(x1, y1); + glVertex2i(x2, y2); + glEnd(); +} + +void Fl_OpenGL_Graphics_Driver::loop(int x0, int y0, int x1, int y1, int x2, int y2, int x3, int y3) { + glBegin(GL_LINE_LOOP); + glVertex2i(x0, y0); + glVertex2i(x1, y1); + glVertex2i(x2, y2); + glVertex2i(x3, y3); + glEnd(); +} + +void Fl_OpenGL_Graphics_Driver::polygon(int x0, int y0, int x1, int y1, int x2, int y2) { + glBegin(GL_POLYGON); + glVertex2i(x0, y0); + glVertex2i(x1, y1); + glVertex2i(x2, y2); + glEnd(); +} + +void Fl_OpenGL_Graphics_Driver::polygon(int x0, int y0, int x1, int y1, int x2, int y2, int x3, int y3) { + glBegin(GL_POLYGON); + glVertex2i(x0, y0); + glVertex2i(x1, y1); + glVertex2i(x2, y2); + glVertex2i(x3, y3); + glEnd(); } -/** - Sets a pointer to the GLContext that this window is using. - This is a system-dependent structure, but it is portable to copy - the context from one window to another. You can also set it to NULL, - which will force FLTK to recreate the context the next time make_current() - is called, this is useful for getting around bugs in OpenGL implementations. - - If <i>destroy_flag</i> is true the context will be destroyed by - fltk when the window is destroyed, or when the mode() is changed, - or the next time context(x) is called. -*/ -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_OpenGL_Graphics_Driver::push_clip(int x, int y, int w, int h) { + // TODO: implement OpenGL clipping + if (rstackptr < region_stack_max) rstack[++rstackptr] = 0L; + else Fl::warning("Fl_OpenGL_Graphics_Driver::push_clip: clip stack overflow!\n"); +} + +int Fl_OpenGL_Graphics_Driver::clip_box(int x, int y, int w, int h, int &X, int &Y, int &W, int &H) { + // TODO: implement OpenGL clipping + X = x; Y = y; W = w, H = h; + return 0; +} -/** - Hides the window and destroys the OpenGL 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(); +int Fl_OpenGL_Graphics_Driver::not_clipped(int x, int y, int w, int h) { + // TODO: implement OpenGL clipping + return 1; } -/** - The destructor removes the widget and destroys the OpenGL context - associated with it. -*/ -Fl_Gl_Window::~Fl_Gl_Window() { - hide(); -// delete overlay; this is done by ~Fl_Group +void Fl_OpenGL_Graphics_Driver::push_no_clip() { + // TODO: implement OpenGL clipping + if (rstackptr < region_stack_max) rstack[++rstackptr] = 0; + else Fl::warning("Fl_OpenGL_Graphics_Driver::push_no_clip: clip stack overflow!\n"); + restore_clip(); } -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_OpenGL_Graphics_Driver::pop_clip() { + // TODO: implement OpenGL clipping + if (rstackptr > 0) { + rstackptr--; + } else Fl::warning("Fl_OpenGL_Graphics_Driver::pop_clip: clip stack underflow!\n"); + restore_clip(); } -/** - You must implement this virtual function if you want to draw into the - overlay. The overlay is cleared before this is called. You should - draw anything that is not clear using OpenGL. You must use - gl_color(i) to choose colors (it allocates them from the colormap - using system-specific calls), and remember that you are in an indexed - OpenGL mode and drawing anything other than flat-shaded will probably - not work. - - Both this function and Fl_Gl_Window::draw() should check - Fl_Gl_Window::valid() and set the same transformation. If you - don't your code may not work on other systems. Depending on the OS, - and on whether overlays are real or simulated, the OpenGL context may - be the same or different between the overlay and main window. -*/ -void Fl_Gl_Window::draw_overlay() {} - -#endif - - /** - You \e \b must subclass Fl_Gl_Window and provide an implementation for - draw(). You may also provide an implementation of draw_overlay() - if you want to draw into the overlay planes. You can avoid - reinitializing the viewport and lights and other things by checking - valid() at the start of draw() and only doing the - initialization if it is false. - - The draw() method can <I>only</I> use OpenGL calls. Do not - attempt to call X, any of the functions in <FL/fl_draw.H>, or glX - directly. Do not call gl_start() or gl_finish(). - - If double-buffering is enabled in the window, the back and front - buffers are swapped after this function is completed. -*/ -void Fl_Gl_Window::draw() { -#ifdef FL_CFG_GFX_OPENGL - Fl_Surface_Device *prev_device = Fl_Surface_Device::surface(); - Fl_OpenGL_Display_Device::display_device()->set_current(); - glPushAttrib(GL_ENABLE_BIT); - glDisable(GL_DEPTH_TEST); - glPushMatrix(); - glLoadIdentity(); - glOrtho(-0.5, w()-0.5, h()-0.5, -0.5, -1, 1); -// glOrtho(0, w(), h(), 0, -1, 1); - glLineWidth(pixels_per_unit()); // should be 1 or 2 (2 if highres OpenGL) - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // FIXME: push on state stack - glEnable(GL_BLEND); // FIXME: push on state stack - - Fl_Window::draw(); - - glPopMatrix(); - glPushAttrib(GL_ENABLE_BIT); - prev_device->set_current(); -#else - Fl::fatal("Fl_Gl_Window::draw() *must* be overriden. Please refer to the documentation."); -#endif +void Fl_OpenGL_Graphics_Driver::restore_clip() { + // TODO: implement OpenGL clipping + fl_clip_state_number++; } +const char *Fl_OpenGL_Graphics_Driver::class_id = "Fl_OpenGL_Graphics_Driver"; -/** - Handle some FLTK events as needed. - */ -int Fl_Gl_Window::handle(int event) -{ - return Fl_Window::handle(event); -} -// don't remove me! this serves only to force linking of Fl_Gl_Device_Plugin.o -int Fl_Gl_Window::gl_plugin_linkage() { - return fl_gl_load_plugin; -} +#endif // FL_CFG_GFX_OPENGL_RECT_CXX // // End of "$Id$". diff --git a/src/cfg_gfx/quartz_rect.cxx b/src/cfg_gfx/quartz_rect.cxx index dd72e6532..78b358b8c 100644 --- a/src/cfg_gfx/quartz_rect.cxx +++ b/src/cfg_gfx/quartz_rect.cxx @@ -17,8 +17,8 @@ // -#ifndef FL_CFG_GFX_QUARTZ_CXX -#define FL_CFG_GFX_QUARTZ_CXX +#ifndef FL_CFG_GFX_QUARTZ_RECT_CXX +#define FL_CFG_GFX_QUARTZ_RECT_CXX /** @@ -282,7 +282,7 @@ void Fl_Quartz_Graphics_Driver::restore_clip() { } -#endif +#endif // FL_CFG_GFX_QUARTZ_RECT_CXX // // End of "$Id$". |
