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