Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// TnzCore includes
Toshihiro Shimizu 890ddd
#include "texception.h"
Toshihiro Shimizu 890ddd
#include "tvectorgl.h"
Toshihiro Shimizu 890ddd
#include "tvectorimage.h"
Toshihiro Shimizu 890ddd
#include "trasterimage.h"
Toshihiro Shimizu 890ddd
#include "tgl.h"
Toshihiro Shimizu 890ddd
#include "tthreadmessage.h"
Toshihiro Shimizu 890ddd
#include "tsystem.h"
Toshihiro Shimizu 890ddd
#include "trop.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// Platform-specific includes
Toshihiro Shimizu 890ddd
#if defined(LINUX)
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#include <x11 xlib.h=""></x11>
Toshihiro Shimizu 890ddd
#include <gl glx.h=""></gl>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#include "xscopedlock.h"
Toshihiro Shimizu 890ddd
#include "tthread.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#elif MACOSX
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#include "qtofflinegl.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#include "tofflinegl.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#ifndef checkErrorsByGL
Shinya Kitaoka 120a6e
#define checkErrorsByGL                                                        \
Shinya Kitaoka 120a6e
  {                                                                            \
Shinya Kitaoka 120a6e
    GLenum err = glGetError();                                                 \
Shinya Kitaoka 120a6e
    assert(err != GL_INVALID_ENUM);                                            \
Shinya Kitaoka 120a6e
    assert(err != GL_INVALID_VALUE);                                           \
Shinya Kitaoka 120a6e
    assert(err != GL_INVALID_OPERATION);                                       \
Shinya Kitaoka 120a6e
    assert(err != GL_STACK_OVERFLOW);                                          \
Shinya Kitaoka 120a6e
    assert(err != GL_STACK_UNDERFLOW);                                         \
Shinya Kitaoka 120a6e
    assert(err != GL_OUT_OF_MEMORY);                                           \
Shinya Kitaoka 120a6e
    assert(err == GL_NO_ERROR);                                                \
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#undef checkErrorsByGL
Toshihiro Shimizu 890ddd
#define checkErrorsByGL /**/
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
using namespace std;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
TGLContextManager *currentContextManager = 0;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TOfflineGL::setContextManager(TGLContextManager *contextManager) {
Shinya Kitaoka 120a6e
  currentContextManager = contextManager;
Shinya Kitaoka 120a6e
  if (contextManager) contextManager->store();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//=============================================================================
Toshihiro Shimizu 890ddd
// WIN32Implementation : implementazione offlineGL  WIN32
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 9f5a1b
#ifdef _WIN32
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
namespace {
Shinya Kitaoka 120a6e
// We found out that our implementation of win32 opengl contexts can be someway
Shinya Kitaoka 120a6e
// not thread-safe. Deadlocks and errors could happen for wgl* and GDI functions
Shinya Kitaoka 120a6e
// on particular configurations (notably, Windows 7). So we mutex them as
Shinya Kitaoka 120a6e
// a temporary workaround.
Toshihiro Shimizu 890ddd
static QMutex win32ImpMutex;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
class WIN32Implementation : public TOfflineGL::Imp {
Toshihiro Shimizu 890ddd
public:
Shinya Kitaoka 120a6e
  HDC m_offDC;
Shinya Kitaoka 120a6e
  HGDIOBJ m_oldobj;
Shinya Kitaoka 120a6e
  HGLRC m_hglRC;
Shinya Kitaoka 120a6e
  HBITMAP m_offDIB;
Shinya Kitaoka 120a6e
  void *m_offData;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  //-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  WIN32Implementation(TDimension rasterSize,
Shinya Kitaoka 120a6e
                      std::shared_ptr<tofflinegl::imp> shared)</tofflinegl::imp>
Shinya Kitaoka 120a6e
      : TOfflineGL::Imp(rasterSize.lx, rasterSize.ly) {
Shinya Kitaoka 120a6e
    m_offData = 0;
Shinya Kitaoka 120a6e
    createContext(
Shinya Kitaoka 120a6e
        rasterSize,
Shinya Kitaoka 120a6e
        std::move(shared));  // makeCurrent is called at the end of this
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
Shinya Kitaoka 120a6e
    glClear(GL_COLOR_BUFFER_BIT);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    doneCurrent();  // doneCurrent must therefore be called here
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //-----------------------------------------------------------------------------
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  ~WIN32Implementation() {
Shinya Kitaoka 120a6e
    QMutexLocker locker(&win32ImpMutex);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    BOOL ret = wglMakeCurrent(m_offDC, NULL);
Shinya Kitaoka 120a6e
    assert(ret == TRUE);
Shinya Kitaoka 120a6e
    wglDeleteContext(m_hglRC);
Shinya Kitaoka 120a6e
    SelectObject(m_offDC, m_oldobj);
Shinya Kitaoka 120a6e
    DeleteObject(m_offDC);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    // si potrebbe passare un parametro che evita di distruggere la bitmap.
Shinya Kitaoka 120a6e
    // In tal caso il raster dovrebbe diventare owner del buffer, ma attualmente
Shinya Kitaoka 120a6e
    // questo non e' settabile in TRaster: quando gli si passa da fuori un
Shinya Kitaoka 120a6e
    // buffer,
Shinya Kitaoka 120a6e
    // automaticamente bufferOwner viene settato a false e non e' modificabile!
Shinya Kitaoka 120a6e
    DeleteObject(m_offDIB);
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //-----------------------------------------------------------------------------
Shinya Kitaoka 120a6e
Shinya Kitaoka 473e70
  void makeCurrent() override {
Shinya Kitaoka 120a6e
    QMutexLocker locker(&win32ImpMutex);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    int ret = wglMakeCurrent(m_offDC, m_hglRC);
Shinya Kitaoka 120a6e
    assert(ret == TRUE);
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //-----------------------------------------------------------------------------
Shinya Kitaoka 120a6e
Shinya Kitaoka 473e70
  void doneCurrent() override {
Shinya Kitaoka 120a6e
    QMutexLocker locker(&win32ImpMutex);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    glFlush();
Shinya Kitaoka 120a6e
    glFinish();
Shinya Kitaoka 120a6e
    assert(glGetError() == 0);
Shinya Kitaoka 120a6e
    wglMakeCurrent(NULL, NULL);
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //-----------------------------------------------------------------------------
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  void initBITMAPINFO(BITMAPINFO &info, const TDimension rasterSize) {
Shinya Kitaoka 120a6e
    memset(&info, 0, sizeof(BITMAPINFOHEADER));
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    info.bmiHeader.biSize          = sizeof(BITMAPINFOHEADER);
Shinya Kitaoka 120a6e
    info.bmiHeader.biWidth         = rasterSize.lx;
Shinya Kitaoka 120a6e
    info.bmiHeader.biHeight        = rasterSize.ly;
Shinya Kitaoka 120a6e
    info.bmiHeader.biPlanes        = 1;
Shinya Kitaoka 120a6e
    info.bmiHeader.biBitCount      = 32;
Shinya Kitaoka 120a6e
    info.bmiHeader.biCompression   = BI_RGB;
Shinya Kitaoka 120a6e
    info.bmiHeader.biSizeImage     = 0;
Shinya Kitaoka 120a6e
    info.bmiHeader.biXPelsPerMeter = 1000;
Shinya Kitaoka 120a6e
    info.bmiHeader.biYPelsPerMeter = 1000;
Shinya Kitaoka 120a6e
    info.bmiHeader.biClrUsed       = 0;
Shinya Kitaoka 120a6e
    info.bmiHeader.biClrImportant  = 0;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //-----------------------------------------------------------------------------
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  void createContext(TDimension rasterSize,
Shinya Kitaoka 473e70
                     std::shared_ptr<tofflinegl::imp> shared) override {</tofflinegl::imp>
Shinya Kitaoka 120a6e
    QMutexLocker locker(&win32ImpMutex);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    BITMAPINFO info;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    initBITMAPINFO(info, rasterSize);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    // open an offscreen device
Shinya Kitaoka 120a6e
    m_offDC = CreateCompatibleDC(NULL);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    // and a bitmap image
Shinya Kitaoka 120a6e
    m_offDIB =
Shinya Kitaoka 120a6e
        CreateDIBSection(m_offDC, &info, DIB_RGB_COLORS, &m_offData, NULL, 0);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    assert(m_offDIB);
Shinya Kitaoka 120a6e
    assert(m_offData);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    if (!m_offDIB || !m_offData)
Shinya Kitaoka 120a6e
      throw TException("cannot create OpenGL context. Check system resources!");
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    int dataSize =
Shinya Kitaoka 120a6e
        rasterSize.lx * rasterSize.ly * 4;  // number of byte of raster
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    memset(m_offData, 0, dataSize);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    m_oldobj = SelectObject(m_offDC, m_offDIB);  // select BIB to write
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    static PIXELFORMATDESCRIPTOR pfd = {
Shinya Kitaoka 120a6e
        sizeof(PIXELFORMATDESCRIPTOR),  // size of this pfd
Shinya Kitaoka 120a6e
        1,                              // version number
Shinya Kitaoka 120a6e
        0 | (false ? (PFD_DRAW_TO_WINDOW | PFD_DOUBLEBUFFER)
Shinya Kitaoka 120a6e
                   : (PFD_DRAW_TO_BITMAP | PFD_SUPPORT_GDI)) |
Shinya Kitaoka 120a6e
            PFD_SUPPORT_OPENGL,  // support OpenGL
Shinya Kitaoka 120a6e
        PFD_TYPE_RGBA,           // RGBA type
Shinya Kitaoka 120a6e
        32,                      // 32-bit color depth
Shinya Kitaoka 120a6e
        0,
Shinya Kitaoka 120a6e
        0, 0, 0, 0, 0,   // color bits ignored
Shinya Kitaoka 120a6e
        8,               // no alpha buffer /*===*/
Shinya Kitaoka 120a6e
        0,               // shift bit ignored
Shinya Kitaoka 120a6e
        0,               // no accumulation buffer
Shinya Kitaoka 120a6e
        0, 0, 0, 0,      // accum bits ignored
Shinya Kitaoka 120a6e
        32,              // 32-bit z-buffer
Shinya Kitaoka 120a6e
        32,              // max stencil buffer
Shinya Kitaoka 120a6e
        0,               // no auxiliary buffer
Shinya Kitaoka 120a6e
        PFD_MAIN_PLANE,  // main layer
Shinya Kitaoka 120a6e
        0,               // reserved
Shinya Kitaoka 120a6e
        0, 0, 0          // layer masks ignored
Shinya Kitaoka 120a6e
    };
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    // get the best available match of pixel format for the device context
Shinya Kitaoka 120a6e
    int iPixelFormat = ChoosePixelFormat(m_offDC, &pfd);
Shinya Kitaoka 120a6e
    assert(iPixelFormat != 0);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    // make that the pixel format of the device context
Shinya Kitaoka 120a6e
    int ret = SetPixelFormat(m_offDC, iPixelFormat, &pfd);
Shinya Kitaoka 120a6e
    assert(ret == TRUE);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    // make a valid context for OpenGL rendering
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    m_hglRC = wglCreateContext(m_offDC);
Shinya Kitaoka 120a6e
    assert(m_hglRC);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    if (!m_hglRC)
Shinya Kitaoka 120a6e
      throw TException("cannot create OpenGL context. Check system resources!");
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    if (shared) {
Shinya Kitaoka 120a6e
      // Share shared's display lists
Shinya Kitaoka 120a6e
      const WIN32Implementation *sharedImp =
Shinya Kitaoka 120a6e
          dynamic_cast<const *="" win32implementation="">(shared.get());</const>
Shinya Kitaoka 120a6e
      assert(sharedImp);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      bool ok = wglShareLists(sharedImp->m_hglRC, m_hglRC);
Shinya Kitaoka 120a6e
      assert(ok);
Shinya Kitaoka 120a6e
    }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    ret = wglMakeCurrent(m_offDC, m_hglRC);
Shinya Kitaoka 120a6e
    assert(ret == TRUE);
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  //-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  void swapRedBlueChannels(
Shinya Kitaoka 120a6e
      void *buffer,
Shinya Kitaoka 120a6e
      int bufferSize)  // Flips The Red And Blue Bytes (WidthxHeight)
Shinya Kitaoka 120a6e
  {
Shinya Kitaoka 120a6e
    void *b = buffer;  // Pointer To The Buffer
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
#ifdef x64
Shinya Kitaoka 120a6e
    int size   = bufferSize;
Shinya Kitaoka 120a6e
    UCHAR *pix = (UCHAR *)b;
Shinya Kitaoka 120a6e
    while (size > 0) {
Shinya Kitaoka 120a6e
      UCHAR r    = *pix;
Shinya Kitaoka 120a6e
      UCHAR b    = *(pix + 2);
Shinya Kitaoka 120a6e
      *pix       = b;
Shinya Kitaoka 120a6e
      *(pix + 2) = r;
Shinya Kitaoka 120a6e
      pix += 4;
Shinya Kitaoka 120a6e
      size--;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
/*unsigned long ebx = (unsigned long)b;
Shinya Kitaoka 120a6e
          while(size>0)
Shinya Kitaoka 120a6e
          {
Shinya Kitaoka 120a6e
            unsigned char al =__readgsbyte(ebx);
Shinya Kitaoka 120a6e
                unsigned char ah =__readgsbyte(ebx+2);
Shinya Kitaoka 120a6e
                __writegsbyte(ebx+2,al);
Shinya Kitaoka 120a6e
                __writegsbyte(ebx,ah);
Shinya Kitaoka 120a6e
                ebx+=4;
Shinya Kitaoka 120a6e
            size--;
Shinya Kitaoka 120a6e
          }*/
Shinya Kitaoka 120a6e
#else
Shinya Kitaoka 120a6e
    __asm        // Assembler Code To Follow
Shinya Kitaoka 120a6e
    {
Shinya Kitaoka 120a6e
        mov ecx, bufferSize  // Counter Set To Dimensions Of Our Memory Block
Shinya Kitaoka 120a6e
        mov ebx, b  // Points ebx To Our Data (b)
Shinya Kitaoka 120a6e
        label:  // Label Used For Looping
Shinya Kitaoka 120a6e
          mov al,[ebx+0]  // Loads Value At ebx Into al
Shinya Kitaoka 120a6e
          mov ah,[ebx+2]  // Loads Value At ebx+2 Into ah
Shinya Kitaoka 120a6e
          mov [ebx+2],al  // Stores Value In al At ebx+2
Shinya Kitaoka 120a6e
          mov [ebx+0],ah  // Stores Value In ah At ebx
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
          add ebx,4  // Moves Through The Data By 4 Bytes
Shinya Kitaoka 120a6e
          dec ecx  // Decreases Our Loop Counter
Shinya Kitaoka 120a6e
          jnz label  // If Not Zero Jump Back To Label
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
#endif
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  //-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 473e70
  void getRaster(TRaster32P raster) override {
Shinya Kitaoka 120a6e
    makeCurrent();
Shinya Kitaoka 120a6e
    glFlush();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    int lx = raster->getLx();
Shinya Kitaoka 120a6e
    int ly = raster->getLy();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    raster->lock();
Shinya Kitaoka 120a6e
    glReadPixels(0, 0, lx, ly, GL_RGBA /*GL_BGRA_EXT*/, GL_UNSIGNED_BYTE,
Shinya Kitaoka 120a6e
                 raster->getRawData());
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    swapRedBlueChannels(raster->getRawData(), lx * ly);
Shinya Kitaoka 120a6e
    raster->unlock();
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
};
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
// default imp generator
Shinya Kitaoka 120a6e
std::shared_ptr<tofflinegl::imp> defaultOfflineGLGenerator(</tofflinegl::imp>
Shinya Kitaoka 120a6e
    const TDimension &dim, std::shared_ptr<tofflinegl::imp> shared) {</tofflinegl::imp>
Shinya Kitaoka 120a6e
  return std::make_shared<win32implementation>(dim, shared);</win32implementation>
Shinya Kitaoka 120a6e
}
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
//=============================================================================
Shinya Kitaoka 120a6e
// XImplementation : implementazione offlineGL  Server X (MACOSX & LINUX)
Shinya Kitaoka 120a6e
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
#elif defined(LINUX)
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
class XImplementation : public TOfflineGL::Imp {
Shinya Kitaoka 120a6e
public:
Shinya Kitaoka 120a6e
  Display *m_dpy;
Shinya Kitaoka 120a6e
  GLXContext m_context;
Shinya Kitaoka 120a6e
  GLXPixmap m_pixmap;
Shinya Kitaoka 120a6e
  Pixmap m_xpixmap;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //-----------------------------------------------------------------------------
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  XImplementation(TDimension rasterSize) {
Shinya Kitaoka 120a6e
    createContext(rasterSize);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
Shinya Kitaoka 120a6e
    glClear(GL_COLOR_BUFFER_BIT);
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //-----------------------------------------------------------------------------
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  ~XImplementation() {
Shinya Kitaoka 120a6e
    glXDestroyContext(m_dpy, m_context);
Shinya Kitaoka 120a6e
    m_context = 0;
Shinya Kitaoka 120a6e
    safeGlXMakeCurrent(true);
Shinya Kitaoka 120a6e
    XCloseDisplay(m_dpy);
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //-----------------------------------------------------------------------------
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  bool safeGlXMakeCurrent(bool isDtor = false) {
Shinya Kitaoka 120a6e
    static std::map<pthread_t, glxcontext=""> m_glxContext;</pthread_t,>
Shinya Kitaoka 120a6e
    static TThread::Mutex mutex;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    QMutexLocker sl(&mutex);
Shinya Kitaoka 120a6e
    pthread_t self = pthread_self();
Shinya Kitaoka 120a6e
    std::map<pthread_t, glxcontext="">::iterator it = m_glxContext.find(self);</pthread_t,>
Shinya Kitaoka 120a6e
    if (((it != m_glxContext.end()) && (it->second != m_context)) ||
Shinya Kitaoka 120a6e
        (it == m_glxContext.end())) {
Shinya Kitaoka 120a6e
      //	cout << "calling GLXMakeCurrent " << self << " " << m_context <<
Shinya Kitaoka 120a6e
      //endl;
Shinya Kitaoka 120a6e
      Bool ret;
Shinya Kitaoka 120a6e
      if (!isDtor) ret   = glXMakeCurrent(m_dpy, m_pixmap, m_context);
Shinya Kitaoka 120a6e
      m_glxContext[self] = m_context;
Shinya Kitaoka 120a6e
      return ret;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
    // cout << "don't call GLXMakeCurrent " << self << " " << m_context << endl;
Shinya Kitaoka 120a6e
    return true;
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  //-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  void makeCurrent() {
Shinya Kitaoka 120a6e
    XScopedLock xsl;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    // Bool ret = glXMakeCurrent(m_dpy,m_pixmap,m_context);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    Bool ret = safeGlXMakeCurrent();
Shinya Kitaoka 120a6e
    assert(ret == True);
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  //-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  // DA IMPLEMENTARE !!!
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  void doneCurrent() {}
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  //-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  void createContext(TDimension rasterSize) {
Shinya Kitaoka 120a6e
    m_dpy            = XOpenDisplay(NULL);
Shinya Kitaoka 120a6e
    Window win       = DefaultRootWindow(m_dpy);
Shinya Kitaoka 120a6e
    int attribList[] = {GLX_RGBA, GLX_RED_SIZE, 1, GLX_GREEN_SIZE, 1,
Shinya Kitaoka 120a6e
                        GLX_BLUE_SIZE, 1,
Shinya Kitaoka 120a6e
                        //    			GLX_ALPHA_SIZE,  1,
Shinya Kitaoka 120a6e
                        GLX_STENCIL_SIZE, 8,
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
                        //			GLX_DEPTH_SIZE,  24,
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
                        None};
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    int dbAttrib[] = {GLX_RGBA, GLX_RED_SIZE,     1,   GLX_GREEN_SIZE,
Shinya Kitaoka 120a6e
                      1,        GLX_BLUE_SIZE,    1,   GLX_STENCIL_SIZE,
Shinya Kitaoka 120a6e
                      8,        GLX_DOUBLEBUFFER, None};
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    int w = rasterSize.lx;
Shinya Kitaoka 120a6e
    int h = rasterSize.ly;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    XVisualInfo *vis = glXChooseVisual(m_dpy, DefaultScreen(m_dpy), attribList);
Shinya Kitaoka 120a6e
    if (!vis) {
Shinya Kitaoka 120a6e
      std::cout << "unable to create sb visual" << std::endl;
Shinya Kitaoka 120a6e
      vis = glXChooseVisual(m_dpy, DefaultScreen(m_dpy), dbAttrib);
Shinya Kitaoka 120a6e
      assert(vis && "unable to create db visual");
Shinya Kitaoka 120a6e
    }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    m_context = glXCreateContext(m_dpy, vis, 0, False);
Shinya Kitaoka 120a6e
    //    std::cout << "Direct rendering: " << (glXIsDirect(m_dpy, m_context) ?
Shinya Kitaoka 120a6e
    //    "Yes" : "No" )<< std::endl;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    if (!m_context) assert("not m_context" && false);
Shinya Kitaoka 120a6e
    TRaster32P raster(w, h);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    m_xpixmap = XCreatePixmap(m_dpy, win, w, h, vis->depth);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    assert(m_xpixmap && "not m_xpixmap");
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    m_pixmap = glXCreateGLXPixmap(m_dpy, vis, m_xpixmap);
Shinya Kitaoka 120a6e
    if (!m_pixmap) assert("not m_pixmap" && m_pixmap);
Shinya Kitaoka 120a6e
    /*
Shinya Kitaoka 120a6e
Bool ret = glXMakeCurrent(m_dpy,
Shinya Kitaoka 120a6e
                  m_pixmap,
Shinya Kitaoka 120a6e
                  m_context);
Toshihiro Shimizu 890ddd
*/
Shinya Kitaoka 120a6e
    Bool ret = safeGlXMakeCurrent();
Shinya Kitaoka 120a6e
    assert(ret);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    m_raster = raster;
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#if defined(MACOSX)
Toshihiro Shimizu 890ddd
#if defined(powerpc)
Shinya Kitaoka 120a6e
  void rightRotateBits(UCHAR *buf, int bufferSize) {
Shinya Kitaoka 120a6e
    UINT *buffer = (UINT *)buf;
Shinya Kitaoka 120a6e
    UINT app;
Shinya Kitaoka 120a6e
    for (int i = 0; i < bufferSize; i++, buffer++) {
Shinya Kitaoka 120a6e
      app     = *buffer;
Shinya Kitaoka 120a6e
      *buffer = app >> 8 | app << 24;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
#else
Shinya Kitaoka 120a6e
  void rightRotateBits(UCHAR *buf, int bufferSize) {
Shinya Kitaoka 120a6e
    UINT *buffer = (UINT *)buf;
Shinya Kitaoka 120a6e
    UINT app;
Shinya Kitaoka 120a6e
    for (int i = 0; i < bufferSize; i++, buffer++) {
Shinya Kitaoka 120a6e
      app     = *buffer;
Shinya Kitaoka 120a6e
      *buffer = (app >> 16 & 0x000000ff) | (app << 16 & 0x00ff0000) |
Shinya Kitaoka 120a6e
                (app & 0xff00ff00);
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
#endif
Shinya Kitaoka 120a6e
  //-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  const TRaster32P &getRaster() {
Shinya Kitaoka 120a6e
    makeCurrent();
Shinya Kitaoka 120a6e
    glFlush();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    int lx = m_raster->getLx();
Shinya Kitaoka 120a6e
    int ly = m_raster->getLy();
Shinya Kitaoka 120a6e
    m_raster->lock();
Shinya Kitaoka 120a6e
    glReadPixels(0, 0, lx, ly, GL_RGBA /*GL_BGRA_EXT*/, GL_UNSIGNED_BYTE,
Shinya Kitaoka 120a6e
                 m_raster->getRawData());
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#if defined(MACOSX)
Shinya Kitaoka 120a6e
    rightRotateBits(m_raster->getRawData(), lx * ly);
Toshihiro Shimizu 890ddd
#warning "to do"
Toshihiro Shimizu 890ddd
#endif
Shinya Kitaoka 120a6e
    m_raster->unlock();
Shinya Kitaoka 120a6e
    return m_raster;
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  //-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  int getLx() const { return m_raster->getLx(); }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  //-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  int getLy() const { return m_raster->getLy(); }
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
std::shared_ptr<tofflinegl::imp> defaultOfflineGLGenerator(</tofflinegl::imp>
Shinya Kitaoka 120a6e
    const TDimension &dim, std::shared_ptr<tofflinegl::imp> shared) {</tofflinegl::imp>
Shinya Kitaoka 120a6e
  return std::make_shared<ximplementation>(dim);</ximplementation>
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#elif MACOSX
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
std::shared_ptr<tofflinegl::imp> defaultOfflineGLGenerator(</tofflinegl::imp>
Shinya Kitaoka 120a6e
    const TDimension &dim, std::shared_ptr<tofflinegl::imp> shared) {</tofflinegl::imp>
Shinya Kitaoka 120a6e
  return std::make_shared<qtofflinegl>(dim, shared);</qtofflinegl>
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//=============================================================================
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// current imp generator
Shinya Kitaoka 120a6e
namespace {
Toshihiro Shimizu 890ddd
TOfflineGL::ImpGenerator *currentImpGenerator = defaultOfflineGLGenerator;
Shinya Kitaoka 120a6e
}  // namespace
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//=============================================================================
Toshihiro Shimizu 890ddd
// TOfflineGL
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
// namespace {
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
class MessageCreateContext : public TThread::Message {
Shinya Kitaoka 120a6e
  friend class TOfflineGL;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  TOfflineGL *m_ogl;
Shinya Kitaoka 120a6e
  TDimension m_size;
Shinya Kitaoka 120a6e
  std::shared_ptr<tofflinegl::imp> m_shared;</tofflinegl::imp>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
public:
Shinya Kitaoka 120a6e
  MessageCreateContext(TOfflineGL *ogl, const TDimension &size,
Shinya Kitaoka 120a6e
                       std::shared_ptr<tofflinegl::imp> shared)</tofflinegl::imp>
Shinya Kitaoka 120a6e
      : m_ogl(ogl), m_size(size), m_shared(std::move(shared)) {}
Shinya Kitaoka 120a6e
Shinya Kitaoka 473e70
  void onDeliver() override { m_ogl->m_imp = currentImpGenerator(m_size, m_shared); }
Shinya Kitaoka 120a6e
Shinya Kitaoka 473e70
  TThread::Message *clone() const override { return new MessageCreateContext(*this); }
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//} // namespace
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//--------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
TOfflineGL::TOfflineGL(TDimension dim, const TOfflineGL *shared) {
Toshihiro Shimizu 890ddd
#if defined(LINUX)
Shinya Kitaoka 120a6e
  XScopedLock xsl;
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  std::shared_ptr<imp> sharedImp = shared ? shared->m_imp : 0;</imp>
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  /*
Shinya Kitaoka 120a6e
  元のコードは(別スレッドから呼び出すための) offline renderer を作って main
Shinya Kitaoka 120a6e
  thread に dispatch するという訳のわからないことをしていたが Q*GLContext は
Shinya Kitaoka 120a6e
  thread context を超えられないので直接生成してこのコンテキストで閉じる.
Shinya Kitaoka 120a6e
  別スレッドには dispatch しない.
Shinya Kitaoka 120a6e
*/
Shinya Kitaoka 120a6e
  m_imp = currentImpGenerator(dim, std::move(sharedImp));
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  initMatrix();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
TOfflineGL::TOfflineGL(const TRaster32P &raster, const TOfflineGL *shared) {
Toshihiro Shimizu 890ddd
#if defined(LINUX)
Shinya Kitaoka 120a6e
  XScopedLock xsl;
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  m_imp = currentImpGenerator(raster->getSize(), shared->m_imp);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  initMatrix();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  glRasterPos2d(0, 0);
Shinya Kitaoka 120a6e
  raster->lock();
Shinya Kitaoka 120a6e
  glDrawPixels(raster->getLx(), raster->getLy(), GL_BGRA_EXT, GL_UNSIGNED_BYTE,
Shinya Kitaoka 120a6e
               raster->getRawData());
Shinya Kitaoka 120a6e
  raster->unlock();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
TOfflineGL::~TOfflineGL() {}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
TOfflineGL::ImpGenerator *TOfflineGL::defineImpGenerator(
Shinya Kitaoka 120a6e
    TOfflineGL::ImpGenerator *impGenerator) {
Shinya Kitaoka 120a6e
  TOfflineGL::ImpGenerator *ret = currentImpGenerator;
Shinya Kitaoka 120a6e
  currentImpGenerator           = impGenerator;
Shinya Kitaoka 120a6e
  return ret;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TOfflineGL::makeCurrent() {
Shinya Kitaoka 120a6e
  if (currentContextManager) currentContextManager->store();
Shinya Kitaoka 120a6e
  // Tutto il codice è stato spostato dentro Imp
Shinya Kitaoka 120a6e
  m_imp->makeCurrent();
Shinya Kitaoka 120a6e
  assert(glGetError() == GL_NO_ERROR);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TOfflineGL::doneCurrent() {
Shinya Kitaoka 120a6e
  m_imp->doneCurrent();
Shinya Kitaoka 120a6e
  if (currentContextManager) {
Shinya Kitaoka 120a6e
    currentContextManager->restore();
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TOfflineGL::initMatrix() {
Shinya Kitaoka 120a6e
  m_imp->makeCurrent();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  // cfr. help: OpenGL/Programming tip/OpenGL Correctness Tips
Shinya Kitaoka 120a6e
  glViewport(0, 0, m_imp->getLx(), m_imp->getLy());
Shinya Kitaoka 120a6e
  glMatrixMode(GL_PROJECTION);
Shinya Kitaoka 120a6e
  glLoadIdentity();
Shinya Kitaoka 120a6e
  gluOrtho2D(0, m_imp->getLx(), 0, m_imp->getLy());
Shinya Kitaoka 120a6e
  glMatrixMode(GL_MODELVIEW);
Shinya Kitaoka 120a6e
  glLoadIdentity();
Shinya Kitaoka 120a6e
  // glTranslatef(0.375, 0.375, 0.0);    //WRONG
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  /*  (From Daniele)
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
Quoting from the aforementioned source:
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
"An optimum compromise that allows all primitives to be specified at integer
Shinya Kitaoka 120a6e
positions, while still ensuring predictable rasterization, is to translate x
Shinya Kitaoka 120a6e
and y by 0.375, as shown in the following code sample. Such a translation
Shinya Kitaoka 120a6e
keeps polygon and pixel image edges safely away from the centers of pixels,
Toshihiro Shimizu 890ddd
while moving line vertices close enough to the pixel centers"
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
NOTE: This is not an acceptable excuse in our case - as we're NOT USING
Shinya Kitaoka 120a6e
    INTEGER COORDINATES ONLY. OpenGL has all the rights to render pixels
Shinya Kitaoka 120a6e
    at integer coordinates across the neighbouring 4 pixels - and their
Shinya Kitaoka 120a6e
    (0.5, 0.5) translations at the EXACT screen pixel.
Shinya Kitaoka 120a6e
*/
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TOfflineGL::clear(TPixel32 color) {
Shinya Kitaoka 120a6e
  const double maxValue = 255.0;
Shinya Kitaoka 120a6e
  makeCurrent();
Shinya Kitaoka 120a6e
  glClearColor((double)color.r / maxValue, (double)color.g / maxValue,
Shinya Kitaoka 120a6e
               (double)color.b / maxValue, (double)color.m / maxValue);
Shinya Kitaoka 120a6e
  glClear(GL_COLOR_BUFFER_BIT);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TOfflineGL::draw(TVectorImageP image, const TVectorRenderData &rd,
Shinya Kitaoka 120a6e
                      bool doInitMatrix) {
Shinya Kitaoka 120a6e
  checkErrorsByGL;
Shinya Kitaoka 120a6e
  makeCurrent();
Shinya Kitaoka 120a6e
  checkErrorsByGL;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (doInitMatrix) {
Shinya Kitaoka 120a6e
    initMatrix();
Shinya Kitaoka 120a6e
    checkErrorsByGL;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (image) {
Shinya Kitaoka 120a6e
    checkErrorsByGL;
Shinya Kitaoka 120a6e
    tglDraw(rd, image.getPointer());
Shinya Kitaoka 120a6e
    checkErrorsByGL;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  checkErrorsByGL;
Shinya Kitaoka 120a6e
  glFlush();
Shinya Kitaoka 120a6e
  checkErrorsByGL;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TOfflineGL::draw(TRasterImageP ri, const TAffine &aff, bool doInitMatrix) {
Shinya Kitaoka 120a6e
  makeCurrent();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (doInitMatrix) initMatrix();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  TRaster32P ras32 = ri->getRaster();
Shinya Kitaoka 120a6e
  if (!ras32) return;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  int lx = ras32->getLx();
Shinya Kitaoka 120a6e
  int ly = ras32->getLy();
Shinya Kitaoka 120a6e
  // lx e ly devono essere potenze di due
Shinya Kitaoka 120a6e
  assert((lx & (lx - 1)) == 0);
Shinya Kitaoka 120a6e
  assert((ly & (ly - 1)) == 0);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  glPushMatrix();
Shinya Kitaoka 120a6e
  tglMultMatrix(aff);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
Shinya Kitaoka 120a6e
  glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
Shinya Kitaoka 120a6e
  glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
Shinya Kitaoka 120a6e
  glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  glEnable(GL_TEXTURE_2D);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  /*
Shinya Kitaoka 120a6e
TNZ_MACHINE_CHANNEL_ORDER_BGRM
Shinya Kitaoka 120a6e
TNZ_MACHINE_CHANNEL_ORDER_MBGR
Shinya Kitaoka 120a6e
TNZ_MACHINE_CHANNEL_ORDER_RGBM
Shinya Kitaoka 120a6e
TNZ_MACHINE_CHANNEL_ORDER_MRGB
Shinya Kitaoka 120a6e
*/
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  GLenum fmt = TGL_FMT;
Shinya Kitaoka 120a6e
  /*
Shinya Kitaoka 120a6e
#ifdef TNZ_MACHINE_CHANNEL_ORDER_BGRM
Shinya Kitaoka 120a6e
GL_BGRA_EXT;
Shinya Kitaoka 120a6e
#elif TNZ_MACHINE_CHANNEL_ORDER_MBGR
Shinya Kitaoka 120a6e
GL_ABGR_EXT;
Shinya Kitaoka 120a6e
#elif TNZ_MACHINE_CHANNEL_ORDER_RGBM
Shinya Kitaoka 120a6e
GL_RGBA;
Shinya Kitaoka 120a6e
#elif TNZ_MACHINE_CHANNEL_ORDER_MRGB
Shinya Kitaoka 120a6e
#warning "to do"
Shinya Kitaoka 120a6e
GL_ABGR_EXT;
Shinya Kitaoka 120a6e
#else
Shinya Kitaoka 120a6e
Error  PLATFORM NOT SUPPORTED
Shinya Kitaoka 120a6e
#endif
Toshihiro Shimizu 890ddd
*/
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  // Generate a texture id and bind it.
Shinya Kitaoka 120a6e
  GLuint texId;
Shinya Kitaoka 120a6e
  glGenTextures(1, &texId);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  glBindTexture(GL_TEXTURE_2D, texId);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  glPixelStorei(GL_UNPACK_ROW_LENGTH,
Shinya Kitaoka 120a6e
                ras32->getWrap() != ras32->getLx() ? ras32->getWrap() : 0);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  ras32->lock();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  glTexImage2D(GL_TEXTURE_2D,  // target (is a 2D texture)
Shinya Kitaoka 120a6e
               0,              // is one level only
Shinya Kitaoka 120a6e
               GL_RGB,         //  number of component of a pixel
Shinya Kitaoka 120a6e
               lx,             // size width
Shinya Kitaoka 120a6e
               ly,             //      height
Shinya Kitaoka 120a6e
               0,              // size of a border
Shinya Kitaoka 120a6e
               fmt,
Shinya Kitaoka 120a6e
               GL_UNSIGNED_BYTE,  //
Shinya Kitaoka 120a6e
               ras32->getRawData());
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  ras32->unlock();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  double halfWidth  = 0.5 * lx;
Shinya Kitaoka 120a6e
  double halfHeight = 0.5 * ly;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  double dpix = 1, dpiy = 1;
Shinya Kitaoka 120a6e
  ri->getDpi(dpix, dpiy);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (dpix != 0 && dpiy != 0) {
Shinya Kitaoka 120a6e
    double unit = 100;
Shinya Kitaoka 120a6e
    halfWidth *= unit / dpix;
Shinya Kitaoka 120a6e
    halfHeight *= unit / dpiy;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  glBegin(GL_QUAD_STRIP);
Shinya Kitaoka 120a6e
  glTexCoord2d(0, 0);
Shinya Kitaoka 120a6e
  glVertex2d(-halfWidth, -halfHeight);
Shinya Kitaoka 120a6e
  glTexCoord2d(1, 0);
Shinya Kitaoka 120a6e
  glVertex2d(halfWidth, -halfHeight);
Shinya Kitaoka 120a6e
  glTexCoord2d(0, 1);
Shinya Kitaoka 120a6e
  glVertex2d(-halfWidth, halfHeight);
Shinya Kitaoka 120a6e
  glTexCoord2d(1, 1);
Shinya Kitaoka 120a6e
  glVertex2d(halfWidth, halfHeight);
Shinya Kitaoka 120a6e
  glEnd();
Shinya Kitaoka 120a6e
  glDisable(GL_TEXTURE_2D);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  glPopMatrix();
Shinya Kitaoka 120a6e
  glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // Delete texture
Shinya Kitaoka 120a6e
  glDeleteTextures(1, &texId);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  glFlush();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TOfflineGL::flush() {
Shinya Kitaoka 120a6e
  makeCurrent();
Shinya Kitaoka 120a6e
  glFlush();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TOfflineGL::getRaster(TRaster32P raster) {
Shinya Kitaoka 120a6e
  assert(raster->getLx() <= getLx() && raster->getLy() <= getLy());
Shinya Kitaoka 120a6e
  if (raster->getWrap() == raster->getLx()) {
Shinya Kitaoka 120a6e
    m_imp->getRaster(raster);
Shinya Kitaoka 120a6e
  } else {
Shinya Kitaoka 120a6e
    // There are 2 possible solutions: use glReadPixels multiple times for each
Shinya Kitaoka 120a6e
    // row of input raster,
Shinya Kitaoka 120a6e
    // OR allocate a new contiguous buffer, use glReadPixels once, and then
Shinya Kitaoka 120a6e
    // memcpy each row.
Shinya Kitaoka 120a6e
    // It actually seems that the *latter* is actually the fastest solution,
Shinya Kitaoka 120a6e
    // although it requires
Shinya Kitaoka 120a6e
    // allocating a temporary buffer of the same size of the requested raster...
Shinya Kitaoka 120a6e
    // I also could not actually manage to make the former work - the code
Shinya Kitaoka 120a6e
    // seemed right but results were weird...
Shinya Kitaoka 120a6e
    TRaster32P ras32(raster->getSize());
Shinya Kitaoka 120a6e
    m_imp->getRaster(ras32);
Shinya Kitaoka 120a6e
    TRop::copy(raster, ras32);
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TOfflineGL::getRaster(TRasterP raster) {
Shinya Kitaoka 120a6e
  assert(raster->getLx() <= getLx() && raster->getLy() <= getLy());
Shinya Kitaoka 120a6e
  TRaster32P ras32 = raster;
Shinya Kitaoka 120a6e
  if (ras32 && (raster->getWrap() == raster->getLx())) {
Shinya Kitaoka 120a6e
    m_imp->getRaster(ras32);
Shinya Kitaoka 120a6e
  } else {
Shinya Kitaoka 120a6e
    ras32 = TRaster32P(raster->getSize());
Shinya Kitaoka 120a6e
    m_imp->getRaster(ras32);
Shinya Kitaoka 120a6e
    TRop::copy(raster, ras32);
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
TRaster32P TOfflineGL::getRaster() {
Shinya Kitaoka 120a6e
  TRaster32P raster(getLx(), getLy());
Shinya Kitaoka 120a6e
  m_imp->getRaster(raster);
Shinya Kitaoka 120a6e
  return raster;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
int TOfflineGL::getLx() const { return m_imp->getLx(); }
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
int TOfflineGL::getLy() const { return m_imp->getLy(); }
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//=============================================================================
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
namespace {
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
struct DimensionLess
Shinya Kitaoka 120a6e
    : public std::binary_function<tdimension, bool="" tdimension,=""> {</tdimension,>
Shinya Kitaoka 120a6e
  bool operator()(const TDimension &d1, const TDimension &d2) const {
Shinya Kitaoka 120a6e
    return d1.lx < d2.lx || (d1.lx == d2.lx && d1.ly < d2.ly);
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
class OglStock {  // singleton
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  typedef std::map<const *,="" dimensionless="" tdimension,="" tofflinegl=""> ContextMap;</const>
Shinya Kitaoka 120a6e
  ContextMap m_table;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  OglStock() {}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
public:
Shinya Kitaoka 120a6e
  ~OglStock() {
Shinya Kitaoka 120a6e
    /*  // PER ADESSO, LASCIAMO IL MEMORY LEAK DATO CHE ALTRIMENTI VA IN CRASH
Shinya Kitaoka 120a6e
ContextMap::iterator it = m_table.begin();
Shinya Kitaoka 120a6e
for(; it!=m_table.end(); ++it)
Shinya Kitaoka 120a6e
{
Shinya Kitaoka 120a6e
delete it->second;
Shinya Kitaoka 120a6e
}
Shinya Kitaoka 120a6e
*/
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  TOfflineGL *get(const TDimension &d) {
Shinya Kitaoka 120a6e
    ContextMap::iterator it = m_table.find(d);
Shinya Kitaoka 120a6e
    if (it == m_table.end()) {
Shinya Kitaoka 120a6e
      TOfflineGL *glContext;
Shinya Kitaoka 120a6e
      glContext = new TOfflineGL(d);
Shinya Kitaoka 120a6e
      pair<contextmap::iterator, bool=""> result =</contextmap::iterator,>
Shinya Kitaoka 120a6e
          m_table.insert(ContextMap::value_type(d, glContext));
Shinya Kitaoka 120a6e
      assert(result.second);
Shinya Kitaoka 120a6e
      assert(m_table.size() < 15);
Shinya Kitaoka 120a6e
      return glContext;
Toshihiro Shimizu 890ddd
    }
Shinya Kitaoka 120a6e
    return it->second;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  static OglStock *instance() {
Shinya Kitaoka 120a6e
    static OglStock singleton;
Shinya Kitaoka 120a6e
    return &singleton;
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
}  // namespace
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
TOfflineGL *TOfflineGL::getStock(const TDimension dim) {
Shinya Kitaoka 120a6e
  return OglStock::instance()->get(dim);
Toshihiro Shimizu 890ddd
}