|
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 |
}
|