diff options
| author | Manolo Gouy <Manolo> | 2016-03-09 10:30:29 +0000 |
|---|---|---|
| committer | Manolo Gouy <Manolo> | 2016-03-09 10:30:29 +0000 |
| commit | fc3adbd7cbd73106dd3ec47216b485b6cd39a2a9 (patch) | |
| tree | 6bcc6b76c59c45dfc7e6b0efb124aff4c415fcd7 | |
| parent | 309213bfaeaff9b3beec9548aeb7762d7dbaa2f8 (diff) | |
Rewrite Fl_Gl_Device_Plugin.cxx in a platform-independent way.
The platform-specific code lands in src/Drivers/OpenGL/Fl_OpenGL_Display_Device.cxx
and the FL_PORTING clause should be compilable.
git-svn-id: file:///fltk/svn/fltk/branches/branch-1.3-porting@11327 ea41ed52-d2ee-0310-a9c1-e6b18d33e121
| -rw-r--r-- | src/Fl_Gl_Device_Plugin.cxx | 92 | ||||
| -rw-r--r-- | src/drivers/OpenGL/Fl_OpenGL_Display_Device.H | 3 | ||||
| -rw-r--r-- | src/drivers/OpenGL/Fl_OpenGL_Display_Device.cxx | 116 |
3 files changed, 122 insertions, 89 deletions
diff --git a/src/Fl_Gl_Device_Plugin.cxx b/src/Fl_Gl_Device_Plugin.cxx index 269a9ef02..fd428c96f 100644 --- a/src/Fl_Gl_Device_Plugin.cxx +++ b/src/Fl_Gl_Device_Plugin.cxx @@ -16,98 +16,12 @@ // http://www.fltk.org/str.php // -#include <config.h> #include "config_lib.h" -#include <FL/Fl_Printer.H> #include <FL/Fl_Gl_Window.H> -#include "Fl_Gl_Choice.H" #include <FL/Fl_RGB_Image.H> #include <FL/Fl_Shared_Image.H> -#include "FL/Fl.H" +#include "drivers/OpenGL/Fl_OpenGL_Display_Device.H" -#if defined(WIN32) || defined(__APPLE__) // PORTME: Fl_Surface_Driver - platform OpenGL management -#elif defined(FL_PORTING) -# pragma message "FL_PORTING: implement code to read OpenGL renderings into RGB maps" -#else -#endif - - -#if defined(__APPLE__) // PORTME: Fl_Surface_Driver - platform OpenGL management -uchar *convert_BGRA_to_RGB(uchar *baseAddress, int w, int h, int mByteWidth) -{ - uchar *newimg = new uchar[3*w*h]; - uchar *to = newimg; - for (int i = 0; i < h; i++) { - uchar *from = baseAddress + i * mByteWidth; - for (int j = 0; j < w; j++, from += 4) { -#if __ppc__ - memcpy(to, from + 1, 3); - to += 3; -#else - *(to++) = *(from+2); - *(to++) = *(from+1); - *(to++) = *from; -#endif - } - } - delete[] baseAddress; - return newimg; -} -#endif - -static Fl_RGB_Image* capture_gl_rectangle(Fl_Gl_Window *glw, int x, int y, int w, int h) -/* captures a rectangle of a Fl_Gl_Window window, and returns it as a RGB image - */ -{ -#if defined(__APPLE__) // PORTME: Fl_Surface_Driver - platform OpenGL management - const int bytesperpixel = 4; - int factor = glw->pixels_per_unit(); - if (factor > 1) { - w *= factor; h *= factor; x *= factor; y *= factor; - } -#else - const int bytesperpixel = 3; -#endif - glw->flush(); // forces a GL redraw, necessary for the glpuzzle demo - // Read OpenGL context pixels directly. - // For extra safety, save & restore OpenGL states that are changed - glPushClientAttrib(GL_CLIENT_PIXEL_STORE_BIT); - glPixelStorei(GL_PACK_ALIGNMENT, 4); /* Force 4-byte alignment */ - glPixelStorei(GL_PACK_ROW_LENGTH, 0); - glPixelStorei(GL_PACK_SKIP_ROWS, 0); - glPixelStorei(GL_PACK_SKIP_PIXELS, 0); - // Read a block of pixels from the frame buffer - int mByteWidth = w * bytesperpixel; - mByteWidth = (mByteWidth + 3) & ~3; // Align to 4 bytes - uchar *baseAddress = new uchar[mByteWidth * h]; - glReadPixels(x, glw->pixel_h() - (y+h), w, h, -#if defined(__APPLE__) // PORTME: Fl_Surface_Driver - platform OpenGL management - GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, -#else - GL_RGB, GL_UNSIGNED_BYTE, -#endif - baseAddress); - glPopClientAttrib(); -#if defined(__APPLE__) // PORTME: Fl_Surface_Driver - platform OpenGL management - baseAddress = convert_BGRA_to_RGB(baseAddress, w, h, mByteWidth); - mByteWidth = 3 * w; -#endif - - // GL gives a bottom-to-top image, convert it to top-to-bottom - uchar *tmp = new uchar[mByteWidth]; - uchar *p = baseAddress ; - uchar *q = baseAddress + (h-1)*mByteWidth; - for (int i = 0; i < h/2; i++, p += mByteWidth, q -= mByteWidth) { - memcpy(tmp, p, mByteWidth); - memcpy(p, q, mByteWidth); - memcpy(q, tmp, mByteWidth); - } - delete[] tmp; - - Fl_RGB_Image *img = new Fl_RGB_Image(baseAddress, w, h, 3, mByteWidth); - img->alloc_array = 1; - return img; -} /** This class will make sure that OpenGL printing/screen capture is available if fltk_gl @@ -120,7 +34,7 @@ public: virtual int print(Fl_Widget *w, int x, int y, int height /*useless*/) { Fl_Gl_Window *glw = w->as_gl_window(); if (!glw) return 0; - Fl_RGB_Image *img = capture_gl_rectangle(glw, 0, 0, glw->w(), glw->h()); + Fl_RGB_Image *img = Fl_OpenGL_Display_Device::capture_gl_rectangle(glw, 0, 0, glw->w(), glw->h()); Fl_Shared_Image *shared = Fl_Shared_Image::get(img); shared->scale(glw->w(), glw->h()); shared->draw(x, y); @@ -130,7 +44,7 @@ public: virtual Fl_RGB_Image* rectangle_capture(Fl_Widget *widget, int x, int y, int w, int h) { Fl_Gl_Window *glw = widget->as_gl_window(); if (!glw) return NULL; - return capture_gl_rectangle(glw, x, y, w, h); + return Fl_OpenGL_Display_Device::capture_gl_rectangle(glw, x, y, w, h); } }; diff --git a/src/drivers/OpenGL/Fl_OpenGL_Display_Device.H b/src/drivers/OpenGL/Fl_OpenGL_Display_Device.H index 9730fc9c4..5637e6525 100644 --- a/src/drivers/OpenGL/Fl_OpenGL_Display_Device.H +++ b/src/drivers/OpenGL/Fl_OpenGL_Display_Device.H @@ -20,6 +20,8 @@ #include <FL/Fl_Device.H> class Fl_OpenGL_Graphics_Driver; +class Fl_Gl_Window; +class Fl_RGB_Image; /** OpenGL Surface. @@ -29,6 +31,7 @@ class FL_EXPORT Fl_OpenGL_Display_Device : public Fl_Surface_Device { public: Fl_OpenGL_Display_Device(Fl_OpenGL_Graphics_Driver *graphics_driver); static Fl_OpenGL_Display_Device *display_device(); + static Fl_RGB_Image* capture_gl_rectangle(Fl_Gl_Window*, int, int, int, int); }; diff --git a/src/drivers/OpenGL/Fl_OpenGL_Display_Device.cxx b/src/drivers/OpenGL/Fl_OpenGL_Display_Device.cxx index 707bd1e52..a9a181f7c 100644 --- a/src/drivers/OpenGL/Fl_OpenGL_Display_Device.cxx +++ b/src/drivers/OpenGL/Fl_OpenGL_Display_Device.cxx @@ -19,8 +19,10 @@ #include <config.h> #include "../../config_lib.h" #include <FL/Fl_Gl_Window.H> +#include <FL/Fl_Image.H> #include <FL/Fl_Device.H> #include <FL/gl.h> +#include <string.h> #include "Fl_OpenGL_Graphics_Driver.H" #include "Fl_OpenGL_Display_Device.H" @@ -37,6 +39,120 @@ Fl_OpenGL_Display_Device::Fl_OpenGL_Display_Device(Fl_OpenGL_Graphics_Driver *gr { } +#ifdef FL_CFG_GFX_QUARTZ + +uchar *convert_BGRA_to_RGB(uchar *baseAddress, int w, int h, int mByteWidth) +{ + uchar *newimg = new uchar[3*w*h]; + uchar *to = newimg; + for (int i = 0; i < h; i++) { + uchar *from = baseAddress + i * mByteWidth; + for (int j = 0; j < w; j++, from += 4) { +#if __ppc__ + memcpy(to, from + 1, 3); + to += 3; +#else + *(to++) = *(from+2); + *(to++) = *(from+1); + *(to++) = *from; +#endif + } + } + delete[] baseAddress; + return newimg; +} + +Fl_RGB_Image* Fl_OpenGL_Display_Device::capture_gl_rectangle(Fl_Gl_Window* glw, int x, int y, int w, int h) +{ + const int bytesperpixel = 4; + int factor = glw->pixels_per_unit(); + if (factor > 1) { + w *= factor; h *= factor; x *= factor; y *= factor; + } + glw->flush(); // forces a GL redraw, necessary for the glpuzzle demo + // Read OpenGL context pixels directly. + // For extra safety, save & restore OpenGL states that are changed + glPushClientAttrib(GL_CLIENT_PIXEL_STORE_BIT); + glPixelStorei(GL_PACK_ALIGNMENT, 4); /* Force 4-byte alignment */ + glPixelStorei(GL_PACK_ROW_LENGTH, 0); + glPixelStorei(GL_PACK_SKIP_ROWS, 0); + glPixelStorei(GL_PACK_SKIP_PIXELS, 0); + // Read a block of pixels from the frame buffer + int mByteWidth = w * bytesperpixel; + mByteWidth = (mByteWidth + 3) & ~3; // Align to 4 bytes + uchar *baseAddress = new uchar[mByteWidth * h]; + glReadPixels(x, glw->pixel_h() - (y+h), w, h, + GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, + baseAddress); + glPopClientAttrib(); + baseAddress = convert_BGRA_to_RGB(baseAddress, w, h, mByteWidth); + mByteWidth = 3 * w; + + // GL gives a bottom-to-top image, convert it to top-to-bottom + uchar *tmp = new uchar[mByteWidth]; + uchar *p = baseAddress ; + uchar *q = baseAddress + (h-1)*mByteWidth; + for (int i = 0; i < h/2; i++, p += mByteWidth, q -= mByteWidth) { + memcpy(tmp, p, mByteWidth); + memcpy(p, q, mByteWidth); + memcpy(q, tmp, mByteWidth); + } + delete[] tmp; + + Fl_RGB_Image *img = new Fl_RGB_Image(baseAddress, w, h, 3, mByteWidth); + img->alloc_array = 1; + return img; + +} +#elif defined(FL_CFG_GFX_GDI) || defined(FL_CFG_GFX_XLIB) + +Fl_RGB_Image* Fl_OpenGL_Display_Device::capture_gl_rectangle(Fl_Gl_Window *glw, int x, int y, int w, int h) +/* captures a rectangle of a Fl_Gl_Window window, and returns it as a RGB image + */ +{ + const int bytesperpixel = 3; + glw->flush(); // forces a GL redraw, necessary for the glpuzzle demo + // Read OpenGL context pixels directly. + // For extra safety, save & restore OpenGL states that are changed + glPushClientAttrib(GL_CLIENT_PIXEL_STORE_BIT); + glPixelStorei(GL_PACK_ALIGNMENT, 4); /* Force 4-byte alignment */ + glPixelStorei(GL_PACK_ROW_LENGTH, 0); + glPixelStorei(GL_PACK_SKIP_ROWS, 0); + glPixelStorei(GL_PACK_SKIP_PIXELS, 0); + // Read a block of pixels from the frame buffer + int mByteWidth = w * bytesperpixel; + mByteWidth = (mByteWidth + 3) & ~3; // Align to 4 bytes + uchar *baseAddress = new uchar[mByteWidth * h]; + glReadPixels(x, glw->pixel_h() - (y+h), w, h, + GL_RGB, GL_UNSIGNED_BYTE, + baseAddress); + glPopClientAttrib(); + + // GL gives a bottom-to-top image, convert it to top-to-bottom + uchar *tmp = new uchar[mByteWidth]; + uchar *p = baseAddress ; + uchar *q = baseAddress + (h-1)*mByteWidth; + for (int i = 0; i < h/2; i++, p += mByteWidth, q -= mByteWidth) { + memcpy(tmp, p, mByteWidth); + memcpy(p, q, mByteWidth); + memcpy(q, tmp, mByteWidth); + } + delete[] tmp; + + Fl_RGB_Image *img = new Fl_RGB_Image(baseAddress, w, h, 3, mByteWidth); + img->alloc_array = 1; + return img; +} + +#elif defined(FL_PORTING) + +# pragma message "FL_PORTING: implement Fl_OpenGL_Display_Device::capture_gl_rectangle() for your platform" +Fl_RGB_Image* Fl_OpenGL_Display_Device::capture_gl_rectangle(Fl_Gl_Window* glw, int x, int y, int w, int h) +{ + return NULL; +} + +#endif // // End of "$Id$". // |
